MXVK Vulkan Framework 0.24.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.
PortMappingoperator= (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 75 of file port_mapping.cpp.

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

◆ 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 110 of file port_mapping.cpp.

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

185{ return status_message; }

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