From dabd9cb996f497e8e993ecf08ff6eead7bd6500a Mon Sep 17 00:00:00 2001
From: Cthulhu-throwaway <96153783+Cthulhu-throwaway@users.noreply.github.com>
Date: Sat, 18 Jun 2022 22:41:04 -0300
Subject: [PATCH] (Netplay/LAN Discovery) Task refactor (#14070)
---
menu/cbs/menu_cbs_ok.c | 28 ++++-----
network/netplay/netplay_frontend.c | 38 ++++++------
tasks/task_netplay_lan_scan.c | 93 ++++++++++++++++++++++++------
tasks/tasks_internal.h | 2 +-
4 files changed, 104 insertions(+), 57 deletions(-)
diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c
index 6b39519a84..684bdf96ec 100644
--- a/menu/cbs/menu_cbs_ok.c
+++ b/menu/cbs/menu_cbs_ok.c
@@ -6088,17 +6088,17 @@ static int action_ok_push_netplay_refresh_rooms(const char *path,
}
#ifdef HAVE_NETPLAYDISCOVERY
-static void netplay_refresh_lan_cb(retro_task_t *task, void *task_data,
- void *user_data, const char *error)
+static void netplay_refresh_lan_cb(const void *data)
{
int i;
- const char *path = NULL;
- const char *label = NULL;
- unsigned menu_type = 0;
- enum msg_hash_enums enum_idx = MSG_UNKNOWN;
- struct netplay_host_list *hosts = NULL;
- bool refresh = false;
- net_driver_state_t *net_st = networking_state_get_ptr();
+ const char *path = NULL;
+ const char *label = NULL;
+ unsigned menu_type = 0;
+ enum msg_hash_enums enum_idx = MSG_UNKNOWN;
+ bool refresh = false;
+ const struct netplay_host_list *hosts =
+ (const struct netplay_host_list*)data;
+ net_driver_state_t *net_st = networking_state_get_ptr();
free(net_st->room_list);
net_st->room_list = NULL;
@@ -6109,11 +6109,8 @@ static void netplay_refresh_lan_cb(retro_task_t *task, void *task_data,
/* Don't push the results if we left the netplay menu */
if (!string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY_TAB)) &&
!string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_NETPLAY)))
- goto deinit;
+ return;
- if (!netplay_discovery_driver_ctl(
- RARCH_NETPLAY_DISCOVERY_CTL_LAN_GET_RESPONSES, &hosts))
- goto done;
if (!hosts || !hosts->size)
goto done;
@@ -6154,15 +6151,12 @@ static void netplay_refresh_lan_cb(retro_task_t *task, void *task_data,
done:
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
-
-deinit:
- deinit_netplay_discovery();
}
static int action_ok_push_netplay_refresh_lan(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
- task_push_netplay_lan_scan(netplay_refresh_lan_cb);
+ task_push_netplay_lan_scan(netplay_refresh_lan_cb, 800);
return 0;
}
diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c
index 926ae434cc..9af034b82c 100644
--- a/network/netplay/netplay_frontend.c
+++ b/network/netplay/netplay_frontend.c
@@ -240,7 +240,7 @@ bool init_netplay_discovery(void)
net_st->lan_ad_client_fd = fd;
- ret = socket_bind(fd, addr);
+ ret = socket_bind(fd, addr) && socket_nonblock(fd);
}
if (!ret)
{
@@ -305,6 +305,8 @@ static bool netplay_lan_ad_client_query(void)
static bool netplay_lan_ad_client_response(void)
{
+ size_t count;
+ ssize_t ret;
char address[16];
struct ad_packet ad_packet_buffer;
struct netplay_host *host;
@@ -312,21 +314,19 @@ static bool netplay_lan_ad_client_response(void)
net_driver_state_t *net_st = &networking_driver_st;
/* Check for any ad queries */
- for (;;)
+ for (count = 0;;)
{
- bool has_data = true;
struct sockaddr_storage their_addr = {0};
socklen_t addr_size = sizeof(their_addr);
- if (!socket_wait(net_st->lan_ad_client_fd, &has_data, NULL, 500) ||
- !has_data)
- break;
+ ret = recvfrom(net_st->lan_ad_client_fd,
+ (char*)&ad_packet_buffer, sizeof(ad_packet_buffer), 0,
+ (struct sockaddr*)&their_addr, &addr_size);
+ if (ret < 0)
+ return isagain((int)ret) && count > 0;
/* Somebody queried, so check that it's valid */
- if (recvfrom(net_st->lan_ad_client_fd,
- (char*)&ad_packet_buffer, sizeof(ad_packet_buffer), 0,
- (struct sockaddr*)&their_addr, &addr_size) !=
- sizeof(ad_packet_buffer))
+ if (ret != sizeof(ad_packet_buffer))
continue;
/* Make sure it's a valid response */
@@ -430,9 +430,9 @@ static bool netplay_lan_ad_client_response(void)
has_password = ntohl(ad_packet_buffer.has_password);
host->has_password = (has_password & 1) ? true : false;
host->has_spectate_password = (has_password & 2) ? true : false;
- }
- return true;
+ count++;
+ }
}
/** Discovery control */
@@ -441,19 +441,14 @@ bool netplay_discovery_driver_ctl(
{
net_driver_state_t *net_st = &networking_driver_st;
- if (net_st->lan_ad_client_fd < 0)
- return false;
-
switch (state)
{
case RARCH_NETPLAY_DISCOVERY_CTL_LAN_SEND_QUERY:
- return netplay_lan_ad_client_query();
+ return net_st->lan_ad_client_fd >= 0 && netplay_lan_ad_client_query();
case RARCH_NETPLAY_DISCOVERY_CTL_LAN_GET_RESPONSES:
- if (!netplay_lan_ad_client_response())
- return false;
- *(struct netplay_host_list**)data = &net_st->discovered_hosts;
- break;
+ return net_st->lan_ad_client_fd >= 0 &&
+ netplay_lan_ad_client_response();
case RARCH_NETPLAY_DISCOVERY_CTL_LAN_CLEAR_RESPONSES:
net_st->discovered_hosts.size = 0;
@@ -473,7 +468,8 @@ static bool init_lan_ad_server_socket(void)
net_driver_state_t *net_st = &networking_driver_st;
int fd = socket_init((void**)&addr, RARCH_DEFAULT_PORT,
NULL, SOCKET_TYPE_DATAGRAM);
- bool ret = fd >= 0 && addr && socket_bind(fd, addr);
+ bool ret = fd >= 0 && addr &&
+ socket_bind(fd, addr) && socket_nonblock(fd);
if (ret)
{
diff --git a/tasks/task_netplay_lan_scan.c b/tasks/task_netplay_lan_scan.c
index fafe0272fb..05f67e130b 100644
--- a/tasks/task_netplay_lan_scan.c
+++ b/tasks/task_netplay_lan_scan.c
@@ -1,6 +1,7 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2016-2017 - Jean-André Santoni
* Copyright (C) 2016-2019 - Andrés Suárez
+ * Copyright (C) 2021-2022 - Roberto V. Rampim
*
* 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-
@@ -14,50 +15,106 @@
* If not, see .
*/
-#include
-#include
-#include "../paths.h"
+#include
-#include "task_file_transfer.h"
#include "tasks_internal.h"
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
-#include "../verbosity.h"
-#ifdef HAVE_NETWORKING
-#include "../network/netplay/netplay.h"
-#endif
-
#ifdef HAVE_NETPLAYDISCOVERY
+
+#include "../network/netplay/netplay.h"
+
+struct netplay_lan_scan_data
+{
+ retro_time_t timeout;
+ void (*cb)(const void*);
+ bool query;
+ bool busy;
+};
+
static void task_netplay_lan_scan_handler(retro_task_t *task)
{
- if (init_netplay_discovery())
+ struct netplay_lan_scan_data *data =
+ (struct netplay_lan_scan_data*)task->task_data;
+
+ if (data->query)
{
netplay_discovery_driver_ctl(
- RARCH_NETPLAY_DISCOVERY_CTL_LAN_CLEAR_RESPONSES, NULL);
- netplay_discovery_driver_ctl(
- RARCH_NETPLAY_DISCOVERY_CTL_LAN_SEND_QUERY, NULL);
+ RARCH_NETPLAY_DISCOVERY_CTL_LAN_CLEAR_RESPONSES, NULL);
+
+ if (!init_netplay_discovery())
+ goto finished;
+
+ if (!netplay_discovery_driver_ctl(
+ RARCH_NETPLAY_DISCOVERY_CTL_LAN_SEND_QUERY, NULL))
+ goto finished;
+
+ data->timeout += cpu_features_get_time_usec();
+ data->query = false;
}
+ else
+ {
+ if (!netplay_discovery_driver_ctl(
+ RARCH_NETPLAY_DISCOVERY_CTL_LAN_GET_RESPONSES, NULL))
+ {
+ if (cpu_features_get_time_usec() >= data->timeout)
+ goto finished;
+ }
+ }
+
+ return;
+
+finished:
+ deinit_netplay_discovery();
task_set_progress(task, 100);
task_set_finished(task, true);
}
-bool task_push_netplay_lan_scan(retro_task_callback_t cb)
+static void task_netplay_lan_scan_callback(retro_task_t *task,
+ void *task_data, void *user_data, const char *error)
{
- retro_task_t *task = task_init();
+ struct netplay_lan_scan_data *data =
+ (struct netplay_lan_scan_data*)task_data;
+ net_driver_state_t *net_st = networking_state_get_ptr();
+ data->cb(&net_st->discovered_hosts);
+
+ data->busy = false;
+}
+
+bool task_push_netplay_lan_scan(void (*cb)(const void*), unsigned timeout)
+{
+ static struct netplay_lan_scan_data data = {0};
+ retro_task_t *task;
+
+ /* Do not run more than one LAN scan task at a time. */
+ if (data.busy)
+ return false;
+
+ task = task_init();
if (!task)
return false;
- task->type = TASK_TYPE_BLOCKING;
- task->handler = task_netplay_lan_scan_handler;
- task->callback = cb;
+ data.busy = true;
+ data.query = true;
+ data.timeout = (retro_time_t)timeout * 1000;
+ data.cb = cb;
+
+ task->handler = task_netplay_lan_scan_handler;
+ task->callback = task_netplay_lan_scan_callback;
+ task->task_data = &data;
task_queue_push(task);
return true;
}
+#else
+bool task_push_netplay_lan_scan(void (*cb)(const void*), unsigned timeout)
+{
+ return false;
+}
#endif
diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h
index 3cacd4e4f0..2380f070f6 100644
--- a/tasks/tasks_internal.h
+++ b/tasks/tasks_internal.h
@@ -87,7 +87,7 @@ bool task_push_wifi_disable(retro_task_callback_t cb);
bool task_push_wifi_disconnect(retro_task_callback_t cb);
bool task_push_wifi_connect(retro_task_callback_t cb, void*);
-bool task_push_netplay_lan_scan(retro_task_callback_t cb);
+bool task_push_netplay_lan_scan(void (*cb)(const void*), unsigned timeout);
bool task_push_netplay_crc_scan(uint32_t crc, char* name,
const char *hostname, const char *corename, const char* subsystem);