Compare commits

..

30 Commits

Author SHA1 Message Date
stephb9959
67910c982a https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 23:22:00 -07:00
stephb9959
9be196ce40 https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 23:19:28 -07:00
stephb9959
222afe2858 https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 23:19:10 -07:00
stephb9959
40a02c4752 https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 23:11:56 -07:00
stephb9959
7f1577503f https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 23:08:32 -07:00
stephb9959
7ab2e6c96e https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 14:26:45 -07:00
stephb9959
639db8631e https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 14:24:40 -07:00
stephb9959
9fe9b74dea https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 14:22:08 -07:00
stephb9959
20c025f994 https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 14:18:38 -07:00
stephb9959
ee78155b68 https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 14:13:58 -07:00
stephb9959
9f9a866ad3 https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 14:09:13 -07:00
stephb9959
adbd852ccd https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 14:07:43 -07:00
stephb9959
4bb5ee0b86 https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 13:42:34 -07:00
stephb9959
06bb8cebbe https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 13:39:18 -07:00
stephb9959
dde46ce6b2 https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 13:34:13 -07:00
stephb9959
515f8a4fea https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 11:13:49 -07:00
stephb9959
8dcfe04310 https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 10:38:39 -07:00
stephb9959
5db6fc3027 https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-29 10:26:11 -07:00
stephb9959
6ee3cae1db https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-11 21:36:17 -07:00
stephb9959
33e4f8abd8 https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-10 23:16:56 -07:00
stephb9959
d5b4d15307 https://telecominfraproject.atlassian.net/browse/WIFI-10547
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-10 23:07:05 -07:00
stephb9959
8dc3e53fc0 https://telecominfraproject.atlassian.net/browse/WIFI-10245
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-10 16:40:28 -07:00
stephb9959
55b0075c0c https://telecominfraproject.atlassian.net/browse/WIFI-10388
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-07 22:30:28 -07:00
stephb9959
fa434f79c3 https://telecominfraproject.atlassian.net/browse/WIFI-10388
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-04 06:58:29 -07:00
stephb9959
61837a8975 https://telecominfraproject.atlassian.net/browse/WIFI-10388
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-03 08:01:23 -07:00
stephb9959
10ffba95b5 https://telecominfraproject.atlassian.net/browse/WIFI-10388
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-01 09:11:51 -07:00
stephb9959
fd3a6be11a https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-26 14:52:31 -07:00
stephb9959
ec2874748f https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-24 18:18:07 -07:00
stephb9959
1d4aa80205 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10040
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-04 14:01:19 -07:00
stephb9959
34100b5fb0 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10040
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-01 09:31:54 -07:00
18 changed files with 405 additions and 336 deletions

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13)
project(owanalytics VERSION 2.6.0)
project(owanalytics VERSION 2.7.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_GENERATOR "Unix Makefiles")

View File

@@ -9,8 +9,8 @@ RUN apk add --update --no-cache \
FROM build-base AS poco-build
ADD https://api.github.com/repos/stephb9959/poco/git/refs/heads/master version.json
RUN git clone https://github.com/stephb9959/poco /poco
ADD https://api.github.com/repos/AriliaWireless/poco/git/refs/tags/poco-tip-v1 version.json
RUN git clone https://github.com/AriliaWireless/poco --branch poco-tip-v1 /poco
WORKDIR /poco
RUN mkdir cmake-build
@@ -21,8 +21,8 @@ RUN cmake --build . --target install
FROM build-base AS cppkafka-build
ADD https://api.github.com/repos/stephb9959/cppkafka/git/refs/heads/master version.json
RUN git clone https://github.com/stephb9959/cppkafka /cppkafka
ADD https://api.github.com/repos/AriliaWireless/cppkafka/git/refs/tags/tip-v1 version.json
RUN git clone https://github.com/AriliaWireless/cppkafka --branch tip-v1 /cppkafka
WORKDIR /cppkafka
RUN mkdir cmake-build
@@ -31,24 +31,24 @@ RUN cmake ..
RUN cmake --build . --config Release -j8
RUN cmake --build . --target install
FROM build-base AS json-schema-validator-build
FROM build-base AS fmtlib-build
ADD https://api.github.com/repos/pboettch/json-schema-validator/git/refs/heads/master version.json
RUN git clone https://github.com/pboettch/json-schema-validator /json-schema-validator
ADD https://api.github.com/repos/fmtlib/fmt/git/refs/tags/9.0.0 version.json
RUN git clone https://github.com/fmtlib/fmt --branch 9.0.0 /fmtlib
WORKDIR /json-schema-validator
WORKDIR /fmtlib
RUN mkdir cmake-build
WORKDIR cmake-build
RUN cmake ..
RUN make
RUN make install
FROM build-base AS fmtlib-build
FROM build-base AS json-schema-validator-build
ADD https://api.github.com/repos/fmtlib/fmt/git/refs/heads/master version.json
RUN git clone https://github.com/fmtlib/fmt /fmtlib
ADD https://api.github.com/repos/pboettch/json-schema-validator/git/refs/tags/2.1.0 version.json
RUN git clone https://github.com/pboettch/json-schema-validator --branch 2.1.0 /json-schema-validator
WORKDIR /fmtlib
WORKDIR /json-schema-validator
RUN mkdir cmake-build
WORKDIR cmake-build
RUN cmake ..

2
build
View File

@@ -1 +1 @@
69
10

View File

@@ -9,7 +9,7 @@ fullnameOverride: ""
images:
owanalytics:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owanalytics
tag: v2.6.0-RC3
tag: main
pullPolicy: Always
# regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io

View File

@@ -27,71 +27,13 @@ components:
responses:
NotFound:
description: The specified resource was not found.
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
ErrorDetails:
type: string
ErrorDescription:
type: string
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/NotFound'
Unauthorized:
description: The requested does not have sufficient rights to perform the operation.
content:
application/json:
schema:
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
- 9 # EXPIRED_TOKEN
- 10 # RATE_LIMIT_EXCEEDED
- 11 # BAD_MFA_TRANSACTION
- 12 # MFA_FAILURE
- 13 # SECURITY_SERVICE_UNREACHABLE
ErrorDetails:
type: string
ErrorDescription:
type: string
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Unauthorized'
Success:
description: The requested operation was performed.
content:
application/json:
schema:
properties:
Operation:
type: string
Details:
type: string
Code:
type: integer
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Success'
BadRequest:
description: The requested operation failed.
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
ErrorDetails:
type: string
ErrorDescription:
type: integer
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/BadRequest'
schemas:
ObjectInfo:
@@ -1134,42 +1076,6 @@ paths:
404:
$ref: '#/components/responses/NotFound'
/iptocountry:
get:
tags:
- Utility
summary: Get the country code for an IP address
operationId: getIpToCountry
parameters:
- in: query
name: iplist
schema:
type: string
example:
10.2.2.2,10.3.4.3
required: true
responses:
200:
description: List of country codes.
content:
application/json:
schema:
type: object
properties:
enabled:
type: boolean
countryCodes:
type: array
items:
type: string
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/wifiClientHistory:
get:
tags:

View File

@@ -23,6 +23,7 @@ namespace OpenWifi {
}
void DeviceStatusReceiver::run() {
Utils::SetThreadName("dev-status");
Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification());
while(Note && Running_) {
auto Msg = dynamic_cast<DeviceStatusMessage *>(Note.get());

View File

@@ -23,6 +23,7 @@ namespace OpenWifi {
}
void HealthReceiver::run() {
Utils::SetThreadName("dev-health");
Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification());
while(Note && Running_) {
auto Msg = dynamic_cast<HealthMessage *>(Note.get());

View File

@@ -90,7 +90,7 @@ namespace OpenWifi {
}
if(StorageService()->BoardsDB().UpdateRecord("id",Existing.info.id,Existing)) {
VenueCoordinator()->ModifyBoard(Existing.info.id);
VenueCoordinator()->UpdateBoard(Existing.info.id);
AnalyticsObjects::BoardInfo NewBoard;
StorageService()->BoardsDB().GetRecord("id",Existing.info.id,NewBoard);
Poco::JSON::Object Answer;

View File

@@ -5,54 +5,11 @@
#include "RESTAPI_board_timepoint_handler.h"
#include "StorageService.h"
#include <algorithm>
namespace OpenWifi {
static auto find_number_of_buckets(std::vector<AnalyticsObjects::DeviceTimePoint> &p) {
uint32_t buckets=0,cur_buckets=0;
std::string current_serialNumber;
for(const auto &i:p) {
if(current_serialNumber.empty()) {
current_serialNumber = i.device_info.serialNumber;
cur_buckets=0;
}
if(current_serialNumber==i.device_info.serialNumber) {
cur_buckets++;
} else {
buckets = std::max(buckets,cur_buckets);
current_serialNumber=i.device_info.serialNumber;
cur_buckets=1;
}
}
return std::max(buckets,cur_buckets);
}
typedef std::vector< std::vector<AnalyticsObjects::DeviceTimePoint>> split_points;
static void split_in_buckets([[maybe_unused]] uint32_t buckets,std::vector<AnalyticsObjects::DeviceTimePoint> &p,split_points &sp) {
std::string cur_sn;
uint32_t cur_bucket=0;
for(const auto &i:p) {
if(cur_sn.empty()) {
cur_bucket=1;
cur_sn=i.device_info.serialNumber;
}
if(cur_sn==i.device_info.serialNumber) {
if (cur_bucket>sp.size()) {
std::vector<AnalyticsObjects::DeviceTimePoint> tmp_p;
tmp_p.push_back(i);
sp.push_back(tmp_p);
cur_bucket++;
} else {
sp[cur_bucket-1].push_back(i);
cur_bucket++;
}
} else {
cur_bucket=1;
sp[cur_bucket-1].push_back(i);
cur_bucket++;
cur_sn=i.device_info.serialNumber;
}
}
}
typedef std::vector<std::pair<std::uint64_t , std::uint64_t >> bucket_timespans;
typedef std::vector< std::vector<AnalyticsObjects::DeviceTimePoint>> split_points;
template <typename X, typename M> void AverageAPData( X T, const std::vector<M> &Values, AnalyticsObjects::AveragePoint &P) {
if(Values.empty())
@@ -89,6 +46,81 @@ namespace OpenWifi {
P.avg = 0.0;
}
static void NewSort(const AnalyticsObjects::DeviceTimePointList &l,split_points &sp) {
struct {
bool operator()(const AnalyticsObjects::DeviceTimePoint &lhs, const AnalyticsObjects::DeviceTimePoint &rhs) const {
if (lhs.device_info.serialNumber < rhs.device_info.serialNumber) return true;
if (lhs.device_info.serialNumber > rhs.device_info.serialNumber) return false;
return lhs.timestamp < rhs.timestamp;
}
} sort_serial_ts;
// attempt at finding an interval
AnalyticsObjects::DeviceTimePointList tmp{l};
std::sort(tmp.points.begin(),tmp.points.end(),sort_serial_ts);
std::string cur_ser;
std::uint64_t cur_int=0,start_val, last_val, first_val = 0;
for(const auto &point:tmp.points) {
if(cur_ser.empty()) {
start_val = point.timestamp;
cur_ser = point.serialNumber;
first_val = point.timestamp;
continue;
}
if(cur_ser==point.serialNumber) {
auto this_int = point.timestamp - start_val;
if(cur_int) {
if(this_int<cur_int) {
cur_int = this_int;
}
} else {
cur_int = this_int;
}
start_val = point.timestamp;
} else {
cur_ser = point.serialNumber;
start_val = point.timestamp;
}
last_val = point.timestamp;
}
// std::cout << "Intervals: " << cur_int << std::endl;
std::vector<std::pair<std::uint64_t,std::uint64_t>> time_slots; // timeslot 0 has <t1,t2>
std::vector<std::set<std::string>> serial_numbers; // serial number already in a timeslot.
std::uint64_t cur_first=first_val,cur_end=0;
sp.clear();
while(cur_end<last_val) {
std::pair<std::uint64_t,std::uint64_t> e;
e.first = cur_first;
e.second = e.first + cur_int-1;
cur_first = e.second+1;
cur_end = e.second;
time_slots.emplace_back(e);
std::set<std::string> q;
serial_numbers.emplace_back(q);
std::vector<AnalyticsObjects::DeviceTimePoint> qq;
sp.emplace_back(qq);
}
for(const auto &point:tmp.points) {
std::uint64_t slot_index=0;
for(const auto &slot:time_slots) {
if(point.timestamp >= slot.first && point.timestamp <= slot.second) {
serial_numbers[slot_index].insert(point.serialNumber);
sp[slot_index].emplace_back(point);
}
slot_index++;
}
}
}
void RESTAPI_board_timepoint_handler::DoGet() {
auto id = GetBinding("id","");
if(id.empty() || !Utils::ValidUUID(id)) {
@@ -102,7 +134,12 @@ namespace OpenWifi {
auto fromDate = GetParameter("fromDate",0);
auto endDate = GetParameter("endDate",0);
auto maxRecords = GetParameter("maxRecords",1000);
std::uint64_t maxRecords;
if(Request->has("limit"))
maxRecords = QB_.Limit;
else
maxRecords = GetParameter("maxRecords",1000);
auto statsOnly = GetBoolParameter("statsOnly");
auto pointsOnly = GetBoolParameter("pointsOnly");
auto pointsStatsOnly = GetBoolParameter("pointsStatsOnly");
@@ -115,71 +152,39 @@ namespace OpenWifi {
return ReturnObject(Answer);
}
auto Points = std::make_unique<AnalyticsObjects::DeviceTimePointList>();
StorageService()->TimePointsDB().SelectRecords(id,fromDate, endDate, maxRecords, Points->points);
AnalyticsObjects::DeviceTimePointList Points;
StorageService()->TimePointsDB().SelectRecords(id,fromDate, endDate, maxRecords, Points.points);
std::cout << "1 MaxRecords=" << maxRecords << " retrieved=" << Points.points.size() << std::endl;
// sort by timestamp & serial number.
struct {
bool operator()(const AnalyticsObjects::DeviceTimePoint &lhs, const AnalyticsObjects::DeviceTimePoint &rhs) const {
if(lhs.device_info.serialNumber < rhs.device_info.serialNumber) return true;
if(lhs.device_info.serialNumber > rhs.device_info.serialNumber) return false;
return lhs.timestamp < rhs.timestamp;
}
} DeviceTimePoint_sort;
split_points sp;
struct {
bool operator()(const AnalyticsObjects::SSIDTimePoint &lhs, const AnalyticsObjects::SSIDTimePoint &rhs) const {
if(lhs.ssid < rhs.ssid) return true;
if(lhs.ssid > rhs.ssid) return false;
return lhs.bssid < rhs.bssid;
}
} SSID_sort;
NewSort(Points,sp);
std::cout << __LINE__ << std::endl;
struct {
bool operator()(const AnalyticsObjects::UETimePoint &lhs, const AnalyticsObjects::UETimePoint &rhs) const {
if(lhs.station < rhs.station) return true;
return false;
}
} Association_sort;
std::sort( Points->points.begin(), Points->points.end(), DeviceTimePoint_sort);
auto BucketsNeeded = find_number_of_buckets(Points->points);
auto sp = std::make_unique<split_points>();
split_in_buckets(BucketsNeeded,Points->points, *sp);
// must sort each bucket according to serial number.
for(auto &i: *sp) {
std::sort(i.begin(),i.end(),DeviceTimePoint_sort);
// now sort according to UEs within a block
for(auto &j:i) {
std::sort(j.ssid_data.begin(),j.ssid_data.end(),SSID_sort);
for(auto &k:j.ssid_data) {
std::sort(k.associations.begin(),k.associations.end(),Association_sort);
}
}
}
auto Answer = std::make_unique<Poco::JSON::Object>();
Poco::JSON::Object Answer;
if(!pointsStatsOnly) {
auto Points_OuterArray = std::make_unique<Poco::JSON::Array>();
for (const auto &point_list:*sp) {
Poco::JSON::Array Points_OuterArray;
for (const auto &point_list:sp) {
Poco::JSON::Array Points_InnerArray;
for (const auto &point: point_list) {
Poco::JSON::Object O;
point.to_json(O);
Points_InnerArray.add(O);
}
Points_OuterArray->add(Points_InnerArray);
Points_OuterArray.add(Points_InnerArray);
}
Answer->set("points",*Points_OuterArray);
Answer.set("points",Points_OuterArray);
}
// calculate the stats for each time slot
if(!pointsOnly) {
auto Stats_Array = std::make_unique<Poco::JSON::Array>();
for (const auto &point_list:*sp) {
Poco::JSON::Array Stats_Array;
for (const auto &point_list:sp) {
AnalyticsObjects::DeviceTimePointAnalysis DTPA;
if(point_list.empty())
continue;
DTPA.timestamp = point_list[0].timestamp;
AverageAPData(&AnalyticsObjects::APTimePoint::tx_bytes_bw, point_list, DTPA.tx_bytes_bw);
AverageAPData(&AnalyticsObjects::APTimePoint::rx_bytes_bw, point_list, DTPA.rx_bytes_bw);
@@ -200,12 +205,12 @@ namespace OpenWifi {
Poco::JSON::Object Stats_point;
DTPA.to_json(Stats_point);
Stats_Array->add(Stats_point);
Stats_Array.add(Stats_point);
}
Answer->set("stats", *Stats_Array);
Answer.set("stats", Stats_Array);
}
return ReturnObject(*Answer);
return ReturnObject(Answer);
}
void RESTAPI_board_timepoint_handler::DoDelete() {

View File

@@ -25,6 +25,7 @@ namespace OpenWifi {
void StateReceiver::run() {
Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification());
Utils::SetThreadName("dev-state");
while(Note && Running_) {
auto Msg = dynamic_cast<StateMessage *>(Note.get());
if(Msg!= nullptr) {

View File

@@ -66,6 +66,7 @@ namespace OpenWifi {
}
void Storage::run() {
Utils::SetThreadName("strg-updtr");
Running_ = true ;
bool FirstRun=true;
long Retry = 2000;

View File

@@ -13,9 +13,27 @@ namespace OpenWifi {
int VenueCoordinator::Start() {
GetBoardList();
Worker_.start(*this);
ReconcileTimerCallback_ = std::make_unique<Poco::TimerCallback<VenueCoordinator>>(*this,&VenueCoordinator::onReconcileTimer);
ReconcileTimerTimer_.setStartInterval( 3 * 60 * 1000 );
ReconcileTimerTimer_.setPeriodicInterval(3 * 60 * 1000); // 1 hours
ReconcileTimerTimer_.start(*ReconcileTimerCallback_, MicroService::instance().TimerPool());
return 0;
}
void VenueCoordinator::onReconcileTimer([[maybe_unused]] Poco::Timer &timer) {
std::lock_guard G(Mutex_);
Utils::SetThreadName("brd-refresh");
Logger().information("Starting to reconcile board information.");
for(const auto &[board_id, watcher]:Watchers_) {
Logger().information(fmt::format("Updating: {}", board_id));
UpdateBoard(board_id);
}
Logger().information("Finished reconciling board information.");
}
void VenueCoordinator::GetBoardList() {
BoardsToWatch_.clear();
auto F = [&](const AnalyticsObjects::BoardInfo &B) ->bool {
@@ -34,6 +52,7 @@ namespace OpenWifi {
}
void VenueCoordinator::run() {
Utils::SetThreadName("venue-coord");
Running_=true;
while(Running_) {
Poco::Thread::trySleep(20000);
@@ -58,9 +77,11 @@ namespace OpenWifi {
void VenueCoordinator::RetireBoard(const AnalyticsObjects::BoardInfo &B) {
Logger().error(fmt::format("Venue board '{}' is no longer in the system. Retiring its associated board.", B.venueList[0].name));
/*
StopBoard(B.info.id);
StorageService()->BoardsDB().DeleteRecord("id",B.info.id);
StorageService()->TimePointsDB().DeleteRecords(fmt::format(" boardId='{}' ", B.info.id));
*/
}
bool VenueCoordinator::GetDevicesForBoard(const AnalyticsObjects::BoardInfo &B, std::vector<uint64_t> & Devices, bool & VenueExists) {
@@ -118,7 +139,7 @@ namespace OpenWifi {
}
}
void VenueCoordinator::ModifyBoard(const std::string &id) {
void VenueCoordinator::UpdateBoard(const std::string &id) {
AnalyticsObjects::BoardInfo B;
if(StorageService()->BoardsDB().GetRecord("id",id,B)) {
std::vector<uint64_t> Devices;
@@ -129,15 +150,15 @@ namespace OpenWifi {
if(it!=ExistingBoards_.end()) {
if(it->second!=Devices) {
auto it2 = Watchers_.find(id);
if(it2!=Watchers_.end())
if(it2!=Watchers_.end()) {
it2->second->ModifySerialNumbers(Devices);
}
ExistingBoards_[id] = Devices;
Logger().information(fmt::format("Modified board {}",B.info.name));
} else {
Logger().information(fmt::format("No device changes in board {}",B.info.name));
}
}
Logger().information(fmt::format("Modified board {}",B.info.name));
return;
}

View File

@@ -3,9 +3,12 @@
//
#pragma once
#include "framework/MicroService.h"
#include "VenueWatcher.h"
#include "Poco/Timer.h"
namespace OpenWifi {
class VenueCoordinator : public SubSystemServer, Poco::Runnable {
@@ -21,7 +24,7 @@ namespace OpenWifi {
void run() override;
void StopBoard(const std::string &id);
void ModifyBoard(const std::string &id);
void UpdateBoard(const std::string &id);
void AddBoard(const std::string &id);
bool GetDevicesForBoard(const AnalyticsObjects::BoardInfo &B, std::vector<uint64_t> & Devices, bool & VenueExists);
@@ -30,13 +33,17 @@ namespace OpenWifi {
bool Watching(const std::string &id);
void RetireBoard(const AnalyticsObjects::BoardInfo &B);
private:
Poco::Thread Worker_;
std::atomic_bool Running_=false;
std::set<AnalyticsObjects::BoardInfo> BoardsToWatch_;
std::map<std::string,std::shared_ptr<VenueWatcher>> Watchers_;
void onReconcileTimer(Poco::Timer & timer);
std::map<std::string,std::vector<uint64_t>> ExistingBoards_;
private:
Poco::Thread Worker_;
std::atomic_bool Running_=false;
std::set<AnalyticsObjects::BoardInfo> BoardsToWatch_;
std::map<std::string,std::shared_ptr<VenueWatcher>> Watchers_;
std::unique_ptr<Poco::TimerCallback<VenueCoordinator>> ReconcileTimerCallback_;
Poco::Timer ReconcileTimerTimer_;
std::map<std::string,std::vector<uint64_t>> ExistingBoards_;
VenueCoordinator() noexcept:
SubSystemServer("VenueCoordinator", "VENUE-COORD", "venue.coordinator")

View File

@@ -34,6 +34,7 @@ namespace OpenWifi {
}
void VenueWatcher::run() {
Utils::SetThreadName("venue-watch");
Running_ = true;
Poco::AutoPtr<Poco::Notification> Msg(Queue_.waitDequeueNotification());
while(Msg && Running_) {

View File

@@ -69,9 +69,11 @@ namespace OpenWifi {
void GetDevices(std::vector<AnalyticsObjects::DeviceInfo> & DI);
void GetBandwidth(uint64_t start, uint64_t end, uint64_t interval , AnalyticsObjects::BandwidthAnalysis & BW);
inline std::string Venue() const {
return venue_id_;
}
private:
std::recursive_mutex Mutex_;
std::mutex Mutex_;
std::string boardId_;
std::string venue_id_;
Poco::NotificationQueue Queue_;

View File

@@ -27,6 +27,11 @@ namespace OpenWifi {
inline uint64_t Now() { return std::time(nullptr); };
}
namespace OpenWifi::Utils {
std::vector<unsigned char> base64decode(const std::string& input);
std::string base64encode(const unsigned char *input, uint32_t size);
}
using namespace std::chrono_literals;
#include "Poco/Util/Application.h"
@@ -238,6 +243,11 @@ namespace OpenWifi::RESTAPI_utils {
Obj.set(Field,Value);
}
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Poco::Data::BLOB &Value) {
auto Result = Utils::base64encode((const unsigned char *)Value.rawContent(),Value.size());
Obj.set(Field,Result);
}
inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::StringPairVec & S) {
Poco::JSON::Array Array;
for(const auto &i:S) {
@@ -334,12 +344,12 @@ namespace OpenWifi::RESTAPI_utils {
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, double & Value) {
if(Obj->has(Field) && !Obj->isNull(Field))
Value = (double) Obj->get(Field);
Value = (double)Obj->get(Field);
}
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, float & Value) {
if(Obj->has(Field) && !Obj->isNull(Field))
Value = (float) Obj->get(Field);
Value = (float)Obj->get(Field);
}
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, bool &Value) {
@@ -374,7 +384,14 @@ namespace OpenWifi::RESTAPI_utils {
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, uint64_t &Value) {
if(Obj->has(Field) && !Obj->isNull(Field))
Value = (uint64_t ) Obj->get(Field);
Value = (uint64_t)Obj->get(Field);
}
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, Poco::Data::BLOB &Value) {
if(Obj->has(Field) && !Obj->isNull(Field)) {
auto Result = Utils::base64decode(Obj->get(Field).toString());
Value.assignRaw((const unsigned char *)&Result[0],Result.size());
}
}
inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, Types::StringPairVec &Vec) {
@@ -643,6 +660,27 @@ namespace OpenWifi::RESTAPI_utils {
namespace OpenWifi::Utils {
inline void SetThreadName(const char *name) {
#ifdef __linux__
Poco::Thread::current()->setName(name);
pthread_setname_np(pthread_self(), name);
#endif
#ifdef __APPLE__
Poco::Thread::current()->setName(name);
pthread_setname_np(name);
#endif
}
inline void SetThreadName(Poco::Thread &thr, const char *name) {
#ifdef __linux__
thr.setName(name);
pthread_setname_np(thr.tid(), name);
#endif
#ifdef __APPLE__
thr.setName(name);
#endif
}
enum MediaTypeEncodings {
PLAIN,
BINARY,
@@ -665,6 +703,19 @@ namespace OpenWifi::Utils {
return (std::all_of(UUID.begin(),UUID.end(),[&](auto i){ if(i=='-') dashes++; return i=='-' || std::isxdigit(i);})) && (dashes>0);
}
template <typename ...Args> std::string ComputeHash(Args&&... args) {
Poco::SHA2Engine E;
auto as_string = [](auto p) {
if constexpr(std::is_arithmetic_v<decltype(p)>) {
return std::to_string(p);
} else {
return p;
}
};
(E.update(as_string(args)),...);
return Poco::SHA2Engine::digestToHex(E.digest());
}
[[nodiscard]] inline std::vector<std::string> Split(const std::string &List, char Delimiter=',' ) {
std::vector<std::string> ReturnList;
@@ -1316,7 +1367,7 @@ namespace OpenWifi {
inline void Start();
inline void Stop();
private:
std::atomic_bool Running_ = false;
mutable std::atomic_bool Running_ = false;
Poco::Thread Thread_;
};
@@ -1361,13 +1412,14 @@ namespace OpenWifi {
[[nodiscard]] inline const std::string &Address() const { return address_; };
[[nodiscard]] inline uint32_t Port() const { return port_; };
[[nodiscard]] inline const std::string &KeyFile() const { return key_file_; };
[[nodiscard]] inline const std::string &CertFile() const { return cert_file_; };
[[nodiscard]] inline const std::string &RootCA() const { return root_ca_; };
[[nodiscard]] inline const std::string &KeyFilePassword() const { return key_file_password_; };
[[nodiscard]] inline const std::string &IssuerCertFile() const { return issuer_cert_file_; };
[[nodiscard]] inline const std::string &Name() const { return name_; };
[[nodiscard]] inline auto KeyFile() const { return key_file_; };
[[nodiscard]] inline auto CertFile() const { return cert_file_; };
[[nodiscard]] inline auto RootCA() const { return root_ca_; };
[[nodiscard]] inline auto KeyFilePassword() const { return key_file_password_; };
[[nodiscard]] inline auto IssuerCertFile() const { return issuer_cert_file_; };
[[nodiscard]] inline auto Name() const { return name_; };
[[nodiscard]] inline int Backlog() const { return backlog_; }
[[nodiscard]] inline auto Cas() const { return cas_; }
[[nodiscard]] inline Poco::Net::SecureServerSocket CreateSecureSocket(Poco::Logger &L) const {
Poco::Net::Context::Params P;
@@ -1847,7 +1899,8 @@ namespace OpenWifi {
Request = &RequestIn;
Response = &ResponseIn;
Poco::Thread::current()->setName("WebServerThread_" + std::to_string(TransactionId_));
// std::string th_name = "restsvr_" + std::to_string(TransactionId_);
// Utils::SetThreadName(th_name.c_str());
if(Request->getContentLength()>0) {
if(Request->getContentType().find("application/json")!=std::string::npos) {
@@ -2042,6 +2095,17 @@ namespace OpenWifi {
return false;
}
static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, Poco::Data::BLOB &Value) {
if(O->has(Field)) {
std::string Content = O->get(Field).toString();
auto DecodedBlob = Utils::base64decode(Content);
Value.assignRaw((const unsigned char *)&DecodedBlob[0],DecodedBlob.size());
return true;
}
return false;
}
template <typename T> bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, const T &value, T & assignee) {
if(O->has(Field)) {
assignee = value;
@@ -2382,6 +2446,7 @@ namespace OpenWifi {
Poco::Net::HTTPServerResponse *Response= nullptr;
SecurityObjects::UserInfoAndPolicy UserInfo_;
QueryBlock QB_;
const std::string & Requester() const { return REST_Requester_; }
protected:
BindingMap Bindings_;
Poco::URI::QueryParameters Parameters_;
@@ -2398,6 +2463,7 @@ namespace OpenWifi {
RateLimit MyRates_;
uint64_t TransactionId_;
Poco::JSON::Object::Ptr ParsedBody_;
std::string REST_Requester_;
};
class RESTAPI_UnknownRequestHandler : public RESTAPIHandler {
@@ -2579,7 +2645,7 @@ namespace OpenWifi {
private:
std::recursive_mutex Mutex_;
Poco::Thread Worker_;
std::atomic_bool Running_=false;
mutable std::atomic_bool Running_=false;
Poco::NotificationQueue Queue_;
};
@@ -2605,7 +2671,7 @@ namespace OpenWifi {
private:
std::recursive_mutex Mutex_;
Poco::Thread Worker_;
std::atomic_bool Running_=false;
mutable std::atomic_bool Running_=false;
};
class KafkaDispatcher : public Poco::Runnable {
@@ -2662,6 +2728,7 @@ namespace OpenWifi {
inline void run() override {
Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification());
Utils::SetThreadName("kafka:dispatch");
while(Note && Running_) {
auto Msg = dynamic_cast<KafkaMessage*>(Note.get());
if(Msg!= nullptr) {
@@ -2684,12 +2751,12 @@ namespace OpenWifi {
}
private:
std::recursive_mutex Mutex_;
Types::NotifyTable Notifiers_;
Poco::Thread Worker_;
std::atomic_bool Running_=false;
uint64_t FunctionId_=1;
Poco::NotificationQueue Queue_;
std::recursive_mutex Mutex_;
Types::NotifyTable Notifiers_;
Poco::Thread Worker_;
mutable std::atomic_bool Running_=false;
uint64_t FunctionId_=1;
Poco::NotificationQueue Queue_;
};
class KafkaManager : public SubSystemServer {
@@ -2882,6 +2949,7 @@ namespace OpenWifi {
void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) override
{
Utils::SetThreadName("alb-request");
try {
if((id_ % 100) == 0) {
Logger_.debug(fmt::format("ALB-REQUEST({}): ALB Request {}.",
@@ -2950,7 +3018,7 @@ namespace OpenWifi {
std::unique_ptr<Poco::Net::HTTPServer> Server_;
std::unique_ptr<Poco::Net::ServerSocket> Socket_;
int Port_ = 0;
std::atomic_bool Running_=false;
mutable std::atomic_bool Running_=false;
};
inline auto ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); }
@@ -2970,7 +3038,7 @@ namespace OpenWifi {
}
int Start() override;
inline void Stop() override {
Logger().information("Stopping ");
Logger().information("Stopping...");
for( const auto & svr : RESTServers_ )
svr->stop();
Pool_.stopAll();
@@ -2978,22 +3046,23 @@ namespace OpenWifi {
RESTServers_.clear();
}
inline void reinitialize(Poco::Util::Application &self) override;
inline Poco::Net::HTTPRequestHandler *CallServer(const std::string &Path, uint64_t Id) {
RESTAPIHandler::BindingMap Bindings;
Poco::Thread::current()->setName(fmt::format("RESTAPI_ExtServer_{}",Id));
Utils::SetThreadName(fmt::format("x-rest:{}",Id).c_str());
return RESTAPI_ExtRouter(Path, Bindings, Logger(), Server_, Id);
}
const Poco::ThreadPool & Pool() { return Pool_; }
private:
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> RESTServers_;
Poco::ThreadPool Pool_;
Poco::ThreadPool Pool_{"x-rest",2,32};
RESTAPI_GenericServer Server_;
RESTAPI_ExtServer() noexcept:
SubSystemServer("RESTAPI_ExtServer", "RESTAPIServer", "openwifi.restapi"),
Pool_("RESTAPI_ExtServer",4,50,120)
SubSystemServer("RESTAPI_ExtServer", "REST-XSRV", "openwifi.restapi")
{
}
};
@@ -3006,7 +3075,7 @@ namespace OpenWifi {
inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override {
try {
Poco::URI uri(Request.getURI());
Poco::Thread::current()->setName(fmt::format("ExtWebServer_{}",TransactionId_));
Utils::SetThreadName(fmt::format("x-rest:{}",TransactionId_).c_str());
return RESTAPI_ExtServer()->CallServer(uri.getPath(), TransactionId_++);
} catch (...) {
@@ -3104,7 +3173,7 @@ namespace OpenWifi {
inline int Start() override;
inline void Stop() override {
Logger().information("Stopping ");
Logger().information("Stopping...");
for( const auto & svr : RESTServers_ )
svr->stop();
Pool_.stopAll();
@@ -3115,17 +3184,18 @@ namespace OpenWifi {
inline Poco::Net::HTTPRequestHandler *CallServer(const std::string &Path, uint64_t Id) {
RESTAPIHandler::BindingMap Bindings;
Poco::Thread::current()->setName(fmt::format("RESTAPI_IntServer_{}",Id));
Utils::SetThreadName(fmt::format("i-rest:{}",Id).c_str());
return RESTAPI_IntRouter(Path, Bindings, Logger(), Server_, Id);
}
const Poco::ThreadPool & Pool() { return Pool_; }
private:
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> RESTServers_;
Poco::ThreadPool Pool_;
Poco::ThreadPool Pool_{"i-rest",2,16};
RESTAPI_GenericServer Server_;
RESTAPI_IntServer() noexcept:
SubSystemServer("RESTAPI_IntServer", "REST-ISRV", "openwifi.internal.restapi"),
Pool_("RESTAPI_IntServer",4,50,120)
SubSystemServer("RESTAPI_IntServer", "REST-ISRV", "openwifi.internal.restapi")
{
}
};
@@ -3136,6 +3206,7 @@ namespace OpenWifi {
public:
inline IntRequestHandlerFactory() = default;
inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override {
Utils::SetThreadName(fmt::format("i-rest:{}",TransactionId_).c_str());
Poco::URI uri(Request.getURI());
return RESTAPI_IntServer()->CallServer(uri.getPath(), TransactionId_);
}
@@ -3179,7 +3250,6 @@ namespace OpenWifi {
}
[[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]] inline const std::string & WWWAssetsDir() { return WWWAssetsDir_; }
[[nodiscard]] bool Debug() const { return DebugMode_; }
@@ -3212,7 +3282,12 @@ namespace OpenWifi {
return Poco::Logger::get(Name);
}
static inline void Exit(int Reason);
virtual void GetExtraConfiguration(Poco::JSON::Object & Cfg) {
Cfg.set("additionalConfiguration",false);
}
static inline void Exit(int Reason);
inline void BusMessageReceived(const std::string &Key, const std::string & Payload);
inline MicroServiceMetaVec GetServices(const std::string & Type);
inline MicroServiceMetaVec GetServices();
@@ -3248,7 +3323,6 @@ namespace OpenWifi {
inline std::string ConfigPath(const std::string &Key);
inline std::string Encrypt(const std::string &S);
inline std::string Decrypt(const std::string &S);
inline std::string CreateHash(const std::string &S);
inline std::string MakeSystemEventMessage( const std::string & Type ) const;
[[nodiscard]] inline bool IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request);
inline static void SavePID();
@@ -3278,6 +3352,9 @@ namespace OpenWifi {
return Signer_.sign(T,Algo);
}
}
inline Poco::ThreadPool & TimerPool() { return TimerPool_; }
private:
static MicroService * instance_;
bool HelpRequested_ = false;
@@ -3291,7 +3368,6 @@ namespace OpenWifi {
std::string WWWAssetsDir_;
Poco::Crypto::CipherFactory & CipherFactory_ = Poco::Crypto::CipherFactory::defaultFactory();
Poco::Crypto::Cipher * Cipher_ = nullptr;
Poco::SHA2Engine SHA2_;
MicroServiceMetaMap Services_;
std::string MyHash_;
std::string MyPrivateEndPoint_;
@@ -3312,6 +3388,7 @@ namespace OpenWifi {
bool NoBuiltInCrypto_=false;
Poco::JWT::Signer Signer_;
Poco::Logger &Logger_;
Poco::ThreadPool TimerPool_{"timer:pool",2,16};
};
inline void MicroService::Exit(int Reason) {
@@ -3461,7 +3538,7 @@ namespace OpenWifi {
MyPrivateEndPoint_ = ConfigGetString("openwifi.system.uri.private");
MyPublicEndPoint_ = ConfigGetString("openwifi.system.uri.public");
UIURI_ = ConfigGetString("openwifi.system.uri.ui");
MyHash_ = CreateHash(MyPublicEndPoint_);
MyHash_ = Utils::ComputeHash(MyPublicEndPoint_);
}
void MicroServicePostInitialization();
@@ -3524,7 +3601,7 @@ namespace OpenWifi {
void DaemonPostInitialization(Poco::Util::Application &self);
inline void MicroService::initialize(Poco::Util::Application &self) {
// add the default services
// add the default services
LoadConfigurationFile();
InitializeLoggingSystem();
@@ -3798,11 +3875,6 @@ namespace OpenWifi {
return Cipher_->decryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);;
}
inline std::string MicroService::CreateHash(const std::string &S) {
SHA2_.update(S);
return Utils::ToHex(SHA2_.digest());
}
inline std::string MicroService::MakeSystemEventMessage( const std::string & Type ) const {
Poco::JSON::Object Obj;
Obj.set(KafkaTopics::ServiceEvents::Fields::EVENT,Type);
@@ -3865,6 +3937,7 @@ namespace OpenWifi {
Params->setMaxThreads(50);
Params->setMaxQueued(200);
Params->setKeepAlive(true);
Params->setName("ws:xrest");
std::unique_ptr<Poco::Net::HTTPServer> NewServer;
if(MicroService::instance().NoAPISecurity()) {
@@ -3901,6 +3974,7 @@ namespace OpenWifi {
Params->setMaxThreads(50);
Params->setMaxQueued(200);
Params->setKeepAlive(true);
Params->setName("ws:irest");
std::unique_ptr<Poco::Net::HTTPServer> NewServer;
if(MicroService::instance().NoAPISecurity()) {
@@ -3918,7 +3992,6 @@ namespace OpenWifi {
}
inline int MicroService::main([[maybe_unused]] const ArgVec &args) {
MyErrorHandler ErrorHandler(*this);
Poco::ErrorHandler::set(&ErrorHandler);
@@ -4025,6 +4098,7 @@ namespace OpenWifi {
Port_ = (int)MicroService::instance().ConfigGetInt("alb.port",15015);
Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_);
auto Params = new Poco::Net::HTTPServerParams;
Params->setName("ws:alb");
Server_ = std::make_unique<Poco::Net::HTTPServer>(new ALBRequestHandlerFactory(Logger()), *Socket_, Params);
Server_->start();
}
@@ -4034,6 +4108,7 @@ namespace OpenWifi {
inline void BusEventManager::run() {
Running_ = true;
Utils::SetThreadName("fmwk:EventMgr");
auto Msg = MicroService::instance().MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_JOIN);
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,MicroService::instance().PrivateEndPoint(),Msg, false);
while(Running_) {
@@ -4119,6 +4194,8 @@ namespace OpenWifi {
}
inline void KafkaProducer::run() {
Utils::SetThreadName("Kafka:Prod");
cppkafka::Configuration Config({
{ "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") },
{ "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") }
@@ -4157,6 +4234,8 @@ namespace OpenWifi {
}
inline void KafkaConsumer::run() {
Utils::SetThreadName("Kafka:Cons");
cppkafka::Configuration Config({
{ "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") },
{ "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") },
@@ -4295,6 +4374,11 @@ namespace OpenWifi {
Answer.set("certificates", Certificates);
return ReturnObject(Answer);
}
if(GetBoolParameter("extraConfiguration")) {
Poco::JSON::Object Answer;
MicroService::instance().GetExtraConfiguration(Answer);
return ReturnObject(Answer);
}
BadRequest(RESTAPI::Errors::InvalidCommand);
}
@@ -4667,6 +4751,7 @@ namespace OpenWifi {
inline bool RESTAPIHandler::IsAuthorized( bool & Expired , [[maybe_unused]] bool & Contacted , bool Sub ) {
if(Internal_ && Request->has("X-INTERNAL-NAME")) {
auto Allowed = MicroService::instance().IsValidAPIKEY(*Request);
Contacted = true;
if(!Allowed) {
if(Server_.LogBadTokens(false)) {
Logger_.debug(fmt::format("I-REQ-DENIED({}): Method={} Path={}",
@@ -4675,6 +4760,7 @@ namespace OpenWifi {
}
} else {
auto Id = Request->get("X-INTERNAL-NAME", "unknown");
REST_Requester_ = Id;
if(Server_.LogIt(Request->getMethod(),true)) {
Logger_.debug(fmt::format("I-REQ-ALLOWED({}): User='{}' Method={} Path={}",
Utils::FormatIPv6(Request->clientAddress().toString()), Id,
@@ -4698,6 +4784,7 @@ namespace OpenWifi {
#else
if (AuthClient()->IsAuthorized( SessionToken_, UserInfo_, Expired, Contacted, Sub)) {
#endif
REST_Requester_ = UserInfo_.userinfo.email;
if(Server_.LogIt(Request->getMethod(),true)) {
Logger_.debug(fmt::format("X-REQ-ALLOWED({}): User='{}@{}' Method={} Path={}",
UserInfo_.userinfo.email,
@@ -4815,8 +4902,8 @@ namespace OpenWifi {
[[nodiscard]] bool SendToUser(const std::string &userName, const std::string &Payload);
void SendToAll(const std::string &Payload);
private:
std::atomic_bool Running_ = false;
Poco::Thread Thr_;
mutable std::atomic_bool Running_ = false;
Poco::Thread Thr_;
// std::unique_ptr<MyParallelSocketReactor> ReactorPool_;
Poco::Net::SocketReactor Reactor_;
Poco::Thread ReactorThread_;
@@ -4906,12 +4993,13 @@ namespace OpenWifi {
[[nodiscard]] inline bool SendToUser(const std::string &userName, const std::string &Payload);
inline WebSocketClientServer::WebSocketClientServer() noexcept:
SubSystemServer("WebSocketClientServer", "WSCLNT-SVR", "websocketclients")
SubSystemServer("WebSocketClientServer", "UI-WSCLNT-SVR", "websocketclients")
{
}
inline void WebSocketClientServer::run() {
Running_ = true ;
Utils::SetThreadName("ws:uiclnt-svr");
while(Running_) {
Poco::Thread::trySleep(2000);
@@ -4959,8 +5047,12 @@ namespace OpenWifi {
for(const auto &client:Clients_) {
if(client.second.second == UserName) {
if(client.second.first->Send(Payload))
Sent++;
try {
if (client.second.first->Send(Payload))
Sent++;
} catch (...) {
return false;
}
}
}
return Sent>0;
@@ -4982,70 +5074,70 @@ namespace OpenWifi {
int flags;
int n;
bool Done=false;
Poco::Buffer<char> IncomingFrame(0);
n = WS_->receiveFrame(IncomingFrame, flags);
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
try {
Poco::Buffer<char> IncomingFrame(0);
n = WS_->receiveFrame(IncomingFrame, flags);
auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
if(n==0) {
return delete this;
}
if (n == 0) {
return delete this;
}
switch(Op) {
case Poco::Net::WebSocket::FRAME_OP_PING: {
WS_->sendFrame("", 0,
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
}
break;
case Poco::Net::WebSocket::FRAME_OP_PONG: {
}
break;
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
Logger().warning(Poco::format("CLOSE(%s): Client is closing its connection.",Id_));
Done=true;
}
break;
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
IncomingFrame.append(0);
if(!Authenticated_) {
std::string Frame{IncomingFrame.begin()};
auto Tokens = Utils::Split(Frame,':');
bool Expired = false, Contacted = false;
if(Tokens.size()==2 && AuthClient()->IsAuthorized(Tokens[1], UserInfo_, Expired, Contacted)) {
Authenticated_=true;
std::string S{"Welcome! Bienvenue! Bienvenidos!"};
WS_->sendFrame(S.c_str(),S.size());
WebSocketClientServer()->SetUser(Id_,UserInfo_.userinfo.email);
} else {
std::string S{"Invalid token. Closing connection."};
WS_->sendFrame(S.c_str(),S.size());
Done=true;
}
switch (Op) {
case Poco::Net::WebSocket::FRAME_OP_PING: {
WS_->sendFrame("", 0,
(int)Poco::Net::WebSocket::FRAME_OP_PONG |
(int)Poco::Net::WebSocket::FRAME_FLAG_FIN);
} break;
case Poco::Net::WebSocket::FRAME_OP_PONG: {
} break;
case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
Logger().warning(Poco::format("CLOSE(%s): UI Client is closing its connection.", Id_));
Done = true;
} break;
case Poco::Net::WebSocket::FRAME_OP_TEXT: {
IncomingFrame.append(0);
if (!Authenticated_) {
std::string Frame{IncomingFrame.begin()};
auto Tokens = Utils::Split(Frame, ':');
bool Expired = false, Contacted = false;
if (Tokens.size() == 2 &&
AuthClient()->IsAuthorized(Tokens[1], UserInfo_, Expired, Contacted)) {
Authenticated_ = true;
std::string S{"Welcome! Bienvenue! Bienvenidos!"};
WS_->sendFrame(S.c_str(), S.size());
WebSocketClientServer()->SetUser(Id_, UserInfo_.userinfo.email);
} else {
std::string S{"Invalid token. Closing connection."};
WS_->sendFrame(S.c_str(), S.size());
Done = true;
}
} else {
try {
Poco::JSON::Parser P;
auto Obj = P.parse(IncomingFrame.begin())
.extract<Poco::JSON::Object::Ptr>();
std::string Answer;
if(Processor_!= nullptr)
Processor_->Processor(Obj, Answer, Done);
if (!Answer.empty())
WS_->sendFrame(Answer.c_str(), (int) Answer.size());
else {
WS_->sendFrame("{}", 2);
}
} catch (const Poco::JSON::JSONException & E) {
Logger().log(E);
}
}
}
break;
default:
{
}
}
} else {
try {
Poco::JSON::Parser P;
auto Obj =
P.parse(IncomingFrame.begin()).extract<Poco::JSON::Object::Ptr>();
std::string Answer;
if (Processor_ != nullptr)
Processor_->Processor(Obj, Answer, Done);
if (!Answer.empty())
WS_->sendFrame(Answer.c_str(), (int)Answer.size());
else {
WS_->sendFrame("{}", 2);
}
} catch (const Poco::JSON::JSONException &E) {
Logger().log(E);
Done=true;
}
}
} break;
default: {
}
}
} catch (...) {
Done=true;
}
if(Done) {
delete this;
@@ -5139,7 +5231,7 @@ namespace OpenWifi {
try
{
Poco::Net::WebSocket WS(*Request, *Response);
Logger().information("WebSocket connection established.");
Logger().information("UI-WebSocket connection established.");
auto Id = MicroService::CreateUUID();
WebSocketClientServer()->NewClient(WS,Id);
}

View File

@@ -133,6 +133,37 @@ namespace ORM {
return R;
}
inline std::string WHERE_AND_(std::string Result) {
return Result;
}
template <typename T, typename... Args> std::string WHERE_AND_(std::string Result, const char *fieldName, const T &Value, Args... args) {
if constexpr(std::is_same_v<T,std::string>)
{
if(!Value.empty()) {
if(!Result.empty())
Result += " and ";
Result += fieldName;
Result += '=';
Result += "'";
Result += Escape(Value);
Result += "'";
}
} else {
if(!Result.empty())
Result += " and ";
Result += fieldName ;
Result += '=';
Result += std::to_string(Value);
}
return WHERE_AND_(Result,args...);
}
template <typename... Args> std::string WHERE_AND(Args... args) {
std::string Result;
return WHERE_AND_(Result, args...);
}
enum SqlComparison { EQ = 0, NEQ, LT, LTE, GT, GTE };
enum SqlBinaryOp { AND = 0 , OR };

View File

@@ -71,7 +71,7 @@ namespace OpenWifi {
} else if (LastDate) {
WhereClause = fmt::format(" boardId='{}' and (timestamp <= {}) ", boardId, LastDate);
}
GetRecords(0,MaxRecords,Recs,WhereClause," order by timestamp ASC ");
GetRecords(0,MaxRecords,Recs,WhereClause," order by timestamp, serialNumber ASC ");
return true;
}