From 5712a367d5f40dc1742ec27f07b62e993b9e34e4 Mon Sep 17 00:00:00 2001 From: msieben <4319079+msieben@users.noreply.github.com> Date: Thu, 7 Nov 2024 13:48:33 +0100 Subject: [PATCH 1/8] [Core/WebSocketLink] : Enable unsollicited 'Pong' and rename enum item (#1784) * [WebSocket/WebSocketLink] : Enable unsollicited 'Pong' and rename enum item - Rename 'WEBSERVER' to 'WEBSERVICE' as both client and server utilize state information - Unsollicited 'Pong' may act as a heart beat * [WebSocket/WebSocketLink] : METROL-1087 * [WebSocket/WebSocketLink] : rename forgotten 'WEBSERVER' to 'WEBSERVICE' --------- Co-authored-by: Pierre Wielders --- Source/websocket/WebSocketLink.h | 44 +++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/Source/websocket/WebSocketLink.h b/Source/websocket/WebSocketLink.h index babf7076c..98e3d2dac 100644 --- a/Source/websocket/WebSocketLink.h +++ b/Source/websocket/WebSocketLink.h @@ -35,6 +35,10 @@ namespace Web { CLOSE = 0x08, PING = 0x09, PONG = 0x0A, + // Reserved ranges + // 0x3-0x7 + // 0xB-0xF + // Following are outside reseved 4-bit ranges VIOLATION = 0x10, // e.g. a control package without a FIN flag TOO_BIG = 0x20, // Protocol max support for 2^16 message per chunk INCONSISTENT = 0x30 // e.g. Protocol defined as Text, but received a binary. @@ -182,13 +186,15 @@ namespace Web { class WebSocketLinkType { public: enum EnumlinkState : uint8_t { - WEBSERVER = 0x01, + WEBSERVICE = 0x01, UPGRADING = 0x02, WEBSOCKET = 0x04, SUSPENDED = 0x08, ACTIVITY = 0x10 }; + DEPRECATED constexpr static EnumlinkState WEBSERVER { EnumlinkState::WEBSERVICE }; + typedef WebSocketLinkType ParentClass; private: @@ -373,7 +379,7 @@ PUSH_WARNING(DISABLE_WARNING_THIS_IN_MEMBER_INITIALIZER_LIST) , _handler(binary, masking) , _parent(parent) , _adminLock() - , _state(WEBSERVER) + , _state(WEBSERVICE) , _serializerImpl(*this, queueSize) , _deserialiserImpl(*this, queueSize) , _path() @@ -390,7 +396,7 @@ PUSH_WARNING(DISABLE_WARNING_THIS_IN_MEMBER_INITIALIZER_LIST) , _handler(binary, masking) , _parent(parent) , _adminLock() - , _state(WEBSERVER) + , _state(WEBSERVICE) , _serializerImpl(*this, queueSize) , _deserialiserImpl(*this, allocator) , _path() @@ -419,7 +425,7 @@ POP_WARNING() } bool IsWebServer() const { - return ((State() & WEBSERVER) != 0); + return ((State() & WEBSERVICE) != 0); } bool IsUpgrading() const { @@ -477,6 +483,18 @@ POP_WARNING() ACTUALLINK::Trigger(); } + void Pong() + { + _pingFireTime = Core::Time::Now().Ticks(); + + _adminLock.Lock(); + + _handler.Pong(); + + _adminLock.Unlock(); + + ACTUALLINK::Trigger(); + } bool Masking() const { return (_handler.Masking()); @@ -775,7 +793,7 @@ POP_WARNING() // Multiple message might be coming in, protect the state before we make assumptions on it value. _adminLock.Lock(); - if ((_state & WEBSERVER) == 0) { + if ((_state & WEBSERVICE) == 0) { _webSocketMessage->ErrorCode = Web::STATUS_INTERNAL_SERVER_ERROR; _webSocketMessage->Message = _T("State of the link can not be upgraded."); } else { @@ -794,7 +812,7 @@ POP_WARNING() _parent.StateChange(); if (_webSocketMessage->ErrorCode != Web::STATUS_SWITCH_PROTOCOL) { - _state = (_state & 0xF0) | WEBSERVER; + _state = (_state & 0xF0) | WEBSERVICE; _path.clear(); _query.clear(); _protocol.Clear(); @@ -845,7 +863,7 @@ POP_WARNING() _adminLock.Lock(); - if ((_state & WEBSERVER) != 0) { + if ((_state & WEBSERVICE) != 0) { result = true; _state = (_state & 0xF0) | UPGRADING; _origin = (origin.empty() ? ACTUALLINK::LocalId() : origin); @@ -1076,6 +1094,10 @@ POP_WARNING() { _channel.Ping(); } + void Pong() + { + _channel.Pong(); + } void Trigger() { _channel.Trigger(); @@ -1272,6 +1294,10 @@ POP_WARNING() { _channel.Ping(); } + void Pong() + { + _channel.Pong(); + } virtual bool IsIdle() const = 0; virtual void StateChange() = 0; @@ -1430,6 +1456,10 @@ POP_WARNING() { _channel.Ping(); } + void Pong() + { + _channel.Pong(); + } virtual bool IsIdle() const = 0; virtual void StateChange() = 0; From 3a82e15301291fdeb4dd382088a5ca2f968ae55c Mon Sep 17 00:00:00 2001 From: Pierre Wielders Date: Mon, 11 Nov 2024 10:44:06 +0100 Subject: [PATCH 2/8] =?UTF-8?q?[METADATA]=20Expose=20all=20COMRPC=20metada?= =?UTF-8?q?ta=20like=20Channels=20and=20Proxies=20(also=E2=80=A6=20(#1775)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [METADATA] Expose all COMRPC metadata like Channels and Proxies (also the private channels) * Update IController.h * Update IUnknown.cpp * Update test_rpc.cpp * Update IUnknown.cpp Thank you Coverity! I like tools that add value :-) * Update IUnknown.cpp * [FIXES] After testing on windows :-) * Update IShell.h * Update PluginHost.cpp * Update test_rpc.cpp --------- Co-authored-by: MFransen69 <39826971+MFransen69@users.noreply.github.com> Co-authored-by: Volkan Aslan --- Source/Thunder/Controller.cpp | 11 ++++- Source/Thunder/Controller.h | 2 +- Source/Thunder/ExampleConfigWindows.json | 30 +++++------- Source/Thunder/PluginHost.cpp | 4 +- Source/Thunder/PluginServer.h | 32 ++++++++++--- Source/com/Administrator.cpp | 44 ++++++++++++------ Source/com/Administrator.h | 22 ++++++--- Source/com/Communicator.cpp | 17 ++++--- Source/com/Communicator.h | 59 ++++++++++++++++++++---- Source/com/IUnknown.cpp | 15 ++---- Source/com/IUnknown.h | 14 +++--- Source/core/IPCConnector.h | 22 +++++++++ Source/core/SocketPort.h | 8 ++-- Source/core/SocketServer.h | 2 +- Source/plugins/IController.h | 8 ++-- Source/plugins/IShell.h | 14 +++--- Source/plugins/plugins.vcxproj | 6 ++- Tests/unit/core/test_rpc.cpp | 2 +- 18 files changed, 210 insertions(+), 102 deletions(-) diff --git a/Source/Thunder/Controller.cpp b/Source/Thunder/Controller.cpp index 04ab088c8..d0964c046 100644 --- a/Source/Thunder/Controller.cpp +++ b/Source/Thunder/Controller.cpp @@ -1216,22 +1216,27 @@ namespace Plugin { return (Core::ERROR_NONE); } - Core::hresult Controller::Proxies(const uint32_t linkId, IMetadata::Data::IProxiesIterator*& outProxies) const + Core::hresult Controller::Proxies(const Core::OptionalType& linkId, IMetadata::Data::IProxiesIterator*& outProxies) const { Core::hresult result = Core::ERROR_UNKNOWN_KEY; std::vector collection; - bool proxySearch = RPC::Administrator::Instance().Allocations(linkId, [&collection](const std::vector& proxies) { + bool proxySearch = RPC::Administrator::Instance().Allocations(linkId.IsSet() ? linkId.Value() : EMPTY_STRING, [&collection, &linkId](const string& origin, const std::vector& proxies) { for (const auto& proxy : proxies) { IMetadata::Data::Proxy data; data.Count = proxy->ReferenceCount(); data.Instance = proxy->Implementation(); data.Interface = proxy->InterfaceId(); data.Name = proxy->Name(); + if (linkId.IsSet() == false) { + data.Origin = Core::NumberType(proxy->ChannelId()).Text() + '@' + origin; + } collection.emplace_back(std::move(data)); } }); + TRACE(Trace::Information, (_T("Found %d proxies to be listed and the search = [%s]"), collection.size(), proxySearch ? _T("true") : _T("false"))); + if (proxySearch == true) { using Iterator = IMetadata::Data::IProxiesIterator; @@ -1440,6 +1445,8 @@ namespace Plugin { buildInfo.ThreadPoolCount = THREADPOOL_COUNT; #endif + buildInfo.COMRPCTimeOut = RPC::CommunicationTimeOut; + return (Core::ERROR_NONE); } } diff --git a/Source/Thunder/Controller.h b/Source/Thunder/Controller.h index 3063e5850..3ea2df158 100644 --- a/Source/Thunder/Controller.h +++ b/Source/Thunder/Controller.h @@ -328,7 +328,7 @@ namespace Plugin { // IMetadata overrides Core::hresult Links(IMetadata::Data::ILinksIterator*& links) const override; - Core::hresult Proxies(const uint32_t linkId, IMetadata::Data::IProxiesIterator*& proxies) const override; + Core::hresult Proxies(const Core::OptionalType& linkId, IMetadata::Data::IProxiesIterator*& proxies) const override; Core::hresult Services(const Core::OptionalType& callsign, IMetadata::Data::IServicesIterator*& services) const override; Core::hresult CallStack(const uint8_t threadId, IMetadata::Data::ICallStackIterator*& callstack) const override; Core::hresult Threads(IMetadata::Data::IThreadsIterator*& threads) const override; diff --git a/Source/Thunder/ExampleConfigWindows.json b/Source/Thunder/ExampleConfigWindows.json index a5f943668..87d01da86 100644 --- a/Source/Thunder/ExampleConfigWindows.json +++ b/Source/Thunder/ExampleConfigWindows.json @@ -3,16 +3,16 @@ "binding": "127.0.0.1", "idletime": 60, "ipv6": false, - "persistentpath": "C:/ThunderWin/artifacts/Persistent", - "volatilepath": "C:/ThunderWin/artifacts/temp", - "datapath": "C:/ThunderWin/artifacts/Debug/Plugins", - "systempath": "C:/ThunderWin/artifacts/Debug", - "proxystubpath": "C:/ThunderWin/artifacts/ProxyStubs/Debug", + "persistentpath": "D:/domotica/artifacts/Persistent", + "volatilepath": "D:/domotica//artifacts/temp", + "datapath": "D:/domotica/artifacts/Debug/Plugins", + "systempath": "D:/domotica/artifacts/Debug", + "proxystubpath": "D:/domotica/artifacts/ProxyStubs/Debug", "communicator": "127.0.0.1:62000", "redirect": "Service/Controller/UI", "observe": { - "proxystubpath": "C:/ThunderWin/artifacts/dynamic/proxystubs", - "configpath": "C:/ThunderWin/artifacts/dynamic/config" + "proxystubpath": "D:/domotica/artifacts/dynamic/proxystubs", + "configpath": "D:/domotica/artifacts/dynamic/config" }, "messaging": { "port": 63000, @@ -137,7 +137,7 @@ "callsign": "Butler", "locator": "libButler.so", "classname": "Butler", - "startmode": "Activated" + "startmode": "Deactivated" }, { "callsign": "ZigbeeControl", @@ -154,10 +154,10 @@ "callsign": "ZWaveControl", "locator": "libZWaveControl.so", "classname": "ZWaveControl", - "startmode": "Activated", + "startmode": "Deactivated", "configuration": { "port": "\\\\.\\COM4", - "key": "ba:09:87:65:43:21:de:ad:be:ef:12:34:56:78:90:ab" + "key": "ba:09:87:65:43:21:de:ad:be:ef:12:34:56:78:90:ab" } }, { @@ -401,7 +401,7 @@ "sleep": "5", "single": false, "crash": true, - "leak": true, + "leak": true, "root": { "mode": "Local" } @@ -458,7 +458,7 @@ "callsign": "WebServer", "locator": "libWebServer.so", "classname": "WebServer", - "startmode": "Deactivated", + "startmode": "Activated", "communicator": "127.0.0.1:2349", "configuration": { "port": 8080, @@ -571,12 +571,6 @@ "classname": "MessageControl", "startmode": "Activated" }, - { - "callsign": "TraceControl", - "locator": "libtracecontrol.so", - "classname": "TraceControl", - "startmode": "Deactivated" - }, { "callsign": "RemoteControl", "locator": "libremotecontrol.so", diff --git a/Source/Thunder/PluginHost.cpp b/Source/Thunder/PluginHost.cpp index abbb9c6a7..5e9b84341 100644 --- a/Source/Thunder/PluginHost.cpp +++ b/Source/Thunder/PluginHost.cpp @@ -712,10 +712,10 @@ POP_WARNING() printf("Link: %s\n", index.Current().Remote.Value().c_str()); printf("------------------------------------------------------------\n"); - RPC::Administrator::Instance().Allocations(index.Current().ID.Value(), [](const std::vector& proxies) { + RPC::Administrator::Instance().Allocations(index.Current().Name.Value(), [](const string& origin, const std::vector& proxies) { for (const auto& proxy: proxies) { Core::instance_id instanceId = proxy->Implementation(); - printf("[%s] InstanceId: 0x%" PRIx64 ", RefCount: %d, InterfaceId %d [0x%X]\n", proxy->Name().c_str(), static_cast(instanceId), proxy->ReferenceCount(), proxy->InterfaceId(), proxy->InterfaceId()); + printf("[%s] InstanceId: 0x%" PRIx64 ", RefCount: %d, InterfaceId %d [0x%X], Origin: %s\n", proxy->Name().c_str(), static_cast(instanceId), proxy->ReferenceCount(), proxy->InterfaceId(), proxy->InterfaceId(), origin.c_str()); } printf("\n"); }); diff --git a/Source/Thunder/PluginServer.h b/Source/Thunder/PluginServer.h index fef22a2ad..9ddc623bb 100644 --- a/Source/Thunder/PluginServer.h +++ b/Source/Thunder/PluginServer.h @@ -532,10 +532,11 @@ namespace PluginHost { ExternalAccess& operator=(const ExternalAccess&) = delete; ExternalAccess( - const Core::NodeId& source, + const Core::NodeId& sourceNode, const string& proxyStubPath, - const Core::ProxyType& handler) - : RPC::Communicator(source, proxyStubPath, Core::ProxyType(handler)) + const Core::ProxyType& handler, + const string& sourceName) + : RPC::Communicator(sourceNode, proxyStubPath, Core::ProxyType(handler), sourceName.c_str()) , _plugin(nullptr) { } ~ExternalAccess() override = default; @@ -822,7 +823,7 @@ namespace PluginHost { , _lastId(0) , _metadata(plugin.MaxRequests.Value()) , _library() - , _external(PluginNodeId(server, plugin), server.ProxyStubPath(), handler) + , _external(PluginNodeId(server, plugin), server.ProxyStubPath(), handler, '/' + Callsign()) , _administrator(administrator) , _composit(*this) , _jobs(administrator) @@ -855,6 +856,9 @@ namespace PluginHost { } public: + inline const RPC::Communicator& COMServer() const { + return (_external); + } inline void Submit(Core::ProxyType&& job) { _jobs.Push(std::move(job)); } @@ -2205,7 +2209,7 @@ namespace PluginHost { const uint8_t hardKillCheckWaitTime, const bool delegatedReleases, const Core::ProxyType& handler) - : RPC::Communicator(node, ProxyStubPathCreator(proxyStubPath, observableProxyStubPath), Core::ProxyType(handler)) + : RPC::Communicator(node, ProxyStubPathCreator(proxyStubPath, observableProxyStubPath), Core::ProxyType(handler), _T("/")) , _parent(parent) , _persistentPath(persistentPath) , _systemPath(systemPath) @@ -3203,10 +3207,24 @@ namespace PluginHost { entry.Activity = element.Source().IsOpen(); entry.State = Metadata::Channel::state::COMRPC; - entry.Name = string("/" EXPAND_AND_QUOTE(APPLICATION_NAME) "/Communicator"); + entry.Name = element.Extension().Origin(); entry.Remote = element.Source().RemoteId(); }); - _adminLock.Unlock(); + + for (const auto& entry : _services) { + entry.second->COMServer().Visit([&](const RPC::Communicator::Client& element) + { + Metadata::Channel& entry = metaData.Add(); + entry.ID = element.Extension().Id(); + + entry.Activity = element.Source().IsOpen(); + entry.State = Metadata::Channel::state::COMRPC; + entry.Name = element.Extension().Origin(); + entry.Remote = element.Source().RemoteId(); + }); + } + + _adminLock.Unlock(); } uint32_t FromIdentifier(const string& callSign, Core::ProxyType& service) { diff --git a/Source/com/Administrator.cpp b/Source/com/Administrator.cpp index 8ef34abcc..3f03b6e7d 100644 --- a/Source/com/Administrator.cpp +++ b/Source/com/Administrator.cpp @@ -19,10 +19,13 @@ #include "Administrator.h" #include "IUnknown.h" +#include "Communicator.h" namespace Thunder { namespace RPC { + /* static */ const string Administrator::DanglingId("/Dangling"); + Administrator::Administrator() : _adminLock() , _stubs() @@ -122,17 +125,17 @@ namespace RPC { ChannelMap::iterator index(_channelProxyMap.find(proxy.Id())); if (index != _channelProxyMap.end()) { - Proxies::iterator entry(index->second.begin()); - while ((entry != index->second.end()) && ((*entry) != &proxy)) { + Proxies::iterator entry(index->second.second.begin()); + while ((entry != index->second.second.end()) && ((*entry) != &proxy)) { entry++; } - ASSERT(entry != index->second.end()); + ASSERT(entry != index->second.second.end()); - if (entry != index->second.end()) { - index->second.erase(entry); + if (entry != index->second.second.end()) { + index->second.second.erase(entry); removed = true; - if (index->second.size() == 0) { + if (index->second.second.size() == 0) { _channelProxyMap.erase(index); } } @@ -228,11 +231,11 @@ namespace RPC { ChannelMap::iterator index(_channelProxyMap.find(channel->Id())); if (index != _channelProxyMap.end()) { - Proxies::iterator entry(index->second.begin()); - while ((entry != index->second.end()) && (((*entry)->InterfaceId() != id) || ((*entry)->Implementation() != impl))) { + Proxies::iterator entry(index->second.second.begin()); + while ((entry != index->second.second.end()) && (((*entry)->InterfaceId() != id) || ((*entry)->Implementation() != impl))) { entry++; } - if (entry != index->second.end()) { + if (entry != index->second.second.end()) { interface = (*entry)->QueryInterface(id); if (interface != nullptr) { result = (*entry); @@ -261,11 +264,11 @@ namespace RPC { ChannelMap::iterator index(_channelProxyMap.find(channelId)); if (index != _channelProxyMap.end()) { - Proxies::iterator entry(index->second.begin()); - while ((entry != index->second.end()) && (((*entry)->InterfaceId() != id) || ((*entry)->Implementation() != impl))) { + Proxies::iterator entry(index->second.second.begin()); + while ((entry != index->second.second.end()) && (((*entry)->InterfaceId() != id) || ((*entry)->Implementation() != impl))) { entry++; } - if (entry != index->second.end()) { + if (entry != index->second.second.end()) { interface = (*entry)->Acquire(outbound, id); // The implementation could be found, but the current implemented proxy is not @@ -287,7 +290,18 @@ namespace RPC { ASSERT(result != nullptr); // Register it as it is remotely registered :-) - _channelProxyMap[channelId].push_back(result); + ChannelMap::iterator channelIndex(_channelProxyMap.find(channelId)); + + if (channelIndex != _channelProxyMap.end()) { + channelIndex->second.second.push_back(result); + } + else { + Proxies baseList; + baseList.emplace_back(result); + _channelProxyMap.emplace(std::piecewise_construct, + std::forward_as_tuple(channelId), + std::forward_as_tuple(std::pair(channel->Origin(), baseList))); + } // This will increment the reference count to 2 (one in the ChannelProxyMap and one in the QueryInterface ). interface = result->QueryInterface(id); @@ -431,7 +445,7 @@ namespace RPC { ChannelMap::iterator index(_channelProxyMap.find(channelId)); if (index != _channelProxyMap.end()) { - for (auto entry : index->second) { + for (auto entry : index->second.second) { entry->Invalidate(); _danglingProxies.emplace_back(entry); @@ -444,7 +458,7 @@ namespace RPC { // the pendingProxies. The receiver of pendingProxies has to take // care of releasing the last reference we, as administration layer // hold upon this.. - pendingProxies = std::move(index->second); + pendingProxies = std::move(index->second.second); _channelProxyMap.erase(index); } diff --git a/Source/com/Administrator.h b/Source/com/Administrator.h index 95b5eeea0..422cc10b0 100644 --- a/Source/com/Administrator.h +++ b/Source/com/Administrator.h @@ -124,8 +124,10 @@ namespace RPC { }; public: + static const string DanglingId; + using Proxies = std::vector; - using ChannelMap = std::unordered_map; + using ChannelMap = std::unordered_map >; using ReferenceMap = std::unordered_map >; using Stubs = std::unordered_map; using Factories = std::unordered_map; @@ -149,25 +151,31 @@ namespace RPC { } template - bool Allocations(const uint32_t id, ACTION&& action) const { + bool Allocations(const string& linkId, ACTION&& action) const { bool found = false; _adminLock.Lock(); - if (id == 0) { + if (linkId.empty() == true) { for (const auto& proxy : _channelProxyMap) { - action(proxy.second); + action(proxy.second.first, proxy.second.second); } - action(_danglingProxies); + action(DanglingId, _danglingProxies); found = true; } + else if (linkId == DanglingId) { + action(DanglingId, _danglingProxies); + found = true; + } else { ChannelMap::const_iterator index(_channelProxyMap.begin()); while ((found == false) && (index != _channelProxyMap.end())) { - if (index->first != id) { + ASSERT(index->second.second.size() != 0); + + if (index->second.first != linkId) { index++; } else { found = true; - action(index->second); + action(index->second.first, index->second.second); } } } diff --git a/Source/com/Communicator.cpp b/Source/com/Communicator.cpp index 8e156fc12..3740bc0d2 100644 --- a/Source/com/Communicator.cpp +++ b/Source/com/Communicator.cpp @@ -362,8 +362,9 @@ namespace RPC { uint8_t Communicator::_hardKillCheckWaitTime = 4; PUSH_WARNING(DISABLE_WARNING_THIS_IN_MEMBER_INITIALIZER_LIST) - Communicator::Communicator(const Core::NodeId& node, const string& proxyStubPath) - : _connectionMap(*this) + Communicator::Communicator(const Core::NodeId& node, const string& proxyStubPath, const TCHAR* sourceName) + : _source(sourceName == nullptr ? _T("UnknownServer") : sourceName) + , _connectionMap(*this) , _ipcServer(node, _connectionMap, proxyStubPath) { if (proxyStubPath.empty() == false) { RPC::LoadProxyStubs(proxyStubPath); @@ -374,10 +375,12 @@ namespace RPC { } Communicator::Communicator( - const Core::NodeId& node, + const Core::NodeId& node, const string& proxyStubPath, - const Core::ProxyType& handler) - : _connectionMap(*this) + const Core::ProxyType& handler, + const TCHAR* sourceName) + : _source(sourceName == nullptr ? _T("UnknownServer") : sourceName) + , _connectionMap(*this) , _ipcServer(node, _connectionMap, proxyStubPath, handler) { if (proxyStubPath.empty() == false) { RPC::LoadProxyStubs(proxyStubPath); @@ -416,7 +419,7 @@ namespace RPC { PUSH_WARNING(DISABLE_WARNING_THIS_IN_MEMBER_INITIALIZER_LIST) CommunicatorClient::CommunicatorClient( const Core::NodeId& remoteNode) - : Core::IPCChannelClientType(remoteNode, CommunicationBufferSize) + : BaseClass(remoteNode, CommunicationBufferSize) , _announceMessage() , _announceEvent(false, true) , _connectionId(~0) @@ -432,7 +435,7 @@ namespace RPC { CommunicatorClient::CommunicatorClient( const Core::NodeId& remoteNode, const Core::ProxyType& handler) - : Core::IPCChannelClientType(remoteNode, CommunicationBufferSize) + : BaseClass(remoteNode, CommunicationBufferSize) , _announceMessage() , _announceEvent(false, true) , _connectionId(~0) diff --git a/Source/com/Communicator.h b/Source/com/Communicator.h index e6439a279..1f157c361 100644 --- a/Source/com/Communicator.h +++ b/Source/com/Communicator.h @@ -105,7 +105,7 @@ namespace RPC { RPC::Environment::Value = value; RPC::Environment::Scope = scoping; } - Environment(Environment&& move) { + Environment(Environment&& move) noexcept { RPC::Environment::Key = std::move(move.RPC::Environment::Key); RPC::Environment::Value = std::move(move.RPC::Environment::Value); RPC::Environment::Scope = std::move(move.RPC::Environment::Scope); @@ -117,7 +117,7 @@ namespace RPC { } ~Environment() = default; - Environment& operator= (Environment&& move) { + Environment& operator= (Environment&& move) noexcept { RPC::Environment::Key = std::move(move.RPC::Environment::Key); RPC::Environment::Value = std::move(move.RPC::Environment::Value); RPC::Environment::Scope = std::move(move.RPC::Environment::Scope); @@ -351,7 +351,7 @@ namespace RPC { { return (_environments); } - inline void Environments(const std::vector& environments) { + inline void Environments(std::vector&& environments) { _environments = std::move(environments); } @@ -568,7 +568,10 @@ namespace RPC { } uint32_t Id() const { - return _id; + return (_channel.Descriptor()); + } + string Origin() const { + return (_connectionMap->Origin()); } private: @@ -1187,6 +1190,9 @@ namespace RPC { } public: + const string& Origin() const { + return (_parent.Origin()); + } inline void Register(RPC::IRemoteConnection::INotification* sink) { ASSERT(sink != nullptr); @@ -1651,12 +1657,14 @@ POP_WARNING() Communicator( const Core::NodeId& node, - const string& proxyStubPath); + const string& proxyStubPath, + const TCHAR* sourceName = nullptr); Communicator( const Core::NodeId& node, const string& proxyStubPath, - const Core::ProxyType& handler); - virtual ~Communicator(); + const Core::ProxyType& handler, + const TCHAR* sourceName = nullptr); + virtual ~Communicator(); public: // void action(const Client& client) @@ -1669,6 +1677,9 @@ POP_WARNING() void Visit(ACTION&& action) const { _ipcServer.Visit(action); } + const string& Origin() const { + return (_source); + } inline bool IsListening() const { return (_ipcServer.IsListening()); @@ -1753,15 +1764,45 @@ POP_WARNING() } private: + const string _source; RemoteConnectionMap _connectionMap; ChannelServer _ipcServer; static uint8_t _softKillCheckWaitTime; static uint8_t _hardKillCheckWaitTime; }; - class EXTERNAL CommunicatorClient : public Core::IPCChannelClientType, public Core::IDispatchType { + class EXTERNAL ClientMetadata { + public: + ClientMetadata() = delete; + ClientMetadata(ClientMetadata&&) = delete; + ClientMetadata(const ClientMetadata&) = delete; + ClientMetadata& operator=(ClientMetadata&&) = delete; + ClientMetadata& operator=(const ClientMetadata&) = delete; + + ClientMetadata(Core::IPCChannelType* channel) + : _socketPort(channel->Source()) + { + } + ~ClientMetadata() = default; + + public: + uint32_t Id() const + { + return (_socketPort.Descriptor()); + } + string Origin() const { + return (_socketPort.RemoteId()); + } + + private: + // Non ref-counted reference to our parent, of which we are a composit :-) + Core::SocketPort& _socketPort; + }; + + + class EXTERNAL CommunicatorClient : public Core::IPCChannelClientType, public Core::IDispatchType { private: - typedef Core::IPCChannelClientType BaseClass; + using BaseClass = Core::IPCChannelClientType; class AnnounceHandler : public Core::IIPCServer { public: diff --git a/Source/com/IUnknown.cpp b/Source/com/IUnknown.cpp index bb09281af..c09638b06 100644 --- a/Source/com/IUnknown.cpp +++ b/Source/com/IUnknown.cpp @@ -99,20 +99,13 @@ namespace ProxyStub { // ------------------------------------------------------------------------------------------- // PROXY // ------------------------------------------------------------------------------------------- - const Core::SocketPort* UnknownProxy::Socket() const + uint32_t UnknownProxy::Id() const { - const Core::SocketPort* result = nullptr; - - _adminLock.Lock(); + uint32_t id = 0; if (_channel.IsValid() == true) { - const RPC::Communicator::Client* comchannel = dynamic_cast(_channel.operator->()); - if (comchannel != nullptr) { - result = &(comchannel->Source()); - } + id = _channel->Id(); } - _adminLock.Unlock(); - - return (result); + return (id); } static class UnknownInstantiation { diff --git a/Source/com/IUnknown.h b/Source/com/IUnknown.h index e46f13269..5f33e5df6 100644 --- a/Source/com/IUnknown.h +++ b/Source/com/IUnknown.h @@ -272,7 +272,6 @@ namespace ProxyStub { { return (&_parent); } - const Core::SocketPort* Socket() const; void* Interface(const Core::instance_id& implementation, const uint32_t id) const { void* result = nullptr; @@ -287,6 +286,12 @@ namespace ProxyStub { { return (_implementation); } + inline uint32_t ChannelId() const + { + Core::SafeSyncType lock(_adminLock); + + return (_channel.IsValid() ? _channel->Id() : ~0); + } // Required by proxystubs! const Core::ProxyType& Channel() const { return (_channel); @@ -426,16 +431,13 @@ namespace ProxyStub { return (_parent.QueryInterface(id)); } - // The RPC::Administrator uses this to identifiy to what link this + // The RPC::Administrator uses this to identifiy to what link this // proxy belongs. The LinkId is always called within the lock of the // RPC::Administrator, and since it is onl used and called from there // and the clearing of the _channel is also only called from there, // Invalidate(), It is safe to use it on the _channel in an unlocked // fashion!! - uint32_t Id() const - { - return (_channel.IsValid() ? _channel->Id() : 0); - } + uint32_t Id() const; void Invalidate() { ASSERT(_refCount > 0); _adminLock.Lock(); diff --git a/Source/core/IPCConnector.h b/Source/core/IPCConnector.h index d50420872..32567e625 100644 --- a/Source/core/IPCConnector.h +++ b/Source/core/IPCConnector.h @@ -760,6 +760,7 @@ POP_WARNING() } virtual uint32_t Id() const = 0; + virtual string Origin() const = 0; virtual uint32_t ReportResponse(Core::ProxyType& inbound) = 0; private: @@ -923,6 +924,10 @@ POP_WARNING() uint32_t Id() const override { return (__Id()); } + string Origin() const override { + return (__Origin()); + } + uint32_t ReportResponse(Core::ProxyType& inbound) override { // We got the event, start the invoke, wait for the event to be set again.. @@ -968,6 +973,23 @@ POP_WARNING() return (0); } + IS_MEMBER_AVAILABLE(Origin, hasOrigin); + + template + typename Core::TypeTraits::enable_if ::value, string>::type + __Origin() const + { + return (_extension.Origin()); + } + + template + typename Core::TypeTraits::enable_if ::value, string>::type + __Origin() const + { + static string unknown(_T("Unknown")); + return (unknown); + } + uint32_t Execute(const ProxyType& command, IDispatchType* completed) override { uint32_t success = Core::ERROR_UNAVAILABLE; diff --git a/Source/core/SocketPort.h b/Source/core/SocketPort.h index efadf89bb..2f3f51b31 100644 --- a/Source/core/SocketPort.h +++ b/Source/core/SocketPort.h @@ -250,6 +250,10 @@ namespace Thunder { NodeId Accept(); void Listen(); SOCKET Accept(NodeId& remoteId); + IResource::handle Descriptor() const override + { + return (static_cast(m_Socket)); + } protected: virtual uint32_t Initialize(); @@ -267,10 +271,6 @@ namespace Thunder { private: string Identifier(const NodeId& node) const; - IResource::handle Descriptor() const override - { - return (static_cast(m_Socket)); - } inline uint32_t SocketMode() const { return (((m_SocketType == LISTEN) || (m_SocketType == STREAM)) ? SOCK_STREAM : ((m_SocketType == DATAGRAM) ? SOCK_DGRAM : (m_SocketType == SEQUENCED ? SOCK_SEQPACKET : SOCK_RAW))); diff --git a/Source/core/SocketServer.h b/Source/core/SocketServer.h index aca3a38ab..0b439618c 100644 --- a/Source/core/SocketServer.h +++ b/Source/core/SocketServer.h @@ -114,7 +114,7 @@ namespace Core { } inline uint32_t Count() const { - return (_clients.size()); + return (static_cast(_clients.size())); } HANDLECLIENT Client() { diff --git a/Source/plugins/IController.h b/Source/plugins/IController.h index e389a55aa..56901f3ef 100644 --- a/Source/plugins/IController.h +++ b/Source/plugins/IController.h @@ -260,6 +260,7 @@ namespace Controller { uint8_t InstanceIDBits /* @brief Core instance bits */; Core::OptionalType TraceLevel /* @brief Trace level */; uint8_t ThreadPoolCount /* Number of configured threads on the threadpool */; + uint32_t COMRPCTimeOut /* The number of milliseconds a COMRPC call can take before it is assumed to fail */; }; struct CallStack { @@ -280,6 +281,7 @@ namespace Controller { string Name /* @brief The fully qualified name of the interface */; Core::instance_id Instance /* @brief Instance ID */; uint32_t Count /* @brief Reference count */; + Core::OptionalType Origin /* @brief The Origin of the assocated connection */; }; struct Link { @@ -294,9 +296,9 @@ namespace Controller { string Remote /* @brief IP address (or FQDN) of the other side of the connection */; state State /* @brief State of the link */; - Core::OptionalType Name /* @brief Name of the connection */; uint32_t Id /* @brief A unique number identifying the connection */; bool Activity /* @brief Denotes if there was any activity on this connection */; + Core::OptionalType Name /* @brief Name of the connection */; }; struct Service { @@ -354,12 +356,12 @@ namespace Controller { virtual Core::hresult Services(const Core::OptionalType& callsign /* @index */, Data::IServicesIterator*& services /* @out @extract */) const = 0; // @property - // @brief Connections list + // @brief Connections list of Thunder connections virtual Core::hresult Links(Data::ILinksIterator*& links /* @out */) const = 0; // @property // @brief Proxies list - virtual Core::hresult Proxies(const uint32_t linkID /* @index */, Data::IProxiesIterator*& proxies /* @out */) const = 0; + virtual Core::hresult Proxies(const Core::OptionalType& linkID /* @index */, Data::IProxiesIterator*& proxies /* @out */) const = 0; // @property // @brief Framework version diff --git a/Source/plugins/IShell.h b/Source/plugins/IShell.h index 8c03770e6..b850c0409 100644 --- a/Source/plugins/IShell.h +++ b/Source/plugins/IShell.h @@ -77,24 +77,24 @@ namespace PluginHost { virtual void Unregister(const INotification* sink) = 0; }; - enum class startmode : uint8_t { - UNAVAILABLE, - DEACTIVATED, - ACTIVATED - }; - // State of the IPlugin interface associated with this shell. enum state : uint8_t { UNAVAILABLE, DEACTIVATED, - DEACTIVATION, ACTIVATED, + DEACTIVATION, ACTIVATION, PRECONDITION, HIBERNATED, DESTROYED }; + enum class startmode : uint8_t { + UNAVAILABLE = static_cast(state::UNAVAILABLE), + DEACTIVATED = static_cast(state::DEACTIVATED), + ACTIVATED = static_cast(state::ACTIVATED) + }; + enum reason : uint8_t { REQUESTED, AUTOMATIC, diff --git a/Source/plugins/plugins.vcxproj b/Source/plugins/plugins.vcxproj index 378a1e795..4ca92589e 100755 --- a/Source/plugins/plugins.vcxproj +++ b/Source/plugins/plugins.vcxproj @@ -50,6 +50,10 @@ true false true + python "$(ToolPath)\JsonGenerator\JsonGenerator.py" -I "$(FrameworkPath)\" --case-convention legacy --no-includes --keep-empty -c --namespace Thunder::Exchange::Controller -o "$(ProjectDir)/json" "%(FullPath)" --force + python "$(ToolPath)\JsonGenerator\JsonGenerator.py" -I "$(FrameworkPath)\" --case-convention legacy --no-includes --keep-empty -c --namespace Thunder::Exchange::Controller -o "$(ProjectDir)/json" "%(FullPath)" --force + python "$(ToolPath)\JsonGenerator\JsonGenerator.py" -I "$(FrameworkPath)\" --case-convention legacy --no-includes --keep-empty -c --namespace Thunder::Exchange::Controller -o "$(ProjectDir)/json" "%(FullPath)" --force + python "$(ToolPath)\JsonGenerator\JsonGenerator.py" -I "$(FrameworkPath)\" --case-convention legacy --no-includes --keep-empty -c --namespace Thunder::Exchange::Controller -o "$(ProjectDir)/json" "%(FullPath)" --force $(ProjectDir)json/JDispatcher.h @@ -314,4 +318,4 @@ - + \ No newline at end of file diff --git a/Tests/unit/core/test_rpc.cpp b/Tests/unit/core/test_rpc.cpp index 83cd7c632..fdd703057 100644 --- a/Tests/unit/core/test_rpc.cpp +++ b/Tests/unit/core/test_rpc.cpp @@ -224,7 +224,7 @@ namespace Exchange { ExternalAccess& operator=(const ExternalAccess &) = delete; ExternalAccess(const ::Thunder::Core::NodeId & source) - : ::Thunder::RPC::Communicator(source, _T("")) + : ::Thunder::RPC::Communicator(source, _T(""), _T("@test")) { Open(::Thunder::Core::infinite); } From d16cdd179f6ab9e7c4c7ffcd126cae579db0cfa7 Mon Sep 17 00:00:00 2001 From: Mateusz Daniluk <121170681+VeithMetro@users.noreply.github.com> Date: Tue, 12 Nov 2024 14:43:44 +0100 Subject: [PATCH 3/8] The stringop-overread warning is not available on clang (#1789) --- Source/core/Portability.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/core/Portability.h b/Source/core/Portability.h index bea130a23..65a3fd146 100644 --- a/Source/core/Portability.h +++ b/Source/core/Portability.h @@ -218,7 +218,6 @@ #define DISABLE_WARNING_DEPRECATED_COPY PUSH_WARNING_ARG_("-Wdeprecated-copy") #define DISABLE_WARNING_NON_VIRTUAL_DESTRUCTOR PUSH_WARNING_ARG_("-Wnon-virtual-dtor") #define DISABLE_WARNING_TYPE_LIMITS PUSH_WARNING_ARG_("-Wtype-limits") -#define DISABLE_WARNING_STRING_OPERATION_OVERREAD PUSH_WARNING_ARG_("-Wstringop-overread") #define DISABLE_WARNING_PEDANTIC PUSH_WARNING_ARG_("-Wpedantic") #define DISABLE_WARNING_OVERLOADED_VIRTUALS PUSH_WARNING_ARG_("-Woverloaded-virtual") #define DISABLE_WARNING_CONVERSION_TO_GREATERSIZE PUSH_WARNING_ARG_("-Wint-to-pointer-cast") @@ -229,6 +228,13 @@ #define DISABLE_WARNING_FREE_NONHEAP_OBJECT PUSH_WARNING_ARG_("-Wfree-nonheap-object") #define DISABLE_WARNING_ARRAY_BOUNDS PUSH_WARNING_ARG_("-Warray-bounds") #endif + +#if !(defined(__clang__)) && (__GNUC__ >= 4) +#define DISABLE_WARNING_STRING_OPERATION_OVERREAD PUSH_WARNING_ARG_("-Wstringop-overread") +#else +#define DISABLE_WARNING_STRING_OPERATION_OVERREAD +#endif + #endif #if defined WIN32 || defined _WINDOWS From ec7172d8bcca541230192f4c2294fe7b7f997f11 Mon Sep 17 00:00:00 2001 From: Volkan Aslan Date: Wed, 13 Nov 2024 13:42:35 +0100 Subject: [PATCH 4/8] Fixing references documentation (#1790) --- docs/references/references.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/references/references.md b/docs/references/references.md index 38f004492..70daa6c55 100644 --- a/docs/references/references.md +++ b/docs/references/references.md @@ -1,3 +1,3 @@ You can find references to some other related information here. Please check below links: -[WPE-API-Thunder](https://github.com/WebPlatformForEmbedded/Documentation/blob/master/Thunder/WPE-API-Thunder/WPE-API-Thunder.pdf) +[WPE-API-Thunder](https://github.com/WebPlatformForEmbedded/Documentation/blob/master/Thunder/WPE-API-Thunder/WPE-API-Thunder.pdf) (Deprecated Early Thunder Documentation) From e14d120dc901d9aa376a3974ed3c39fe184d7303 Mon Sep 17 00:00:00 2001 From: Karthick Somasundaresan Date: Sat, 16 Nov 2024 12:44:16 +0530 Subject: [PATCH 5/8] Fix for RDKTV-31859 (#1791) --- Source/websocket/WebSocketLink.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/websocket/WebSocketLink.h b/Source/websocket/WebSocketLink.h index 98e3d2dac..9b5e38d69 100644 --- a/Source/websocket/WebSocketLink.h +++ b/Source/websocket/WebSocketLink.h @@ -408,7 +408,9 @@ PUSH_WARNING(DISABLE_WARNING_THIS_IN_MEMBER_INITIALIZER_LIST) { } POP_WARNING() - ~HandlerType() override = default; + ~HandlerType() override { + ACTUALLINK::Close(Core::infinite); + } public: bool IsOpen() const From ee1748165abac43e25da9132f3694dec4e98e747 Mon Sep 17 00:00:00 2001 From: Mateusz Daniluk <121170681+VeithMetro@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:17:32 +0100 Subject: [PATCH 6/8] [Actions] Adding Thunder dependencies in the MacOS workflow, fixing Tests action (#1792) * Add building of all Thunder dependencies in the MacOS workflow * Explicitly state the ubuntu version in Tests workflow * Make sure the MacOS job names are unique Otherwise they clash with Linux ones and are marked as required checks, even though the workflow name is different --- .github/workflows/Build Thunder on MacOS.yml | 30 +++++++++----------- .github/workflows/Test Thunder.yml | 2 +- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/.github/workflows/Build Thunder on MacOS.yml b/.github/workflows/Build Thunder on MacOS.yml index 7aadd595b..91972b2df 100644 --- a/.github/workflows/Build Thunder on MacOS.yml +++ b/.github/workflows/Build Thunder on MacOS.yml @@ -16,25 +16,21 @@ on: - 'ReleaseNotes/**' jobs: - Thunder: + Thunder_MacOS: uses: rdkcentral/Thunder/.github/workflows/MacOS build template.yml@master - # ThunderInterfaces: - # needs: Thunder - # uses: rdkcentral/ThunderInterfaces/.github/workflows/Linux build template.yml@master + ThunderInterfaces_MacOS: + needs: Thunder_MacOS + uses: rdkcentral/ThunderInterfaces/.github/workflows/MacOS build template.yml@master - # ThunderLibraries: - # needs: Thunder - # uses: WebPlatformForEmbedded/ThunderLibraries/.github/workflows/Linux build template.yml@main + ThunderClientLibraries_MacOS: + needs: ThunderInterfaces_MacOS + uses: rdkcentral/ThunderClientLibraries/.github/workflows/MacOS build template.yml@master - # ThunderClientLibraries: - # needs: ThunderInterfaces - # uses: rdkcentral/ThunderClientLibraries/.github/workflows/Linux build template.yml@master + ThunderNanoServices_MacOS: + needs: ThunderInterfaces_MacOS + uses: rdkcentral/ThunderNanoServices/.github/workflows/MacOS build template.yml@master - # ThunderNanoServices: - # needs: ThunderInterfaces - # uses: rdkcentral/ThunderNanoServices/.github/workflows/Linux build template.yml@master - - # ThunderNanoServicesRDK: - # needs: ThunderInterfaces - # uses: WebPlatformForEmbedded/ThunderNanoServicesRDK/.github/workflows/Linux build template.yml@master + ThunderNanoServicesRDK_MacOS: + needs: ThunderInterfaces_MacOS + uses: WebPlatformForEmbedded/ThunderNanoServicesRDK/.github/workflows/MacOS build template.yml@master diff --git a/.github/workflows/Test Thunder.yml b/.github/workflows/Test Thunder.yml index 6c589cdbf..d8c13fff4 100644 --- a/.github/workflows/Test Thunder.yml +++ b/.github/workflows/Test Thunder.yml @@ -17,7 +17,7 @@ on: jobs: Thunder: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 strategy: matrix: From 9b67a12c8a5e144dccb7edeef0ccc2fd7dc7a6cc Mon Sep 17 00:00:00 2001 From: Mateusz Daniluk <121170681+VeithMetro@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:30:07 +0100 Subject: [PATCH 7/8] [Warnings] Remove unnecessary member variables to save some memory (#1793) * Use the warning suppression instead of the variable is not used macro in SystemInfo * Use the warning suppression instead of the variable is not used macro in NetworkInfo * Introduce a new DISABLE_WARNING_UNUSED_PRIVATE_FIELD macro Which is specific to clang * Change the macro to in NetworkInfo * Change the macro in SystemInfo * Change macros in PluginServer * Make sure to define the DISABLE_WARNING_UNUSED_PRIVATE_FIELD macro only for clang * Remove unused member variables, declare _hibernateStorage only if hibernate support is enabled * AdapterObserver callback member variable shouldn't be present on Windows and Apple * m_lastUpdateCpuStats is only used on Linux * m_lastUpdateCpuStats should be in the constructor only in case of Linux * Remove the -Wunused-private-field macro as it is no longer needed * Make sure not to initliaze callback for Windows and Apple * Make sure so that m_lastUpdateCpuStats is not defined on Apple but just Linux * Simplify the conditions for m_lastUpdateCpuStats initialization * Remove initialization of _state member variable from ControlData --- Source/Thunder/PluginServer.h | 10 ++++------ Source/core/NetworkInfo.cpp | 4 +++- Source/core/NetworkInfo.h | 4 +++- Source/core/SystemInfo.cpp | 2 +- Source/core/SystemInfo.h | 4 ++-- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Source/Thunder/PluginServer.h b/Source/Thunder/PluginServer.h index 9ddc623bb..9da464f97 100644 --- a/Source/Thunder/PluginServer.h +++ b/Source/Thunder/PluginServer.h @@ -676,7 +676,6 @@ namespace PluginHost { ControlData(const uint32_t maxRequests) : _isExtended(false) , _maxRequests(maxRequests) - , _state(0) , _major(~0) , _minor(~0) , _patch(~0) @@ -753,7 +752,6 @@ namespace PluginHost { private: bool _isExtended; uint32_t _maxRequests; - VARIABLE_IS_NOT_USED uint8_t _state; uint8_t _major; uint8_t _minor; uint8_t _patch; @@ -803,9 +801,8 @@ namespace PluginHost { Service& operator=(Service&&) = delete; Service& operator=(const Service&) = delete; - Service(const PluginHost::Config& server, const Plugin::Config& plugin, ServiceMap& administrator, const mode type, const Core::ProxyType& handler) + Service(const PluginHost::Config& server, const Plugin::Config& plugin, ServiceMap& administrator, const mode /* type */, const Core::ProxyType& handler) : PluginHost::Service(plugin, server.WebPrefix(), server.PersistentPath(), server.DataPath(), server.VolatilePath()) - , _mode(type) , _pluginHandling() , _handler(nullptr) , _extended(nullptr) @@ -1626,7 +1623,6 @@ namespace PluginHost { } private: - VARIABLE_IS_NOT_USED const mode _mode; mutable Core::CriticalSection _pluginHandling; // The handlers that implement the actual logic behind the service @@ -1646,7 +1642,9 @@ namespace PluginHost { uint32_t _lastId; ControlData _metadata; Core::Library _library; - VARIABLE_IS_NOT_USED void* _hibernateStorage; +#ifdef HIBERNATE_SUPPORT_ENABLED + void* _hibernateStorage; +#endif ExternalAccess _external; ServiceMap& _administrator; Core::SinkType _composit; diff --git a/Source/core/NetworkInfo.cpp b/Source/core/NetworkInfo.cpp index 8127300cd..0f877b626 100644 --- a/Source/core/NetworkInfo.cpp +++ b/Source/core/NetworkInfo.cpp @@ -1863,8 +1863,10 @@ namespace Core { #endif - AdapterObserver::AdapterObserver(INotification* callback) + AdapterObserver::AdapterObserver(INotification* callback VARIABLE_IS_NOT_USED) +#if !defined(__WINDOWS__) && !defined(__APPLE__) : _callback(callback) +#endif { #ifdef __WINDOWS__ //IoWMIOpenBlock(&GUID_NDIS_STATUS_LINK_STATE, WMIGUID_NOTIFICATION, . . .); diff --git a/Source/core/NetworkInfo.h b/Source/core/NetworkInfo.h index cd063ca21..683ce67a5 100644 --- a/Source/core/NetworkInfo.h +++ b/Source/core/NetworkInfo.h @@ -206,7 +206,9 @@ namespace Core { uint32_t Close(); private: - VARIABLE_IS_NOT_USED INotification* _callback; +#if !defined(__WINDOWS__) && !defined(__APPLE__) + INotification* _callback; +#endif }; #if defined(__WINDOWS__) || defined(__APPLE__) diff --git a/Source/core/SystemInfo.cpp b/Source/core/SystemInfo.cpp index f4878c46e..e519b8c55 100644 --- a/Source/core/SystemInfo.cpp +++ b/Source/core/SystemInfo.cpp @@ -141,7 +141,6 @@ namespace Core { SystemInfo::SystemInfo() : m_HostName(ConstructHostname()) - , m_lastUpdateCpuStats(0) { #ifdef __LINUX__ #ifdef __APPLE__ @@ -171,6 +170,7 @@ namespace Core { m_cpuloadavg[0]=info.loads[0]; m_cpuloadavg[1]=info.loads[1]; m_cpuloadavg[2]=info.loads[2]; + m_lastUpdateCpuStats = 0; #endif #endif diff --git a/Source/core/SystemInfo.h b/Source/core/SystemInfo.h index 39301480d..4202eff51 100644 --- a/Source/core/SystemInfo.h +++ b/Source/core/SystemInfo.h @@ -239,8 +239,6 @@ namespace Core { mutable uint64_t m_freeswap; mutable uint64_t m_cpuload; mutable uint64_t m_cpuloadavg[3]; - VARIABLE_IS_NOT_USED mutable time_t m_lastUpdateCpuStats; - void UpdateCpuStats() const; void UpdateRealtimeInfo(); @@ -250,6 +248,8 @@ namespace Core { mutable uint64_t m_prevCpuSystemTicks; mutable uint64_t m_prevCpuUserTicks; mutable uint64_t m_prevCpuIdleTicks; +#elif defined(__LINUX__) + mutable time_t m_lastUpdateCpuStats; #endif }; // class SystemInfo } // namespace Core From cd70ca5e75bede8b7179b4b380fe76be2b85c0b4 Mon Sep 17 00:00:00 2001 From: Pierre Wielders Date: Fri, 22 Nov 2024 08:51:38 +0100 Subject: [PATCH 8/8] Development/secure socket port (#1795) * [ASSERT] If Thunder is to avoid a crash, at least report it using an ASSERT! * [SECURESOCKET] Start enabling the possibility to run a SecureSocketPort server. Sofar Thunder supported SecureSocket clients where the intiative to enable secure connections was only based on creating a socket as a client. Tests are being written that require a secure socket server. This requires a sifferent set of calls and revealed an issue in the SocketPort. The server accepts the incoming socket. The bug was that the incoming socket, as it is already open and connected would not call the "Initialize()" method before it was added to the Resource Monitor. This has been fixed in SocketPort.cpp. Than this new incoming connection *must* follow a different path in the interaction with the opensll library. Already added new states like, ACCEPTING and CONNECTING, in stead of EXCHANGE however, testing it with a server build using the Thunder fnctionality still fails. It is probably due to the functionality/initialization that has to take place in the Initialize() method of the SecureScketPort where the SSL context is being created. The diffrentiation between a client socket and a server socket is already added to the Initialize, I guess it has to be tweaked. The client functionality of the SecureSocketPort has been tested with a server on the internet and is still working oke, so Client functionality has *not* been broken with these changes! --- Source/core/SocketPort.cpp | 12 +++- Source/cryptalgo/SecureSocketPort.cpp | 80 +++++++++++++++++---------- Source/cryptalgo/SecureSocketPort.h | 10 ++-- Source/websocket/WebSocketLink.h | 4 ++ 4 files changed, 69 insertions(+), 37 deletions(-) diff --git a/Source/core/SocketPort.cpp b/Source/core/SocketPort.cpp index 5a487e84f..c8e953396 100644 --- a/Source/core/SocketPort.cpp +++ b/Source/core/SocketPort.cpp @@ -496,9 +496,15 @@ namespace Thunder { m_SendOffset = 0; if ((m_State.load(Core::memory_order::memory_order_relaxed) & (SocketPort::LINK | SocketPort::OPEN | SocketPort::MONITOR)) == (SocketPort::LINK | SocketPort::OPEN)) { - // Open up an accepted socket, but not yet added to the monitor. - m_State.fetch_or(SocketPort::UPDATE, Core::memory_order::memory_order_relaxed); - nStatus = Core::ERROR_NONE; + + if (Initialize() != Core::ERROR_NONE) { + nStatus = Core::ERROR_ABORTED; + } + else { + // Open up an accepted socket, but not yet added to the monitor. + m_State.fetch_or(SocketPort::UPDATE, Core::memory_order::memory_order_relaxed); + nStatus = Core::ERROR_INPROGRESS; + } } else { ASSERT((m_Socket == INVALID_SOCKET) && (m_State.load(Core::memory_order::memory_order_relaxed) == 0)); diff --git a/Source/cryptalgo/SecureSocketPort.cpp b/Source/cryptalgo/SecureSocketPort.cpp index 764b94398..073414867 100644 --- a/Source/cryptalgo/SecureSocketPort.cpp +++ b/Source/cryptalgo/SecureSocketPort.cpp @@ -122,27 +122,35 @@ bool SecureSocketPort::Certificate::Verify(string& errorMsg) const { SecureSocketPort::Handler::~Handler() { - if(_ssl != nullptr) { - SSL_free(static_cast(_ssl)); - } - if(_context != nullptr) { - SSL_CTX_free(static_cast(_context)); - } + ASSERT(IsClosed() == true); + Close(0); } uint32_t SecureSocketPort::Handler::Initialize() { uint32_t success = Core::ERROR_NONE; - _context = SSL_CTX_new(TLS_method()); + if (IsOpen() == true) { + _context = SSL_CTX_new(TLS_server_method()); + _handShaking = ACCEPTING; + } + else { + _context = SSL_CTX_new(TLS_method()); + _handShaking = CONNECTING; + } _ssl = SSL_new(static_cast(_context)); SSL_set_fd(static_cast(_ssl), static_cast(*this).Descriptor()); - SSL_CTX_set_options(static_cast(_context), SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + SSL_CTX_set_options(static_cast(_context), SSL_OP_ALL | SSL_OP_NO_SSLv2); // Trust the same certificates as any other application if (SSL_CTX_set_default_verify_paths(static_cast(_context)) == 1) { success = Core::SocketPort::Initialize(); - } else { + + if (success == Core::ERROR_NONE) { + SSL_set_tlsext_host_name(static_cast(_ssl), RemoteNode().HostName().c_str()); + } + } + else { TRACE_L1("OpenSSL failed to load certificate store"); success = Core::ERROR_GENERAL; } @@ -151,12 +159,10 @@ uint32_t SecureSocketPort::Handler::Initialize() { } int32_t SecureSocketPort::Handler::Read(uint8_t buffer[], const uint16_t length) const { - int32_t result = SSL_read(static_cast(_ssl), buffer, length); - if (_handShaking != CONNECTED) { const_cast(*this).Update(); } - return (result); + return (SSL_read(static_cast(_ssl), buffer, length)); } int32_t SecureSocketPort::Handler::Write(const uint8_t buffer[], const uint16_t length) { @@ -171,8 +177,14 @@ uint32_t SecureSocketPort::Handler::Open(const uint32_t waitTime) { uint32_t SecureSocketPort::Handler::Close(const uint32_t waitTime) { if (_ssl != nullptr) { SSL_shutdown(static_cast(_ssl)); + SSL_free(static_cast(_ssl)); + _ssl = nullptr; + } + if (_context != nullptr) { + SSL_CTX_free(static_cast(_context)); + _context = nullptr; } - _handShaking = IDLE; + return(Core::SocketPort::Close(waitTime)); } @@ -199,43 +211,53 @@ void SecureSocketPort::Handler::ValidateHandShake() { if (!validationError.empty()) { TRACE_L1("OpenSSL certificate validation error for %s: %s", certificate.Subject().c_str(), validationError.c_str()); } - _handShaking = IDLE; + _handShaking = ERROR; Core::SocketPort::Unlock(); SetError(); } X509_free(x509cert); } else { - _handShaking = IDLE; + _handShaking = ERROR; SetError(); } } void SecureSocketPort::Handler::Update() { + if (IsOpen() == true) { int result; - if (_handShaking == IDLE) { - SSL_set_tlsext_host_name(static_cast(_ssl), RemoteNode().HostName().c_str()); - result = SSL_connect(static_cast(_ssl)); - if (result == 1) { - ValidateHandShake(); + ASSERT(_ssl != nullptr); + + if (_handShaking == CONNECTING) { + if ((result = SSL_connect(static_cast(_ssl))) == 1) { + _handShaking = EXCHANGE; } - else { - result = SSL_get_error(static_cast(_ssl), result); - if ((result == SSL_ERROR_WANT_READ) || (result == SSL_ERROR_WANT_WRITE)) { - _handShaking = EXCHANGE; - } + } + else if (_handShaking == ACCEPTING) { + if ((result = SSL_accept(static_cast(_ssl))) == 1) { + _handShaking = EXCHANGE; } } - else if (_handShaking == EXCHANGE) { - if (SSL_do_handshake(static_cast(_ssl)) == 1) { + + if (_handShaking == EXCHANGE) { + if ((result = SSL_do_handshake(static_cast(_ssl))) == 1) { ValidateHandShake(); } } + + if (result != 1) { + result = SSL_get_error(static_cast(_ssl), result); + if ((result != SSL_ERROR_WANT_READ) && (result != SSL_ERROR_WANT_WRITE)) { + _handShaking = ERROR; + } + else if (result == SSL_ERROR_WANT_WRITE) { + Trigger(); + } + } } - else if (_ssl != nullptr) { - _handShaking = IDLE; + else { _parent.StateChange(); } } diff --git a/Source/cryptalgo/SecureSocketPort.h b/Source/cryptalgo/SecureSocketPort.h index 280a44ae3..5fd037b40 100644 --- a/Source/cryptalgo/SecureSocketPort.h +++ b/Source/cryptalgo/SecureSocketPort.h @@ -64,9 +64,11 @@ namespace Crypto { class EXTERNAL Handler : public Core::SocketPort { private: enum state : uint8_t { - IDLE, + ACCEPTING, + CONNECTING, EXCHANGE, - CONNECTED + CONNECTED, + ERROR }; public: @@ -81,7 +83,7 @@ namespace Crypto { , _context(nullptr) , _ssl(nullptr) , _callback(nullptr) - , _handShaking(IDLE) { + , _handShaking(CONNECTING) { } ~Handler(); @@ -105,8 +107,6 @@ namespace Crypto { // Signal a state change, Opened, Closed or Accepted void StateChange() override { - - ASSERT(_context != nullptr); Update(); }; inline uint32_t Callback(IValidator* callback) { diff --git a/Source/websocket/WebSocketLink.h b/Source/websocket/WebSocketLink.h index 9b5e38d69..f074ed136 100644 --- a/Source/websocket/WebSocketLink.h +++ b/Source/websocket/WebSocketLink.h @@ -409,6 +409,10 @@ PUSH_WARNING(DISABLE_WARNING_THIS_IN_MEMBER_INITIALIZER_LIST) } POP_WARNING() ~HandlerType() override { + // If this assert fires, it means the socket was not closed + // by the one who opened it. That is unexpected. The creater + // of this link, should (besides opening it) also close it. + ASSERT(ACTUALLINK::IsClosed() == true); ACTUALLINK::Close(Core::infinite); }