MXVK Vulkan Framework 0.35.0
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
space::PortMapping Class Reference

Owns an automatically created UPnP or NAT-PMP port mapping. More...

#include <examples/asteroids-net/port_mapping.hpp>

Public Member Functions

void open (const std::string &port)
 Attempts to expose a local UDP port through the router.
PortMapping & operator= (const PortMapping &)=delete
 PortMapping ()=default
 Creates an inactive port mapping.
 PortMapping (const PortMapping &)=delete
const std::string & status () const
 Returns a human-readable description of the mapping result.
 ~PortMapping ()
 Removes the active mapping, if one was created.

Detailed Description

Owns an automatically created UPnP or NAT-PMP port mapping.

Destroying the object removes any mapping successfully created by open().

Definition at line 20 of file port_mapping.hpp.

Constructor & Destructor Documentation

◆ PortMapping() [1/2]

space::PortMapping::PortMapping ( )
default

Creates an inactive port mapping.

◆ ~PortMapping()

space::PortMapping::~PortMapping ( )

Removes the active mapping, if one was created.

Definition at line 72 of file port_mapping.cpp.

72 {
73 if (private_port == 0 || public_port == 0)
74 return;
75 const std::string port = std::to_string(public_port);
76#if defined(ASTEROIDS_NET_HAS_MINIUPNPC)
77 if (method == Method::Upnp) {
78 int error = 0;
79 UPNPDev *devices = upnpDiscover(1000, nullptr, nullptr, 0, 0, 2, &error);
80 UPNPUrls urls{};
81 IGDdatas data{};
82 char local_address[64]{};
83 char external_address[64]{};
84 if (devices != nullptr && get_valid_igd(devices, urls, data, local_address, sizeof(local_address), external_address, sizeof(external_address)) > 0) {
85 UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "UDP", nullptr);
86 FreeUPNPUrls(&urls);
87 }
88 if (devices != nullptr)
89 freeUPNPDevlist(devices);
90 return;
91 }
92#endif
93#if defined(ASTEROIDS_NET_HAS_NATPMP)
94 if (method == Method::NatPmp) {
95 natpmp_t natpmp{};
96 if (initnatpmp(&natpmp, 0, 0) >= 0) {
97 sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_UDP, private_port, public_port, 0);
98 natpmpresp_t response{};
99 wait_for_natpmp(natpmp, response);
100 closenatpmp(&natpmp);
101 }
102 }
103#endif
104 }

◆ PortMapping() [2/2]

space::PortMapping::PortMapping ( const PortMapping & )
delete

Member Function Documentation

◆ open()

void space::PortMapping::open ( const std::string & port)

Attempts to expose a local UDP port through the router.

Parameters
portDecimal UDP port number to map.

Definition at line 106 of file port_mapping.cpp.

106 {
107 if (!parse_port(port_text, private_port)) {
108 private_port = 0;
109 status_message = "Invalid port; automatic router mapping skipped.";
110 return;
111 }
112 public_port = private_port;
113 const std::string port = std::to_string(private_port);
114 std::string upnp_failure = "UPnP support was not built";
115 std::string natpmp_failure = "NAT-PMP support was not built";
116
117#if defined(ASTEROIDS_NET_HAS_MINIUPNPC)
118 int error = 0;
119 UPNPDev *devices = upnpDiscover(1500, nullptr, nullptr, 0, 0, 2, &error);
120 UPNPUrls urls{};
121 IGDdatas data{};
122 char local_address[64]{};
123 char external_address[64]{};
124 const int igd_result = devices == nullptr ? 0 : get_valid_igd(devices, urls, data, local_address, sizeof(local_address), external_address, sizeof(external_address));
125 if (igd_result > 0) {
126 const int result = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), local_address, "asteroids-net", "UDP", nullptr, std::to_string(MAPPING_LIFETIME_SECONDS).c_str());
127 if (result == UPNPCOMMAND_SUCCESS) {
128 if (external_address[0] == '\0')
129 UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, external_address);
130 method = Method::Upnp;
131 status_message = std::string("UPnP mapped UDP ") + port;
132 if (external_address[0] != '\0')
133 status_message += std::string(" at ") + external_address + ":" + port;
134 status_message += "; waiting for players...";
135 FreeUPNPUrls(&urls);
136 freeUPNPDevlist(devices);
137 return;
138 }
139 upnp_failure = std::string("UPnP mapping failed: ") + strupnperror(result);
140 FreeUPNPUrls(&urls);
141 } else if (devices == nullptr) {
142 upnp_failure = "no UPnP devices responded";
143 } else {
144 upnp_failure = "no valid UPnP internet gateway";
145 }
146 if (devices != nullptr)
147 freeUPNPDevlist(devices);
148#endif
149
150#if defined(ASTEROIDS_NET_HAS_NATPMP)
151 natpmp_t natpmp{};
152 const int init_result = initnatpmp(&natpmp, 0, 0);
153 if (init_result >= 0) {
154 const int sent = sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_UDP, private_port, public_port, MAPPING_LIFETIME_SECONDS);
155 natpmpresp_t response{};
156 const int response_result = sent < 0 ? sent : wait_for_natpmp(natpmp, response);
157 if (response_result >= 0) {
158 public_port = response.pnu.newportmapping.mappedpublicport;
159 method = Method::NatPmp;
160 status_message = "NAT-PMP mapped UDP " + std::to_string(public_port) + "; waiting for players...";
161 closenatpmp(&natpmp);
162 return;
163 }
164 natpmp_failure = natpmp_error(response_result);
165 closenatpmp(&natpmp);
166 } else {
167 natpmp_failure = natpmp_error(init_result);
168 }
169#endif
170
171 private_port = 0;
172 public_port = 0;
173 status_message = upnp_failure + "; " + natpmp_failure + ". Forward UDP " + port + " manually.";
174 }
bool parse_port(const std::string &text, std::uint16_t &port)

◆ operator=()

PortMapping & space::PortMapping::operator= ( const PortMapping & )
delete

◆ status()

const std::string & space::PortMapping::status ( ) const
nodiscard

Returns a human-readable description of the mapping result.

Definition at line 176 of file port_mapping.cpp.

176{ return status_message; }

The documentation for this class was generated from the following files: