Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jincysam87 upnp #87

Open
wants to merge 17 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ pkg_check_modules(GLIB REQUIRED glib-2.0)
pkg_check_modules(LIBNM REQUIRED libnm)
pkg_check_modules(GLIB REQUIRED gio-2.0)
else()
pkg_check_modules(LIBSOUP REQUIRED libsoup-2.4)
pkg_check_modules(GLIB REQUIRED glib-2.0)
pkg_check_modules(GUPNP REQUIRED gupnp-1.0)
pkg_check_modules(GSSDP REQUIRED gssdp-1.2)
find_package(IARMBus REQUIRED)
endif ()

Expand Down Expand Up @@ -107,7 +111,10 @@ add_library(${MODULE_NAME} SHARED
NetworkManagerStunClient.cpp
WiFiSignalStrengthMonitor.cpp
Module.cpp
UpnpDiscoveryManager.cpp
${PROXY_STUB_SOURCES})
target_include_directories(${MODULE_NAME} PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS} ${GUPNP_INCLUDE_DIRS} ${GSSDP_INCLUDE_DIRS})
target_link_libraries(${MODULE_NAME} PRIVATE ${GLIB_LIBRARIES} ${LIBSOUP_LIBRARIES} ${GUPNP_LIBRARIES} ${GSSDP_LIBRARIES})

target_link_libraries(${MODULE_NAME} PRIVATE
${NAMESPACE}Core::${NAMESPACE}Core
Expand Down
7 changes: 7 additions & 0 deletions NetworkManagerImplementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,11 @@ namespace WPEFramework
m_defaultInterface = interface;

connectivityMonitor.switchToInitialCheck();
if (ipversion == "IPv4")
{
NMLOG_ERROR("MYTEST: Calling findGatewayDevice for %s", interface.c_str());
m_upnpDiscoveryManager.startUpnpDiscovery(interface);
}
}

_notificationLock.Lock();
Expand Down Expand Up @@ -675,6 +680,8 @@ namespace WPEFramework
{
m_wlanConnected = true;
m_wifiSignalMonitor.startWiFiSignalStrengthMonitor(DEFAULT_WIFI_SIGNAL_TEST_INTERVAL_SEC);
NMLOG_ERROR("MYTEST: Calling findGatewayDevice for wlan0");
m_upnpDiscoveryManager.findGatewayDevice("wlan0");
}
else
m_wlanConnected = false; /* Any other state is considered as WiFi not connected. */
Expand Down
2 changes: 2 additions & 0 deletions NetworkManagerImplementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ using namespace std;
#include "WiFiSignalStrengthMonitor.h"
#include "NetworkManagerConnectivity.h"
#include "NetworkManagerStunClient.h"
#include "UpnpDiscoveryManager.h"

namespace WPEFramework
{
Expand Down Expand Up @@ -276,6 +277,7 @@ namespace WPEFramework
std::atomic<bool> m_ethConnected;
std::atomic<bool> m_wlanConnected;
WiFiSignalStrengthMonitor m_wifiSignalMonitor;
UpnpDiscoveryManager m_upnpDiscoveryManager;
mutable ConnectivityMonitor connectivityMonitor;
};
}
Expand Down
4 changes: 2 additions & 2 deletions NetworkManagerRDKProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,9 +545,9 @@ namespace WPEFramework
oldInterface = e->oldInterface;
newInterface = e->newInterface;
NMLOG_INFO ("IARM_BUS_NETWORK_MANAGER_EVENT_DEFAULT_INTERFACE %s :: %s..", oldInterface.c_str(), newInterface.c_str());
if(oldInterface != "eth0" || oldInterface != "wlan0")
if(oldInterface != "eth0" && oldInterface != "wlan0")
oldInterface = ""; /* assigning "null" if the interface is not eth0 or wlan0 */
if(newInterface != "eth0" || newInterface != "wlan0")
if(newInterface != "eth0" && newInterface != "wlan0")
newInterface = ""; /* assigning "null" if the interface is not eth0 or wlan0 */

::_instance->ReportActiveInterfaceChange(oldInterface, newInterface);
Expand Down
164 changes: 164 additions & 0 deletions UpnpDiscoveryManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/**
* If not stated otherwise in this file or this component's LICENSE
* file the following copyright and licenses apply:
*
* Copyright 2023 RDK Management
*
* 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 <fstream>
#include <sstream>
#include <thread>
#include "UpnpDiscoveryManager.h"

std::string const UpnpDiscoveryManager::m_deviceInternetGateway = "urn:schemas-upnp-org:device:InternetGatewayDevice:1";

UpnpDiscoveryManager::UpnpDiscoveryManager()
{
m_mainLoop = g_main_loop_new(NULL, FALSE);

//Create timeout threads to handle telemetry logging
g_timeout_add_seconds (LOGGING_PERIOD_IN_SEC, GSourceFunc(&UpnpDiscoveryManager::logTelemetry), this);

m_threadUpnp = g_thread_new("thread_upnp", UpnpDiscoveryManager::runUpnp, this);
m_threadGmain = g_thread_new("thread_gmain", UpnpDiscoveryManager::runMainLoop, this);
}

UpnpDiscoveryManager::~UpnpDiscoveryManager()
{
if (m_controlPoint)
g_object_unref(m_controlPoint);
if (m_context)
g_object_unref(m_context);
if (m_mainLoop)
{
g_main_loop_quit(m_mainLoop);
g_main_loop_unref(m_mainLoop);
}
}

void UpnpDiscoveryManager::startUpnpDiscovery(const std::string& interface)
{
std::lock_guard<std::mutex> lock(m_upnpCvMutex);
m_interface = interface;
m_upnpReady = true;
m_upnpCv.notify_one();
}

void* UpnpDiscoveryManager::runUpnp(void *arg)
{
UpnpDiscoveryManager* manager = static_cast<UpnpDiscoveryManager*>(arg);
int timeoutInMin = 30;
while(true)
{
std::unique_lock<std::mutex> lock(manager->m_upnpCvMutex);
if (manager->m_upnpCv.wait_for(lock, std::chrono::minutes(timeoutInMin)) == std::cv_status::timeout) {
LOG_INFO("upnp run thread timeout");
}
if (manager->m_upnpReady)
{
manager->findGatewayDevice(manager->m_interface);
manager->m_upnpReady = false;
}
}
}

void UpnpDiscoveryManager::initialiseUpnp(const std::string& interface)
{
GError *error = NULL;
// Create a gupnp context
m_context = gupnp_context_new(NULL, interface.c_str(), 0, &error);
if (!m_context) {
LOG_ERR("Error creating Upnp context: %s", error->message);
g_clear_error(&error);
}

// Create a control point for InternetGatewayDevice
m_controlPoint = gupnp_control_point_new(m_context, m_deviceInternetGateway.c_str());
if (!m_controlPoint) {
LOG_ERR("Error creating control point");
}

// Connects a callback function to a signal for InternetGatewayDevice
g_signal_connect(m_controlPoint, "device-proxy-available",
G_CALLBACK(&UpnpDiscoveryManager::deviceProxyAvailableCallback), this);
}


void* UpnpDiscoveryManager::runMainLoop(void *arg)
{
g_main_loop_run(((UpnpDiscoveryManager *)arg)->m_mainLoop);
}

gboolean UpnpDiscoveryManager::logTelemetry(void *arg)
{
std::lock_guard<std::mutex> lock(((UpnpDiscoveryManager *)arg)->m_apMutex);
//T2 telemtery logging
LOG_INFO("TELEMETRY_UPNP_GATEWAY_DETAILS: %s", ((UpnpDiscoveryManager *)arg)->m_gatewayDetails.str().c_str());
return TRUE;
}

void UpnpDiscoveryManager::findGatewayDevice(const std::string& interface)
{
//Clear previous gupnp contexts if any
clearUpnpExistingRequests();

//Initialise gupnp context
initialiseUpnp(interface);

// Start discovery to find InternetGatewayDevice
if (TRUE != gssdp_resource_browser_get_active(GSSDP_RESOURCE_BROWSER(m_controlPoint)))
{
LOG_INFO("Searching for InternetGatewayDevice");
gssdp_resource_browser_set_active(GSSDP_RESOURCE_BROWSER(m_controlPoint), TRUE);
}
}

void UpnpDiscoveryManager::clearUpnpExistingRequests()
{
if (m_controlPoint)
{
stopSearchGatewayDevice();
g_object_unref(m_controlPoint);
}
if (m_context)
{
g_object_unref(m_context);
}
}

void UpnpDiscoveryManager::on_device_proxy_available(GUPnPControlPoint *controlPoint, GUPnPDeviceProxy *proxy)
{
m_apMake = gupnp_device_info_get_manufacturer(GUPNP_DEVICE_INFO(proxy));
m_apModelName = gupnp_device_info_get_model_name(GUPNP_DEVICE_INFO(proxy));
m_apModelNumber = gupnp_device_info_get_model_number(GUPNP_DEVICE_INFO(proxy));
m_apMake = m_apMake.substr(0, m_apMake.find(','));
LOG_INFO("Connected to Gateway: %s, %s, %s", m_apMake.c_str(), m_apModelName.c_str(), m_apModelNumber.c_str());
// Stop discovery to find InternetGatewayDevice
stopSearchGatewayDevice();
std::lock_guard<std::mutex> lock(m_apMutex);
m_gatewayDetails.str("");
m_gatewayDetails.clear();
m_gatewayDetails << "make=" << m_apMake << ",model_name=" << m_apModelName << ",model_number=" << m_apModelNumber;
}

void UpnpDiscoveryManager::stopSearchGatewayDevice()
{
LOG_INFO("Stop searching for InternetGatewayDevice");
if (TRUE == gssdp_resource_browser_get_active(GSSDP_RESOURCE_BROWSER(m_controlPoint)))
{
gssdp_resource_browser_set_active(GSSDP_RESOURCE_BROWSER(m_controlPoint), FALSE);
}
LOG_INFO("Stopped searching for InternetGatewayDevice");
}
69 changes: 69 additions & 0 deletions UpnpDiscoveryManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* If not stated otherwise in this file or this component's LICENSE
* file the following copyright and licenses apply:
*
* Copyright 2023 RDK Management
*
* 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.
**/
#ifndef __UPNP_H__
#define __UPNP_H__

#include <libgupnp/gupnp.h>
#include <mutex>
#include <string>
#include <vector>
#include <chrono>
#include <condition_variable>

#define LOG_ERR(msg, ...) g_printerr("[%s:%d] " msg "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_INFO(msg, ...) g_printerr("[%s:%d] " msg "\n", __FILE__, __LINE__, ##__VA_ARGS__)

class UpnpDiscoveryManager
{
public:
void startUpnpDiscovery(const std::string& interface);
UpnpDiscoveryManager();
~UpnpDiscoveryManager();

private:
void initialiseUpnp(const std::string& interface);
void clearUpnpExistingRequests();
static void* runMainLoop(void *arg);
static void* runUpnp(void *arg);
static gboolean logTelemetry(void* arg);
void findGatewayDevice(const std::string& interface);
void stopSearchGatewayDevice();
void on_device_proxy_available(GUPnPControlPoint *control_point, GUPnPDeviceProxy *proxy);
static void deviceProxyAvailableCallback(GUPnPControlPoint *control_point, GUPnPDeviceProxy *proxy, gpointer user_data) {
auto *self = static_cast<UpnpDiscoveryManager *>(user_data);
self->on_device_proxy_available(control_point, proxy);
}
GUPnPContext* m_context;
GUPnPControlPoint* m_controlPoint;
GMainLoop* m_mainLoop;
GThread * m_threadGmain;
GThread * m_threadUpnp;
std::string m_apMake;
std::string m_apModelName;
std::string m_apModelNumber;
std::ostringstream m_gatewayDetails;
std::mutex m_apMutex;
std::condition_variable m_upnpCv;
std::mutex m_upnpCvMutex;
std::string m_interface;
static std::string const m_deviceInternetGateway;
static const int LOGGING_PERIOD_IN_SEC = 2; //15min * 60
bool m_upnpReady;
};
#endif
Loading