Skip to content

Commit 28acffd

Browse files
committed
net: Add NAT-PMP to port mapping loop
1 parent a8d9f27 commit 28acffd

File tree

1 file changed

+53
-7
lines changed

1 file changed

+53
-7
lines changed

src/mapport.cpp

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed"
4040
#if defined(USE_NATPMP) || defined(USE_UPNP)
4141
static CThreadInterrupt g_mapport_interrupt;
4242
static std::thread g_mapport_thread;
43-
static std::atomic_uint g_mapport_target_proto{MapPortProtoFlag::NONE};
43+
static std::atomic_uint g_mapport_enabled_protos{MapPortProtoFlag::NONE};
44+
static std::atomic<MapPortProtoFlag> g_mapport_current_proto{MapPortProtoFlag::NONE};
4445

4546
using namespace std::chrono_literals;
4647
static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD{20min};
@@ -220,9 +221,34 @@ static bool ProcessUpnp()
220221

221222
static void ThreadMapPort()
222223
{
224+
bool ok;
223225
do {
224-
if (ProcessUpnp()) return;
225-
} while (g_mapport_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD));
226+
ok = false;
227+
228+
#ifdef USE_UPNP
229+
// High priority protocol.
230+
if (g_mapport_enabled_protos & MapPortProtoFlag::UPNP) {
231+
g_mapport_current_proto = MapPortProtoFlag::UPNP;
232+
ok = ProcessUpnp();
233+
if (ok) continue;
234+
}
235+
#endif // USE_UPNP
236+
237+
#ifdef USE_NATPMP
238+
// Low priority protocol.
239+
if (g_mapport_enabled_protos & MapPortProtoFlag::NAT_PMP) {
240+
g_mapport_current_proto = MapPortProtoFlag::NAT_PMP;
241+
ok = ProcessNatpmp();
242+
if (ok) continue;
243+
}
244+
#endif // USE_NATPMP
245+
246+
g_mapport_current_proto = MapPortProtoFlag::NONE;
247+
if (g_mapport_enabled_protos == MapPortProtoFlag::NONE) {
248+
return;
249+
}
250+
251+
} while (ok || g_mapport_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD));
226252
}
227253

228254
void StartThreadMapPort()
@@ -235,20 +261,39 @@ void StartThreadMapPort()
235261

236262
static void DispatchMapPort()
237263
{
238-
if (g_mapport_target_proto == MapPortProtoFlag::UPNP) {
264+
if (g_mapport_current_proto == MapPortProtoFlag::NONE && g_mapport_enabled_protos == MapPortProtoFlag::NONE) {
265+
return;
266+
}
267+
268+
if (g_mapport_current_proto == MapPortProtoFlag::NONE && g_mapport_enabled_protos != MapPortProtoFlag::NONE) {
239269
StartThreadMapPort();
240-
} else {
270+
return;
271+
}
272+
273+
if (g_mapport_current_proto != MapPortProtoFlag::NONE && g_mapport_enabled_protos == MapPortProtoFlag::NONE) {
241274
InterruptMapPort();
242275
StopMapPort();
276+
return;
277+
}
278+
279+
if (g_mapport_enabled_protos & g_mapport_current_proto) {
280+
// Enabling another protocol does not cause switching from the currently used one.
281+
return;
243282
}
283+
284+
assert(g_mapport_thread.joinable());
285+
assert(!g_mapport_interrupt);
286+
// Interrupt a protocol-specific loop in the ThreadUpnp() or in the ThreadNatpmp()
287+
// to force trying the next protocol in the ThreadMapPort() loop.
288+
g_mapport_interrupt();
244289
}
245290

246291
static void MapPortProtoSetEnabled(MapPortProtoFlag proto, bool enabled)
247292
{
248293
if (enabled) {
249-
g_mapport_target_proto |= proto;
294+
g_mapport_enabled_protos |= proto;
250295
} else {
251-
g_mapport_target_proto &= ~proto;
296+
g_mapport_enabled_protos &= ~proto;
252297
}
253298
}
254299

@@ -260,6 +305,7 @@ void StartMapPort(bool use_upnp)
260305

261306
void InterruptMapPort()
262307
{
308+
g_mapport_enabled_protos = MapPortProtoFlag::NONE;
263309
if (g_mapport_thread.joinable()) {
264310
g_mapport_interrupt();
265311
}

0 commit comments

Comments
 (0)