From f07a75c380131a8141973f1aa34017a997cf08f2 Mon Sep 17 00:00:00 2001 From: VeithMetro Date: Mon, 12 May 2025 09:56:08 +0200 Subject: [PATCH 1/3] Update after interface changes --- DHCPServer/CMakeLists.txt | 1 - DHCPServer/DHCPServer.cpp | 124 +++++++++++++++++++++- DHCPServer/DHCPServer.h | 24 +++-- DHCPServer/DHCPServerJsonRpc.cpp | 160 ----------------------------- DHCPServer/DHCPServerPlugin.json | 2 +- DHCPServer/doc/DHCPServerPlugin.md | 85 ++++++++------- 6 files changed, 179 insertions(+), 217 deletions(-) delete mode 100644 DHCPServer/DHCPServerJsonRpc.cpp diff --git a/DHCPServer/CMakeLists.txt b/DHCPServer/CMakeLists.txt index 93d74e202..ec0d0e105 100644 --- a/DHCPServer/CMakeLists.txt +++ b/DHCPServer/CMakeLists.txt @@ -45,7 +45,6 @@ find_package(CompileSettingsDebug CONFIG REQUIRED) add_library(${MODULE_NAME} SHARED DHCPServer.cpp - DHCPServerJsonRpc.cpp DHCPServerImplementation.cpp Module.cpp) diff --git a/DHCPServer/DHCPServer.cpp b/DHCPServer/DHCPServer.cpp index f3c49a618..e825e6267 100644 --- a/DHCPServer/DHCPServer.cpp +++ b/DHCPServer/DHCPServer.cpp @@ -18,7 +18,6 @@ */ #include "DHCPServer.h" -#include namespace Thunder { namespace Plugin { @@ -45,14 +44,14 @@ PUSH_WARNING(DISABLE_WARNING_THIS_IN_MEMBER_INITIALIZER_LIST) DHCPServer::DHCPServer() : _skipURL(0) , _servers() + , _persistentPath() + , _adminLock() { - RegisterAll(); } POP_WARNING() /* virtual */ DHCPServer::~DHCPServer() { - UnregisterAll(); } /* virtual */ const string DHCPServer::Initialize(PluginHost::IShell* service) @@ -93,12 +92,16 @@ POP_WARNING() } } + Exchange::JDHCPServer::Register(*this, this); + // On success return empty, to indicate there is no error text. return (result); } /* virtual */ void DHCPServer::Deinitialize(PluginHost::IShell*) { + Exchange::JDHCPServer::Unregister(*this); + std::map::iterator index(_servers.begin()); while (index != _servers.end()) { @@ -255,5 +258,120 @@ POP_WARNING() } } + Core::hresult DHCPServer::Activate(const string& interface) + { + Core::hresult result = Core::ERROR_UNKNOWN_KEY; + + if (interface.empty() == false) { + _adminLock.Lock(); + auto server(_servers.find(interface)); + + if (server != _servers.end()) { + + if (server->second.IsActive() == false) { + result = server->second.Open(); + } + else { + result = Core::ERROR_ILLEGAL_STATE; + } + } + _adminLock.Unlock(); + } + + return (result); + } + + Core::hresult DHCPServer::Deactivate(const string& interface) + { + Core::hresult result = Core::ERROR_UNKNOWN_KEY; + + if (interface.empty() == false) { + _adminLock.Lock(); + auto server(_servers.find(interface)); + + if (server != _servers.end()) { + + if (server->second.IsActive() == true) { + result = server->second.Close(); + } else { + result = Core::ERROR_ILLEGAL_STATE; + } + } + _adminLock.Unlock(); + } + + return (result); + } + + void DHCPServer::Fill(Exchange::IDHCPServer::Server& data, const DHCPServerImplementation& server) const + { + data.interface = server.Interface(); + data.active = server.IsActive(); + + if (server.IsActive()) { + data.begin = server.BeginPool().HostAddress(); + data.end = server.EndPool().HostAddress(); + data.router = server.Router().HostAddress(); + + data.leases.Value() = std::vector(); + auto it(server.Leases()); + + while (it.Next() == true) { + Exchange::IDHCPServer::Lease lease; + lease.name = it.Current().Id().Text(); + lease.ip = it.Current().Address().HostAddress(); + + if (it.Current().Expiration() != 0) { + lease.expires.Value() = Core::Time(it.Current().Expiration()).ToISO8601(true); + } + data.leases.Value().push_back(lease); + } + } + } + + Core::hresult DHCPServer::Status(const Core::OptionalType& interface, Exchange::IDHCPServer::IServerIterator*& servers) const + { + Core::hresult result = Core::ERROR_NONE; + std::list serverList; + + _adminLock.Lock(); + + if (interface.IsSet() == false) { + + DHCPServerMap::const_iterator index = _servers.begin(); + + while (index != _servers.end()) { + Exchange::IDHCPServer::Server server; + Fill(server, index->second); + serverList.push_back(server); + index++; + } + } + else { + DHCPServerMap::const_iterator index = _servers.find(interface); + + if (index != _servers.end()) { + Exchange::IDHCPServer::Server server; + Fill(server, index->second); + serverList.push_back(server); + } + else { + result = Core::ERROR_UNKNOWN_KEY; + } + } + _adminLock.Unlock(); + + if (serverList.empty() == false) { + using Iterator = Exchange::IDHCPServer::IServerIterator; + servers = Core::ServiceType>::Create(serverList); + ASSERT(servers != nullptr); + } + else { + servers = nullptr; + } + + return (result); + } + } // namespace Plugin } // namespace Thunder diff --git a/DHCPServer/DHCPServer.h b/DHCPServer/DHCPServer.h index d5f02724c..541e66a34 100644 --- a/DHCPServer/DHCPServer.h +++ b/DHCPServer/DHCPServer.h @@ -20,13 +20,17 @@ #pragma once #include "DHCPServerImplementation.h" -#include +#include +#include #include "Module.h" namespace Thunder { namespace Plugin { - class DHCPServer : public PluginHost::IPlugin, public PluginHost::IWeb, public PluginHost::JSONRPC { + class DHCPServer : public Exchange::IDHCPServer + , public PluginHost::IPlugin + , public PluginHost::IWeb + , public PluginHost::JSONRPC { public: class Data : public Core::JSON::Container { private: @@ -253,6 +257,7 @@ namespace Plugin { INTERFACE_ENTRY(PluginHost::IPlugin) INTERFACE_ENTRY(PluginHost::IWeb) INTERFACE_ENTRY(PluginHost::IDispatcher) + INTERFACE_ENTRY(Exchange::IDHCPServer) END_INTERFACE_MAP public: @@ -267,12 +272,10 @@ namespace Plugin { void Inbound(Web::Request& request) override; Core::ProxyType Process(const Web::Request& request) override; - // JsonRpc - void RegisterAll(); - void UnregisterAll(); - uint32_t endpoint_activate(const JsonData::DHCPServer::ActivateParamsInfo& params); - uint32_t endpoint_deactivate(const JsonData::DHCPServer::ActivateParamsInfo& params); - uint32_t get_status(const string& index, Core::JSON::ArrayType& response) const; + Core::hresult Activate(const string& interface) override; + Core::hresult Deactivate(const string& interface) override; + void Fill(Exchange::IDHCPServer::Server& data, const DHCPServerImplementation& server) const; + Core::hresult Status(const Core::OptionalType& interface /* @index */, Exchange::IDHCPServer::IServerIterator*& servers /* @out */) const override; // Lease permanent storage // ------------------------------------------------------------------------------------------------------- @@ -282,9 +285,12 @@ namespace Plugin { // Callbacks void OnNewIPRequest(const string& interface, const DHCPServerImplementation::Lease* lease); private: + using DHCPServerMap = std::map; + uint16_t _skipURL; - std::map _servers; + DHCPServerMap _servers; std::string _persistentPath; + mutable Core::CriticalSection _adminLock; }; } // namespace Plugin diff --git a/DHCPServer/DHCPServerJsonRpc.cpp b/DHCPServer/DHCPServerJsonRpc.cpp deleted file mode 100644 index 6c5fca7e9..000000000 --- a/DHCPServer/DHCPServerJsonRpc.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 Metrological - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Module.h" -#include "DHCPServer.h" -#include "DHCPServerImplementation.h" -#include - - -namespace Thunder { - -namespace Plugin { - - using namespace JsonData::DHCPServer; - - namespace - { - void Fill(ServerData& data, const DHCPServerImplementation& server) - { - data.Interface = server.Interface(); - data.Active = server.IsActive(); - if (server.IsActive()) { - data.Begin = server.BeginPool().HostAddress(); - data.End = server.EndPool().HostAddress(); - data.Router = server.Router().HostAddress(); - - auto it(server.Leases()); - while (it.Next() == true) { - auto& lease = data.Leases.Add(); - lease.Name = it.Current().Id().Text(); - lease.Ip = it.Current().Address().HostAddress(); - if (it.Current().Expiration() != 0) { - lease.Expires = Core::Time(it.Current().Expiration()).ToISO8601(true); - } - } - } - } - } - - // Registration - // - - void DHCPServer::RegisterAll() - { - Register(_T("activate"), &DHCPServer::endpoint_activate, this); - Register(_T("deactivate"), &DHCPServer::endpoint_deactivate, this); - Property>(_T("status"), &DHCPServer::get_status, nullptr, this); - } - - void DHCPServer::UnregisterAll() - { - Unregister(_T("deactivate")); - Unregister(_T("activate")); - Unregister(_T("status")); - } - - // API implementation - // - - // Method: activate - Activates a DHCP server - // Return codes: - // - ERROR_NONE: Success - // - ERROR_GENERAL: Failed to activate server - // - ERROR_UNKNOWN_KEY: Invalid interface name given - // - ERROR_ILLEGAL_STATE: Server is already activated - uint32_t DHCPServer::endpoint_activate(const ActivateParamsInfo& params) - { - uint32_t result = Core::ERROR_UNKNOWN_KEY; - const string& interface = params.Interface.Value(); - - if (interface.empty() == false) { - auto server(_servers.find(interface)); - if (server != _servers.end()) { - if (server->second.IsActive() == false) { - result = server->second.Open(); - } - else { - result = Core::ERROR_ILLEGAL_STATE; - } - } - } - - return result; - } - - // Method: deactivate - Deactivates a DHCP server - // Return codes: - // - ERROR_NONE: Success - // - ERROR_GENERAL: Failed to deactivate server - // - ERROR_UNKNOWN_KEY: Invalid interface name given - // - ERROR_ILLEGAL_STATE: Server is not activated - uint32_t DHCPServer::endpoint_deactivate(const ActivateParamsInfo& params) - { - uint32_t result = Core::ERROR_UNKNOWN_KEY; - const string& interface = params.Interface.Value(); - - if (interface.empty() == false) { - auto server(_servers.find(interface)); - if (server != _servers.end()) { - if (server->second.IsActive() == true) { - result = server->second.Close(); - } else { - result = Core::ERROR_ILLEGAL_STATE; - } - } - } - - return result; - } - - // Property: status - Server status - // Return codes: - // - ERROR_NONE: Success - // - ERROR_UNKNOWN_KEY: Invalid server name given - uint32_t DHCPServer::get_status(const string& index, Core::JSON::ArrayType& response) const - { - uint32_t result = Core::ERROR_NONE; - - if (index.empty()) { - auto it = _servers.begin(); - while (it != _servers.end()) { - ServerData info; - Fill(info, it->second); - response.Add(info); - it++; - } - } else { - auto it(_servers.find(index)); - if (it != _servers.end()) { - ServerData info; - Fill(info, it->second); - response.Add(info); - } else { - result = Core::ERROR_UNKNOWN_KEY; - } - } - - return result; - } - -} // namespace Plugin - -} - diff --git a/DHCPServer/DHCPServerPlugin.json b/DHCPServer/DHCPServerPlugin.json index 65b7ca2df..37b4d2300 100644 --- a/DHCPServer/DHCPServerPlugin.json +++ b/DHCPServer/DHCPServerPlugin.json @@ -72,6 +72,6 @@ ] }, "interface": { - "$ref": "{interfacedir}/DHCPServer.json#" + "$ref": "{cppinterfacedir}/IDHCPServer.h" } } diff --git a/DHCPServer/doc/DHCPServerPlugin.md b/DHCPServer/doc/DHCPServerPlugin.md index 5599aa24d..809e4f114 100644 --- a/DHCPServer/doc/DHCPServerPlugin.md +++ b/DHCPServer/doc/DHCPServerPlugin.md @@ -1,5 +1,5 @@ - + # DHCP Server Plugin **Version: 1.0** @@ -10,26 +10,26 @@ DHCPServer plugin for Thunder framework. ### Table of Contents -- [Introduction](#head.Introduction) -- [Configuration](#head.Configuration) -- [Interfaces](#head.Interfaces) -- [Methods](#head.Methods) -- [Properties](#head.Properties) +- [Introduction](#head_Introduction) +- [Configuration](#head_Configuration) +- [Interfaces](#head_Interfaces) +- [Methods](#head_Methods) +- [Properties](#head_Properties) - + # Introduction - + ## Scope This document describes purpose and functionality of the DHCPServer plugin. It includes detailed specification about its configuration, methods and properties provided. - + ## Case Sensitivity All identifiers of the interfaces described in this document are case-sensitive. Thus, unless stated otherwise, all keywords, entities, properties, relations and actions should be treated as such. - + ## Acronyms, Abbreviations and Terms The table below provides and overview of acronyms used in this document and their definitions. @@ -48,7 +48,7 @@ The table below provides and overview of terms and abbreviations used in this do | :-------- | :-------- | | callsign | The name given to an instance of a plugin. One plugin can be instantiated multiple times, but each instance the instance name, callsign, must be unique. | - + ## References | Ref ID | Description | @@ -59,7 +59,7 @@ The table below provides and overview of terms and abbreviations used in this do | [JSON](http://www.json.org/) | JSON specification | | [Thunder](https://github.com/WebPlatformForEmbedded/Thunder/blob/master/doc/WPE%20-%20API%20-%20Thunder.docx) | Thunder API Reference | - + # Configuration The table below lists configuration options of the plugin. @@ -79,14 +79,15 @@ The table below lists configuration options of the plugin. | configuration.servers[#].poolsize | integer | mandatory | IP pool size (in IP numbers) | | configuration.servers[#]?.router | integer | optional | IP of router | - + # Interfaces This plugin implements the following interfaces: -- [DHCPServer.json](https://github.com/rdkcentral/ThunderInterfaces/blob/master/jsonrpc/DHCPServer.json) (version 1.0.0) (compliant format) +- IDHCPServer ([IDHCPServer.h](https://github.com/rdkcentral/ThunderInterfaces/blob/master/interfaces/IDHCPServer.h)) (version 1.0.0) (compliant format) +> This interface uses legacy ```lowercase``` naming convention. With the next major release the naming convention will change to ```camelCase```. - + # Methods The following methods are provided by the DHCPServer plugin: @@ -95,11 +96,11 @@ DHCPServer interface methods: | Method | Description | | :-------- | :-------- | -| [activate](#method.activate) | Activates a DHCP server | -| [deactivate](#method.deactivate) | Deactivates a DHCP server | +| [activate](#method_activate) | Activates a DHCP server | +| [deactivate](#method_deactivate) | Deactivates a DHCP server | - -## *activate [method](#head.Methods)* + +## *activate [method](#head_Methods)* Activates a DHCP server. @@ -114,7 +115,7 @@ Activates a DHCP server. | Name | Type | M/O | Description | | :-------- | :-------- | :-------- | :-------- | -| result | null | mandatory | Always null (default: *None*) | +| result | null | mandatory | Always null | ### Errors @@ -149,8 +150,8 @@ Activates a DHCP server. } ``` - -## *deactivate [method](#head.Methods)* + +## *deactivate [method](#head_Methods)* Deactivates a DHCP server. @@ -165,7 +166,7 @@ Deactivates a DHCP server. | Name | Type | M/O | Description | | :-------- | :-------- | :-------- | :-------- | -| result | null | mandatory | Always null (default: *None*) | +| result | null | mandatory | Always null | ### Errors @@ -200,7 +201,7 @@ Deactivates a DHCP server. } ``` - + # Properties The following properties are provided by the DHCPServer plugin: @@ -209,41 +210,39 @@ DHCPServer interface properties: | Property | R/W | Description | | :-------- | :-------- | :-------- | -| [status](#property.status) | read-only | Server status | +| [status](#property_status) | read-only | Server status | - -## *status [property](#head.Properties)* + +## *status [property](#head_Properties)* Provides access to the server status. > This property is **read-only**. -> The *server* parameter shall be passed as the index to the property, e.g. ``DHCPServer.1.status@``. +> The *interface* parameter shall be passed as the index to the property, i.e. ``status@``. ### Index | Name | Type | M/O | Description | | :-------- | :-------- | :-------- | :-------- | -| server | string | mandatory | If omitted, status of all configured servers is returned | +| interface | string | mandatory | Server name, if omitted, status of all configured servers is returned | ### Value -### Result - | Name | Type | M/O | Description | | :-------- | :-------- | :-------- | :-------- | -| result | array | mandatory | List of configured servers | -| result[#] | object | mandatory | *...* | -| result[#].interface | string | mandatory | Network interface name | -| result[#].active | boolean | mandatory | Denotes if server is currently active | -| result[#]?.begin | string | optional | IP address pool start | -| result[#]?.end | string | optional | IP address pool end | -| result[#]?.router | string | optional | Router IP address | -| result[#]?.leases | array | optional | List of IP address leases | -| result[#]?.leases[#] | object | optional | Lease description | -| result[#]?.leases[#].name | string | mandatory | Client identifier (or client hardware address if identifier is absent) | -| result[#]?.leases[#].ip | string | mandatory | Client IP address | -| result[#]?.leases[#]?.expires | string | optional | Client IP expiration time (in ISO8601 format, empty: never expires) | +| (property) | array | mandatory | List of configured servers *(if only one element is present then the array will be omitted)* | +| (property)[#] | object | mandatory | *...* | +| (property)[#].interface | string | mandatory | Network interface name | +| (property)[#].active | boolean | mandatory | Denotes if server is currently active | +| (property)[#]?.begin | string | optional | IP address pool start | +| (property)[#]?.end | string | optional | IP address pool end | +| (property)[#]?.router | string | optional | Router IP address | +| (property)[#]?.leases | array | optional | List of IP address leases
*Array length must be at most 100 elements.* | +| (property)[#]?.leases[#] | object | mandatory | *...* | +| (property)[#]?.leases[#].name | string | mandatory | Client identifier (or client hardware address if identifier is absent) | +| (property)[#]?.leases[#].ip | string | mandatory | Client IP address | +| (property)[#]?.leases[#]?.expires | string | optional | Client IP expiration time (in ISO8601 format, empty: never expires) | ### Errors From 2c8d8511c24f1b62623b210f44ce87753ae5489f Mon Sep 17 00:00:00 2001 From: VeithMetro Date: Mon, 12 May 2025 11:04:31 +0200 Subject: [PATCH 2/3] Adjust the Windows project files --- DHCPServer/DHCPServer.vcxproj | 1 - DHCPServer/DHCPServer.vcxproj.filters | 3 --- 2 files changed, 4 deletions(-) diff --git a/DHCPServer/DHCPServer.vcxproj b/DHCPServer/DHCPServer.vcxproj index c72879f57..346eb252f 100644 --- a/DHCPServer/DHCPServer.vcxproj +++ b/DHCPServer/DHCPServer.vcxproj @@ -181,7 +181,6 @@ - diff --git a/DHCPServer/DHCPServer.vcxproj.filters b/DHCPServer/DHCPServer.vcxproj.filters index 1815f3cae..55016b7dc 100644 --- a/DHCPServer/DHCPServer.vcxproj.filters +++ b/DHCPServer/DHCPServer.vcxproj.filters @@ -10,9 +10,6 @@ Source Files - - Source Files - From 555f3fb05c287b49759a193578a3b71fea9706d9 Mon Sep 17 00:00:00 2001 From: VeithMetro Date: Tue, 13 May 2025 12:38:43 +0200 Subject: [PATCH 3/3] expires is now Core::Time, so no need to translte to string anymore --- DHCPServer/DHCPServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DHCPServer/DHCPServer.cpp b/DHCPServer/DHCPServer.cpp index e825e6267..ae6180093 100644 --- a/DHCPServer/DHCPServer.cpp +++ b/DHCPServer/DHCPServer.cpp @@ -322,7 +322,7 @@ POP_WARNING() lease.ip = it.Current().Address().HostAddress(); if (it.Current().Expiration() != 0) { - lease.expires.Value() = Core::Time(it.Current().Expiration()).ToISO8601(true); + lease.expires.Value() = Core::Time(it.Current().Expiration()); } data.leases.Value().push_back(lease); }