From a44f5bbf78855387d9700cc4c0d2a3312cfabe32 Mon Sep 17 00:00:00 2001 From: Autechre Date: Sat, 4 Dec 2021 15:45:29 +0100 Subject: [PATCH] Fix UPNP port mapping failed error - switch to a permanent lease time, (#13324) but request it to be removed when we do netplay_free --- libretro-common/include/net/net_natt.h | 10 +++ libretro-common/net/net_natt.c | 84 ++++++++++++++++++-------- network/netplay/netplay_frontend.c | 2 +- tasks/task_netplay_nat_traversal.c | 25 ++++++++ tasks/tasks_internal.h | 1 + 5 files changed, 95 insertions(+), 27 deletions(-) diff --git a/libretro-common/include/net/net_natt.h b/libretro-common/include/net/net_natt.h index 8634dc3e73..724febee56 100644 --- a/libretro-common/include/net/net_natt.h +++ b/libretro-common/include/net/net_natt.h @@ -65,6 +65,11 @@ struct natt_status void natt_init(struct natt_status *status, uint16_t port, enum socket_protocol proto); +/** + * Uninitialize global NAT traversal structures */ +void natt_deinit(struct natt_status *status, + enum socket_protocol proto); + /** Initialize a NAT traversal status object */ bool natt_new(struct natt_status *status); @@ -77,6 +82,11 @@ void natt_free(struct natt_status *status); bool natt_open_port_any(struct natt_status *status, uint16_t port, enum socket_protocol proto); +/** + * Request for a port forwarding to be removed/closed. */ +bool natt_close_port(struct natt_status *status, + enum socket_protocol proto); + /** Check for port forwarding responses */ bool natt_read(struct natt_status *status); diff --git a/libretro-common/net/net_natt.c b/libretro-common/net/net_natt.c index a345af98dc..e2254027ac 100644 --- a/libretro-common/net/net_natt.c +++ b/libretro-common/net/net_natt.c @@ -94,13 +94,29 @@ end: #endif } +void natt_deinit(struct natt_status *status, + enum socket_protocol proto) +{ +#if !defined(HAVE_SOCKET_LEGACY) && HAVE_MINIUPNPC + natt_close_port(status, proto); + natt_free(status); + + memset(&urls, 0, sizeof(urls)); + memset(&data, 0, sizeof(data)); +#endif +} + bool natt_new(struct natt_status *status) { memset(status, 0, sizeof(struct natt_status)); return true; } -void natt_free(struct natt_status *status) { } +void natt_free(struct natt_status *status) +{ + /* Invalidate the state */ + memset(status, 0, sizeof(*status)); +} static bool natt_open_port(struct natt_status *status, struct sockaddr *addr, socklen_t addrlen, enum socket_protocol proto) @@ -129,7 +145,7 @@ static bool natt_open_port(struct natt_status *status, r = UPNP_AddAnyPortMapping(urls.controlURL, data.first.servicetype, port_str, port_str, host, "retroarch", - proto_str, NULL, "3600", ext_port_str); + proto_str, NULL, "0", ext_port_str); if (r != 0) { @@ -138,7 +154,7 @@ static bool natt_open_port(struct natt_status *status, r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port_str, port_str, host, "retroarch", - proto_str, NULL, "3600"); + proto_str, NULL, "0"); } if (r != 0) return false; @@ -231,32 +247,48 @@ bool natt_open_port_any(struct natt_status *status, #endif } +bool natt_close_port(struct natt_status *status, + enum socket_protocol proto) +{ +#if !defined(HAVE_SOCKET_LEGACY) && HAVE_MINIUPNPC + const struct sockaddr *addr; + socklen_t addrlen; + char port_str[6]; + const char *proto_str = (proto == SOCKET_PROTOCOL_UDP) ? + "UDP" : "TCP"; + + if (!status) + return false; + + if (string_is_empty(urls.controlURL)) + return false; + + /* Grab our external port */ + if (status->have_inet4) + { + addr = (struct sockaddr *) &status->ext_inet4_addr; + addrlen = sizeof(status->ext_inet4_addr); + } + else if (status->have_inet6) + { + addr = (struct sockaddr *) &status->ext_inet6_addr; + addrlen = sizeof(status->ext_inet6_addr); + } + else + return false; + if (getnameinfo(addr, addrlen, NULL, 0, + port_str, sizeof(port_str), NI_NUMERICSERV)) + return false; + + /* Request the device to remove our port forwarding. */ + return !UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, + port_str, proto_str, NULL); +#endif +} + bool natt_read(struct natt_status *status) { /* MiniUPNPC is always synchronous, so there's nothing to read here. * Reserved for future backends. */ return false; } - -#if 0 -/* If we want to remove redirects in the future, this is a - * sample of how to do that. */ - -void upnp_rem_redir (int port) -{ - int t; - char port_str[16]; - - printf("TB : upnp_rem_redir (%d)\n", port); - - if(urls.controlURL[0] == '\0') - { - printf("TB : the init was not done !\n"); - return; - } - - snprintf(port_str, sizeof(port_str), "%d", port); - UPNP_DeletePortMapping(urls.controlURL, - data.first.servicetype, port_str, "TCP", NULL); -} -#endif diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 85f64f08b7..7e88fb9788 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -6116,7 +6116,7 @@ void netplay_free(netplay_t *netplay) free(netplay->connections); if (netplay->nat_traversal) - natt_free(&netplay->nat_traversal_state); + task_push_netplay_nat_close(&netplay->nat_traversal_state); if (netplay->buffer) { diff --git a/tasks/task_netplay_nat_traversal.c b/tasks/task_netplay_nat_traversal.c index 790702d46c..62591e559b 100644 --- a/tasks/task_netplay_nat_traversal.c +++ b/tasks/task_netplay_nat_traversal.c @@ -84,6 +84,31 @@ bool task_push_netplay_nat_traversal(void *nat_traversal_state, uint16_t port) return true; } + +static void task_netplay_nat_close_handler(retro_task_t *task) +{ + natt_deinit((struct natt_status *) task->task_data, + SOCKET_PROTOCOL_TCP); + + task_set_progress(task, 100); + task_set_finished(task, true); +} + +bool task_push_netplay_nat_close(void *nat_traversal_state) +{ + retro_task_t *task = task_init(); + + if (!task) + return false; + + task->handler = task_netplay_nat_close_handler; + task->task_data = nat_traversal_state; + + task_queue_push(task); + + return true; +} #else bool task_push_netplay_nat_traversal(void *nat_traversal_state, uint16_t port) { return false; } +bool task_push_netplay_nat_close(void *nat_traversal_state) { return false; } #endif diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index 983f03ad28..d98d7be2e4 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -87,6 +87,7 @@ bool task_push_netplay_crc_scan(uint32_t crc, char* name, const char *hostname, const char *corename, const char* subsystem); bool task_push_netplay_nat_traversal(void *nat_traversal_state, uint16_t port); +bool task_push_netplay_nat_close(void *nat_traversal_state); /* Core updater tasks */