UPNP
Universal Plug and Play (UPnP) functions for network device discovery, querying and port forwarding.
UPNP.swift:34class UPNP
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 7777
, note both discover(timeout:ttl:deviceFilter:)
and addPortMapping(port:portInternal:desc:proto:duration:)
can return errors that should be checked):
To close a specific port (e.g. after you have finished using it):
Terminology: 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”.
Pitfalls:
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).
Further reading: If you want to know more about UPnP (and the Internet Gateway Device (IGD) and Port Control Protocol (PCP) specifically), Wikipedia is a good first stop, the specification can be found at the Open Connectivity Foundation and Godot’s implementation is based on the MiniUPnP client.
Superclasses
class RefCounted
Base class for reference-counted objects.
Citizens in SwiftGodot
Conformances
protocol CustomStringConvertible
A type with a customized textual representation.
protocol Equatable
A type that can be compared for value equality.
protocol Hashable
A type that can be hashed into a
Hasher
to produce an integer hash value.protocol Identifiable<ID>
A class of types whose instances hold the value of an entity with stable identity.
protocol VariantRepresentable
Types that conform to VariantRepresentable can be stored directly in
Variant
with no conversion. These include all of the Variant types from Godot (for exampleGString
,Rect
,Plane
), Godot objects (those that subclass SwiftGodot.Object) as well as the built-in Swift types UInt8, Int64 and Double.protocol VariantStorable
Types that conform to VariantStorable can be stored in a Variant and can be extracted back out of a Variant.
Types
Type members
Instance members
var discoverIpv6: Bool
If
true
, IPv6 is used forUPNPDevice
discovery.var discoverLocalPort: Int32
If
0
, the local port to use for discovery is chosen automatically by the system. If1
, discovery will be done from the source port 1900 (same as destination port). Otherwise, the value will be used as the port.var discoverMulticastIf: String
Multicast interface to use for discovery. Uses the default multicast interface if empty.
func addDevice(UPNPDevice?
) Adds the given
UPNPDevice
to the list of discovered devices.func addPortMapping(port: Int32, portInternal: Int32, desc: String, proto: String, duration: Int32
) -> Int32 Adds a mapping to forward the external
port
(between 1 and 65535, although recommended to use port 1024 or above) on the default gateway (seegetGateway
) to theportInternal
on the local machine for the given protocolproto
(either"TCP"
or"UDP"
, 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 withgetGateway
and calladdPortMapping(port:portInternal:desc:proto:duration:)
on it, if any. Note that forwarding a well-known port (below 1024) with UPnP may fail depending on the device.func clearDevices(
) Clears the list of discovered devices.
func deletePortMapping(port: Int32, proto: String
) -> Int32 Deletes the port mapping for the given port and protocol combination on the default gateway (see
getGateway
) if one exists.port
must be a valid port between 1 and 65535,proto
can be either"TCP"
or"UDP"
. 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. SeeUPNPResult
for possible return values.func discover(timeout: Int32, ttl: Int32, deviceFilter: String
) -> Int32 Discovers local
UPNPDevice
s. Clears the list of previously discovered devices.func getDevice(index: Int32
) -> UPNPDevice? Returns the
UPNPDevice
at the givenindex
.func getDeviceCount(
) -> Int32 Returns the number of discovered
UPNPDevice
s.func getGateway(
) -> UPNPDevice? Returns the default gateway. That is the first discovered
UPNPDevice
that is also a valid IGD (InternetGatewayDevice).func queryExternalAddress(
) -> String Returns the external
IP
address of the default gateway (seegetGateway
) as string. Returns an empty string on error.func removeDevice(index: Int32
) Removes the device at
index
from the list of discovered devices.func setDevice(index: Int32, device: UPNPDevice?
) Sets the device at
index
from the list of discovered devices todevice
.