From 5f723d1bda9da81f960008bf7c31431aa3cd43c8 Mon Sep 17 00:00:00 2001 From: Gregor Richards <hg-yff@gregor.im> Date: Mon, 20 Feb 2017 19:08:31 -0500 Subject: [PATCH] Moving NAT traversal into a task to avoid blocking the UI. --- Makefile.common | 1 + griffin/griffin.c | 1 + network/netplay/netplay.h | 3 +- network/netplay/netplay_frontend.c | 3 ++ network/netplay/netplay_io.c | 17 ++---- tasks/task_netplay_nat_traversal.c | 87 ++++++++++++++++++++++++++++++ tasks/tasks_internal.h | 4 ++ 7 files changed, 101 insertions(+), 15 deletions(-) create mode 100644 tasks/task_netplay_nat_traversal.c diff --git a/Makefile.common b/Makefile.common index 91054f6a17..9ed9d260c1 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1165,6 +1165,7 @@ ifeq ($(HAVE_NETWORKING), 1) network/net_http_special.o \ tasks/task_http.o \ tasks/task_netplay_lan_scan.o \ + tasks/task_netplay_nat_traversal.o \ tasks/task_wifi.o \ tasks/task_netplay_find_content.o diff --git a/griffin/griffin.c b/griffin/griffin.c index 7c8dc2e1e2..85ea85804b 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -911,6 +911,7 @@ NETPLAY #endif #include "../tasks/task_http.c" #include "../tasks/task_netplay_lan_scan.c" +#include "../tasks/task_netplay_nat_traversal.c" #include "../tasks/task_wifi.c" #include "../tasks/task_netplay_find_content.c" #endif diff --git a/network/netplay/netplay.h b/network/netplay/netplay.h index d873e62e99..8b72bfc50b 100644 --- a/network/netplay/netplay.h +++ b/network/netplay/netplay.h @@ -45,7 +45,8 @@ enum rarch_netplay_ctl_state RARCH_NETPLAY_CTL_UNPAUSE, RARCH_NETPLAY_CTL_LOAD_SAVESTATE, RARCH_NETPLAY_CTL_RESET, - RARCH_NETPLAY_CTL_DISCONNECT + RARCH_NETPLAY_CTL_DISCONNECT, + RARCH_NETPLAY_CTL_FINISHED_NAT_TRAVERSAL }; int16_t input_state_net(unsigned port, unsigned device, diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index e02332fed0..83a9671b20 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -1197,6 +1197,9 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data) case RARCH_NETPLAY_CTL_DISCONNECT: ret = netplay_disconnect(netplay_data); goto done; + case RARCH_NETPLAY_CTL_FINISHED_NAT_TRAVERSAL: + netplay_announce_nat_traversal(netplay_data); + goto done; default: case RARCH_NETPLAY_CTL_NONE: ret = false; diff --git a/network/netplay/netplay_io.c b/network/netplay/netplay_io.c index 4de8e02375..1e7c51f3be 100644 --- a/network/netplay/netplay_io.c +++ b/network/netplay/netplay_io.c @@ -25,6 +25,7 @@ #include "netplay_private.h" #include "../../runloop.h" +#include "../../tasks/tasks_internal.h" #if 0 #define DEBUG_NETPLAY_STEPS 1 @@ -1430,18 +1431,6 @@ void netplay_announce_nat_traversal(netplay_t *netplay) */ void netplay_init_nat_traversal(netplay_t *netplay) { - natt_init(); - - if (!natt_new(&netplay->nat_traversal_state)) - { - netplay->nat_traversal = false; - return; - } - - natt_open_port_any(&netplay->nat_traversal_state, netplay->tcp_port, SOCKET_PROTOCOL_TCP); - -#ifndef HAVE_SOCKET_LEGACY - if (!netplay->nat_traversal_state.request_outstanding) - netplay_announce_nat_traversal(netplay); -#endif + memset(&netplay->nat_traversal_state, 0, sizeof(netplay->nat_traversal_state)); + task_push_netplay_nat_traversal(&netplay->nat_traversal_state, netplay->tcp_port); } diff --git a/tasks/task_netplay_nat_traversal.c b/tasks/task_netplay_nat_traversal.c new file mode 100644 index 0000000000..d0dbc3ffae --- /dev/null +++ b/tasks/task_netplay_nat_traversal.c @@ -0,0 +1,87 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2017 - Gregor Richards + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see <http://www.gnu.org/licenses/>. + */ + +#include <lists/file_list.h> +#include <string/stdstring.h> + +#include "tasks_internal.h" +#include "net/net_natt.h" + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#include "../network/netplay/netplay.h" +#include "../verbosity.h" + +struct nat_traversal_state_data +{ + struct natt_status *nat_traversal_state; + uint16_t port; +}; + +static void netplay_nat_traversal_callback(void *task_data, + void *user_data, const char *error) +{ + struct nat_traversal_state_data *ntsd = + (struct nat_traversal_state_data *) task_data; + + free(ntsd); + + netplay_driver_ctl(RARCH_NETPLAY_CTL_FINISHED_NAT_TRAVERSAL, NULL); +} + +static void task_netplay_nat_traversal_handler(retro_task_t *task) +{ + struct nat_traversal_state_data *ntsd = + (struct nat_traversal_state_data *) task->task_data; + + natt_init(); + + if (natt_new(ntsd->nat_traversal_state)) + natt_open_port_any(ntsd->nat_traversal_state, ntsd->port, SOCKET_PROTOCOL_TCP); + + task_set_progress(task, 100); + task_set_finished(task, true); +} + +bool task_push_netplay_nat_traversal(struct natt_status *nat_traversal_state, uint16_t port) +{ + struct nat_traversal_state_data *ntsd; + retro_task_t *task = (retro_task_t*)calloc(1, sizeof(*task)); + + if (!task) + return false; + + ntsd = (struct nat_traversal_state_data *) calloc(1, sizeof(*ntsd)); + + if (!ntsd) + { + free(task); + return false; + } + + ntsd->nat_traversal_state = nat_traversal_state; + ntsd->port = port; + + task->type = TASK_TYPE_BLOCKING; + task->handler = task_netplay_nat_traversal_handler; + task->callback = netplay_nat_traversal_callback; + task->task_data = ntsd; + + task_queue_ctl(TASK_QUEUE_CTL_PUSH, task); + + return true; +} diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index 61bedf861a..9df0996709 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -25,6 +25,7 @@ #include <queues/message_queue.h> #include <queues/task_queue.h> #include <formats/image.h> +#include <net/net_natt.h> #include "../content.h" #include "../core_type.h" @@ -101,6 +102,9 @@ bool task_push_netplay_lan_scan(void); bool task_push_netplay_crc_scan(uint32_t crc, char* name, const char *hostname, const char *corename); +bool task_push_netplay_nat_traversal(struct natt_status *nat_traversal_state, + uint16_t port); + #endif bool task_push_image_load(const char *fullpath,