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);