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 .
+ */
+
+#include
+#include
+
+#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
#include
#include
+#include
#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,