Skip to content

[RDK-E]: NetworkconnectionRecovery.sh migration to C/C++ Module#274

Open
udaykrishnag wants to merge 17 commits intodevelopfrom
topic/RDK-59986
Open

[RDK-E]: NetworkconnectionRecovery.sh migration to C/C++ Module#274
udaykrishnag wants to merge 17 commits intodevelopfrom
topic/RDK-59986

Conversation

@udaykrishnag
Copy link

No description provided.

@udaykrishnag udaykrishnag requested a review from a team as a code owner February 10, 2026 20:26
Copilot AI review requested due to automatic review settings February 10, 2026 20:26
@github-actions
Copy link


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@rdkcmf-jenkins
Copy link
Contributor

b'## Blackduck scan failure details

Summary: 0 violations, 0 files pending approval, 1 file pending identification.

  • Protex Server Path: /home/blackduck/github/networkmanager/274/rdkcentral/networkmanager

  • Commit: 3fd5c23

Report detail: gist'

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new NetworkConnectionStats Thunder/WPEFramework module (in-process plugin + out-of-process implementation) intended to replace shell-based recovery/diagnostics with a C/C++ implementation that queries NetworkManager via COM-RPC/JSON-RPC and emits telemetry.

Changes:

  • Adds an out-of-process diagnostics implementation that periodically generates network reports and subscribes to NetworkManager events.
  • Adds two NetworkManager provider implementations (COM-RPC and JSON-RPC) plus a runtime factory selector.
  • Integrates the new networkstats/ component into the build and adds configuration/docs assets.

Reviewed changes

Copilot reviewed 27 out of 28 changed files in this pull request and generated 24 comments.

Show a summary per file
File Description
networkstats/plugin/ThunderJsonRPCProvider.h Declares JSON-RPC-based NetworkManager provider.
networkstats/plugin/ThunderJsonRPCProvider.cpp Implements NetworkManager JSON-RPC calls (GetIPSettings, Ping, event subscribe).
networkstats/plugin/ThunderComRPCProvider.h Declares COM-RPC-based NetworkManager provider.
networkstats/plugin/ThunderComRPCProvider.cpp Implements NetworkManager COM-RPC calls (GetIPSettings, Ping, event subscribe).
networkstats/plugin/NetworkDataProviderFactory.h Factory to select COM-RPC vs JSON-RPC provider based on config.
networkstats/plugin/NetworkConnectionStatsLogger.h Adds a lightweight logging wrapper/macros for the module.
networkstats/plugin/NetworkConnectionStatsLogger.cpp Implements stdout/RDK logger backend for logging wrapper.
networkstats/plugin/NetworkConnectionStatsImplementation.h Declares out-of-process implementation class, threading, and event handlers.
networkstats/plugin/NetworkConnectionStatsImplementation.cpp Implements periodic report generation, telemetry emission, and event-driven triggers.
networkstats/plugin/NetworkConnectionStats.h Declares in-process plugin shell that spawns/aggregates the implementation.
networkstats/plugin/NetworkConnectionStats.cpp Implements plugin lifecycle wiring and COM-RPC aggregation.
networkstats/plugin/NetworkConnectionStats.config Adds example Thunder plugin JSON configuration.
networkstats/plugin/NetworkConnectionStats.conf.in Adds config template for CMake write_config() generation.
networkstats/plugin/Module.h Adds module header wiring for Thunder build macros/includes.
networkstats/plugin/Module.cpp Adds module declaration for build reference.
networkstats/plugin/INetworkData.h Defines common interface for network data providers.
networkstats/plugin/CMakeLists.txt Builds the plugin + implementation libraries and installs config.
networkstats/interface/INetworkConnectionStats.h Defines COM-RPC interface for the out-of-process implementation.
networkstats/interface/CMakeLists.txt Generates ProxyStub library for the interface.
networkstats/definition/NetworkConnectionStats.json Adds JSON-RPC API definition/documentation (currently not wired into build).
networkstats/definition/CMakeLists.txt Adds JsonGenerator integration for docs/stubs generation.
networkstats/THUNDER_PLUGIN_QUICK_REFERENCE.md Adds quick-reference documentation for the intended architecture.
networkstats/THUNDER_PLUGIN_CONVERSION.md Adds conversion notes from standalone app to Thunder module.
networkstats/README_INTERNAL_PLUGIN.md Describes internal-only plugin behavior/configuration and telemetry outputs.
networkstats/NetworkStatsDesign_ver1.md Provides high-level design diagrams and operational flow.
networkstats/CMakeLists.txt Adds networkstats sub-project build entrypoint.
CMakeLists.txt Adds USE_TELEMETRY option and includes networkstats in the top-level build.
.DS_Store Adds an unintended macOS metadata file.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +20 to +21
#ifndef __THUNDERPROVIDER_H__
#define __THUNDERPROVIDER_H__
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The include guard macro name starts with double underscores (THUNDERPROVIDER_H), which is reserved for the implementation in C/C++. Please rename it to a non-reserved identifier (e.g., THUNDER_JSONRPC_PROVIDER_H).

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +21
#ifndef __THUNDERCOMRPCPROVIDER_H__
#define __THUNDERCOMRPCPROVIDER_H__
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The include guard macro (THUNDERCOMRPCPROVIDER_H) begins with double underscores, which are reserved identifiers in C/C++. Please rename it to a non-reserved macro to avoid undefined behavior/toolchain issues.

Copilot uses AI. Check for mistakes.
Comment on lines +186 to +191
/* @brief Get DNS server entries */
std::string NetworkJsonRPCProvider::getDnsEntries()
{
// TODO: Implement DNS entries retrieval
return "";
}
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getDnsEntries() is currently a stub that always returns an empty string. Since this provider can be selected at runtime via providerType=jsonrpc, this will lead to incorrect diagnostics when that provider is used; please implement DNS retrieval (or remove the method from the interface if it’s not needed).

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +118
struct tm* lt;
const char* fileName = trimPath(file);

if (gDefaultLogLevel < level)
return;

gettimeofday(&tv, NULL);
lt = localtime(&tv.tv_sec);

printf("%.2d:%.2d:%.2d.%.6lld [%-5s] [PID=%d] [TID=%d] [%s +%d] %s : %s\n", lt->tm_hour, lt->tm_min, lt->tm_sec, (long long int)tv.tv_usec, levelMap[level], getpid(), gettid(), fileName, line, func, formattedLog);
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logPrint() uses localtime(), which is not thread-safe and can cause data races/corrupted timestamps when logging from multiple threads (this plugin starts several threads). Please use localtime_r() (or gmtime_r()) with a stack-allocated tm instead.

Suggested change
struct tm* lt;
const char* fileName = trimPath(file);
if (gDefaultLogLevel < level)
return;
gettimeofday(&tv, NULL);
lt = localtime(&tv.tv_sec);
printf("%.2d:%.2d:%.2d.%.6lld [%-5s] [PID=%d] [TID=%d] [%s +%d] %s : %s\n", lt->tm_hour, lt->tm_min, lt->tm_sec, (long long int)tv.tv_usec, levelMap[level], getpid(), gettid(), fileName, line, func, formattedLog);
struct tm lt;
const char* fileName = trimPath(file);
if (gDefaultLogLevel < level)
return;
gettimeofday(&tv, NULL);
localtime_r(&tv.tv_sec, &lt);
printf("%.2d:%.2d:%.2d.%.6lld [%-5s] [PID=%d] [TID=%d] [%s +%d] %s : %s\n", lt.tm_hour, lt.tm_min, lt.tm_sec, (long long int)tv.tv_usec, levelMap[level], getpid(), gettid(), fileName, line, func, formattedLog);

Copilot uses AI. Check for mistakes.
Comment on lines +118 to +119
printf("%.2d:%.2d:%.2d.%.6lld [%-5s] [PID=%d] [TID=%d] [%s +%d] %s : %s\n", lt->tm_hour, lt->tm_min, lt->tm_sec, (long long int)tv.tv_usec, levelMap[level], getpid(), gettid(), fileName, line, func, formattedLog);
fflush(stdout);
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code calls gettid(), but gettid() is not a portable/POSIX API and may be unavailable depending on libc/kernel headers, causing build failures. Consider using syscall(SYS_gettid) (since you already include <sys/syscall.h>) or conditionally compiling the TID output.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +35
#### COM-RPC Interface
- **INetworkConnectionStats.h** - Defines the COM-RPC interface with:
- INetworkConnectionStats interface with all network diagnostic methods
- INotification sub-interface for event notifications
- Proper interface IDs and stubgen annotations

#### Plugin Main Class
- **NetworkConnectionStats.h** - Plugin header with:
- Inherits from `PluginHost::IPlugin` and `PluginHost::JSONRPC`
- Notification handler for RPC connection lifecycle and events
- Interface aggregation for COM-RPC

- **NetworkConnectionStats.cpp** - Plugin implementation with:
- IPlugin lifecycle methods (Initialize, Deinitialize, Information)
- RPC connection management
- JSON-RPC registration
- Notification forwarding
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This conversion document states the plugin inherits PluginHost::JSONRPC, registers JSON-RPC methods, and provides a JSON-RPC API spec. The current codebase implements an internal-only IPlugin + COM-RPC aggregate and the networkstats/definition subdir is not built. Please update the document to reflect the implemented architecture (or implement the described JSON-RPC layer).

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +8
{
"$schema": "interface.schema.json",
"jsonrpc": "2.0",
"info": {
"title": "NetworkConnectionStats API",
"class": "NetworkConnectionStats",
"description": "NetworkConnectionStats plugin for network diagnostics and monitoring"
},
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This JSON-RPC definition describes a public API surface (methods/events) that is not implemented by the current plugin (which is internal-only and does not derive from PluginHost::JSONRPC). Please either update this spec to match the implemented interfaces, or remove/disable it to avoid generating misleading documentation/stubs later.

Copilot uses AI. Check for mistakes.
#include <atomic>
#include <queue>
#include <mutex>
#include <condition_variable>
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NetworkConnectionStatsImplementation.h uses std::list (_notificationCallbacks) but does not include . Please add the missing standard header to avoid compile failures depending on indirect includes.

Suggested change
#include <condition_variable>
#include <condition_variable>
#include <list>

Copilot uses AI. Check for mistakes.
#include "INetworkData.h"
#include "Module.h"
#include <string>
#include <core/JSON.h>
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This header declares std::shared_ptr (m_networkManagerClient) but never includes . Please include here to avoid build failures due to indirect include order.

Suggested change
#include <core/JSON.h>
#include <core/JSON.h>
#include <memory>
#include <functional>

Copilot uses AI. Check for mistakes.
@rdkcmf-jenkins
Copy link
Contributor

b'## Blackduck scan failure details

Summary: 0 violations, 0 files pending approval, 1 file pending identification.

  • Protex Server Path: /home/blackduck/github/networkmanager/274/rdkcentral/networkmanager

  • Commit: 3fd5c23

Report detail: gist'

@rdkcmf-jenkins
Copy link
Contributor

b'## WARNING: A Blackduck scan failure has been waived

A prior failure has been upvoted

  • Upvote reason: OK

  • Commit: 3fd5c23
    '

@mhughesacn
Copy link

I have checked the fossid failures: There is one match to rdkcentral which is not of interest. The other two matches are from jmanc3/winbar and Karunakaran has pointed out that jmanc3 has used original code from rdkcentral (committed 17-Nov-24) which jmanc3 then committed several months later on 16-Jun-25. So the matches are a non-issue.

Copilot AI review requested due to automatic review settings February 12, 2026 15:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 28 changed files in this pull request and generated 9 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

CMakeLists.txt Outdated
option(ENABLE_LEGACY_PLUGINS "Enable Legacy Plugins" ON)
option(USE_RDK_LOGGER "Enable RDK Logger for logging" OFF )
option(ENABLE_UNIT_TESTING "Enable unit tests" OFF)
option(USE_TELEMETRY "Enable Telemetry support for NetworkConnectionStats" ON)
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This top-level option introduces USE_TELEMETRY defaulting to ON. USE_TELEMETRY is also used by other targets in this repo (e.g., tools/upnp), so this change will implicitly enable telemetry (and add a hard dependency on T2) beyond NetworkConnectionStats. Consider defaulting this option to OFF, or using a more scoped option name (e.g., NETWORKSTATS_USE_TELEMETRY) to avoid changing behavior of unrelated components.

Copilot uses AI. Check for mistakes.
Comment on lines +96 to +99

// Notification callbacks
std::list<Exchange::INetworkConnectionStats::INotification*> _notificationCallbacks;
Core::CriticalSection _notificationLock;
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This header uses std::list for _notificationCallbacks but does not include <list>. Please include the required standard header directly here (avoid relying on transitive includes from Thunder headers).

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +15
│ │ - Inherits IPlugin + JSONRPC │ │
│ │ - Manages RPC connection │ │
│ │ - Forwards JSON-RPC calls │ │
│ │ - Handles notifications │ │
│ └────────────────┬───────────────────────────────────────────┘ │
│ │ COM-RPC │
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This quick reference states the plugin inherits PluginHost::JSONRPC and exposes many JSON-RPC methods/events, but the implementation in this PR is IPlugin-only and the COM-RPC interface only defines Configure/Register/Unregister. Please update this document to match the actual code (or implement the documented APIs) to avoid misleading integrators.

Suggested change
│ │ - Inherits IPlugin + JSONRPC │ │
│ │ - Manages RPC connection │ │
│ │ - Forwards JSON-RPC calls │ │
│ │ - Handles notifications │ │
│ └────────────────┬───────────────────────────────────────────┘ │
│ │ COM-RPC │
│ │ - Implements IPlugin │ │
│ │ - Manages COM-RPC connection │ │
│ │ - Uses COM-RPC to talk to implementation │ │
│ └────────────────┬───────────────────────────────────────────┘ │
│ │ COM-RPC (INetworkConnectionStats) │

Copilot uses AI. Check for mistakes.
configuration = JSON()
configuration.add("root", process)
configuration.add("reportingInterval", "@PLUGIN_NETWORKCONNECTIONSTATS_REPORTING_INTERVAL@")
configuration.add("autoStart", True)
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configuration.add("autoStart", True) doesn’t match the format used by other *.conf.in files in this repo (they use quoted strings like "true" or CMake substitutions). True is likely invalid for this config templating and may break config generation/parsing.

Suggested change
configuration.add("autoStart", True)
configuration.add("autoStart", "@PLUGIN_NETWORKCONNECTIONSTATS_AUTOSTART@")

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +58
uint32_t Register(INetworkConnectionStats::INotification* notification) override;
uint32_t Unregister(INetworkConnectionStats::INotification* notification) override;
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Register/Unregister use INetworkConnectionStats::INotification* but INetworkConnectionStats is declared under WPEFramework::Exchange. As written, this won’t resolve in WPEFramework::Plugin and should be fully qualified (e.g., Exchange::INetworkConnectionStats::INotification*) to match the inherited interface.

Suggested change
uint32_t Register(INetworkConnectionStats::INotification* notification) override;
uint32_t Unregister(INetworkConnectionStats::INotification* notification) override;
uint32_t Register(Exchange::INetworkConnectionStats::INotification* notification) override;
uint32_t Unregister(Exchange::INetworkConnectionStats::INotification* notification) override;

Copilot uses AI. Check for mistakes.
Comment on lines +174 to +176
// Create network provider using factory
m_provider = NetworkDataProviderFactory::CreateProvider(providerType);
if (m_provider == nullptr) {
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Configure() assigns a new object to m_provider without first cleaning up any existing provider instance (and any running threads/subscriptions tied to it). If Configure() is called more than once, this will leak and can leave multiple background threads running. Clean up the previous state before replacing m_provider.

Copilot uses AI. Check for mistakes.

#include "Module.h"

MODULE_NAME_DECLARATION(BUILD_REFERENCE)
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MODULE_NAME_DECLARATION(BUILD_REFERENCE) looks inconsistent with the rest of this repo, which uses PLUGIN_BUILD_REFERENCE (and this module’s CMake defines -DPLUGIN_BUILD_REFERENCE=...). If BUILD_REFERENCE isn’t defined, this will fail to compile or embed the wrong build reference.

Suggested change
MODULE_NAME_DECLARATION(BUILD_REFERENCE)
MODULE_NAME_DECLARATION(PLUGIN_BUILD_REFERENCE)

Copilot uses AI. Check for mistakes.
/* Test main function to validate NetworkJsonRPCProvider member functions */
int main()
{
NetworkJsonRPCProvider provider;
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSON-RPC provider test main() constructs NetworkJsonRPCProvider but never calls Initialize(). As a result, the menu actions will hit "client not initialized" and return empty/false. Call provider.Initialize() once before entering the menu (as done in the COM-RPC provider test).

Suggested change
NetworkJsonRPCProvider provider;
NetworkJsonRPCProvider provider;
uint32_t initResult = provider.Initialize();
if (initResult != WPEFramework::Core::ERROR_NONE) {
std::cerr << "Failed to initialize NetworkJsonRPCProvider, error code: " << initResult << std::endl;
return 1;
}

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 18, 2026 14:55
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 28 changed files in this pull request and generated 15 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

* @param interface_name Interface name (e.g., eth0, wlan0)
* @return IPv4 address string
*/
std::string getIpv4Address(std::string interface_name) override;
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String parameters should be passed by const reference to avoid unnecessary copies. Change std::string interface_name to const std::string& interface_name.

Copilot uses AI. Check for mistakes.
int choice;
std::string interface_name;
bool running = true;

Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Initialize method should be called before using the provider in the test main function. Add a check and call to provider.Initialize() before running tests to ensure proper initialization.

Suggested change
const uint32_t initResult = provider.Initialize();
if (initResult != WPEFramework::Core::ERROR_NONE) {
std::cerr << "Failed to initialize NetworkJsonRPCProvider, error code: " << initResult << std::endl;
return -1;
}

Copilot uses AI. Check for mistakes.

uint32_t NetworkConnectionStatsImplementation::Configure(const string configLine)
{
NSLOG_INFO("NetworkConnectionStatsImplementation::Configure");
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing error handling: If m_provider is deleted due to initialization failure but Configure() is called again (which shouldn't happen but could in error scenarios), m_provider will be nullptr and any subsequent access will cause crashes. Consider adding a check at the beginning of Configure() to prevent re-configuration or handle the re-initialization case properly.

Suggested change
NSLOG_INFO("NetworkConnectionStatsImplementation::Configure");
NSLOG_INFO("NetworkConnectionStatsImplementation::Configure");
// Ensure provider is available before proceeding. If this occurs,
// it likely indicates an earlier initialization failure or misuse.
if (m_provider == nullptr) {
NSLOG_ERROR("Configure called while provider is not initialized (m_provider is nullptr)");
return Core::ERROR_GENERAL;
}

Copilot uses AI. Check for mistakes.
if (result.HasLabel("success")) {
bool success = result["success"].Boolean();

// Extract ping statistics from JSON
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment mismatch: The comment says "Extract ping statistics from JSON" but the field being accessed is "success" which is a Boolean, not statistics. Consider updating the comment to accurately reflect the code flow.

Suggested change
// Extract ping statistics from JSON
// Retrieve ping result status and statistics from JSON response

Copilot uses AI. Check for mistakes.
std::cout << "Primary DNS: " << (primaryDns.empty() ? "(empty)" : primaryDns) << "\n";
}

std::cout << "\n[Test 6/7] getIpv6Address()\n";
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test count mismatch: The text says "Test 6/7" but there are only 6 tests shown (getInterface, getIpv4Address, getIpv6Address, getConnectionType, getDnsEntries, populateNetworkData, pingToGatewayCheck). Either the label should be "Test 6/7" or the comment should reflect the actual number of tests.

Suggested change
std::cout << "\n[Test 6/7] getIpv6Address()\n";
std::cout << "\n[Test 6/6] getIpv6Address()\n";

Copilot uses AI. Check for mistakes.
{
try {
// Set Thunder access point
WPEFramework::Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), _T("127.0.0.1:9998"));
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security concern: The THUNDER_ACCESS environment variable is hardcoded to "127.0.0.1:9998". If this plugin runs in an environment where Thunder is bound to a different address or port, or if the environment variable is already set, this could cause connection failures or unexpected behavior. Consider making this configurable through the plugin configuration or checking if the environment variable is already set before overwriting it.

Copilot uses AI. Check for mistakes.
Comment on lines +45 to +98
std::string getIpv4Address(std::string interface_name) override;

/* @brief Retrieve IPv6 address for specified interface
* @param interface_name Interface name (e.g., eth0, wlan0)
* @return IPv6 address string
*/
std::string getIpv6Address(std::string interface_name) override;

/* @brief Get IPv4 gateway/route address from last getIpv4Address call */
std::string getIpv4Gateway() override;

/* @brief Get IPv6 gateway/route address from last getIpv6Address call */
std::string getIpv6Gateway() override;

/* @brief Get IPv4 primary DNS from last getIpv4Address call */
std::string getIpv4PrimaryDns() override;

/* @brief Get IPv6 primary DNS from last getIpv6Address call */
std::string getIpv6PrimaryDns() override;

/* @brief Get current network connection type */
std::string getConnectionType() override;

/* @brief Get DNS server entries */
std::string getDnsEntries() override;

/* @brief Populate network interface data */
void populateNetworkData() override;

/* @brief Get current active interface name */
std::string getInterface() override;

/* @brief Ping to gateway to check packet loss
* @param endpoint Gateway IP address to ping
* @param ipversion Either "IPv4" or "IPv6"
* @param count Number of ping packets to send
* @param timeout Timeout in seconds
* @return true if ping successful, false otherwise
*/
bool pingToGatewayCheck(std::string endpoint, std::string ipversion, int count, int timeout) override;

/* @brief Get packet loss from last ping call */
std::string getPacketLoss() override;

/* @brief Get average RTT from last ping call */
std::string getAvgRtt() override;

/* @brief Subscribe to NetworkManager events
* @param eventName Name of the event (e.g., "onInterfaceStateChange")
* @param callback Callback function to be called when event fires
* @return Error code (Core::ERROR_NONE on success)
*/
uint32_t SubscribeToEvent(const std::string& eventName,
std::function<void(const WPEFramework::Core::JSON::VariantContainer&)> callback) override;
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String parameters should be passed by const reference to avoid unnecessary copies. Change all std::string parameters to const std::string& throughout the interface methods.

Copilot uses AI. Check for mistakes.
Comment on lines +208 to +211
// Clean up the partially initialized provider to prevent leaks and later accidental use
delete m_provider;
m_provider = nullptr;
result = Core::ERROR_GENERAL;
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential memory leak: When initialization fails (lines 176-177 and 209-211), m_provider is deleted but not set to nullptr. If Configure is called again or if other methods check m_provider before deletion in the destructor, this could cause use-after-free or double-free issues. After deleting m_provider, set it to nullptr.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 23, 2026 17:33
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 28 changed files in this pull request and generated 12 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +186 to +197
/* @brief Get DNS server entries */
std::string NetworkJsonRPCProvider::getDnsEntries()
{
// TODO: Implement DNS entries retrieval
return "";
}

/* @brief Populate network interface data */
void NetworkJsonRPCProvider::populateNetworkData()
{
// TODO: Implement network data population
}
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getDnsEntries() is currently a TODO that always returns an empty string, while the COM-RPC provider returns the cached IPv4/IPv6 DNS values. This makes provider behavior inconsistent depending on configuration. Please implement this method (and populateNetworkData()) similarly to NetworkComRPCProvider or remove them from the interface if they’re not needed.

Copilot uses AI. Check for mistakes.
Comment on lines +168 to +213
// Get provider type from configuration (default: comrpc)
std::string providerType = "comrpc";
if (config.HasLabel("providerType")) {
providerType = config["providerType"].Value();
}

// Create network provider using factory
m_provider = NetworkDataProviderFactory::CreateProvider(providerType);
if (m_provider == nullptr) {
NSLOG_ERROR("Failed to create network provider for type: %s", providerType.c_str());
result = Core::ERROR_GENERAL;
} else {
auto factoryType = NetworkDataProviderFactory::ParseProviderType(providerType);
std::string typeName = NetworkDataProviderFactory::GetProviderTypeName(factoryType);
NSLOG_INFO("%s provider created", typeName.c_str());

// Initialize the provider
if (m_provider->Initialize()) {
NSLOG_INFO("%s provider initialized successfully", typeName.c_str());

// Subscribe to NetworkManager events (with automatic retry)
_stopSubscriptionRetry = false;
subscribeToEvents();
_subscriptionRetryThread = std::thread(&NetworkConnectionStatsImplementation::subscriptionRetryThread, this);

// Generate initial report
generateReport();

// Start timer and consumer threads if enabled
if (_periodicReportingEnabled) {
_stopReporting = false;
_timerThread = std::thread(&NetworkConnectionStatsImplementation::timerThread, this);
_reportingThread = std::thread(&NetworkConnectionStatsImplementation::periodicReportingThread, this);
NSLOG_INFO("Timer and reporting threads started with %u second interval (%u minutes)",
_reportingIntervalSeconds.load(), _reportingIntervalSeconds.load() / 60);
}
} else {
auto factoryType = NetworkDataProviderFactory::ParseProviderType(providerType);
std::string typeName = NetworkDataProviderFactory::GetProviderTypeName(factoryType);
NSLOG_ERROR("Failed to initialize %s provider", typeName.c_str());
// Clean up the partially initialized provider to prevent leaks and later accidental use
delete m_provider;
m_provider = nullptr;
result = Core::ERROR_GENERAL;
}
}
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Configure() overwrites m_provider without cleaning up any existing instance. If Thunder calls Configure() more than once (e.g., reconfiguration), the previous provider will leak and any existing subscriptions/threads may reference stale state. Please delete/reset the existing provider (and stop any running threads) before creating a new one, or guard against multiple Configure calls.

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +120
- Proper interface IDs and stubgen annotations

#### Plugin Main Class
- **NetworkConnectionStats.h** - Plugin header with:
- Inherits from `PluginHost::IPlugin` and `PluginHost::JSONRPC`
- Notification handler for RPC connection lifecycle and events
- Interface aggregation for COM-RPC

- **NetworkConnectionStats.cpp** - Plugin implementation with:
- IPlugin lifecycle methods (Initialize, Deinitialize, Information)
- RPC connection management
- JSON-RPC registration
- Notification forwarding

#### Out-of-Process Implementation
- **NetworkConnectionStatsImplementation.h/.cpp** - Business logic implementation:
- All original diagnostic functionality preserved
- Implements INetworkConnectionStats and IConfiguration interfaces
- Notification management for event subscribers
- Periodic reporting thread with configurable interval
- Telemetry integration (T2)
- Network provider integration (NetworkJsonRPCProvider)

#### API Specification
- **NetworkConnectionStats.json** - JSON-RPC API definition:
- Method definitions with parameters and return types
- Event definitions (onReportGenerated)
- Schema-compliant for Thunder code generation

#### Configuration Files
- **NetworkConnectionStats.config** - Plugin configuration (JSON format)
- **NetworkConnectionStats.conf.in** - CMake template for configuration generation

#### Build System
- **CMakeLists.txt** - Thunder-compliant build system:
- Interface library for COM-RPC definitions
- Plugin library (in-process)
- Implementation library (out-of-process)
- Proper dependency management
- Installation rules for plugins, headers, and API specs

## API Methods Available

### Diagnostic Methods
1. **generateReport()** - Generate full network diagnostics report
2. **getConnectionType()** - Get Ethernet/WiFi connection type
3. **getIpv4Address(interface)** - Get IPv4 address
4. **getIpv6Address(interface)** - Get IPv6 address
5. **getIpv4Gateway()** - Get IPv4 gateway
6. **getIpv6Gateway()** - Get IPv6 gateway
7. **getIpv4Dns()** - Get IPv4 DNS server
8. **getIpv6Dns()** - Get IPv6 DNS server
9. **getInterface()** - Get active network interface
10. **pingGateway(endpoint, ipversion, count, timeout)** - Ping gateway with stats

### Configuration Methods
11. **setPeriodicReporting(enable)** - Enable/disable periodic reports
12. **setReportingInterval(intervalMinutes)** - Set reporting interval

### Events
- **onReportGenerated** - Fired when report is generated

## Key Features Preserved

### Network Diagnostics
- Connection type detection (Ethernet/WiFi)
- IPv4/IPv6 address retrieval
- Gateway/route validation
- DNS configuration checks
- Packet loss monitoring
- RTT measurements

### Telemetry Integration
- T2 telemetry events for network metrics
- Conditional compilation with USE_TELEMETRY flag
- Event logging for connection type, IP info, gateway stats

### Periodic Reporting
- Configurable reporting interval (default 10 minutes)
- Background thread for periodic diagnostics
- Thread-safe start/stop control

## Migration from Standalone to Plugin

### What Was Removed
- `main()` function - No longer needed in plugin architecture
- Singleton pattern - Thunder manages plugin lifecycle
- Standalone initialization - Replaced with IPlugin::Initialize()

### What Was Added
- Thunder plugin lifecycle (IPlugin interface)
- RPC connection management
- Notification system for events
- COM-RPC and JSON-RPC interfaces
- Configuration interface (IConfiguration)
- Proper Thunder logging (TRACE macros)

### What Was Transformed
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This document states the plugin supports/exposes JSON-RPC APIs and that NetworkConnectionStats.json is part of the shipped API surface, but the current code registers only PluginHost::IPlugin and aggregates a minimal COM-RPC interface (no PluginHost::JSONRPC). Please update this doc to match the internal-only implementation or add the missing JSON-RPC layer if that’s still the goal.

Copilot uses AI. Check for mistakes.
Comment on lines +360 to +398
#ifdef TEST_MAIN
/* Test main function to validate NetworkJsonRPCProvider member functions */
int main()
{
NetworkJsonRPCProvider provider;
int choice;
std::string interface_name;
bool running = true;

std::cout << "\n========================================\n";
std::cout << "NetworkJsonRPCProvider Test Suite\n";
std::cout << "========================================\n";

while (running)
{
std::cout << "\nMenu:\n";
std::cout << "1. Test getIpv4Address()\n";
std::cout << "2. Test getIpv6Address()\n";
std::cout << "3. Test getConnectionType()\n";
std::cout << "4. Test getDnsEntries()\n";
std::cout << "5. Test populateNetworkData()\n";
std::cout << "6. Test getInterface()\n";
std::cout << "7. Test pingToGatewayCheck()\n";
std::cout << "8. Run all tests\n";
std::cout << "0. Exit\n";
std::cout << "\nEnter your choice: ";
std::cin >> choice;

switch (choice)
{
case 1:
std::cout << "\nTesting getIpv4Address()...\n";
{
//interface_name = provider.getInterface();
interface_name = "eno1"; // Hardcoded for testing
std::cout << "Using interface: " << (interface_name.empty() ? "(empty)" : interface_name) << "\n";
std::string ipv4 = provider.getIpv4Address(interface_name);
std::cout << "Result: " << (ipv4.empty() ? "(empty)" : ipv4) << "\n";
std::string gateway = provider.getIpv4Gateway();
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TEST_MAIN test harness constructs NetworkJsonRPCProvider but never calls Initialize(), so all JSON-RPC calls will fail with "client not initialized" and the tests won’t validate behavior. Please call provider.Initialize() before running the menu/tests (and fail fast if initialization fails).

Copilot uses AI. Check for mistakes.
Comment on lines +101 to +130
uint32_t NetworkConnectionStatsImplementation::Register(INetworkConnectionStats::INotification* notification)
{
if (nullptr == notification) {
NSLOG_ERROR("Register: notification parameter is nullptr");
return Core::ERROR_BAD_REQUEST;
}

NSLOG_INFO("Register::Enter");
_notificationLock.Lock();

// Make sure we can't register the same notification callback multiple times
if (std::find(_notificationCallbacks.begin(), _notificationCallbacks.end(), notification) == _notificationCallbacks.end()) {
_notificationCallbacks.push_back(notification);
notification->AddRef();
}

_notificationLock.Unlock();

return Core::ERROR_NONE;
}

/**
* Unregister a notification callback
*/
uint32_t NetworkConnectionStatsImplementation::Unregister(INetworkConnectionStats::INotification* notification)
{
if (nullptr == notification) {
NSLOG_ERROR("Unregister: notification parameter is nullptr");
return Core::ERROR_BAD_REQUEST;
}
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method definitions for Register/Unregister use INetworkConnectionStats::INotification* without qualifying Exchange::. This should match the interface type (Exchange::INetworkConnectionStats::INotification*) to avoid name lookup/compile errors and to correctly override the base interface methods.

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +87
### 1. NetworkConnectionStats (Plugin)
**File**: NetworkConnectionStats.h/cpp
**Inherits**: PluginHost::IPlugin, PluginHost::JSONRPC
**Purpose**: Main plugin class running in Thunder process

**Key Methods**:
- `Initialize(PluginHost::IShell*)` - Plugin activation
- `Deinitialize(PluginHost::IShell*)` - Plugin cleanup
- `Information()` - Plugin description
- `Deactivated(RPC::IRemoteConnection*)` - Handle out-of-process crash

**Inner Class**: `Notification`
- Implements `RPC::IRemoteConnection::INotification`
- Implements `INetworkConnectionStats::INotification`
- Forwards events to JSON-RPC clients

### 2. INetworkConnectionStats (Interface)
**File**: INetworkConnectionStats.h
**Purpose**: COM-RPC interface definition

**Sub-Interface**: `INotification`
- `OnReportGenerated(const string&)` - Event notification

**Main Interface Methods**:
- `Register/Unregister` - Notification subscription
- `GenerateReport()` - Trigger diagnostics
- `GetConnectionType()` - Network type
- `GetIpv4Address/GetIpv6Address` - IP addresses
- `GetIpv4Gateway/GetIpv6Gateway` - Gateways
- `GetIpv4Dns/GetIpv6Dns` - DNS servers
- `GetInterface()` - Active interface
- `PingGateway()` - Gateway connectivity test
- `SetPeriodicReporting()` - Enable/disable periodic reports
- `SetReportingInterval()` - Configure interval

Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This quick reference claims the plugin inherits PluginHost::JSONRPC and exposes many JSON-RPC methods/events, but the current implementation (NetworkConnectionStats.h/.cpp and INetworkConnectionStats.h) is internal-only and doesn’t provide that API surface. Please update this document to match the actual architecture, or update the code to match the documented APIs.

Copilot uses AI. Check for mistakes.
Comment on lines +221 to +233

while (!_stopReporting && _periodicReportingEnabled) {
// Sleep for configured interval
std::this_thread::sleep_for(std::chrono::seconds(_reportingIntervalSeconds.load()));

if (_stopReporting || !_periodicReportingEnabled) {
break;
}

// Queue report generation
queueReportGeneration("Timer");
}

Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

timerThread() uses a single sleep_for(reportingInterval) which means shutdown/deinitialize can block for up to the full interval (default 600s) before the thread exits and join() returns. Consider using a condition_variable timed wait (or smaller sleep slices) that can be interrupted when _stopReporting becomes true.

Suggested change
while (!_stopReporting && _periodicReportingEnabled) {
// Sleep for configured interval
std::this_thread::sleep_for(std::chrono::seconds(_reportingIntervalSeconds.load()));
if (_stopReporting || !_periodicReportingEnabled) {
break;
}
// Queue report generation
queueReportGeneration("Timer");
}
while (!_stopReporting && _periodicReportingEnabled) {
// Sleep for the configured interval in small slices so we can react quickly to stop requests
const auto intervalSeconds = _reportingIntervalSeconds.load();
auto startTime = std::chrono::steady_clock::now();
while (!_stopReporting && _periodicReportingEnabled) {
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::steady_clock::now() - startTime).count();
if (elapsed >= intervalSeconds) {
break;
}
auto remaining = intervalSeconds - elapsed;
auto sleepSeconds = std::min<std::int64_t>(remaining, 1);
std::this_thread::sleep_for(std::chrono::seconds(sleepSeconds));
}
if (_stopReporting || !_periodicReportingEnabled) {
break;
}
// Queue report generation
queueReportGeneration("Timer");
}

Copilot uses AI. Check for mistakes.
Comment on lines +104 to +112
### Configuration Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `reportingInterval` | number | 10 | Diagnostic interval in minutes |
| `autoStart` | boolean | true | Auto-start periodic reporting on plugin activation |
| `outofprocess` | boolean | true | Run implementation out-of-process (recommended) |

## Files Structure
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs describe reportingInterval as minutes, but the implementation treats it as seconds (_reportingIntervalSeconds and sleep_for(seconds(...))) and the default config uses 600. Please clarify the unit in this README (and/or rename the config key) so operators don’t misconfigure the interval by 60x.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 6, 2026 18:09
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 28 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +179 to +180
m_provider = NetworkDataProviderFactory::CreateProvider(providerType);
if (m_provider == nullptr) {
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Configure() assigns a new instance to m_provider without cleaning up any previously created provider or stopping any previously started threads/subscriptions. If Configure() can be called more than once (e.g., reconfiguration), this can leak the old provider and start duplicate worker threads. Consider guarding against re-entry or performing a full shutdown before replacing m_provider.

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +53

// Create JSON-RPC client connection to NetworkManager
m_networkManagerClient = std::make_shared<WPEFramework::JSONRPC::SmartLinkType<WPEFramework::Core::JSON::IElement>>(
_T(NETWORK_MANAGER_CALLSIGN),
_T(""), // No specific version
_T("") // No token needed for inter-plugin communication
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SmartLinkType is constructed with empty namespace/query/token fields here. Elsewhere in this repo, JSON-RPC calls to org.rdk.NetworkManager mint a SecurityAgent token and pass it via the query string; if security is enabled, the current construction may fail. Consider following the established token/query pattern or making these parameters configurable.

Suggested change
// Create JSON-RPC client connection to NetworkManager
m_networkManagerClient = std::make_shared<WPEFramework::JSONRPC::SmartLinkType<WPEFramework::Core::JSON::IElement>>(
_T(NETWORK_MANAGER_CALLSIGN),
_T(""), // No specific version
_T("") // No token needed for inter-plugin communication
// Optional: read query and token for NetworkManager from environment so that
// secured deployments can provide a SecurityAgent token or custom query string.
WPEFramework::Core::string networkManagerQuery;
WPEFramework::Core::string networkManagerToken;
WPEFramework::Core::SystemInfo::GetEnvironment(_T("NETWORK_MANAGER_QUERY"), networkManagerQuery);
WPEFramework::Core::SystemInfo::GetEnvironment(_T("NETWORK_MANAGER_TOKEN"), networkManagerToken);
// Create JSON-RPC client connection to NetworkManager
m_networkManagerClient = std::make_shared<WPEFramework::JSONRPC::SmartLinkType<WPEFramework::Core::JSON::IElement>>(
_T(NETWORK_MANAGER_CALLSIGN),
networkManagerQuery,
networkManagerToken

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +23
#### COM-RPC Interface
- **INetworkConnectionStats.h** - Defines the COM-RPC interface with:
- INetworkConnectionStats interface with all network diagnostic methods
- INotification sub-interface for event notifications
- Proper interface IDs and stubgen annotations
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This document states the plugin provides COM-RPC + JSON-RPC APIs and lists many API methods/events, but the actual code/interface added in this PR implements an internal-only plugin with a minimal COM-RPC interface (and no JSON-RPC dispatcher). Please update this doc to reflect the current architecture so it doesn’t mislead future maintainers.

Copilot uses AI. Check for mistakes.
Comment on lines +582 to +585
// Retry subscription
NSLOG_INFO("Retrying event subscriptions...");
subscribeToEvents();
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The retry loop logs "Retrying event subscriptions..." very frequently (every 500ms) until all subscriptions succeed. If NetworkManager is down for an extended period this will spam logs and increase CPU wakeups. Consider increasing the interval, using exponential backoff, and/or rate-limiting the log message (e.g., log every N retries).

Copilot uses AI. Check for mistakes.
Co-authored-by: gururaajar <r.gururaaja@gmail.com>
Copilot AI review requested due to automatic review settings March 16, 2026 16:46
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 28 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +23 to +109
#include "INetworkData.h"
#include "Module.h"
#include <string>
#include <core/JSON.h>

class NetworkJsonRPCProvider : public INetworkData
{
public:
NetworkJsonRPCProvider();
~NetworkJsonRPCProvider();

/* @brief Initialize the provider with Thunder connection */
bool Initialize();
/* @brief Retrieve IPv4 address for specified interface
* @param interface_name Interface name (e.g., eth0, wlan0)
* @return IPv4 address string
*/
std::string getIpv4Address(std::string interface_name) override;

/* @brief Retrieve IPv6 address for specified interface
* @param interface_name Interface name (e.g., eth0, wlan0)
* @return IPv6 address string
*/
std::string getIpv6Address(std::string interface_name) override;

/* @brief Get IPv4 gateway/route address from last getIpv4Address call */
std::string getIpv4Gateway() override;

/* @brief Get IPv6 gateway/route address from last getIpv6Address call */
std::string getIpv6Gateway() override;

/* @brief Get IPv4 primary DNS from last getIpv4Address call */
std::string getIpv4PrimaryDns() override;

/* @brief Get IPv6 primary DNS from last getIpv6Address call */
std::string getIpv6PrimaryDns() override;

/* @brief Get current network connection type */
std::string getConnectionType() override;

/* @brief Get DNS server entries */
std::string getDnsEntries() override;

/* @brief Populate network interface data */
void populateNetworkData() override;

/* @brief Get current active interface name */
std::string getInterface() override;

/* @brief Ping to gateway to check packet loss
* @param endpoint Gateway IP address to ping
* @param ipversion Either "IPv4" or "IPv6"
* @param count Number of ping packets to send
* @param timeout Timeout in seconds
* @return true if ping successful, false otherwise
*/
bool pingToGatewayCheck(std::string endpoint, std::string ipversion, int count, int timeout) override;

/* @brief Get packet loss from last ping call */
std::string getPacketLoss() override;

/* @brief Get average RTT from last ping call */
std::string getAvgRtt() override;

/* @brief Subscribe to NetworkManager events
* @param eventName Name of the event (e.g., "onInterfaceStateChange")
* @param callback Callback function to be called when event fires
* @return Error code (Core::ERROR_NONE on success)
*/
uint32_t SubscribeToEvent(const std::string& eventName,
std::function<void(const WPEFramework::Core::JSON::VariantContainer&)> callback) override;

/* @brief Invoke WiFiConnect API on NetworkManager with empty params to reconnect to last SSID */
uint32_t invokeWiFiConnect() override;

private:
// Cached data from last API calls
std::string m_ipv4Gateway;
std::string m_ipv6Gateway;
std::string m_ipv4PrimaryDns;
std::string m_ipv6PrimaryDns;
std::string m_packetLoss;
std::string m_avgRtt;

// Thunder JSON-RPC client for NetworkManager communication
std::shared_ptr<WPEFramework::JSONRPC::SmartLinkType<WPEFramework::Core::JSON::IElement>> m_networkManagerClient;
};
Comment on lines +383 to +395
#ifdef TEST_MAIN
/* Test main function to validate NetworkJsonRPCProvider member functions */
int main()
{
NetworkJsonRPCProvider provider;
int choice;
std::string interface_name;
bool running = true;

std::cout << "\n========================================\n";
std::cout << "NetworkJsonRPCProvider Test Suite\n";
std::cout << "========================================\n";

Comment on lines +560 to +582
void NetworkConnectionStatsImplementation::subscriptionRetryThread()
{
NSLOG_INFO("Subscription retry thread started");

while (!_stopSubscriptionRetry)
{
// Check if all subscriptions are successful
if (m_subsIfaceStateChange && m_subsActIfaceChange && m_subsIPAddrChange)
{
NSLOG_INFO("All required events subscribed; Stopping retry thread");
break;
}

// Wait before retry
std::this_thread::sleep_for(std::chrono::milliseconds(SUBSCRIPTION_RETRY_INTERVAL_MS));

if (_stopSubscriptionRetry)
break;

// Retry subscription
NSLOG_INFO("Retrying event subscriptions...");
subscribeToEvents();
}
Comment on lines +23 to +114
#include "INetworkData.h"
#include "Module.h"
#include <string>
#include <core/JSON.h>

#define NETWORK_MANAGER_CALLSIGN "org.rdk.NetworkManager"

class NetworkComRPCProvider : public INetworkData
{
public:
NetworkComRPCProvider();
virtual ~NetworkComRPCProvider();

/* @brief Initialize COM-RPC connection to NetworkManager
* @return true if connection successful, false otherwise
*/
bool Initialize();

/* @brief Retrieve IPv4 address for specified interface
* @param interface_name Interface name (e.g., eth0, wlan0)
* @return IPv4 address string
*/
std::string getIpv4Address(std::string interface_name) override;

/* @brief Retrieve IPv6 address for specified interface
* @param interface_name Interface name (e.g., eth0, wlan0)
* @return IPv6 address string
*/
std::string getIpv6Address(std::string interface_name) override;

/* @brief Get IPv4 gateway/route address from last getIpv4Address call */
std::string getIpv4Gateway() override;

/* @brief Get IPv6 gateway/route address from last getIpv6Address call */
std::string getIpv6Gateway() override;

/* @brief Get IPv4 primary DNS from last getIpv4Address call */
std::string getIpv4PrimaryDns() override;

/* @brief Get IPv6 primary DNS from last getIpv6Address call */
std::string getIpv6PrimaryDns() override;

/* @brief Get current network connection type */
std::string getConnectionType() override;

/* @brief Get DNS server entries */
std::string getDnsEntries() override;

/* @brief Populate network interface data */
void populateNetworkData() override;

/* @brief Get current active interface name */
std::string getInterface() override;

/* @brief Ping to gateway to check packet loss
* @param endpoint Gateway IP address to ping
* @param ipversion Either "IPv4" or "IPv6"
* @param count Number of ping packets to send
* @param timeout Timeout in seconds
* @return true if ping successful, false otherwise
*/
bool pingToGatewayCheck(std::string endpoint, std::string ipversion, int count, int timeout) override;

/* @brief Get packet loss from last ping call */
std::string getPacketLoss() override;

/* @brief Get average RTT from last ping call */
std::string getAvgRtt() override;

/* @brief Subscribe to NetworkManager events
* @param eventName Name of the event (e.g., "onInterfaceStateChange")
* @param callback Callback function to be called when event fires
* @return Error code (Core::ERROR_NONE on success)
*/
uint32_t SubscribeToEvent(const std::string& eventName,
std::function<void(const WPEFramework::Core::JSON::VariantContainer&)> callback) override;

/* @brief Invoke WiFiConnect API on NetworkManager with empty params to reconnect to last SSID */
uint32_t invokeWiFiConnect() override;

private:
// Cached data from last API calls
std::string m_ipv4Gateway;
std::string m_ipv6Gateway;
std::string m_ipv4PrimaryDns;
std::string m_ipv6PrimaryDns;
std::string m_packetLoss;
std::string m_avgRtt;

// Thunder JSON-RPC client for inter-plugin communication
std::shared_ptr<WPEFramework::JSONRPC::LinkType<WPEFramework::Core::JSON::IElement>> m_networkManagerClient;
};
Comment on lines +112 to +121
NSLOG_INFO("Register::Enter");
_notificationLock.Lock();

// Make sure we can't register the same notification callback multiple times
if (std::find(_notificationCallbacks.begin(), _notificationCallbacks.end(), notification) == _notificationCallbacks.end()) {
_notificationCallbacks.push_back(notification);
notification->AddRef();
}

_notificationLock.Unlock();
Comment on lines +64 to +91
## API Methods Available

### Diagnostic Methods
1. **generateReport()** - Generate full network diagnostics report
2. **getConnectionType()** - Get Ethernet/WiFi connection type
3. **getIpv4Address(interface)** - Get IPv4 address
4. **getIpv6Address(interface)** - Get IPv6 address
5. **getIpv4Gateway()** - Get IPv4 gateway
6. **getIpv6Gateway()** - Get IPv6 gateway
7. **getIpv4Dns()** - Get IPv4 DNS server
8. **getIpv6Dns()** - Get IPv6 DNS server
9. **getInterface()** - Get active network interface
10. **pingGateway(endpoint, ipversion, count, timeout)** - Ping gateway with stats

### Configuration Methods
11. **setPeriodicReporting(enable)** - Enable/disable periodic reports
12. **setReportingInterval(intervalMinutes)** - Set reporting interval

### Events
- **onReportGenerated** - Fired when report is generated

## Key Features Preserved

### Network Diagnostics
- Connection type detection (Ethernet/WiFi)
- IPv4/IPv6 address retrieval
- Gateway/route validation
- DNS configuration checks
Comment on lines +58 to +66

NSLOG_INFO("NetworkConnectionStatsImplementation Constructor");
/* Set NetworkManager Out-Process name to be "NetworkConnectionStats" */
Core::ProcessInfo().Name("NetworkConnectionStats");
NSLOG_INFO((_T("NetworkConnectionStats Out-Of-Process Instantiation; SHA: " _T(EXPAND_AND_QUOTE(PLUGIN_BUILD_REFERENCE)))));
#if USE_TELEMETRY
t2_init("networkstats");
#endif
}
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 16, 2026 19:29
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 28 changed files in this pull request and generated 10 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

# Optional Telemetry support
if (USE_TELEMETRY)
find_package(T2 REQUIRED)
add_definitions(-DUSE_TELEMETRY)
Comment on lines +628 to +630

// Queue report generation
std::lock_guard<std::mutex> lock(_queueMutex);
Comment on lines +68 to +99
NetworkConnectionStatsImplementation::~NetworkConnectionStatsImplementation()
{
NSLOG_INFO("NetworkConnectionStatsImplementation Destructor");

// Stop subscription retry thread
_stopSubscriptionRetry = true;
if (_subscriptionRetryThread.joinable()) {
_subscriptionRetryThread.join();
}

// Stop reporting threads
_stopReporting = true;

// Push STOP message to unblock consumer thread
{
std::lock_guard<std::mutex> lock(_queueMutex);
_messageQueue.push({MessageType::STOP});
}
_queueCondition.notify_one();

// Wait for threads to finish
if (_timerThread.joinable()) {
_timerThread.join();
}
if (_reportingThread.joinable()) {
_reportingThread.join();
}

if (m_provider) {
delete m_provider;
m_provider = nullptr;
}
Comment on lines +45 to +54
try {
// Set Thunder access point
WPEFramework::Core::SystemInfo::SetEnvironment(_T("THUNDER_ACCESS"), _T("127.0.0.1:9998"));

// Create JSON-RPC client connection to NetworkManager
m_networkManagerClient = std::make_shared<WPEFramework::JSONRPC::SmartLinkType<WPEFramework::Core::JSON::IElement>>(
_T(NETWORK_MANAGER_CALLSIGN),
_T(""), // No specific version
_T("") // No token needed for inter-plugin communication
);
Comment on lines +383 to +391
#ifdef TEST_MAIN
/* Test main function to validate NetworkJsonRPCProvider member functions */
int main()
{
NetworkJsonRPCProvider provider;
int choice;
std::string interface_name;
bool running = true;

set(GENERATOR_SEARCH_PATH ${CMAKE_SYSROOT}${CMAKE_INSTALL_PREFIX}/include/${NAMESPACE})
endif()

file(GLOB INTERFACE_HEADER ${CMAKE_CURRENT_SOURCE_DIR})
Comment on lines +129 to +131
bool m_subsIfaceStateChange;
bool m_subsActIfaceChange;
bool m_subsIPAddrChange;
/**
* Logging level with an increasing order of refinement
* (DEBUG_LEVEL = Finest logging)
* It is essental to start with 0 and increase w/o gaps as the value
Comment on lines +30 to +37
"methods": {
"generateReport": {
"summary": "Generate network diagnostics report",
"description": "Triggers a full network diagnostic scan including connection type, IP configuration, routes, and DNS",
"result": {
"$ref": "#/definitions/success"
}
},
Comment on lines +398 to +405
#ifdef TEST_MAIN
/* Test main function to validate NetworkComRPCProvider member functions */
int main()
{
NetworkComRPCProvider provider;
int choice;
std::string interface_name;
bool running = true;
Copy link
Contributor

@karuna2git karuna2git left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NetworkStat is something cannot in sub folder.

In EntOS, each plugin is a separate repo is the model being used now. So it should be separate repo. Ex:
https://github.com/rdkcentral/entservices-hdmicecsource
https://github.com/rdkcentral/entservices-hdmicecsink

Or, we can have functional grouping..
The new interface has to go to existing interface folder
The new definition has to go to existing definition folder
ex:
https://github.com/rdkcentral/entservices-appgateway

Above is based on the expectation. I did not review the technicality yet.

Thanks,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants