From bb303c1e0f37463bbff6564b019b9be89b38753d Mon Sep 17 00:00:00 2001 From: Yukita Mayako Date: Sat, 5 Nov 2022 19:12:09 -0400 Subject: [PATCH] Allow skipping UPnP discovery by using cached IGD description URL This is much faster than running a full discover, but only works if the user's network hasn't changed. --- modules/upnp/doc_classes/UPNP.xml | 8 ++++++++ modules/upnp/upnp.cpp | 34 +++++++++++++++++++++++++++++++ modules/upnp/upnp.h | 1 + 3 files changed, 43 insertions(+) diff --git a/modules/upnp/doc_classes/UPNP.xml b/modules/upnp/doc_classes/UPNP.xml index 92e25efbe04..b0ee8194d44 100644 --- a/modules/upnp/doc_classes/UPNP.xml +++ b/modules/upnp/doc_classes/UPNP.xml @@ -66,6 +66,14 @@ Adds the given [UPNPDevice] to the list of discovered devices. + + + + + Discovers a [UPNPDevice] directly from the provided device description URL [code]desc_url[/code], allowing the much slower call to [method discover] to be skipped. + Returns one of the [enum UPNPResult] code constants ([constant UPNP_RESULT_SUCCESS] on success). + + diff --git a/modules/upnp/upnp.cpp b/modules/upnp/upnp.cpp index 82fe39e0034..2ff9abb53fe 100644 --- a/modules/upnp/upnp.cpp +++ b/modules/upnp/upnp.cpp @@ -90,6 +90,39 @@ int UPNP::discover(int timeout, int ttl, const String &device_filter) { return UPNP_RESULT_SUCCESS; } +UPNP::UPNPResult UPNP::add_device_from_url(const String &desc_url) { + ERR_FAIL_COND_V_MSG(desc_url.is_empty(), UPNP_RESULT_INVALID_PARAM, "The description url must not be empty."); + + Ref dev; + struct UPNPUrls urls; + struct IGDdatas data; + char addr[16]; + + int i = UPNP_GetIGDFromUrl(desc_url.utf8().get_data(), &urls, &data, (char *)&addr, 16); + if (i != 1) { + FreeUPNPUrls(&urls); + return UPNP_RESULT_ACTION_FAILED; + } + + if (urls.controlURL[0] == '\0') { + FreeUPNPUrls(&urls); + return UPNP_RESULT_INVALID_RESPONSE; + } + + dev.instantiate(); + dev->set_description_url(desc_url); + dev->set_service_type("urn:schemas-upnp-org:device:InternetGatewayDevice:1"); + dev->set_igd_control_url(urls.controlURL); + dev->set_igd_service_type(data.first.servicetype); + dev->set_igd_our_addr(addr); + dev->set_igd_status(UPNPDevice::IGD_STATUS_OK); + FreeUPNPUrls(&urls); + + devices.push_back(dev); + + return UPNP_RESULT_SUCCESS; +} + void UPNP::add_device_to_list(UPNPDev *dev, UPNPDev *devlist) { Ref new_device; new_device.instantiate(); @@ -343,6 +376,7 @@ void UPNP::_bind_methods() { ClassDB::bind_method(D_METHOD("get_gateway"), &UPNP::get_gateway); ClassDB::bind_method(D_METHOD("discover", "timeout", "ttl", "device_filter"), &UPNP::discover, DEFVAL(2000), DEFVAL(2), DEFVAL("InternetGatewayDevice")); + ClassDB::bind_method(D_METHOD("add_device_from_url", "desc_url"), &UPNP::add_device_from_url); ClassDB::bind_method(D_METHOD("query_external_address"), &UPNP::query_external_address); diff --git a/modules/upnp/upnp.h b/modules/upnp/upnp.h index be7ede3ee04..3fb5aa24d11 100644 --- a/modules/upnp/upnp.h +++ b/modules/upnp/upnp.h @@ -100,6 +100,7 @@ public: Ref get_gateway() const; int discover(int timeout = 2000, int ttl = 2, const String &device_filter = "InternetGatewayDevice"); + UPNPResult add_device_from_url(const String &desc_url); String query_external_address() const;