Skip to content

Commit

Permalink
Merge pull request #339 from Telecominfraproject/WIFI-13447
Browse files Browse the repository at this point in the history
  • Loading branch information
stephb9959 authored Mar 13, 2024
2 parents 1a0a6d4 + e75d3cf commit aa8486c
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 91 deletions.
2 changes: 2 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion build
Original file line number Diff line number Diff line change
@@ -1 +1 @@
89
91
24 changes: 6 additions & 18 deletions openapi/owgw.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,12 @@ components:
lastModified:
type: integer
format: int64
platform:
type: string
enum:
- AP
- SWITCH
default: AP

DefaultConfigurationList:
properties:
Expand Down Expand Up @@ -1963,15 +1969,6 @@ paths:
schema:
type: string
required: true
- in: query
name: deviceType
schema:
type: string
enum:
- AP
- SWITCH
required: false
default: AP
requestBody:
description: Information used to create the new device
content:
Expand Down Expand Up @@ -2018,15 +2015,6 @@ paths:
schema:
type: string
required: true
- in: query
name: deviceType
schema:
type: string
enum:
- AP
- SWITCH
required: false
default: AP
requestBody:
description: Configuration details
content:
Expand Down
18 changes: 6 additions & 12 deletions src/AP_WS_Connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,11 @@ namespace OpenWifi {
}

AP_WS_Connection::~AP_WS_Connection() {
// poco_information(Logger_, fmt::format("DESTRUCTOR({}): 0 - Session={} Connection closed.", SerialNumber_,
// State_.sessionId));
// std::lock_guard G(ConnectionMutex_);
// poco_information(Logger_, fmt::format("DESTRUCTOR({}): 1 - Session={} Connection closed.", SerialNumber_,
// State_.sessionId));
EndConnection(false);
poco_debug(Logger_, fmt::format("TERMINATION({}): Session={}, Connection removed.", SerialNumber_,
State_.sessionId));
std::lock_guard G(ConnectionMutex_);
AP_WS_Server()->DecrementConnectionCount();
EndConnection();
poco_debug(Logger_, fmt::format("TERMINATION({}): Session={}, Connection removed.", SerialNumber_,
State_.sessionId));
}

static void NotifyKafkaDisconnect(const std::string &SerialNumber, std::uint64_t uuid) {
Expand All @@ -100,7 +96,7 @@ namespace OpenWifi {
}
}

void AP_WS_Connection::EndConnection(bool Clean) {
void AP_WS_Connection::EndConnection() {
bool expectedValue=false;
if (Dead_.compare_exchange_strong(expectedValue,true,std::memory_order_release,std::memory_order_relaxed)) {

Expand All @@ -126,9 +122,7 @@ namespace OpenWifi {
if(!SerialNumber_.empty()) {
DeviceDisconnectionCleanup(SerialNumber_, uuid_);
}

if(Clean)
AP_WS_Server()->EndSession(State_.sessionId, SerialNumberInt_);
AP_WS_Server()->AddCleanupSession(State_.sessionId, SerialNumberInt_);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/AP_WS_Connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace OpenWifi {
Poco::Logger &L, std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R);
~AP_WS_Connection();

void EndConnection(bool Clean = true);
void EndConnection();
void ProcessJSONRPCEvent(Poco::JSON::Object::Ptr &Doc);
void ProcessJSONRPCResult(Poco::JSON::Object::Ptr Doc);
void ProcessIncomingFrame();
Expand Down Expand Up @@ -108,7 +108,7 @@ namespace OpenWifi {
void Start();

private:
std::recursive_mutex ConnectionMutex_;
mutable std::recursive_mutex ConnectionMutex_;
std::mutex TelemetryMutex_;
Poco::Logger &Logger_;
std::shared_ptr<Poco::Net::SocketReactor> Reactor_;
Expand Down
103 changes: 69 additions & 34 deletions src/AP_WS_Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,31 @@ namespace OpenWifi {
Running_ = true;
GarbageCollector_.setName("ws:garbage");
GarbageCollector_.start(*this);

std::thread CleanupThread([this](){ CleanupSessions(); });
CleanupThread.detach();

return 0;
}

void AP_WS_Server::CleanupSessions() {

while(Running_) {
std::this_thread::sleep_for(std::chrono::seconds(10));

while(Running_ && !CleanupSessions_.empty()) {
std::pair<uint64_t, uint64_t> Session;
{
std::lock_guard G(CleanupMutex_);
Session = CleanupSessions_.front();
CleanupSessions_.pop_front();
}
this->Logger().information(fmt::format("Cleaning up session: {} for device: {}", Session.first, Utils::IntToSerialNumber(Session.second)));
EndSession(Session.first, Session.second);
}
}
}

void AP_WS_Server::run() {
uint64_t last_log = Utils::Now(),
last_zombie_run = 0,
Expand Down Expand Up @@ -236,29 +258,35 @@ namespace OpenWifi {
waits = 0;
auto hint = SerialNumbers_[hashIndex].begin();
while (hint != end(SerialNumbers_[hashIndex])) {

if (hint->second == nullptr) {
poco_information(
LocalLogger,
fmt::format("Dead device found in hash index {}", hashIndex));
hint = SerialNumbers_[hashIndex].erase(hint);
continue;
}
auto Device = hint->second;
auto RightNow = Utils::Now();
if (RightNow > Device->LastContact_ &&
(RightNow - Device->LastContact_) > SessionTimeOut_) {
poco_information(
LocalLogger,
fmt::format("{}: Session seems idle. Controller disconnecting device.",
Device->SerialNumber_));
hint = SerialNumbers_[hashIndex].erase(hint);
} else if (Device->State_.Connected) {
total_connected_time +=
(RightNow - Device->State_.started);
++hint;
} else {
++hint;
auto Device = hint->second;
auto RightNow = Utils::Now();
if (Device->Dead_) {
AddCleanupSession(Device->State_.sessionId, Device->SerialNumberInt_);
++hint;
// hint = SerialNumbers_[hashIndex].erase(hint);
} else if (RightNow > Device->LastContact_ &&
(RightNow - Device->LastContact_) > SessionTimeOut_) {
poco_information(
LocalLogger,
fmt::format(
"{}: Session seems idle. Controller disconnecting device.",
Device->SerialNumber_));
// hint = SerialNumbers_[hashIndex].erase(hint);
AddCleanupSession(Device->State_.sessionId, Device->SerialNumberInt_);
++hint;
} else {
if (Device->State_.Connected) {
total_connected_time +=
(RightNow - Device->State_.started);
}
++hint;
}
}
}
SerialNumbersMutex_[hashIndex].unlock();
Expand All @@ -272,8 +300,7 @@ namespace OpenWifi {
}
}

poco_information(LocalLogger,
fmt::format("Garbage collecting zombies... (step 2)"));
poco_information(LocalLogger, fmt::format("Garbage collecting zombies... (step 2)"));
LeftOverSessions_ = 0;
for (int i = 0; i < SessionHash::HashMax(); i++) {
waits = 0;
Expand All @@ -285,14 +312,20 @@ namespace OpenWifi {
while (hint != end(Sessions_[i])) {
if (hint->second == nullptr) {
hint = Sessions_[i].erase(hint);
} else if (hint->second->Dead_) {
// hint = Sessions_[i].erase(hint);
AddCleanupSession(hint->second->State_.sessionId, hint->second->SerialNumberInt_);
++hint;
} else if (RightNow > hint->second->LastContact_ &&
(RightNow - hint->second->LastContact_) >
SessionTimeOut_) {
poco_information(
LocalLogger,
fmt::format("{}: Session seems idle. Controller disconnecting device.",
hint->second->SerialNumber_));
hint = Sessions_[i].erase(hint);
AddCleanupSession(hint->second->State_.sessionId, hint->second->SerialNumberInt_);
++hint;
// hint = Sessions_[i].erase(hint);
} else {
++LeftOverSessions_;
++hint;
Expand All @@ -309,10 +342,9 @@ namespace OpenWifi {
}
}

AverageDeviceConnectionTime_ =
NumberOfConnectedDevices_ > 0
? total_connected_time / NumberOfConnectedDevices_
: 0;
AverageDeviceConnectionTime_ = NumberOfConnectedDevices_ > 0
? total_connected_time / NumberOfConnectedDevices_
: 0;
poco_information(LocalLogger, fmt::format("Garbage collecting zombies done..."));
} catch (const Poco::Exception &E) {
poco_error(LocalLogger, fmt::format("Poco::Exception: Garbage collecting zombies failed: {}", E.displayText()));
Expand All @@ -323,12 +355,11 @@ namespace OpenWifi {
}

}

if(NumberOfConnectedDevices_) {
if (last_garbage_run > 0) {
AverageDeviceConnectionTime_ += (now - last_garbage_run);
}
} else {
AverageDeviceConnectionTime_ = 0;
}

try {
Expand Down Expand Up @@ -445,17 +476,21 @@ namespace OpenWifi {
}

void AP_WS_Server::StartSession(uint64_t session_id, uint64_t SerialNumber) {
auto deviceHash = MACHash::Hash(SerialNumber);
auto sessionHash = SessionHash::Hash(session_id);
std::lock_guard SessionLock(SessionMutex_[sessionHash]);
auto SessionHint = Sessions_[sessionHash].find(session_id);
if (SessionHint != end(Sessions_[sessionHash])) {
std::lock_guard Lock(SerialNumbersMutex_[deviceHash]);
SerialNumbers_[deviceHash][SerialNumber] = SessionHint->second;
std::shared_ptr<AP_WS_Connection> Connection;
{
std::lock_guard SessionLock(SessionMutex_[sessionHash]);
auto SessionHint = Sessions_[sessionHash].find(session_id);
if (SessionHint == end(Sessions_[sessionHash])) {
return;
}
Connection = SessionHint->second;
Sessions_[sessionHash].erase(SessionHint);
} else {
poco_error(Logger(), fmt::format("StartSession: Could not find session '{}'", session_id));
}

auto deviceHash = MACHash::Hash(SerialNumber);
std::lock_guard Lock(SerialNumbersMutex_[deviceHash]);
SerialNumbers_[deviceHash][SerialNumber] = Connection;
}

bool AP_WS_Server::EndSession(uint64_t session_id, uint64_t SerialNumber) {
Expand Down
11 changes: 11 additions & 0 deletions src/AP_WS_Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,13 @@ namespace OpenWifi {
--NumberOfConnectedDevices_;
}

inline void AddCleanupSession(uint64_t session_id, uint64_t SerialNumber) {
std::lock_guard G(CleanupMutex_);
CleanupSessions_.emplace_back(session_id, SerialNumber);
}

void CleanupSessions();

private:
std::array<std::mutex,SessionHashMax> SessionMutex_;
std::array<std::map<std::uint64_t, std::shared_ptr<AP_WS_Connection>>,SessionHashMax> Sessions_;
Expand All @@ -222,6 +229,10 @@ namespace OpenWifi {
bool SimulatorEnabled_ = false;
bool AllowSerialNumberMismatch_ = true;

Poco::Thread CleanupThread_;
std::mutex CleanupMutex_;
std::deque<std::pair<uint64_t, uint64_t>> CleanupSessions_;

std::unique_ptr<AP_WS_ReactorThreadPool> Reactor_pool_;
std::atomic_bool Running_ = false;

Expand Down
22 changes: 18 additions & 4 deletions src/RESTAPI/RESTAPI_default_configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,13 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::ModelIDListCannotBeEmpty);
}

auto DeviceType = GetParameter("deviceType", "AP");
DefConfig.Platform = DefConfig.Platform.empty() ? "AP" : DefConfig.Platform;
if(DefConfig.Platform != "AP" && DefConfig.Platform != "SWITCH") {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}

std::string Error;
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(DeviceType),
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(DefConfig.Platform),
DefConfig.Configuration, Error,
GetBoolParameter("strict", false))) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
Expand Down Expand Up @@ -90,10 +94,20 @@ namespace OpenWifi {
return NotFound();
}

if(Existing.Platform.empty()) {
Existing.Platform = "AP";
}

if(ParsedBody_->has("platform")) {
if(NewConfig.Platform.empty() || (NewConfig.Platform != "AP" && NewConfig.Platform != "SWITCH")) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
Existing.Platform = NewConfig.Platform;
}

if (!NewConfig.Configuration.empty()) {
auto DeviceType = GetParameter("deviceType", "AP");
std::string Error;
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(DeviceType),
if (!ValidateUCentralConfiguration(ConfigurationValidator::GetType(Existing.Platform),
NewConfig.Configuration, Error,
GetBoolParameter("strict", false))) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid, Error);
Expand Down
24 changes: 14 additions & 10 deletions src/RESTObjects/RESTAPI_GWobjects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,6 @@ namespace OpenWifi::GWObjects {
return false;
}

void DefaultConfiguration::to_json(Poco::JSON::Object &Obj) const {
EmbedDocument("configuration", Obj, Configuration);
field_to_json(Obj, "name", Name);
field_to_json(Obj, "modelIds", Models);
field_to_json(Obj, "description", Description);
field_to_json(Obj, "created", Created);
field_to_json(Obj, "lastModified", LastModified);
}

void DefaultFirmware::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "deviceType", deviceType);
field_to_json(Obj, "description", Description);
Expand Down Expand Up @@ -240,12 +231,25 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj, "deferred", deferred);
}

void DefaultConfiguration::to_json(Poco::JSON::Object &Obj) const {
EmbedDocument("configuration", Obj, Configuration);
field_to_json(Obj, "name", Name);
field_to_json(Obj, "modelIds", Models);
field_to_json(Obj, "description", Description);
field_to_json(Obj, "created", Created);
field_to_json(Obj, "lastModified", LastModified);
field_to_json(Obj, "Platform", Platform);
}

bool DefaultConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "name", Name);
field_from_json(Obj, "configuration", Configuration);
field_from_json(Obj, "name", Name);
field_from_json(Obj, "modelIds", Models);
field_from_json(Obj, "description", Description);
field_from_json(Obj, "created", Created);
field_from_json(Obj, "lastModified", LastModified);
field_from_json(Obj, "Platform", Platform);
return true;
} catch (const Poco::Exception &E) {
}
Expand Down
Loading

0 comments on commit aa8486c

Please sign in to comment.