diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index fc371ca9c1..fa082796d7 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -916,6 +916,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ENABLE_HOST, "Start hosting") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_IP_ADDRESS, "Server Address") +MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_LAN_SCAN_SETTINGS, + "Scan local network") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_MODE, "Netplay Client Enable") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_NICKNAME, @@ -1682,6 +1684,8 @@ MSG_HASH(MENU_ENUM_SUBLABEL_LOG_VERBOSITY, "Enable or disable logging to the terminal.") MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY, "Join or host a netplay session.") +MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_LAN_SCAN_SETTINGS, + "Search for and connect to netplay hosts on the local network.") MSG_HASH(MENU_ENUM_SUBLABEL_INFORMATION_LIST_LIST, "Display information for core, network, and system.\nDisplay manager for database and cursor.") MSG_HASH(MENU_ENUM_SUBLABEL_ONLINE_UPDATER, @@ -2246,4 +2250,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_DATABASE_CURSOR_LIST_ENTRY_DATABASE_INFO, MSG_HASH(MSG_WIFI_SCAN_COMPLETE, "Wi-Fi scan complete.") MSG_HASH(MSG_SCANNING_WIRELESS_NETWORKS, - "Scanning wireless networks...") \ No newline at end of file + "Scanning wireless networks...") +MSG_HASH(MSG_NETPLAY_LAN_SCAN_COMPLETE, + "Netplay scan complete.") +MSG_HASH(MSG_NETPLAY_LAN_SCANNING, + "Scanning for netplay hosts...") diff --git a/menu/cbs/menu_cbs_deferred_push.c b/menu/cbs/menu_cbs_deferred_push.c index 61cff95e54..299108bfec 100644 --- a/menu/cbs/menu_cbs_deferred_push.c +++ b/menu/cbs/menu_cbs_deferred_push.c @@ -190,6 +190,11 @@ static int deferred_push_network_settings_list(menu_displaylist_info_t *info) return deferred_push_dlist(info, DISPLAYLIST_NETWORK_SETTINGS_LIST); } +static int deferred_push_netplay_lan_scan_settings_list(menu_displaylist_info_t *info) +{ + return deferred_push_dlist(info, DISPLAYLIST_NETPLAY_LAN_SCAN_SETTINGS_LIST); +} + static int deferred_push_lakka_services_list(menu_displaylist_info_t *info) { return deferred_push_dlist(info, DISPLAYLIST_LAKKA_SERVICES_LIST); @@ -792,6 +797,12 @@ static int menu_cbs_init_bind_deferred_push_compare_label( return 0; } + if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_NETPLAY_LAN_SCAN_SETTINGS_LIST))) + { + BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_netplay_lan_scan_settings_list); + return 0; + } + if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_LAKKA_SERVICES_LIST))) { BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_lakka_services_list); diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 1d3a749b41..ee1f338e25 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -53,6 +53,7 @@ #ifdef HAVE_NETWORKING #include "../../network/netplay/netplay.h" +#include "../../network/netplay/netplay_discovery.h" #endif typedef struct @@ -754,6 +755,14 @@ int generic_action_ok_displaylist_push(const char *path, info.enum_idx = MENU_ENUM_LABEL_DEFERRED_WIFI_SETTINGS_LIST; dl_type = DISPLAYLIST_GENERIC; break; + case ACTION_OK_DL_NETPLAY_LAN_SCAN_SETTINGS_LIST: + info.directory_ptr = idx; + info.type = type; + info_path = path; + info_label = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_NETPLAY_LAN_SCAN_SETTINGS_LIST); + info.enum_idx = MENU_ENUM_LABEL_DEFERRED_NETPLAY_LAN_SCAN_SETTINGS_LIST; + dl_type = DISPLAYLIST_GENERIC; + break; case ACTION_OK_DL_LAKKA_SERVICES_LIST: info.directory_ptr = idx; info.type = type; @@ -2927,6 +2936,13 @@ static int action_ok_network_list(const char *path, entry_idx, ACTION_OK_DL_NETWORK_SETTINGS_LIST); } +static int action_ok_netplay_lan_scan_list(const char *path, + const char *label, unsigned type, size_t idx, size_t entry_idx) +{ + return generic_action_ok_displaylist_push(path, NULL, label, type, idx, + entry_idx, ACTION_OK_DL_NETPLAY_LAN_SCAN_SETTINGS_LIST); +} + static int action_ok_lakka_services(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { @@ -2979,6 +2995,39 @@ static int action_ok_wifi(const char *path, return 0; } +static int action_ok_netplay_lan_scan(const char *path, + const char *label, unsigned type, size_t idx, size_t entry_idx) +{ + struct netplay_host_list *hosts; + struct netplay_host *host; + bool netplay_was_on = false; + + /* Figure out what host we're connecting to */ + if (!netplay_discovery_driver_ctl(RARCH_NETPLAY_DISCOVERY_CTL_LAN_GET_RESPONSES, &hosts)) + return -1; + if (entry_idx >= hosts->size) + return -1; + host = &hosts->hosts[entry_idx]; + + /* Enable Netplay client mode */ + if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)) + { + netplay_was_on = true; + command_event(CMD_EVENT_NETPLAY_DEINIT, NULL); + } + netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL); + + /* Enable Netplay */ + if (!command_event(CMD_EVENT_NETPLAY_INIT, (void *) host)) + return -1; + + /* And make sure we use its callbacks */ + if (!netplay_was_on && !core_set_netplay_callbacks()) + return -1; + + return generic_action_ok_command(CMD_EVENT_RESUME); +} + static int action_ok_content_collection_list(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { @@ -3829,6 +3878,9 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_NETWORK_SETTINGS: BIND_ACTION_OK(cbs, action_ok_network_list); break; + case MENU_ENUM_LABEL_NETPLAY_LAN_SCAN_SETTINGS: + BIND_ACTION_OK(cbs, action_ok_netplay_lan_scan_list); + break; case MENU_ENUM_LABEL_LAKKA_SERVICES: BIND_ACTION_OK(cbs, action_ok_lakka_services); break; @@ -4154,6 +4206,9 @@ static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs, case MENU_WIFI: BIND_ACTION_OK(cbs, action_ok_wifi); break; + case MENU_NETPLAY_LAN_SCAN: + BIND_ACTION_OK(cbs, action_ok_netplay_lan_scan); + break; case FILE_TYPE_CURSOR: switch (menu_label_hash) { diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index f6ba1bb147..2ad8fa27cb 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -58,6 +58,7 @@ default_sublabel_macro(action_bind_sublabel_video_window_scale, MENU_ default_sublabel_macro(action_bind_sublabel_audio_settings_list, MENU_ENUM_SUBLABEL_AUDIO_SETTINGS) default_sublabel_macro(action_bind_sublabel_input_settings_list, MENU_ENUM_SUBLABEL_INPUT_SETTINGS) default_sublabel_macro(action_bind_sublabel_wifi_settings_list, MENU_ENUM_SUBLABEL_WIFI_SETTINGS) +default_sublabel_macro(action_bind_sublabel_netplay_lan_scan_settings_list,MENU_ENUM_SUBLABEL_NETPLAY_LAN_SCAN_SETTINGS) default_sublabel_macro(action_bind_sublabel_help_list, MENU_ENUM_SUBLABEL_HELP_LIST) default_sublabel_macro(action_bind_sublabel_services_settings_list, MENU_ENUM_SUBLABEL_SERVICES_SETTINGS) default_sublabel_macro(action_bind_sublabel_ssh_enable, MENU_ENUM_SUBLABEL_SSH_ENABLE) @@ -351,6 +352,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_WIFI_SETTINGS: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_wifi_settings_list); break; + case MENU_ENUM_LABEL_NETPLAY_LAN_SCAN_SETTINGS: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_netplay_lan_scan_settings_list); + break; case MENU_ENUM_LABEL_HELP_LIST: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_help_list); break; diff --git a/menu/cbs/menu_cbs_title.c b/menu/cbs/menu_cbs_title.c index 55e2fff822..ed69c9907c 100644 --- a/menu/cbs/menu_cbs_title.c +++ b/menu/cbs/menu_cbs_title.c @@ -118,6 +118,7 @@ default_title_macro(action_get_menu_file_browser_settings_list, MENU_ENUM_LABEL_ default_title_macro(action_get_retro_achievements_settings_list,MENU_ENUM_LABEL_VALUE_RETRO_ACHIEVEMENTS_SETTINGS) default_title_macro(action_get_wifi_settings_list, MENU_ENUM_LABEL_VALUE_WIFI_SETTINGS) default_title_macro(action_get_network_settings_list, MENU_ENUM_LABEL_VALUE_NETWORK_SETTINGS) +default_title_macro(action_get_netplay_lan_scan_settings_list, MENU_ENUM_LABEL_VALUE_NETPLAY_LAN_SCAN_SETTINGS) default_title_macro(action_get_lakka_services_list, MENU_ENUM_LABEL_VALUE_LAKKA_SERVICES) default_title_macro(action_get_user_settings_list, MENU_ENUM_LABEL_VALUE_USER_SETTINGS) default_title_macro(action_get_directory_settings_list, MENU_ENUM_LABEL_VALUE_DIRECTORY_SETTINGS) @@ -403,6 +404,12 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs, return 0; } + if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_NETPLAY_LAN_SCAN_SETTINGS_LIST))) + { + BIND_ACTION_GET_TITLE(cbs, action_get_netplay_lan_scan_settings_list); + return 0; + } + if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_LAKKA_SERVICES_LIST))) { BIND_ACTION_GET_TITLE(cbs, action_get_lakka_services_list); diff --git a/menu/menu_cbs.h b/menu/menu_cbs.h index 84668a78d6..7f9ac751c3 100644 --- a/menu/menu_cbs.h +++ b/menu/menu_cbs.h @@ -93,6 +93,7 @@ enum ACTION_OK_DL_UPDATER_SETTINGS_LIST, ACTION_OK_DL_WIFI_SETTINGS_LIST, ACTION_OK_DL_NETWORK_SETTINGS_LIST, + ACTION_OK_DL_NETPLAY_LAN_SCAN_SETTINGS_LIST, ACTION_OK_DL_LAKKA_SERVICES_LIST, ACTION_OK_DL_USER_SETTINGS_LIST, ACTION_OK_DL_DIRECTORY_SETTINGS_LIST, diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index d32345c235..eaf879c887 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -40,6 +40,10 @@ #include "../cheevos.h" #endif +#ifdef HAVE_NETWORKING +#include "../network/netplay/netplay_discovery.h" +#endif + #ifdef __linux__ #include "../frontend/drivers/platform_linux.h" #endif @@ -4216,6 +4220,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) case DISPLAYLIST_UPDATER_SETTINGS_LIST: case DISPLAYLIST_WIFI_SETTINGS_LIST: case DISPLAYLIST_NETWORK_SETTINGS_LIST: + case DISPLAYLIST_NETPLAY_LAN_SCAN_SETTINGS_LIST: case DISPLAYLIST_LAKKA_SERVICES_LIST: case DISPLAYLIST_USER_SETTINGS_LIST: case DISPLAYLIST_DIRECTORY_SETTINGS_LIST: @@ -5008,6 +5013,50 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) 0, 0, 0); } + info->need_refresh = true; + info->need_push = true; + break; + case DISPLAYLIST_NETPLAY_LAN_SCAN_SETTINGS_LIST: +#ifdef HAVE_NETWORKING + { + struct netplay_host_list *hosts; + + if (!netplay_discovery_driver_ctl(RARCH_NETPLAY_DISCOVERY_CTL_LAN_GET_RESPONSES, &hosts)) + hosts = NULL; + + if (!hosts || hosts->size == 0) + { + if (!hosts) + task_push_netplay_lan_scan(); + + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_NETWORKS_FOUND), + msg_hash_to_str(MENU_ENUM_LABEL_NO_NETWORKS_FOUND), + MENU_ENUM_LABEL_NO_NETWORKS_FOUND, + 0, 0, 0); + } + else + { + size_t i; + for (i = 0; i < hosts->size; i++) + { + struct netplay_host *host = &hosts->hosts[i]; + menu_entries_append_enum(info->list, + host->nick, + msg_hash_to_str(MENU_ENUM_LABEL_CONNECT_NETPLAY_LAN), + MENU_ENUM_LABEL_CONNECT_NETPLAY_LAN, + MENU_NETPLAY_LAN_SCAN, 0, 0); + } + } + } +#else + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_NETWORKS_FOUND), + msg_hash_to_str(MENU_ENUM_LABEL_NO_NETWORKS_FOUND), + MENU_ENUM_LABEL_NO_NETWORKS_FOUND, + 0, 0, 0); +#endif + info->need_refresh = true; info->need_push = true; break; @@ -5418,6 +5467,8 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) MENU_ENUM_LABEL_WIFI_SETTINGS, PARSE_ACTION, false); ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_NETWORK_SETTINGS, PARSE_ACTION, false); + ret = menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_NETPLAY_LAN_SCAN_SETTINGS, PARSE_ACTION, false); ret = menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_LAKKA_SERVICES, PARSE_ACTION, false); ret = menu_displaylist_parse_settings_enum(menu, info, diff --git a/menu/menu_displaylist.h b/menu/menu_displaylist.h index 2248148abb..d03324acea 100644 --- a/menu/menu_displaylist.h +++ b/menu/menu_displaylist.h @@ -128,6 +128,7 @@ enum menu_displaylist_ctl_state DISPLAYLIST_UPDATER_SETTINGS_LIST, DISPLAYLIST_WIFI_SETTINGS_LIST, DISPLAYLIST_NETWORK_SETTINGS_LIST, + DISPLAYLIST_NETPLAY_LAN_SCAN_SETTINGS_LIST, DISPLAYLIST_LAKKA_SERVICES_LIST, DISPLAYLIST_USER_SETTINGS_LIST, DISPLAYLIST_DIRECTORY_SETTINGS_LIST, diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 2a399079d3..67fb41412d 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -2560,6 +2560,14 @@ static bool setting_append_list( &subgroup_info, parent_group); + CONFIG_ACTION( + list, list_info, + MENU_ENUM_LABEL_NETPLAY_LAN_SCAN_SETTINGS, + MENU_ENUM_LABEL_VALUE_NETPLAY_LAN_SCAN_SETTINGS, + &group_info, + &subgroup_info, + parent_group); + #ifdef HAVE_LAKKA CONFIG_ACTION( list, list_info, diff --git a/msg_hash.h b/msg_hash.h index 13989391bc..5a5494c483 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -141,6 +141,7 @@ enum msg_hash_enums MSG_NETPLAY_USERS_HAS_FLIPPED, MSG_UNKNOWN_NETPLAY_COMMAND_RECEIVED, MSG_CONNECTING_TO_NETPLAY_HOST, + MSG_NETPLAY_LAN_SCAN_COMPLETE, MSG_NETPLAY_LAN_SCANNING, MSG_WAITING_FOR_CLIENT, MSG_AUTODETECT, @@ -714,8 +715,10 @@ enum msg_hash_enums MENU_LABEL(DIRECTORY_SETTINGS), MENU_LABEL(PRIVACY_SETTINGS), MENU_LABEL(NETWORK_SETTINGS), + MENU_LABEL(NETPLAY_LAN_SCAN_SETTINGS), MENU_ENUM_LABEL_CONNECT_WIFI, + MENU_ENUM_LABEL_CONNECT_NETPLAY_LAN, MENU_LABEL(MENU_ENUM_LINEAR_FILTER), MENU_LABEL(MENU_ENUM_THROTTLE_FRAMERATE), diff --git a/network/netplay/netplay.c b/network/netplay/netplay.c index f3dd7c0e56..905d340fc8 100644 --- a/network/netplay/netplay.c +++ b/network/netplay/netplay.c @@ -1259,7 +1259,7 @@ netplay_t *netplay_new(void *direct_host, const char *server, uint16_t port, netplay->check_frames = check_frames; netplay->quirks = quirks; - strlcpy(netplay->nick, nick, sizeof(netplay->nick)); + strlcpy(netplay->nick, nick[0] ? nick : RARCH_DEFAULT_NICK, sizeof(netplay->nick)); if (!netplay_init_buffers(netplay, delay_frames)) { diff --git a/network/netplay/netplay_discovery.c b/network/netplay/netplay_discovery.c index 6ac8062d81..61122e58bb 100644 --- a/network/netplay/netplay_discovery.c +++ b/network/netplay/netplay_discovery.c @@ -116,12 +116,18 @@ bool netplay_discovery_driver_ctl(enum rarch_netplay_discovery_ctl_state state, case RARCH_NETPLAY_DISCOVERY_CTL_LAN_SEND_QUERY: { struct addrinfo hints = {0}, *addr; + int canBroadcast = 1; /* Get the broadcast address (IPv4 only for now) */ snprintf(port_str, 6, "%hu", RARCH_DEFAULT_PORT); if (getaddrinfo_retro("255.255.255.255", port_str, &hints, &addr) < 0) return false; + /* Make it broadcastable */ +#if defined(SOL_SOCKET) && defined(SO_BROADCAST) + setsockopt(lan_ad_client_fd, SOL_SOCKET, SO_BROADCAST, (void *) &canBroadcast, sizeof(canBroadcast)); +#endif + /* Put together the request */ memcpy((void *) &ad_packet_buffer, "RANQ", 4); ad_packet_buffer.protocol_version = htonl(NETPLAY_PROTOCOL_VERSION); @@ -298,7 +304,7 @@ bool netplay_lan_ad_client(void) if (their_addr.sa_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in *) &their_addr; - sin->sin_port = htons(ad_packet_buffer.port); + sin->sin_port = htons(ntohl(ad_packet_buffer.port)); } #ifdef AF_INET6 diff --git a/network/netplay/netplay_net.c b/network/netplay/netplay_net.c index 51a3535e97..a9472ef039 100644 --- a/network/netplay/netplay_net.c +++ b/network/netplay/netplay_net.c @@ -338,19 +338,6 @@ static bool netplay_net_info_cb(netplay_t* netplay, unsigned frames) netplay->has_connection = true; } - { - struct natt_status status; - natt_init(); - if (natt_new(&status) && natt_open_port_any(&status, netplay->tcp_port, SOCKET_PROTOCOL_TCP)) - { - fprintf(stderr, "Forwarded to %d!\n", status.ext_inet4_addr.sin_port); - } - else - { - fprintf(stderr, "Forwarding failed :(\n"); - } - } - return true; } diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h index 3b72e52160..e8bf108da7 100644 --- a/network/netplay/netplay_private.h +++ b/network/netplay/netplay_private.h @@ -37,6 +37,7 @@ #define WORDS_PER_FRAME 4 /* Allows us to send 128 bits worth of state per frame. */ #define MAX_SPECTATORS 16 #define RARCH_DEFAULT_PORT 55435 +#define RARCH_DEFAULT_NICK "Anonymous" #define NETPLAY_PROTOCOL_VERSION 3 diff --git a/tasks/task_netplay_lan_scan.c b/tasks/task_netplay_lan_scan.c index cd2462d58f..8844b78f54 100644 --- a/tasks/task_netplay_lan_scan.c +++ b/tasks/task_netplay_lan_scan.c @@ -39,12 +39,14 @@ static void netplay_lan_scan_callback(void *task_data, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_NETPLAY_LAN_SCAN_SETTINGS_LIST))) return; - file_list = menu_entries_get_selection_buf_ptr(0); - - menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, file_list); - if (netplay_discovery_driver_ctl(RARCH_NETPLAY_DISCOVERY_CTL_LAN_GET_RESPONSES, (void *) &netplay_hosts)) { + if (netplay_hosts->size > 0) + { + file_list = menu_entries_get_selection_buf_ptr(0); + menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, file_list); + } + for (i = 0; i < netplay_hosts->size; i++) { struct netplay_host *host = &netplay_hosts->hosts[i];