initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
52
modules/upnp/SCsub
Normal file
52
modules/upnp/SCsub
Normal file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
Import("env_modules")
|
||||
|
||||
env_upnp = env_modules.Clone()
|
||||
|
||||
# Thirdparty source files
|
||||
|
||||
thirdparty_obj = []
|
||||
|
||||
if env["builtin_miniupnpc"] and env["platform"] != "web":
|
||||
thirdparty_dir = "#thirdparty/miniupnpc/"
|
||||
thirdparty_sources = [
|
||||
"igd_desc_parse.c",
|
||||
"miniupnpc.c",
|
||||
"minixml.c",
|
||||
"minisoap.c",
|
||||
"minissdpc.c",
|
||||
"miniwget.c",
|
||||
"upnpcommands.c",
|
||||
"upnpdev.c",
|
||||
"upnpreplyparse.c",
|
||||
"connecthostport.c",
|
||||
"portlistingparse.c",
|
||||
"receivedata.c",
|
||||
"addr_is_reserved.c",
|
||||
]
|
||||
thirdparty_sources = [thirdparty_dir + "src/" + file for file in thirdparty_sources]
|
||||
|
||||
env_upnp.Prepend(CPPEXTPATH=[thirdparty_dir + "include"])
|
||||
env_upnp.Append(CPPDEFINES=["MINIUPNP_STATICLIB"])
|
||||
if env["platform"] != "windows":
|
||||
env_upnp.Append(CPPDEFINES=["MINIUPNPC_SET_SOCKET_TIMEOUT"])
|
||||
|
||||
env_thirdparty = env_upnp.Clone()
|
||||
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_dir + "include/miniupnpc"])
|
||||
env_thirdparty.disable_warnings()
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
|
||||
env.modules_sources += thirdparty_obj
|
||||
|
||||
|
||||
# Godot source files
|
||||
|
||||
module_obj = []
|
||||
|
||||
env_upnp.add_source_files(module_obj, "*.cpp")
|
||||
env.modules_sources += module_obj
|
||||
|
||||
# Needed to force rebuilding the module files when the thirdparty library is updated.
|
||||
env.Depends(module_obj, thirdparty_obj)
|
17
modules/upnp/config.py
Normal file
17
modules/upnp/config.py
Normal file
@@ -0,0 +1,17 @@
|
||||
def can_build(env, platform):
|
||||
return True
|
||||
|
||||
|
||||
def configure(env):
|
||||
pass
|
||||
|
||||
|
||||
def get_doc_classes():
|
||||
return [
|
||||
"UPNP",
|
||||
"UPNPDevice",
|
||||
]
|
||||
|
||||
|
||||
def get_doc_path():
|
||||
return "doc_classes"
|
251
modules/upnp/doc_classes/UPNP.xml
Normal file
251
modules/upnp/doc_classes/UPNP.xml
Normal file
@@ -0,0 +1,251 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="UPNP" inherits="RefCounted" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||
<brief_description>
|
||||
Universal Plug and Play (UPnP) functions for network device discovery, querying and port forwarding.
|
||||
</brief_description>
|
||||
<description>
|
||||
This class can be used to discover compatible [UPNPDevice]s on the local network and execute commands on them, like managing port mappings (for port forwarding/NAT traversal) and querying the local and remote network IP address. Note that methods on this class are synchronous and block the calling thread.
|
||||
To forward a specific port (here [code]7777[/code], note both [method discover] and [method add_port_mapping] can return errors that should be checked):
|
||||
[codeblock]
|
||||
var upnp = UPNP.new()
|
||||
upnp.discover()
|
||||
upnp.add_port_mapping(7777)
|
||||
[/codeblock]
|
||||
To close a specific port (e.g. after you have finished using it):
|
||||
[codeblock]
|
||||
upnp.delete_port_mapping(port)
|
||||
[/codeblock]
|
||||
[b]Note:[/b] UPnP discovery blocks the current thread. To perform discovery without blocking the main thread, use [Thread]s like this:
|
||||
[codeblock]
|
||||
# Emitted when UPnP port mapping setup is completed (regardless of success or failure).
|
||||
signal upnp_completed(error)
|
||||
|
||||
# Replace this with your own server port number between 1024 and 65535.
|
||||
const SERVER_PORT = 3928
|
||||
var thread = null
|
||||
|
||||
func _upnp_setup(server_port):
|
||||
# UPNP queries take some time.
|
||||
var upnp = UPNP.new()
|
||||
var err = upnp.discover()
|
||||
|
||||
if err != OK:
|
||||
push_error(str(err))
|
||||
upnp_completed.emit(err)
|
||||
return
|
||||
|
||||
if upnp.get_gateway() and upnp.get_gateway().is_valid_gateway():
|
||||
upnp.add_port_mapping(server_port, server_port, ProjectSettings.get_setting("application/config/name"), "UDP")
|
||||
upnp.add_port_mapping(server_port, server_port, ProjectSettings.get_setting("application/config/name"), "TCP")
|
||||
upnp_completed.emit(OK)
|
||||
|
||||
func _ready():
|
||||
thread = Thread.new()
|
||||
thread.start(_upnp_setup.bind(SERVER_PORT))
|
||||
|
||||
func _exit_tree():
|
||||
# Wait for thread finish here to handle game exit while the thread is running.
|
||||
thread.wait_to_finish()
|
||||
[/codeblock]
|
||||
[b]Terminology:[/b] In the context of UPnP networking, "gateway" (or "internet gateway device", short IGD) refers to network devices that allow computers in the local network to access the internet ("wide area network", WAN). These gateways are often also called "routers".
|
||||
[b]Pitfalls:[/b]
|
||||
- As explained above, these calls are blocking and shouldn't be run on the main thread, especially as they can block for multiple seconds at a time. Use threading!
|
||||
- Networking is physical and messy. Packets get lost in transit or get filtered, addresses, free ports and assigned mappings change, and devices may leave or join the network at any time. Be mindful of this, be diligent when checking and handling errors, and handle these gracefully if you can: add clear error UI, timeouts and re-try handling.
|
||||
- Port mappings may change (and be removed) at any time, and the remote/external IP address of the gateway can change likewise. You should consider re-querying the external IP and try to update/refresh the port mapping periodically (for example, every 5 minutes and on networking failures).
|
||||
- Not all devices support UPnP, and some users disable UPnP support. You need to handle this (e.g. documenting and requiring the user to manually forward ports, or adding alternative methods of NAT traversal, like a relay/mirror server, or NAT hole punching, STUN/TURN, etc.).
|
||||
- Consider what happens on mapping conflicts. Maybe multiple users on the same network would like to play your game at the same time, or maybe another application uses the same port. Make the port configurable, and optimally choose a port automatically (re-trying with a different port on failure).
|
||||
[b]Further reading:[/b] If you want to know more about UPnP (and the Internet Gateway Device (IGD) and Port Control Protocol (PCP) specifically), [url=https://en.wikipedia.org/wiki/Universal_Plug_and_Play]Wikipedia[/url] is a good first stop, the specification can be found at the [url=https://openconnectivity.org/developer/specifications/upnp-resources/upnp/]Open Connectivity Foundation[/url] and Godot's implementation is based on the [url=https://github.com/miniupnp/miniupnp]MiniUPnP client[/url].
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_device">
|
||||
<return type="void" />
|
||||
<param index="0" name="device" type="UPNPDevice" />
|
||||
<description>
|
||||
Adds the given [UPNPDevice] to the list of discovered devices.
|
||||
</description>
|
||||
</method>
|
||||
<method name="add_port_mapping" qualifiers="const">
|
||||
<return type="int" />
|
||||
<param index="0" name="port" type="int" />
|
||||
<param index="1" name="port_internal" type="int" default="0" />
|
||||
<param index="2" name="desc" type="String" default="""" />
|
||||
<param index="3" name="proto" type="String" default=""UDP"" />
|
||||
<param index="4" name="duration" type="int" default="0" />
|
||||
<description>
|
||||
Adds a mapping to forward the external [param port] (between 1 and 65535, although recommended to use port 1024 or above) on the default gateway (see [method get_gateway]) to the [param port_internal] on the local machine for the given protocol [param proto] (either [code]"TCP"[/code] or [code]"UDP"[/code], with UDP being the default). If a port mapping for the given port and protocol combination already exists on that gateway device, this method tries to overwrite it. If that is not desired, you can retrieve the gateway manually with [method get_gateway] and call [method add_port_mapping] on it, if any. Note that forwarding a well-known port (below 1024) with UPnP may fail depending on the device.
|
||||
Depending on the gateway device, if a mapping for that port already exists, it will either be updated or it will refuse this command due to that conflict, especially if the existing mapping for that port wasn't created via UPnP or points to a different network address (or device) than this one.
|
||||
If [param port_internal] is [code]0[/code] (the default), the same port number is used for both the external and the internal port (the [param port] value).
|
||||
The description ([param desc]) is shown in some routers management UIs and can be used to point out which application added the mapping.
|
||||
The mapping's lease [param duration] can be limited by specifying a duration in seconds. The default of [code]0[/code] means no duration, i.e. a permanent lease and notably some devices only support these permanent leases. Note that whether permanent or not, this is only a request and the gateway may still decide at any point to remove the mapping (which usually happens on a reboot of the gateway, when its external IP address changes, or on some models when it detects a port mapping has become inactive, i.e. had no traffic for multiple minutes). If not [code]0[/code] (permanent), the allowed range according to spec is between [code]120[/code] (2 minutes) and [code]86400[/code] seconds (24 hours).
|
||||
See [enum UPNPResult] for possible return values.
|
||||
</description>
|
||||
</method>
|
||||
<method name="clear_devices">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Clears the list of discovered devices.
|
||||
</description>
|
||||
</method>
|
||||
<method name="delete_port_mapping" qualifiers="const">
|
||||
<return type="int" />
|
||||
<param index="0" name="port" type="int" />
|
||||
<param index="1" name="proto" type="String" default=""UDP"" />
|
||||
<description>
|
||||
Deletes the port mapping for the given port and protocol combination on the default gateway (see [method get_gateway]) if one exists. [param port] must be a valid port between 1 and 65535, [param proto] can be either [code]"TCP"[/code] or [code]"UDP"[/code]. May be refused for mappings pointing to addresses other than this one, for well-known ports (below 1024), or for mappings not added via UPnP. See [enum UPNPResult] for possible return values.
|
||||
</description>
|
||||
</method>
|
||||
<method name="discover">
|
||||
<return type="int" />
|
||||
<param index="0" name="timeout" type="int" default="2000" />
|
||||
<param index="1" name="ttl" type="int" default="2" />
|
||||
<param index="2" name="device_filter" type="String" default=""InternetGatewayDevice"" />
|
||||
<description>
|
||||
Discovers local [UPNPDevice]s. Clears the list of previously discovered devices.
|
||||
Filters for IGD (InternetGatewayDevice) type devices by default, as those manage port forwarding. [param timeout] is the time to wait for responses in milliseconds. [param ttl] is the time-to-live; only touch this if you know what you're doing.
|
||||
See [enum UPNPResult] for possible return values.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_device" qualifiers="const">
|
||||
<return type="UPNPDevice" />
|
||||
<param index="0" name="index" type="int" />
|
||||
<description>
|
||||
Returns the [UPNPDevice] at the given [param index].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_device_count" qualifiers="const">
|
||||
<return type="int" />
|
||||
<description>
|
||||
Returns the number of discovered [UPNPDevice]s.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_gateway" qualifiers="const">
|
||||
<return type="UPNPDevice" />
|
||||
<description>
|
||||
Returns the default gateway. That is the first discovered [UPNPDevice] that is also a valid IGD (InternetGatewayDevice).
|
||||
</description>
|
||||
</method>
|
||||
<method name="query_external_address" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns the external [IP] address of the default gateway (see [method get_gateway]) as string. Returns an empty string on error.
|
||||
</description>
|
||||
</method>
|
||||
<method name="remove_device">
|
||||
<return type="void" />
|
||||
<param index="0" name="index" type="int" />
|
||||
<description>
|
||||
Removes the device at [param index] from the list of discovered devices.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_device">
|
||||
<return type="void" />
|
||||
<param index="0" name="index" type="int" />
|
||||
<param index="1" name="device" type="UPNPDevice" />
|
||||
<description>
|
||||
Sets the device at [param index] from the list of discovered devices to [param device].
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="discover_ipv6" type="bool" setter="set_discover_ipv6" getter="is_discover_ipv6" default="false">
|
||||
If [code]true[/code], IPv6 is used for [UPNPDevice] discovery.
|
||||
</member>
|
||||
<member name="discover_local_port" type="int" setter="set_discover_local_port" getter="get_discover_local_port" default="0">
|
||||
If [code]0[/code], the local port to use for discovery is chosen automatically by the system. If [code]1[/code], discovery will be done from the source port 1900 (same as destination port). Otherwise, the value will be used as the port.
|
||||
</member>
|
||||
<member name="discover_multicast_if" type="String" setter="set_discover_multicast_if" getter="get_discover_multicast_if" default="""">
|
||||
Multicast interface to use for discovery. Uses the default multicast interface if empty.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="UPNP_RESULT_SUCCESS" value="0" enum="UPNPResult">
|
||||
UPNP command or discovery was successful.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_NOT_AUTHORIZED" value="1" enum="UPNPResult">
|
||||
Not authorized to use the command on the [UPNPDevice]. May be returned when the user disabled UPNP on their router.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_PORT_MAPPING_NOT_FOUND" value="2" enum="UPNPResult">
|
||||
No port mapping was found for the given port, protocol combination on the given [UPNPDevice].
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_INCONSISTENT_PARAMETERS" value="3" enum="UPNPResult">
|
||||
Inconsistent parameters.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_NO_SUCH_ENTRY_IN_ARRAY" value="4" enum="UPNPResult">
|
||||
No such entry in array. May be returned if a given port, protocol combination is not found on a [UPNPDevice].
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_ACTION_FAILED" value="5" enum="UPNPResult">
|
||||
The action failed.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_SRC_IP_WILDCARD_NOT_PERMITTED" value="6" enum="UPNPResult">
|
||||
The [UPNPDevice] does not allow wildcard values for the source IP address.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_EXT_PORT_WILDCARD_NOT_PERMITTED" value="7" enum="UPNPResult">
|
||||
The [UPNPDevice] does not allow wildcard values for the external port.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_INT_PORT_WILDCARD_NOT_PERMITTED" value="8" enum="UPNPResult">
|
||||
The [UPNPDevice] does not allow wildcard values for the internal port.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_REMOTE_HOST_MUST_BE_WILDCARD" value="9" enum="UPNPResult">
|
||||
The remote host value must be a wildcard.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_EXT_PORT_MUST_BE_WILDCARD" value="10" enum="UPNPResult">
|
||||
The external port value must be a wildcard.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_NO_PORT_MAPS_AVAILABLE" value="11" enum="UPNPResult">
|
||||
No port maps are available. May also be returned if port mapping functionality is not available.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_CONFLICT_WITH_OTHER_MECHANISM" value="12" enum="UPNPResult">
|
||||
Conflict with other mechanism. May be returned instead of [constant UPNP_RESULT_CONFLICT_WITH_OTHER_MAPPING] if a port mapping conflicts with an existing one.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_CONFLICT_WITH_OTHER_MAPPING" value="13" enum="UPNPResult">
|
||||
Conflict with an existing port mapping.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_SAME_PORT_VALUES_REQUIRED" value="14" enum="UPNPResult">
|
||||
External and internal port values must be the same.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_ONLY_PERMANENT_LEASE_SUPPORTED" value="15" enum="UPNPResult">
|
||||
Only permanent leases are supported. Do not use the [code]duration[/code] parameter when adding port mappings.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_INVALID_GATEWAY" value="16" enum="UPNPResult">
|
||||
Invalid gateway.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_INVALID_PORT" value="17" enum="UPNPResult">
|
||||
Invalid port.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_INVALID_PROTOCOL" value="18" enum="UPNPResult">
|
||||
Invalid protocol.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_INVALID_DURATION" value="19" enum="UPNPResult">
|
||||
Invalid duration.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_INVALID_ARGS" value="20" enum="UPNPResult">
|
||||
Invalid arguments.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_INVALID_RESPONSE" value="21" enum="UPNPResult">
|
||||
Invalid response.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_INVALID_PARAM" value="22" enum="UPNPResult">
|
||||
Invalid parameter.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_HTTP_ERROR" value="23" enum="UPNPResult">
|
||||
HTTP error.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_SOCKET_ERROR" value="24" enum="UPNPResult">
|
||||
Socket error.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_MEM_ALLOC_ERROR" value="25" enum="UPNPResult">
|
||||
Error allocating memory.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_NO_GATEWAY" value="26" enum="UPNPResult">
|
||||
No gateway available. You may need to call [method discover] first, or discovery didn't detect any valid IGDs (InternetGatewayDevices).
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_NO_DEVICES" value="27" enum="UPNPResult">
|
||||
No devices available. You may need to call [method discover] first, or discovery didn't detect any valid [UPNPDevice]s.
|
||||
</constant>
|
||||
<constant name="UPNP_RESULT_UNKNOWN_ERROR" value="28" enum="UPNPResult">
|
||||
Unknown error.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
96
modules/upnp/doc_classes/UPNPDevice.xml
Normal file
96
modules/upnp/doc_classes/UPNPDevice.xml
Normal file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="UPNPDevice" inherits="RefCounted" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||
<brief_description>
|
||||
Universal Plug and Play (UPnP) device.
|
||||
</brief_description>
|
||||
<description>
|
||||
Universal Plug and Play (UPnP) device. See [UPNP] for UPnP discovery and utility functions. Provides low-level access to UPNP control commands. Allows to manage port mappings (port forwarding) and to query network information of the device (like local and external IP address and status). Note that methods on this class are synchronous and block the calling thread.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="add_port_mapping" qualifiers="const">
|
||||
<return type="int" />
|
||||
<param index="0" name="port" type="int" />
|
||||
<param index="1" name="port_internal" type="int" default="0" />
|
||||
<param index="2" name="desc" type="String" default="""" />
|
||||
<param index="3" name="proto" type="String" default=""UDP"" />
|
||||
<param index="4" name="duration" type="int" default="0" />
|
||||
<description>
|
||||
Adds a port mapping to forward the given external port on this [UPNPDevice] for the given protocol to the local machine. See [method UPNP.add_port_mapping].
|
||||
</description>
|
||||
</method>
|
||||
<method name="delete_port_mapping" qualifiers="const">
|
||||
<return type="int" />
|
||||
<param index="0" name="port" type="int" />
|
||||
<param index="1" name="proto" type="String" default=""UDP"" />
|
||||
<description>
|
||||
Deletes the port mapping identified by the given port and protocol combination on this device. See [method UPNP.delete_port_mapping].
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_valid_gateway" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if this is a valid IGD (InternetGatewayDevice) which potentially supports port forwarding.
|
||||
</description>
|
||||
</method>
|
||||
<method name="query_external_address" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns the external IP address of this [UPNPDevice] or an empty string.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="description_url" type="String" setter="set_description_url" getter="get_description_url" default="""">
|
||||
URL to the device description.
|
||||
</member>
|
||||
<member name="igd_control_url" type="String" setter="set_igd_control_url" getter="get_igd_control_url" default="""">
|
||||
IDG control URL.
|
||||
</member>
|
||||
<member name="igd_our_addr" type="String" setter="set_igd_our_addr" getter="get_igd_our_addr" default="""">
|
||||
Address of the local machine in the network connecting it to this [UPNPDevice].
|
||||
</member>
|
||||
<member name="igd_service_type" type="String" setter="set_igd_service_type" getter="get_igd_service_type" default="""">
|
||||
IGD service type.
|
||||
</member>
|
||||
<member name="igd_status" type="int" setter="set_igd_status" getter="get_igd_status" enum="UPNPDevice.IGDStatus" default="9">
|
||||
IGD status.
|
||||
</member>
|
||||
<member name="service_type" type="String" setter="set_service_type" getter="get_service_type" default="""">
|
||||
Service type.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="IGD_STATUS_OK" value="0" enum="IGDStatus">
|
||||
OK.
|
||||
</constant>
|
||||
<constant name="IGD_STATUS_HTTP_ERROR" value="1" enum="IGDStatus">
|
||||
HTTP error.
|
||||
</constant>
|
||||
<constant name="IGD_STATUS_HTTP_EMPTY" value="2" enum="IGDStatus">
|
||||
Empty HTTP response.
|
||||
</constant>
|
||||
<constant name="IGD_STATUS_NO_URLS" value="3" enum="IGDStatus" deprecated="This value is no longer used.">
|
||||
Returned response contained no URLs.
|
||||
</constant>
|
||||
<constant name="IGD_STATUS_NO_IGD" value="4" enum="IGDStatus">
|
||||
Not a valid IGD.
|
||||
</constant>
|
||||
<constant name="IGD_STATUS_DISCONNECTED" value="5" enum="IGDStatus">
|
||||
Disconnected.
|
||||
</constant>
|
||||
<constant name="IGD_STATUS_UNKNOWN_DEVICE" value="6" enum="IGDStatus">
|
||||
Unknown device.
|
||||
</constant>
|
||||
<constant name="IGD_STATUS_INVALID_CONTROL" value="7" enum="IGDStatus">
|
||||
Invalid control.
|
||||
</constant>
|
||||
<constant name="IGD_STATUS_MALLOC_ERROR" value="8" enum="IGDStatus" deprecated="This value is no longer used.">
|
||||
Memory allocation error.
|
||||
</constant>
|
||||
<constant name="IGD_STATUS_UNKNOWN_ERROR" value="9" enum="IGDStatus">
|
||||
Unknown error.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
59
modules/upnp/register_types.cpp
Normal file
59
modules/upnp/register_types.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/**************************************************************************/
|
||||
/* register_types.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "register_types.h"
|
||||
|
||||
#include "upnp.h"
|
||||
#include "upnp_device.h"
|
||||
|
||||
#ifndef WEB_ENABLED
|
||||
#include "upnp_device_miniupnp.h"
|
||||
#include "upnp_miniupnp.h"
|
||||
#endif
|
||||
|
||||
void initialize_upnp_module(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
|
||||
ClassDB::register_custom_instance_class<UPNP>();
|
||||
ClassDB::register_custom_instance_class<UPNPDevice>();
|
||||
|
||||
#ifndef WEB_ENABLED
|
||||
UPNPMiniUPNP::make_default();
|
||||
UPNPDeviceMiniUPNP::make_default();
|
||||
#endif
|
||||
}
|
||||
|
||||
void uninitialize_upnp_module(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
}
|
36
modules/upnp/register_types.h
Normal file
36
modules/upnp/register_types.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/**************************************************************************/
|
||||
/* register_types.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "modules/register_module_types.h"
|
||||
|
||||
void initialize_upnp_module(ModuleInitializationLevel p_level);
|
||||
void uninitialize_upnp_module(ModuleInitializationLevel p_level);
|
93
modules/upnp/upnp.cpp
Normal file
93
modules/upnp/upnp.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/**************************************************************************/
|
||||
/* upnp.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "upnp.h"
|
||||
|
||||
UPNP *(*UPNP::_create)(bool p_notify_postinitialize) = nullptr;
|
||||
|
||||
void UPNP::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_device_count"), &UPNP::get_device_count);
|
||||
ClassDB::bind_method(D_METHOD("get_device", "index"), &UPNP::get_device);
|
||||
ClassDB::bind_method(D_METHOD("add_device", "device"), &UPNP::add_device);
|
||||
ClassDB::bind_method(D_METHOD("set_device", "index", "device"), &UPNP::set_device);
|
||||
ClassDB::bind_method(D_METHOD("remove_device", "index"), &UPNP::remove_device);
|
||||
ClassDB::bind_method(D_METHOD("clear_devices"), &UPNP::clear_devices);
|
||||
|
||||
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("query_external_address"), &UPNP::query_external_address);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("add_port_mapping", "port", "port_internal", "desc", "proto", "duration"), &UPNP::add_port_mapping, DEFVAL(0), DEFVAL(""), DEFVAL("UDP"), DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("delete_port_mapping", "port", "proto"), &UPNP::delete_port_mapping, DEFVAL("UDP"));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_discover_multicast_if", "m_if"), &UPNP::set_discover_multicast_if);
|
||||
ClassDB::bind_method(D_METHOD("get_discover_multicast_if"), &UPNP::get_discover_multicast_if);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "discover_multicast_if"), "set_discover_multicast_if", "get_discover_multicast_if");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_discover_local_port", "port"), &UPNP::set_discover_local_port);
|
||||
ClassDB::bind_method(D_METHOD("get_discover_local_port"), &UPNP::get_discover_local_port);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "discover_local_port", PROPERTY_HINT_RANGE, "0,65535"), "set_discover_local_port", "get_discover_local_port");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_discover_ipv6", "ipv6"), &UPNP::set_discover_ipv6);
|
||||
ClassDB::bind_method(D_METHOD("is_discover_ipv6"), &UPNP::is_discover_ipv6);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "discover_ipv6"), "set_discover_ipv6", "is_discover_ipv6");
|
||||
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_SUCCESS);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_NOT_AUTHORIZED);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_PORT_MAPPING_NOT_FOUND);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_INCONSISTENT_PARAMETERS);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_NO_SUCH_ENTRY_IN_ARRAY);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_ACTION_FAILED);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_SRC_IP_WILDCARD_NOT_PERMITTED);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_EXT_PORT_WILDCARD_NOT_PERMITTED);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_INT_PORT_WILDCARD_NOT_PERMITTED);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_REMOTE_HOST_MUST_BE_WILDCARD);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_EXT_PORT_MUST_BE_WILDCARD);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_NO_PORT_MAPS_AVAILABLE);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_CONFLICT_WITH_OTHER_MECHANISM);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_CONFLICT_WITH_OTHER_MAPPING);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_SAME_PORT_VALUES_REQUIRED);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_ONLY_PERMANENT_LEASE_SUPPORTED);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_INVALID_GATEWAY);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_INVALID_PORT);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_INVALID_PROTOCOL);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_INVALID_DURATION);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_INVALID_ARGS);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_INVALID_RESPONSE);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_INVALID_PARAM);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_HTTP_ERROR);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_SOCKET_ERROR);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_MEM_ALLOC_ERROR);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_NO_GATEWAY);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_NO_DEVICES);
|
||||
BIND_ENUM_CONSTANT(UPNP_RESULT_UNKNOWN_ERROR);
|
||||
}
|
114
modules/upnp/upnp.h
Normal file
114
modules/upnp/upnp.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/**************************************************************************/
|
||||
/* upnp.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "upnp_device.h"
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
class UPNP : public RefCounted {
|
||||
GDCLASS(UPNP, RefCounted);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
static UPNP *(*_create)(bool p_notify_postinitialize);
|
||||
|
||||
public:
|
||||
enum UPNPResult {
|
||||
UPNP_RESULT_SUCCESS,
|
||||
UPNP_RESULT_NOT_AUTHORIZED,
|
||||
UPNP_RESULT_PORT_MAPPING_NOT_FOUND,
|
||||
UPNP_RESULT_INCONSISTENT_PARAMETERS,
|
||||
UPNP_RESULT_NO_SUCH_ENTRY_IN_ARRAY,
|
||||
UPNP_RESULT_ACTION_FAILED,
|
||||
UPNP_RESULT_SRC_IP_WILDCARD_NOT_PERMITTED,
|
||||
UPNP_RESULT_EXT_PORT_WILDCARD_NOT_PERMITTED,
|
||||
UPNP_RESULT_INT_PORT_WILDCARD_NOT_PERMITTED,
|
||||
UPNP_RESULT_REMOTE_HOST_MUST_BE_WILDCARD,
|
||||
UPNP_RESULT_EXT_PORT_MUST_BE_WILDCARD,
|
||||
UPNP_RESULT_NO_PORT_MAPS_AVAILABLE,
|
||||
UPNP_RESULT_CONFLICT_WITH_OTHER_MECHANISM,
|
||||
UPNP_RESULT_CONFLICT_WITH_OTHER_MAPPING,
|
||||
UPNP_RESULT_SAME_PORT_VALUES_REQUIRED,
|
||||
UPNP_RESULT_ONLY_PERMANENT_LEASE_SUPPORTED,
|
||||
UPNP_RESULT_INVALID_GATEWAY,
|
||||
UPNP_RESULT_INVALID_PORT,
|
||||
UPNP_RESULT_INVALID_PROTOCOL,
|
||||
UPNP_RESULT_INVALID_DURATION,
|
||||
UPNP_RESULT_INVALID_ARGS,
|
||||
UPNP_RESULT_INVALID_RESPONSE,
|
||||
UPNP_RESULT_INVALID_PARAM,
|
||||
UPNP_RESULT_HTTP_ERROR,
|
||||
UPNP_RESULT_SOCKET_ERROR,
|
||||
UPNP_RESULT_MEM_ALLOC_ERROR,
|
||||
UPNP_RESULT_NO_GATEWAY,
|
||||
UPNP_RESULT_NO_DEVICES,
|
||||
UPNP_RESULT_UNKNOWN_ERROR,
|
||||
};
|
||||
|
||||
static UPNP *create(bool p_notify_postinitialize = true) {
|
||||
if (!_create) {
|
||||
return nullptr;
|
||||
}
|
||||
return _create(p_notify_postinitialize);
|
||||
}
|
||||
|
||||
virtual int get_device_count() const = 0;
|
||||
virtual Ref<UPNPDevice> get_device(int index) const = 0;
|
||||
virtual void add_device(Ref<UPNPDevice> device) = 0;
|
||||
virtual void set_device(int index, Ref<UPNPDevice> device) = 0;
|
||||
virtual void remove_device(int index) = 0;
|
||||
virtual void clear_devices() = 0;
|
||||
|
||||
virtual Ref<UPNPDevice> get_gateway() const = 0;
|
||||
|
||||
virtual int discover(int timeout = 2000, int ttl = 2, const String &device_filter = "InternetGatewayDevice") = 0;
|
||||
|
||||
virtual String query_external_address() const = 0;
|
||||
|
||||
virtual int add_port_mapping(int port, int port_internal = 0, String desc = "", String proto = "UDP", int duration = 0) const = 0;
|
||||
virtual int delete_port_mapping(int port, String proto = "UDP") const = 0;
|
||||
|
||||
virtual void set_discover_multicast_if(const String &m_if) = 0;
|
||||
virtual String get_discover_multicast_if() const = 0;
|
||||
|
||||
virtual void set_discover_local_port(int port) = 0;
|
||||
virtual int get_discover_local_port() const = 0;
|
||||
|
||||
virtual void set_discover_ipv6(bool ipv6) = 0;
|
||||
virtual bool is_discover_ipv6() const = 0;
|
||||
|
||||
UPNP() {}
|
||||
virtual ~UPNP() {}
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(UPNP::UPNPResult)
|
75
modules/upnp/upnp_device.cpp
Normal file
75
modules/upnp/upnp_device.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/**************************************************************************/
|
||||
/* upnp_device.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "upnp_device.h"
|
||||
|
||||
UPNPDevice *(*UPNPDevice::_create)(bool p_notify_postinitialize) = nullptr;
|
||||
|
||||
void UPNPDevice::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("is_valid_gateway"), &UPNPDevice::is_valid_gateway);
|
||||
ClassDB::bind_method(D_METHOD("query_external_address"), &UPNPDevice::query_external_address);
|
||||
ClassDB::bind_method(D_METHOD("add_port_mapping", "port", "port_internal", "desc", "proto", "duration"), &UPNPDevice::add_port_mapping, DEFVAL(0), DEFVAL(""), DEFVAL("UDP"), DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("delete_port_mapping", "port", "proto"), &UPNPDevice::delete_port_mapping, DEFVAL("UDP"));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_description_url", "url"), &UPNPDevice::set_description_url);
|
||||
ClassDB::bind_method(D_METHOD("get_description_url"), &UPNPDevice::get_description_url);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "description_url"), "set_description_url", "get_description_url");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_service_type", "type"), &UPNPDevice::set_service_type);
|
||||
ClassDB::bind_method(D_METHOD("get_service_type"), &UPNPDevice::get_service_type);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "service_type"), "set_service_type", "get_service_type");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_igd_control_url", "url"), &UPNPDevice::set_igd_control_url);
|
||||
ClassDB::bind_method(D_METHOD("get_igd_control_url"), &UPNPDevice::get_igd_control_url);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "igd_control_url"), "set_igd_control_url", "get_igd_control_url");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_igd_service_type", "type"), &UPNPDevice::set_igd_service_type);
|
||||
ClassDB::bind_method(D_METHOD("get_igd_service_type"), &UPNPDevice::get_igd_service_type);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "igd_service_type"), "set_igd_service_type", "get_igd_service_type");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_igd_our_addr", "addr"), &UPNPDevice::set_igd_our_addr);
|
||||
ClassDB::bind_method(D_METHOD("get_igd_our_addr"), &UPNPDevice::get_igd_our_addr);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "igd_our_addr"), "set_igd_our_addr", "get_igd_our_addr");
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_igd_status", "status"), &UPNPDevice::set_igd_status);
|
||||
ClassDB::bind_method(D_METHOD("get_igd_status"), &UPNPDevice::get_igd_status);
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "igd_status", PROPERTY_HINT_ENUM), "set_igd_status", "get_igd_status");
|
||||
|
||||
BIND_ENUM_CONSTANT(IGD_STATUS_OK);
|
||||
BIND_ENUM_CONSTANT(IGD_STATUS_HTTP_ERROR);
|
||||
BIND_ENUM_CONSTANT(IGD_STATUS_HTTP_EMPTY);
|
||||
BIND_ENUM_CONSTANT(IGD_STATUS_NO_URLS);
|
||||
BIND_ENUM_CONSTANT(IGD_STATUS_NO_IGD);
|
||||
BIND_ENUM_CONSTANT(IGD_STATUS_DISCONNECTED);
|
||||
BIND_ENUM_CONSTANT(IGD_STATUS_UNKNOWN_DEVICE);
|
||||
BIND_ENUM_CONSTANT(IGD_STATUS_INVALID_CONTROL);
|
||||
BIND_ENUM_CONSTANT(IGD_STATUS_MALLOC_ERROR);
|
||||
BIND_ENUM_CONSTANT(IGD_STATUS_UNKNOWN_ERROR);
|
||||
}
|
91
modules/upnp/upnp_device.h
Normal file
91
modules/upnp/upnp_device.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/**************************************************************************/
|
||||
/* upnp_device.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
class UPNPDevice : public RefCounted {
|
||||
GDCLASS(UPNPDevice, RefCounted);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
static UPNPDevice *(*_create)(bool p_notify_postinitialize);
|
||||
|
||||
public:
|
||||
enum IGDStatus {
|
||||
IGD_STATUS_OK,
|
||||
IGD_STATUS_HTTP_ERROR,
|
||||
IGD_STATUS_HTTP_EMPTY,
|
||||
IGD_STATUS_NO_URLS,
|
||||
IGD_STATUS_NO_IGD,
|
||||
IGD_STATUS_DISCONNECTED,
|
||||
IGD_STATUS_UNKNOWN_DEVICE,
|
||||
IGD_STATUS_INVALID_CONTROL,
|
||||
IGD_STATUS_MALLOC_ERROR,
|
||||
IGD_STATUS_UNKNOWN_ERROR,
|
||||
};
|
||||
|
||||
static UPNPDevice *create(bool p_notify_postinitialize = true) {
|
||||
if (!_create) {
|
||||
return nullptr;
|
||||
}
|
||||
return _create(p_notify_postinitialize);
|
||||
}
|
||||
|
||||
virtual void set_description_url(const String &url) = 0;
|
||||
virtual String get_description_url() const = 0;
|
||||
|
||||
virtual void set_service_type(const String &type) = 0;
|
||||
virtual String get_service_type() const = 0;
|
||||
|
||||
virtual void set_igd_control_url(const String &url) = 0;
|
||||
virtual String get_igd_control_url() const = 0;
|
||||
|
||||
virtual void set_igd_service_type(const String &type) = 0;
|
||||
virtual String get_igd_service_type() const = 0;
|
||||
|
||||
virtual void set_igd_our_addr(const String &addr) = 0;
|
||||
virtual String get_igd_our_addr() const = 0;
|
||||
|
||||
virtual void set_igd_status(IGDStatus status) = 0;
|
||||
virtual IGDStatus get_igd_status() const = 0;
|
||||
|
||||
virtual bool is_valid_gateway() const = 0;
|
||||
virtual String query_external_address() const = 0;
|
||||
virtual int add_port_mapping(int port, int port_internal = 0, String desc = "", String proto = "UDP", int duration = 0) const = 0;
|
||||
virtual int delete_port_mapping(int port, String proto = "UDP") const = 0;
|
||||
|
||||
UPNPDevice() {}
|
||||
virtual ~UPNPDevice() {}
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(UPNPDevice::IGDStatus)
|
153
modules/upnp/upnp_device_miniupnp.cpp
Normal file
153
modules/upnp/upnp_device_miniupnp.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/**************************************************************************/
|
||||
/* upnp_device_miniupnp.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef WEB_ENABLED
|
||||
|
||||
#include "upnp_device_miniupnp.h"
|
||||
|
||||
#include "upnp_miniupnp.h"
|
||||
|
||||
#include <miniupnpc/upnpcommands.h>
|
||||
|
||||
void UPNPDeviceMiniUPNP::make_default() {
|
||||
UPNPDevice::_create = UPNPDeviceMiniUPNP::_create;
|
||||
}
|
||||
|
||||
String UPNPDeviceMiniUPNP::query_external_address() const {
|
||||
ERR_FAIL_COND_V_MSG(!is_valid_gateway(), "", "The Internet Gateway Device must be valid.");
|
||||
|
||||
char addr[16];
|
||||
int i = UPNP_GetExternalIPAddress(
|
||||
igd_control_url.utf8().get_data(),
|
||||
igd_service_type.utf8().get_data(),
|
||||
(char *)&addr);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(i != UPNPCOMMAND_SUCCESS, "", "Couldn't get external IP address.");
|
||||
|
||||
return String(addr);
|
||||
}
|
||||
|
||||
int UPNPDeviceMiniUPNP::add_port_mapping(int port, int port_internal, String desc, String proto, int duration) const {
|
||||
ERR_FAIL_COND_V_MSG(!is_valid_gateway(), UPNP::UPNP_RESULT_INVALID_GATEWAY, "The Internet Gateway Device must be valid.");
|
||||
ERR_FAIL_COND_V_MSG(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT, "The port number must be set between 1 and 65535 (inclusive).");
|
||||
ERR_FAIL_COND_V_MSG(port_internal < 0 || port_internal > 65535, UPNP::UPNP_RESULT_INVALID_PORT, "The port number must be set between 0 and 65535 (inclusive)."); // Needs to allow 0 because 0 signifies "use external port as internal port"
|
||||
ERR_FAIL_COND_V_MSG(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL, "The protocol must be either TCP or UDP.");
|
||||
ERR_FAIL_COND_V_MSG(duration < 0, UPNP::UPNP_RESULT_INVALID_DURATION, "The port mapping's lease duration can't be negative.");
|
||||
|
||||
if (port_internal < 1) {
|
||||
port_internal = port;
|
||||
}
|
||||
|
||||
int i = UPNP_AddPortMapping(
|
||||
igd_control_url.utf8().get_data(),
|
||||
igd_service_type.utf8().get_data(),
|
||||
itos(port).utf8().get_data(),
|
||||
itos(port_internal).utf8().get_data(),
|
||||
igd_our_addr.utf8().get_data(),
|
||||
desc.is_empty() ? nullptr : desc.utf8().get_data(),
|
||||
proto.utf8().get_data(),
|
||||
nullptr, // Remote host, always nullptr as IGDs don't support it
|
||||
duration > 0 ? itos(duration).utf8().get_data() : nullptr);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(i != UPNPCOMMAND_SUCCESS, UPNPMiniUPNP::upnp_result(i), "Couldn't add port mapping.");
|
||||
|
||||
return UPNP::UPNP_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
int UPNPDeviceMiniUPNP::delete_port_mapping(int port, String proto) const {
|
||||
ERR_FAIL_COND_V_MSG(port < 1 || port > 65535, UPNP::UPNP_RESULT_INVALID_PORT, "The port number must be set between 1 and 65535 (inclusive).");
|
||||
ERR_FAIL_COND_V_MSG(proto != "UDP" && proto != "TCP", UPNP::UPNP_RESULT_INVALID_PROTOCOL, "The protocol must be either TCP or UDP.");
|
||||
|
||||
int i = UPNP_DeletePortMapping(
|
||||
igd_control_url.utf8().get_data(),
|
||||
igd_service_type.utf8().get_data(),
|
||||
itos(port).utf8().get_data(),
|
||||
proto.utf8().get_data(),
|
||||
nullptr // Remote host, always nullptr as IGDs don't support it
|
||||
);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(i != UPNPCOMMAND_SUCCESS, UPNPMiniUPNP::upnp_result(i), "Couldn't delete port mapping.");
|
||||
|
||||
return UPNP::UPNP_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
void UPNPDeviceMiniUPNP::set_description_url(const String &url) {
|
||||
description_url = url;
|
||||
}
|
||||
|
||||
String UPNPDeviceMiniUPNP::get_description_url() const {
|
||||
return description_url;
|
||||
}
|
||||
|
||||
void UPNPDeviceMiniUPNP::set_service_type(const String &type) {
|
||||
service_type = type;
|
||||
}
|
||||
|
||||
String UPNPDeviceMiniUPNP::get_service_type() const {
|
||||
return service_type;
|
||||
}
|
||||
|
||||
void UPNPDeviceMiniUPNP::set_igd_control_url(const String &url) {
|
||||
igd_control_url = url;
|
||||
}
|
||||
|
||||
String UPNPDeviceMiniUPNP::get_igd_control_url() const {
|
||||
return igd_control_url;
|
||||
}
|
||||
|
||||
void UPNPDeviceMiniUPNP::set_igd_service_type(const String &type) {
|
||||
igd_service_type = type;
|
||||
}
|
||||
|
||||
String UPNPDeviceMiniUPNP::get_igd_service_type() const {
|
||||
return igd_service_type;
|
||||
}
|
||||
|
||||
void UPNPDeviceMiniUPNP::set_igd_our_addr(const String &addr) {
|
||||
igd_our_addr = addr;
|
||||
}
|
||||
|
||||
String UPNPDeviceMiniUPNP::get_igd_our_addr() const {
|
||||
return igd_our_addr;
|
||||
}
|
||||
|
||||
void UPNPDeviceMiniUPNP::set_igd_status(IGDStatus status) {
|
||||
igd_status = status;
|
||||
}
|
||||
|
||||
UPNPDeviceMiniUPNP::IGDStatus UPNPDeviceMiniUPNP::get_igd_status() const {
|
||||
return igd_status;
|
||||
}
|
||||
|
||||
bool UPNPDeviceMiniUPNP::is_valid_gateway() const {
|
||||
return igd_status == IGD_STATUS_OK;
|
||||
}
|
||||
|
||||
#endif // WEB_ENABLED
|
80
modules/upnp/upnp_device_miniupnp.h
Normal file
80
modules/upnp/upnp_device_miniupnp.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**************************************************************************/
|
||||
/* upnp_device_miniupnp.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef WEB_ENABLED
|
||||
|
||||
#include "upnp_device.h"
|
||||
|
||||
class UPNPDeviceMiniUPNP : public UPNPDevice {
|
||||
GDCLASS(UPNPDeviceMiniUPNP, UPNPDevice);
|
||||
|
||||
private:
|
||||
static UPNPDevice *_create(bool p_notify_postinitialize) { return static_cast<UPNPDevice *>(ClassDB::creator<UPNPDeviceMiniUPNP>(p_notify_postinitialize)); }
|
||||
|
||||
String description_url;
|
||||
String service_type;
|
||||
String igd_control_url;
|
||||
String igd_service_type;
|
||||
String igd_our_addr;
|
||||
IGDStatus igd_status = IGD_STATUS_UNKNOWN_ERROR;
|
||||
|
||||
public:
|
||||
static void make_default();
|
||||
|
||||
virtual void set_description_url(const String &url) override;
|
||||
virtual String get_description_url() const override;
|
||||
|
||||
virtual void set_service_type(const String &type) override;
|
||||
virtual String get_service_type() const override;
|
||||
|
||||
virtual void set_igd_control_url(const String &url) override;
|
||||
virtual String get_igd_control_url() const override;
|
||||
|
||||
virtual void set_igd_service_type(const String &type) override;
|
||||
virtual String get_igd_service_type() const override;
|
||||
|
||||
virtual void set_igd_our_addr(const String &addr) override;
|
||||
virtual String get_igd_our_addr() const override;
|
||||
|
||||
virtual void set_igd_status(IGDStatus status) override;
|
||||
virtual IGDStatus get_igd_status() const override;
|
||||
|
||||
virtual bool is_valid_gateway() const override;
|
||||
virtual String query_external_address() const override;
|
||||
virtual int add_port_mapping(int port, int port_internal = 0, String desc = "", String proto = "UDP", int duration = 0) const override;
|
||||
virtual int delete_port_mapping(int port, String proto = "UDP") const override;
|
||||
|
||||
UPNPDeviceMiniUPNP() {}
|
||||
virtual ~UPNPDeviceMiniUPNP() {}
|
||||
};
|
||||
|
||||
#endif // WEB_ENABLED
|
334
modules/upnp/upnp_miniupnp.cpp
Normal file
334
modules/upnp/upnp_miniupnp.cpp
Normal file
@@ -0,0 +1,334 @@
|
||||
/**************************************************************************/
|
||||
/* upnp_miniupnp.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef WEB_ENABLED
|
||||
|
||||
#include "upnp_miniupnp.h"
|
||||
|
||||
#include "upnp_device_miniupnp.h"
|
||||
|
||||
#include <miniupnpc/miniwget.h>
|
||||
#include <miniupnpc/upnpcommands.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
void UPNPMiniUPNP::make_default() {
|
||||
UPNP::_create = UPNPMiniUPNP::_create;
|
||||
}
|
||||
|
||||
bool UPNPMiniUPNP::is_common_device(const String &dev) const {
|
||||
return dev.is_empty() ||
|
||||
dev.contains("InternetGatewayDevice") ||
|
||||
dev.contains("WANIPConnection") ||
|
||||
dev.contains("WANPPPConnection") ||
|
||||
dev.contains("rootdevice");
|
||||
}
|
||||
|
||||
int UPNPMiniUPNP::discover(int timeout, int ttl, const String &device_filter) {
|
||||
ERR_FAIL_COND_V_MSG(timeout < 0, UPNP_RESULT_INVALID_PARAM, "The response's wait time can't be negative.");
|
||||
ERR_FAIL_COND_V_MSG(ttl < 0 || ttl > 255, UPNP_RESULT_INVALID_PARAM, "The time-to-live must be set between 0 and 255 (inclusive).");
|
||||
|
||||
devices.clear();
|
||||
|
||||
int error = 0;
|
||||
struct UPNPDev *devlist;
|
||||
|
||||
CharString cs = discover_multicast_if.utf8();
|
||||
const char *m_if = cs.length() ? cs.get_data() : nullptr;
|
||||
if (is_common_device(device_filter)) {
|
||||
devlist = upnpDiscover(timeout, m_if, nullptr, discover_local_port, discover_ipv6, ttl, &error);
|
||||
} else {
|
||||
devlist = upnpDiscoverAll(timeout, m_if, nullptr, discover_local_port, discover_ipv6, ttl, &error);
|
||||
}
|
||||
|
||||
if (error != UPNPDISCOVER_SUCCESS) {
|
||||
switch (error) {
|
||||
case UPNPDISCOVER_SOCKET_ERROR:
|
||||
return UPNP_RESULT_SOCKET_ERROR;
|
||||
case UPNPDISCOVER_MEMORY_ERROR:
|
||||
return UPNP_RESULT_MEM_ALLOC_ERROR;
|
||||
default:
|
||||
return UPNP_RESULT_UNKNOWN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (!devlist) {
|
||||
return UPNP_RESULT_NO_DEVICES;
|
||||
}
|
||||
|
||||
struct UPNPDev *dev = devlist;
|
||||
|
||||
while (dev) {
|
||||
if (device_filter.is_empty() || strstr(dev->st, device_filter.utf8().get_data())) {
|
||||
add_device_to_list(dev, devlist);
|
||||
}
|
||||
|
||||
dev = dev->pNext;
|
||||
}
|
||||
|
||||
freeUPNPDevlist(devlist);
|
||||
|
||||
return UPNP_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
void UPNPMiniUPNP::add_device_to_list(UPNPDev *dev, UPNPDev *devlist) {
|
||||
Ref<UPNPDeviceMiniUPNP> new_device;
|
||||
new_device.instantiate();
|
||||
|
||||
new_device->set_description_url(dev->descURL);
|
||||
new_device->set_service_type(dev->st);
|
||||
|
||||
parse_igd(new_device, devlist);
|
||||
|
||||
devices.push_back(new_device);
|
||||
}
|
||||
|
||||
char *UPNPMiniUPNP::load_description(const String &url, int *size, int *status_code) const {
|
||||
return (char *)miniwget(url.utf8().get_data(), size, 0, status_code);
|
||||
}
|
||||
|
||||
void UPNPMiniUPNP::parse_igd(Ref<UPNPDevice> dev, UPNPDev *devlist) {
|
||||
int size = 0;
|
||||
int status_code = -1;
|
||||
char *xml = load_description(dev->get_description_url(), &size, &status_code);
|
||||
|
||||
if (status_code != 200) {
|
||||
dev->set_igd_status(UPNPDevice::IGD_STATUS_HTTP_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!xml || size < 1) {
|
||||
dev->set_igd_status(UPNPDevice::IGD_STATUS_HTTP_EMPTY);
|
||||
return;
|
||||
}
|
||||
|
||||
struct UPNPUrls urls = {};
|
||||
struct IGDdatas data;
|
||||
|
||||
parserootdesc(xml, size, &data);
|
||||
free(xml);
|
||||
xml = nullptr;
|
||||
|
||||
GetUPNPUrls(&urls, &data, dev->get_description_url().utf8().get_data(), 0);
|
||||
|
||||
char addr[16];
|
||||
#if MINIUPNPC_API_VERSION >= 18
|
||||
int i = UPNP_GetValidIGD(devlist, &urls, &data, (char *)&addr, 16, nullptr, 0);
|
||||
#else
|
||||
int i = UPNP_GetValidIGD(devlist, &urls, &data, (char *)&addr, 16);
|
||||
#endif
|
||||
|
||||
if (i != 1) {
|
||||
FreeUPNPUrls(&urls);
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
dev->set_igd_status(UPNPDevice::IGD_STATUS_NO_IGD);
|
||||
return;
|
||||
case 2:
|
||||
dev->set_igd_status(UPNPDevice::IGD_STATUS_DISCONNECTED);
|
||||
return;
|
||||
case 3:
|
||||
dev->set_igd_status(UPNPDevice::IGD_STATUS_UNKNOWN_DEVICE);
|
||||
return;
|
||||
default:
|
||||
dev->set_igd_status(UPNPDevice::IGD_STATUS_UNKNOWN_ERROR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (urls.controlURL[0] == '\0') {
|
||||
FreeUPNPUrls(&urls);
|
||||
dev->set_igd_status(UPNPDevice::IGD_STATUS_INVALID_CONTROL);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int UPNPMiniUPNP::upnp_result(int in) {
|
||||
switch (in) {
|
||||
case UPNPCOMMAND_SUCCESS:
|
||||
return UPNP_RESULT_SUCCESS;
|
||||
case UPNPCOMMAND_UNKNOWN_ERROR:
|
||||
return UPNP_RESULT_UNKNOWN_ERROR;
|
||||
case UPNPCOMMAND_INVALID_ARGS:
|
||||
return UPNP_RESULT_INVALID_ARGS;
|
||||
case UPNPCOMMAND_HTTP_ERROR:
|
||||
return UPNP_RESULT_HTTP_ERROR;
|
||||
case UPNPCOMMAND_INVALID_RESPONSE:
|
||||
return UPNP_RESULT_INVALID_RESPONSE;
|
||||
case UPNPCOMMAND_MEM_ALLOC_ERROR:
|
||||
return UPNP_RESULT_MEM_ALLOC_ERROR;
|
||||
|
||||
case 402:
|
||||
return UPNP_RESULT_INVALID_ARGS;
|
||||
case 403:
|
||||
return UPNP_RESULT_NOT_AUTHORIZED;
|
||||
case 501:
|
||||
return UPNP_RESULT_ACTION_FAILED;
|
||||
case 606:
|
||||
return UPNP_RESULT_NOT_AUTHORIZED;
|
||||
case 714:
|
||||
return UPNP_RESULT_NO_SUCH_ENTRY_IN_ARRAY;
|
||||
case 715:
|
||||
return UPNP_RESULT_SRC_IP_WILDCARD_NOT_PERMITTED;
|
||||
case 716:
|
||||
return UPNP_RESULT_EXT_PORT_WILDCARD_NOT_PERMITTED;
|
||||
case 718:
|
||||
return UPNP_RESULT_CONFLICT_WITH_OTHER_MAPPING;
|
||||
case 724:
|
||||
return UPNP_RESULT_SAME_PORT_VALUES_REQUIRED;
|
||||
case 725:
|
||||
return UPNP_RESULT_ONLY_PERMANENT_LEASE_SUPPORTED;
|
||||
case 726:
|
||||
return UPNP_RESULT_REMOTE_HOST_MUST_BE_WILDCARD;
|
||||
case 727:
|
||||
return UPNP_RESULT_EXT_PORT_MUST_BE_WILDCARD;
|
||||
case 728:
|
||||
return UPNP_RESULT_NO_PORT_MAPS_AVAILABLE;
|
||||
case 729:
|
||||
return UPNP_RESULT_CONFLICT_WITH_OTHER_MECHANISM;
|
||||
case 732:
|
||||
return UPNP_RESULT_INT_PORT_WILDCARD_NOT_PERMITTED;
|
||||
case 733:
|
||||
return UPNP_RESULT_INCONSISTENT_PARAMETERS;
|
||||
}
|
||||
|
||||
return UPNP_RESULT_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
int UPNPMiniUPNP::get_device_count() const {
|
||||
return devices.size();
|
||||
}
|
||||
|
||||
Ref<UPNPDevice> UPNPMiniUPNP::get_device(int index) const {
|
||||
ERR_FAIL_INDEX_V(index, devices.size(), nullptr);
|
||||
|
||||
return devices.get(index);
|
||||
}
|
||||
|
||||
void UPNPMiniUPNP::add_device(Ref<UPNPDevice> device) {
|
||||
ERR_FAIL_COND(device.is_null());
|
||||
|
||||
devices.push_back(device);
|
||||
}
|
||||
|
||||
void UPNPMiniUPNP::set_device(int index, Ref<UPNPDevice> device) {
|
||||
ERR_FAIL_INDEX(index, devices.size());
|
||||
ERR_FAIL_COND(device.is_null());
|
||||
|
||||
devices.set(index, device);
|
||||
}
|
||||
|
||||
void UPNPMiniUPNP::remove_device(int index) {
|
||||
ERR_FAIL_INDEX(index, devices.size());
|
||||
|
||||
devices.remove_at(index);
|
||||
}
|
||||
|
||||
void UPNPMiniUPNP::clear_devices() {
|
||||
devices.clear();
|
||||
}
|
||||
|
||||
Ref<UPNPDevice> UPNPMiniUPNP::get_gateway() const {
|
||||
ERR_FAIL_COND_V_MSG(devices.is_empty(), nullptr, "Couldn't find any UPNPDevices.");
|
||||
|
||||
for (int i = 0; i < devices.size(); i++) {
|
||||
Ref<UPNPDevice> dev = get_device(i);
|
||||
|
||||
if (dev.is_valid() && dev->is_valid_gateway()) {
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UPNPMiniUPNP::set_discover_multicast_if(const String &m_if) {
|
||||
discover_multicast_if = m_if;
|
||||
}
|
||||
|
||||
String UPNPMiniUPNP::get_discover_multicast_if() const {
|
||||
return discover_multicast_if;
|
||||
}
|
||||
|
||||
void UPNPMiniUPNP::set_discover_local_port(int port) {
|
||||
discover_local_port = port;
|
||||
}
|
||||
|
||||
int UPNPMiniUPNP::get_discover_local_port() const {
|
||||
return discover_local_port;
|
||||
}
|
||||
|
||||
void UPNPMiniUPNP::set_discover_ipv6(bool ipv6) {
|
||||
discover_ipv6 = ipv6;
|
||||
}
|
||||
|
||||
bool UPNPMiniUPNP::is_discover_ipv6() const {
|
||||
return discover_ipv6;
|
||||
}
|
||||
|
||||
String UPNPMiniUPNP::query_external_address() const {
|
||||
Ref<UPNPDevice> dev = get_gateway();
|
||||
|
||||
if (dev.is_null()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return dev->query_external_address();
|
||||
}
|
||||
|
||||
int UPNPMiniUPNP::add_port_mapping(int port, int port_internal, String desc, String proto, int duration) const {
|
||||
Ref<UPNPDevice> dev = get_gateway();
|
||||
|
||||
if (dev.is_null()) {
|
||||
return UPNP_RESULT_NO_GATEWAY;
|
||||
}
|
||||
|
||||
return dev->add_port_mapping(port, port_internal, desc, proto, duration);
|
||||
}
|
||||
|
||||
int UPNPMiniUPNP::delete_port_mapping(int port, String proto) const {
|
||||
Ref<UPNPDevice> dev = get_gateway();
|
||||
|
||||
if (dev.is_null()) {
|
||||
return UPNP_RESULT_NO_GATEWAY;
|
||||
}
|
||||
|
||||
return dev->delete_port_mapping(port, proto);
|
||||
}
|
||||
|
||||
#endif // WEB_ENABLED
|
90
modules/upnp/upnp_miniupnp.h
Normal file
90
modules/upnp/upnp_miniupnp.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/**************************************************************************/
|
||||
/* upnp_miniupnp.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef WEB_ENABLED
|
||||
|
||||
#include "upnp.h"
|
||||
|
||||
#include <miniupnpc/miniupnpc.h>
|
||||
|
||||
class UPNPMiniUPNP : public UPNP {
|
||||
GDCLASS(UPNPMiniUPNP, UPNP);
|
||||
|
||||
private:
|
||||
static UPNP *_create(bool p_notify_postinitialize) { return static_cast<UPNP *>(ClassDB::creator<UPNPMiniUPNP>(p_notify_postinitialize)); }
|
||||
|
||||
String discover_multicast_if = "";
|
||||
int discover_local_port = 0;
|
||||
bool discover_ipv6 = false;
|
||||
|
||||
Vector<Ref<UPNPDevice>> devices;
|
||||
|
||||
bool is_common_device(const String &dev) const;
|
||||
void add_device_to_list(UPNPDev *dev, UPNPDev *devlist);
|
||||
void parse_igd(Ref<UPNPDevice> dev, UPNPDev *devlist);
|
||||
char *load_description(const String &url, int *size, int *status_code) const;
|
||||
|
||||
public:
|
||||
static void make_default();
|
||||
|
||||
static int upnp_result(int in);
|
||||
|
||||
virtual int get_device_count() const override;
|
||||
virtual Ref<UPNPDevice> get_device(int index) const override;
|
||||
virtual void add_device(Ref<UPNPDevice> device) override;
|
||||
virtual void set_device(int index, Ref<UPNPDevice> device) override;
|
||||
virtual void remove_device(int index) override;
|
||||
virtual void clear_devices() override;
|
||||
|
||||
virtual Ref<UPNPDevice> get_gateway() const override;
|
||||
|
||||
virtual int discover(int timeout = 2000, int ttl = 2, const String &device_filter = "InternetGatewayDevice") override;
|
||||
|
||||
virtual String query_external_address() const override;
|
||||
|
||||
virtual int add_port_mapping(int port, int port_internal = 0, String desc = "", String proto = "UDP", int duration = 0) const override;
|
||||
virtual int delete_port_mapping(int port, String proto = "UDP") const override;
|
||||
|
||||
virtual void set_discover_multicast_if(const String &m_if) override;
|
||||
virtual String get_discover_multicast_if() const override;
|
||||
|
||||
virtual void set_discover_local_port(int port) override;
|
||||
virtual int get_discover_local_port() const override;
|
||||
|
||||
virtual void set_discover_ipv6(bool ipv6) override;
|
||||
virtual bool is_discover_ipv6() const override;
|
||||
|
||||
UPNPMiniUPNP() {}
|
||||
virtual ~UPNPMiniUPNP() {}
|
||||
};
|
||||
|
||||
#endif // WEB_ENABLED
|
Reference in New Issue
Block a user