Compare commits

...

352 Commits

Author SHA1 Message Date
TIP Automation User
1ab1a0cefa Chg: update image tag in helm values to v2.4.1 2022-07-21 13:50:26 +00:00
Dmitry Dunaev
4ea065a54f [WIFI-9174] Fix: switch from deprecated bitnami charts to mirrored ones
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-07-21 16:37:01 +03:00
TIP Automation User
dfa182482f Chg: update image tag in helm values to v2.4.0 2021-12-17 02:36:52 +00:00
Johann Hoffmann
8a0c7e23ad [WIFI-6170] Add OpenWifi Docker Compose deployment with PostgreSQL (#70)
* Add wait-for-postgres.sh wrapper script

Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>

* Copy wait-for-postgres.sh into Docker image

Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2021-12-16 17:29:29 +01:00
Johann Hoffmann
9be04d1f9b Add config property to templating mechanism
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2021-12-15 18:04:01 +01:00
TIP Automation User
c86227de9e Chg: update image tag in helm values to v2.4.0-RC6 2021-12-11 08:12:26 +00:00
stephb9959
04063ddd41 Merge remote-tracking branch 'origin/release/v2.4.0' into release/v2.4.0 2021-12-10 10:33:58 -08:00
stephb9959
1808376445 Fixing https://telecominfraproject.atlassian.net/browse/WIFI-6149 and enabling Archiver by default. 2021-12-10 10:33:51 -08:00
TIP Automation User
83211baba8 Chg: update image tag in helm values to v2.4.0-RC5 2021-12-08 07:42:39 +00:00
Dmitry Dunaev
9b87fb756f Add: .git dir to build image to expose git hash for version
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2021-12-08 10:26:22 +03:00
stephb9959
1064bfe137 Merge remote-tracking branch 'origin/release/v2.4.0' into release/v2.4.0 2021-12-06 09:06:40 -08:00
stephb9959
5125dc5eb6 Adding git hash - no Jira: display git hash in the systeminfo version. 2021-12-06 09:06:28 -08:00
Dmitry Dunaev
ec1acd922d Chg: helm values image tag to v2.4.0-RC4 2021-12-03 12:00:48 +03:00
stephb9959
6a29facd59 Merge remote-tracking branch 'origin/release/v2.4.0' into release/v2.4.0 2021-12-02 10:10:26 -08:00
stephb9959
aef76b12e4 Fix for: https://telecominfraproject.atlassian.net/browse/WIFI-6014 2021-12-02 10:10:15 -08:00
Dmitry Dunaev
1f2aaa94ba Chg: helm values image tag to v2.4.0-RC3
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2021-11-30 15:37:18 +03:00
stephb9959
2f4ff94280 Fix for: https://telecominfraproject.atlassian.net/browse/WIFI-5981 2021-11-29 09:50:19 -08:00
stephb9959
26ac5b836e Fix for: https://telecominfraproject.atlassian.net/browse/WIFI-5965 2021-11-29 09:32:48 -08:00
Dmitry Dunaev
e2508846b3 Bkpr: backport dependencies required for unsafe sysctls (WIFI-5420) 2021-11-22 15:50:51 +03:00
Dmitry Dunaev
2d8ee9b033 Chg: helm image in values to new release candidate 2021-11-22 14:53:01 +03:00
stephb9959
bf3ba546b6 Solving https://telecominfraproject.atlassian.net/browse/WIFI-5780 2021-11-18 21:00:58 -08:00
Leonid Mirsky
8b282a032c Update Helm values to v2.4.0-RC1
Signed-off-by: Leonid Mirsky <leonid@opsfleet.com>
2021-11-16 23:24:46 +02:00
stephb9959
4aa9e93d8a New UUIDv4 Generator 2021-11-15 11:26:56 -08:00
stephb9959
515f6cdf91 New UUIDv4 Generator 2021-11-15 10:58:29 -08:00
stephb9959
9d91b15110 Refactoring StorageArchiver 2021-11-14 23:47:31 -08:00
stephb9959
c73aba6ad4 Refactoring StorageArchiver 2021-11-14 23:40:43 -08:00
stephb9959
15fcd30030 Refactoring StorageArchiver 2021-11-14 23:26:30 -08:00
stephb9959
6fa4432f74 Refactoring StorageArchiver 2021-11-14 23:12:49 -08:00
stephb9959
c1367ddf3b Refactoring StorageArchiver 2021-11-14 23:08:07 -08:00
stephb9959
d80f146877 Refactoring StorageArchiver 2021-11-14 22:54:37 -08:00
stephb9959
e43b032d3a Refactoring StorageArchiver 2021-11-14 22:52:55 -08:00
stephb9959
b84ad117cf Refactoring StorageArchiver 2021-11-14 22:48:00 -08:00
stephb9959
03d29c4bd8 Fixed shutdown crash. 2021-11-14 13:50:25 -08:00
stephb9959
2344cea825 Debugging system exit 2021-11-14 13:48:23 -08:00
stephb9959
b431dc1293 Debugging system exit 2021-11-14 13:43:24 -08:00
stephb9959
566368638a Debugging system exit 2021-11-14 13:37:37 -08:00
stephb9959
957f1fe7d8 Debugging system exit 2021-11-14 13:22:00 -08:00
stephb9959
570f9de425 Debugging system exit 2021-11-14 11:29:44 -08:00
stephb9959
4121f70315 Debugging system exit 2021-11-14 11:23:33 -08:00
stephb9959
fec45de4e8 Debugging system exit 2021-11-14 11:16:49 -08:00
stephb9959
f981513ee2 Debugging system exit 2021-11-14 11:08:06 -08:00
stephb9959
e997eac63c Debugging system exit 2021-11-14 10:57:55 -08:00
stephb9959
736f9aa099 Debugging system exit 2021-11-14 10:31:44 -08:00
stephb9959
1e3711f293 Debugging system exit 2021-11-14 10:10:02 -08:00
stephb9959
76eca308c9 Debugging system exit 2021-11-14 09:43:17 -08:00
stephb9959
7a77497522 Debugging system exit 2021-11-14 09:34:47 -08:00
stephb9959
dd04572aef Debugging system exit 2021-11-14 09:00:12 -08:00
stephb9959
d6a4ab86e7 Debugging system exit 2021-11-14 08:56:04 -08:00
stephb9959
1367b5a4a2 Debugging system exit 2021-11-14 08:42:35 -08:00
stephb9959
7dbc1476d8 Debugging system exit 2021-11-14 08:32:19 -08:00
stephb9959
63fc7055f8 Debugging system exit 2021-11-14 08:24:30 -08:00
stephb9959
1c61ad8798 Debugging system exit 2021-11-14 08:20:29 -08:00
stephb9959
8f641df7e4 Debugging system exit 2021-11-14 08:11:13 -08:00
stephb9959
8241a4f287 Debugging system exit 2021-11-14 07:47:22 -08:00
stephb9959
8008bac1af Debugging system exit 2021-11-14 07:43:03 -08:00
stephb9959
b1fe5bcd39 Debugging system exit 2021-11-14 07:38:50 -08:00
stephb9959
aacc230ff2 Debugging system exit 2021-11-14 07:33:19 -08:00
stephb9959
a6823b2e2c Fixing commands command and newestcommands. 2021-11-13 23:49:56 -08:00
stephb9959
756ee323a5 Fixing commands command and newestcommands. 2021-11-13 23:11:46 -08:00
stephb9959
5f0a432cdc Fixing commands command and newestcommands. 2021-11-13 23:02:36 -08:00
stephb9959
a7ee104828 Fixing commands command and newestcommands. 2021-11-13 22:50:12 -08:00
stephb9959
980564d945 Fixing commands command and newestcommands. 2021-11-13 22:45:15 -08:00
stephb9959
085e8b93ee Fixing commands command and newestcommands. 2021-11-13 22:41:14 -08:00
stephb9959
ffe85278f1 Fixing commands command and newestcommands. 2021-11-13 22:09:01 -08:00
stephb9959
240d94c687 Fixing commands command. 2021-11-13 22:03:50 -08:00
stephb9959
31466efde8 Fixing commands command. 2021-11-13 21:57:13 -08:00
stephb9959
aa9fd229b6 Fixing commands command. 2021-11-13 21:54:18 -08:00
stephb9959
daf1563636 Framework update. 2021-11-13 15:23:34 -08:00
stephb9959
ac74dffd0c Framework update. 2021-11-12 23:36:20 -08:00
stephb9959
c85f22bfb5 Framework update. 2021-11-12 09:05:53 -08:00
stephb9959
126b391080 Framework update. 2021-11-11 20:36:41 -08:00
stephb9959
48b2c57245 Merge remote-tracking branch 'origin/master' 2021-11-11 17:57:15 -08:00
stephb9959
c82126234d Framework update. 2021-11-11 17:57:04 -08:00
Max
d9488cdd79 Revert "[WIFI-5420] Add: helm sysctl for tcp keepalive" (#62) 2021-11-11 16:12:36 +01:00
Dmitry Dunaev
0745badb8a Merge pull request #61 from Telecominfraproject/feature/wifi-5420--add-sysctl-context
[WIFI-5420] Add: helm sysctl for tcp keepalive
2021-11-10 18:19:20 +03:00
Dmitry Dunaev
c13a6c1852 [WIFI-5420] Add: helm sysctl for tcp keepalive 2021-11-10 17:56:49 +03:00
stephb9959
053b9de558 Framework update. 2021-11-09 18:01:30 -08:00
stephb9959
6d058930c9 Framework update. 2021-11-09 17:25:16 -08:00
stephb9959
9e52c9d7da Merge remote-tracking branch 'origin/master' 2021-11-08 20:19:29 -08:00
stephb9959
7fbdc4b18b Fixing some static singleton instantiation 2021-11-08 20:19:13 -08:00
Stephane Bourque
d2ce73f75e Merge pull request #60 from Telecominfraproject/WIFI-5407-add-pod-annotations
allow to set pod annotations
2021-11-06 23:17:30 -07:00
stephb9959
8bfd0f57ab Added bulk deletion for an OUI 2021-11-06 10:28:14 -07:00
stephb9959
66c17e7691 Added bulk deletion for an OUI 2021-11-06 10:25:10 -07:00
stephb9959
05b7be1270 Added bulk deletion for an OUI 2021-11-06 10:21:18 -07:00
stephb9959
57c11d9a09 Added bulk deletion for an OUI 2021-11-06 10:17:26 -07:00
stephb9959
5664dbef6d Remove all traces of a device when deleting. 2021-11-06 08:55:33 -07:00
stephb9959
874cd297b1 Remove all traces of a device when deleting. 2021-11-05 18:31:25 -07:00
Max Brenner
cef65da7d8 allow to set pod annotations 2021-11-05 14:43:14 +01:00
stephb9959
c7bb51e73f Adding the ability to support OWLS. 2021-11-03 23:20:03 -07:00
stephb9959
cfc9422266 Closing the socket after a WebSocket session from the UI. 2021-11-01 15:39:54 -07:00
stephb9959
e15f3af410 Fixing state processor for radio associations processing. 2021-10-31 00:17:18 -07:00
stephb9959
c1797d9caf Testing stateprocessor 2021-10-31 00:07:34 -07:00
stephb9959
ddc26b7e08 Testing stateprocessor 2021-10-30 23:55:21 -07:00
stephb9959
1ba31d3480 Testing stateprocessor 2021-10-30 23:51:45 -07:00
stephb9959
b38043c02d Testing stateprocessor 2021-10-30 23:48:51 -07:00
stephb9959
bc5b430c2e Testing stateprocessor 2021-10-30 23:36:53 -07:00
stephb9959
03503cc525 Testing stateprocessor 2021-10-30 23:29:22 -07:00
stephb9959
310cdd6245 Fixing ConfigurationValidator 2021-10-30 15:38:54 -07:00
stephb9959
5f089105b7 Fixing ConfigurationValidator 2021-10-30 15:34:02 -07:00
stephb9959
3548c004cb Adding better parallel processing for telemetry. 2021-10-30 12:32:12 -07:00
stephb9959
f9f1101ac9 Adding better parallel processing for telemetry. 2021-10-30 12:30:05 -07:00
stephb9959
1f8294a208 Adding better parallel processing for telemetry. 2021-10-30 11:47:36 -07:00
stephb9959
6b2e3db363 Adding better parallel processing for telemetry. 2021-10-30 11:40:21 -07:00
stephb9959
8faa8a82fd Adding better parallel processing for telemetry. 2021-10-30 11:32:58 -07:00
stephb9959
24bb3fc2f6 Adding better parallel processing for telemetry. 2021-10-30 11:22:07 -07:00
stephb9959
38dd9f592a Adding better parallel processing for telemetry. 2021-10-30 11:04:00 -07:00
stephb9959
bb176c23bb Fixing sanity check dashboard miscalculation. Fixing telemetry for multiple client on same device.
Fixing CLI syntax mistake.
2021-10-30 10:01:36 -07:00
stephb9959
124f941a10 Framework patch. 2021-10-28 08:57:51 -07:00
stephb9959
fa6a00cf99 Version 2.3.0 2021-10-27 12:24:03 -07:00
stephb9959
e58fa4b0fb Version 2.3.0 2021-10-26 09:17:24 -07:00
stephb9959
645f484d1d Fixing typos. 2021-10-26 08:59:17 -07:00
stephb9959
1e0f43bd4b Fixing typos. 2021-10-25 14:54:54 -07:00
stephb9959
09a1e5d429 Framework update. 2021-10-25 14:35:24 -07:00
stephb9959
a0beee77aa Fixing the healthcheck bug where only newest records were being returned. 2021-10-24 22:18:48 -07:00
stephb9959
04c221784b Adding support for reboot in recovery mode. 2021-10-24 11:45:35 -07:00
stephb9959
544d6babe5 Finishing framework refactor. 2021-10-24 10:32:33 -07:00
stephb9959
5d16414bb2 Added support for state in telemetry. 2021-10-23 22:22:16 -07:00
stephb9959
925a48929f Added support for state in telemetry. 2021-10-23 22:20:48 -07:00
stephb9959
816bc9c799 Merge remote-tracking branch 'origin/master' 2021-10-23 22:16:06 -07:00
stephb9959
7f0148a33d Added support for state in telemetry. 2021-10-23 22:15:59 -07:00
Stephane Bourque
e2f07d6d05 Merge pull request #59 from Telecominfraproject/feature/wifi-4997
test_scripts/curl: add option to delete default config
2021-10-23 20:06:44 -07:00
Dmitry Dunaev
c708ffd23a Merge pull request #58 from Telecominfraproject/feature/wifi-3162--readiness
[WIFI-3162] Add: readiness_check script that is using cli to check if system is ready
2021-10-22 17:22:28 +03:00
Dmitry Dunaev
9db5b5f39a [WIFI-3162] Add: readiness_check script that is using cli to check if system is ready 2021-10-22 13:17:47 +03:00
stephb9959
e47feab9ad Added support for state in telemetry. 2021-10-21 23:15:16 -07:00
Stijn Tintel
f673cdc1ba test_scripts/curl: add option to delete default config
Closes: WIFI-4997
Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
2021-10-21 16:20:17 +02:00
stephb9959
4fa59fdfd2 Added support for state in telemetry. 2021-10-20 10:00:30 -07:00
stephb9959
1d6bafa75a Added support for state in telemetry. 2021-10-20 09:59:30 -07:00
stephb9959
aa0a9aabce Refactoring project layout 2021-10-19 20:20:50 -07:00
stephb9959
2a0b45fde1 Refactoring project layout 2021-10-19 19:45:50 -07:00
stephb9959
816f0a6e7c Merge remote-tracking branch 'origin/master' 2021-10-19 09:52:25 -07:00
stephb9959
02e8c59052 Adding new Sub Portal MicroService entries. 2021-10-19 09:52:18 -07:00
Dmitry Dunaev
b26509c8b7 Merge pull request #57 from Telecominfraproject/fix/wifi-4923--helm-git-readme
[WIFI-4923] Fix: helm-git link in chart README
2021-10-19 11:53:10 +03:00
Dmitry Dunaev
cd3b663f0a [WIFI-4923] Fix: helm-git link in chart README 2021-10-19 11:34:40 +03:00
stephb9959
9172ec6532 Added new endpoint /capabilities for provisioning. 2021-10-17 23:57:17 -07:00
stephb9959
eab9557f51 Added new endpoint /capabilities for provisioning. 2021-10-17 23:51:39 -07:00
stephb9959
ee1d0fbde9 Added new endpoint /capabilities for provisioning. 2021-10-17 23:49:15 -07:00
stephb9959
352e4c3857 Update to some common RESTAPI classes. 2021-10-15 23:49:34 -07:00
stephb9959
80cf939503 Update to some common RESTAPI classes. 2021-10-15 23:25:11 -07:00
stephb9959
60c0d83a95 Cleanup in return types for RESTAPI 2021-10-15 23:10:57 -07:00
stephb9959
1de5d2902d Fixing GetStatistics: should be ASC and newest should be DESC 2021-10-15 21:29:22 -07:00
stephb9959
62e5060204 Fixing wrong logging for security check. 2021-10-15 09:20:53 -07:00
stephb9959
e317f1c0e2 Fixing CLI for BlackList management. 2021-10-14 15:16:52 -07:00
stephb9959
e87d9efd09 Finishing blacklist managememtn 2021-10-14 14:49:34 -07:00
stephb9959
a92601b285 Adding blacklist support at connection time. 2021-10-14 13:41:29 -07:00
stephb9959
6fa7165171 Including CN for bad devices so we may block them in the future. 2021-10-14 11:29:12 -07:00
stephb9959
7703955b0e Merge remote-tracking branch 'origin/master' 2021-10-14 10:57:45 -07:00
stephb9959
20bfda45bc Adding protection for devices not following protocol. 2021-10-14 10:57:35 -07:00
Dmitry Dunaev
53d914f58a Fix: adapt docker-compose CI check based new changes in deployment repo 2021-10-13 20:54:24 +03:00
stephb9959
b91ddf5272 Adding country list 2021-10-13 10:24:28 -07:00
stephb9959
621b1953d9 Adding country list 2021-10-13 10:01:24 -07:00
stephb9959
63d78d5c14 Merge remote-tracking branch 'origin/master' 2021-10-13 10:01:09 -07:00
stephb9959
e32bf08ef8 Adding country list 2021-10-13 10:00:08 -07:00
stephb9959
bc7d291262 Adding access to the UI in the system info call. 2021-10-13 09:46:44 -07:00
Johann Hoffmann
28e1da2f08 Move template file to root directory (#56)
Signed-off-by: oblom0v <johann.hoffmann@mailbox.org>
2021-10-08 17:25:26 +02:00
stephb9959
f7d6487306 Fixing improper DB setup identification. 2021-10-06 08:41:12 -07:00
stephb9959
b8448355db Fixed a broken link. 2021-10-04 16:08:12 -07:00
stephb9959
b26dd1b709 Fixed a broken link. 2021-10-04 16:07:24 -07:00
stephb9959
7eed435e68 Addded some safety code around device disconnection as a possible crash scenatio was discovered. 2021-10-04 14:05:14 -07:00
stephb9959
29ddc81814 Addded some safety code around device disconnection as a possible crash scenatio was discovered. 2021-10-04 08:40:41 -07:00
stephb9959
6dd1ee63a0 Updating Configuration Validator. 2021-09-30 09:31:55 -07:00
stephb9959
a28904ba62 Updated the configuration validator with latest schema. 2021-09-30 08:56:09 -07:00
stephb9959
bc4bcd7a5c Added the "validateconfig" command. Same used in OW-PROV. 2021-09-30 06:44:23 -07:00
stephb9959
01cc10bd63 Added the "validateOnly" flag for configuration validation. Same used in OW-PROV. 2021-09-30 06:40:13 -07:00
stephb9959
2961b7bb42 Adding required security logging 2021-09-29 20:26:12 -07:00
stephb9959
ee2df31e51 Adding IP address in connection message for provisioning system. 2021-09-29 08:25:38 -07:00
stephb9959
2717ed9d23 Adding IP address in connection message for provisioning system. 2021-09-29 08:07:04 -07:00
stephb9959
942e99cf41 Adding IP address in connection message for provisioning system. 2021-09-29 07:59:47 -07:00
stephb9959
7340abf40e Merge remote-tracking branch 'origin/master' 2021-09-29 06:49:14 -07:00
stephb9959
1d1d744d67 Fix for new device veing added. 2021-09-29 06:49:06 -07:00
Dmitry Dunaev
8656cac16e [WIFI-4240] Fix: revert changes in helm values on ucentral.websocket.* properties 2021-09-28 16:14:49 +03:00
oblom0v
d9552b3971 Add missing backslash in entrypoint script 2021-09-28 13:23:15 +02:00
Dmitry Dunaev
1685224cba [WIFI-4240] Fix: helm deployment template 2021-09-28 13:13:47 +03:00
oblom0v
1ab94d0b78 Restore changes from PR #52 2021-09-28 10:56:03 +02:00
stephb9959
35cc18b1dc Standardizing logs messages and HTTP error messages. 2021-09-27 22:54:52 -07:00
stephb9959
35fbf1d5ca Standardizing logs messages and HTTP error messages. 2021-09-27 22:20:20 -07:00
stephb9959
d29876f948 Build change. 2021-09-27 21:12:49 -07:00
stephb9959
d8b4d4a173 Build change. 2021-09-27 15:38:58 -07:00
Stephane Bourque
ff577f2aa3 Merge pull request #55 from Telecominfraproject/dev-2.2
Dev 2.2
2021-09-27 15:33:38 -07:00
stephb9959
6b871a27e2 conflict 2021-09-27 22:31:02 +00:00
stephb9959
b4b2707f3f conflict 2021-09-27 22:30:00 +00:00
stephb9959
153477b649 resolve conflicts 2021-09-27 22:17:40 +00:00
stephb9959
f73389af3c resolve conflicts 2021-09-27 22:15:37 +00:00
stephb9959
eb361cad14 resolve conflicts 2021-09-27 22:12:12 +00:00
Stephane Bourque
0e7dcf88a3 Merge pull request #52 from Telecominfraproject/WIFI-4240-adapt-ucentral-sdk
[WIFI-4240] Adapt uCentral SDK for deployment changes
2021-09-27 14:07:26 -07:00
Stephane Bourque
7726c8b346 Merge pull request #53 from Telecominfraproject/feature/wifi-4240--adapt-helm
[WIFI-4240] Chg: adapt helm files to 2.2 renaming
2021-09-27 14:07:07 -07:00
stephb9959
b3a0593f8e Refactoring yaml file name. 2021-09-27 09:50:01 -07:00
stephb9959
cd047f8d38 Refactoring errors. 2021-09-27 09:30:58 -07:00
oblom0v
96b09eacc3 Adapt Github actions workflows 2021-09-27 15:35:05 +02:00
Dmitry Dunaev
cafb26e13d [WIFI-4240] Chg: adapt helm files to 2.2 renaming 2021-09-27 15:49:13 +03:00
oblom0v
007d034a54 Add new packages to Docker build 2021-09-24 15:47:10 +02:00
oblom0v
6d578193b6 Adapt renaming in Docker and associated config 2021-09-24 10:17:15 +02:00
stephb9959
0d63f9882d Fixing stats. 2021-09-23 11:46:37 -07:00
stephb9959
1ea2542a00 Refactoring DB Access. 2021-09-23 11:31:33 -07:00
stephb9959
87054cfaa3 Refactoring DB Access. 2021-09-23 11:28:44 -07:00
stephb9959
b4fd04ef9c Refactoring DB Access. 2021-09-23 10:21:49 -07:00
stephb9959
0e1bd681d8 Merge remote-tracking branch 'origin/dev-2.2' into dev-2.2 2021-09-23 10:16:59 -07:00
stephb9959
3919c95250 Refactoring DB Access. 2021-09-23 10:16:44 -07:00
Johann Hoffmann
e85e00a5db [WIFI-3938] Remove ./add-ca-cert.sh script in Docker Compose deployment (#51)
* Update ca-certificates in entrypoint script

* Add restapi-ca.pem to Docker image
2021-09-23 18:04:37 +02:00
Johann Hoffmann
1ef2a62b06 [WIFI-3016] Add support for configuration through environment variables (#48)
* Add template and envsubst call in docker-entrypoint.sh

* Fix env variable name
2021-09-23 18:04:19 +02:00
Johann Hoffmann
95ce12fabc Change ownership of uCentralGW root directory inside Dockerfile (#47) 2021-09-23 18:03:53 +02:00
stephb9959
408183eada Refactoring DB Access. 2021-09-22 22:40:59 -07:00
stephb9959
b7d42c76dc Refactoring DB Access. 2021-09-22 11:41:10 -07:00
stephb9959
7ee0aa57a9 Refactoring DB Access. 2021-09-22 11:18:07 -07:00
stephb9959
51dd6dbc13 Refactoring DB Access. 2021-09-22 11:05:20 -07:00
stephb9959
7f4e6303c7 Refactoring DB Access. 2021-09-22 10:42:27 -07:00
stephb9959
3b59a36012 Ficxing the Newest command call. 2021-09-22 07:12:04 -07:00
stephb9959
3ca43225ae Fixing some device DB issues and improving upgrade detection for configuration. 2021-09-21 22:15:26 -07:00
stephb9959
119638f108 Fixing some device DB issues and improving upgrade detection for configuration. 2021-09-21 21:59:08 -07:00
stephb9959
dd8265c1c7 Fixing some device DB issues and improving upgrade detection for configuration. 2021-09-21 21:48:22 -07:00
stephb9959
f2f413dbfe Fixing some device DB issues and improving upgrade detection for configuration. 2021-09-21 21:38:15 -07:00
stephb9959
271d97e152 Fixing some device DB issues and improving upgrade detection for configuration. 2021-09-21 21:25:03 -07:00
stephb9959
cda780bbca Fixing some device DB issues and improving upgrade detection for configuration. 2021-09-21 20:47:46 -07:00
stephb9959
a739f1e48c Fixing some device DB issues and improving upgrade detection for configuration. 2021-09-21 14:57:51 -07:00
stephb9959
7881e4297b Fixing some device DB issues and improving upgrade detection for configuration. 2021-09-21 14:57:31 -07:00
Johann Hoffmann
0fa0af3159 [WIFI-3938] Remove ./add-ca-cert.sh script in Docker Compose deployment (#51)
* Update ca-certificates in entrypoint script

* Add restapi-ca.pem to Docker image
2021-09-21 19:02:03 +02:00
stephb9959
3ea4e5a641 Fixing config reload. 2021-09-21 08:42:42 -07:00
stephb9959
75fda33eaf Adding RESTAPI_handler fix. 2021-09-20 07:52:33 -07:00
stephb9959
1d9e30ab0f Updating documentation. 2021-09-19 16:20:24 -07:00
stephb9959
771ea62a3e Updating documentation. 2021-09-19 16:19:00 -07:00
stephb9959
c89bee14c0 Adding processing for system commands to support OS information. 2021-09-18 22:31:41 -07:00
stephb9959
f9e52526b4 Adding processing for system commands to support OS information. 2021-09-18 22:00:09 -07:00
stephb9959
ed7ecc0eff Adding processing for system commands to support OS information. 2021-09-18 15:58:40 -07:00
stephb9959
79128169c2 Adding processing for system commands to support OS information. 2021-09-18 15:53:37 -07:00
stephb9959
557538e30d Adding processing for system commands to support OS information. 2021-09-18 15:45:25 -07:00
stephb9959
5d5bdd99d8 Adding processing for system commands to support OS information. 2021-09-18 15:40:51 -07:00
stephb9959
d1b2524632 Adding processing for system commands to support OS information. 2021-09-18 15:38:44 -07:00
stephb9959
2eb3238cdc Adding processing for system commands to support OS information. 2021-09-18 15:28:05 -07:00
stephb9959
b7bc615d05 Adding processing for system commands to support OS information. 2021-09-18 10:32:46 -07:00
stephb9959
222f7df0e4 Adding processing for system commands to support OS information. 2021-09-18 10:05:05 -07:00
stephb9959
c93459bf18 Addressing the command lockup. 2021-09-18 00:01:00 -07:00
stephb9959
8d2173a046 Changing mutex type 2021-09-16 22:01:33 -07:00
stephb9959
efd8b81625 Finishing the TelemetrStream. Changed the mode so now Chrome also works. 2021-09-16 14:35:27 -07:00
stephb9959
24163b5fce Finishing the TelemetrStream. Changed the mode so now Chrome also works. 2021-09-16 14:29:23 -07:00
stephb9959
f50ce2f816 Improving incoming device management with multiple reactors. 2021-09-16 14:13:18 -07:00
stephb9959
cc4ba61c15 Improving incoming device management with multiple reactors. 2021-09-16 12:08:30 -07:00
stephb9959
bbc0255ad4 Improving incoming device management with multiple reactors. 2021-09-16 11:32:17 -07:00
stephb9959
1e0628abf4 Changing WebSocket connection for better performance. 2021-09-16 11:27:26 -07:00
stephb9959
5d8e9355b1 Changing WebSocket connection for better performance. 2021-09-16 11:25:54 -07:00
stephb9959
3eaedf4752 Changing WebSocket connection for better performance. 2021-09-16 11:09:28 -07:00
stephb9959
da38f204b6 Changing WebSocket connection for better performance. 2021-09-16 11:05:42 -07:00
stephb9959
ab29614b99 Changing WebSocket connection for better performance. 2021-09-16 11:03:55 -07:00
stephb9959
881015331c Changing WebSocket connection for better performance. 2021-09-16 10:57:05 -07:00
stephb9959
16ce257dc5 Changing WebSocket connection for better performance. 2021-09-16 10:45:29 -07:00
stephb9959
8b63e5a873 Changing WebSocket connection for better performance. 2021-09-16 10:39:45 -07:00
stephb9959
3b690b1878 Changing WebSocket connection for better performance. 2021-09-16 10:37:55 -07:00
stephb9959
c9157f1df4 Changing WebSocket connection for better performance. 2021-09-16 10:29:50 -07:00
stephb9959
d5f6c7a976 Changing WebSocket connection for better performance. 2021-09-16 10:27:06 -07:00
stephb9959
c9528b7c1d Changing WebSocket connection for better performance. 2021-09-16 10:22:54 -07:00
stephb9959
cf1b5c019f Changing WebSocket connection for better performance. 2021-09-16 08:51:06 -07:00
stephb9959
ee075fff67 Changing WebSocket connection for better performance. 2021-09-16 08:49:53 -07:00
stephb9959
348f30a05f Changing WebSocket connection for better performance. 2021-09-16 08:48:29 -07:00
stephb9959
c0930929d9 Changing WebSocket connection for better performance. 2021-09-16 08:47:42 -07:00
stephb9959
cbd2b3ccb9 Changing WebSocket connection for better performance. 2021-09-16 08:43:17 -07:00
stephb9959
c53d98282a Changing WebSocket connection for better performance. 2021-09-16 08:39:56 -07:00
stephb9959
871063e029 Changing WebSocket connection for better performance. 2021-09-16 08:22:41 -07:00
stephb9959
94c6f89f4a Changing WebSocket connection for better performance. 2021-09-16 08:16:46 -07:00
stephb9959
24f1561847 Changing WebSocket connection for better performance. 2021-09-16 08:07:51 -07:00
stephb9959
61472453a1 Changing WebSocket connection for better performance. 2021-09-16 08:04:29 -07:00
stephb9959
4031c94fb9 Adding processing for close frame. 2021-09-16 00:14:07 -07:00
stephb9959
25079004b8 Adding processing for close frame. 2021-09-16 00:10:15 -07:00
stephb9959
61f89fb005 Adding processing for close frame. 2021-09-16 00:05:58 -07:00
stephb9959
5b51a097b2 Adding processing for close frame. 2021-09-15 23:59:39 -07:00
stephb9959
417b82ce70 Adding processing for close frame. 2021-09-15 23:57:06 -07:00
stephb9959
6ca66e313f Adding processing for close frame. 2021-09-15 23:50:18 -07:00
stephb9959
45a7d5066e Adding processing for close frame. 2021-09-15 23:48:21 -07:00
stephb9959
000a01ab09 Adding processing for close frame. 2021-09-15 23:44:41 -07:00
stephb9959
fca3fcf6a8 Adding processing for close frame. 2021-09-15 23:35:59 -07:00
stephb9959
f3ff04c185 Adding processing for close frame. 2021-09-15 23:31:41 -07:00
stephb9959
5d96d5f572 Adding processing for close frame. 2021-09-15 23:20:21 -07:00
stephb9959
7fc45c160e Adding processing for close frame. 2021-09-15 23:15:13 -07:00
stephb9959
83c1bb305b Adding processing for close frame. 2021-09-15 23:11:02 -07:00
stephb9959
63ac9d2c72 Adding processing for close frame. 2021-09-15 23:05:15 -07:00
stephb9959
0ee5c56d33 Adding processing for close frame. 2021-09-15 22:59:13 -07:00
stephb9959
f6cd8bd73e Adding processing for close frame. 2021-09-15 22:58:20 -07:00
stephb9959
d49b89b775 Adding processing for close frame. 2021-09-15 22:54:41 -07:00
stephb9959
7183767a50 Adding processing for close frame. 2021-09-15 21:33:52 -07:00
stephb9959
b38c657a27 Adding processing for close frame. 2021-09-15 21:31:57 -07:00
stephb9959
2ea8fdf57f Adding processing for close frame. 2021-09-15 19:11:30 -07:00
stephb9959
b8d5b86b3e Adding processing for close frame. 2021-09-15 19:05:08 -07:00
stephb9959
0aa5837ea2 Adding processing for close frame. 2021-09-15 19:01:28 -07:00
stephb9959
187f1669cf Adding processing for close frame. 2021-09-15 18:54:36 -07:00
stephb9959
faebf38a3f Adding processing for close frame. 2021-09-15 17:19:23 -07:00
stephb9959
488d5d0a24 Adding processing for close frame. 2021-09-15 17:15:58 -07:00
stephb9959
461094d883 Adding processing for close frame. 2021-09-15 17:09:55 -07:00
stephb9959
bf00fa34f4 Adding processing for close frame. 2021-09-15 17:05:38 -07:00
stephb9959
2d283ffd32 Adding processing for close frame. 2021-09-15 17:02:00 -07:00
stephb9959
5ec8523b46 Adding processing for close frame. 2021-09-15 17:01:21 -07:00
stephb9959
a78c2f6961 Adding processing for close frame. 2021-09-15 16:42:52 -07:00
stephb9959
14f2ea79e1 Adding processing for close frame. 2021-09-15 16:37:16 -07:00
stephb9959
fcb3f2efbc Adding processing for close frame. 2021-09-15 16:24:22 -07:00
stephb9959
2061a3a699 Adding processing for close frame. 2021-09-15 16:20:00 -07:00
stephb9959
8e4c528da5 Adding processing for close frame. 2021-09-15 16:18:34 -07:00
stephb9959
8277f8dd92 Adding processing for close frame. 2021-09-15 16:14:56 -07:00
stephb9959
6a1f844631 Adding processing for close frame. 2021-09-15 16:11:57 -07:00
stephb9959
0ba02f1c70 Adding processing for close frame. 2021-09-15 13:52:05 -07:00
stephb9959
79e0304841 Adding processing for close frame. 2021-09-15 13:25:43 -07:00
stephb9959
5fa7a2d766 Changing telemetry close. 2021-09-15 12:42:14 -07:00
stephb9959
1d1caa7270 Adding proper security logging. 2021-09-15 12:02:00 -07:00
stephb9959
d740167972 Adding proper security logging. 2021-09-15 11:56:55 -07:00
stephb9959
bf93257343 Adding proper security logging. 2021-09-15 11:56:30 -07:00
stephb9959
2286a9063f Telemetry Stream Implemented. 2021-09-14 22:28:23 -07:00
stephb9959
1e35473b82 Telemetry Stream Implemented. 2021-09-14 22:12:53 -07:00
stephb9959
17f0dc4de9 Changing log level from error to information. 2021-09-14 22:07:57 -07:00
stephb9959
8c21b86d5c Changing log level from error to information. 2021-09-14 22:03:33 -07:00
stephb9959
f6780d545d Changing log level from error to information. 2021-09-14 21:52:18 -07:00
stephb9959
6a63a252d5 Changing log level from error to information. 2021-09-14 21:51:49 -07:00
stephb9959
51f8bd7342 Changing log level from error to information. 2021-09-14 21:40:57 -07:00
stephb9959
c0d199a12e Changing log level from error to information. 2021-09-14 21:37:45 -07:00
stephb9959
06a997c6cb Changing log level from error to information. 2021-09-14 21:25:39 -07:00
stephb9959
c2ead350aa Changing log level from error to information. 2021-09-14 21:12:55 -07:00
stephb9959
9941b9a15c Changing log level from error to information. 2021-09-14 21:08:24 -07:00
stephb9959
ef58d30ae3 Changing log level from error to information. 2021-09-14 21:04:56 -07:00
stephb9959
aa6e4e6350 Changing log level from error to information. 2021-09-14 20:55:52 -07:00
stephb9959
6e03253aac Changing log level from error to information. 2021-09-14 20:54:16 -07:00
stephb9959
79c37e3e71 Changing log level from error to information. 2021-09-14 19:49:11 -07:00
stephb9959
44fca56806 Changing log level from error to information. 2021-09-14 19:46:55 -07:00
stephb9959
7d0571269a Changing en erroneous log level. 2021-09-13 09:04:49 -07:00
stephb9959
0734e93b7c Changing log level from error to information. 2021-09-13 08:34:56 -07:00
stephb9959
5986d34e24 Fixing CommandManager problems. 2021-09-12 14:07:05 -07:00
stephb9959
0edd85e991 Fixing CommandManager problems. 2021-09-12 12:40:02 -07:00
stephb9959
1d4995641b Fixing CommandManager problems. 2021-09-11 20:18:51 -07:00
stephb9959
3be56ada41 Fixing RPC Loop lock problem. 2021-09-11 20:12:45 -07:00
stephb9959
a1160f7de5 Adding support for fileuplaod URI 2021-09-10 20:52:52 -07:00
stephb9959
17971d1dd0 Fixing RPC Loop lock problem. 2021-09-10 20:46:55 -07:00
stephb9959
7a762ab3f2 Adding support for fileuplaod URI 2021-09-10 20:45:41 -07:00
stephb9959
1a9ddd2df9 Adding support for fileuplaod URI 2021-09-10 20:27:57 -07:00
stephb9959
f3ae6de093 Adding support for fileuplaod URI 2021-09-10 20:16:32 -07:00
stephb9959
219e8fc59e Adding support for fileuplaod URI 2021-09-10 20:09:17 -07:00
stephb9959
389fcb9f3b Adding support for fileuplaod URI 2021-09-10 20:03:39 -07:00
stephb9959
e40abd2a91 Adding support for fileuplaod URI 2021-09-10 19:55:33 -07:00
stephb9959
ee11dc8d91 Adding support for fileuplaod URI 2021-09-10 19:51:34 -07:00
stephb9959
a9ec2e7821 Adding support for fileuplaod URI 2021-09-10 19:09:03 -07:00
stephb9959
b6b1c99c86 Adding support for fileuplaod URI 2021-09-10 18:58:43 -07:00
stephb9959
31f96968b2 Adding support for fileuplaod URI 2021-09-09 10:47:24 -07:00
stephb9959
1e845a6ff2 Fixing bug 3202 2021-09-09 09:00:39 -07:00
stephb9959
0e9ddee588 Adding some logs for fileuploading. 2021-09-09 08:14:06 -07:00
stephb9959
6e167372b5 Adding support for fileuplaod URI 2021-09-09 07:52:08 -07:00
stephb9959
1e1f0c37e9 Adding ucentral.fileupoloader.uri to support port mapping through docker. 2021-09-09 07:45:35 -07:00
stephb9959
4cf10b0f3a Solve WIFI-3733 and WIFI-3434 2021-09-07 17:57:17 -07:00
stephb9959
314fef87e2 Adding telemetry stream. 2021-09-07 11:13:40 -07:00
stephb9959
e4e2075021 Merge remote-tracking branch 'origin/master' 2021-09-03 08:03:23 -07:00
stephb9959
314ae21d6a Fixing disconnection bug. 2021-09-03 08:03:12 -07:00
stephb9959
8ad0da5781 Fixed disconne ctions. 2021-09-02 19:10:01 -07:00
Johann Hoffmann
935cc78bb4 [WIFI-3016] Add support for configuration through environment variables (#48)
* Add template and envsubst call in docker-entrypoint.sh

* Fix env variable name
2021-09-02 19:01:36 +02:00
stephb9959
5bc7508d96 Fixed disconne ctions. 2021-09-01 23:37:30 -07:00
stephb9959
498e8f880c Fixed disconne ctions. 2021-09-01 23:22:13 -07:00
stephb9959
e9e5d8be41 Fixed disconne ctions. 2021-09-01 23:07:01 -07:00
stephb9959
319e8918b1 Fixed disconne ctions. 2021-09-01 19:24:15 -07:00
stephb9959
0d6471acae Fixing Namespace 2021-08-31 22:52:18 -07:00
stephb9959
41a04c9108 Fixing Namespace 2021-08-31 17:08:54 -07:00
stephb9959
95cc17bb16 Fixing Namespace 2021-08-31 15:30:54 -07:00
stephb9959
9f9e1b4cdb Fixing Namespace 2021-08-31 14:53:11 -07:00
170 changed files with 15252 additions and 8340 deletions

View File

@@ -28,7 +28,7 @@ jobs:
- uses: actions/checkout@v2
- name: Build Docker image
run: docker build -t wlan-cloud-ucentralgw:${{ github.sha }} .
run: docker build -t wlan-cloud-owgw:${{ github.sha }} .
- name: Tag Docker image
run: |
@@ -52,7 +52,7 @@ jobs:
echo "Result tags: $TAGS"
for tag in $TAGS; do
docker tag wlan-cloud-ucentralgw:${{ github.sha }} ${{ env.DOCKER_REGISTRY_URL }}/ucentralgw:$tag
docker tag wlan-cloud-owgw:${{ github.sha }} ${{ env.DOCKER_REGISTRY_URL }}/owgw:$tag
done
- name: Log into Docker registry
@@ -66,7 +66,7 @@ jobs:
- name: Push Docker images
if: startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/pull/') || github.ref == 'refs/heads/master'
run: |
docker images | grep ${{ env.DOCKER_REGISTRY_URL }}/ucentralgw | awk -F ' ' '{print $1":"$2}' | xargs -I {} docker push {}
docker images | grep ${{ env.DOCKER_REGISTRY_URL }}/owgw | awk -F ' ' '{print $1":"$2}' | xargs -I {} docker push {}
docker-compose:
if: startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/pull/') || github.ref == 'refs/heads/master'
@@ -82,11 +82,11 @@ jobs:
- name: Instantiate Docker Compose deployment
working-directory: ./wlan-cloud-ucentral-deploy/docker-compose
env:
UCENTRALGW_TAG: ${{ github.sha }}
OWGW_TAG: ${{ github.sha }}
run: |
docker-compose up -d
- name: Wait for uCentralSec to be alive and kicking
- name: Wait for OWSec to be alive and kicking
run: |
n=0
until [ "$n" -ge 3 ]
@@ -100,11 +100,6 @@ jobs:
fi
done
- name: Add self-signed certificates to system trust store of containers
working-directory: ./wlan-cloud-ucentral-deploy/docker-compose
run: |
./add-ca-cert.sh
- name: Check out wlan-cloud-ucentralgw repository
uses: actions/checkout@v2
with:
@@ -112,8 +107,8 @@ jobs:
- name: Check functionality of microservices
env:
UCENTRALSEC: "ucentral.wlan.local:16001"
FLAGS: "-s --cacert ./wlan-cloud-ucentral-deploy/docker-compose/certs/restapi-ca.pem --resolve ucentral.wlan.local:16001:127.0.0.1"
OWSEC: "openwifi.wlan.local:16001"
FLAGS: "-s --cacert ./wlan-cloud-ucentral-deploy/docker-compose/certs/restapi-ca.pem --resolve openwifi.wlan.local:16001:127.0.0.1"
run: |
./wlan-cloud-ucentralgw/test_scripts/curl/cli listdevices

View File

@@ -17,4 +17,4 @@ jobs:
- name: Cleanup Docker image with PR branch tag
run: |
export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-')
curl -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/ucentralgw/$PR_BRANCH_TAG"
curl -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owgw/$PR_BRANCH_TAG"

View File

@@ -82,6 +82,9 @@ Do wifiscan for a device.
- `serial`: device serial number
- `verbose`: verbose=true/false
### telemetry <serial>
Start `telemetry` stream for a device.
### trace <serial> <duration> <network>
Launch a remote trace for a device.
- `serial`: device serial number
@@ -161,12 +164,23 @@ Get a list of devices based on a list.
### deviceswithstatus
Get devices with their status.
### setloglevel <sys> <level>
Set the logging system level for individual subsystems.
- `sys`: ufileuploader/websocket/storage/restapi/commandmanager/auth/deviceregistry/all
- `level`: level:none/fatal/critical/error/warning/notice/information/debug/trace
### setloglevel <subsystem> <loglevel>
Set the log level for s specific subsystem.
### getfile <uuid>
### getloglevels
Get the current log levels for all subsystems.
### getloglevelnames
Get the log level names available.
### getsubsystemnames
Get the list of subsystems.
### systeminfo
Get basic system information.
### reloadsubsystem <subsystem name>
Reload the configuration for a subsystem.### getfile <uuid>
Get the file associated with trace command <uuid>.
- `uuid`: UUID of file to retrieve

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13)
project(ucentralgw VERSION 2.1.0)
project(owgw VERSION 2.4.0)
set(CMAKE_CXX_STANDARD 17)
@@ -29,7 +29,20 @@ else()
set(BUILD_NUM 1)
file(WRITE build ${BUILD_NUM})
endif()
add_definitions(-DAPP_VERSION="${CMAKE_PROJECT_VERSION}" -DBUILD_NUMBER="${BUILD_NUM}")
find_package(Git QUIET)
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
execute_process(COMMAND ${GIT_EXECUTABLE} describe --always --tags
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_RESULT
OUTPUT_VARIABLE GIT_HASH)
if(NOT GIT_RESULT EQUAL "0")
message(FATAL_ERROR "git describe --always --tags failed with ${GIT_RESULT}")
endif()
string(REGEX REPLACE "\n$" "" GIT_HASH "${GIT_HASH}")
endif()
add_definitions(-DAWS_CUSTOM_MEMORY_MANAGEMENT)
add_definitions(-DTIP_GATEWAY_SERVICE="1")
set(Boost_USE_STATIC_LIBS OFF)
@@ -38,6 +51,8 @@ set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost REQUIRED system)
find_package(OpenSSL REQUIRED)
find_package(ZLIB REQUIRED)
find_package(nlohmann_json REQUIRED)
find_package(nlohmann_json_schema_validator REQUIRED)
if(SMALL_BUILD)
find_package(Poco REQUIRED COMPONENTS Crypto JWT Net Util NetSSL Data DataSQLite)
@@ -50,69 +65,80 @@ endif()
include_directories(/usr/local/include /usr/local/opt/openssl/include src include/kafka /usr/local/opt/mysql-client/include)
add_executable( ucentralgw
build
src/Daemon.cpp src/Daemon.h
src/RESTAPI_server.cpp src/RESTAPI_server.h
src/WebSocketServer.cpp src/WebSocketServer.h
src/SubSystemServer.cpp src/SubSystemServer.h
src/StorageService.cpp src/StorageService.h
src/RESTAPI_SecurityObjects.cpp src/RESTAPI_SecurityObjects.h
src/DeviceRegistry.cpp src/DeviceRegistry.h
src/RESTAPI_devices_handler.cpp src/RESTAPI_devices_handler.h
src/RESTAPI_device_handler.cpp src/RESTAPI_device_handler.h
src/RESTAPI_handler.cpp src/RESTAPI_handler.h
src/RESTAPI_device_commandHandler.cpp src/RESTAPI_device_commandHandler.h
src/RESTAPI_GWobjects.h src/RESTAPI_GWobjects.cpp
src/CentralConfig.cpp src/CentralConfig.h
src/RESTAPI_default_configuration.cpp
src/RESTAPI_InternalServer.cpp src/RESTAPI_InternalServer.h
src/RESTAPI_default_configuration.h src/RESTAPI_default_configurations.cpp src/RESTAPI_default_configurations.h
src/RESTAPI_commands.cpp src/RESTAPI_commands.h
src/CommandManager.cpp src/CommandManager.h
src/RESTAPI_command.cpp src/RESTAPI_command.h
src/FileUploader.cpp src/FileUploader.h
src/RESTAPI_file.cpp src/RESTAPI_file.h
src/RESTAPI_system_command.cpp src/RESTAPI_system_command.h
src/RESTAPI_BlackList.cpp src/RESTAPI_BlackList.h
src/Utils.h src/Utils.cpp src/storage_blacklist.cpp
src/storage_command.cpp src/storage_healthcheck.cpp src/storage_statistics.cpp src/storage_logs.cpp
src/storage_device.cpp src/storage_capabilities.cpp src/storage_defconfig.cpp
src/storage_tables.cpp
src/storage_setup.cpp
src/StateProcessor.cpp src/StateProcessor.h
src/storage_lifetime_stats.cpp src/uCentralProtocol.h src/RESTAPI_protocol.h
src/ALBHealthCheckServer.h src/Kafka_topics.h
src/OUIServer.cpp src/OUIServer.h
src/RESTAPI_ouis.cpp src/RESTAPI_ouis.h
src/MicroService.cpp src/MicroService.h
src/RESTAPI_RPC.cpp src/RESTAPI_RPC.h
src/AuthClient.cpp src/AuthClient.h
src/OpenAPIRequest.cpp src/OpenAPIRequest.h
src/RESTAPI_utils.h src/RESTAPI_utils.cpp
src/StorageArchiver.cpp src/StorageArchiver.h
src/Dashboard.cpp src/Dashboard.h
src/RESTAPI_deviceDashboardHandler.cpp src/RESTAPI_deviceDashboardHandler.h
src/SerialNumberCache.cpp src/SerialNumberCache.h
src/RESTAPI_webSocketServer.cpp src/RESTAPI_webSocketServer.h
src/OpenWifiTypes.h)
configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY)
add_executable( owgw
build
src/ow_version.h.in
src/framework/CountryCodes.h
src/framework/KafkaTopics.h
src/framework/MicroService.h
src/framework/OpenWifiTypes.h
src/framework/orm.h
src/framework/RESTAPI_errors.h
src/framework/RESTAPI_protocol.h
src/framework/StorageClass.h
src/framework/uCentral_Protocol.h
src/RESTObjects/RESTAPI_SecurityObjects.h src/RESTObjects/RESTAPI_SecurityObjects.cpp
src/RESTObjects/RESTAPI_ProvObjects.cpp src/RESTObjects/RESTAPI_ProvObjects.h
src/RESTObjects/RESTAPI_GWobjects.h src/RESTObjects/RESTAPI_GWobjects.cpp
src/RESTObjects/RESTAPI_FMSObjects.h src/RESTObjects/RESTAPI_FMSObjects.cpp
src/RESTAPI/RESTAPI_devices_handler.cpp src/RESTAPI/RESTAPI_devices_handler.h
src/RESTAPI/RESTAPI_device_handler.cpp src/RESTAPI/RESTAPI_device_handler.h
src/RESTAPI/RESTAPI_device_commandHandler.cpp src/RESTAPI/RESTAPI_device_commandHandler.h
src/RESTAPI/RESTAPI_default_configuration.cpp
src/RESTAPI/RESTAPI_default_configuration.h src/RESTAPI/RESTAPI_default_configurations.cpp src/RESTAPI/RESTAPI_default_configurations.h
src/RESTAPI/RESTAPI_commands.cpp src/RESTAPI/RESTAPI_commands.h
src/RESTAPI/RESTAPI_command.cpp src/RESTAPI/RESTAPI_command.h
src/RESTAPI/RESTAPI_file.cpp src/RESTAPI/RESTAPI_file.h
src/RESTAPI/RESTAPI_blacklist.cpp src/RESTAPI/RESTAPI_blacklist.h
src/RESTAPI/RESTAPI_ouis.cpp src/RESTAPI/RESTAPI_ouis.h
src/RESTAPI/RESTAPI_blacklist_list.cpp src/RESTAPI/RESTAPI_blacklist_list.h
src/RESTAPI/RESTAPI_capabilities_handler.cpp src/RESTAPI/RESTAPI_capabilities_handler.h
src/RESTAPI/RESTAPI_RPC.cpp src/RESTAPI/RESTAPI_RPC.h
src/RESTAPI/RESTAPI_deviceDashboardHandler.cpp src/RESTAPI/RESTAPI_deviceDashboardHandler.h
src/RESTAPI/RESTAPI_TelemetryWebSocket.cpp src/RESTAPI/RESTAPI_TelemetryWebSocket.h
src/RESTAPI/RESTAPI_webSocketServer.cpp src/RESTAPI/RESTAPI_webSocketServer.h
src/storage/storage_blacklist.cpp src/storage/storage_tables.cpp src/storage/storage_logs.cpp
src/storage/storage_command.cpp src/storage/storage_healthcheck.cpp src/storage/storage_statistics.cpp
src/storage/storage_device.cpp src/storage/storage_capabilities.cpp src/storage/storage_defconfig.cpp
src/storage/storage_tables.cpp
src/APIServers.cpp
src/Daemon.cpp src/Daemon.h
src/StateProcessor.cpp src/StateProcessor.h
src/storage/storage_lifetime_stats.cpp
src/WebSocketServer.cpp src/WebSocketServer.h
src/StorageService.cpp src/StorageService.h
src/DeviceRegistry.cpp src/DeviceRegistry.h
src/CommandManager.cpp src/CommandManager.h
src/CentralConfig.cpp src/CentralConfig.h
src/FileUploader.cpp src/FileUploader.h
src/OUIServer.cpp src/OUIServer.h
src/StorageArchiver.cpp src/StorageArchiver.h
src/Dashboard.cpp src/Dashboard.h
src/SerialNumberCache.cpp src/SerialNumberCache.h
src/TelemetryStream.cpp src/TelemetryStream.h
src/framework/ConfigurationValidator.cpp src/framework/ConfigurationValidator.h
src/ConfigurationCache.cpp src/ConfigurationCache.h
)
if(NOT SMALL_BUILD)
target_sources(ucentralgw PUBLIC src/KafkaManager.cpp src/KafkaManager.h)
endif()
INSTALL(TARGETS ucentralgw
INSTALL(TARGETS owgw
RUNTIME DESTINATION /usr/bin
)
target_link_libraries(ucentralgw PUBLIC
target_link_libraries(owgw PUBLIC
${Poco_LIBRARIES} ${Boost_LIBRARIES} ${ZLIB_LIBRARIES})
if(NOT SMALL_BUILD)
target_link_libraries(ucentralgw PUBLIC
target_link_libraries(owgw PUBLIC
${MySQL_LIBRARIES} ${ZLIB_LIBRARIES}
CppKafka::cppkafka
CppKafka::cppkafka
nlohmann_json_schema_validator
)
if(UNIX AND NOT APPLE)
target_link_libraries(ucentralgw PUBLIC PocoJSON)
target_link_libraries(owgw PUBLIC PocoJSON)
endif()
endif()

View File

@@ -7,10 +7,12 @@ RUN apk add --update --no-cache \
make cmake gcc g++ libstdc++ libgcc git zlib-dev yaml-cpp-dev \
openssl-dev boost-dev unixodbc-dev postgresql-dev mariadb-dev \
apache2-utils yaml-dev apr-util-dev \
lua-dev librdkafka-dev
lua-dev librdkafka-dev \
nlohmann-json
RUN git clone https://github.com/stephb9959/poco /poco
RUN git clone https://github.com/stephb9959/cppkafka /cppkafka
RUN git clone https://github.com/pboettch/json-schema-validator /json-schema-validator
WORKDIR /cppkafka
RUN mkdir cmake-build
@@ -26,36 +28,51 @@ RUN cmake ..
RUN cmake --build . --config Release -j8
RUN cmake --build . --target install
ADD CMakeLists.txt build /ucentralgw/
ADD cmake /ucentralgw/cmake
ADD src /ucentralgw/src
WORKDIR /ucentralgw
WORKDIR /json-schema-validator
RUN mkdir cmake-build
WORKDIR /ucentralgw/cmake-build
WORKDIR cmake-build
RUN cmake ..
RUN make
RUN make install
ADD CMakeLists.txt build /owgw/
ADD cmake /owgw/cmake
ADD src /owgw/src
ADD .git /owgw/.git
WORKDIR /owgw
RUN mkdir cmake-build
WORKDIR /owgw/cmake-build
RUN cmake ..
RUN cmake --build . --config Release -j8
FROM alpine
ENV UCENTRALGW_USER=ucentralgw \
UCENTRALGW_ROOT=/ucentralgw-data \
UCENTRALGW_CONFIG=/ucentralgw-data
ENV OWGW_USER=owgw \
OWGW_ROOT=/owgw-data \
OWGW_CONFIG=/owgw-data
RUN addgroup -S "$UCENTRALGW_USER" && \
adduser -S -G "$UCENTRALGW_USER" "$UCENTRALGW_USER"
RUN addgroup -S "$OWGW_USER" && \
adduser -S -G "$OWGW_USER" "$OWGW_USER"
RUN mkdir /ucentral
RUN mkdir -p "$UCENTRALGW_ROOT" "$UCENTRALGW_CONFIG" && \
chown "$UCENTRALGW_USER": "$UCENTRALGW_ROOT" "$UCENTRALGW_CONFIG"
RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc su-exec
RUN mkdir /openwifi
RUN mkdir -p "$OWGW_ROOT" "$OWGW_CONFIG" && \
chown "$OWGW_USER": "$OWGW_ROOT" "$OWGW_CONFIG"
RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc su-exec gettext ca-certificates bash jq curl postgresql-client
COPY --from=builder /ucentralgw/cmake-build/ucentralgw /ucentral/ucentralgw
COPY --from=builder /owgw/cmake-build/owgw /openwifi/owgw
COPY --from=builder /cppkafka/cmake-build/src/lib/* /lib/
COPY --from=builder /poco/cmake-build/lib/* /lib/
COPY owgw.properties.tmpl /
COPY docker-entrypoint.sh /
COPY wait-for-postgres.sh /
RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentral-deploy/main/docker-compose/certs/restapi-ca.pem \
-O /usr/local/share/ca-certificates/restapi-ca-selfsigned.pem
COPY readiness_check /readiness_check
EXPOSE 15002 16002 16003 17002 16102
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/ucentral/ucentralgw"]
CMD ["/openwifi/owgw"]

View File

@@ -2,7 +2,7 @@
This document will describe how the API is built and how to use it.
## Where is the OpenAPI.
This uses OpenAPI definition 3.0 and can be found [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/openapi/ucentral/ucentral.yaml).
This uses OpenAPI definition 3.0 and can be found [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/openapi/ucentral/owgw.yaml).
All endpoints begin with `/api/v1`.
## The flow

View File

@@ -155,6 +155,22 @@ which version it is running. The Controller may decide to send the device a newe
}
```
#### Recovery Event
Device may decide it has to do into recovery mode. This event should be used.
```
{ "jsonrpc" : "2.0" ,
"method" : "recovery" ,
"params" : {
"serial" : <serial number> ,
"uuid" : <the UUID of the configuration that generated the crash log>,
"firmware: <the string describing the current firmware>,
"reboot" : true/false (shoudld the device be instructed to reboot after loggin the information),
"loglines" : [ an array of strings representing the logs from the log file ]
}
}
```
### Controller commands
Most controller commands include a `when` member. This is a UTC clock time asking the AP
to perform the command at that time. This is a suggestion only. The AP may ignore this
@@ -518,6 +534,48 @@ The device should answer:
}
```
#### Controller requesting telemetry stream information
Controller sends this command when it needs the device to telemetry streaming.
```
{ "jsonrpc" : "2.0" ,
"method" : "telemetry" ,
"params" : {
"serial" : <serial number> ,
"interval" : 0-60, # number of seconds for polling information. 0 means to shutdown the stream
"types" : [ "dhcp", "rrm"], <this must be an array: array of 1 or 2 elements, right now only "rrm" and "dhcp" are supported
},
"id" : <some number>
}
```
The device should answer:
```
{ "jsonrpc" : "2.0" ,
"result" : {
"serial" : <serial number> ,
"status" : {
"error" : 0 or an error number,
"text" : <description of the error or success>
}
},
"id" : <same number>
}
```
When the interval is greater than 0, the gateway will start to receive messages
```
{ "jsonrpc" : "2.0" ,
"method" : "telemetry" ,
"params" : {
"serial" : <serial number> ,
"data" : <A JSON document describing the information coming from the device>
}
}
```
The device will stop sending data after 30 minutes or if it receives a `telemetry` command with an interval of 0.
#### Controller requesting an `rtty` session
Controller sends this command an administrator requests to start an `rtty` session with the AP.
```

116
README.md
View File

@@ -26,9 +26,9 @@ Poco may take several minutes depending on the platform you are building on.
### Ubuntu
These instructions have proven to work on Ubuntu 20.4.
```
sudo apt install git cmake g++ libssl-dev libmariadb-dev unixodbc-dev
sudo apt install git cmake g++ libssl-dev libmariadb-dev
sudo apt install libpq-dev libaprutil1-dev apache2-dev libboost-all-dev
sudo apt install librdkafka-dev liblua5.3-dev libmysqlclient-dev
sudo apt install librdkafka-dev libmysqlclient-dev default-libmysqlclient-dev
git clone https://github.com/stephb9959/poco
cd poco
@@ -179,7 +179,7 @@ You should now have the following:
+-- test_scripts
+-- openapi
+-- uploads
+-- ucentralgw.properties
+-- owgw.properties
```
### Certificates
@@ -218,14 +218,14 @@ document. Once you have these files, you need to renamed them `restapi-key.pem`,
in your browner
#### Configuration
The configuration for this service is kept in a properties file. This file is called `ucentralgw.properties` and you can
see the latest version [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/ucentralgw.properties). The file will be loaded from
The configuration for this service is kept in a properties file. This file is called `owgw.properties` and you can
see the latest version [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/owgw.properties). The file will be loaded from
the directory set by the environment variable `UCENTRALGW_CONFIG`. To use environment variables in the configuration,
you must use `$<varname>`. Only `path names` support the use of environment variables. The sample configuration requires very
little changes if you keep the suggested directory structure. For the sample configuration to work, you need to define 2
environment variables.
```
export UCENTRALGW_ROOT=`pwd`
export OWGW_ROOT=`pwd`
export UCENTRALGW_CONFIG=`pwd`
```
If you current working directory is the root of the project, this will set the variables properly. Otherwise, you can set the variables
@@ -234,7 +234,7 @@ to point to wherever is necessary.
##### Important config entries
###### This is the logging directory
```
logging.channels.c2.path = $UCENTRALGW_ROOT/logs/sample.log
logging.channels.c2.path = $OWGW_ROOT/logs/sample.log
```
###### This is the type of storage in use
@@ -244,23 +244,23 @@ storage.type = sqlite
###### Autoprovisioning settings
```asm
ucentral.autoprovisioning = true
ucentral.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
ucentral.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
ucentral.devicetypes.2 = IOT:esp32
openwifi.autoprovisioning = true
openwifi.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
openwifi.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
openwifi.devicetypes.2 = IOT:esp32
```
###### This is the RESTAPI endpoint
```asm
ucentral.restapi.host.0.backlog = 100
ucentral.restapi.host.0.security = relaxed
ucentral.restapi.host.0.rootca = $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.restapi.host.0.address = *
ucentral.restapi.host.0.port = 16002
ucentral.restapi.host.0.cert = $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.restapi.host.0.key = $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.restapi.host.0.key.password = mypassword
openwifi.restapi.host.0.backlog = 100
openwifi.restapi.host.0.security = relaxed
openwifi.restapi.host.0.rootca = $OWGW_ROOT/certs/restapi-ca.pem
openwifi.restapi.host.0.address = *
openwifi.restapi.host.0.port = 16002
openwifi.restapi.host.0.cert = $OWGW_ROOT/certs/restapi-cert.pem
openwifi.restapi.host.0.key = $OWGW_ROOT/certs/restapi-key.pem
openwifi.restapi.host.0.key.password = mypassword
```
##### This is the end point for the devices to connect with
@@ -309,12 +309,12 @@ You will need to get the `cert.pem` and `key.pem` from Digicert. The rest is her
```asm
ucentral.websocket.host.0.backlog = 500
ucentral.websocket.host.0.rootca = $UCENTRALGW_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer = $UCENTRALGW_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert = $UCENTRALGW_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key = $UCENTRALGW_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas = $UCENTRALGW_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas = $UCENTRALGW_ROOT/certs/cas
ucentral.websocket.host.0.rootca = $OWGW_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer = $OWGW_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert = $OWGW_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key = $OWGW_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas = $OWGW_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas = $OWGW_ROOT/certs/cas
ucentral.websocket.host.0.address = *
ucentral.websocket.host.0.port = 15002
ucentral.websocket.host.0.security = strict
@@ -324,17 +324,17 @@ ucentral.websocket.maxreactors = 20
###### This is the end point for the devices when uploading files
```asm
ucentral.fileuploader.host.0.backlog = 100
ucentral.fileuploader.host.0.rootca = $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.fileuploader.host.0.security = relaxed
ucentral.fileuploader.host.0.address = *
ucentral.fileuploader.host.0.name = 192.168.1.176
ucentral.fileuploader.host.0.port = 16003
ucentral.fileuploader.host.0.cert = $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.fileuploader.host.0.key = $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.fileuploader.host.0.key.password = mypassword
ucentral.fileuploader.path = $UCENTRALGW_ROOT/uploads
ucentral.fileuploader.maxsize = 10000
openwifi.fileuploader.host.0.backlog = 100
openwifi.fileuploader.host.0.rootca = $OWGW_ROOT/certs/restapi-ca.pem
openwifi.fileuploader.host.0.security = relaxed
openwifi.fileuploader.host.0.address = *
openwifi.fileuploader.host.0.name = 192.168.1.176
openwifi.fileuploader.host.0.port = 16003
openwifi.fileuploader.host.0.cert = $OWGW_ROOT/certs/restapi-cert.pem
openwifi.fileuploader.host.0.key = $OWGW_ROOT/certs/restapi-key.pem
openwifi.fileuploader.host.0.key.password = mypassword
openwifi.fileuploader.path = $OWGW_ROOT/uploads
openwifi.fileuploader.maxsize = 10000
```
###### host.0.address entries
@@ -343,7 +343,7 @@ the `*`. Using the `*` means all interfaces will be able to accept connections.
by changing the `0` to another index. You need to repeat the whole configuration block for each index. Indexes must be sequential
start at `0`.
###### ucentral.fileuploader.host.0.name
###### openwifi.fileuploader.host.0.name
This must point to the IP or FQDN of your uCentralGW.
#### Running the gateway
@@ -369,7 +369,7 @@ can be any of the keys you are already using. You must keep that keep secret and
this is the entry
```asm
ucentral.service.key = $UCENTRALGW_ROOT/certs/websocket-key.pem
openwifi.service.key = $OWGW_ROOT/certs/websocket-key.pem
```
#### Command line options
@@ -440,9 +440,9 @@ then
exit 1
fi
if [[ ! -f ucentralgw.properties ]]
if [[ ! -f owgw.properties ]]
then
echo "Configuration file ucentralgw.properties is missing in the current directory"
echo "Configuration file owgw.properties is missing in the current directory"
exit 2
fi
@@ -458,9 +458,9 @@ docker run -d -p 15002:15002 \
```
Create yourself a directory and copy that script which you can also get from [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/docker_run.sh).
You must have the basic configuration file copied in the directory. This file must be called `ucentralgw.properties`. You can bring your own or
copy it from [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/ucentralgw.properties). Please look at [this](#certificates-with-docker) to have the right
certificates. You need to make sure that the names match the content of the `ucentralgw.properties`
You must have the basic configuration file copied in the directory. This file must be called `owgw.properties`. You can bring your own or
copy it from [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/owgw.properties). Please look at [this](#certificates-with-docker) to have the right
certificates. You need to make sure that the names match the content of the `owgw.properties`
file. Once all this is done, you can simply run `docker_run.sh`.
#### Docker installation directory layout
@@ -472,15 +472,15 @@ Run-time root
----- certs (same as above)
+---- logs (dir)
+---- uploads (dir)
+---- ucentralgw.properties (file)
+---- owgw.properties (file)
```
#### `ucentralgw.properties` for Docker
#### `owgw.properties` for Docker
If you use the pre-made configuration file, and you follow the directory layout, the only line you must change
is the following line:
```asm
ucentral.fileuploader.host.0.name = 192.168.1.176
openwifi.fileuploader.host.0.name = 192.168.1.176
```
This line should reflect the IP of your gateway or its FQDN. You must make sure that this name or IP is accessible
@@ -491,8 +491,8 @@ Please refer to the `certs` directory from the sections above.
#### Configuration with Docker
The configuration for this service is kept in a properties file. Currently, this configuration file must be kept in the
current directory of uCentral or one level up. This file is called `ucentralgw.properties` and you can see the latest version
[here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/ucentralgw.properties). The file will be loaded from
current directory of uCentral or one level up. This file is called `owgw.properties` and you can see the latest version
[here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/owgw.properties). The file will be loaded from
the directory set by the environment variable `UCENTRALGW_CONFIG`. To use environment variables in the configuration,
you must use `$<varname>`. The path for the logs for the service must exist prior to starting the
service. The path is defined under `logging.channels.c2.path`. Only `path names` support the use of
@@ -502,34 +502,34 @@ environment variables. Here is a sample configuration:
The communication protocol between the device and the controller is detailed in this [document](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/PROTOCOL.md).
## OpenAPI
The service supports an OpenAPI REST based interface for management. You can find the [definition here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/openapi/ucentral/ucentral.yaml).
The service supports an OpenAPI REST based interface for management. You can find the [definition here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/openapi/ucentral/owgw.yaml).
And here is [how to use it](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/OPENAPI.md)
## Using the API
In the `test_scripts` directory, you will find a series of scripts that will show you how to use the API
with [curl](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/TEST_CURL.md)
with [curl](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/CLI.md)
or [python](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/TEST_PYTHON.md).
More scripts will be added in the future.
## Firewall Considerations
- The protocol uses TCP port 15002 between the devices and the gateway. This port must be opened.
- Devices use the TCP port 16003 to upload files. This port is configurable in the `ucentralgw.properties` file. Look for `ucentral.fileuploader.host.0.port`.
- The RESTAPI is accessed through TCP port 16002 by default. This port is configurable in the `ucentralgw.properties` file. Look for the entry `ucentral.restapi.host.0.port`.
- Devices use the TCP port 16003 to upload files. This port is configurable in the `owgw.properties` file. Look for `openwifi.fileuploader.host.0.port`.
- The RESTAPI is accessed through TCP port 16002 by default. This port is configurable in the `owgw.properties` file. Look for the entry `openwifi.restapi.host.0.port`.
## Kafka integration
So what about Kafka? Well, the gateway has basic integration with Kafka. It is turned off by default, to turn it on, in the configuration:
```asm
ucentral.kafka.enable = false
ucentral.kafka.brokerlist = 127.0.0.1:9092
ucentral.kafka.commit = false
ucentral.kafka.queue.buffering.max.ms = 50
openwifi.kafka.enable = false
openwifi.kafka.brokerlist = 127.0.0.1:9092
openwifi.kafka.commit = false
openwifi.kafka.queue.buffering.max.ms = 50
```
#### `ucentral.kafka.enable`
#### `openwifi.kafka.enable`
Kind of obvious but hey, set `true` or `false`. Default is `false`
#### `ucentral.kafka.brokerlist`
#### `openwifi.kafka.brokerlist`
This is a comma separator list of the brokers in your `kafka` deployment.
#### Kafka topics

2
build
View File

@@ -1 +1 @@
46
44

View File

@@ -1,11 +1,71 @@
#!/bin/sh
set -e
if [ "$1" = '/ucentral/ucentralgw' -a "$(id -u)" = '0' ]; then
if [ "$SELFSIGNED_CERTS" = 'true' ]; then
update-ca-certificates
fi
if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWGW_CONFIG"/owgw.properties ]]; then
WEBSOCKET_HOST_ROOTCA=${WEBSOCKET_HOST_ROOTCA:-"\$OWGW_ROOT/certs/root.pem"} \
WEBSOCKET_HOST_ISSUER=${WEBSOCKET_HOST_ISSUER:-"\$OWGW_ROOT/certs/issuer.pem"} \
WEBSOCKET_HOST_CERT=${WEBSOCKET_HOST_CERT:-"\$OWGW_ROOT/certs/websocket-cert.pem"} \
WEBSOCKET_HOST_KEY=${WEBSOCKET_HOST_KEY:-"\$OWGW_ROOT/certs/websocket-key.pem"} \
WEBSOCKET_HOST_CLIENTCAS=${WEBSOCKET_HOST_CLIENTCAS:-"\$OWGW_ROOT/certs/clientcas.pem"} \
WEBSOCKET_HOST_CAS=${WEBSOCKET_HOST_CAS:-"\$OWGW_ROOT/certs/cas"} \
WEBSOCKET_HOST_PORT=${WEBSOCKET_HOST_PORT:-"15002"} \
WEBSOCKET_HOST_KEY_PASSWORD=${WEBSOCKET_HOST_KEY_PASSWORD:-"mypassword"} \
RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWGW_ROOT/certs/restapi-ca.pem"} \
RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16002"} \
RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWGW_ROOT/certs/restapi-cert.pem"} \
RESTAPI_HOST_KEY=${RESTAPI_HOST_KEY:-"\$OWGW_ROOT/certs/restapi-key.pem"} \
RESTAPI_HOST_KEY_PASSWORD=${RESTAPI_HOST_KEY_PASSWORD:-"mypassword"} \
INTERNAL_RESTAPI_HOST_ROOTCA=${INTERNAL_RESTAPI_HOST_ROOTCA:-"\$OWGW_ROOT/certs/restapi-ca.pem"} \
INTERNAL_RESTAPI_HOST_PORT=${INTERNAL_RESTAPI_HOST_PORT:-"17002"} \
INTERNAL_RESTAPI_HOST_CERT=${INTERNAL_RESTAPI_HOST_CERT:-"\$OWGW_ROOT/certs/restapi-cert.pem"} \
INTERNAL_RESTAPI_HOST_KEY=${INTERNAL_RESTAPI_HOST_KEY:-"\$OWGW_ROOT/certs/restapi-key.pem"} \
INTERNAL_RESTAPI_HOST_KEY_PASSWORD=${INTERNAL_RESTAPI_HOST_KEY_PASSWORD:-"mypassword"} \
FILEUPLOADER_HOST_ROOTCA=${FILEUPLOADER_HOST_ROOTCA:-"\$OWGW_ROOT/certs/restapi-ca.pem"} \
FILEUPLOADER_HOST_NAME=${FILEUPLOADER_HOST_NAME:-"localhost"} \
FILEUPLOADER_HOST_PORT=${FILEUPLOADER_HOST_PORT:-"16003"} \
FILEUPLOADER_HOST_CERT=${FILEUPLOADER_HOST_CERT:-"\$OWGW_ROOT/certs/restapi-cert.pem"} \
FILEUPLOADER_HOST_KEY=${FILEUPLOADER_HOST_KEY:-"\$OWGW_ROOT/certs/restapi-key.pem"} \
FILEUPLOADER_HOST_KEY_PASSWORD=${FILEUPLOADER_HOST_KEY_PASSWORD:-"mypassword"} \
FILEUPLOADER_PATH=${FILEUPLOADER_PATH:-"\$OWGW_ROOT/uploads"} \
FILEUPLOADER_URI=${FILEUPLOADER_URI:-"https://localhost:16003"} \
SERVICE_KEY=${SERVICE_KEY:-"\$OWGW_ROOT/certs/restapi-key.pem"} \
SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \
SYSTEM_DATA=${SYSTEM_DATA:-"\$OWGW_ROOT/data"} \
SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17002"} \
SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16002"} \
SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \
SIMULATORID=${SIMULATORID:-""} \
RTTY_ENABLED=${RTTY_ENABLED:-"false"} \
RTTY_SERVER=${RTTY_SERVER:-"localhost"} \
RTTY_PORT=${RTTY_PORT:-"5912"} \
RTTY_TOKEN=${RTTY_TOKEN:-"96181c567b4d0d98c50f127230068fa8"} \
RTTY_TIMEOUT=${RTTY_TIMEOUT:-"60"} \
RTTY_VIEWPORT=${RTTY_VIEWPORT:-"5913"} \
KAFKA_ENABLE=${KAFKA_ENABLE:-"true"} \
KAFKA_BROKERLIST=${KAFKA_BROKERLIST:-"localhost:9092"} \
STORAGE_TYPE=${STORAGE_TYPE:-"sqlite"} \
STORAGE_TYPE_POSTGRESQL_HOST=${STORAGE_TYPE_POSTGRESQL_HOST:-"localhost"} \
STORAGE_TYPE_POSTGRESQL_USERNAME=${STORAGE_TYPE_POSTGRESQL_USERNAME:-"owgw"} \
STORAGE_TYPE_POSTGRESQL_PASSWORD=${STORAGE_TYPE_POSTGRESQL_PASSWORD:-"owgw"} \
STORAGE_TYPE_POSTGRESQL_DATABASE=${STORAGE_TYPE_POSTGRESQL_DATABASE:-"owgw"} \
STORAGE_TYPE_POSTGRESQL_PORT=${STORAGE_TYPE_POSTGRESQL_PORT:-"5432"} \
STORAGE_TYPE_MYSQL_HOST=${STORAGE_TYPE_MYSQL_HOST:-"localhost"} \
STORAGE_TYPE_MYSQL_USERNAME=${STORAGE_TYPE_MYSQL_USERNAME:-"owgw"} \
STORAGE_TYPE_MYSQL_PASSWORD=${STORAGE_TYPE_MYSQL_PASSWORD:-"owgw"} \
STORAGE_TYPE_MYSQL_DATABASE=${STORAGE_TYPE_MYSQL_DATABASE:-"owgw"} \
STORAGE_TYPE_MYSQL_PORT=${STORAGE_TYPE_MYSQL_PORT:-"3306"} \
envsubst < /owgw.properties.tmpl > $OWGW_CONFIG/owgw.properties
fi
if [ "$1" = '/openwifi/owgw' -a "$(id -u)" = '0' ]; then
if [ "$RUN_CHOWN" = 'true' ]; then
chown -R "$UCENTRALGW_USER": "$UCENTRALGW_ROOT" "$UCENTRALGW_CONFIG"
chown -R "$OWGW_USER": "$OWGW_ROOT" "$OWGW_CONFIG"
fi
exec su-exec "$UCENTRALGW_USER" "$@"
exec su-exec "$OWGW_USER" "$@"
fi
exec "$@"

View File

@@ -26,7 +26,7 @@ then
exit 1
fi
if [[ ! -f ucentralgw.properties ]]
if [[ ! -f owgw.properties ]]
then
echo "Configuration file ucentral.properties is missing in the current directory"
exit 2

View File

@@ -1,12 +0,0 @@
dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 10.9.2
- name: mysql
repository: https://charts.bitnami.com/bitnami
version: 8.8.3
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 9.4.2
digest: sha256:1fdae7cbea906e41dccd8618ff9e2c68d0c684724ae27c79a12bb6089968df5c
generated: "2021-08-17T12:18:40.341427893+03:00"

View File

@@ -1,18 +1,18 @@
apiVersion: v2
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: ucentralgw
name: owgw
version: 0.1.0
dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
version: 10.9.2
condition: postgresql.enabled
- name: mysql
repository: https://charts.bitnami.com/bitnami
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
version: 8.8.3
condition: mysql.enabled
- name: mariadb
repository: https://charts.bitnami.com/bitnami
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
version: 9.4.2
condition: mariadb.enabled

View File

@@ -1,6 +1,6 @@
# ucentralgw
# owgw
This Helm chart helps to deploy uCentralGW to the Kubernetes clusters. It is mainly used in [assembly chart](https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart) as uCentralGW requires other services as dependencies that are considered in that Helm chart. This chart is purposed to define deployment logic close to the application code itself and define default values that could be overriden during deployment.
This Helm chart helps to deploy OpenWIFI Gateway (further on refered as __Gateway__) to the Kubernetes clusters. It is mainly used in [assembly chart](https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart) as Gateway requires other services as dependencies that are considered in that Helm chart. This chart is purposed to define deployment logic close to the application code itself and define default values that could be overriden during deployment.
## TL;DR;
@@ -11,7 +11,7 @@ $ helm install .
## Introduction
This chart bootstraps an ucentralgw on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
This chart bootstraps the Gateway on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
## Installing the Chart
@@ -20,10 +20,10 @@ Currently this chart is not assembled in charts archives, so [helm-git](https://
To install the chart with the release name `my-release`:
```bash
$ helm install --name my-release git+https://github.com/Telecominfraproject/wlan-cloud-ucentralgw@helm?ref=master
$ helm install --name my-release git+https://github.com/Telecominfraproject/wlan-cloud-ucentralgw@helm/owgw-0.1.0.tgz?ref=master
```
The command deploys ucentralgw on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.
The command deploys the Gateway on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.
> **Tip**: List all releases using `helm list`
@@ -47,40 +47,40 @@ The following table lists the configurable parameters of the chart and their def
| strategyType | string | Application deployment strategy | `'Recreate'` |
| nameOverride | string | Override to be used for application deployment | |
| fullnameOverride | string | Override to be used for application deployment (has priority over nameOverride) | |
| images.ucentralgw.repository | string | Docker image repository | |
| images.ucentralgw.tag | string | Docker image tag | `'master'` |
| images.ucentralgw.pullPolicy | string | Docker image pull policy | `'Always'` |
| services.ucentralgw.type | string | uCentralGW service type | `'LoadBalancer'` |
| services.ucentralgw.ports.websocket.servicePort | number | Websocket endpoint port to be exposed on service | `15002` |
| services.ucentralgw.ports.websocket.targetPort | number | Websocket endpoint port to be targeted by service | `15002` |
| services.ucentralgw.ports.websocket.protocol | string | Websocket endpoint protocol | `'TCP'` |
| services.ucentralgw.ports.restapi.servicePort | number | REST API endpoint port to be exposed on service | `16002` |
| services.ucentralgw.ports.restapi.targetPort | number | REST API endpoint port to be targeted by service | `16002` |
| services.ucentralgw.ports.restapi.protocol | string | REST API endpoint protocol | `'TCP'` |
| services.ucentralgw.ports.restapiinternal.servicePort | string | Internal REST API endpoint port to be exposed on service | `17002` |
| services.ucentralgw.ports.restapiinternal.targetPort | number | Internal REST API endpoint port to be targeted by service | `17002` |
| services.ucentralgw.ports.restapiinternal.protocol | string | Internal REST API endpoint protocol | `'TCP'` |
| services.ucentralgw.ports.fileuploader.servicePort | string | Fileuploader endpoint port to be exposed on service | `16003` |
| services.ucentralgw.ports.fileuploader.targetPort | number | Fileuploader endpoint port to be targeted by service | `16003` |
| services.ucentralgw.ports.fileuploader.protocol | string | Fileuploader endpoint protocol | `'TCP'` |
| checks.ucentralgw.liveness.httpGet.path | string | Liveness check path to be used | `'/'` |
| checks.ucentralgw.liveness.httpGet.port | number | Liveness check port to be used (should be pointint to ALB endpoint) | `16102` |
| checks.ucentralgw.readiness.httpGet.path | string | Readiness check path to be used | `'/'` |
| checks.ucentralgw.readiness.httpGet.port | number | Readiness check port to be used (should be pointint to ALB endpoint) | `16102` |
| images.owgw.repository | string | Docker image repository | |
| images.owgw.tag | string | Docker image tag | `'master'` |
| images.owgw.pullPolicy | string | Docker image pull policy | `'Always'` |
| services.owgw.type | string | OpenWIFI Gateway service type | `'LoadBalancer'` |
| services.owgw.ports.websocket.servicePort | number | Websocket endpoint port to be exposed on service | `15002` |
| services.owgw.ports.websocket.targetPort | number | Websocket endpoint port to be targeted by service | `15002` |
| services.owgw.ports.websocket.protocol | string | Websocket endpoint protocol | `'TCP'` |
| services.owgw.ports.restapi.servicePort | number | REST API endpoint port to be exposed on service | `16002` |
| services.owgw.ports.restapi.targetPort | number | REST API endpoint port to be targeted by service | `16002` |
| services.owgw.ports.restapi.protocol | string | REST API endpoint protocol | `'TCP'` |
| services.owgw.ports.restapiinternal.servicePort | string | Internal REST API endpoint port to be exposed on service | `17002` |
| services.owgw.ports.restapiinternal.targetPort | number | Internal REST API endpoint port to be targeted by service | `17002` |
| services.owgw.ports.restapiinternal.protocol | string | Internal REST API endpoint protocol | `'TCP'` |
| services.owgw.ports.fileuploader.servicePort | string | Fileuploader endpoint port to be exposed on service | `16003` |
| services.owgw.ports.fileuploader.targetPort | number | Fileuploader endpoint port to be targeted by service | `16003` |
| services.owgw.ports.fileuploader.protocol | string | Fileuploader endpoint protocol | `'TCP'` |
| checks.owgw.liveness.httpGet.path | string | Liveness check path to be used | `'/'` |
| checks.owgw.liveness.httpGet.port | number | Liveness check port to be used (should be pointint to ALB endpoint) | `16102` |
| checks.owgw.readiness.httpGet.path | string | Readiness check path to be used | `'/'` |
| checks.owgw.readiness.httpGet.port | number | Readiness check port to be used (should be pointint to ALB endpoint) | `16102` |
| ingresses.restapi.enabled | boolean | Defines if REST API endpoint should be exposed via Ingress controller | `False` |
| ingresses.restapi.hosts | array | List of hosts for exposed REST API | |
| ingresses.restapi.paths | array | List of paths to be exposed for REST API | |
| ingresses.fileuploader.enabled | boolean | Defines if Fileuploader endpoint should be exposed via Ingress controller | `False` |
| ingresses.fileuploader.hosts | array | List of hosts for exposed Fileuploader | |
| ingresses.fileuploader.paths | array | List of paths for exposed Fileuploader | |
| volumes.ucentralgw | array | Defines list of volumes to be attached to uCentralGW | |
| persistence.enabled | boolean | Defines if uCentralGW requires Persistent Volume (required for permanent files storage and SQLite DB if enabled) | `True` |
| volumes.owgw | array | Defines list of volumes to be attached to the Gateway | |
| persistence.enabled | boolean | Defines if the Gateway requires Persistent Volume (required for permanent files storage and SQLite DB if enabled) | `True` |
| persistence.accessModes | array | Defines PV access modes | |
| persistence.size | string | Defines PV size | `'10Gi'` |
| public_env_variables | hash | Defines list of environment variables to be passed to uCentralGW | |
| configProperties | hash | Configuration properties that should be passed to the application in `ucentralgw.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | |
| certs | hash | Defines files (keys and certificates) that should be passed to uCentralGW (PEM format is adviced to be used) (see `volumes.ucentralgw` on where it is mounted) | |
| certsCAs | hash | Defines files with CAs that should be passed to uCentralGW (see `volumes.ucentralgw` on where it is mounted) | |
| public_env_variables | hash | Defines list of environment variables to be passed to the Gateway | |
| configProperties | hash | Configuration properties that should be passed to the application in `owgw.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | |
| certs | hash | Defines files (keys and certificates) that should be passed to the Gateway (PEM format is adviced to be used) (see `volumes.owgw` on where it is mounted) | |
| certsCAs | hash | Defines files with CAs that should be passed to the Gateway (see `volumes.owgw` on where it is mounted) | |
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
@@ -100,5 +100,3 @@ $ helm install --name my-release -f values.yaml .
```
> **Tip**: You can use the default [values.yaml](values.yaml) as a base for customization.

View File

@@ -1,4 +1,4 @@
{{- define "ucentralgw.config" -}}
{{- define "owgw.config" -}}
{{- range $key, $value := .Values.configProperties }}
{{ $key }} = {{ $value }}
{{- end }}

View File

@@ -2,7 +2,7 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "ucentralgw.name" -}}
{{- define "owgw.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
@@ -11,7 +11,7 @@ Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "ucentralgw.fullname" -}}
{{- define "owgw.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
@@ -27,6 +27,6 @@ If release name contains chart name it will be used as a full name.
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "ucentralgw.chart" -}}
{{- define "owgw.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@@ -3,10 +3,10 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "ucentralgw.fullname" . }}
name: {{ include "owgw.fullname" . }}
labels:
app.kubernetes.io/name: {{ include "ucentralgw.name" . }}
helm.sh/chart: {{ include "ucentralgw.chart" . }}
app.kubernetes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
@@ -15,28 +15,34 @@ spec:
type: {{ .Values.strategyType }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "ucentralgw.name" . }}
app.kubernetes.io/name: {{ include "owgw.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- with .Values.services.ucentralgw.labels }}
{{- with .Values.services.owgw.labels }}
{{- toYaml . | nindent 6 }}
{{- end }}
template:
metadata:
annotations:
checksum/config: {{ include "ucentralgw.config" . | sha256sum }}
checksum/config: {{ include "owgw.config" . | sha256sum }}
{{- if .Values.podSecurityPolicy.enabled }}
kubernetes.io/psp: {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl
{{- end }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
app.kubernetes.io/name: {{ include "ucentralgw.name" . }}
app.kubernetes.io/name: {{ include "owgw.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- with .Values.services.ucentralgw.labels }}
{{- with .Values.services.owgw.labels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
containers:
- name: ucentralgw
image: "{{ .Values.images.ucentralgw.repository }}:{{ .Values.images.ucentralgw.tag }}"
imagePullPolicy: {{ .Values.images.ucentralgw.pullPolicy }}
- name: owgw
image: "{{ .Values.images.owgw.repository }}:{{ .Values.images.owgw.tag }}"
imagePullPolicy: {{ .Values.images.owgw.pullPolicy }}
env:
- name: KUBERNETES_DEPLOYED
@@ -49,19 +55,19 @@ spec:
- name: {{ $key }}
valueFrom:
secretKeyRef:
name: {{ include "ucentralgw.fullname" $root }}-env
name: {{ include "owgw.fullname" $root }}-env
key: {{ $key }}
{{- end }}
ports:
{{- range $port, $portValue := .Values.services.ucentralgw.ports }}
{{- range $port, $portValue := .Values.services.owgw.ports }}
- name: {{ $port }}
containerPort: {{ $portValue.targetPort }}
protocol: {{ $portValue.protocol }}
{{- end }}
volumeMounts:
{{- range .Values.volumes.ucentralgw }}
{{- range .Values.volumes.owgw }}
- name: {{ .name }}
mountPath: {{ .mountPath }}
{{- if .subPath }}
@@ -69,13 +75,13 @@ spec:
{{- end }}
{{- end }}
{{- if .Values.checks.ucentralgw.liveness }}
{{- if .Values.checks.owgw.liveness }}
livenessProbe:
{{- toYaml .Values.checks.ucentralgw.liveness | nindent 12 }}
{{- toYaml .Values.checks.owgw.liveness | nindent 12 }}
{{- end }}
{{- if .Values.checks.ucentralgw.readiness }}
{{- if .Values.checks.owgw.readiness }}
readinessProbe:
{{- toYaml .Values.checks.ucentralgw.readiness | nindent 12 }}
{{- toYaml .Values.checks.owgw.readiness | nindent 12 }}
{{- end }}
{{- with .Values.resources }}
@@ -91,7 +97,7 @@ spec:
imagePullSecrets:
{{- range $image, $imageValue := .Values.images }}
{{- if $imageValue.regcred }}
- name: {{ include "ucentralgw.fullname" $root }}-{{ $image }}-regcred
- name: {{ include "owgw.fullname" $root }}-{{ $image }}-regcred
{{- end }}
{{- end }}

View File

@@ -5,10 +5,10 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ include "ucentralgw.fullname" $root }}-{{ $ingress }}
name: {{ include "owgw.fullname" $root }}-{{ $ingress }}
labels:
app.kubernetes.io/name: {{ include "ucentralgw.name" $root }}
helm.sh/chart: {{ include "ucentralgw.chart" $root }}
app.kubernetes.io/name: {{ include "owgw.name" $root }}
helm.sh/chart: {{ include "owgw.chart" $root }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
app.kubernetes.io/managed-by: {{ $root.Release.Service }}
{{- with $ingressValue.annotations }}
@@ -37,7 +37,7 @@ spec:
{{- range $ingressValue.paths }}
- path: {{ .path }}
backend:
serviceName: {{ include "ucentralgw.fullname" $root }}-{{ .serviceName }}
serviceName: {{ include "owgw.fullname" $root }}-{{ .serviceName }}
servicePort: {{ .servicePort }}
{{- end }}
{{- end }}

28
helm/templates/psp.yaml Normal file
View File

@@ -0,0 +1,28 @@
{{- if .Values.podSecurityPolicy.enabled }}
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl
labels:
app.kubernetes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
allowedUnsafeSysctls:
{{- range $unsafeSysctl := .Values.securityContext.sysctls }}
- {{ $unsafeSysctl.name }}
{{- end }}
privileged: false
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
{{- end }}

View File

@@ -3,10 +3,10 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ template "ucentralgw.fullname" . }}-pvc
name: {{ template "owgw.fullname" . }}-pvc
labels:
app.kubernetes.io/name: {{ include "ucentralgw.name" . }}
helm.sh/chart: {{ include "ucentralgw.chart" . }}
app.kubernetes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- with .Values.persistence.annotations }}

16
helm/templates/role.yaml Normal file
View File

@@ -0,0 +1,16 @@
{{- if .Values.podSecurityPolicy.enabled }}
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl
rules:
- apiGroups:
- policy
resources:
- podsecuritypolicies
verbs:
- use
resourceNames:
- {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl
{{- end }}

View File

@@ -0,0 +1,15 @@
{{- if .Values.podSecurityPolicy.enabled }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl-to-default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl
subjects:
- kind: ServiceAccount
name: default
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@@ -2,11 +2,11 @@
apiVersion: v1
metadata:
labels:
app.kuberentes.io/name: {{ include "ucentralgw.name" . }}
helm.sh/chart: {{ include "ucentralgw.chart" . }}
app.kuberentes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "ucentralgw.fullname" . }}-certs-cas
name: {{ include "owgw.fullname" . }}-certs-cas
kind: Secret
type: Opaque
data:

View File

@@ -2,11 +2,11 @@
apiVersion: v1
metadata:
labels:
app.kuberentes.io/name: {{ include "ucentralgw.name" . }}
helm.sh/chart: {{ include "ucentralgw.chart" . }}
app.kuberentes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "ucentralgw.fullname" . }}-certs
name: {{ include "owgw.fullname" . }}-certs
kind: Secret
type: Opaque
data:

View File

@@ -2,12 +2,12 @@
apiVersion: v1
metadata:
labels:
app.kuberentes.io/name: {{ include "ucentralgw.name" . }}
helm.sh/chart: {{ include "ucentralgw.chart" . }}
app.kuberentes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "ucentralgw.fullname" . }}-config
name: {{ include "owgw.fullname" . }}-config
kind: Secret
type: Opaque
data:
ucentralgw.properties: {{ include "ucentralgw.config" . | b64enc }}
owgw.properties: {{ include "owgw.config" . | b64enc }}

View File

@@ -2,11 +2,11 @@
apiVersion: v1
metadata:
labels:
app.kuberentes.io/name: {{ include "ucentralgw.name" . }}
helm.sh/chart: {{ include "ucentralgw.chart" . }}
app.kuberentes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "ucentralgw.fullname" . }}-env
name: {{ include "owgw.fullname" . }}-env
kind: Secret
type: Opaque
data:

View File

@@ -10,11 +10,11 @@ kind: Secret
type: kubernetes.io/dockerconfigjson
metadata:
labels:
app.kuberentes.io/name: {{ include "ucentralgw.name" $root }}
helm.sh/chart: {{ include "ucentralgw.chart" $root }}
app.kuberentes.io/name: {{ include "owgw.name" $root }}
helm.sh/chart: {{ include "owgw.chart" $root }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
app.kubernetes.io/managed-by: {{ $root.Release.Service }}
name: {{ include "ucentralgw.fullname" $root }}-{{ $image }}-regcred
name: {{ include "owgw.fullname" $root }}-{{ $image }}-regcred
data:
.dockerconfigjson: {{ template "imagePullSecret" $imageValue.regcred }}
{{- end }}

View File

@@ -4,14 +4,14 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "ucentralgw.fullname" $root }}-{{ $service }}
name: {{ include "owgw.fullname" $root }}-{{ $service }}
{{- with $serviceValue.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
labels:
app.kubernetes.io/name: {{ include "ucentralgw.name" $root }}
helm.sh/chart: {{ include "ucentralgw.chart" $root }}
app.kubernetes.io/name: {{ include "owgw.name" $root }}
helm.sh/chart: {{ include "owgw.chart" $root }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
app.kubernetes.io/managed-by: {{ $root.Release.Service }}
@@ -39,7 +39,7 @@ spec:
{{- end }}
{{- end }}
selector:
app.kubernetes.io/name: {{ include "ucentralgw.name" $root }}
app.kubernetes.io/name: {{ include "owgw.name" $root }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
{{- with $serviceValue.labels }}
{{- toYaml . | nindent 4 }}

View File

@@ -6,9 +6,9 @@ nameOverride: ""
fullnameOverride: ""
images:
ucentralgw:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/ucentralgw
tag: master
owgw:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
tag: v2.4.1
pullPolicy: Always
# regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
@@ -16,7 +16,7 @@ images:
# password: password
services:
ucentralgw:
owgw:
type: LoadBalancer
ports:
websocket:
@@ -37,15 +37,16 @@ services:
protocol: TCP
checks:
ucentralgw:
owgw:
liveness:
httpGet:
path: /
port: 16102
readiness:
httpGet:
path: /
port: 16102
exec:
command:
- /readiness_check
failureThreshold: 1
ingresses:
restapi:
@@ -57,7 +58,7 @@ ingresses:
- restapi.chart-example.local
paths:
- path: /
serviceName: ucentralgw
serviceName: owgw
servicePort: restapi
fileuploader:
enabled: false
@@ -68,34 +69,34 @@ ingresses:
- fileuploader.chart-example.local
paths:
- path: /
serviceName: ucentralgw
serviceName: owgw
servicePort: fileuploader
volumes:
ucentralgw:
owgw:
- name: config
mountPath: /ucentralgw-data/ucentralgw.properties
subPath: ucentralgw.properties
mountPath: /owgw-data/owgw.properties
subPath: owgw.properties
# Template below will be rendered in template
volumeDefinition: |
secret:
secretName: {{ include "ucentralgw.fullname" . }}-config
secretName: {{ include "owgw.fullname" . }}-config
- name: certs
mountPath: /ucentralgw-data/certs
mountPath: /owgw-data/certs
volumeDefinition: |
secret:
secretName: {{ include "ucentralgw.fullname" . }}-certs
secretName: {{ include "owgw.fullname" . }}-certs
- name: certs-cas
mountPath: /ucentralgw-data/certs/cas
mountPath: /owgw-data/certs/cas
volumeDefinition: |
secret:
secretName: {{ include "ucentralgw.fullname" . }}-certs-cas
secretName: {{ include "owgw.fullname" . }}-certs-cas
# Change this if you want to use another volume type
- name: persist
mountPath: /ucentralgw-data/persist
mountPath: /owgw-data/persist
volumeDefinition: |
persistentVolumeClaim:
claimName: {{ template "ucentralgw.fullname" . }}-pvc
claimName: {{ template "owgw.fullname" . }}-pvc
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
@@ -111,6 +112,17 @@ resources: {}
securityContext:
fsGroup: 101
# Usage of unsafe sysctls requires multiple things:
# - allow these unsafe sysctls on kubelet level (by adding --allowed-unsafe-sysctls flag)
# - enabling addition of PodSecurityContext setting podSecurityPolicy.enabled to "true" below
# - uncommenting parameters below
#sysctls:
#- name: net.ipv4.tcp_keepalive_intvl
# value: "5"
#- name: net.ipv4.tcp_keepalive_probes
# value: "2"
#- name: net.ipv4.tcp_keepalive_time
# value: "45"
nodeSelector: {}
@@ -118,6 +130,11 @@ tolerations: []
affinity: {}
podAnnotations: {}
podSecurityPolicy:
enabled: false
persistence:
enabled: true
# storageClassName: "-"
@@ -128,63 +145,71 @@ persistence:
# Application
public_env_variables:
UCENTRALGW_ROOT: /ucentralgw-data
UCENTRALGW_CONFIG: /ucentralgw-data
OWGW_ROOT: /owgw-data
OWGW_CONFIG: /owgw-data
# Environment variables required for the readiness checks using script
FLAGS: "-s --connect-timeout 3"
# NOTE in order for readiness check to use system info you need to set READINESS_METHOD to "systeminfo" and set OWSEC to the OWSEC's REST API endpoint
#READINESS_METHOD: systeminfo
#OWSEC: gw-qa01.cicd.lab.wlan.tip.build:16001
secret_env_variables: {}
secret_env_variables:
# NOTE in order for readiness check to use system info method you need to override these values to the real OWSEC credentials
OWSEC_USERNAME: tip@ucentral.com
OWSEC_PASSWORD: openwifi
configProperties:
# -> Public part
# Websocket
ucentral.websocket.host.0.backlog: 500
ucentral.websocket.host.0.rootca: $UCENTRALGW_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer: $UCENTRALGW_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert: $UCENTRALGW_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key: $UCENTRALGW_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas: $UCENTRALGW_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas: $UCENTRALGW_ROOT/certs/cas
ucentral.websocket.host.0.rootca: $OWGW_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer: $OWGW_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert: $OWGW_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key: $OWGW_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas: $OWGW_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas: $OWGW_ROOT/certs/cas
ucentral.websocket.host.0.address: "*"
ucentral.websocket.host.0.port: 15002
ucentral.websocket.host.0.security: strict
ucentral.websocket.maxreactors: 20
# REST API
ucentral.restapi.host.0.backlog: 100
ucentral.restapi.host.0.security: relaxed
ucentral.restapi.host.0.rootca: $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.restapi.host.0.address: "*"
ucentral.restapi.host.0.port: 16002
ucentral.restapi.host.0.cert: $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.restapi.host.0.key: $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.internal.restapi.host.0.backlog: 100
ucentral.internal.restapi.host.0.security: relaxed
ucentral.internal.restapi.host.0.rootca: $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.internal.restapi.host.0.address: "*"
ucentral.internal.restapi.host.0.port: 17002
ucentral.internal.restapi.host.0.cert: $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.internal.restapi.host.0.key: $UCENTRALGW_ROOT/certs/restapi-key.pem
openwifi.restapi.host.0.backlog: 100
openwifi.restapi.host.0.security: relaxed
openwifi.restapi.host.0.rootca: $OWGW_ROOT/certs/restapi-ca.pem
openwifi.restapi.host.0.address: "*"
openwifi.restapi.host.0.port: 16002
openwifi.restapi.host.0.cert: $OWGW_ROOT/certs/restapi-cert.pem
openwifi.restapi.host.0.key: $OWGW_ROOT/certs/restapi-key.pem
openwifi.internal.restapi.host.0.backlog: 100
openwifi.internal.restapi.host.0.security: relaxed
openwifi.internal.restapi.host.0.rootca: $OWGW_ROOT/certs/restapi-ca.pem
openwifi.internal.restapi.host.0.address: "*"
openwifi.internal.restapi.host.0.port: 17002
openwifi.internal.restapi.host.0.cert: $OWGW_ROOT/certs/restapi-cert.pem
openwifi.internal.restapi.host.0.key: $OWGW_ROOT/certs/restapi-key.pem
# File uploader
ucentral.fileuploader.host.0.backlog: 100
ucentral.fileuploader.host.0.rootca: $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.fileuploader.host.0.security: relaxed
ucentral.fileuploader.host.0.address: "*"
ucentral.fileuploader.host.0.name: localhost
ucentral.fileuploader.host.0.port: 16003
ucentral.fileuploader.host.0.cert: $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.fileuploader.host.0.key: $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.fileuploader.path: $UCENTRALGW_ROOT/persist/uploads
ucentral.fileuploader.maxsize: 10000
openwifi.fileuploader.host.0.backlog: 100
openwifi.fileuploader.host.0.rootca: $OWGW_ROOT/certs/restapi-ca.pem
openwifi.fileuploader.host.0.security: relaxed
openwifi.fileuploader.host.0.address: "*"
openwifi.fileuploader.host.0.name: localhost
openwifi.fileuploader.host.0.port: 16003
openwifi.fileuploader.host.0.cert: $OWGW_ROOT/certs/restapi-cert.pem
openwifi.fileuploader.host.0.key: $OWGW_ROOT/certs/restapi-key.pem
openwifi.fileuploader.path: $OWGW_ROOT/uploads
openwifi.fileuploader.maxsize: 10000
# Auto provisioning
ucentral.autoprovisioning: "true"
ucentral.devicetypes.0: AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
ucentral.devicetypes.1: SWITCH:edgecore_ecs4100-12ph
ucentral.devicetypes.2: IOT:esp32
openwifi.autoprovisioning: "true"
openwifi.devicetypes.0: AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
openwifi.devicetypes.1: SWITCH:edgecore_ecs4100-12ph
openwifi.devicetypes.2: IOT:esp32
oui.download.uri: https://linuxnet.ca/ieee/oui.txt
firmware.autoupdate.policy.default: auto
# Callback
ucentral.callback.enable: "false"
ucentral.callback.0.local: localhost:16001
ucentral.callback.0.remote: localhost:15055
ucentral.callback.0.topics: ucentralfws
openwifi.callback.enable: "false"
openwifi.callback.0.local: localhost:16001
openwifi.callback.0.remote: localhost:15055
openwifi.callback.0.topics: owfws
# rtty
rtty.enabled: "true"
rtty.server: localhost
@@ -195,12 +220,12 @@ configProperties:
alb.enable: "true"
alb.port: 16102
# Kafka
ucentral.kafka.enable: "false"
ucentral.kafka.group.id: gateway
ucentral.kafka.client.id: gateway1
ucentral.kafka.brokerlist: localhost:9092
ucentral.kafka.auto.commit: false
ucentral.kafka.queue.buffering.max.ms: 50
openwifi.kafka.enable: "false"
openwifi.kafka.group.id: gateway
openwifi.kafka.client.id: gateway1
openwifi.kafka.brokerlist: localhost:9092
openwifi.kafka.auto.commit: false
openwifi.kafka.queue.buffering.max.ms: 50
# Storage
storage.type: sqlite # (sqlite|postgresql|mysql|odbc)
## SQLite
@@ -211,23 +236,23 @@ configProperties:
storage.type.postgresql.maxsessions: 64
storage.type.postgresql.idletime: 60
storage.type.postgresql.host: localhost
storage.type.postgresql.database: ucentral
storage.type.postgresql.database: owgw
storage.type.postgresql.port: 5432
storage.type.postgresql.connectiontimeout: 60
## MySQL
storage.type.mysql.maxsessions: 64
storage.type.mysql.idletime: 60
storage.type.mysql.host: localhost
storage.type.mysql.database: ucentral
storage.type.mysql.database: owgw
storage.type.mysql.port: 3306
storage.type.mysql.connectiontimeout: 60
# System
ucentral.service.key: $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.system.data: $UCENTRALGW_ROOT/persist
ucentral.system.debug: "true"
ucentral.system.uri.private: https://localhost:17002
ucentral.system.uri.public: https://localhost:16002
ucentral.system.commandchannel: /tmp/app_ucentralgw
openwifi.service.key: $OWGW_ROOT/certs/restapi-key.pem
openwifi.system.data: $OWGW_ROOT/persist
openwifi.system.debug: "true"
openwifi.system.uri.private: https://localhost:17002
openwifi.system.uri.public: https://localhost:16002
openwifi.system.commandchannel: /tmp/app_owgw
# Logging
logging.formatters.f1.class: PatternFormatter
logging.formatters.f1.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t"
@@ -235,7 +260,7 @@ configProperties:
logging.channels.c1.class: ConsoleChannel
logging.channels.c1.formatter: f1
logging.channels.c2.class: FileChannel
logging.channels.c2.path: /tmp/log_ucentralgw
logging.channels.c2.path: /tmp/log_owgw
logging.channels.c2.formatter.class: PatternFormatter
logging.channels.c2.formatter.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t"
logging.channels.c2.rotation: "20 M"
@@ -250,14 +275,14 @@ configProperties:
# Websocket
ucentral.websocket.host.0.key.password: mypassword
# REST API
ucentral.restapi.host.0.key.password: mypassword
ucentral.internal.restapi.host.0.key.password: mypassword
openwifi.restapi.host.0.key.password: mypassword
openwifi.internal.restapi.host.0.key.password: mypassword
# File uploader
ucentral.fileuploader.host.0.key.password: mypassword
openwifi.fileuploader.host.0.key.password: mypassword
# Callback
ucentral.callback.id: qblat6dfDHxQAZ6yMe6MrypBpgRDhQrhUtTOovOXAKAWU8qOvjjKKiUai4t9hGjA
ucentral.callback.0.localkey: t2dEOc88OIxVDb94mw7SLcLocgnCzZzzFoQ4JJv3OCU9UO6Ou5ds5Dh4CfBnHgrk
ucentral.callback.0.remotekey: t2dEOc88OIxVDb94mw7SLcLocgnCzZzzFoQ4JJv3OCU9UO6Ou5ds5Dh4CfBnHgrk
openwifi.callback.id: qblat6dfDHxQAZ6yMe6MrypBpgRDhQrhUtTOovOXAKAWU8qOvjjKKiUai4t9hGjA
openwifi.callback.0.localkey: t2dEOc88OIxVDb94mw7SLcLocgnCzZzzFoQ4JJv3OCU9UO6Ou5ds5Dh4CfBnHgrk
openwifi.callback.0.remotekey: t2dEOc88OIxVDb94mw7SLcLocgnCzZzzFoQ4JJv3OCU9UO6Ou5ds5Dh4CfBnHgrk
# rtty
rtty.token: 96181c567b4d0d98c50f127230068fa8
# Storage
@@ -438,10 +463,10 @@ postgresql:
repository: bitnami/postgresql
tag: 11.13.0-debian-10-r0
postgresqlPostgresPassword: ""
postgresqlUsername: postgres
postgresqlPassword: ""
postgresqlDatabase: ""
postgresqlPostgresPassword: "rootPassword"
postgresqlUsername: stephb
postgresqlPassword: snoopy99
postgresqlDatabase: owgw
persistence:
enabled: true
@@ -458,10 +483,10 @@ mysql:
tag: 8.0.26-debian-10-r10
auth:
rootPassword: ""
database: my_database
username: ""
password: ""
rootPassword: rootPassword
database: owgw
username: stephb
password: snoopy99
primary:
persistence:
@@ -479,10 +504,10 @@ mariadb:
tag: 10.5.12-debian-10-r0
auth:
rootPassword: ""
database: my_database
username: ""
password: ""
rootPassword: rootPassword
database: owgw
username: stephb
password: snoopy99
primary:
persistence:

View File

@@ -51,6 +51,16 @@ components:
properties:
ErrorCode:
type: integer
enum:
- 0 # Success
- 1 # PASSWORD_CHANGE_REQUIRED,
- 2 # INVALID_CREDENTIALS,
- 3 # PASSWORD_ALREADY_USED,
- 4 # USERNAME_PENDING_VERIFICATION,
- 5 # PASSWORD_INVALID,
- 6 # INTERNAL_ERROR,
- 7 # ACCESS_DENIED,
- 8 # INVALID_TOKEN
ErrorDetails:
type: string
ErrorDescription:
@@ -91,6 +101,9 @@ components:
location:
type: string
format: uuid
venue:
type: string
format: uuid
serialNumber:
type: string
deviceType:
@@ -631,6 +644,42 @@ components:
associations:
$ref: '#/components/schemas/TagIntPairList'
TelemetryStreamRequest:
type: object
properties:
serialNumber:
type: string
interval:
type: integer
example:
0 - means to stop streaming, values 1-120 in seconds.
types:
type: array
items:
type: string
enum:
- dhcp-snooping
- wire-frames
- state
uuid:
type: string
example:
only valid when terminating a stream
TelemetryStreamResponse:
type: object
properties:
serialNumber:
type: string
uuid:
type: string
format: uuid
uri:
type: string
format: uri
example:
wss://host.domain:port/endpoint
#########################################################################################
##
## These are endpoints that all services in the uCentral stack must provide
@@ -716,6 +765,107 @@ components:
note:
type: string
SystemInfoResults:
type: object
properties:
version:
type: string
uptime:
type: integer
format: integer64
start:
type: integer
format: integer64
os:
type: string
processors:
type: integer
hostname:
type: string
certificates:
type: array
items:
type: object
properties:
filename:
type: string
expires:
type: integer
format: int64
SystemCommandSetLogLevel:
type: object
properties:
command:
type: string
enum:
- setloglevel
subsystems:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
SystemCommandReload:
type: object
properties:
command:
type: string
enum:
- reload
subsystems:
type: array
items:
type: string
example: these are the SubSystems names retrieve with the GetSubSystemsNamesResult.
SystemCommandGetLogLevels:
type: object
properties:
command:
type: string
enum:
- getloglevels
SystemGetLogLevelsResult:
type: object
properties:
taglist:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
SystemCommandGetLogLevelNames:
type: object
properties:
command:
type: string
enum:
- getloglevelnames
SystemCommandGetSubsystemNames:
type: object
properties:
command:
type: string
enum:
- getsubsystemnames
SystemCommandGetLogLevelNamesResult:
type: object
properties:
list:
type: array
items:
type: string
SystemGetSubSystemNamesResult:
type: object
properties:
taglist:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
#########################################################################################
##
## End of uCentral system wide values
@@ -829,6 +979,22 @@ components:
password:
type: string
CapabilitiesModel:
type: object
properties:
deviceType:
type: string
capabilities:
type: string
CapabilitiesModelList:
type: object
properties:
devices:
type: array
items:
$ref: '#/components/schemas/CapabilitiesModel'
paths:
/devices:
get:
@@ -986,7 +1152,7 @@ paths:
get:
tags:
- Commands
summary: Returns a specific command
summary: Returns a specific command.
description: Returns a specific command
operationId: getACommandDetails
parameters:
@@ -1011,7 +1177,7 @@ paths:
delete:
tags:
- Commands
summary: Delete a specific command
summary: Delete a specific command.
description: Delete a specific command
operationId: deleteACommand
parameters:
@@ -1037,8 +1203,8 @@ paths:
get:
tags:
- Configurations
summary: Retrieve the lists of all default configurations
description: Retrieve the lists of all default configurations
summary: Retrieve the lists of all default configurations.
description: Retrieve the lists of all default configurations.
operationId: getDefaultConfigurations
responses:
@@ -1057,8 +1223,8 @@ paths:
get:
tags:
- Configurations
summary: Retrieve a default configuration
description: Retrieve a default configuration
summary: Retrieve a default configuration.
description: Retrieve a default configuration.
operationId: getDefaultConfiguration
parameters:
- in: path
@@ -1081,8 +1247,8 @@ paths:
post:
tags:
- Configurations
summary: Create a default configuration
description: Create a default configuration
summary: Create a default configuration.
description: Create a default configuration.
operationId: createDefaultConfiguration
parameters:
- in: path
@@ -1154,7 +1320,7 @@ paths:
get:
tags:
- Devices
summary: Retrieve information for a single device
summary: Retrieve information for a single device.
description: Retrieve all the inforamtion about a single device
operationId: getDeviceInformation
parameters:
@@ -1178,7 +1344,7 @@ paths:
post:
tags:
- Devices
summary: Creating a new device
summary: Create a new device.
operationId: createNewDevice
parameters:
- in: path
@@ -1186,6 +1352,11 @@ paths:
schema:
type: string
required: true
- in: query
name: validateOnly
schema:
type: boolean
required: false
requestBody:
description: Information used to create the new device
content:
@@ -1207,7 +1378,7 @@ paths:
put:
tags:
- Devices
summary: Updating a new device
summary: Update a device.
operationId: updateNewDevice
parameters:
- in: path
@@ -1236,7 +1407,7 @@ paths:
delete:
tags:
- Devices
summary: Deleting a single device
summary: Delete a single device.
operationId: deleteDevice
parameters:
- in: path
@@ -1313,7 +1484,7 @@ paths:
delete:
tags:
- Commands
summary: Delete some device logs
summary: Delete some device logs.
operationId: deleteDeviceLogs
parameters:
- in: path
@@ -1355,7 +1526,7 @@ paths:
get:
tags:
- Commands
summary: Get the latest health checks for a given device
summary: Get the latest health checks for a given device.
operationId: getDeviceHealthChecks
parameters:
- in: path
@@ -1402,7 +1573,7 @@ paths:
responses:
200:
description: Array of device health checks for this device
description: Array of device health checks for this device
content:
application/json:
schema:
@@ -1415,7 +1586,7 @@ paths:
delete:
tags:
- Commands
summary: Delete some device health checks
summary: Delete some device health checks.
operationId: deleteDeviceHealthChecks
parameters:
- in: path
@@ -1452,7 +1623,7 @@ paths:
get:
tags:
- Commands
summary: Get the latest capabilities for a given device
summary: Get the latest capabilities for a given device.
operationId: getDeviceCapabilities
parameters:
- in: path
@@ -1475,7 +1646,7 @@ paths:
delete:
tags:
- Commands
summary: Delete the capabilities for a given device
summary: Delete the capabilities for a given device.
operationId: deleteDeviceCapabilities
parameters:
- in: path
@@ -1499,7 +1670,7 @@ paths:
get:
tags:
- Commands
summary: Get the latest statistics for a given device
summary: Get the latest statistics for a given device.
operationId: getDeviceStats
parameters:
- in: path
@@ -1567,7 +1738,7 @@ paths:
delete:
tags:
- Commands
summary: Get the latest statistics for a given device
summary: Get the latest statistics for a given device.
operationId: deleteDeviceStats
parameters:
- in: path
@@ -1604,7 +1775,7 @@ paths:
get:
tags:
- Commands
summary: Get the latest status for a given device
summary: Get the latest status for a given device.
operationId: getDeviceStatus
parameters:
- in: path
@@ -1654,7 +1825,7 @@ paths:
post:
tags:
- Commands
summary: Configura a device
summary: Configure a device.
operationId: updateConfigurationForADevice
parameters:
- in: path
@@ -1680,7 +1851,7 @@ paths:
post:
tags:
- Commands
summary: Upgrade a device
summary: Upgrade a device.
operationId: UpgradeDeviceFirmware
parameters:
- in: path
@@ -1706,7 +1877,7 @@ paths:
post:
tags:
- Commands
summary: Upgrade a device
summary: Reboot a device.
operationId: rebootDevice
parameters:
- in: path
@@ -1732,7 +1903,7 @@ paths:
post:
tags:
- Commands
summary: Factory reset a device a device
summary: Factory reset a device.
operationId: factoryReset
parameters:
- in: path
@@ -1758,7 +1929,7 @@ paths:
post:
tags:
- Commands
summary: Blink the LEDs on a device
summary: Blink the LEDs on a device.
operationId: ledsRequest
parameters:
- in: path
@@ -1784,7 +1955,7 @@ paths:
post:
tags:
- Commands
summary: Launch a trace for a device
summary: Launch a trace for a device.
operationId: traceRequest
parameters:
- in: path
@@ -1810,7 +1981,7 @@ paths:
post:
tags:
- Commands
summary: Launch a wifi scan for a device
summary: Launch a wifi scan for a device.
operationId: wifiscanRequest
parameters:
- in: path
@@ -1862,7 +2033,7 @@ paths:
post:
tags:
- Commands
summary: Request a list of queued events
summary: Request a list of queued events.
operationId: eventQueueRequest
parameters:
- in: path
@@ -1884,12 +2055,38 @@ paths:
404:
$ref: '#/components/responses/NotFound'
/device/{serialNumber}/telemetry:
post:
tags:
- Commands
summary: Request a telemetry stream.
operationId: eventTelemetryStreamRequest
parameters:
- in: path
name: serialNumber
schema:
type: string
required: true
requestBody:
description: Message request details
content:
application/json:
schema:
$ref: '#/components/schemas/TelemetryStreamRequest'
responses:
200:
$ref: '#/components/schemas/TelemetryStreamResponse'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/ouis:
get:
tags:
- OUIs
operationId: getOUIs
summary: Get a list of OUIs
summary: Get a list of OUIs.
parameters:
- in: query
name: macList
@@ -1908,7 +2105,7 @@ paths:
get:
tags:
- Commands
summary: Get the rtty parameters to initiate a session
summary: Get the rtty parameters to initiate a session.
operationId: getRttySessionInfo
parameters:
- in: path
@@ -1932,7 +2129,7 @@ paths:
get:
tags:
- Files
summary: Get a file from the upload directory
summary: Get a file from the upload directory.
operationId: getUploadFile
parameters:
- in: path
@@ -1962,7 +2159,7 @@ paths:
delete:
tags:
- Files
summary: Delete a file from the upload directory
summary: Delete a file from the upload directory.
operationId: deleteUploadFidelete
parameters:
- in: path
@@ -1989,7 +2186,7 @@ paths:
tags:
- Blacklist
summary: Returns a list blacklisted devices.
description: Get a list of blacklisteddevices.
description: Get a list of blacklisted devices.
operationId: getBlacklistDeviceList
parameters:
- in: query
@@ -2022,17 +2219,76 @@ paths:
404:
$ref: '#/components/responses/NotFound'
/blacklist/{serialNumber}:
get:
tags:
- Blacklist
summary: Returns a blacklist entry.
description: Get a list of blacklisted devices.
operationId: getBlacklistDevice
parameters:
- in: path
description: Pagination start (starts at 1. If not specified, 1 is assumed)
name: serialNumber
schema:
type: string
required: true
responses:
200:
description: List blacklisted devices
content:
application/json:
schema:
$ref: '#/components/schemas/BlackDeviceInfo'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
post:
tags:
- Blacklist
summary: Adds to the blacklist
operationId: addToBlackList
summary: Create to the blacklist.
operationId: createBlackListDevice
parameters:
- in: path
description: Pagination start (starts at 1. If not specified, 1 is assumed)
name: serialNumber
schema:
type: string
required: true
requestBody:
description: Add blacklisted device
content:
application/json:
schema:
$ref: '#/components/schemas/BlackDeviceInfo'
responses:
200:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
put:
tags:
- Blacklist
summary: Modify to the blacklist.
operationId: modifyBlackList
parameters:
- in: path
description: Pagination start (starts at 1. If not specified, 1 is assumed)
name: serialNumber
schema:
type: string
required: true
requestBody:
description: Add blacklisted devices
content:
application/json:
schema:
$ref: '#/components/schemas/BlackDeviceList'
$ref: '#/components/schemas/BlackDeviceInfo'
responses:
200:
$ref: '#/components/responses/Success'
@@ -2044,11 +2300,10 @@ paths:
delete:
tags:
- Blacklist
summary: Delete from the blacklist
summary: Delete from the blacklist.
operationId: deleteFromBlackList
parameters:
- in: query
description: Serial Number
- in: path
name: serialNumber
schema:
type: string
@@ -2061,11 +2316,29 @@ paths:
404:
$ref: '#/components/responses/NotFound'
/capabilities:
get:
tags:
- Devices
summary: Get the list of device types and capabilities.
operationId: getCapabilitiesList
responses:
200:
description: Successful command execution
content:
application/json:
schema:
$ref: '#/components/schemas/CapabilitiesModelList'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/deviceDashboard:
get:
tags:
- Dashboards
summary: Get the last version of the dashboard
summary: Get the last version of the dashboard.
operationId: getDeviceDashboard
responses:
200:
@@ -2080,26 +2353,33 @@ paths:
## These are endpoints that all services in the uCentral stack must provide
##
#########################################################################################
/system:
post:
tags:
- System Commands
summary: Perform some systeme wide commands
summary: Perform some system wide commands.
operationId: systemCommand
requestBody:
description: Command details
content:
application/json:
schema:
$ref: '#/components/schemas/SystemCommandDetails'
oneOf:
- $ref: '#/components/schemas/SystemCommandSetLogLevel'
- $ref: '#/components/schemas/SystemCommandReload'
- $ref: '#/components/schemas/SystemCommandGetLogLevels'
- $ref: '#/components/schemas/SystemCommandGetLogLevelNames'
- $ref: '#/components/schemas/SystemCommandGetSubsystemNames'
responses:
200:
description: Successfull command execution
description: Successful command execution
content:
application/json:
schema:
$ref: '#/components/schemas/SystemCommandResults'
oneOf:
- $ref: '#/components/schemas/SystemGetLogLevelsResult'
- $ref: '#/components/schemas/SystemCommandGetLogLevelNamesResult'
- $ref: '#/components/schemas/SystemGetSubSystemNamesResult'
403:
$ref: '#/components/responses/Unauthorized'
404:
@@ -2116,18 +2396,18 @@ paths:
schema:
type: string
enum:
- version
- times
- info
required: true
responses:
200:
description: Successfull command execution
description: Successful command execution
content:
application/json:
schema:
$ref: '#/components/schemas/TagValuePair'
oneOf:
- $ref: '#/components/schemas/SystemInfoResults'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
$ref: '#/components/responses/NotFound'

View File

@@ -4,12 +4,12 @@
# address of one of your interfaces
#
ucentral.websocket.host.0.backlog = 500
ucentral.websocket.host.0.rootca = $UCENTRALGW_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer = $UCENTRALGW_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert = $UCENTRALGW_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key = $UCENTRALGW_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas = $UCENTRALGW_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas = $UCENTRALGW_ROOT/certs/cas
ucentral.websocket.host.0.rootca = $OWGW_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer = $OWGW_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert = $OWGW_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key = $OWGW_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas = $OWGW_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas = $OWGW_ROOT/certs/cas
ucentral.websocket.host.0.address = *
ucentral.websocket.host.0.port = 15002
ucentral.websocket.host.0.security = strict
@@ -19,60 +19,61 @@ ucentral.websocket.maxreactors = 20
#
# REST API access
#
ucentral.restapi.host.0.backlog = 100
ucentral.restapi.host.0.security = relaxed
ucentral.restapi.host.0.rootca = $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.restapi.host.0.address = *
ucentral.restapi.host.0.port = 16002
ucentral.restapi.host.0.cert = $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.restapi.host.0.key = $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.restapi.host.0.key.password = mypassword
openwifi.restapi.host.0.backlog = 100
openwifi.restapi.host.0.security = relaxed
openwifi.restapi.host.0.rootca = $OWGW_ROOT/certs/restapi-ca.pem
openwifi.restapi.host.0.address = *
openwifi.restapi.host.0.port = 16002
openwifi.restapi.host.0.cert = $OWGW_ROOT/certs/restapi-cert.pem
openwifi.restapi.host.0.key = $OWGW_ROOT/certs/restapi-key.pem
openwifi.restapi.host.0.key.password = mypassword
ucentral.internal.restapi.host.0.backlog = 100
ucentral.internal.restapi.host.0.security = relaxed
ucentral.internal.restapi.host.0.rootca = $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.internal.restapi.host.0.address = *
ucentral.internal.restapi.host.0.port = 17002
ucentral.internal.restapi.host.0.cert = $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.internal.restapi.host.0.key = $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.internal.restapi.host.0.key.password = mypassword
openwifi.internal.restapi.host.0.backlog = 100
openwifi.internal.restapi.host.0.security = relaxed
openwifi.internal.restapi.host.0.rootca = $OWGW_ROOT/certs/restapi-ca.pem
openwifi.internal.restapi.host.0.address = *
openwifi.internal.restapi.host.0.port = 17002
openwifi.internal.restapi.host.0.cert = $OWGW_ROOT/certs/restapi-cert.pem
openwifi.internal.restapi.host.0.key = $OWGW_ROOT/certs/restapi-key.pem
openwifi.internal.restapi.host.0.key.password = mypassword
#
# Used to upload files to the service.
# You should replace the 'name' vaalue with the IP address of your gateway or an FQDN
# that your devices can reach
#
ucentral.fileuploader.host.0.backlog = 100
ucentral.fileuploader.host.0.rootca = $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.fileuploader.host.0.security = relaxed
ucentral.fileuploader.host.0.address = *
ucentral.fileuploader.host.0.name = ucentral.dpaas.arilia.com
ucentral.fileuploader.host.0.port = 16003
ucentral.fileuploader.host.0.cert = $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.fileuploader.host.0.key = $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.fileuploader.host.0.key.password = mypassword
ucentral.fileuploader.path = $UCENTRALGW_ROOT/uploads
ucentral.fileuploader.maxsize = 10000
openwifi.fileuploader.host.0.backlog = 100
openwifi.fileuploader.host.0.rootca = $OWGW_ROOT/certs/restapi-ca.pem
openwifi.fileuploader.host.0.security = relaxed
openwifi.fileuploader.host.0.address = *
openwifi.fileuploader.host.0.name = ucentral.dpaas.arilia.com
openwifi.fileuploader.host.0.port = 16003
openwifi.fileuploader.host.0.cert = $OWGW_ROOT/certs/restapi-cert.pem
openwifi.fileuploader.host.0.key = $OWGW_ROOT/certs/restapi-key.pem
openwifi.fileuploader.host.0.key.password = mypassword
openwifi.fileuploader.path = $OWGW_ROOT/uploads
openwifi.fileuploader.maxsize = 10000
openwifi.fileuploader.uri = https://ucentral.dpaas.arilia.com:16003
#
# Generic section that all microservices must have
#
ucentral.service.key = $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.service.key.password = mypassword
ucentral.system.data = $UCENTRALGW_ROOT/data
ucentral.system.debug = true
ucentral.system.uri.private = https://localhost:17002
ucentral.system.uri.public = https://local.dpaas.arilia.com:16002
ucentral.system.uri.ui = https://ucentral-ui.arilia.com
ucentral.system.commandchannel = /tmp/app.ucentralgw
openwifi.service.key = $OWGW_ROOT/certs/restapi-key.pem
openwifi.service.key.password = mypassword
openwifi.system.data = $OWGW_ROOT/data
openwifi.system.debug = true
openwifi.system.uri.private = https://localhost:17002
openwifi.system.uri.public = https://ucentral.dpaas.arilia.com:16002
openwifi.system.uri.ui = https://ucentral-ui.arilia.com
openwifi.system.commandchannel = /tmp/app.ucentralgw
#
# Gateway Microservice Specific Section
#
ucentral.autoprovisioning = true
ucentral.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
ucentral.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
ucentral.devicetypes.2 = IOT:esp32
openwifi.autoprovisioning = true
openwifi.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
openwifi.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
openwifi.devicetypes.2 = IOT:esp32
oui.download.uri = https://linuxnet.ca/ieee/oui.txt
firmware.autoupdate.policy.default = auto
@@ -98,13 +99,12 @@ alb.port = 16102
#
# Kafka
#
ucentral.kafka.group.id = gateway
ucentral.kafka.client.id = gateway1
ucentral.kafka.enable = true
# ucentral.kafka.brokerlist = a1.arilia.com:9092
ucentral.kafka.brokerlist = debfarm1-node-c.arilia.com:9092
ucentral.kafka.auto.commit = false
ucentral.kafka.queue.buffering.max.ms = 50
openwifi.kafka.group.id = gateway
openwifi.kafka.client.id = gateway1
openwifi.kafka.enable = true
openwifi.kafka.brokerlist = a1.arilia.com:9092
openwifi.kafka.auto.commit = false
openwifi.kafka.queue.buffering.max.ms = 50
#
# This section select which form of persistence you need
@@ -164,7 +164,7 @@ logging.channels.c1.formatter = f1
# This is where the logs will be written. This path MUST exist
logging.channels.c2.class = FileChannel
logging.channels.c2.path = $UCENTRALGW_ROOT/logs/log
logging.channels.c2.path = $OWGW_ROOT/logs/log
logging.channels.c2.formatter.class = PatternFormatter
logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.channels.c2.rotation = 20 M

190
owgw.properties.tmpl Normal file
View File

@@ -0,0 +1,190 @@
#
# uCentral protocol server for devices. This is where you point
# all your devices. You can replace the * for address by the specific
# address of one of your interfaces
#
ucentral.websocket.host.0.backlog = 500
ucentral.websocket.host.0.rootca = ${WEBSOCKET_HOST_ROOTCA}
ucentral.websocket.host.0.issuer = ${WEBSOCKET_HOST_ISSUER}
ucentral.websocket.host.0.cert = ${WEBSOCKET_HOST_CERT}
ucentral.websocket.host.0.key = ${WEBSOCKET_HOST_KEY}
ucentral.websocket.host.0.clientcas = ${WEBSOCKET_HOST_CLIENTCAS}
ucentral.websocket.host.0.cas = ${WEBSOCKET_HOST_CAS}
ucentral.websocket.host.0.address = *
ucentral.websocket.host.0.port = ${WEBSOCKET_HOST_PORT}
ucentral.websocket.host.0.security = strict
ucentral.websocket.host.0.key.password = ${WEBSOCKET_HOST_KEY_PASSWORD}
ucentral.websocket.maxreactors = 20
#
# REST API access
#
openwifi.restapi.host.0.backlog = 100
openwifi.restapi.host.0.security = relaxed
openwifi.restapi.host.0.rootca = ${RESTAPI_HOST_ROOTCA}
openwifi.restapi.host.0.address = *
openwifi.restapi.host.0.port = ${RESTAPI_HOST_PORT}
openwifi.restapi.host.0.cert = ${RESTAPI_HOST_CERT}
openwifi.restapi.host.0.key = ${RESTAPI_HOST_KEY}
openwifi.restapi.host.0.key.password = ${RESTAPI_HOST_KEY_PASSWORD}
openwifi.internal.restapi.host.0.backlog = 100
openwifi.internal.restapi.host.0.security = relaxed
openwifi.internal.restapi.host.0.rootca = ${INTERNAL_RESTAPI_HOST_ROOTCA}
openwifi.internal.restapi.host.0.address = *
openwifi.internal.restapi.host.0.port = ${INTERNAL_RESTAPI_HOST_PORT}
openwifi.internal.restapi.host.0.cert = ${INTERNAL_RESTAPI_HOST_CERT}
openwifi.internal.restapi.host.0.key = ${INTERNAL_RESTAPI_HOST_KEY}
openwifi.internal.restapi.host.0.key.password = ${INTERNAL_RESTAPI_HOST_KEY_PASSWORD}
#
# Used to upload files to the service.
# You should replace the 'name' vaalue with the IP address of your gateway or an FQDN
# that your devices can reach
#
openwifi.fileuploader.host.0.backlog = 100
openwifi.fileuploader.host.0.rootca = ${FILEUPLOADER_HOST_ROOTCA}
openwifi.fileuploader.host.0.security = relaxed
openwifi.fileuploader.host.0.address = *
openwifi.fileuploader.host.0.name = ${FILEUPLOADER_HOST_NAME}
openwifi.fileuploader.host.0.port = ${FILEUPLOADER_HOST_PORT}
openwifi.fileuploader.host.0.cert = ${FILEUPLOADER_HOST_CERT}
openwifi.fileuploader.host.0.key = ${FILEUPLOADER_HOST_KEY}
openwifi.fileuploader.host.0.key.password = ${FILEUPLOADER_HOST_KEY_PASSWORD}
openwifi.fileuploader.path = ${FILEUPLOADER_PATH}
openwifi.fileuploader.uri = ${FILEUPLOADER_URI}
openwifi.fileuploader.maxsize = 10000
#
# Generic section that all microservices must have
#
openwifi.service.key = ${SERVICE_KEY}
openwifi.service.key.password = ${SERVICE_KEY_PASSWORD}
openwifi.system.data = ${SYSTEM_DATA}
openwifi.system.debug = true
openwifi.system.uri.private = ${SYSTEM_URI_PRIVATE}
openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC}
openwifi.system.uri.ui = ${SYSTEM_URI_UI}
openwifi.system.commandchannel = /tmp/app.ucentralgw
#
# Gateway Microservice Specific Section
#
openwifi.autoprovisioning = true
openwifi.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
openwifi.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
openwifi.devicetypes.2 = IOT:esp32
oui.download.uri = https://linuxnet.ca/ieee/oui.txt
firmware.autoupdate.policy.default = auto
simulatorid = ${SIMULATORID}
#
# rtty
#
rtty.enabled = ${RTTY_ENABLED}
rtty.server = ${RTTY_SERVER}
rtty.port = ${RTTY_PORT}
rtty.token = ${RTTY_TOKEN}
rtty.timeout = ${RTTY_TIMEOUT}
rtty.viewport = ${RTTY_VIEWPORT}
#############################
# Generic information for all micro services
#############################
#
# NLB Support
#
alb.enable = true
alb.port = 16102
#
# Kafka
#
openwifi.kafka.group.id = gateway
openwifi.kafka.client.id = gateway1
openwifi.kafka.enable = ${KAFKA_ENABLE}
openwifi.kafka.brokerlist = ${KAFKA_BROKERLIST}
openwifi.kafka.auto.commit = false
openwifi.kafka.queue.buffering.max.ms = 50
#
# This section select which form of persistence you need
# Only one selected at a time. If you select multiple, this service will die if a horrible
# death and might make your beer flat.
#
storage.type = ${STORAGE_TYPE}
storage.type.sqlite.db = devices.db
storage.type.sqlite.idletime = 120
storage.type.sqlite.maxsessions = 128
storage.type.postgresql.maxsessions = 64
storage.type.postgresql.idletime = 60
storage.type.postgresql.host = ${STORAGE_TYPE_POSTGRESQL_HOST}
storage.type.postgresql.username = ${STORAGE_TYPE_POSTGRESQL_USERNAME}
storage.type.postgresql.password = ${STORAGE_TYPE_POSTGRESQL_PASSWORD}
storage.type.postgresql.database = ${STORAGE_TYPE_POSTGRESQL_DATABASE}
storage.type.postgresql.port = ${STORAGE_TYPE_POSTGRESQL_PORT}
storage.type.postgresql.connectiontimeout = 60
storage.type.mysql.maxsessions = 64
storage.type.mysql.idletime = 60
storage.type.mysql.host = ${STORAGE_TYPE_MYSQL_HOST}
storage.type.mysql.username = ${STORAGE_TYPE_MYSQL_USERNAME}
storage.type.mysql.password = ${STORAGE_TYPE_MYSQL_PASSWORD}
storage.type.mysql.database = ${STORAGE_TYPE_MYSQL_DATABASE}
storage.type.mysql.port = ${STORAGE_TYPE_MYSQL_PORT}
storage.type.mysql.connectiontimeout = 60
archiver.enabled = true
archiver.schedule = 03:00
archiver.db.0.name = healthchecks
archiver.db.0.keep = 7
archiver.db.1.name = statistics
archiver.db.1.keep = 7
archiver.db.2.name = devicelogs
archiver.db.2.keep = 7
archiver.db.3.name = commandlist
archiver.db.3.keep = 7
########################################################################
########################################################################
#
# Logging: please leave as is for now.
#
########################################################################
logging.formatters.f1.class = PatternFormatter
logging.formatters.f1.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.formatters.f1.times = UTC
logging.channels.c1.class = ConsoleChannel
logging.channels.c1.formatter = f1
# This is where the logs will be written. This path MUST exist
logging.channels.c2.class = FileChannel
logging.channels.c2.path = $OWGW_ROOT/logs/log
logging.channels.c2.formatter.class = PatternFormatter
logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.channels.c2.rotation = 20 M
logging.channels.c2.archive = timestamp
logging.channels.c2.purgeCount = 20
logging.channels.c3.class = ConsoleChannel
logging.channels.c3.pattern = %s: [%p] %t
# External Channel
logging.loggers.root.channel = c1
logging.loggers.root.level = debug
# Inline Channel with PatternFormatter
# logging.loggers.l1.name = logger1
# logging.loggers.l1.channel.class = ConsoleChannel
# logging.loggers.l1.channel.pattern = %s: [%p] %t
# logging.loggers.l1.level = information
# SplitterChannel
# logging.channels.splitter.class = SplitterChannel
# logging.channels.splitter.channels = l1,l2
# logging.loggers.l2.name = logger2
# logging.loggers.l2.channel = splitter

View File

@@ -5,8 +5,8 @@ Wants=network-online.target
[Service]
Type=simple
Environment="UCENTRALGW_ROOT=/home/admin/dev/wlan-cloud-ucentralgw"
ExecStart=/home/admin/dev/wlan-cloud-ucentralgw/cmake-build/ucentralgw
Environment="OWGW_ROOT=/home/admin/dev/wlan-cloud-ucentralgw"
ExecStart=/home/admin/dev/wlan-cloud-ucentralgw/cmake-build/owgw
WorkingDirectory=/home/admin/dev/wlan-cloud-ucentralgw
# ExecReload=/bin/kill -s HUP $MAINPID
User=admin

65
readiness_check Executable file
View File

@@ -0,0 +1,65 @@
#!/bin/bash
set -e
if [[ "$(which jq)" == "" ]]
then
echo "You need the package jq installed to use this script."
exit 1
fi
if [[ "$(which curl)" == "" ]]
then
echo "You need the package curl installed to use this script."
exit 1
fi
if [[ "${OWSEC}" == "" ]]
then
echo "You must set the variable OWSEC in order to use this script. Something like"
echo "OWSEC=security.isp.com:16001"
exit 1
fi
if [[ "${OWSEC_USERNAME}" == "" ]]
then
echo "You must set the variable OWSEC_USERNAME in order to use this script. Something like"
echo "OWSEC_USERNAME=tip@ucentral.com"
exit 1
fi
if [[ "${OWSEC_PASSWORD}" == "" ]]
then
echo "You must set the variable OWSEC_PASSWORD in order to use this script. Something like"
echo "OWSEC_PASSWORD=openwifi"
exit 1
fi
if [[ "${READINESS_METHOD}" == "systeminfo" ]]
then
# Get OAuth token from OWSEC and cache it or use cached one
payload="{ \"userId\" : \"$OWSEC_USERNAME\" , \"password\" : \"$OWSEC_PASSWORD\" }"
if [[ -f "/tmp/token" ]]
then
token=$(cat /tmp/token)
else
token=$(curl ${FLAGS} -X POST -H "Content-Type: application/json" -d "$payload" "https://${OWSEC}/api/v1/oauth2" | jq -r '.access_token')
fi
if [[ "${token}" == "" ]]
then
echo "Could not login. Please verify the host and username/password."
exit 13
fi
echo -n $token > /tmp/token
# Make systeminfo request to the local owgw instance
export RESTAPI_PORT=$(grep 'openwifi.restapi.host.0.port' $OWGW_CONFIG/owgw.properties | awk -F '=' '{print $2}' | xargs | envsubst)
curl ${FLAGS} -k -X GET "https://localhost:$RESTAPI_PORT/api/v1/system?command=info" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > /tmp/result.json
exit_code=$?
jq < /tmp/result.json
exit $exit_code
else
export ALB_PORT=$(grep 'alb.port' $OWGW_CONFIG/owgw.properties | awk -F '=' '{print $2}' | xargs | envsubst)
curl localhost:$ALB_PORT
fi

View File

@@ -1,4 +1,4 @@
#!/bin/bash
export UCENTRALGW_CONFIG=`pwd`
export UCENTRALGW_ROOT=`pwd`
export OWGW_CONFIG=`pwd`
export OWGW_ROOT=`pwd`

View File

@@ -1,114 +0,0 @@
//
// Created by stephane bourque on 2021-06-04.
//
#ifndef UCENTRALGW_ALBHEALTHCHECKSERVER_H
#define UCENTRALGW_ALBHEALTHCHECKSERVER_H
#include <memory>
#include <iostream>
#include <fstream>
#include <sstream>
#include "Poco/Thread.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Logger.h"
#include "Daemon.h"
#include "SubSystemServer.h"
namespace OpenWifi {
class ALBRequestHandler: public Poco::Net::HTTPRequestHandler
/// Return a HTML document with the current date and time.
{
public:
ALBRequestHandler(Poco::Logger & L)
: Logger_(L)
{
}
void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response)
{
Logger_.information(Poco::format("ALB-REQUEST(%s): New ALB request.",Request.clientAddress().toString()));
Response.setChunkedTransferEncoding(true);
Response.setContentType("text/html");
Response.setDate(Poco::Timestamp());
Response.setStatus(Poco::Net::HTTPResponse::HTTP_OK);
Response.setKeepAlive(true);
Response.set("Connection","keep-alive");
Response.setVersion(Poco::Net::HTTPMessage::HTTP_1_1);
std::ostream &Answer = Response.send();
Answer << "uCentralGW Alive and kicking!" ;
}
private:
Poco::Logger & Logger_;
};
class ALBRequestHandlerFactory: public Poco::Net::HTTPRequestHandlerFactory
{
public:
explicit ALBRequestHandlerFactory(Poco::Logger & L):
Logger_(L)
{
}
ALBRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& request) override
{
if (request.getURI() == "/")
return new ALBRequestHandler(Logger_);
else
return nullptr;
}
private:
Poco::Logger &Logger_;
};
class ALBHealthCheckServer : public SubSystemServer {
public:
ALBHealthCheckServer() noexcept:
SubSystemServer("ALBHealthCheckServer", "ALB-SVR", "alb")
{
}
static ALBHealthCheckServer *instance() {
if (instance_ == nullptr) {
instance_ = new ALBHealthCheckServer;
}
return instance_;
}
int Start() {
if(Daemon()->ConfigGetBool("alb.enable",false)) {
Port_ = (int)Daemon()->ConfigGetInt("alb.port",15015);
Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_);
auto Params = new Poco::Net::HTTPServerParams;
Server_ = std::make_unique<Poco::Net::HTTPServer>(new ALBRequestHandlerFactory(Logger_), *Socket_, Params);
Server_->start();
}
return 0;
}
void Stop() {
if(Server_)
Server_->stop();
}
private:
static ALBHealthCheckServer *instance_;
std::unique_ptr<Poco::Net::HTTPServer> Server_;
std::unique_ptr<Poco::Net::ServerSocket> Socket_;
int Port_ = 0;
};
inline ALBHealthCheckServer * ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); }
inline class ALBHealthCheckServer * ALBHealthCheckServer::instance_ = nullptr;
}
#endif // UCENTRALGW_ALBHEALTHCHECKSERVER_H

61
src/APIServers.cpp Normal file
View File

@@ -0,0 +1,61 @@
//
// Created by stephane bourque on 2021-10-23.
//
#include "framework/MicroService.h"
#include "RESTAPI/RESTAPI_blacklist.h"
#include "RESTAPI/RESTAPI_blacklist_list.h"
#include "RESTAPI/RESTAPI_command.h"
#include "RESTAPI/RESTAPI_commands.h"
#include "RESTAPI/RESTAPI_default_configuration.h"
#include "RESTAPI/RESTAPI_default_configurations.h"
#include "RESTAPI/RESTAPI_deviceDashboardHandler.h"
#include "RESTAPI/RESTAPI_device_commandHandler.h"
#include "RESTAPI/RESTAPI_device_handler.h"
#include "RESTAPI/RESTAPI_devices_handler.h"
#include "RESTAPI/RESTAPI_file.h"
#include "RESTAPI/RESTAPI_ouis.h"
#include "RESTAPI/RESTAPI_capabilities_handler.h"
#include "RESTAPI/RESTAPI_TelemetryWebSocket.h"
#include "RESTAPI/RESTAPI_webSocketServer.h"
namespace OpenWifi {
Poco::Net::HTTPRequestHandler * RESTAPI_external_server(const char *Path, RESTAPIHandler::BindingMap &Bindings,
Poco::Logger & L, RESTAPI_GenericServer & S) {
return RESTAPI_Router<
RESTAPI_devices_handler,
RESTAPI_device_handler,
RESTAPI_device_commandHandler,
RESTAPI_default_configurations,
RESTAPI_default_configuration,
RESTAPI_command,
RESTAPI_commands,
RESTAPI_ouis,
RESTAPI_file,
RESTAPI_system_command,
RESTAPI_deviceDashboardHandler,
RESTAPI_webSocketServer,
RESTAPI_blacklist,
RESTAPI_blacklist_list,
RESTAPI_capabilities_handler,
RESTAPI_TelemetryWebSocket>(Path,Bindings,L, S);
}
Poco::Net::HTTPRequestHandler * RESTAPI_internal_server(const char *Path, RESTAPIHandler::BindingMap &Bindings,
Poco::Logger & L, RESTAPI_GenericServer & S) {
return RESTAPI_Router_I<
RESTAPI_devices_handler,
RESTAPI_device_handler,
RESTAPI_device_commandHandler,
RESTAPI_default_configurations,
RESTAPI_default_configuration,
RESTAPI_command,
RESTAPI_commands,
RESTAPI_ouis,
RESTAPI_file, RESTAPI_blacklist,
RESTAPI_blacklist_list>(Path,Bindings,L, S);
}
}

View File

@@ -1,88 +0,0 @@
//
// Created by stephane bourque on 2021-06-30.
//
#include <utility>
#include "AuthClient.h"
#include "RESTAPI_SecurityObjects.h"
#include "Daemon.h"
#include "OpenAPIRequest.h"
namespace OpenWifi {
class AuthClient * AuthClient::instance_ = nullptr;
int AuthClient::Start() {
return 0;
}
void AuthClient::Stop() {
}
void AuthClient::RemovedCachedToken(const std::string &Token) {
SubMutexGuard G(Mutex_);
UserCache_.erase(Token);
}
bool IsTokenExpired(const SecurityObjects::WebToken &T) {
return ((T.expires_in_+T.created_)<std::time(nullptr));
}
bool AuthClient::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) {
SubMutexGuard G(Mutex_);
auto User = UserCache_.find(SessionToken);
if(User != UserCache_.end() && !IsTokenExpired(User->second.webtoken)) {
UInfo = User->second;
return true;
} else {
Types::StringPairVec QueryData;
QueryData.push_back(std::make_pair("token",SessionToken));
OpenAPIRequestGet Req( uSERVICE_SECURITY,
"/api/v1/validateToken",
QueryData,
5000);
Poco::JSON::Object::Ptr Response;
if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) {
if(Response->has("tokenInfo") && Response->has("userInfo")) {
SecurityObjects::UserInfoAndPolicy P;
P.from_json(Response);
UserCache_[SessionToken] = P;
UInfo = P;
}
return true;
}
}
return false;
}
bool AuthClient::IsTokenAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo) {
SubMutexGuard G(Mutex_);
auto User = UserCache_.find(SessionToken);
if(User != UserCache_.end() && !IsTokenExpired(User->second.webtoken)) {
UInfo = User->second;
return true;
} else {
Types::StringPairVec QueryData;
QueryData.push_back(std::make_pair("token",SessionToken));
OpenAPIRequestGet Req(uSERVICE_SECURITY,
"/api/v1/validateToken",
QueryData,
5000);
Poco::JSON::Object::Ptr Response;
if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) {
if(Response->has("tokenInfo") && Response->has("userInfo")) {
SecurityObjects::UserInfoAndPolicy P;
P.from_json(Response);
UserCache_[SessionToken] = P;
UInfo = P;
}
return true;
}
}
return false;
}
}

View File

@@ -1,45 +0,0 @@
//
// Created by stephane bourque on 2021-06-30.
//
#ifndef UCENTRALGW_AUTHCLIENT_H
#define UCENTRALGW_AUTHCLIENT_H
#include "Poco/JSON/Object.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/JWT/Signer.h"
#include "Poco/SHA2Engine.h"
#include "RESTAPI_SecurityObjects.h"
#include "SubSystemServer.h"
namespace OpenWifi {
class AuthClient : public SubSystemServer {
public:
explicit AuthClient() noexcept:
SubSystemServer("Authentication", "AUTH-CLNT", "authentication")
{
}
static AuthClient *instance() {
if (instance_ == nullptr) {
instance_ = new AuthClient;
}
return instance_;
}
int Start() override;
void Stop() override;
bool IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string &SessionToken, OpenWifi::SecurityObjects::UserInfoAndPolicy & UInfo );
void RemovedCachedToken(const std::string &Token);
bool IsTokenAuthorized(const std::string &Token, SecurityObjects::UserInfoAndPolicy & UInfo);
private:
static AuthClient *instance_;
OpenWifi::SecurityObjects::UserInfoCache UserCache_;
};
inline AuthClient * AuthClient() { return AuthClient::instance(); }
}
#endif // UCENTRALGW_AUTHCLIENT_H

View File

@@ -7,13 +7,14 @@
//
#include <fstream>
#include "CentralConfig.h"
#include "Daemon.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "Poco/File.h"
#include "CentralConfig.h"
#include "framework/MicroService.h"
#include "Daemon.h"
namespace OpenWifi::Config {
static std::string DefaultConfiguration;
@@ -119,7 +120,7 @@ namespace OpenWifi::Config {
})lit"};
void SetBasicConfigFile() {
Poco::File DefaultConfigFileName{Daemon()->DataDir()+"/default_config.json"};
Poco::File DefaultConfigFileName{MicroService::instance().DataDir()+"/default_config.json"};
DefaultConfiguration = BasicConfig;
std::ofstream F;
F.open(DefaultConfigFileName.path(),std::ios::binary);
@@ -134,7 +135,7 @@ namespace OpenWifi::Config {
void Config::Init() {
if(DefaultConfiguration.empty()) {
// open the file
Poco::File DefaultConfigFileName{Daemon()->DataDir()+"/default_config.json"};
Poco::File DefaultConfigFileName{MicroService::instance().DataDir()+"/default_config.json"};
try {
if (!DefaultConfigFileName.exists()) {
SetBasicConfigFile();
@@ -232,7 +233,7 @@ namespace OpenWifi::Config {
}
catch ( const Poco::Exception & E )
{
Daemon::instance()->logger().warning(Poco::format("%s: Failed with: %s", std::string(__func__) , E.displayText()));
Daemon()->logger().log(E);
}
}

View File

@@ -6,27 +6,20 @@
// Arilia Wireless Inc.
//
#include "CommandManager.h"
#include <algorithm>
#include "CommandManager.h"
#include "DeviceRegistry.h"
#include "RESTAPI_GWobjects.h"
#include "RESTAPI_handler.h"
#include "StorageService.h"
#include "uCentralProtocol.h"
#include "Poco/JSON/Parser.h"
#include "CommandManager.h"
#include "DeviceRegistry.h"
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "StorageService.h"
#include "framework/MicroService.h"
#include "framework/uCentral_Protocol.h"
namespace OpenWifi {
class CommandManager * CommandManager::instance_ = nullptr;
CommandManager::CommandManager() noexcept:
SubSystemServer("CommandManager", "CMD_MGR", "command.manager")
{
}
void CommandManager::run() {
Running_ = true;
while(Running_)
@@ -34,16 +27,27 @@ namespace OpenWifi {
Poco::Thread::trySleep(30000);
if(!Running_)
break;
std::vector<GWObjects::CommandDetails> Commands;
if(Storage()->GetReadyToExecuteCommands(1,200,Commands))
std::vector<GWObjects::CommandDetails> Commands;
if(StorageService()->GetReadyToExecuteCommands(1,200,Commands))
{
for(auto & Cmd: Commands)
{
if(!Running_)
break;
if(!SendCommand(Cmd)) {
uint64_t RPC_Id;
Poco::JSON::Parser P;
auto Params = P.parse(Cmd.Details).extract<Poco::JSON::Object::Ptr>();
if(SendCommand( Cmd.SerialNumber,
Cmd.Command,
*Params,
Cmd.UUID,
RPC_Id)) {
StorageService()->SetCommandExecuted(Cmd.UUID);
Logger_.information(Poco::format("Sent command '%s' to '%s'",Cmd.Command,Cmd.SerialNumber));
} else {
Logger_.information(Poco::format("Failed to send command '%s' to %s",Cmd.Command,Cmd.SerialNumber));
}
}
@@ -71,105 +75,85 @@ namespace OpenWifi {
}
void CommandManager::Janitor() {
SubMutexGuard G(SubMutex);
std::lock_guard G(Mutex_);
uint64_t Now = time(nullptr);
for(auto i = Age_.begin(); i!= Age_.end();)
if((Now-i->first)>300)
Age_.erase(i++);
Logger_.information("Janitor starting.");
for(auto i=OutStandingRequests_.begin();i!=OutStandingRequests_.end();) {
if((Now-i->second.Submitted)>120)
i = OutStandingRequests_.erase(i);
else
++i;
}
Logger_.information("Janitor finished.");
}
bool CommandManager::SendCommand(const std::string &SerialNumber,
const std::string &Method,
const Poco::JSON::Object &Params,
std::shared_ptr<std::promise<Poco::JSON::Object::Ptr>> Promise,
const std::string &UUID) {
bool CommandManager::GetCommand(uint64_t Id, const std::string &SerialNumber, CommandTag &T) {
std::lock_guard G(Mutex_);
CommandTagIndex TI{.Id=Id,.SerialNumber=SerialNumber};
auto Hint=OutStandingRequests_.find(TI);
if(Hint==OutStandingRequests_.end() || Hint->second.Completed==0)
return false;
T = Hint->second;
OutStandingRequests_.erase(Hint);
return true;
}
SubMutexGuard G(SubMutex);
bool CommandManager::SendCommand( const std::string &SerialNumber,
const std::string &Method,
const Poco::JSON::Object &Params,
const std::string &UUID,
uint64_t & Id,
bool oneway_rpc) {
Poco::JSON::Object CompleteRPC;
CompleteRPC.set(uCentralProtocol::JSONRPC, uCentralProtocol::JSONRPC_VERSION);
CompleteRPC.set(uCentralProtocol::ID, Id_);
CompleteRPC.set(uCentralProtocol::METHOD, Method );
CompleteRPC.set(uCentralProtocol::PARAMS, Params);
std::stringstream ToSend;
std::unique_lock G(Mutex_);
if(oneway_rpc)
Id = 1;
else
Id = ++Id_;
Poco::JSON::Object CompleteRPC;
CompleteRPC.set(uCentralProtocol::JSONRPC, uCentralProtocol::JSONRPC_VERSION);
CompleteRPC.set(uCentralProtocol::ID, Id);
CompleteRPC.set(uCentralProtocol::METHOD, Method);
CompleteRPC.set(uCentralProtocol::PARAMS, Params);
Poco::JSON::Stringifier::stringify(CompleteRPC, ToSend);
OutStandingRequests_[Id_] = std::make_pair(std::move(Promise),UUID);
Age_[Id_] = time(nullptr);
Id_++;
Logger_.information(
Poco::format("(%s): Sending command '%s', ID: %lu", SerialNumber, Method, Id));
CommandTagIndex Idx{.Id = Id, .SerialNumber = SerialNumber};
CommandTag Tag;
Tag.UUID = UUID;
Tag.Submitted = std::time(nullptr);
Tag.Completed = 0;
Tag.Result = Poco::makeShared<Poco::JSON::Object>();
OutStandingRequests_[Idx] = Tag;
G.unlock();
return DeviceRegistry()->SendFrame(SerialNumber, ToSend.str());
}
bool CommandManager::SendCommand(GWObjects::CommandDetails & Command) {
SubMutexGuard G(SubMutex);
Logger_.debug(Poco::format("Sending command to %s",Command.SerialNumber));
try {
Poco::JSON::Object Obj;
Obj.set(uCentralProtocol::JSONRPC,uCentralProtocol::JSONRPC_VERSION);
Obj.set(uCentralProtocol::ID,Id_);
Obj.set(uCentralProtocol::METHOD, Command.Custom ? uCentralProtocol::PERFORM : Command.Command );
bool FullCommand = true;
if(Command.Command==uCentralProtocol::REQUEST)
FullCommand = false;
// the params section was composed earlier... just include it here
Poco::JSON::Parser parser;
auto ParsedMessage = parser.parse(Command.Details);
const auto & ParamsObj = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
Obj.set(uCentralProtocol::PARAMS,ParamsObj);
std::stringstream ToSend;
Poco::JSON::Stringifier::stringify(Obj,ToSend);
if(DeviceRegistry()->SendFrame(Command.SerialNumber, ToSend.str())) {
Storage()->SetCommandExecuted(Command.UUID);
OutStandingRequests_[Id_] = std::make_pair(nullptr,Command.UUID);
Age_[Id_] = time(nullptr);
return true;
} else {
}
Id_++;
}
catch( const Poco::Exception & E )
{
Logger_.warning(Poco::format("COMMAND(%s): Exception while sending a command.",Command.SerialNumber));
}
return false;
}
void CommandManager::PostCommandResult(const std::string &SerialNumber, Poco::JSON::Object::Ptr Obj) {
if(!Obj->has(uCentralProtocol::ID)){
Logger_.error("Invalid RPC response.");
Logger_.error(Poco::format("(%s): Invalid RPC response.",SerialNumber));
return;
}
SubMutexGuard G(SubMutex);
uint64_t ID = Obj->get(uCentralProtocol::ID);
auto RPC = OutStandingRequests_.find(ID);
Age_.erase(ID);
if(RPC != OutStandingRequests_.end()) {
if(RPC->second.first.use_count() > 1) {
try {
RPC->second.first->set_value(std::move(Obj));
} catch (...) {
Logger_.error(Poco::format("COMPLETING-RPC(%Lu): future was lost", ID));
Storage()->CommandCompleted(RPC->second.second, Obj, true);
}
}
else {
Storage()->CommandCompleted(RPC->second.second, Obj, true);
}
OutStandingRequests_.erase(RPC);
} else {
Logger_.warning(Poco::format("OUTDATED-RPC(%lu): Nothing waiting for this RPC.",ID));
if(ID<2) {
Logger_.error(Poco::format("(%s): Ignoring RPC response.",SerialNumber));
return;
}
std::unique_lock G(Mutex_);
auto Idx = CommandTagIndex{.Id = ID, .SerialNumber = SerialNumber};
auto RPC = OutStandingRequests_.find(Idx);
if (RPC == OutStandingRequests_.end()) {
Logger_.warning(Poco::format("(%s): Outdated RPC %lu", SerialNumber, ID));
return;
}
RPC->second.Completed = std::time(nullptr);
RPC->second.Result = Obj;
Logger_.information(Poco::format("(%s): Received RPC answer %lu", SerialNumber, ID));
G.unlock();
StorageService()->CommandCompleted(RPC->second.UUID, Obj, true);
}
} // namespace

View File

@@ -19,11 +19,37 @@
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "RESTAPI_GWobjects.h"
#include "SubSystemServer.h"
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "framework/MicroService.h"
namespace OpenWifi {
struct CommandTagIndex {
uint64_t Id=0;
std::string SerialNumber;
};
inline bool operator <(const CommandTagIndex& lhs, const CommandTagIndex& rhs) {
if(lhs.Id<rhs.Id)
return true;
if(lhs.Id>rhs.Id)
return false;
return lhs.SerialNumber<rhs.SerialNumber;
}
inline bool operator ==(const CommandTagIndex& lhs, const CommandTagIndex& rhs) {
if(lhs.Id == rhs.Id && lhs.SerialNumber == rhs.SerialNumber)
return true;
return false;
}
struct CommandTag {
std::string UUID;
Poco::JSON::Object::Ptr Result;
uint64_t Submitted=0;
uint64_t Completed=0;
};
class CommandManager : public SubSystemServer, Poco::Runnable {
public:
int Start() override;
@@ -31,34 +57,32 @@ namespace OpenWifi {
void WakeUp();
void PostCommandResult(const std::string &SerialNumber, Poco::JSON::Object::Ptr Obj);
bool SendCommand( const std::string &SerialNumber,
const std::string &Method,
const Poco::JSON::Object &Params,
std::shared_ptr<std::promise<Poco::JSON::Object::Ptr>> Promise,
const std::string &UUID);
bool SendCommand( const std::string & SerialNumber,
const std::string & Method,
const Poco::JSON::Object &Params,
const std::string & UUID);
bool SendCommand(GWObjects::CommandDetails & Command);
const std::string &Method,
const Poco::JSON::Object &Params,
const std::string &UUID,
uint64_t & Id,
bool oneway_rpc=false);
void Janitor();
void run() override;
bool GetCommand(uint64_t Id, const std::string & SerialNumber, CommandTag &T);
static CommandManager *instance() {
if (instance_ == nullptr) {
instance_ = new CommandManager;
}
static CommandManager *instance_ = new CommandManager;
return instance_;
}
inline bool Running() const { return Running_; }
private:
static CommandManager * instance_;
std::atomic_bool Running_ = false;
Poco::Thread ManagerThread;
uint64_t Id_=1;
std::map< uint64_t , std::pair< std::shared_ptr<std::promise<Poco::JSON::Object::Ptr>>, std::string> > OutStandingRequests_;
std::map< uint64_t , uint64_t > Age_;
std::atomic_bool Running_ = false;
Poco::Thread ManagerThread;
uint64_t Id_=2; // do not start @1. We ignore ID=1 & 0 is illegal..
std::map<CommandTagIndex,CommandTag> OutStandingRequests_;
CommandManager() noexcept;
CommandManager() noexcept:
SubSystemServer("CommandManager", "CMD-MGR", "command.manager")
{
}
};
inline CommandManager * CommandManager() { return CommandManager::instance(); }

View File

@@ -0,0 +1,8 @@
//
// Created by stephane bourque on 2021-09-21.
//
#include "ConfigurationCache.h"
namespace OpenWifi {
}

42
src/ConfigurationCache.h Normal file
View File

@@ -0,0 +1,42 @@
//
// Created by stephane bourque on 2021-09-21.
//
#ifndef OWGW_CONFIGURATIONCACHE_H
#define OWGW_CONFIGURATIONCACHE_H
#include <map>
#include <string>
#include <mutex>
namespace OpenWifi {
class ConfigurationCache {
public:
static ConfigurationCache & instance() {
static ConfigurationCache instance;
return instance;
}
inline uint64_t CurrentConfig(const std::string &SerialNumber) {
std::lock_guard G(Mutex_);
const auto Hint = Cache_.find(SerialNumber);
if(Hint==end(Cache_))
return 0;
return Hint->second;
}
inline void Add(const std::string &SerialNumber, uint64_t Id) {
std::lock_guard G(Mutex_);
Cache_[SerialNumber]=Id;
}
private:
std::mutex Mutex_;
std::map<std::string,uint64_t> Cache_;
};
inline uint64_t GetCurrentConfigurationID(const std::string &S) { return ConfigurationCache::instance().CurrentConfig(S); }
inline void SetCurrentConfigurationID(const std::string &S, uint64_t ID) { ConfigurationCache::instance().Add(S,ID); }
}
#endif // OWGW_CONFIGURATIONCACHE_H

View File

@@ -10,63 +10,53 @@
#include "Poco/Util/Application.h"
#include "Poco/Util/Option.h"
#include "Poco/Environment.h"
#include "Poco/Net/HTTPStreamFactory.h"
#include "Daemon.h"
#include "CentralConfig.h"
#include "CommandManager.h"
#include "Daemon.h"
#include "DeviceRegistry.h"
#include "FileUploader.h"
#include "RESTAPI_server.h"
#include "StorageService.h"
#include "WebSocketServer.h"
#include "CentralConfig.h"
#include "OUIServer.h"
#include "StateProcessor.h"
#include "Utils.h"
#include "RESTAPI_InternalServer.h"
#include "AuthClient.h"
#include "StorageArchiver.h"
#include "SerialNumberCache.h"
#include "StorageArchiver.h"
#include "StorageService.h"
#include "TelemetryStream.h"
#include "WebSocketServer.h"
#include "framework/ConfigurationValidator.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class Daemon *Daemon::instance_ = nullptr;
class Daemon *Daemon::instance() {
if (instance_ == nullptr) {
instance_ = new Daemon(vDAEMON_PROPERTIES_FILENAME,
static Daemon instance(vDAEMON_PROPERTIES_FILENAME,
vDAEMON_ROOT_ENV_VAR,
vDAEMON_CONFIG_ENV_VAR,
vDAEMON_APP_NAME,
vDAEMON_BUS_TIMER,
Types::SubSystemVec{
Storage(),
SubSystemVec{
StorageService(),
SerialNumberCache(),
AuthClient(),
ConfigurationValidator(),
DeviceRegistry(),
RESTAPI_server(),
RESTAPI_InternalServer(),
WebSocketServer(),
CommandManager(),
FileUploader(),
OUIServer(),
StorageArchiver(),
TelemetryStream()
});
}
return instance_;
return &instance;
}
void Daemon::initialize(Poco::Util::Application &self) {
MicroService::initialize(*this);
void Daemon::initialize() {
Config::Config::Init();
AutoProvisioning_ = config().getBool("ucentral.autoprovisioning",false);
AutoProvisioning_ = config().getBool("openwifi.autoprovisioning",false);
// DeviceTypeIdentifications_
Types::StringVec Keys;
config().keys("ucentral.devicetypes",Keys);
config().keys("openwifi.devicetypes",Keys);
for(const auto & i:Keys)
{
std::string Line = config().getString("ucentral.devicetypes."+i);
std::string Line = config().getString("openwifi.devicetypes."+i);
auto P1 = Line.find_first_of(':');
auto Type = Line.substr(0, P1);
auto List = Line.substr(P1+1);
@@ -84,6 +74,10 @@ namespace OpenWifi {
}
}
void MicroServicePostInitialization() {
Daemon()->initialize();
}
[[nodiscard]] std::string Daemon::IdentifyDevice(const std::string & Id ) const {
for(const auto &[Type,List]:DeviceTypeIdentifications_)
{
@@ -94,12 +88,12 @@ namespace OpenWifi {
}
}
int main(int argc, char **argv) {
try {
auto App = OpenWifi::Daemon::instance();
auto ExitCode = App->run(argc, argv);
delete App;
return ExitCode;
} catch (Poco::Exception &exc) {

View File

@@ -26,34 +26,34 @@
#include "Poco/Crypto/Cipher.h"
#include "Dashboard.h"
#include "MicroService.h"
#include "OpenWifiTypes.h"
#include "framework/MicroService.h"
#include "framework/OpenWifiTypes.h"
namespace OpenWifi {
static const char * vDAEMON_PROPERTIES_FILENAME = "ucentralgw.properties";
static const char * vDAEMON_ROOT_ENV_VAR = "UCENTRALGW_ROOT";
static const char * vDAEMON_CONFIG_ENV_VAR = "UCENTRALGW_CONFIG";
static const char * vDAEMON_PROPERTIES_FILENAME = "owgw.properties";
static const char * vDAEMON_ROOT_ENV_VAR = "OWGW_ROOT";
static const char * vDAEMON_CONFIG_ENV_VAR = "OWGW_CONFIG";
static const char * vDAEMON_APP_NAME = uSERVICE_GATEWAY.c_str();
static const uint64_t vDAEMON_BUS_TIMER = 10000;
class Daemon : public MicroService {
public:
explicit Daemon(std::string PropFile,
std::string RootEnv,
std::string ConfigEnv,
std::string AppName,
explicit Daemon(const std::string & PropFile,
const std::string & RootEnv,
const std::string & ConfigEnv,
const std::string & AppName,
uint64_t BusTimer,
Types::SubSystemVec SubSystems) :
const SubSystemVec & SubSystems) :
MicroService( PropFile, RootEnv, ConfigEnv, AppName, BusTimer, SubSystems) {};
bool AutoProvisioning() const { return AutoProvisioning_ ; }
[[nodiscard]] std::string IdentifyDevice(const std::string & Compatible) const;
void initialize(Poco::Util::Application &self);
void initialize();
static Daemon *instance();
inline DeviceDashboard & GetDashboard() { return DB_; }
Poco::Logger & Log() { return Poco::Logger::get(AppName()); }
private:
static Daemon *instance_;
bool AutoProvisioning_ = false;
Types::StringMapStringSet DeviceTypeIdentifications_;
DeviceDashboard DB_;

View File

@@ -12,9 +12,8 @@ namespace OpenWifi {
if(LastRun_==0 || (Now-LastRun_)>120) {
DB_.reset();
Storage()->AnalyzeCommands(DB_.commands);
// DeviceRegistry()->AnalyzeRegistry(DB_);
Storage()->AnalyzeDevices(DB_);
StorageService()->AnalyzeCommands(DB_.commands);
StorageService()->AnalyzeDevices(DB_);
LastRun_ = Now;
}
}

View File

@@ -5,14 +5,15 @@
#ifndef UCENTRALGW_DASHBOARD_H
#define UCENTRALGW_DASHBOARD_H
#include "OpenWifiTypes.h"
#include "RESTAPI_GWobjects.h"
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "framework/OpenWifiTypes.h"
namespace OpenWifi {
class DeviceDashboard {
public:
DeviceDashboard() { DB_.reset(); }
void Create();
const GWObjects::Dashboard & Report() const { return DB_;}
[[nodiscard]] const GWObjects::Dashboard & Report() const { return DB_;}
private:
GWObjects::Dashboard DB_;
uint64_t LastRun_=0;

View File

@@ -6,50 +6,41 @@
// Arilia Wireless Inc.
//
#include "DeviceRegistry.h"
#include "RESTAPI_handler.h"
#include "WebSocketServer.h"
#include "DeviceRegistry.h"
#include "OUIServer.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
namespace OpenWifi {
class DeviceRegistry *DeviceRegistry::instance_ = nullptr;
#include "DeviceRegistry.h"
#include "WebSocketServer.h"
#include "OUIServer.h"
DeviceRegistry::DeviceRegistry() noexcept:
SubSystemServer("DeviceRegistry", "DevStatus", "devicestatus") {
}
namespace OpenWifi {
int DeviceRegistry::Start() {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
Logger_.notice("Starting ");
return 0;
}
void DeviceRegistry::Stop() {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
Logger_.notice("Stopping ");
}
bool DeviceRegistry::GetStatistics(const std::string &SerialNumber, std::string & Statistics) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device != Devices_.end()) {
Statistics = Device->second->LastStats;
return true;
}
return false;
if(Device == Devices_.end())
return false;
Statistics = Device->second->LastStats;
return true;
}
void DeviceRegistry::SetStatistics(const std::string &SerialNumber, const std::string &Statistics) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device != Devices_.end())
{
Device->second->Conn_.LastContact = time(nullptr);
@@ -58,22 +49,18 @@ namespace OpenWifi {
}
bool DeviceRegistry::GetState(const std::string &SerialNumber, GWObjects::ConnectionState & State) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device != Devices_.end())
{
State = Device->second->Conn_;
return true;
}
return false;
if(Device == Devices_.end())
return false;
State = Device->second->Conn_;
return true;
}
void DeviceRegistry::SetState(const std::string & SerialNumber, GWObjects::ConnectionState & State) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device != Devices_.end())
{
Device->second->Conn_.LastContact = time(nullptr);
@@ -82,7 +69,7 @@ namespace OpenWifi {
}
bool DeviceRegistry::GetHealthcheck(const std::string &SerialNumber, GWObjects::HealthCheck & CheckData) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device != Devices_.end()) {
@@ -93,86 +80,70 @@ namespace OpenWifi {
}
void DeviceRegistry::SetHealthcheck(const std::string &SerialNumber, const GWObjects::HealthCheck & CheckData) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device != Devices_.end())
{
Device->second->LastHealthcheck = CheckData;
}
}
GWObjects::ConnectionState * DeviceRegistry::Register(const std::string & SerialNumber, WSConnection *Ptr)
std::shared_ptr<DeviceRegistry::ConnectionEntry> DeviceRegistry::Register(const std::string & SerialNumber, WSConnection *Ptr, uint64_t & ConnectionId )
{
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if( Device == Devices_.end()) {
auto E = std::make_unique<ConnectionEntry>();
E->WSConn_ = Ptr;
E->Conn_.SerialNumber = SerialNumber;
E->Conn_.LastContact = std::time(nullptr);
E->Conn_.Connected = true ;
E->Conn_.UUID = 0 ;
E->Conn_.MessageCount = 0 ;
E->Conn_.Address = "";
E->Conn_.TX = 0 ;
E->Conn_.RX = 0;
E->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
auto R=&E->Conn_;
Devices_[SerialNumber] = std::move(E);
return R;
}
else
{
Device->second->WSConn_ = Ptr;
Device->second->Conn_.Connected = true;
Device->second->Conn_.LastContact = std::time(nullptr);
Device->second->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
return &Device->second->Conn_;
}
const auto & E = Devices_[SerialNumber] = std::make_shared<ConnectionEntry>();
E->WSConn_ = Ptr;
E->Conn_.SerialNumber = SerialNumber;
E->Conn_.LastContact = std::time(nullptr);
E->Conn_.Connected = true ;
E->Conn_.UUID = 0 ;
E->Conn_.MessageCount = 0 ;
E->Conn_.Address = "";
E->Conn_.TX = 0 ;
E->Conn_.RX = 0;
E->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
ConnectionId = E->ConnectionId = ++Id_;
return E;
}
bool DeviceRegistry::Connected(const std::string & SerialNumber) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device == Devices_.end())
return false;
return Device->second->Conn_.Connected;
}
void DeviceRegistry::UnRegister(const std::string & SerialNumber, WSConnection *Ptr) {
SubMutexGuard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if( Device != Devices_.end() && Device->second->WSConn_==Ptr) {
Device->second->Conn_.Address = "";
Device->second->WSConn_ = nullptr;
Device->second->Conn_.Connected = false;
Device->second->Conn_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
}
}
void DeviceRegistry::UnRegister(const std::string & SerialNumber, uint64_t ConnectionId) {
std::lock_guard Guard(Mutex_);
auto It = Devices_.find(SerialNumber);
if(It!=Devices_.end()) {
if(It->second->ConnectionId == ConnectionId)
Devices_.erase(SerialNumber);
}
}
bool DeviceRegistry::SendFrame(const std::string & SerialNumber, const std::string & Payload) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device!=Devices_.end() && Device->second->WSConn_!= nullptr) {
auto *WSConn =
static_cast<WSConnection *>(Device->second->WSConn_);
return WSConn->Send(Payload);
try {
return Device->second->WSConn_->Send(Payload);
} catch (...) {
Logger_.debug(Poco::format("Could not send data to device '%s'", SerialNumber));
Device->second->Conn_.Address = "";
Device->second->WSConn_ = nullptr;
Device->second->Conn_.Connected = false;
Device->second->Conn_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
}
}
return false;
}
void DeviceRegistry::SetPendingUUID(const std::string & SerialNumber, uint64_t PendingUUID) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device!=Devices_.end()) {
Device->second->Conn_.PendingUUID = PendingUUID;
@@ -237,7 +208,7 @@ namespace OpenWifi {
}
bool DeviceRegistry::AnalyzeRegistry(GWObjects::Dashboard &D) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
for(auto const &[SerialNumber,Connection]:Devices_) {
Types::UpdateCountedMap(D.status, Connection->Conn_.Connected ? "connected" : "not connected");

View File

@@ -6,13 +6,12 @@
// Arilia Wireless Inc.
//
#ifndef UCENTRAL_UDEVICEREGISTRY_H
#define UCENTRAL_UDEVICEREGISTRY_H
#pragma once
#include "Poco/JSON/Object.h"
#include "RESTAPI_GWobjects.h"
#include "SubSystemServer.h"
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "framework/MicroService.h"
// class uCentral::WebSocket::WSConnection;
@@ -26,12 +25,11 @@ namespace OpenWifi {
GWObjects::ConnectionState Conn_;
std::string LastStats;
GWObjects::HealthCheck LastHealthcheck;
uint64_t ConnectionId=0;
};
static DeviceRegistry *instance() {
if (instance_ == nullptr) {
instance_ = new DeviceRegistry;
}
static DeviceRegistry *instance_ = new DeviceRegistry;
return instance_;
}
@@ -43,24 +41,24 @@ namespace OpenWifi {
void SetState(const std::string & SerialNumber, GWObjects::ConnectionState & State);
bool GetHealthcheck(const std::string &SerialNumber, GWObjects::HealthCheck & CheckData);
void SetHealthcheck(const std::string &SerialNumber, const GWObjects::HealthCheck &H);
GWObjects::ConnectionState * Register(const std::string & SerialNumber, WSConnection *);
void UnRegister(const std::string & SerialNumber, WSConnection *);
std::shared_ptr<ConnectionEntry> Register(const std::string & SerialNumber, WSConnection *, uint64_t & ConnectionId);
void UnRegister(const std::string & SerialNumber, uint64_t ConnectionId);
bool SendCommand(GWObjects::CommandDetails & Command);
bool Connected(const std::string & SerialNumber);
bool SendFrame(const std::string & SerialNumber, const std::string & Payload);
void SetPendingUUID(const std::string & SerialNumber, uint64_t PendingUUID);
bool AnalyzeRegistry(GWObjects::Dashboard &D);
private:
static DeviceRegistry *instance_;
std::map<std::string,std::unique_ptr<ConnectionEntry>> Devices_;
inline static std::atomic_uint64_t Id_=1;
std::map<std::string,std::shared_ptr<ConnectionEntry>> Devices_;
DeviceRegistry() noexcept;
DeviceRegistry() noexcept:
SubSystemServer("DeviceRegistry", "DevStatus", "devicestatus") {
}
};
inline DeviceRegistry * DeviceRegistry() { return DeviceRegistry::instance(); }
} // namespace
#endif //UCENTRAL_UDEVICEREGISTRY_H

View File

@@ -10,10 +10,6 @@
#include <fstream>
#include <cstdio>
#include "Daemon.h"
#include "FileUploader.h"
#include "StorageService.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/DynamicAny.h"
@@ -24,35 +20,34 @@
#include "Poco/StreamCopier.h"
#include "Poco/Exception.h"
#include "Utils.h"
#include "FileUploader.h"
#include "StorageService.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class FileUploader *FileUploader::instance_ = nullptr;
static const std::string URI_BASE{"/v1/upload/"};
int FileUploader::Start() {
Logger_.notice("Starting.");
Poco::File UploadsDir(MicroService::instance().ConfigPath("openwifi.fileuploader.path","/tmp"));
Path_ = UploadsDir.path();
if(!UploadsDir.exists()) {
try {
UploadsDir.createDirectory();
} catch (const Poco::Exception &E) {
Logger_.log(E);
Path_ = "/tmp";
}
}
for(const auto & Svr: ConfigServersList_) {
std::string l{"Starting: " +
Svr.Address() + ":" + std::to_string(Svr.Port()) +
" key:" + Svr.KeyFile() +
" cert:" + Svr.CertFile()};
Logger_.information(l);
Poco::File UploadsDir(Daemon()->ConfigPath("ucentral.fileuploader.path","/tmp"));
Path_ = UploadsDir.path();
if(!UploadsDir.exists()) {
try {
UploadsDir.createDirectory();
} catch (const Poco::Exception &E) {
Logger_.log(E);
Path_ = "/tmp";
}
}
auto Sock{Svr.CreateSecureSocket(Logger_)};
Svr.LogCert(Logger_);
@@ -64,26 +59,40 @@ namespace OpenWifi {
Params->setMaxQueued(100);
if(FullName_.empty()) {
FullName_ = "https://" + Svr.Name() + ":" + std::to_string(Svr.Port()) + URI_BASE;
Logger_.information(Poco::format("Uploader URI base is '%s'", FullName_));
std::string TmpName = MicroService::instance().ConfigGetString("openwifi.fileuploader.uri","");
if(TmpName.empty()) {
FullName_ =
"https://" + Svr.Name() + ":" + std::to_string(Svr.Port()) + URI_BASE;
} else {
FullName_ = TmpName + URI_BASE ;
}
Logger_.information(Poco::format("Uploader URI base is '%s'", FullName_));
}
auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new FileUpLoaderRequestHandlerFactory(Logger_), Pool_, Sock, Params);
NewServer->start();
Servers_.push_back(std::move(NewServer));
}
MaxSize_ = 1000 * Daemon()->ConfigGetInt("ucentral.fileuploader.maxsize", 10000);
MaxSize_ = 1000 * MicroService::instance().ConfigGetInt("openwifi.fileuploader.maxsize", 10000);
return 0;
}
void FileUploader::reinitialize(Poco::Util::Application &self) {
MicroService::instance().LoadConfigurationFile();
Logger_.information("Reinitializing.");
Stop();
Start();
}
const std::string & FileUploader::FullName() {
return FullName_;
}
// if you pass in an empty UUID, it will just clean the list and not add it.
bool FileUploader::AddUUID( const std::string & UUID) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
uint64_t Now = time(nullptr) ;
@@ -102,13 +111,13 @@ namespace OpenWifi {
}
bool FileUploader::ValidRequest(const std::string &UUID) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
return OutStandingUploads_.find(UUID)!=OutStandingUploads_.end();
}
void FileUploader::RemoveRequest(const std::string &UUID) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
OutStandingUploads_.erase(UUID);
}
@@ -133,19 +142,19 @@ namespace OpenWifi {
Name_ = Parameters.get("filename", "(unnamed)");
}
Poco::TemporaryFile TmpFile;
std::string FinalFileName = FileUploader()->Path() + "/" + UUID_;
Logger_.information(Poco::format("FILE-UPLOADER: uploading trace for %s", UUID_));
Logger_.information(Poco::format("FILE-UPLOADER: uploading trace for %s", FinalFileName));
Poco::CountingInputStream InputStream(Stream);
std::ofstream OutputStream(TmpFile.path(), std::ofstream::out);
std::ofstream OutputStream(FinalFileName, std::ofstream::out);
Poco::StreamCopier::copyStream(InputStream, OutputStream);
Length_ = TmpFile.getSize();
Poco::File TmpFile(FinalFileName);
Length_ = TmpFile.getSize();
if (Length_ < FileUploader()->MaxSize()) {
rename(TmpFile.path().c_str(), FinalFileName.c_str());
Good_=true;
} else {
TmpFile.remove();
Error_ = "File is too large.";
}
return;
@@ -193,12 +202,12 @@ namespace OpenWifi {
if (partHandler.Good()) {
Answer.set("filename", UUID_);
Answer.set("error", 0);
Storage()->AttachFileToCommand(UUID_);
StorageService()->AttachFileToCommand(UUID_);
} else {
Answer.set("filename", UUID_);
Answer.set("error", 13);
Answer.set("errorText", partHandler.Error() );
Storage()->CancelWaitFile(UUID_, partHandler.Error() );
StorageService()->CancelWaitFile(UUID_, partHandler.Error() );
}
std::ostream &ResponseStream = Response.send();
Poco::JSON::Stringifier::stringify(Answer, ResponseStream);
@@ -245,6 +254,7 @@ namespace OpenWifi {
Logger_.notice("Stopping ");
for( const auto & svr : Servers_ )
svr->stop();
Servers_.clear();
}
} // Namespace

View File

@@ -9,13 +9,12 @@
#ifndef UCENTRAL_UFILEUPLOADER_H
#define UCENTRAL_UFILEUPLOADER_H
#include "SubSystemServer.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "RESTAPI_handler.h"
#include "framework/MicroService.h"
namespace OpenWifi {
@@ -23,6 +22,7 @@ namespace OpenWifi {
public:
int Start() override;
void Stop() override;
void reinitialize(Poco::Util::Application &self) override;
const std::string & FullName();
bool AddUUID( const std::string & UUID);
bool ValidRequest(const std::string & UUID);
@@ -30,16 +30,13 @@ namespace OpenWifi {
const std::string & Path() { return Path_; };
static FileUploader *instance() {
if (instance_ == nullptr) {
instance_ = new FileUploader;
}
return instance_;
static FileUploader * instance_ = new FileUploader;
return instance_;
}
[[nodiscard]] inline uint64_t MaxSize() const { return MaxSize_; }
private:
static FileUploader *instance_;
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> Servers_;
Poco::ThreadPool Pool_;
std::string FullName_;
@@ -48,9 +45,8 @@ namespace OpenWifi {
uint64_t MaxSize_=10000000;
explicit FileUploader() noexcept:
SubSystemServer("FileUploader", "FILE-UPLOAD", "ucentral.fileuploader")
SubSystemServer("FileUploader", "FILE-UPLOAD", "openwifi.fileuploader")
{
SubMutexGuard Guard(Mutex_);
}
};

View File

@@ -1,221 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include <thread>
#include "KafkaManager.h"
#include "Daemon.h"
#include "Utils.h"
namespace OpenWifi {
class KafkaManager *KafkaManager::instance_ = nullptr;
KafkaManager::KafkaManager() noexcept:
SubSystemServer("KafkaManager", "KAFKA-SVR", "ucentral.kafka")
{
}
void KafkaManager::initialize(Poco::Util::Application & self) {
SubSystemServer::initialize(self);
KafkaEnabled_ = Daemon()->ConfigGetBool("ucentral.kafka.enable",false);
}
#ifdef SMALL_BUILD
int KafkaManager::Start() {
return 0;
}
void KafkaManager::Stop() {
}
#else
int KafkaManager::Start() {
if(!KafkaEnabled_)
return 0;
ProducerThr_ = std::make_unique<std::thread>([this]() { this->ProducerThr(); });
ConsumerThr_ = std::make_unique<std::thread>([this]() { this->ConsumerThr(); });
return 0;
}
void KafkaManager::Stop() {
if(KafkaEnabled_) {
ProducerRunning_ = ConsumerRunning_ = false;
ProducerThr_->join();
ConsumerThr_->join();
return;
}
}
void KafkaManager::ProducerThr() {
cppkafka::Configuration Config({
{ "client.id", Daemon()->ConfigGetString("ucentral.kafka.client.id") },
{ "metadata.broker.list", Daemon()->ConfigGetString("ucentral.kafka.brokerlist") }
});
SystemInfoWrapper_ = R"lit({ "system" : { "id" : )lit" +
std::to_string(Daemon()->ID()) +
R"lit( , "host" : ")lit" + Daemon()->PrivateEndPoint() +
R"lit(" } , "payload" : )lit" ;
cppkafka::Producer Producer(Config);
ProducerRunning_ = true;
while(ProducerRunning_) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
try
{
SubMutexGuard G(ProducerMutex_);
auto Num=0;
while (!Queue_.empty()) {
const auto M = Queue_.front();
Producer.produce(
cppkafka::MessageBuilder(M.Topic).key(M.Key).payload(M.PayLoad));
Queue_.pop();
Num++;
}
if(Num)
Producer.flush();
} catch (const cppkafka::HandleException &E ) {
Logger_.warning(Poco::format("Caught a Kafka exception (producer): %s",std::string{E.what()}));
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
}
}
void KafkaManager::PartitionAssignment(const cppkafka::TopicPartitionList& partitions) {
Logger_.information(Poco::format("Partition assigned: %Lu...",(uint64_t )partitions.front().get_partition()));
}
void KafkaManager::PartitionRevocation(const cppkafka::TopicPartitionList& partitions) {
Logger_.information(Poco::format("Partition revocation: %Lu...",(uint64_t )partitions.front().get_partition()));
}
void KafkaManager::ConsumerThr() {
cppkafka::Configuration Config({
{ "client.id", Daemon()->ConfigGetString("ucentral.kafka.client.id") },
{ "metadata.broker.list", Daemon()->ConfigGetString("ucentral.kafka.brokerlist") },
{ "group.id", Daemon()->ConfigGetString("ucentral.kafka.group.id") },
{ "enable.auto.commit", Daemon()->ConfigGetBool("ucentral.kafka.auto.commit",false) },
{ "auto.offset.reset", "latest" } ,
{ "enable.partition.eof", false }
});
cppkafka::TopicConfiguration topic_config = {
{ "auto.offset.reset", "smallest" }
};
// Now configure it to be the default topic config
Config.set_default_topic_configuration(topic_config);
cppkafka::Consumer Consumer(Config);
Consumer.set_assignment_callback([this](cppkafka::TopicPartitionList& partitions) {
if(!partitions.empty()) {
Logger_.information(Poco::format("Partition assigned: %Lu...",
(uint64_t)partitions.front().get_partition()));
}
});
Consumer.set_revocation_callback([this](const cppkafka::TopicPartitionList& partitions) {
if(!partitions.empty()) {
Logger_.information(Poco::format("Partition revocation: %Lu...",
(uint64_t)partitions.front().get_partition()));
}
});
bool AutoCommit = Daemon()->ConfigGetBool("ucentral.kafka.auto.commit",false);
auto BatchSize = Daemon()->ConfigGetInt("ucentral.kafka.consumer.batchsize",20);
Types::StringVec Topics;
for(const auto &i:Notifiers_)
Topics.push_back(i.first);
Consumer.subscribe(Topics);
ConsumerRunning_ = true;
while(ConsumerRunning_) {
try {
std::vector<cppkafka::Message> MsgVec = Consumer.poll_batch(BatchSize, std::chrono::milliseconds(200));
for(auto const &Msg:MsgVec) {
if (!Msg)
continue;
if (Msg.get_error()) {
if (!Msg.is_eof()) {
Logger_.error(Poco::format("Error: %s", Msg.get_error().to_string()));
}if(!AutoCommit)
Consumer.async_commit(Msg);
continue;
}
SubMutexGuard G(ConsumerMutex_);
auto It = Notifiers_.find(Msg.get_topic());
if (It != Notifiers_.end()) {
Types::TopicNotifyFunctionList &FL = It->second;
std::string Key{Msg.get_key()};
std::string Payload{Msg.get_payload()};
for (auto &F : FL) {
std::thread T(F.first, Key, Payload);
T.detach();
}
}
if (!AutoCommit)
Consumer.async_commit(Msg);
}
} catch (const cppkafka::HandleException &E) {
Logger_.warning(Poco::format("Caught a Kafka exception (consumer): %s",std::string{E.what()}));
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
}
}
std::string KafkaManager::WrapSystemId(const std::string & PayLoad) {
return std::move( SystemInfoWrapper_ + PayLoad + "}");
}
void KafkaManager::PostMessage(std::string topic, std::string key, std::string PayLoad, bool WrapMessage ) {
if(KafkaEnabled_) {
SubMutexGuard G(Mutex_);
KMessage M{
.Topic = topic,
.Key = key,
.PayLoad = WrapMessage ? WrapSystemId(PayLoad) : PayLoad };
Queue_.push(M);
}
}
int KafkaManager::RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F) {
if(KafkaEnabled_) {
SubMutexGuard G(Mutex_);
auto It = Notifiers_.find(Topic);
if(It == Notifiers_.end()) {
Types::TopicNotifyFunctionList L;
L.emplace(L.end(),std::make_pair(F,FunctionId_));
Notifiers_[Topic] = std::move(L);
} else {
It->second.emplace(It->second.end(),std::make_pair(F,FunctionId_));
}
return FunctionId_++;
} else {
return 0;
}
}
void KafkaManager::UnregisterTopicWatcher(const std::string &Topic, int Id) {
if(KafkaEnabled_) {
SubMutexGuard G(Mutex_);
auto It = Notifiers_.find(Topic);
if(It != Notifiers_.end()) {
Types::TopicNotifyFunctionList & L = It->second;
for(auto it=L.begin(); it!=L.end(); it++)
if(it->second == Id) {
L.erase(it);
break;
}
}
}
}
#endif
} // namespace

View File

@@ -1,74 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#ifndef UCENTRALGW_KAFKAMANAGER_H
#define UCENTRALGW_KAFKAMANAGER_H
#include <queue>
#include <thread>
#include "SubSystemServer.h"
#include "OpenWifiTypes.h"
#include "cppkafka/cppkafka.h"
namespace OpenWifi {
class KafkaManager : public SubSystemServer {
public:
struct KMessage {
std::string Topic,
Key,
PayLoad;
};
void initialize(Poco::Util::Application & self) override;
static KafkaManager *instance() {
if(instance_== nullptr)
instance_ = new KafkaManager;
return instance_;
}
void ProducerThr();
void ConsumerThr();
int Start() override;
void Stop() override;
void PostMessage(std::string topic, std::string key, std::string payload, bool WrapMessage = true);
[[nodiscard]] std::string WrapSystemId(const std::string & PayLoad);
[[nodiscard]] bool Enabled() { return KafkaEnabled_; }
int RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction & F);
void UnregisterTopicWatcher(const std::string &Topic, int FunctionId);
void WakeUp();
void PartitionAssignment(const cppkafka::TopicPartitionList& partitions);
void PartitionRevocation(const cppkafka::TopicPartitionList& partitions);
private:
static KafkaManager *instance_;
SubMutex ProducerMutex_;
SubMutex ConsumerMutex_;
bool KafkaEnabled_ = false;
std::atomic_bool ProducerRunning_ = false;
std::atomic_bool ConsumerRunning_ = false;
std::queue<KMessage> Queue_;
std::string SystemInfoWrapper_;
std::unique_ptr<std::thread> ConsumerThr_;
std::unique_ptr<std::thread> ProducerThr_;
int FunctionId_=1;
Types::NotifyTable Notifiers_;
std::unique_ptr<cppkafka::Configuration> Config_;
KafkaManager() noexcept;
};
inline KafkaManager * KafkaManager() { return KafkaManager::instance(); }
} // NameSpace
#endif // UCENTRALGW_KAFKAMANAGER_H

View File

@@ -1,501 +0,0 @@
//
// Created by stephane bourque on 2021-06-22.
//
#include <cstdlib>
#include <boost/algorithm/string.hpp>
#include "Poco/Util/Application.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Environment.h"
#include "Poco/Net/HTTPSStreamFactory.h"
#include "Poco/Net/HTTPStreamFactory.h"
#include "Poco/Net/FTPSStreamFactory.h"
#include "Poco/Net/FTPStreamFactory.h"
#include "Poco/Path.h"
#include "Poco/File.h"
#include "Poco/String.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Stringifier.h"
#include "ALBHealthCheckServer.h"
#ifndef SMALL_BUILD
#include "KafkaManager.h"
#endif
#include "Kafka_topics.h"
#include "MicroService.h"
#include "Utils.h"
#ifndef TIP_SECURITY_SERVICE
#include "AuthClient.h"
#endif
namespace OpenWifi {
void MyErrorHandler::exception(const Poco::Exception & E) {
Poco::Thread * CurrentThread = Poco::Thread::current();
App_.logger().log(E);
App_.logger().error(Poco::format("Exception occurred in %s",CurrentThread->getName()));
}
void MyErrorHandler::exception(const std::exception & E) {
Poco::Thread * CurrentThread = Poco::Thread::current();
App_.logger().warning(Poco::format("std::exception on %s",CurrentThread->getName()));
}
void MyErrorHandler::exception() {
Poco::Thread * CurrentThread = Poco::Thread::current();
App_.logger().warning(Poco::format("exception on %s",CurrentThread->getName()));
}
void MicroService::Exit(int Reason) {
std::exit(Reason);
}
void MicroService::BusMessageReceived(const std::string &Key, const std::string & Message) {
SubMutexGuard G(InfraMutex_);
try {
Poco::JSON::Parser P;
auto Object = P.parse(Message).extract<Poco::JSON::Object::Ptr>();
if (Object->has(KafkaTopics::ServiceEvents::Fields::ID) &&
Object->has(KafkaTopics::ServiceEvents::Fields::EVENT)) {
uint64_t ID = Object->get(KafkaTopics::ServiceEvents::Fields::ID);
auto Event = Object->get(KafkaTopics::ServiceEvents::Fields::EVENT).toString();
if (ID != ID_) {
if( Event==KafkaTopics::ServiceEvents::EVENT_JOIN ||
Event==KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE ||
Event==KafkaTopics::ServiceEvents::EVENT_LEAVE ) {
if( Object->has(KafkaTopics::ServiceEvents::Fields::TYPE) &&
Object->has(KafkaTopics::ServiceEvents::Fields::PUBLIC) &&
Object->has(KafkaTopics::ServiceEvents::Fields::PRIVATE) &&
Object->has(KafkaTopics::ServiceEvents::Fields::VRSN) &&
Object->has(KafkaTopics::ServiceEvents::Fields::KEY)) {
if (Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE && Services_.find(ID) != Services_.end()) {
Services_[ID].LastUpdate = std::time(nullptr);
} else if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
Services_.erase(ID);
logger().information(Poco::format("Service %s ID=%Lu leaving system.",Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(),ID));
} else if (Event == KafkaTopics::ServiceEvents::EVENT_JOIN || Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE) {
logger().information(Poco::format("Service %s ID=%Lu joining system.",Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(),ID));
Services_[ID] = MicroServiceMeta{
.Id = ID,
.Type = Poco::toLower(Object->get(KafkaTopics::ServiceEvents::Fields::TYPE).toString()),
.PrivateEndPoint = Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(),
.PublicEndPoint = Object->get(KafkaTopics::ServiceEvents::Fields::PUBLIC).toString(),
.AccessKey = Object->get(KafkaTopics::ServiceEvents::Fields::KEY).toString(),
.Version = Object->get(KafkaTopics::ServiceEvents::Fields::VRSN).toString(),
.LastUpdate = (uint64_t)std::time(nullptr)};
for (const auto &[Id, Svc] : Services_) {
logger().information(Poco::format("ID: %Lu Type: %s EndPoint: %s",Id,Svc.Type,Svc.PrivateEndPoint));
}
}
} else {
logger().error(Poco::format("KAFKA-MSG: invalid event '%s', missing a field.",Event));
}
} else if (Event==KafkaTopics::ServiceEvents::EVENT_REMOVE_TOKEN) {
if(Object->has(KafkaTopics::ServiceEvents::Fields::TOKEN)) {
#ifndef TIP_SECURITY_SERVICE
AuthClient()->RemovedCachedToken(Object->get(KafkaTopics::ServiceEvents::Fields::TOKEN).toString());
#endif
} else {
logger().error(Poco::format("KAFKA-MSG: invalid event '%s', missing token",Event));
}
} else {
logger().error(Poco::format("Unknown Event: %s Source: %Lu", Event, ID));
}
}
} else {
logger().error("Bad bus message.");
}
auto i=Services_.begin();
auto Now = (uint64_t )std::time(nullptr);
for(;i!=Services_.end();) {
if((Now - i->second.LastUpdate)>60) {
i = Services_.erase(i);
} else
++i;
}
} catch (const Poco::Exception &E) {
logger().log(E);
}
}
MicroServiceMetaVec MicroService::GetServices(const std::string & Type) {
SubMutexGuard G(InfraMutex_);
auto T = Poco::toLower(Type);
MicroServiceMetaVec Res;
for(const auto &[Id,ServiceRec]:Services_) {
if(ServiceRec.Type==T)
Res.push_back(ServiceRec);
}
return Res;
}
MicroServiceMetaVec MicroService::GetServices() {
SubMutexGuard G(InfraMutex_);
MicroServiceMetaVec Res;
for(const auto &[Id,ServiceRec]:Services_) {
Res.push_back(ServiceRec);
}
return Res;
}
void MicroService::initialize(Poco::Util::Application &self) {
// add the default services
SubSystems_.push_back(KafkaManager());
SubSystems_.push_back(ALBHealthCheckServer());
Poco::Net::initializeSSL();
Poco::Net::HTTPStreamFactory::registerFactory();
Poco::Net::HTTPSStreamFactory::registerFactory();
Poco::Net::FTPStreamFactory::registerFactory();
Poco::Net::FTPSStreamFactory::registerFactory();
std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR,".");
Poco::Path ConfigFile;
ConfigFile = ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
if(!ConfigFile.isFile())
{
std::cerr << DAEMON_APP_NAME << ": Configuration "
<< ConfigFile.toString() << " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR
+ " env variable the path of the " + DAEMON_PROPERTIES_FILENAME + " file." << std::endl;
std::exit(Poco::Util::Application::EXIT_CONFIG);
}
static const char * LogFilePathKey = "logging.channels.c2.path";
loadConfiguration(ConfigFile.toString());
if(LogDir_.empty()) {
std::string OriginalLogFileValue = ConfigPath(LogFilePathKey);
config().setString(LogFilePathKey, OriginalLogFileValue);
} else {
config().setString(LogFilePathKey, LogDir_);
}
Poco::File DataDir(ConfigPath("ucentral.system.data"));
DataDir_ = DataDir.path();
if(!DataDir.exists()) {
try {
DataDir.createDirectory();
} catch (const Poco::Exception &E) {
logger().log(E);
}
}
std::string KeyFile = ConfigPath("ucentral.service.key");
std::string KeyFilePassword = ConfigPath("ucentral.service.key.password" , "" );
AppKey_ = Poco::SharedPtr<Poco::Crypto::RSAKey>(new Poco::Crypto::RSAKey("", KeyFile, KeyFilePassword));
Cipher_ = CipherFactory_.createCipher(*AppKey_);
ID_ = Utils::GetSystemId();
if(!DebugMode_)
DebugMode_ = ConfigGetBool("ucentral.system.debug",false);
MyPrivateEndPoint_ = ConfigGetString("ucentral.system.uri.private");
MyPublicEndPoint_ = ConfigGetString("ucentral.system.uri.public");
UIURI_ = ConfigGetString("ucentral.system.uri.ui");
MyHash_ = CreateHash(MyPublicEndPoint_);
InitializeSubSystemServers();
ServerApplication::initialize(self);
Types::TopicNotifyFunction F = [this](std::string s1,std::string s2) { this->BusMessageReceived(s1,s2); };
KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
}
void MicroService::uninitialize() {
// add your own uninitialization code here
ServerApplication::uninitialize();
}
void MicroService::reinitialize(Poco::Util::Application &self) {
ServerApplication::reinitialize(self);
// add your own reinitialization code here
}
void MicroService::defineOptions(Poco::Util::OptionSet &options) {
ServerApplication::defineOptions(options);
options.addOption(
Poco::Util::Option("help", "", "display help information on command line arguments")
.required(false)
.repeatable(false)
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleHelp)));
options.addOption(
Poco::Util::Option("file", "", "specify the configuration file")
.required(false)
.repeatable(false)
.argument("file")
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleConfig)));
options.addOption(
Poco::Util::Option("debug", "", "to run in debug, set to true")
.required(false)
.repeatable(false)
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleDebug)));
options.addOption(
Poco::Util::Option("logs", "", "specify the log directory and file (i.e. dir/file.log)")
.required(false)
.repeatable(false)
.argument("dir")
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleLogs)));
options.addOption(
Poco::Util::Option("version", "", "get the version and quit.")
.required(false)
.repeatable(false)
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleVersion)));
}
void MicroService::handleHelp(const std::string &name, const std::string &value) {
HelpRequested_ = true;
displayHelp();
stopOptionsProcessing();
}
void MicroService::handleVersion(const std::string &name, const std::string &value) {
HelpRequested_ = true;
std::cout << Version() << std::endl;
stopOptionsProcessing();
}
void MicroService::handleDebug(const std::string &name, const std::string &value) {
if(value == "true")
DebugMode_ = true ;
}
void MicroService::handleLogs(const std::string &name, const std::string &value) {
LogDir_ = value;
}
void MicroService::handleConfig(const std::string &name, const std::string &value) {
ConfigFileName_ = value;
}
void MicroService::displayHelp() {
Poco::Util::HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("A " + DAEMON_APP_NAME + " implementation for TIP.");
helpFormatter.format(std::cout);
}
void MicroService::InitializeSubSystemServers() {
for(auto i:SubSystems_)
addSubsystem(i);
}
void MicroService::StartSubSystemServers() {
for(auto i:SubSystems_) {
i->Start();
}
BusEventManager_.Start();
}
void MicroService::StopSubSystemServers() {
BusEventManager_.Stop();
for(auto i=SubSystems_.rbegin(); i!=SubSystems_.rend(); ++i)
(*i)->Stop();
}
std::string MicroService::CreateUUID() {
return UUIDGenerator_.create().toString();
}
bool MicroService::SetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level) {
try {
auto P = Poco::Logger::parseLevel(Level);
auto Sub = Poco::toLower(SubSystem);
if (Sub == "all") {
for (auto i : SubSystems_) {
i->Logger().setLevel(P);
}
return true;
} else {
// std::cout << "Sub:" << SubSystem << " Level:" << Level << std::endl;
for (auto i : SubSystems_) {
if (Sub == Poco::toLower(i->Name())) {
i->Logger().setLevel(P);
return true;
}
}
}
} catch (const Poco::Exception & E) {
std::cout << "Exception" << std::endl;
}
return false;
}
Types::StringVec MicroService::GetSubSystems() const {
Types::StringVec Result;
for(auto i:SubSystems_)
Result.push_back(i->Name());
return Result;
}
Types::StringPairVec MicroService::GetLogLevels() const {
Types::StringPairVec Result;
for(auto &i:SubSystems_) {
auto P = std::make_pair( i->Name(), Utils::LogLevelToString(i->GetLoggingLevel()));
Result.push_back(P);
}
return Result;
}
const Types::StringVec & MicroService::GetLogLevelNames() const {
static Types::StringVec LevelNames{"none", "fatal", "critical", "error", "warning", "notice", "information", "debug", "trace" };
return LevelNames;
}
uint64_t MicroService::ConfigGetInt(const std::string &Key,uint64_t Default) {
return (uint64_t) config().getInt64(Key,Default);
}
uint64_t MicroService::ConfigGetInt(const std::string &Key) {
return config().getInt(Key);
}
uint64_t MicroService::ConfigGetBool(const std::string &Key,bool Default) {
return config().getBool(Key,Default);
}
uint64_t MicroService::ConfigGetBool(const std::string &Key) {
return config().getBool(Key);
}
std::string MicroService::ConfigGetString(const std::string &Key,const std::string & Default) {
return config().getString(Key, Default);
}
std::string MicroService::ConfigGetString(const std::string &Key) {
return config().getString(Key);
}
std::string MicroService::ConfigPath(const std::string &Key,const std::string & Default) {
std::string R = config().getString(Key, Default);
return Poco::Path::expand(R);
}
std::string MicroService::ConfigPath(const std::string &Key) {
std::string R = config().getString(Key);
return Poco::Path::expand(R);
}
std::string MicroService::Encrypt(const std::string &S) {
return Cipher_->encryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);;
}
std::string MicroService::Decrypt(const std::string &S) {
return Cipher_->decryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);;
}
std::string MicroService::CreateHash(const std::string &S) {
SHA2_.update(S);
return Utils::ToHex(SHA2_.digest());
}
std::string MicroService::MakeSystemEventMessage( const std::string & Type ) const {
Poco::JSON::Object Obj;
Obj.set(KafkaTopics::ServiceEvents::Fields::EVENT,Type);
Obj.set(KafkaTopics::ServiceEvents::Fields::ID,ID_);
Obj.set(KafkaTopics::ServiceEvents::Fields::TYPE,Poco::toLower(DAEMON_APP_NAME));
Obj.set(KafkaTopics::ServiceEvents::Fields::PUBLIC,MyPublicEndPoint_);
Obj.set(KafkaTopics::ServiceEvents::Fields::PRIVATE,MyPrivateEndPoint_);
Obj.set(KafkaTopics::ServiceEvents::Fields::KEY,MyHash_);
Obj.set(KafkaTopics::ServiceEvents::Fields::VRSN,Version_);
std::stringstream ResultText;
Poco::JSON::Stringifier::stringify(Obj, ResultText);
return ResultText.str();
}
void BusEventManager::run() {
Running_ = true;
auto Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_JOIN);
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,Daemon()->PrivateEndPoint(),Msg, false);
while(Running_) {
Poco::Thread::trySleep((unsigned long)Daemon()->DaemonBusTimer());
if(!Running_)
break;
auto Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE);
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,Daemon()->PrivateEndPoint(),Msg, false);
}
Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_LEAVE);
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,Daemon()->PrivateEndPoint(),Msg, false);
};
void BusEventManager::Start() {
if(KafkaManager()->Enabled()) {
Thread_.start(*this);
}
}
void BusEventManager::Stop() {
if(KafkaManager()->Enabled()) {
Running_ = false;
Thread_.wakeUp();
Thread_.join();
}
}
[[nodiscard]] bool MicroService::IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request) {
try {
auto APIKEY = Request.get("X-API-KEY");
return APIKEY == MyHash_;
} catch (const Poco::Exception &E) {
logger().log(E);
}
return false;
}
void MicroService::SavePID() {
try {
std::ofstream O;
O.open(Daemon()->DataDir() + "/pidfile",std::ios::binary | std::ios::trunc);
O << Poco::Process::id();
O.close();
} catch (...)
{
std::cout << "Could not save system ID" << std::endl;
}
}
int MicroService::main(const ArgVec &args) {
MyErrorHandler ErrorHandler(*this);
Poco::ErrorHandler::set(&ErrorHandler);
if (!HelpRequested_) {
SavePID();
Poco::Logger &logger = Poco::Logger::get(DAEMON_APP_NAME);
logger.notice(Poco::format("Starting %s version %s.",DAEMON_APP_NAME, Version()));
if(Poco::Net::Socket::supportsIPv6())
logger.information("System supports IPv6.");
else
logger.information("System does NOT support IPv6.");
if (config().getBool("application.runAsDaemon", false)) {
logger.information("Starting as a daemon.");
}
logger.information(Poco::format("System ID set to %Lu",ID_));
StartSubSystemServers();
waitForTerminationRequest();
StopSubSystemServers();
logger.notice(Poco::format("Stopped %s...",DAEMON_APP_NAME));
}
return Application::EXIT_OK;
}
}

View File

@@ -1,174 +0,0 @@
//
// Created by stephane bourque on 2021-06-22.
//
#ifndef UCENTRALGW_MICROSERVICE_H
#define UCENTRALGW_MICROSERVICE_H
#include <array>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <set>
#include "Poco/Util/Application.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/UUIDGenerator.h"
#include "Poco/ErrorHandler.h"
#include "Poco/Crypto/RSAKey.h"
#include "Poco/Crypto/CipherFactory.h"
#include "Poco/Crypto/Cipher.h"
#include "Poco/SHA2Engine.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Process.h"
#include "OpenWifiTypes.h"
#include "SubSystemServer.h"
namespace OpenWifi {
static const std::string uSERVICE_SECURITY{"ucentralsec"};
static const std::string uSERVICE_GATEWAY{"ucentralgw"};
static const std::string uSERVICE_FIRMWARE{ "ucentralfms"};
static const std::string uSERVICE_TOPOLOGY{ "owtopo"};
static const std::string uSERVICE_PROVISIONING{ "owprov"};
class MyErrorHandler : public Poco::ErrorHandler {
public:
explicit MyErrorHandler(Poco::Util::Application &App) : App_(App) {}
void exception(const Poco::Exception & E) override;
void exception(const std::exception & E) override;
void exception() override;
private:
Poco::Util::Application &App_;
};
class BusEventManager : public Poco::Runnable {
public:
void run() override;
void Start();
void Stop();
private:
std::atomic_bool Running_ = false;
Poco::Thread Thread_;
};
struct MicroServiceMeta {
uint64_t Id=0;
std::string Type;
std::string PrivateEndPoint;
std::string PublicEndPoint;
std::string AccessKey;
std::string Version;
uint64_t LastUpdate=0;
};
typedef std::map<uint64_t, MicroServiceMeta> MicroServiceMetaMap;
typedef std::vector<MicroServiceMeta> MicroServiceMetaVec;
class MicroService : public Poco::Util::ServerApplication {
public:
explicit MicroService( std::string PropFile,
std::string RootEnv,
std::string ConfigVar,
std::string AppName,
uint64_t BusTimer,
Types::SubSystemVec Subsystems) :
DAEMON_PROPERTIES_FILENAME(std::move(PropFile)),
DAEMON_ROOT_ENV_VAR(std::move(RootEnv)),
DAEMON_CONFIG_ENV_VAR(std::move(ConfigVar)),
DAEMON_APP_NAME(std::move(AppName)),
DAEMON_BUS_TIMER(BusTimer),
SubSystems_(std::move(Subsystems)) {
std::string V{APP_VERSION};
std::string B{BUILD_NUMBER};
Version_ = V + "(" + B + ")";
}
int main(const ArgVec &args) override;
void initialize(Application &self) override;
void uninitialize() override;
void reinitialize(Application &self) override;
void defineOptions(Poco::Util::OptionSet &options) override;
void handleHelp(const std::string &name, const std::string &value);
void handleVersion(const std::string &name, const std::string &value);
void handleDebug(const std::string &name, const std::string &value);
void handleLogs(const std::string &name, const std::string &value);
void handleConfig(const std::string &name, const std::string &value);
void displayHelp();
void InitializeSubSystemServers();
void StartSubSystemServers();
void StopSubSystemServers();
void Exit(int Reason);
bool SetSubsystemLogLevel(const std::string & SubSystem, const std::string & Level);
[[nodiscard]] std::string Version() { return Version_; }
[[nodiscard]] const Poco::SharedPtr<Poco::Crypto::RSAKey> & Key() { return AppKey_; }
[[nodiscard]] inline const std::string & DataDir() { return DataDir_; }
[[nodiscard]] std::string CreateUUID();
[[nodiscard]] bool Debug() const { return DebugMode_; }
[[nodiscard]] uint64_t ID() const { return ID_; }
[[nodiscard]] Types::StringVec GetSubSystems() const;
[[nodiscard]] Types::StringPairVec GetLogLevels() const;
[[nodiscard]] const Types::StringVec & GetLogLevelNames() const;
[[nodiscard]] std::string ConfigGetString(const std::string &Key,const std::string & Default);
[[nodiscard]] std::string ConfigGetString(const std::string &Key);
[[nodiscard]] std::string ConfigPath(const std::string &Key,const std::string & Default);
[[nodiscard]] std::string ConfigPath(const std::string &Key);
[[nodiscard]] uint64_t ConfigGetInt(const std::string &Key,uint64_t Default);
[[nodiscard]] uint64_t ConfigGetInt(const std::string &Key);
[[nodiscard]] uint64_t ConfigGetBool(const std::string &Key,bool Default);
[[nodiscard]] uint64_t ConfigGetBool(const std::string &Key);
[[nodiscard]] std::string Encrypt(const std::string &S);
[[nodiscard]] std::string Decrypt(const std::string &S);
[[nodiscard]] std::string CreateHash(const std::string &S);
[[nodiscard]] std::string Hash() const { return MyHash_; };
[[nodiscard]] std::string ServiceType() const { return DAEMON_APP_NAME; };
[[nodiscard]] std::string PrivateEndPoint() const { return MyPrivateEndPoint_; };
[[nodiscard]] std::string PublicEndPoint() const { return MyPublicEndPoint_; };
[[nodiscard]] std::string MakeSystemEventMessage( const std::string & Type ) const ;
inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; };
void BusMessageReceived( const std::string & Key, const std::string & Message);
[[nodiscard]] MicroServiceMetaVec GetServices(const std::string & type);
[[nodiscard]] MicroServiceMetaVec GetServices();
[[nodiscard]] bool IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request);
void SavePID();
inline uint64_t GetPID() { return Poco::Process::id(); };
[[nodiscard]] inline const std::string GetPublicAPIEndPoint() const { return MyPublicEndPoint_ + "/api/v1"; };
[[nodiscard]] inline const std::string & GetUIURI() const { return UIURI_;};
private:
bool HelpRequested_ = false;
std::string LogDir_;
std::string ConfigFileName_;
Poco::UUIDGenerator UUIDGenerator_;
uint64_t ID_ = 1;
Poco::SharedPtr<Poco::Crypto::RSAKey> AppKey_ = nullptr;
bool DebugMode_ = false;
std::string DataDir_;
Types::SubSystemVec SubSystems_;
Poco::Crypto::CipherFactory & CipherFactory_ = Poco::Crypto::CipherFactory::defaultFactory();
Poco::Crypto::Cipher * Cipher_ = nullptr;
Poco::SHA2Engine SHA2_;
MicroServiceMetaMap Services_;
std::string MyHash_;
std::string MyPrivateEndPoint_;
std::string MyPublicEndPoint_;
std::string UIURI_;
std::string Version_;
BusEventManager BusEventManager_;
SubMutex InfraMutex_;
std::string DAEMON_PROPERTIES_FILENAME;
std::string DAEMON_ROOT_ENV_VAR;
std::string DAEMON_CONFIG_ENV_VAR;
std::string DAEMON_APP_NAME;
uint64_t DAEMON_BUS_TIMER;
};
}
#endif // UCENTRALGW_MICROSERVICE_H

View File

@@ -6,7 +6,6 @@
#include <vector>
#include "OUIServer.h"
#include "Daemon.h"
#include "Poco/String.h"
#include "Poco/StringTokenizer.h"
@@ -15,10 +14,10 @@
#include "Poco/URI.h"
#include "Poco/File.h"
#include "Utils.h"
#include "OUIServer.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class OUIServer * OUIServer::instance_;
int OUIServer::Start() {
Running_=true;
@@ -38,10 +37,17 @@ namespace OpenWifi {
Updater.detach();
}
void OUIServer::reinitialize(Poco::Util::Application &self) {
MicroService::instance().LoadConfigurationFile();
Logger_.information("Reinitializing.");
Stop();
Start();
}
bool OUIServer::GetFile(const std::string &FileName) {
try {
std::unique_ptr<std::istream> pStr(
Poco::URIStreamOpener::defaultOpener().open(Daemon()->ConfigGetString("oui.download.uri")));
Poco::URIStreamOpener::defaultOpener().open(MicroService::instance().ConfigGetString("oui.download.uri")));
std::ofstream OS;
Poco::File F(FileName);
if(F.exists())
@@ -97,12 +103,12 @@ namespace OpenWifi {
Updating_ = true;
// fetch data from server, if not available, just use the file we already have.
std::string LatestOUIFileName{ Daemon()->DataDir() + "/newOUIFile.txt"};
std::string CurrentOUIFileName{ Daemon()->DataDir() + "/current_oui.txt"};
std::string LatestOUIFileName{ MicroService::instance().DataDir() + "/newOUIFile.txt"};
std::string CurrentOUIFileName{ MicroService::instance().DataDir() + "/current_oui.txt"};
OUIMap TmpOUIs;
if(GetFile(LatestOUIFileName) && ProcessFile(LatestOUIFileName, TmpOUIs)) {
SubMutexGuard G(Mutex_);
std::lock_guard G(Mutex_);
OUIs_ = std::move(TmpOUIs);
LastUpdate_ = time(nullptr);
Poco::File F1(CurrentOUIFileName);
@@ -114,7 +120,7 @@ namespace OpenWifi {
} else if(OUIs_.empty()) {
if(ProcessFile(CurrentOUIFileName, TmpOUIs)) {
LastUpdate_ = time(nullptr);
SubMutexGuard G(Mutex_);
std::lock_guard G(Mutex_);
OUIs_ = std::move(TmpOUIs);
}
}
@@ -122,7 +128,7 @@ namespace OpenWifi {
}
std::string OUIServer::GetManufacturer(const std::string &MAC) {
SubMutexGuard Guard(Mutex_);
std::lock_guard Guard(Mutex_);
auto Manufacturer = OUIs_.find(Utils::SerialNumberToOUI(MAC));
if(Manufacturer != OUIs_.end())
return Manufacturer->second;

View File

@@ -5,7 +5,7 @@
#ifndef UCENTRALGW_OUISERVER_H
#define UCENTRALGW_OUISERVER_H
#include "SubSystemServer.h"
#include "framework/MicroService.h"
namespace OpenWifi {
@@ -15,14 +15,15 @@ namespace OpenWifi {
typedef std::map<uint64_t,std::string> OUIMap;
static OUIServer *instance() {
if (instance_ == nullptr) {
instance_ = new OUIServer;
}
static OUIServer *instance_ = new OUIServer;
return instance_;
}
int Start() override;
void Stop() override;
void reinitialize(Poco::Util::Application &self) override;
void Update();
void UpdateImpl();
[[nodiscard]] std::string GetManufacturer(const std::string &MAC);
@@ -30,7 +31,6 @@ namespace OpenWifi {
[[nodiscard]] bool ProcessFile(const std::string &FileName, OUIMap &Map);
private:
static OUIServer * instance_;
uint64_t LastUpdate_ = 0 ;
bool ValidFile_=false;
OUIMap OUIs_;

View File

@@ -1,68 +0,0 @@
//
// Created by stephane bourque on 2021-07-01.
//
#include <iostream>
#include "OpenAPIRequest.h"
#include "Poco/Net/HTTPSClientSession.h"
#include <Poco/Net/HTTPClientSession.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/StreamCopier.h>
#include <Poco/JSON/Parser.h>
#include <Poco/Path.h>
#include <Poco/URI.h>
#include <Poco/Exception.h>
#include "Utils.h"
#include "Daemon.h"
namespace OpenWifi {
OpenAPIRequestGet::OpenAPIRequestGet( const std::string & ServiceType,
const std::string & EndPoint,
Types::StringPairVec & QueryData,
uint64_t msTimeout):
Type_(ServiceType),
EndPoint_(EndPoint),
QueryData_(QueryData),
msTimeout_(msTimeout) {
}
int OpenAPIRequestGet::Do(Poco::JSON::Object::Ptr &ResponseObject) {
try {
auto Services = Daemon()->GetServices(Type_);
for(auto const &Svc:Services) {
Poco::URI URI(Svc.PrivateEndPoint);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
URI.setPath(EndPoint_);
for (const auto &qp : QueryData_)
URI.addQueryParameter(qp.first, qp.second);
std::string Path(URI.getPathAndQuery());
Session.setTimeout(Poco::Timespan(msTimeout_/1000, msTimeout_ % 1000));
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET,
Path,
Poco::Net::HTTPMessage::HTTP_1_1);
Request.add("X-API-KEY", Svc.AccessKey);
Session.sendRequest(Request);
Poco::Net::HTTPResponse Response;
std::istream &is = Session.receiveResponse(Response);
if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) {
Poco::JSON::Parser P;
ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>();
}
return Response.getStatus();
}
}
catch (const Poco::Exception &E)
{
std::cerr << E.displayText() << std::endl;
}
return -1;
}
}

View File

@@ -1,29 +0,0 @@
//
// Created by stephane bourque on 2021-07-01.
//
#ifndef UCENTRALGW_OPENAPIREQUEST_H
#define UCENTRALGW_OPENAPIREQUEST_H
#include "Poco/JSON/Object.h"
#include "OpenWifiTypes.h"
namespace OpenWifi {
class OpenAPIRequestGet {
public:
explicit OpenAPIRequestGet( const std::string & Type,
const std::string & EndPoint,
Types::StringPairVec & QueryData,
uint64_t msTimeout);
int Do(Poco::JSON::Object::Ptr &ResponseObject);
private:
std::string Type_;
std::string EndPoint_;
Types::StringPairVec QueryData_;
uint64_t msTimeout_;
};
}
#endif // UCENTRALGW_OPENAPIREQUEST_H

View File

@@ -1,68 +0,0 @@
//
// Created by stephane bourque on 2021-06-13.
//
#ifndef UCENTRALGW_UCENTRALTYPES_H
#define UCENTRALGW_UCENTRALTYPES_H
#include "SubSystemServer.h"
#include <vector>
#include <string>
#include <map>
#include <functional>
#include <list>
#include <utility>
#include <queue>
#include "Poco/StringTokenizer.h"
namespace OpenWifi::Types {
typedef std::pair<std::string,std::string> StringPair;
typedef std::vector<StringPair> StringPairVec;
typedef std::queue<StringPair> StringPairQueue;
typedef std::vector<std::string> StringVec;
typedef std::set<std::string> StringSet;
typedef std::vector<SubSystemServer*> SubSystemVec;
typedef std::map<std::string,std::set<std::string>> StringMapStringSet;
typedef std::function<void(std::string, std::string)> TopicNotifyFunction;
typedef std::list<std::pair<TopicNotifyFunction,int>> TopicNotifyFunctionList;
typedef std::map<std::string, TopicNotifyFunctionList> NotifyTable;
typedef std::map<std::string,uint64_t> CountedMap;
typedef std::string UUID_t;
typedef std::vector<UUID_t> UUIDvec_t;
inline void UpdateCountedMap(CountedMap &M, const std::string &S, uint64_t Increment=1) {
auto it = M.find(S);
if(it==M.end())
M[S] = Increment;
else
it->second += Increment;
}
inline std::string to_string( const StringVec &V) {
std::string Result;
bool first=true;
for(const auto &i:V) {
if(first) {
Result += i;
first = false;
} else {
Result += ",";
Result += i;
}
}
return Result;
}
inline void from_string(const std::string &S, StringVec &V) {
Poco::StringTokenizer Tokens(S,",",Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY);
for(auto const &i:Tokens)
V.emplace_back(i);
}
};
#endif // UCENTRALGW_UCENTRALTYPES_H

118
src/RESTAPI/RESTAPI_RPC.cpp Normal file
View File

@@ -0,0 +1,118 @@
//
// Created by stephane bourque on 2021-06-28.
//
#include <cctype>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <future>
#include <numeric>
#include <chrono>
#include "RESTAPI_RPC.h"
#include "CommandManager.h"
#include "DeviceRegistry.h"
#include "StorageService.h"
#include "framework/uCentral_Protocol.h"
namespace OpenWifi::RESTAPI_RPC {
void SetCommandStatus(GWObjects::CommandDetails &Cmd,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response,
RESTAPIHandler *Handler,
OpenWifi::Storage::CommandExecutionType Status,
Poco::Logger &Logger) {
if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
Poco::JSON::Object RetObj;
Cmd.to_json(RetObj);
Handler->ReturnObject(RetObj);
return;
} else {
Handler->ReturnStatus(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
return;
}
}
void WaitForCommand(GWObjects::CommandDetails &Cmd,
Poco::JSON::Object & Params,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response,
int64_t WaitTimeInMs,
Poco::JSON::Object * ObjectToReturn,
RESTAPIHandler * Handler,
Poco::Logger &Logger) {
// if the command should be executed in the future, or if the device is not connected, then we should just add the command to
// the DB and let it figure out when to deliver the command.
if(Cmd.RunAt || !DeviceRegistry()->Connected(Cmd.SerialNumber)) {
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_PENDING, Logger);
return;
}
Cmd.Executed = std::time(nullptr);
uint64_t RPC_Id=0;
if (CommandManager()->SendCommand(Cmd.SerialNumber, Cmd.Command, Params, Cmd.UUID, RPC_Id)) {
CommandTag T;
while (CommandManager()->Running() && WaitTimeInMs > 0) {
if (CommandManager()->GetCommand(RPC_Id, Cmd.SerialNumber, T)) {
auto Answer = T.Result;
if (Answer->has("result") && Answer->isObject("result")) {
auto ResultFields =
Answer->get("result").extract<Poco::JSON::Object::Ptr>();
if (ResultFields->has("status") && ResultFields->isObject("status")) {
auto StatusInnerObj =
ResultFields->get("status").extract<Poco::JSON::Object::Ptr>();
if (StatusInnerObj->has("error"))
Cmd.ErrorCode = StatusInnerObj->get("error");
if (StatusInnerObj->has("text"))
Cmd.ErrorText = StatusInnerObj->get("text").toString();
std::stringstream ResultText;
Poco::JSON::Stringifier::stringify(Answer->get("result"), ResultText);
Cmd.Results = ResultText.str();
Cmd.Status = "completed";
Cmd.Completed = time(nullptr);
if (Cmd.ErrorCode && Cmd.Command == uCentralProtocol::TRACE) {
Cmd.WaitingForFile = 0;
Cmd.AttachDate = Cmd.AttachSize = 0;
Cmd.AttachType = "";
}
// Add the completed command to the database...
StorageService()->AddCommand(Cmd.SerialNumber, Cmd,
Storage::COMMAND_COMPLETED);
if (ObjectToReturn) {
Handler->ReturnObject(*ObjectToReturn);
} else {
Poco::JSON::Object O;
Cmd.to_json(O);
Handler->ReturnObject(O);
}
return;
} else {
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_FAILED, Logger);
Logger.information(Poco::format("Invalid response for command '%s'. Missing status.", Cmd.UUID));
return;
}
} else {
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_FAILED, Logger);
Logger.information(Poco::format("Invalid response for command '%s'. Missing result.", Cmd.UUID));
return;
}
} else {
Poco::Thread::trySleep(100);
WaitTimeInMs -= 100;
}
}
if(WaitTimeInMs<0)
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_TIMEDOUT, Logger);
else
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_PENDING, Logger);
} else {
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_PENDING, Logger);
}
}
}

View File

@@ -15,29 +15,27 @@
#include "Poco/File.h"
#include "Poco/JSON/Object.h"
#include "RESTAPI_GWobjects.h"
#include "RESTAPI_handler.h"
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "StorageService.h"
#include "framework/MicroService.h"
namespace OpenWifi::RESTAPI_RPC {
bool WaitForRPC(GWObjects::CommandDetails &Cmd,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response,
uint64_t Timeout,
bool ReturnObject,
RESTAPIHandler * Handler);
void WaitForCommand( GWObjects::CommandDetails &Cmd,
void WaitForCommand( GWObjects::CommandDetails &Cmd,
Poco::JSON::Object & Params,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response,
std::chrono::milliseconds D,
int64_t WaitTimeInMs,
Poco::JSON::Object * ObjectToReturn,
RESTAPIHandler * Handler);
RESTAPIHandler * Handler,
Poco::Logger &Logger);
void SetCommandStatus( GWObjects::CommandDetails &Cmd,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response, RESTAPIHandler * handler,
OpenWifi::Storage::CommandExecutionType Status,
Poco::Logger &Logger);
void SetCommandAsPending(GWObjects::CommandDetails &Cmd,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response, RESTAPIHandler * handler);
}
#endif // UCENTRALGW_RESTAPI_RPC_H

View File

@@ -0,0 +1,48 @@
//
// Created by stephane bourque on 2021-09-16.
//
#include "RESTAPI_TelemetryWebSocket.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Net/NetException.h"
#include "TelemetryStream.h"
namespace OpenWifi {
void RESTAPI_TelemetryWebSocket::DoGet() {
// try and upgrade this session to websocket...
if (Request->find("Upgrade") != Request->end() &&
Poco::icompare((*Request)["Upgrade"], "websocket") == 0) {
try {
Poco::URI U(Request->getURI());
std::string UUID, SerialNumber;
auto Parameters = U.getQueryParameters();
for (const auto &i : Parameters) {
if (i.first == "serialNumber") {
SerialNumber = i.second;
} else if(i.first=="uuid") {
UUID = i.second;
}
}
auto WS = Poco::SharedPtr<Poco::Net::WebSocket>( new Poco::Net::WebSocket(*Request, *Response));
new TelemetryClient(UUID, SerialNumber, WS, TelemetryStream()->NextReactor(), Logger_);
} catch (const Poco::Net::WebSocketException &E) {
Logger_.log(E);
switch (E.code()) {
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
Response->set("Sec-WebSocket-Version", Poco::Net::WebSocket::WEBSOCKET_VERSION);
// fallthrough
case Poco::Net::WebSocket::WS_ERR_NO_HANDSHAKE:
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_VERSION:
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_KEY:
Response->setStatusAndReason(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
Response->setContentLength(0);
Response->send();
break;
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
}
}
}

View File

@@ -0,0 +1,28 @@
//
// Created by stephane bourque on 2021-09-16.
//
#ifndef OWGW_RESTAPI_TELEMETRYWEBSOCKET_H
#define OWGW_RESTAPI_TELEMETRYWEBSOCKET_H
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_TelemetryWebSocket : public RESTAPIHandler {
public:
RESTAPI_TelemetryWebSocket(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{ Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, Internal,false) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/ws_telemetry"};}
void DoGet() final;
void DoDelete() final {};
void DoPost() final {};
void DoPut() final {};
private:
void Process(const Poco::JSON::Object::Ptr &O, std::string &Answer);
};
}
#endif // OWGW_RESTAPI_TELEMETRYWEBSOCKET_H

View File

@@ -0,0 +1,120 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include <ctime>
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Stringifier.h"
#include "RESTAPI_blacklist.h"
#include "StorageService.h"
#include "framework/RESTAPI_errors.h"
#include "framework/RESTAPI_protocol.h"
namespace OpenWifi {
void RESTAPI_blacklist::DoDelete() {
auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
GWObjects::BlackListedDevice D;
if(!StorageService()->GetBlackListDevice(SerialNumber, D)) {
return NotFound();
}
if (StorageService()->DeleteBlackListDevice(SerialNumber)) {
return OK();
}
BadRequest(RESTAPI::Errors::CouldNotBeDeleted);
}
void RESTAPI_blacklist::DoGet() {
auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
GWObjects::BlackListedDevice D;
if(!StorageService()->GetBlackListDevice(SerialNumber, D)) {
return NotFound();
}
Poco::JSON::Object Answer;
D.to_json(Answer);
return ReturnObject(Answer);
}
void RESTAPI_blacklist::DoPost() {
auto Obj = ParseStream();
GWObjects::BlackListedDevice D;
if(!D.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(D.serialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
Poco::toLowerInPlace(D.serialNumber);
if(StorageService()->IsBlackListed(D.serialNumber)) {
return BadRequest(RESTAPI::Errors::SerialNumberExists);
}
D.author = UserInfo_.userinfo.email;
D.created = std::time(nullptr);
if(StorageService()->AddBlackListDevice(D)) {
GWObjects::BlackListedDevice CreatedDevice;
StorageService()->GetBlackListDevice(D.serialNumber,CreatedDevice);
Poco::JSON::Object Answer;
CreatedDevice.to_json(Answer);
return ReturnObject(Answer);
}
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_blacklist::DoPut() {
auto SerialNumber = Poco::toLower(GetBinding(RESTAPI::Protocol::SERIALNUMBER, ""));
if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
auto Obj = ParseStream();
GWObjects::BlackListedDevice Existing;
if(!StorageService()->GetBlackListDevice(SerialNumber, Existing)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
GWObjects::BlackListedDevice NewDevice;
if(!NewDevice.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
Existing.reason = NewDevice.reason;
Existing.author = UserInfo_.userinfo.email;
if(StorageService()->UpdateBlackListDevice(SerialNumber, Existing)) {
GWObjects::BlackListedDevice CreatedDevice;
StorageService()->GetBlackListDevice(SerialNumber,CreatedDevice);
Poco::JSON::Object Answer;
CreatedDevice.to_json(Answer);
return ReturnObject(Answer);
}
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
}

View File

@@ -9,25 +9,25 @@
#ifndef UCENTRALGW_RESTAPI_BLACKLIST_H
#define UCENTRALGW_RESTAPI_BLACKLIST_H
#include "RESTAPI_handler.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_BlackList : public RESTAPIHandler {
class RESTAPI_blacklist : public RESTAPIHandler {
public:
RESTAPI_BlackList(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_blacklist(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_PUT,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
void DoGet(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response);
void DoDelete(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response);
void DoPost(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response);
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/blacklist"};}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/blacklist/{serialNumber}"};}
void DoGet() final;
void DoDelete() final;
void DoPost() final;
void DoPut() final;
};
}

View File

@@ -0,0 +1,28 @@
//
// Created by stephane bourque on 2021-10-14.
//
#include "RESTAPI_blacklist_list.h"
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Stringifier.h"
#include "StorageService.h"
namespace OpenWifi {
void RESTAPI_blacklist_list::DoGet() {
std::vector<GWObjects::BlackListedDevice> Devices;
Poco::JSON::Array Arr;
Poco::JSON::Object Answer;
if(StorageService()->GetBlackListDevices(QB_.Offset, QB_.Limit, Devices)) {
for(const auto &i:Devices) {
Poco::JSON::Object O;
i.to_json(O);
Arr.add(O);
}
}
Answer.set("devices", Arr);
return ReturnObject(Answer);
}
}

View File

@@ -0,0 +1,27 @@
//
// Created by stephane bourque on 2021-10-14.
//
#ifndef UCENTRALGW_RESTAPI_BLACKLIST_LIST_H
#define UCENTRALGW_RESTAPI_BLACKLIST_LIST_H
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_blacklist_list : public RESTAPIHandler {
public:
RESTAPI_blacklist_list(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/blacklist"};}
void DoGet() final;
void DoDelete() final {};
void DoPost() final {};
void DoPut() final {};
};
}
#endif // UCENTRALGW_RESTAPI_BLACKLIST_LIST_H

View File

@@ -0,0 +1,28 @@
//
// Created by stephane bourque on 2021-10-17.
//
#include "RESTAPI_capabilities_handler.h"
#include "StorageService.h"
namespace OpenWifi {
void RESTAPI_capabilities_handler::DoGet() {
Storage::DeviceCapabilitiesCache DevCaps;
StorageService()->GetDeviceCapabilitiesCache(DevCaps);
Poco::JSON::Array ObjArr;
for(const auto &[deviceType,capabilities]:DevCaps) {
Poco::JSON::Object Inner;
Inner.set("deviceType",deviceType);
Poco::JSON::Parser P;
auto R = P.parse(capabilities).extract<Poco::JSON::Object::Ptr>();
Inner.set("capabilities", R);
ObjArr.add(Inner);
}
Poco::JSON::Object Answer;
Answer.set("devices",ObjArr);
return ReturnObject(Answer);
}
}

View File

@@ -0,0 +1,26 @@
//
// Created by stephane bourque on 2021-10-17.
//
#ifndef UCENTRALGW_RESTAPI_CAPABILITIES_HANDLER_H
#define UCENTRALGW_RESTAPI_CAPABILITIES_HANDLER_H
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_capabilities_handler : public RESTAPIHandler {
public:
RESTAPI_capabilities_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/capabilities"};}
void DoGet() final;
void DoDelete() final {};
void DoPost() final {};
void DoPut() final {};
};
}
#endif // UCENTRALGW_RESTAPI_CAPABILITIES_HANDLER_H

View File

@@ -0,0 +1,44 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "RESTAPI_command.h"
#include "StorageService.h"
#include "framework/RESTAPI_errors.h"
#include "framework/RESTAPI_protocol.h"
namespace OpenWifi {
void RESTAPI_command::DoGet() {
auto CommandUUID = GetBinding(RESTAPI::Protocol::COMMANDUUID, "");
GWObjects::CommandDetails Command;
if (StorageService()->GetCommand(CommandUUID, Command)) {
Poco::JSON::Object RetObj;
Command.to_json(RetObj);
return ReturnObject(RetObj);
}
return NotFound();
}
void RESTAPI_command::DoDelete() {
auto UUID = GetBinding(RESTAPI::Protocol::COMMANDUUID, "");
if(UUID.empty()) {
return BadRequest(RESTAPI::Errors::MissingUUID);
}
GWObjects::CommandDetails C;
if(!StorageService()->GetCommand(UUID, C)) {
return NotFound();
}
if (StorageService()->DeleteCommand(UUID)) {
return OK();
}
return InternalError();
}
}

View File

@@ -9,21 +9,24 @@
#ifndef UCENTRAL_RESTAPI_COMMAND_H
#define UCENTRAL_RESTAPI_COMMAND_H
#include "RESTAPI_handler.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_command : public RESTAPIHandler {
public:
RESTAPI_command(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_command(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/command/{commandUUID}"};}
};
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/command/{commandUUID}"};}
void DoGet() final;
void DoDelete() final;
void DoPost() final {};
void DoPut() final {};
};
}
#endif //UCENTRAL_RESTAPI_COMMAND_H

View File

@@ -0,0 +1,46 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "RESTAPI_commands.h"
#include "StorageService.h"
#include "framework/RESTAPI_errors.h"
#include "framework/RESTAPI_protocol.h"
namespace OpenWifi {
void RESTAPI_commands::DoGet() {
auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
std::vector<GWObjects::CommandDetails> Commands;
if (QB_.Newest) {
StorageService()->GetNewestCommands(SerialNumber, QB_.Limit, Commands);
} else {
StorageService()->GetCommands(SerialNumber, QB_.StartDate, QB_.EndDate, QB_.Offset, QB_.Limit,
Commands);
}
Poco::JSON::Array ArrayObj;
for (const auto &i : Commands) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::COMMANDS, ArrayObj);
ReturnObject(RetObj);
}
void RESTAPI_commands::DoDelete() {
auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
if (StorageService()->DeleteCommands(SerialNumber, QB_.StartDate, QB_.EndDate)) {
return OK();
}
InternalError();
}
}

View File

@@ -9,20 +9,23 @@
#ifndef UCENTRAL_RESTAPI_COMMANDS_H
#define UCENTRAL_RESTAPI_COMMANDS_H
#include "RESTAPI_handler.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_commands : public RESTAPIHandler {
public:
RESTAPI_commands(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_commands(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/commands"};}
void DoGet() final;
void DoDelete() final;
void DoPost() final {};
void DoPut() final {};
};
}
#endif //UCENTRAL_RESTAPI_COMMANDS_H

View File

@@ -0,0 +1,76 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "Poco/JSON/Parser.h"
#include "RESTAPI_default_configuration.h"
#include "RESTObjects/RESTAPI_GWobjects.h"
#include "StorageService.h"
#include "framework/RESTAPI_errors.h"
#include "framework/RESTAPI_protocol.h"
namespace OpenWifi {
void RESTAPI_default_configuration::DoGet() {
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
GWObjects::DefaultConfiguration DefConfig;
if (StorageService()->GetDefaultConfiguration(Name, DefConfig)) {
Poco::JSON::Object Obj;
DefConfig.to_json(Obj);
return ReturnObject(Obj);
}
NotFound();
}
void RESTAPI_default_configuration::DoDelete() {
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
if(Name.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if (StorageService()->DeleteDefaultConfiguration(Name)) {
return OK();
}
BadRequest(RESTAPI::Errors::CouldNotBeDeleted);
}
void RESTAPI_default_configuration::DoPost() {
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
if(Name.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
auto Obj = ParseStream();
GWObjects::DefaultConfiguration DefConfig;
if (!DefConfig.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if (StorageService()->CreateDefaultConfiguration(Name, DefConfig)) {
return OK();
}
BadRequest(RESTAPI::Errors::RecordNotCreated);
}
void RESTAPI_default_configuration::DoPut() {
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
auto Obj = ParseStream();
GWObjects::DefaultConfiguration DefConfig;
if (!DefConfig.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if (StorageService()->UpdateDefaultConfiguration(Name, DefConfig)) {
return OK();
}
BadRequest(RESTAPI::Errors::RecordNotUpdated);
}
}

View File

@@ -9,21 +9,24 @@
#ifndef UCENTRAL_RESTAPI_DEFAULT_CONFIGURATION_H
#define UCENTRAL_RESTAPI_DEFAULT_CONFIGURATION_H
#include "RESTAPI_handler.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_default_configuration : public RESTAPIHandler {
public:
RESTAPI_default_configuration(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_default_configuration(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{
Poco::Net::HTTPRequest::HTTP_GET, Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_PUT, Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/default_configuration/{name}"};}
void DoGet() final;
void DoDelete() final;
void DoPost() final;
void DoPut() final;
};
}
#endif //UCENTRAL_RESTAPI_DEFAULT_CONFIGURATION_H

View File

@@ -0,0 +1,32 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "Poco/Array.h"
#include "Poco/JSON/Stringifier.h"
#include "RESTAPI_default_configurations.h"
#include "StorageService.h"
#include "framework/RESTAPI_protocol.h"
namespace OpenWifi {
void RESTAPI_default_configurations::DoGet() {
std::vector<GWObjects::DefaultConfiguration> DefConfigs;
StorageService()->GetDefaultConfigurations(QB_.Offset, QB_.Limit, DefConfigs);
Poco::JSON::Array Objects;
for (const auto &i : DefConfigs) {
Poco::JSON::Object Obj;
i.to_json(Obj);
Objects.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::CONFIGURATIONS, Objects);
ReturnObject(RetObj);
}
}

View File

@@ -9,19 +9,22 @@
#ifndef UCENTRAL_RESTAPI_DEFAULT_CONFIGURATIONS_H
#define UCENTRAL_RESTAPI_DEFAULT_CONFIGURATIONS_H
#include "RESTAPI_handler.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_default_configurations : public RESTAPIHandler {
public:
RESTAPI_default_configurations(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_default_configurations(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal){};
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/default_configurations"};}
void DoGet() final;
void DoDelete() final {};
void DoPost() final {};
void DoPut() final {};
};
}
#endif //UCENTRAL_RESTAPI_DEFAULT_CONFIGURATIONS_H

View File

@@ -0,0 +1,16 @@
//
// Created by stephane bourque on 2021-07-21.
//
#include "RESTAPI_deviceDashboardHandler.h"
#include "Daemon.h"
#include "Dashboard.h"
namespace OpenWifi {
void RESTAPI_deviceDashboardHandler::DoGet() {
Daemon()->GetDashboard().Create();
Poco::JSON::Object Answer;
Daemon()->GetDashboard().Report().to_json(Answer);
ReturnObject(Answer);
}
}

View File

@@ -5,21 +5,21 @@
#ifndef UCENTRALGW_RESTAPI_DEVICEDASHBOARDHANDLER_H
#define UCENTRALGW_RESTAPI_DEVICEDASHBOARDHANDLER_H
#include "RESTAPI_handler.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_deviceDashboardHandler : public RESTAPIHandler {
public:
RESTAPI_deviceDashboardHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_deviceDashboardHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{
Poco::Net::HTTPRequest::HTTP_GET, Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Server, Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/deviceDashboard"};}
void DoGet(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
void DoGet() final;
void DoDelete() final {};
void DoPost() final {};
void DoPut() final {};
};
}

View File

@@ -0,0 +1,816 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include <chrono>
#include <algorithm>
#include "Poco/UUIDGenerator.h"
#include "Poco/JSON/Parser.h"
#include "CentralConfig.h"
#include "DeviceRegistry.h"
#include "FileUploader.h"
#include "RESTObjects/RESTAPI_GWobjects.h"
#include "RESTAPI_device_commandHandler.h"
#include "StorageService.h"
#include "RESTAPI_RPC.h"
#include "CommandManager.h"
#include "TelemetryStream.h"
#include "framework/RESTAPI_protocol.h"
#include "framework/uCentral_Protocol.h"
#include "framework/KafkaTopics.h"
#include "framework/RESTAPI_errors.h"
namespace OpenWifi {
void RESTAPI_device_commandHandler::DoGet() {
if(!ValidateParameters()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
GWObjects::Device TheDevice;
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
return NotFound();
}
if (Command_ == RESTAPI::Protocol::CAPABILITIES){
return GetCapabilities();
} else if (Command_ == RESTAPI::Protocol::LOGS) {
return GetLogs();
} else if (Command_ == RESTAPI::Protocol::HEALTHCHECKS) {
return GetChecks();
} else if (Command_ == RESTAPI::Protocol::STATISTICS) {
return GetStatistics();
} else if (Command_ == RESTAPI::Protocol::STATUS) {
return GetStatus();
} else if (Command_ == RESTAPI::Protocol::RTTY) {
return Rtty();
} else {
return BadRequest(RESTAPI::Errors::InvalidCommand);
}
}
void RESTAPI_device_commandHandler::DoDelete() {
if(!ValidateParameters()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
GWObjects::Device TheDevice;
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
return NotFound();
}
if (Command_ == RESTAPI::Protocol::CAPABILITIES) {
return DeleteCapabilities();
} else if (Command_ == RESTAPI::Protocol::LOGS){
return DeleteLogs();
} else if (Command_ == RESTAPI::Protocol::HEALTHCHECKS){
return DeleteChecks();
} else if (Command_ == RESTAPI::Protocol::STATISTICS) {
return DeleteStatistics();
} else {
return BadRequest(RESTAPI::Errors::InvalidCommand);
}
}
void RESTAPI_device_commandHandler::DoPost() {
if(!ValidateParameters()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
GWObjects::Device TheDevice;
if(!StorageService()->GetDevice(SerialNumber_,TheDevice)) {
return NotFound();
}
if (Command_ == RESTAPI::Protocol::PERFORM) {
return ExecuteCommand();
} else if (Command_ == RESTAPI::Protocol::CONFIGURE) {
return Configure();
} else if (Command_ == RESTAPI::Protocol::UPGRADE) {
return Upgrade();
} else if (Command_ == RESTAPI::Protocol::REBOOT) {
return Reboot();
} else if (Command_ == RESTAPI::Protocol::FACTORY) {
return Factory();
} else if (Command_ == RESTAPI::Protocol::LEDS) {
return LEDs();
} else if (Command_ == RESTAPI::Protocol::TRACE) {
return Trace();
} else if (Command_ == RESTAPI::Protocol::REQUEST) {
return MakeRequest();
} else if (Command_ == RESTAPI::Protocol::WIFISCAN) {
return WifiScan();
} else if (Command_ == RESTAPI::Protocol::EVENTQUEUE) {
return EventQueue();
} else if (Command_ == RESTAPI::Protocol::TELEMETRY) {
return Telemetry();
} else {
return BadRequest(RESTAPI::Errors::InvalidCommand);
}
}
void RESTAPI_device_commandHandler::GetCapabilities() {
GWObjects::Capabilities Caps;
if (StorageService()->GetDeviceCapabilities(SerialNumber_, Caps)) {
Poco::JSON::Object RetObj;
Caps.to_json(RetObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
return ReturnObject(RetObj);
}
NotFound();
}
void RESTAPI_device_commandHandler::DeleteCapabilities() {
Logger_.information(Poco::format("DELETE-CAPABILITIES: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
if (StorageService()->DeleteDeviceCapabilities(SerialNumber_)) {
return OK();
}
NotFound();
}
void RESTAPI_device_commandHandler::GetStatistics() {
if (QB_.Lifetime) {
std::string Stats;
StorageService()->GetLifetimeStats(SerialNumber_, Stats);
Poco::JSON::Parser P;
if (Stats.empty())
Stats = uCentralProtocol::EMPTY_JSON_DOC;
auto Obj = P.parse(Stats).extract<Poco::JSON::Object::Ptr>();
return ReturnObject(*Obj);
} else if (QB_.LastOnly) {
std::string Stats;
if (DeviceRegistry()->GetStatistics(SerialNumber_, Stats)) {
Poco::JSON::Parser P;
if (Stats.empty())
Stats = uCentralProtocol::EMPTY_JSON_DOC;
auto Obj = P.parse(Stats).extract<Poco::JSON::Object::Ptr>();
return ReturnObject(*Obj);
} else {
return NotFound();
}
} else {
std::vector<GWObjects::Statistics> Stats;
if (QB_.Newest) {
StorageService()->GetNewestStatisticsData(SerialNumber_, QB_.Limit, Stats);
} else {
StorageService()->GetStatisticsData(SerialNumber_, QB_.StartDate, QB_.EndDate,
QB_.Offset, QB_.Limit, Stats);
}
Poco::JSON::Array ArrayObj;
for (auto i : Stats) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::DATA, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
return ReturnObject(RetObj);
}
}
void RESTAPI_device_commandHandler::DeleteStatistics() {
Logger_.information(Poco::format("DELETE-STATISTICS: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
if (QB_.Lifetime) {
if (StorageService()->ResetLifetimeStats(SerialNumber_)) {
return OK();
}
} else {
if (StorageService()->DeleteStatisticsData(SerialNumber_, QB_.StartDate, QB_.EndDate)) {
return OK();
}
}
NotFound();
}
void RESTAPI_device_commandHandler::GetStatus() {
GWObjects::ConnectionState State;
if (DeviceRegistry()->GetState(SerialNumber_, State)) {
Poco::JSON::Object RetObject;
State.to_json(RetObject);
return ReturnObject(RetObject);
}
NotFound();
}
void RESTAPI_device_commandHandler::Configure() {
// get the configuration from the body of the message
Logger_.information(Poco::format("CONFIGURE: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
auto Obj = ParseStream();
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
Obj->has(RESTAPI::Protocol::UUID) &&
Obj->has(RESTAPI::Protocol::CONFIGURATION)) {
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
auto Configuration = GetS(RESTAPI::Protocol::CONFIGURATION, Obj,uCentralProtocol::EMPTY_JSON_DOC);
auto When = GetWhen(Obj);
uint64_t NewUUID;
if (StorageService()->UpdateDeviceConfiguration(SerialNumber_, Configuration, NewUUID)) {
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = MicroService::CreateUUID();
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentralProtocol::CONFIGURE;
Cmd.RunAt = When;
Config::Config Cfg(Configuration);
Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::UUID, NewUUID);
Params.set(uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::CONFIG, Cfg.to_json());
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
DeviceRegistry()->SetPendingUUID(SerialNumber_, NewUUID);
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
}
return BadRequest(RESTAPI::Errors::RecordNotUpdated);
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::Upgrade() {
Logger_.information(Poco::format("UPGRADE: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
auto Obj = ParseStream();
if (Obj->has(RESTAPI::Protocol::URI) &&
Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
auto URI = GetS(RESTAPI::Protocol::URI, Obj);
auto When = GetWhen(Obj);
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = MicroService::CreateUUID();
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentralProtocol::UPGRADE;
Cmd.RunAt = When;
Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::URI, URI);
Params.set(uCentralProtocol::WHEN, When);
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::GetLogs() {
std::vector<GWObjects::DeviceLog> Logs;
if (QB_.Newest) {
StorageService()->GetNewestLogData(SerialNumber_, QB_.Limit, Logs, QB_.LogType);
} else {
StorageService()->GetLogData(SerialNumber_, QB_.StartDate, QB_.EndDate, QB_.Offset,
QB_.Limit, Logs, QB_.LogType);
}
Poco::JSON::Array ArrayObj;
for (auto i : Logs) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::VALUES, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
ReturnObject(RetObj);
}
void RESTAPI_device_commandHandler::DeleteLogs() {
Logger_.information(Poco::format("DELETE-LOGS: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
if (StorageService()->DeleteLogData(SerialNumber_, QB_.StartDate, QB_.EndDate,
QB_.LogType)) {
return OK();
}
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
}
void RESTAPI_device_commandHandler::GetChecks() {
std::vector<GWObjects::HealthCheck> Checks;
if (QB_.LastOnly) {
GWObjects::HealthCheck HC;
if (DeviceRegistry()->GetHealthcheck(SerialNumber_, HC)) {
Poco::JSON::Object Answer;
HC.to_json(Answer);
return ReturnObject(Answer);
} else {
return NotFound();
}
} else {
if (QB_.Newest) {
StorageService()->GetNewestHealthCheckData(SerialNumber_, QB_.Limit, Checks);
} else {
StorageService()->GetHealthCheckData(SerialNumber_, QB_.StartDate, QB_.EndDate,
QB_.Offset, QB_.Limit, Checks);
}
Poco::JSON::Array ArrayObj;
for (auto i : Checks) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::VALUES, ArrayObj);
RetObj.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
ReturnObject(RetObj);
}
}
void RESTAPI_device_commandHandler::DeleteChecks() {
Logger_.information(Poco::format("DELETE-HEALTHCHECKS: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
if (StorageService()->DeleteHealthCheckData(SerialNumber_, QB_.StartDate, QB_.EndDate)) {
return OK();
}
BadRequest(RESTAPI::Errors::NoRecordsDeleted);
}
void RESTAPI_device_commandHandler::ExecuteCommand() {
Logger_.information(Poco::format("EXECUTE: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
auto Obj = ParseStream();
if (Obj->has(RESTAPI::Protocol::COMMAND) &&
Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
Obj->has(RESTAPI::Protocol::PAYLOAD)) {
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
return BadRequest("Missing serial number.");
}
auto Command = GetS(RESTAPI::Protocol::COMMAND, Obj);
auto Payload = GetS(RESTAPI::Protocol::PAYLOAD, Obj);
auto When = GetWhen(Obj);
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = MicroService::CreateUUID();
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = Command;
Cmd.Custom = 1;
Cmd.RunAt = When;
Poco::JSON::Parser parser2;
Poco::Dynamic::Var result = parser2.parse(Payload);
const auto &PayloadObject = result.extract<Poco::JSON::Object::Ptr>();
Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::COMMAND, Command);
Params.set(uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::PAYLOAD, PayloadObject);
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::Reboot() {
Logger_.information(Poco::format("REBOOT: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
auto Obj = ParseStream();
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
uint64_t When = GetWhen(Obj);
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = MicroService::CreateUUID();
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentralProtocol::REBOOT;
Cmd.RunAt = When;
Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::WHEN, When);
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
}
BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
void RESTAPI_device_commandHandler::Factory() {
Logger_.information(Poco::format("FACTORY-RESET: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
Poco::JSON::Object::Ptr Obj = ParseStream();
if (Obj->has(RESTAPI::Protocol::KEEPREDIRECTOR) &&
Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
auto KeepRedirector = GetB(RESTAPI::Protocol::KEEPREDIRECTOR, Obj, true);
uint64_t When = GetWhen(Obj);
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = MicroService::CreateUUID();
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentralProtocol::FACTORY;
Cmd.RunAt = When;
Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::KEEP_REDIRECTOR, KeepRedirector ? 1 : 0);
Params.set(uCentralProtocol::WHEN, When);
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::LEDs() {
Logger_.information(Poco::format("LEDS: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
auto Obj = ParseStream();
if (Obj->has(uCentralProtocol::PATTERN) &&
Obj->has(RESTAPI::Protocol::SERIALNUMBER)) {
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
auto Pattern =
GetS(uCentralProtocol::PATTERN, Obj, uCentralProtocol::BLINK);
if (Pattern != uCentralProtocol::ON &&
Pattern != uCentralProtocol::OFF &&
Pattern != uCentralProtocol::BLINK) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
auto Duration = Get(uCentralProtocol::DURATION, Obj, 30);
auto When = GetWhen(Obj);
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = MicroService::CreateUUID();
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentralProtocol::LEDS;
Cmd.RunAt = When;
Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::DURATION, Duration);
Params.set(uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::PATTERN, Pattern);
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::Trace() {
Logger_.information(Poco::format("TRACE: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
auto Obj = ParseStream();
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
(Obj->has(RESTAPI::Protocol::NETWORK) ||
Obj->has(RESTAPI::Protocol::INTERFACE))) {
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
auto Duration = Get(RESTAPI::Protocol::DURATION, Obj, 30);
auto When = GetWhen(Obj);
auto NumberOfPackets = Get(RESTAPI::Protocol::NUMBEROFPACKETS, Obj, 100);
auto Network = GetS(RESTAPI::Protocol::NETWORK, Obj);
auto Interface = GetS(RESTAPI::Protocol::INTERFACE, Obj);
auto UUID = MicroService::CreateUUID();
auto URI = FileUploader()->FullName() + UUID;
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentralProtocol::TRACE;
Cmd.RunAt = When;
Cmd.WaitingForFile = 1;
Cmd.AttachType = RESTAPI::Protocol::PCAP_FILE_TYPE;
Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::DURATION, Duration);
Params.set(uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::PACKETS, NumberOfPackets);
Params.set(uCentralProtocol::NETWORK, Network);
Params.set(uCentralProtocol::INTERFACE, Interface);
Params.set(uCentralProtocol::URI, URI);
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
FileUploader()->AddUUID(UUID);
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::WifiScan() {
Logger_.information(Poco::format("WIFISCAN: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
auto Obj = ParseStream();
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
if ((Obj->has(RESTAPI::Protocol::BANDS) &&
Obj->isArray(RESTAPI::Protocol::BANDS) ||
(Obj->has(RESTAPI::Protocol::CHANNELS) &&
Obj->isArray(RESTAPI::Protocol::CHANNELS)) ||
(!Obj->has(RESTAPI::Protocol::BANDS) &&
!Obj->has(RESTAPI::Protocol::CHANNELS)))) {
bool Verbose = GetB(RESTAPI::Protocol::VERBOSE, Obj);
auto UUID = MicroService::CreateUUID();
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentralProtocol::WIFISCAN;
Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::VERBOSE, Verbose);
if (Obj->has(uCentralProtocol::BANDS)) {
Params.set(uCentralProtocol::BANDS, Obj->get(RESTAPI::Protocol::BANDS));
} else if (Obj->has(uCentralProtocol::CHANNELS)) {
Params.set(uCentralProtocol::CHANNELS, Obj->get(RESTAPI::Protocol::CHANNELS));
}
if (Obj->has(RESTAPI::Protocol::ACTIVESCAN)) {
Params.set(uCentralProtocol::ACTIVE,
(int)(Obj->get(RESTAPI::Protocol::ACTIVESCAN).toString() == "true") ? 1 : 0);
} else {
Params.set(uCentralProtocol::ACTIVE, 0);
}
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
if (Cmd.ErrorCode == 0) {
KafkaManager()->PostMessage(KafkaTopics::WIFISCAN, SerialNumber_, Cmd.Results);
}
return;
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::EventQueue() {
Logger_.information(Poco::format("EVENT-QUEUE: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
auto Obj = ParseStream();
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
Obj->isArray(RESTAPI::Protocol::TYPES)) {
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
auto Types = Obj->getArray(RESTAPI::Protocol::TYPES);
auto UUID = MicroService::CreateUUID();
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.UUID = UUID;
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentralProtocol::EVENT;
Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::TYPES, Types);
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_);
if(Cmd.ErrorCode==0) {
KafkaManager()->PostMessage(KafkaTopics::DEVICE_EVENT_QUEUE, SerialNumber_,
Cmd.Results);
}
return;
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::MakeRequest() {
Logger_.information(Poco::format("FORCE-REQUEST: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
auto Obj = ParseStream();
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
Obj->has(uCentralProtocol::MESSAGE)) {
auto SNum = GetS(RESTAPI::Protocol::SERIALNUMBER, Obj);
auto MessageType = GetS(uCentralProtocol::MESSAGE, Obj);
if ((SerialNumber_ != SNum) ||
(MessageType != uCentralProtocol::STATE &&
MessageType != uCentralProtocol::HEALTHCHECK)) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
auto When = GetWhen(Obj);
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.UUID = MicroService::CreateUUID();
Cmd.Command = uCentralProtocol::REQUEST;
Cmd.RunAt = When;
Poco::JSON::Object Params;
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::WHEN, When);
Params.set(uCentralProtocol::MESSAGE, MessageType);
Params.set(uCentralProtocol::REQUEST_UUID, Cmd.UUID);
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, nullptr, this, Logger_ );
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_device_commandHandler::Rtty() {
Logger_.information(Poco::format("RTTY: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
if (MicroService::instance().ConfigGetString("rtty.enabled", "false") == "true") {
GWObjects::Device Device;
if (StorageService()->GetDevice(SerialNumber_, Device)) {
auto CommandUUID = MicroService::CreateUUID();
GWObjects::RttySessionDetails Rtty{
.SerialNumber = SerialNumber_,
.Server = MicroService::instance().ConfigGetString("rtty.server", "localhost"),
.Port = MicroService::instance().ConfigGetInt("rtty.port", 5912),
.Token = MicroService::instance().ConfigGetString("rtty.token", "nothing"),
.TimeOut = MicroService::instance().ConfigGetInt("rtty.timeout", 60),
.ConnectionId = CommandUUID,
.Started = (uint64_t)time(nullptr),
.CommandUUID = CommandUUID,
.ViewPort = MicroService::instance().ConfigGetInt("rtty.viewport", 5913),
};
Poco::JSON::Object ReturnedObject;
Rtty.to_json(ReturnedObject);
// let's create the command for this request
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.UUID = CommandUUID;
Cmd.Command = uCentralProtocol::RTTY;
Poco::JSON::Object Params;
Params.set(uCentralProtocol::METHOD, uCentralProtocol::RTTY);
Params.set(uCentralProtocol::SERIAL, SerialNumber_);
Params.set(uCentralProtocol::ID, Rtty.ConnectionId);
Params.set(uCentralProtocol::TOKEN, Rtty.Token);
Params.set(uCentralProtocol::SERVER, Rtty.Server);
Params.set(uCentralProtocol::PORT, Rtty.Port);
Params.set(uCentralProtocol::USER, UserInfo_.webtoken.username_);
Params.set(uCentralProtocol::TIMEOUT, Rtty.TimeOut);
Params.set(uCentralProtocol::PASSWORD, Device.DevicePassword);
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response, 60000, &ReturnedObject, this, Logger_);
}
return NotFound();
}
ReturnStatus(Poco::Net::HTTPResponse::HTTP_SERVICE_UNAVAILABLE);
}
void RESTAPI_device_commandHandler::Telemetry(){
Logger_.information(Poco::format("TELEMETRY: user=%s serial=%s", UserInfo_.userinfo.email,SerialNumber_));
auto Obj = ParseStream();
if (Obj->has(RESTAPI::Protocol::SERIALNUMBER) &&
Obj->has(RESTAPI::Protocol::INTERVAL) && Obj->has(RESTAPI::Protocol::TYPES)) {
auto SNum = Obj->get(RESTAPI::Protocol::SERIALNUMBER).toString();
if (SerialNumber_ != SNum) {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
GWObjects::Device Device;
if (!StorageService()->GetDevice(SerialNumber_, Device)) {
return NotFound();
}
if (!DeviceRegistry()->Connected(SerialNumber_)) {
return BadRequest(RESTAPI::Errors::DeviceNotConnected);
}
auto Interval = Obj->get(RESTAPI::Protocol::INTERVAL);
std::string UUID;
if (Obj->has(RESTAPI::Protocol::UUID))
UUID = Obj->get(RESTAPI::Protocol::UUID).toString();
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.SubmittedBy = UserInfo_.webtoken.username_;
Cmd.Command = uCentralProtocol::TELEMETRY;
Poco::JSON::Object Params;
Params.set(RESTAPI::Protocol::SERIALNUMBER, SerialNumber_);
Params.set(RESTAPI::Protocol::INTERVAL, Interval);
if (Interval > 0)
Params.set(RESTAPI::Protocol::TYPES, Obj->getArray(RESTAPI::Protocol::TYPES));
std::string Endpoint, NewUUID;
Poco::JSON::Object Answer;
if (Interval) {
if (TelemetryStream()->CreateEndpoint(SerialNumber_, Endpoint, NewUUID)) {
Answer.set("serialNumber", SerialNumber_);
Answer.set("uuid", NewUUID);
Answer.set("uri", Endpoint);
}
} else {
return BadRequest(RESTAPI::Errors::CannotCreateWS);
}
Cmd.UUID = NewUUID;
std::stringstream ParamStream;
Params.stringify(ParamStream);
Cmd.Details = ParamStream.str();
return RESTAPI_RPC::WaitForCommand(Cmd, Params, *Request, *Response,
60000, &Answer, this, Logger_);
}
BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
}

View File

@@ -0,0 +1,71 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#ifndef UCENTRAL_RESTAPI_DEVICECOMMANDHANDLER_H
#define UCENTRAL_RESTAPI_DEVICECOMMANDHANDLER_H
#include "framework/MicroService.h"
#include "framework/RESTAPI_protocol.h"
namespace OpenWifi {
class RESTAPI_device_commandHandler : public RESTAPIHandler {
public:
RESTAPI_device_commandHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{
Poco::Net::HTTPRequest::HTTP_GET, Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void GetCapabilities();
void DeleteCapabilities();
void GetLogs();
void DeleteLogs();
void GetStatistics();
void DeleteStatistics();
void GetStatus();
void ExecuteCommand();
void Configure();
void GetChecks();
void DeleteChecks();
void Upgrade();
void Reboot();
void Factory();
void LEDs();
void Trace();
void MakeRequest();
void WifiScan();
void EventQueue();
void Rtty();
void Telemetry();
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/device/{serialNumber}/{command}"}; };
void DoGet() final;
void DoDelete() final;
void DoPost() final;
void DoPut() final {};
inline bool ValidateParameters() {
Command_ = GetBinding(RESTAPI::Protocol::COMMAND, "");
if (Command_.empty()) {
return false;
}
SerialNumber_ = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if (SerialNumber_.empty()) {
return false;
}
return true;
}
private:
std::string SerialNumber_, Command_;
};
}
#endif //UCENTRAL_RESTAPI_DEVICECOMMANDHANDLER_H

View File

@@ -0,0 +1,191 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "RESTAPI_device_handler.h"
#include "CentralConfig.h"
#include "ConfigurationCache.h"
#include "Poco/JSON/Parser.h"
#include "StorageService.h"
#include "framework/ConfigurationValidator.h"
#include "framework/MicroService.h"
#include "framework/RESTAPI_errors.h"
#include "framework/RESTAPI_protocol.h"
namespace OpenWifi {
void RESTAPI_device_handler::DoGet() {
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
GWObjects::Device Device;
if (StorageService()->GetDevice(SerialNumber, Device)) {
Poco::JSON::Object Obj;
Device.to_json(Obj);
return ReturnObject(Obj);
}
NotFound();
}
void RESTAPI_device_handler::DoDelete() {
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
std::string Arg;
if(HasParameter("oui",Arg) && Arg=="true" && SerialNumber.size()==6) {
std::set<std::string> Set;
std::vector<GWObjects::Device> Devices;
bool Done = false;
uint64_t Offset=1;
while(!Done) {
StorageService()->GetDevices(Offset,500,Devices);
for(const auto &i:Devices) {
if(i.SerialNumber.substr(0,6) == SerialNumber) {
Set.insert(i.SerialNumber);
}
}
if(Devices.size()<500)
Done=true;
Offset += Devices.size();
}
for(auto &i:Set) {
std::string SNum{i};
StorageService()->DeleteDevice(SNum);
}
return OK();
} else if (StorageService()->DeleteDevice(SerialNumber)) {
return OK();
}
NotFound();
}
void RESTAPI_device_handler::DoPost() {
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
std::string Arg;
if(HasParameter("validateOnly",Arg) && Arg=="true") {
auto Body = ParseStream();
if(!Body->has("configuration")) {
return BadRequest("Must have 'configuration' element.");
}
auto Config=Body->get("configuration").toString();
Poco::JSON::Object Answer;
std::string Error;
auto Res = ValidateUCentralConfiguration(Config, Error);
Answer.set("valid",Res);
if(!Error.empty())
Answer.set("error",Error);
return ReturnObject(Answer);
}
if (!Utils::ValidSerialNumber(SerialNumber)) {
Logger_.warning(Poco::format("CREATE-DEVICE(%s): Illegal serial number.", SerialNumber));
return BadRequest( RESTAPI::Errors::InvalidSerialNumber);
}
auto Obj = ParseStream();
GWObjects::Device Device;
if (!Device.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(SerialNumber!=Device.SerialNumber) {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
std::string Error;
if(Device.Configuration.empty() || (!Device.Configuration.empty() && !ValidateUCentralConfiguration(Device.Configuration,Error))) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
}
for(auto &i:Device.Notes)
i.createdBy = UserInfo_.userinfo.email;
Config::Config NewConfig(Device.Configuration);
Device.UUID = std::time(nullptr);
NewConfig.SetUUID(Device.UUID);
Device.Configuration = NewConfig.get();
Poco::toLowerInPlace(Device.SerialNumber);
if (StorageService()->CreateDevice(Device)) {
SetCurrentConfigurationID(SerialNumber, Device.UUID);
Poco::JSON::Object DevObj;
Device.to_json(DevObj);
return ReturnObject(DevObj);
}
InternalError(RESTAPI::Errors::RecordNotCreated);
}
void RESTAPI_device_handler::DoPut() {
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
auto Obj = ParseStream();
GWObjects::Device NewDevice;
if (!NewDevice.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
GWObjects::Device Existing;
if(!StorageService()->GetDevice(SerialNumber, Existing)) {
return NotFound();
}
if(!NewDevice.Configuration.empty()) {
std::string Error;
if (!ValidateUCentralConfiguration(NewDevice.Configuration, Error)) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
}
Config::Config NewConfig(NewDevice.Configuration);
uint64_t NewConfigUUID = std::time(nullptr);
NewConfig.SetUUID(NewConfigUUID);
Existing.Configuration = NewConfig.get();
Existing.UUID = NewConfigUUID;
}
AssignIfPresent(Obj, "venue", Existing.Venue);
AssignIfPresent(Obj, "owner", Existing.Owner);
AssignIfPresent(Obj, "location", Existing.Location);
for(auto &i:NewDevice.Notes) {
i.createdBy = UserInfo_.userinfo.email;
Existing.Notes.push_back(i);
}
Existing.LastConfigurationChange = std::time(nullptr);
if (StorageService()->UpdateDevice(Existing)) {
SetCurrentConfigurationID(SerialNumber, Existing.UUID);
Poco::JSON::Object DevObj;
NewDevice.to_json(DevObj);
return ReturnObject(DevObj);
}
InternalError(RESTAPI::Errors::RecordNotUpdated);
}
}

View File

@@ -9,23 +9,26 @@
#ifndef UCENTRAL_RESTAPI_DEVICEHANDLER_H
#define UCENTRAL_RESTAPI_DEVICEHANDLER_H
#include "RESTAPI_handler.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_device_handler : public RESTAPIHandler {
public:
RESTAPI_device_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_device_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{
Poco::Net::HTTPRequest::HTTP_GET, Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_PUT, Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/device/{serialNumber}"}; };
void DoGet() final;
void DoDelete() final;
void DoPost() final;
void DoPut() final;
};
}

View File

@@ -0,0 +1,78 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "Poco/Array.h"
#include "Poco/JSON/Stringifier.h"
#include "RESTAPI_devices_handler.h"
#include "StorageService.h"
#include "framework/RESTAPI_protocol.h"
#include "framework/MicroService.h"
namespace OpenWifi {
void RESTAPI_devices_handler::DoGet() {
auto serialOnly = GetBoolParameter(RESTAPI::Protocol::SERIALONLY, false);
auto deviceWithStatus = GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, false);
Poco::JSON::Object RetObj;
if (!QB_.Select.empty()) {
Poco::JSON::Array Objects;
std::vector<std::string> Numbers = Utils::Split(QB_.Select);
for (auto &i : Numbers) {
GWObjects::Device D;
if (StorageService()->GetDevice(i, D)) {
Poco::JSON::Object Obj;
if (deviceWithStatus)
D.to_json_with_status(Obj);
else
D.to_json(Obj);
Objects.add(Obj);
} else {
Logger_.error(
Poco::format("DEVICE(%s): device in select cannot be found.", i));
}
}
if (deviceWithStatus)
RetObj.set(RESTAPI::Protocol::DEVICESWITHSTATUS, Objects);
else
RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
} else if (QB_.CountOnly == true) {
uint64_t Count = 0;
if (StorageService()->GetDeviceCount(Count)) {
return ReturnCountOnly(Count);
}
} else if (serialOnly) {
std::vector<std::string> SerialNumbers;
StorageService()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers);
Poco::JSON::Array Objects;
for (const auto &i : SerialNumbers) {
Objects.add(i);
}
RetObj.set(RESTAPI::Protocol::SERIALNUMBERS, Objects);
} else {
std::vector<GWObjects::Device> Devices;
StorageService()->GetDevices(QB_.Offset, QB_.Limit, Devices);
Poco::JSON::Array Objects;
for (const auto &i : Devices) {
Poco::JSON::Object Obj;
if (deviceWithStatus)
i.to_json_with_status(Obj);
else
i.to_json(Obj);
Objects.add(Obj);
}
if (deviceWithStatus)
RetObj.set(RESTAPI::Protocol::DEVICESWITHSTATUS, Objects);
else
RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
}
ReturnObject(RetObj);
}
}

View File

@@ -9,19 +9,22 @@
#ifndef UCENTRAL_RESTAPI_DEVICESHANDLER_H
#define UCENTRAL_RESTAPI_DEVICESHANDLER_H
#include "RESTAPI_handler.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_devices_handler : public RESTAPIHandler {
public:
RESTAPI_devices_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_devices_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal){};
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/devices"}; };
void DoGet() final;
void DoDelete() final {};
void DoPost() final {};
void DoPut() final {};
};
}

View File

@@ -0,0 +1,47 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "RESTAPI_file.h"
#include "FileUploader.h"
#include "Poco/File.h"
#include "StorageService.h"
#include "framework/RESTAPI_errors.h"
#include "framework/RESTAPI_protocol.h"
#include <fstream>
namespace OpenWifi {
void RESTAPI_file::DoGet() {
auto UUID = GetBinding(RESTAPI::Protocol::FILEUUID, "");
auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
// does the file exist
Poco::File DownloadFile(FileUploader()->Path() + "/" + UUID);
std::string FileType;
if (!StorageService()->GetAttachedFile(UUID, SerialNumber, DownloadFile.path(), FileType)) {
return NotFound();
}
SendFile(DownloadFile, UUID);
DownloadFile.remove();
}
void RESTAPI_file::DoDelete() {
auto UUID = GetBinding(RESTAPI::Protocol::FILEUUID, "");
if (UUID.empty()) {
return BadRequest(RESTAPI::Errors::MissingUUID);
}
if (StorageService()->RemoveAttachedFile(UUID)) {
return OK();
}
BadRequest(RESTAPI::Errors::CouldNotBeDeleted);
}
}

View File

@@ -9,20 +9,23 @@
#ifndef UCENTRAL_RESTAPI_FILE_H
#define UCENTRAL_RESTAPI_FILE_H
#include "RESTAPI_handler.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_file : public RESTAPIHandler {
public:
RESTAPI_file(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_file(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/file/{uuid}"};}
void DoGet() final;
void DoDelete() final;
void DoPost() final {};
void DoPut() final {};
};
}

View File

@@ -0,0 +1,24 @@
//
// Created by stephane bourque on 2021-06-17.
//
#include "RESTAPI_ouis.h"
#include "OUIServer.h"
namespace OpenWifi {
void RESTAPI_ouis::DoGet() {
Poco::JSON::Array Objects;
auto Select = GetParameter("macList","");
std::vector<std::string> Macs = Utils::Split(Select);
for (auto &i : Macs) {
Poco::JSON::Object O;
auto Manufacturer = OUIServer()->GetManufacturer(i);
O.set("tag", i);
O.set("value", Manufacturer);
Objects.add(O);
}
Poco::JSON::Object RetObj;
RetObj.set("tagList",Objects);
ReturnObject(RetObj);
}
}

View File

@@ -5,19 +5,21 @@
#ifndef UCENTRALGW_RESTAPI_OUIS_H
#define UCENTRALGW_RESTAPI_OUIS_H
#include "RESTAPI_handler.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_ouis : public RESTAPIHandler {
public:
RESTAPI_ouis(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_ouis(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{
Poco::Net::HTTPRequest::HTTP_GET, Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &request,
Poco::Net::HTTPServerResponse &response) override;
Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Server, Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/ouis"};}
void DoGet() final;
void DoDelete() final {};
void DoPost() final {};
void DoPut() final {};
};
}

View File

@@ -2,38 +2,25 @@
// Created by stephane bourque on 2021-08-12.
//
#include "RESTAPI_webSocketServer.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Stringifier.h"
#include "RESTAPI_webSocketServer.h"
#include "SerialNumberCache.h"
#include "Utils.h"
#include "AuthClient.h"
#include "framework/MicroService.h"
namespace OpenWifi {
void RESTAPI_webSocketServer::handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET)
DoGet(Request,Response);
else
BadRequest(Request, Response, "Can only do get for WebSocket.");
}
void RESTAPI_webSocketServer::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
void RESTAPI_webSocketServer::DoGet() {
// try and upgrade this session to websocket...
if(Request.find("Upgrade") != Request.end() && Poco::icompare(Request["Upgrade"], "websocket") == 0) {
if(Request->find("Upgrade") != Request->end() && Poco::icompare((*Request)["Upgrade"], "websocket") == 0) {
try
{
Poco::Net::WebSocket WS(Request, Response);
Poco::Net::WebSocket WS(*Request, *Response);
Logger_.information("WebSocket connection established.");
int flags;
int n;
@@ -59,7 +46,8 @@ namespace OpenWifi {
if(!Authenticated) {
std::string Frame{IncomingFrame.begin()};
auto Tokens = Utils::Split(Frame,':');
if(Tokens.size()==2 && AuthClient()->IsTokenAuthorized(Tokens[1], UserInfo_)) {
bool Expired=false;
if(Tokens.size()==2 && AuthClient()->IsAuthorized(Tokens[1], UserInfo_, Expired)) {
Authenticated=true;
std::string S{"Welcome! Bienvenue! Bienvenidos!"};
WS.sendFrame(S.c_str(),S.size());
@@ -87,6 +75,12 @@ namespace OpenWifi {
}
}
break;
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
Logger_.warning(Poco::format("CLOSE(%s): Client is closing its WS connection.", UserInfo_.userinfo.email));
Done=true;
}
break;
default:
{
@@ -102,14 +96,14 @@ namespace OpenWifi {
switch (E.code())
{
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
Response.set("Sec-WebSocket-Version", Poco::Net::WebSocket::WEBSOCKET_VERSION);
Response->set("Sec-WebSocket-Version", Poco::Net::WebSocket::WEBSOCKET_VERSION);
// fallthrough
case Poco::Net::WebSocket::WS_ERR_NO_HANDSHAKE:
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_VERSION:
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_KEY:
Response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
Response.setContentLength(0);
Response.send();
Response->setStatusAndReason(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
Response->setContentLength(0);
Response->send();
break;
}
}

View File

@@ -5,23 +5,21 @@
#ifndef UCENTRALGW_RESTAPI_WEBSOCKETSERVER_H
#define UCENTRALGW_RESTAPI_WEBSOCKETSERVER_H
class RESTAPI_webSocketServer {};
#include "RESTAPI_handler.h"
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_webSocketServer : public RESTAPIHandler {
public:
RESTAPI_webSocketServer(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal)
RESTAPI_webSocketServer(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Internal) {}
void handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) override final;
std::vector<std::string>{ Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, Internal,false) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/ws"};}
void DoGet(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
void DoGet() final;
void DoDelete() final {};
void DoPost() final {};
void DoPut() final {};
private:
void Process(const Poco::JSON::Object::Ptr &O, std::string &Answer);
};

View File

@@ -1,128 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include <ctime>
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Stringifier.h"
#include "RESTAPI_BlackList.h"
#include "RESTAPI_protocol.h"
#include "StorageService.h"
namespace OpenWifi {
void RESTAPI_BlackList::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
ParseParameters(Request);
try {
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE)
DoDelete(Request, Response);
else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET)
DoGet(Request, Response);
else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST)
DoPost(Request, Response);
return;
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
}
BadRequest(Request, Response);
}
void RESTAPI_BlackList::DoDelete(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
try {
auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if (!SerialNumber.empty()) {
if (Storage()->DeleteBlackListDevice(SerialNumber)) {
OK(Request, Response);
} else {
NotFound(Request, Response);
}
return;
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
BadRequest(Request, Response);
}
void RESTAPI_BlackList::DoGet(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
try {
if(!InitQueryBlock()) {
BadRequest(Request, Response, "Illegal parameter value.");
return;
}
std::vector<GWObjects::BlackListedDevice> Devices;
Poco::JSON::Array Objects;
if (Storage()->GetBlackListDevices(QB_.Offset, QB_.Limit, Devices)) {
for (const auto &i : Devices) {
Poco::JSON::Object Obj;
i.to_json(Obj);
Objects.add(Obj);
}
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
ReturnObject(Request, RetObj, Response);
return;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
BadRequest(Request, Response);
}
void RESTAPI_BlackList::DoPost(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
try {
Poco::JSON::Parser parser;
Poco::JSON::Object::Ptr Obj =
parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
if (Obj->has(RESTAPI::Protocol::DEVICES) &&
Obj->isArray(RESTAPI::Protocol::DEVICES)) {
std::vector<GWObjects::BlackListedDevice> Devices;
auto DeviceArray = Obj->getArray(RESTAPI::Protocol::DEVICES);
for (const auto &i : *DeviceArray) {
Poco::JSON::Parser pp;
auto InnerObj = pp.parse(i).extract<Poco::JSON::Object::Ptr>();
Poco::DynamicStruct Vars = *InnerObj;
if (Vars.contains(RESTAPI::Protocol::SERIALNUMBER) &&
Vars.contains(RESTAPI::Protocol::REASON)) {
auto SerialNumber = Vars[RESTAPI::Protocol::SERIALNUMBER].toString();
auto Reason = Vars[RESTAPI::Protocol::REASON].toString();
GWObjects::BlackListedDevice D{.SerialNumber = SerialNumber,
.Reason = Reason,
.Author = UserInfo_.webtoken.username_,
.Created = (uint64_t)time(nullptr)};
Devices.push_back(D);
}
}
if (!Devices.empty()) {
if (Storage()->AddBlackListDevices(Devices)) {
OK(Request, Response);
return;
}
}
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
BadRequest(Request, Response);
}
}

View File

@@ -1,80 +0,0 @@
//
// Created by stephane bourque on 2021-06-29.
//
#include "RESTAPI_InternalServer.h"
#include "Poco/URI.h"
#include "RESTAPI_BlackList.h"
#include "RESTAPI_command.h"
#include "RESTAPI_commands.h"
#include "RESTAPI_default_configuration.h"
#include "RESTAPI_default_configurations.h"
#include "RESTAPI_device_commandHandler.h"
#include "RESTAPI_device_handler.h"
#include "RESTAPI_devices_handler.h"
#include "RESTAPI_file.h"
#include "RESTAPI_ouis.h"
#include "Utils.h"
namespace OpenWifi {
class RESTAPI_InternalServer *RESTAPI_InternalServer::instance_ = nullptr;
RESTAPI_InternalServer::RESTAPI_InternalServer() noexcept: SubSystemServer("RESTAPIInternalServer", "REST-ISRV", "ucentral.internal.restapi")
{
}
int RESTAPI_InternalServer::Start() {
Logger_.information("Starting.");
for(const auto & Svr: ConfigServersList_) {
Logger_.information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()),
Svr.KeyFile(),Svr.CertFile()));
auto Sock{Svr.CreateSecureSocket(Logger_)};
Svr.LogCert(Logger_);
if(!Svr.RootCA().empty())
Svr.LogCas(Logger_);
auto Params = new Poco::Net::HTTPServerParams;
Params->setMaxThreads(50);
Params->setMaxQueued(200);
Params->setKeepAlive(true);
auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new InternalRequestHandlerFactory, Pool_, Sock, Params);
NewServer->start();
RESTServers_.push_back(std::move(NewServer));
}
return 0;
}
void RESTAPI_InternalServer::Stop() {
Logger_.information("Stopping ");
for( const auto & svr : RESTServers_ )
svr->stop();
}
Poco::Net::HTTPRequestHandler *InternalRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) {
Logger_.debug(Poco::format("REQUEST(%s): %s %s", Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI()));
Poco::URI uri(Request.getURI());
const auto & Path = uri.getPath();
RESTAPIHandler::BindingMap Bindings;
return RESTAPI_Router_I<
RESTAPI_devices_handler,
RESTAPI_device_handler,
RESTAPI_device_commandHandler,
RESTAPI_default_configurations,
RESTAPI_default_configuration,
RESTAPI_command,
RESTAPI_commands,
RESTAPI_ouis,
RESTAPI_file,
RESTAPI_BlackList>(Path,Bindings,Logger_); }
}

View File

@@ -1,53 +0,0 @@
//
// Created by stephane bourque on 2021-06-29.
//
#ifndef UCENTRALSEC_RESTAPI_INTERNALSERVER_H
#define UCENTRALSEC_RESTAPI_INTERNALSERVER_H
#include "SubSystemServer.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/NetException.h"
namespace OpenWifi {
class RESTAPI_InternalServer : public SubSystemServer {
public:
RESTAPI_InternalServer() noexcept;
static RESTAPI_InternalServer *instance() {
if (instance_ == nullptr) {
instance_ = new RESTAPI_InternalServer;
}
return instance_;
}
int Start() override;
void Stop() override;
private:
static RESTAPI_InternalServer *instance_;
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> RESTServers_;
Poco::ThreadPool Pool_;
};
inline RESTAPI_InternalServer * RESTAPI_InternalServer() { return RESTAPI_InternalServer::instance(); };
class InternalRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
public:
InternalRequestHandlerFactory() :
Logger_(RESTAPI_InternalServer()->Logger()){}
Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &request) override;
private:
Poco::Logger & Logger_;
};
} // namespace
#endif //UCENTRALSEC_RESTAPI_INTERNALSERVER_H

View File

@@ -1,139 +0,0 @@
//
// Created by stephane bourque on 2021-06-28.
//
#include <cctype>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <future>
#include <numeric>
#include <chrono>
#include "RESTAPI_RPC.h"
#include "StorageService.h"
#include "DeviceRegistry.h"
#include "CommandManager.h"
#include "uCentralProtocol.h"
namespace OpenWifi::RESTAPI_RPC {
void SetCommandAsPending(GWObjects::CommandDetails &Cmd,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response, RESTAPIHandler *Handler) {
if (Storage()->AddCommand(Cmd.SerialNumber, Cmd, Storage::COMMAND_PENDING)) {
Poco::JSON::Object RetObj;
Cmd.to_json(RetObj);
Handler->ReturnObject(Request, RetObj, Response);
return;
} else {
Handler->ReturnStatus(Request, Response,
Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
return;
}
}
void WaitForCommand(GWObjects::CommandDetails &Cmd,
Poco::JSON::Object & Params,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response,
std::chrono::milliseconds D,
Poco::JSON::Object * ObjectToReturn,
RESTAPIHandler * Handler) {
// if the command should be executed in the future, or if the device is not connected, then we should just add the command to
// the DB and let it figure out when to deliver the command.
if(Cmd.RunAt || !DeviceRegistry()->Connected(Cmd.SerialNumber)) {
SetCommandAsPending(Cmd, Request, Response, Handler);
return;
} else if(Cmd.RunAt==0 && DeviceRegistry()->Connected(Cmd.SerialNumber)) {
auto Promise = std::make_shared<std::promise<Poco::JSON::Object::Ptr>>();
std::future<Poco::JSON::Object::Ptr> Future = Promise->get_future();
Cmd.Executed = time(nullptr);
if (CommandManager()->SendCommand(Cmd.SerialNumber, Cmd.Command, Params, Promise, Cmd.UUID)) {
auto Status = Future.wait_for(D);
if (Status == std::future_status::ready) {
auto Answer = Future.get();
if (Answer->has("result") && Answer->isObject("result")) {
auto ResultFields =
Answer->get("result").extract<Poco::JSON::Object::Ptr>();
if (ResultFields->has("status") && ResultFields->isObject("status")) {
auto StatusInnerObj =
ResultFields->get("status").extract<Poco::JSON::Object::Ptr>();
if (StatusInnerObj->has("error"))
Cmd.ErrorCode = StatusInnerObj->get("error");
if (StatusInnerObj->has("text"))
Cmd.ErrorText = StatusInnerObj->get("text").toString();
std::stringstream ResultText;
Poco::JSON::Stringifier::stringify(Answer->get("result"), ResultText);
Cmd.Results = ResultText.str();
Cmd.Status = "completed";
Cmd.Completed = time(nullptr);
if(Cmd.ErrorCode && Cmd.Command==uCentralProtocol::TRACE) {
Cmd.WaitingForFile = 0;
Cmd.AttachDate = Cmd.AttachSize = 0 ;
Cmd.AttachType = "";
}
// Add the completed command to the database...
Storage()->AddCommand(Cmd.SerialNumber, Cmd,Storage::COMMAND_COMPLETED);
if(ObjectToReturn) {
Handler->ReturnObject(Request, *ObjectToReturn, Response);
} else {
Poco::JSON::Object O;
Cmd.to_json(O);
Handler->ReturnObject(Request, O, Response);
}
return;
}
} else {
SetCommandAsPending(Cmd, Request, Response, Handler);
return;
}
} else {
SetCommandAsPending(Cmd, Request, Response, Handler);
return;
}
} else {
SetCommandAsPending(Cmd, Request, Response, Handler);
return;
}
}
}
bool WaitForRPC(GWObjects::CommandDetails &Cmd,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response, uint64_t Timeout,
bool ReturnValue,
RESTAPIHandler * Handler) {
if (DeviceRegistry()->Connected(Cmd.SerialNumber)) {
GWObjects::CommandDetails ResCmd;
while (Timeout > 0) {
Timeout -= 1000;
Poco::Thread::sleep(1000);
if (Storage()->GetCommand(Cmd.UUID, ResCmd)) {
if (ResCmd.Completed) {
if (ReturnValue) {
Poco::JSON::Object RetObj;
ResCmd.to_json(RetObj);
Handler->ReturnObject(Request, RetObj, Response);
}
return true;
}
}
}
}
if (ReturnValue) {
Poco::JSON::Object RetObj;
Cmd.to_json(RetObj);
Handler->ReturnObject(Request, RetObj, Response);
}
return false;
}
}

View File

@@ -1,49 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "RESTAPI_command.h"
#include "RESTAPI_protocol.h"
#include "StorageService.h"
namespace OpenWifi {
void RESTAPI_command::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
try {
ParseParameters(Request);
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
auto CommandUUID = GetBinding(RESTAPI::Protocol::COMMANDUUID, "");
GWObjects::CommandDetails Command;
if (Storage()->GetCommand(CommandUUID, Command)) {
Poco::JSON::Object RetObj;
Command.to_json(RetObj);
ReturnObject(Request, RetObj, Response);
} else
NotFound(Request, Response);
} else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE) {
auto CommandUUID = GetBinding(RESTAPI::Protocol::COMMANDUUID, "");
if (Storage()->DeleteCommand(CommandUUID)) {
OK(Request, Response);
} else {
NotFound(Request, Response);
}
}
return;
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
}
BadRequest(Request, Response);
}
}

View File

@@ -1,63 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "RESTAPI_commands.h"
#include "RESTAPI_protocol.h"
#include "StorageService.h"
#include "Utils.h"
namespace OpenWifi {
void RESTAPI_commands::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
try {
ParseParameters(Request);
if(!InitQueryBlock()) {
BadRequest(Request, Response, "Illegal parameter value.");
return;
}
auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
std::vector<GWObjects::CommandDetails> Commands;
if (QB_.Newest) {
Storage()->GetNewestCommands(SerialNumber, QB_.Limit, Commands);
} else {
Storage()->GetCommands(SerialNumber, QB_.StartDate, QB_.EndDate, QB_.Offset,
QB_.Limit, Commands);
}
Poco::JSON::Array ArrayObj;
for (const auto &i : Commands) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::COMMANDS, ArrayObj);
ReturnObject(Request, RetObj, Response);
return;
} else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE) {
if (Storage()->DeleteCommands(SerialNumber, QB_.StartDate, QB_.EndDate))
OK(Request, Response);
else
BadRequest(Request, Response);
return;
}
} catch (const Poco::Exception &E) {
Logger_.error(Poco::format("%s: failed with %s", std::string(__func__), E.displayText()));
}
BadRequest(Request, Response);
}
}

View File

@@ -1,80 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "Poco/JSON/Parser.h"
#include "RESTAPI_default_configuration.h"
#include "RESTAPI_GWobjects.h"
#include "RESTAPI_protocol.h"
#include "StorageService.h"
namespace OpenWifi {
void RESTAPI_default_configuration::handleRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
ParseParameters(Request);
if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) {
GWObjects::DefaultConfiguration DefConfig;
if (Storage()->GetDefaultConfiguration(Name, DefConfig)) {
Poco::JSON::Object Obj;
DefConfig.to_json(Obj);
ReturnObject(Request, Obj, Response);
} else {
NotFound(Request, Response);
}
} else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE) {
if (Storage()->DeleteDefaultConfiguration(Name)) {
OK(Request, Response);
} else {
NotFound(Request, Response);
}
} else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST) {
Poco::JSON::Parser IncomingParser;
Poco::JSON::Object::Ptr Obj =
IncomingParser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
GWObjects::DefaultConfiguration DefConfig;
if (!DefConfig.from_json(Obj)) {
BadRequest(Request, Response);
return;
}
if (Storage()->CreateDefaultConfiguration(Name, DefConfig)) {
OK(Request, Response);
} else {
BadRequest(Request, Response);
}
} else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_PUT) {
Poco::JSON::Parser IncomingParser;
Poco::JSON::Object::Ptr Obj =
IncomingParser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
GWObjects::DefaultConfiguration DefConfig;
if (!DefConfig.from_json(Obj)) {
BadRequest(Request, Response);
return;
}
if (Storage()->UpdateDefaultConfiguration(Name, DefConfig)) {
OK(Request, Response);
} else {
BadRequest(Request, Response);
}
} else {
BadRequest(Request, Response);
}
}
}

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