diff --git a/config.def.h b/config.def.h index a94fb5bb88..6c5e6d410f 100644 --- a/config.def.h +++ b/config.def.h @@ -1019,10 +1019,6 @@ static const bool audio_enable_menu_bgm = false; #define DEFAULT_NOTIFICATION_SHOW_REFRESH_RATE true #endif -#ifdef HAVE_NETWORKING -#define DEFAULT_NOTIFICATION_SHOW_NETPLAY_EXTRA false -#endif - /* Output samplerate. */ #ifdef GEKKO #define DEFAULT_OUTPUT_RATE 32000 @@ -1174,7 +1170,6 @@ static const bool netplay_use_mitm_server = false; #define DEFAULT_NETPLAY_MITM_SERVER "nyc" #ifdef HAVE_NETWORKING -static const unsigned netplay_max_connections = 3; static const unsigned netplay_share_digital = RARCH_NETPLAY_SHARE_DIGITAL_NO_PREFERENCE; static const unsigned netplay_share_analog = RARCH_NETPLAY_SHARE_ANALOG_NO_PREFERENCE; diff --git a/configuration.c b/configuration.c index 59eee6e35e..f407649dcd 100644 --- a/configuration.c +++ b/configuration.c @@ -1702,9 +1702,6 @@ static struct config_bool_setting *populate_settings_bool( SETTING_BOOL("notification_show_screenshot", &settings->bools.notification_show_screenshot, true, DEFAULT_NOTIFICATION_SHOW_SCREENSHOT, false); #endif SETTING_BOOL("notification_show_refresh_rate", &settings->bools.notification_show_refresh_rate, true, DEFAULT_NOTIFICATION_SHOW_REFRESH_RATE, false); -#ifdef HAVE_NETWORKING - SETTING_BOOL("notification_show_netplay_extra", &settings->bools.notification_show_netplay_extra, true, DEFAULT_NOTIFICATION_SHOW_NETPLAY_EXTRA, false); -#endif SETTING_BOOL("menu_widget_scale_auto", &settings->bools.menu_widget_scale_auto, true, DEFAULT_MENU_WIDGET_SCALE_AUTO, false); SETTING_BOOL("audio_enable_menu", &settings->bools.audio_enable_menu, true, audio_enable_menu, false); SETTING_BOOL("audio_enable_menu_ok", &settings->bools.audio_enable_menu_ok, true, audio_enable_menu_ok, false); @@ -2203,7 +2200,6 @@ static struct config_uint_setting *populate_settings_uint( #endif #ifdef HAVE_NETWORKING SETTING_UINT("netplay_ip_port", &settings->uints.netplay_port, true, RARCH_DEFAULT_PORT, false); - SETTING_UINT("netplay_max_connections", &settings->uints.netplay_max_connections, true, netplay_max_connections, false); SETTING_OVERRIDE(RARCH_OVERRIDE_SETTING_NETPLAY_IP_PORT); SETTING_UINT("netplay_input_latency_frames_min",&settings->uints.netplay_input_latency_frames_min, true, 0, false); SETTING_UINT("netplay_input_latency_frames_range",&settings->uints.netplay_input_latency_frames_range, true, 0, false); diff --git a/configuration.h b/configuration.h index e59711d5d2..621e0027c3 100644 --- a/configuration.h +++ b/configuration.h @@ -200,7 +200,6 @@ typedef struct settings unsigned input_max_users; unsigned netplay_port; - unsigned netplay_max_connections; unsigned netplay_input_latency_frames_min; unsigned netplay_input_latency_frames_range; unsigned netplay_share_digital; @@ -625,7 +624,6 @@ typedef struct settings bool notification_show_screenshot; #endif bool notification_show_refresh_rate; - bool notification_show_netplay_extra; bool menu_widget_scale_auto; bool menu_show_start_screen; bool menu_pause_libretro; diff --git a/intl/msg_hash_es.h b/intl/msg_hash_es.h index 2bb9776a1f..0b30c0c61d 100644 --- a/intl/msg_hash_es.h +++ b/intl/msg_hash_es.h @@ -3945,14 +3945,6 @@ MSG_HASH( MENU_ENUM_SUBLABEL_NOTIFICATION_SHOW_REFRESH_RATE, "Muestra un mensaje en pantalla al cambiar la frecuencia de actualización." ) -MSG_HASH( - MENU_ENUM_LABEL_VALUE_NOTIFICATION_SHOW_NETPLAY_EXTRA, - "Notificaciones extras de netplay" - ) -MSG_HASH( - MENU_ENUM_SUBLABEL_NOTIFICATION_SHOW_NETPLAY_EXTRA, - "Muestra mensajes no esenciales de netplay en la pantalla." - ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_FONT_PATH, "Fuente de notificaciones" @@ -5150,10 +5142,6 @@ MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_TCP_UDP_PORT, "Indica el puerto del servidor a conectar. Puede ser TCP o UDP." ) -MSG_HASH( - MENU_ENUM_LABEL_VALUE_NETPLAY_MAX_CONNECTIONS, - "Max Conexiones Simultáneas" - ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_PASSWORD, "Contraseña del servidor" diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index ff6d1db8a9..5779d6a72a 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -1974,10 +1974,6 @@ MSG_HASH( MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT, "netplay_tcp_udp_port" ) -MSG_HASH( - MENU_ENUM_LABEL_NETPLAY_MAX_CONNECTIONS, - "netplay_max_connections" - ) MSG_HASH( MENU_ENUM_LABEL_NETPLAY_LAN_SCAN_SETTINGS, "Search for and connect to netplay hosts on the local network." @@ -4772,10 +4768,6 @@ MSG_HASH( MENU_ENUM_LABEL_NOTIFICATION_SHOW_REFRESH_RATE, "notification_show_refresh_rate" ) -MSG_HASH( - MENU_ENUM_LABEL_NOTIFICATION_SHOW_NETPLAY_EXTRA, - "notification_show_netplay_extra" - ) MSG_HASH( MENU_ENUM_LABEL_VIDEO_SHADERS_ENABLE, "video_shader_enable" diff --git a/intl/msg_hash_pt_br.h b/intl/msg_hash_pt_br.h index 40c957954d..e485de1273 100644 --- a/intl/msg_hash_pt_br.h +++ b/intl/msg_hash_pt_br.h @@ -3921,14 +3921,6 @@ MSG_HASH( MENU_ENUM_SUBLABEL_NOTIFICATION_SHOW_REFRESH_RATE, "Exibe uma mensagem na tela ao definir a taxa de atualização." ) -MSG_HASH( - MENU_ENUM_LABEL_VALUE_NOTIFICATION_SHOW_NETPLAY_EXTRA, - "Notificações extras de netplay" - ) -MSG_HASH( - MENU_ENUM_SUBLABEL_NOTIFICATION_SHOW_NETPLAY_EXTRA, - "Exibe mensagens não essenciais de netplay na tela." - ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_FONT_PATH, "Fonte das notificações na tela" @@ -5122,10 +5114,6 @@ MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_TCP_UDP_PORT, "Porta do endereço de IP do anfitrião. Pode ser uma porta TCP ou uma porta UDP." ) -MSG_HASH( - MENU_ENUM_LABEL_VALUE_NETPLAY_MAX_CONNECTIONS, - "Max Conexões Simultâneas" - ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_PASSWORD, "Senha do servidor" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 8d421ec032..e0904a468a 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -4009,14 +4009,6 @@ MSG_HASH( MENU_ENUM_SUBLABEL_NOTIFICATION_SHOW_REFRESH_RATE, "Display an on-screen message when setting the refresh rate." ) -MSG_HASH( - MENU_ENUM_LABEL_VALUE_NOTIFICATION_SHOW_NETPLAY_EXTRA, - "Extra Netplay Notifications" - ) -MSG_HASH( - MENU_ENUM_SUBLABEL_NOTIFICATION_SHOW_NETPLAY_EXTRA, - "Display non-essential netplay on-screen messages." - ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_FONT_PATH, "Notification Font" @@ -5214,10 +5206,6 @@ MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_TCP_UDP_PORT, "The port of the host IP address. Can be either a TCP or UDP port." ) -MSG_HASH( - MENU_ENUM_LABEL_VALUE_NETPLAY_MAX_CONNECTIONS, - "Max Simultaneous Connections" - ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_PASSWORD, "Server Password" @@ -12069,22 +12057,6 @@ MSG_HASH( MSG_FAILED_TO_SET_INITIAL_DISK, "Failed to set last used disc..." ) -MSG_HASH( - MSG_FAILED_TO_CONNECT_TO_CLIENT, - "Failed to connect to client" - ) -MSG_HASH( - MSG_FAILED_TO_CONNECT_TO_HOST, - "Failed to connect to host" - ) -MSG_HASH( - MSG_NETPLAY_HOST_FULL, - "Netplay host full" - ) -MSG_HASH( - MSG_FAILED_TO_RECEIVE_HEADER_FROM_HOST, - "Failed to receive header from host" - ) MSG_HASH( MSG_CHEEVOS_HARDCORE_MODE_DISABLED, "A save state was loaded. Achievements Hardcore Mode disabled for the current session." diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index ae6babc26a..111f533c1e 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -441,9 +441,6 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_notification_show_screenshot_duratio DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_notification_show_screenshot_flash, MENU_ENUM_SUBLABEL_NOTIFICATION_SHOW_SCREENSHOT_FLASH) #endif DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_notification_show_refresh_rate, MENU_ENUM_SUBLABEL_NOTIFICATION_SHOW_REFRESH_RATE) -#ifdef HAVE_NETWORKING -DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_notification_show_netplay_extra, MENU_ENUM_SUBLABEL_NOTIFICATION_SHOW_NETPLAY_EXTRA) -#endif DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_window_width, MENU_ENUM_SUBLABEL_VIDEO_WINDOW_WIDTH) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_window_height, MENU_ENUM_SUBLABEL_VIDEO_WINDOW_HEIGHT) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_window_auto_width_max, MENU_ENUM_SUBLABEL_VIDEO_WINDOW_AUTO_WIDTH_MAX) @@ -3480,11 +3477,6 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_NOTIFICATION_SHOW_REFRESH_RATE: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_notification_show_refresh_rate); break; -#ifdef HAVE_NETWORKING - case MENU_ENUM_LABEL_NOTIFICATION_SHOW_NETPLAY_EXTRA: - BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_notification_show_netplay_extra); - break; -#endif case MENU_ENUM_LABEL_RESTART_RETROARCH: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_restart_retroarch); break; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index bd94d0ce4b..4efb4893d5 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -7295,7 +7295,6 @@ unsigned menu_displaylist_build_list( {MENU_ENUM_LABEL_NETPLAY_MITM_SERVER, PARSE_ONLY_STRING, false}, {MENU_ENUM_LABEL_NETPLAY_IP_ADDRESS, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT, PARSE_ONLY_UINT, true}, - {MENU_ENUM_LABEL_NETPLAY_MAX_CONNECTIONS, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_NETPLAY_PASSWORD, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_NETPLAY_SPECTATE_PASSWORD, PARSE_ONLY_STRING, true}, {MENU_ENUM_LABEL_NETPLAY_START_AS_SPECTATOR, PARSE_ONLY_BOOL, true}, @@ -8630,9 +8629,6 @@ unsigned menu_displaylist_build_list( #endif #endif {MENU_ENUM_LABEL_NOTIFICATION_SHOW_REFRESH_RATE, PARSE_ONLY_BOOL, false }, -#ifdef HAVE_NETWORKING - {MENU_ENUM_LABEL_NOTIFICATION_SHOW_NETPLAY_EXTRA, PARSE_ONLY_BOOL, false }, -#endif }; for (i = 0; i < ARRAY_SIZE(build_list); i++) @@ -9874,7 +9870,6 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, file_list_t *list = info->list; menu_displaylist_build_info_selective_t build_list[] = { {MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT, PARSE_ONLY_UINT, true}, - {MENU_ENUM_LABEL_NETPLAY_MAX_CONNECTIONS, PARSE_ONLY_UINT, true}, {MENU_ENUM_LABEL_NETPLAY_PUBLIC_ANNOUNCE, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_NETPLAY_USE_MITM_SERVER, PARSE_ONLY_BOOL, true }, {MENU_ENUM_LABEL_NETPLAY_MITM_SERVER, PARSE_ONLY_STRING, false}, diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 6432af54ac..b67fe31ad3 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -13651,7 +13651,6 @@ static bool setting_append_list( (*list)[list_info->index - 1].offset_by = 1; menu_settings_list_current_add_range(list, list_info, 1, 65536, 1, true, true); - CONFIG_UINT( list, list_info, &settings->uints.video_stream_quality, @@ -14565,23 +14564,6 @@ static bool setting_append_list( general_read_handler, SD_FLAG_NONE); -#ifdef HAVE_NETWORKING - CONFIG_BOOL( - list, list_info, - &settings->bools.notification_show_netplay_extra, - MENU_ENUM_LABEL_NOTIFICATION_SHOW_NETPLAY_EXTRA, - MENU_ENUM_LABEL_VALUE_NOTIFICATION_SHOW_NETPLAY_EXTRA, - DEFAULT_NOTIFICATION_SHOW_NETPLAY_EXTRA, - MENU_ENUM_LABEL_VALUE_OFF, - MENU_ENUM_LABEL_VALUE_ON, - &group_info, - &subgroup_info, - parent_group, - general_write_handler, - general_read_handler, - SD_FLAG_NONE); -#endif - END_SUB_GROUP(list, list_info, parent_group); END_GROUP(list, list_info, parent_group); break; @@ -19049,21 +19031,6 @@ static bool setting_append_list( SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ALLOW_INPUT); SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_ADVANCED); - CONFIG_UINT( - list, list_info, - &settings->uints.netplay_max_connections, - MENU_ENUM_LABEL_NETPLAY_MAX_CONNECTIONS, - MENU_ENUM_LABEL_VALUE_NETPLAY_MAX_CONNECTIONS, - netplay_max_connections, - &group_info, - &subgroup_info, - parent_group, - general_write_handler, - general_read_handler); - (*list)[list_info->index - 1].ui_type = ST_UI_TYPE_UINT_SPINBOX; - (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; - menu_settings_list_current_add_range(list, list_info, 1, 31, 1, true, true); - CONFIG_STRING( list, list_info, settings->paths.netplay_password, diff --git a/msg_hash.h b/msg_hash.h index 848a1e0d9e..34e4e45aa6 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -175,10 +175,6 @@ enum msg_hash_enums MSG_SETTING_DISK_IN_TRAY, MSG_FAILED_TO_SET_DISK, MSG_FAILED_TO_SET_INITIAL_DISK, - MSG_FAILED_TO_CONNECT_TO_CLIENT, - MSG_FAILED_TO_CONNECT_TO_HOST, - MSG_NETPLAY_HOST_FULL, - MSG_FAILED_TO_RECEIVE_HEADER_FROM_HOST, MSG_NETPLAY_FAILED, MSG_UNKNOWN_NETPLAY_COMMAND_RECEIVED, MSG_CONNECTING_TO_NETPLAY_HOST, @@ -1901,7 +1897,6 @@ enum msg_hash_enums MENU_LABEL(NETPLAY_INPUT_LATENCY_FRAMES_RANGE), MENU_LABEL(NETPLAY_SPECTATOR_MODE_ENABLE), MENU_LABEL(NETPLAY_TCP_UDP_PORT), - MENU_LABEL(NETPLAY_MAX_CONNECTIONS), MENU_LABEL(NETPLAY_NAT_TRAVERSAL), MENU_LABEL(NETPLAY_REQUEST_DEVICE_I), MENU_ENUM_LABEL_NETPLAY_REQUEST_DEVICE_1, @@ -2865,7 +2860,6 @@ enum msg_hash_enums MENU_ENUM_LABEL_VALUE_NOTIFICATION_SHOW_SCREENSHOT_FLASH_FAST, MENU_LABEL(NOTIFICATION_SHOW_REFRESH_RATE), - MENU_LABEL(NOTIFICATION_SHOW_NETPLAY_EXTRA), MENU_LABEL(SELECT_FILE), MENU_LABEL(SELECT_FROM_PLAYLIST), diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 15b5da29f2..de7a458e01 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -89,7 +89,6 @@ else if (recvd < 0) #define NETPLAY_MAGIC 0x52414E50 /* RANP */ -#define FULL_MAGIC 0x46554C4C /* FULL */ #define POKE_MAGIC 0x504F4B45 /* POKE */ /* @@ -808,34 +807,6 @@ static uint32_t simple_rand_uint32(void) parts[2]); } -/* - * netplay_init_socket_buffer - * - * Initialize a new socket buffer. - */ -static bool netplay_init_socket_buffer( - struct socket_buffer *sbuf, size_t size) -{ - sbuf->data = (unsigned char*)malloc(size); - if (!sbuf->data) - return false; - sbuf->bufsz = size; - sbuf->start = sbuf->read = sbuf->end = 0; - return true; -} - -/** - * netplay_deinit_socket_buffer - * - * Free a socket buffer. - */ -static void netplay_deinit_socket_buffer(struct socket_buffer *sbuf) -{ - if (sbuf->data) - free(sbuf->data); -} - - /** * netplay_handshake_init_send * @@ -907,6 +878,37 @@ static void handshake_password(void *ignore, const char *line) } #endif +/** + * netplay_deinit_socket_buffer + * + * Free a socket buffer. + */ +static void netplay_deinit_socket_buffer(struct socket_buffer *sbuf) +{ + if (sbuf->data) + free(sbuf->data); +} + + +static bool netplay_poke(netplay_t *netplay, struct netplay_connection *connection, uint32_t netplay_magic) +{ + if (!netplay || !netplay->is_server) + return false; + if (!connection || !connection->active) + return false; + if (netplay_magic != POKE_MAGIC) + return false; + + socket_close(connection->fd); + + connection->active = false; + + netplay_deinit_socket_buffer(&connection->send_packet_buffer); + netplay_deinit_socket_buffer(&connection->recv_packet_buffer); + + return true; +} + /** * netplay_handshake_init * @@ -926,43 +928,19 @@ bool netplay_handshake_init(netplay_t *netplay, uint32_t compression = 0; struct compression_transcoder *ctrans = NULL; const char *dmsg = NULL; - settings_t *settings = config_get_ptr(); - bool extra_notifications = settings->bools.notification_show_netplay_extra; memset(header, 0, sizeof(header)); - RECV(header, sizeof(header[0])) + RECV(header, sizeof(uint32_t)) { - dmsg = msg_hash_to_str( - netplay->is_server - ? MSG_FAILED_TO_CONNECT_TO_CLIENT - : MSG_FAILED_TO_CONNECT_TO_HOST); + dmsg = msg_hash_to_str(MSG_FAILED_TO_RECEIVE_HEADER_FROM_CLIENT); goto error; } netplay_magic = ntohl(header[0]); - if (netplay->is_server) - { - /* Poking the server for information? Just disconnect */ - if (netplay_magic == POKE_MAGIC) - { - socket_close(connection->fd); - connection->active = false; - netplay_deinit_socket_buffer(&connection->send_packet_buffer); - netplay_deinit_socket_buffer(&connection->recv_packet_buffer); - return true; - } - } - else - { - if (netplay_magic == FULL_MAGIC) - { - dmsg = msg_hash_to_str(MSG_NETPLAY_HOST_FULL); - goto error; - } - } - + if (netplay_poke(netplay, connection, netplay_magic)) + return true; if (netplay_magic != NETPLAY_MAGIC) { @@ -970,13 +948,9 @@ bool netplay_handshake_init(netplay_t *netplay, goto error; } - RECV(header + 1, sizeof(header) - sizeof(header[0])) + RECV(header + 1, sizeof(header) - sizeof(uint32_t)) { - dmsg = msg_hash_to_str( - netplay->is_server - ? MSG_FAILED_TO_RECEIVE_HEADER_FROM_CLIENT - : MSG_FAILED_TO_RECEIVE_HEADER_FROM_HOST); - + dmsg = msg_hash_to_str(MSG_FAILED_TO_RECEIVE_HEADER_FROM_CLIENT); goto error; } @@ -987,6 +961,14 @@ bool netplay_handshake_init(netplay_t *netplay, goto error; } + if (ntohl(header[5]) != netplay_impl_magic()) + { + /* We allow the connection but warn that this could cause issues. */ + dmsg = msg_hash_to_str(MSG_NETPLAY_DIFFERENT_VERSIONS); + RARCH_WARN("%s\n", dmsg); + runloop_msg_queue_push(dmsg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + } + /* We only care about platform magic if our core is quirky */ local_pmagic = netplay_platform_magic(); remote_pmagic = ntohl(header[1]); @@ -994,28 +976,18 @@ bool netplay_handshake_init(netplay_t *netplay, if ((netplay->quirks & NETPLAY_QUIRK_ENDIAN_DEPENDENT) && netplay_endian_mismatch(local_pmagic, remote_pmagic)) { + RARCH_ERR("Endianness mismatch with an endian-sensitive core.\n"); dmsg = msg_hash_to_str(MSG_NETPLAY_ENDIAN_DEPENDENT); goto error; } if ((netplay->quirks & NETPLAY_QUIRK_PLATFORM_DEPENDENT) && (local_pmagic != remote_pmagic)) { + RARCH_ERR("Platform mismatch with a platform-sensitive core.\n"); dmsg = msg_hash_to_str(MSG_NETPLAY_PLATFORM_DEPENDENT); goto error; } - if (ntohl(header[5]) != netplay_impl_magic()) - { - /* We allow the connection but warn that this could cause issues. */ - dmsg = msg_hash_to_str(MSG_NETPLAY_DIFFERENT_VERSIONS); - RARCH_WARN("%s\n", dmsg); - if (extra_notifications) - runloop_msg_queue_push(dmsg, 1, 180, false, NULL, - MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); - dmsg = NULL; - } - - /* Check what compression is supported */ compression = ntohl(header[2]); compression &= NETPLAY_COMPRESSION_SUPPORTED; @@ -1048,11 +1020,15 @@ bool netplay_handshake_init(netplay_t *netplay, /* Allocate our compression stream */ if (!ctrans->compression_stream) + { ctrans->compression_stream = ctrans->compression_backend->stream_new(); - if (!ctrans->decompression_stream) ctrans->decompression_stream = ctrans->decompression_backend->stream_new(); + } if (!ctrans->compression_stream || !ctrans->decompression_stream) + { + RARCH_ERR("Failed to allocate compression transcoder!\n"); return false; + } /* If a password is demanded, ask for it */ if (!netplay->is_server && (connection->salt = ntohl(header[3]))) @@ -1094,12 +1070,7 @@ error: if (dmsg) { RARCH_ERR("%s\n", dmsg); - /* These notifications are useful to the client in figuring out what caused its premature disconnection, - but they are quite useless (annoying) to the server. - Let them be optional if server. */ - if (!netplay->is_server || extra_notifications) - runloop_msg_queue_push(dmsg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); - + runloop_msg_queue_push(dmsg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); } return false; } @@ -1108,8 +1079,6 @@ static void netplay_handshake_ready(netplay_t *netplay, struct netplay_connection *connection) { char msg[512]; - settings_t *settings = config_get_ptr(); - bool extra_notifications = settings->bools.notification_show_netplay_extra; msg[0] = '\0'; if (netplay->is_server) @@ -1135,13 +1104,7 @@ static void netplay_handshake_ready(netplay_t *netplay, } RARCH_LOG("%s\n", msg); - /* Useful notification to the client in figuring out if a connection was successfully made before an error, - but not as useful to the server. - Let it be optional if server. */ - if (!netplay->is_server || extra_notifications) - runloop_msg_queue_push(msg, 1, 180, false, NULL, - MESSAGE_QUEUE_ICON_DEFAULT, - MESSAGE_QUEUE_CATEGORY_INFO); + runloop_msg_queue_push(msg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); /* Unstall if we were waiting for this */ if (netplay->stall == NETPLAY_STALL_NO_CONNECTION) @@ -1352,9 +1315,9 @@ static bool netplay_handshake_pre_nick(netplay_t *netplay, { struct nick_buf_s nick_buf; ssize_t recvd; - const char *dmsg = NULL; - settings_t *settings = config_get_ptr(); - bool extra_notifications = settings->bools.notification_show_netplay_extra; + char msg[512]; + + msg[0] = '\0'; RECV(&nick_buf, sizeof(nick_buf)) {} @@ -1363,18 +1326,15 @@ static bool netplay_handshake_pre_nick(netplay_t *netplay, ntohl(nick_buf.cmd[0]) != NETPLAY_CMD_NICK || ntohl(nick_buf.cmd[1]) != sizeof(nick_buf.nick)) { - dmsg = msg_hash_to_str( - netplay->is_server - ? MSG_FAILED_TO_GET_NICKNAME_FROM_CLIENT - : MSG_FAILED_TO_RECEIVE_NICKNAME_FROM_HOST); - RARCH_ERR("%s\n", dmsg); - /* Useful to the client in figuring out - what caused its premature disconnection, - but not as useful to the server. - Let it be optional if server. */ - if (!netplay->is_server || extra_notifications) - runloop_msg_queue_push(dmsg, 1, 180, false, NULL, - MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + if (netplay->is_server) + strlcpy(msg, msg_hash_to_str(MSG_FAILED_TO_GET_NICKNAME_FROM_CLIENT), + sizeof(msg)); + else + strlcpy(msg, + msg_hash_to_str(MSG_FAILED_TO_RECEIVE_NICKNAME_FROM_HOST), + sizeof(msg)); + RARCH_ERR("%s\n", msg); + runloop_msg_queue_push(msg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); return false; } @@ -1384,6 +1344,8 @@ static bool netplay_handshake_pre_nick(netplay_t *netplay, if (netplay->is_server) { + settings_t *settings = config_get_ptr(); + /* There's a password, so just put them in PRE_PASSWORD mode */ if ( settings->paths.netplay_password[0] || settings->paths.netplay_spectate_password[0]) @@ -1418,12 +1380,11 @@ static bool netplay_handshake_pre_password(netplay_t *netplay, char password[8+NETPLAY_PASS_LEN]; /* 8 for salt */ char hash[NETPLAY_PASS_HASH_LEN+1]; /* + NULL terminator */ ssize_t recvd; + char msg[512]; bool correct = false; settings_t *settings = config_get_ptr(); - /* Only the server should call this */ - if (!netplay->is_server) - return false; + msg[0] = '\0'; RECV(&password_buf, sizeof(password_buf)) {} @@ -1432,7 +1393,15 @@ static bool netplay_handshake_pre_password(netplay_t *netplay, ntohl(password_buf.cmd[0]) != NETPLAY_CMD_PASSWORD || ntohl(password_buf.cmd[1]) != sizeof(password_buf.password)) { - RARCH_ERR("Failed to receive netplay password.\n"); + if (netplay->is_server) + strlcpy(msg, msg_hash_to_str(MSG_FAILED_TO_GET_NICKNAME_FROM_CLIENT), + sizeof(msg)); + else + strlcpy(msg, + msg_hash_to_str(MSG_FAILED_TO_RECEIVE_NICKNAME_FROM_HOST), + sizeof(msg)); + RARCH_ERR("%s\n", msg); + runloop_msg_queue_push(msg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); return false; } @@ -1466,10 +1435,7 @@ static bool netplay_handshake_pre_password(netplay_t *netplay, /* Just disconnect if it was wrong */ if (!correct) - { - RARCH_WARN("A client tried to connect with the wrong password.\n"); return false; - } /* Otherwise, exchange info */ if (!netplay_handshake_info(netplay, connection)) @@ -1496,20 +1462,8 @@ static bool netplay_handshake_pre_info(netplay_t *netplay, uint32_t content_crc = 0; const char *dmsg = NULL; struct retro_system_info *system = &runloop_state_get_ptr()->system.info; - settings_t *settings = config_get_ptr(); - bool extra_notifications = settings->bools.notification_show_netplay_extra; - RECV(&info_buf, sizeof(info_buf.cmd)) - { - if (!netplay->is_server) - { - dmsg = msg_hash_to_str(MSG_NETPLAY_INCORRECT_PASSWORD); - RARCH_ERR("%s\n", dmsg); - runloop_msg_queue_push(dmsg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); - return false; - } - - } + RECV(&info_buf, sizeof(info_buf.cmd)) {} if (recvd < 0 || ntohl(info_buf.cmd[0]) != NETPLAY_CMD_INFO) @@ -1519,10 +1473,9 @@ static bool netplay_handshake_pre_info(netplay_t *netplay, } cmd_size = ntohl(info_buf.cmd[1]); - if (cmd_size != sizeof(info_buf) - sizeof(info_buf.cmd)) + if (cmd_size != sizeof(info_buf) - 2*sizeof(uint32_t)) { - /* Either the host doesn't have anything loaded, - or this is just screwy */ + /* Either the host doesn't have anything loaded, or this is just screwy */ if (cmd_size != 0) { /* Huh? */ @@ -1540,7 +1493,10 @@ static bool netplay_handshake_pre_info(netplay_t *netplay, } RECV(&info_buf.content_crc, cmd_size) + { + RARCH_ERR("Failed to receive netplay info payload.\n"); return false; + } /* Check the core info */ if (system) @@ -1551,15 +1507,8 @@ static bool netplay_handshake_pre_info(netplay_t *netplay, /* Wrong core! */ dmsg = msg_hash_to_str(MSG_NETPLAY_DIFFERENT_CORES); RARCH_ERR("%s\n", dmsg); - /* Useful to the client in figuring out - what caused its premature disconnection, - but not as useful to the server. - Let it be optional if server. */ - if (!netplay->is_server || extra_notifications) - runloop_msg_queue_push(dmsg, 1, 180, false, NULL, - MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); - /* FIXME: Should still send INFO, so the - other side knows what's what */ + runloop_msg_queue_push(dmsg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + /* FIXME: Should still send INFO, so the other side knows what's what */ return false; } if (strncmp(info_buf.core_version, @@ -1567,9 +1516,7 @@ static bool netplay_handshake_pre_info(netplay_t *netplay, { dmsg = msg_hash_to_str(MSG_NETPLAY_DIFFERENT_CORE_VERSIONS); RARCH_WARN("%s\n", dmsg); - if (extra_notifications) - runloop_msg_queue_push(dmsg, 1, 180, false, NULL, - MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + runloop_msg_queue_push(dmsg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); } } @@ -1582,10 +1529,7 @@ static bool netplay_handshake_pre_info(netplay_t *netplay, { dmsg = msg_hash_to_str(MSG_CONTENT_CRC32S_DIFFER); RARCH_WARN("%s\n", dmsg); - if (extra_notifications) - runloop_msg_queue_push(dmsg, 1, 180, false, NULL, - MESSAGE_QUEUE_ICON_DEFAULT, - MESSAGE_QUEUE_CATEGORY_INFO); + runloop_msg_queue_push(dmsg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); } } @@ -1626,19 +1570,21 @@ static bool netplay_handshake_pre_sync(netplay_t *netplay, char new_nick[NETPLAY_NICK_LEN]; retro_ctx_memory_info_t mem_info; - /* Only the client should call this */ - if (netplay->is_server) + RECV(cmd, sizeof(cmd)) + { + const char *msg = msg_hash_to_str(MSG_NETPLAY_INCORRECT_PASSWORD); + RARCH_ERR("%s\n", msg); + runloop_msg_queue_push(msg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); return false; - - RECV(cmd, sizeof(cmd)) {} + } /* Only expecting a sync command */ - if (recvd < 0 || - ntohl(cmd[0]) != NETPLAY_CMD_SYNC || + if (ntohl(cmd[0]) != NETPLAY_CMD_SYNC || ntohl(cmd[1]) < (2+2*MAX_INPUT_DEVICES)*sizeof(uint32_t) + (MAX_INPUT_DEVICES)*sizeof(uint8_t) + NETPLAY_NICK_LEN) { - RARCH_ERR("Failed to receive netplay sync.\n"); + RARCH_ERR("%s\n", + msg_hash_to_str(MSG_FAILED_TO_RECEIVE_SRAM_DATA_FROM_HOST)); return false; } @@ -2093,6 +2039,22 @@ static size_t buf_remaining(struct socket_buffer *sbuf) return sbuf->bufsz - buf_used(sbuf) - 1; } +/** + * netplay_init_socket_buffer + * + * Initialize a new socket buffer. + */ +static bool netplay_init_socket_buffer( + struct socket_buffer *sbuf, size_t size) +{ + sbuf->data = (unsigned char*)malloc(size); + if (!sbuf->data) + return false; + sbuf->bufsz = size; + sbuf->start = sbuf->read = sbuf->end = 0; + return true; +} + /** * netplay_resize_socket_buffer * @@ -2138,6 +2100,13 @@ static bool netplay_resize_socket_buffer( return true; } +#if 0 +static void netplay_clear_socket_buffer(struct socket_buffer *sbuf) +{ + sbuf->start = sbuf->read = sbuf->end = 0; +} +#endif + /** * netplay_send * @@ -2387,46 +2356,6 @@ void netplay_recv_flush(struct socket_buffer *sbuf) sbuf->start = sbuf->read; } -static bool netplay_full(netplay_t *netplay, int sockfd) -{ - size_t i; - settings_t *settings = config_get_ptr(); - unsigned max_connections = settings->uints.netplay_max_connections; - unsigned total = 0; - - if (max_connections) - { - for (i = 0; i < netplay->connections_size; i++) - if (netplay->connections[i].active) total++; - - if (total >= max_connections) - { - /* We send a header to let the client - know we are full */ - uint32_t header[6]; - - /* The only parameter that we need to set is - netplay magic; - we set the protocol version parameter - too for backwards compatibility */ - memset(header, 0, sizeof(header)); - header[0] = htonl(FULL_MAGIC); - header[4] = htonl(NETPLAY_PROTOCOL_VERSION); - - /* The kernel might close the socket before - sending our data. - This is fine; the header is just a warning - for the client. */ - socket_send_all_nonblocking(sockfd, header, - sizeof(header), false); - - return true; - } - } - - return false; -} - /** * netplay_cmd_crc * @@ -3091,7 +3020,10 @@ bool netplay_sync_pre_frame(netplay_t *netplay) (struct sockaddr*)&their_addr, &addr_size); if (new_fd < 0) + { + RARCH_ERR("%s\n", msg_hash_to_str(MSG_NETPLAY_FAILED)); goto process; + } /* Set the socket nonblocking */ if (!socket_nonblock(new_fd)) @@ -3103,8 +3035,15 @@ bool netplay_sync_pre_frame(netplay_t *netplay) #if defined(IPPROTO_TCP) && defined(TCP_NODELAY) { - int on = 1; - if (setsockopt(new_fd, IPPROTO_TCP, TCP_NODELAY, (const char*) &on, sizeof(on)) < 0) + int flag = 1; + if (setsockopt(new_fd, IPPROTO_TCP, TCP_NODELAY, +#ifdef _WIN32 + (const char*) +#else + (const void*) +#endif + &flag, + sizeof(int)) < 0) RARCH_WARN("Could not set netplay TCP socket to nodelay. Expect jitter.\n"); } #endif @@ -3115,13 +3054,6 @@ bool netplay_sync_pre_frame(netplay_t *netplay) RARCH_WARN("Cannot set Netplay port to close-on-exec. It may fail to reopen if the client disconnects.\n"); #endif - if (netplay_full(netplay, new_fd)) - { - /* Not accepting any more connections. */ - socket_close(new_fd); - goto process; - } - /* Allocate a connection */ for (connection_num = 0; connection_num < netplay->connections_size; connection_num++) if (!netplay->connections[connection_num].active && @@ -3574,33 +3506,20 @@ void netplay_hangup(netplay_t *netplay, char msg[512]; const char *dmsg; size_t i; - bool was_playing = false; - settings_t *settings = config_get_ptr(); -#if 0 - /* TODO/FIXME - doesn't exist yet */ - bool extra_notifications = settings->bools.notification_show_netplay_extra; -#else - bool extra_notifications = false; -#endif if (!netplay) return; if (!connection->active) return; - was_playing = - connection->mode == NETPLAY_CONNECTION_PLAYING - || connection->mode == NETPLAY_CONNECTION_SLAVE; + msg[0] = msg[sizeof(msg)-1] = '\0'; + dmsg = msg; /* Report this disconnection */ if (netplay->is_server) { if (connection->nick[0]) - { - snprintf(msg, sizeof(msg), - msg_hash_to_str(MSG_NETPLAY_SERVER_NAMED_HANGUP), connection->nick); - dmsg = msg; - } + snprintf(msg, sizeof(msg)-1, msg_hash_to_str(MSG_NETPLAY_SERVER_NAMED_HANGUP), connection->nick); else dmsg = msg_hash_to_str(MSG_NETPLAY_SERVER_HANGUP); } @@ -3617,13 +3536,8 @@ void netplay_hangup(netplay_t *netplay, #endif netplay->is_connected = false; } - RARCH_LOG("%s\n", dmsg); - /* This notification is really only important to the server if the client was playing. - * Let it be optional if server and the client wasn't playing. */ - if (!netplay->is_server || was_playing || extra_notifications) - runloop_msg_queue_push(dmsg, 1, 180, false, NULL, - MESSAGE_QUEUE_ICON_DEFAULT, - MESSAGE_QUEUE_CATEGORY_INFO); + RARCH_LOG("[netplay] %s\n", dmsg); + runloop_msg_queue_push(dmsg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); socket_close(connection->fd); connection->active = false; @@ -3636,8 +3550,9 @@ void netplay_hangup(netplay_t *netplay, netplay->connected_players &= (1L<self_client_num); for (i = 0; i < MAX_CLIENTS; i++) { - if (i != netplay->self_client_num) - netplay->client_devices[i] = 0; + if (i == netplay->self_client_num) + continue; + netplay->client_devices[i] = 0; } for (i = 0; i < MAX_INPUT_DEVICES; i++) netplay->device_clients[i] &= (1L<self_client_num); @@ -3646,17 +3561,16 @@ void netplay_hangup(netplay_t *netplay, } else { - /* Mark the player for removal */ - if (was_playing) - { - uint32_t client_num = (uint32_t) - (connection - netplay->connections + 1); + uint32_t client_num = (uint32_t)(connection - netplay->connections + 1); - /* This special mode keeps the connection object - alive long enough to send the disconnection - message at the correct time */ - connection->mode = NETPLAY_CONNECTION_DELAYED_DISCONNECT; - connection->delay_frame = netplay->read_frame_count[client_num]; + /* Mark the player for removal */ + if (connection->mode == NETPLAY_CONNECTION_PLAYING || + connection->mode == NETPLAY_CONNECTION_SLAVE) + { + /* This special mode keeps the connection object alive long enough to + * send the disconnection message at the correct time */ + connection->mode = NETPLAY_CONNECTION_DELAYED_DISCONNECT; + connection->delay_frame = netplay->read_frame_count[client_num]; /* Mark them as not playing anymore */ netplay->connected_players &= ~(1L< device_str) - pdevice_str -= 2; + { + if (!(devices & (1<connections + 1); } - if (client_num >= MAX_CLIENTS) + if (client_num > MAX_CLIENTS) { RARCH_ERR("NETPLAY_CMD_INPUT received data for an unsupported client.\n"); return netplay_cmd_nak(netplay, connection); } - if (!(netplay->connected_players & (1<client_devices[client_num]; input_size = netplay_expected_input_size(netplay, devices); @@ -4491,6 +4392,12 @@ static bool netplay_get_cmd(netplay_t *netplay, return netplay_cmd_nak(netplay, connection); } + if (client_num >= MAX_CLIENTS || !(netplay->connected_players & (1<mode == NETPLAY_CONNECTION_PLAYING) { @@ -4501,7 +4408,7 @@ static bool netplay_get_cmd(netplay_t *netplay, for (; input_size; input_size--) { RECV(&buf, sizeof(uint32_t)) - return false; + return netplay_cmd_nak(netplay, connection); } break; } @@ -4586,16 +4493,12 @@ static bool netplay_get_cmd(netplay_t *netplay, return netplay_cmd_nak(netplay, connection); } - if (cmd_size != sizeof(frame)) + RECV(&frame, sizeof(frame)) { - RARCH_ERR("NETPLAY_CMD_NOINPUT received" - " an unexpected payload size.\n"); + RARCH_ERR("Failed to receive NETPLAY_CMD_NOINPUT payload.\n"); return netplay_cmd_nak(netplay, connection); } - RECV(&frame, sizeof(frame)) - return false; - frame = ntohl(frame); /* We already had this, so ignore the new transmission */ @@ -4633,11 +4536,10 @@ static bool netplay_get_cmd(netplay_t *netplay, return netplay_cmd_nak(netplay, connection); } - if ( connection->mode != NETPLAY_CONNECTION_PLAYING - && connection->mode != NETPLAY_CONNECTION_SLAVE) + if (connection->mode != NETPLAY_CONNECTION_PLAYING && + connection->mode != NETPLAY_CONNECTION_SLAVE) { /* They were confused */ - RARCH_ERR("NETPLAY_CMD_SPECTATE from client not currently playing.\n"); return netplay_cmd_nak(netplay, connection); } @@ -4650,7 +4552,18 @@ static bool netplay_get_cmd(netplay_t *netplay, case NETPLAY_CMD_PLAY: { uint32_t client_num; - uint32_t payload; + uint32_t payload[1]; + + if (cmd_size != sizeof(uint32_t)) + { + RARCH_ERR("Incorrect NETPLAY_CMD_PLAY payload size.\n"); + return netplay_cmd_nak(netplay, connection); + } + RECV(payload, sizeof(uint32_t)) + { + RARCH_ERR("Failed to receive NETPLAY_CMD_PLAY payload.\n"); + return netplay_cmd_nak(netplay, connection); + } if (!netplay->is_server) { @@ -4658,30 +4571,19 @@ static bool netplay_get_cmd(netplay_t *netplay, return netplay_cmd_nak(netplay, connection); } - if (cmd_size != sizeof(payload)) - { - RARCH_ERR("Incorrect NETPLAY_CMD_PLAY payload size.\n"); - return netplay_cmd_nak(netplay, connection); - } - - RECV(&payload, sizeof(payload)) - return false; - if (connection->delay_frame) { - /* Can't switch modes while a mode switch - is already in progress. */ - payload = htonl(NETPLAY_CMD_MODE_REFUSED_REASON_TOO_FAST); - netplay_send_raw_cmd(netplay, connection, NETPLAY_CMD_MODE_REFUSED, &payload, sizeof(payload)); + /* Can't switch modes while a mode switch is already in progress. */ + payload[0] = htonl(NETPLAY_CMD_MODE_REFUSED_REASON_TOO_FAST); + netplay_send_raw_cmd(netplay, connection, NETPLAY_CMD_MODE_REFUSED, payload, sizeof(uint32_t)); break; } if (!connection->can_play) { /* Not allowed to play */ - payload = htonl(NETPLAY_CMD_MODE_REFUSED_REASON_UNPRIVILEGED); - netplay_send_raw_cmd(netplay, connection, - NETPLAY_CMD_MODE_REFUSED, &payload, sizeof(payload)); + payload[0] = htonl(NETPLAY_CMD_MODE_REFUSED_REASON_UNPRIVILEGED); + netplay_send_raw_cmd(netplay, connection, NETPLAY_CMD_MODE_REFUSED, payload, sizeof(uint32_t)); break; } @@ -4689,14 +4591,11 @@ static bool netplay_get_cmd(netplay_t *netplay, if ( connection->mode == NETPLAY_CONNECTION_PLAYING || connection->mode == NETPLAY_CONNECTION_SLAVE) - { - RARCH_ERR("NETPLAY_CMD_PLAY from client already playing.\n"); return netplay_cmd_nak(netplay, connection); - } client_num = (unsigned)(connection - netplay->connections + 1); - handle_play_spectate(netplay, client_num, connection, cmd, cmd_size, &payload); + handle_play_spectate(netplay, client_num, connection, cmd, cmd_size, payload); break; } @@ -4732,7 +4631,10 @@ static bool netplay_get_cmd(netplay_t *netplay, } RECV(payload, sizeof(payload)) - return false; + { + RARCH_ERR("NETPLAY_CMD_MODE failed to receive payload.\n"); + return netplay_cmd_nak(netplay, connection); + } frame = ntohl(payload[0]); @@ -4740,7 +4642,7 @@ static bool netplay_get_cmd(netplay_t *netplay, if (frame < netplay->self_frame_count) netplay->force_rewind = true; - mode = ntohl(payload[1]); + mode = ntohl(payload[1]); client_num = mode & 0xFFFF; if (client_num >= MAX_CLIENTS) { @@ -4947,15 +4849,17 @@ static bool netplay_get_cmd(netplay_t *netplay, return netplay_cmd_nak(netplay, connection); } - if (cmd_size != sizeof(reason)) + if (cmd_size != sizeof(uint32_t)) { RARCH_ERR("Received invalid payload size for NETPLAY_CMD_MODE_REFUSED.\n"); return netplay_cmd_nak(netplay, connection); } RECV(&reason, sizeof(reason)) - return false; - + { + RARCH_ERR("Failed to receive NETPLAY_CMD_MODE_REFUSED payload.\n"); + return netplay_cmd_nak(netplay, connection); + } reason = ntohl(reason); switch (reason) @@ -4976,11 +4880,13 @@ static bool netplay_get_cmd(netplay_t *netplay, dmsg = msg_hash_to_str(MSG_NETPLAY_CANNOT_PLAY); } - RARCH_LOG("%s\n", dmsg); - runloop_msg_queue_push(dmsg, 1, 180, false, NULL, - MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + if (dmsg) + { + RARCH_LOG("[netplay] %s\n", dmsg); + runloop_msg_queue_push(dmsg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + } + break; } - break; case NETPLAY_CMD_DISCONNECT: netplay_hangup(netplay, connection); @@ -4999,7 +4905,10 @@ static bool netplay_get_cmd(netplay_t *netplay, } RECV(buffer, sizeof(buffer)) - return false; + { + RARCH_ERR("NETPLAY_CMD_CRC failed to receive payload.\n"); + return netplay_cmd_nak(netplay, connection); + } buffer[0] = ntohl(buffer[0]); buffer[1] = ntohl(buffer[1]); @@ -5109,15 +5018,17 @@ static bool netplay_get_cmd(netplay_t *netplay, /* Check the payload size */ if ((cmd == NETPLAY_CMD_LOAD_SAVESTATE && (cmd_size < 2*sizeof(uint32_t) || cmd_size > netplay->zbuffer_size + 2*sizeof(uint32_t))) || - (cmd == NETPLAY_CMD_RESET && cmd_size != sizeof(frame))) + (cmd == NETPLAY_CMD_RESET && cmd_size != sizeof(uint32_t))) { RARCH_ERR("CMD_LOAD_SAVESTATE received an unexpected payload size.\n"); return netplay_cmd_nak(netplay, connection); } RECV(&frame, sizeof(frame)) - return false; - + { + RARCH_ERR("CMD_LOAD_SAVESTATE failed to receive savestate frame.\n"); + return netplay_cmd_nak(netplay, connection); + } frame = ntohl(frame); if (netplay->is_server) @@ -5147,8 +5058,10 @@ static bool netplay_get_cmd(netplay_t *netplay, if (cmd == NETPLAY_CMD_LOAD_SAVESTATE) { RECV(&isize, sizeof(isize)) - return false; - + { + RARCH_ERR("CMD_LOAD_SAVESTATE failed to receive inflated size.\n"); + return netplay_cmd_nak(netplay, connection); + } isize = ntohl(isize); if (isize != netplay->state_size) @@ -5158,7 +5071,10 @@ static bool netplay_get_cmd(netplay_t *netplay, } RECV(netplay->zbuffer, cmd_size - 2*sizeof(uint32_t)) - return false; + { + RARCH_ERR("CMD_LOAD_SAVESTATE failed to receive savestate.\n"); + return netplay_cmd_nak(netplay, connection); + } /* And decompress it */ switch (connection->compression_supported) @@ -5234,6 +5150,7 @@ static bool netplay_get_cmd(netplay_t *netplay, case NETPLAY_CMD_PAUSE: { char msg[512], nick[NETPLAY_NICK_LEN]; + msg[sizeof(msg)-1] = '\0'; /* Read in the paused nick */ if (cmd_size != sizeof(nick)) @@ -5241,10 +5158,11 @@ static bool netplay_get_cmd(netplay_t *netplay, RARCH_ERR("NETPLAY_CMD_PAUSE received invalid payload size.\n"); return netplay_cmd_nak(netplay, connection); } - RECV(nick, sizeof(nick)) - return false; - + { + RARCH_ERR("Failed to receive paused nickname.\n"); + return netplay_cmd_nak(netplay, connection); + } nick[sizeof(nick)-1] = '\0'; /* We outright ignore pausing from spectators and slaves */ @@ -5256,9 +5174,7 @@ static bool netplay_get_cmd(netplay_t *netplay, if (netplay->is_server) { /* Inform peers */ - snprintf(msg, sizeof(msg), - msg_hash_to_str(MSG_NETPLAY_PEER_PAUSED), - connection->nick); + snprintf(msg, sizeof(msg)-1, msg_hash_to_str(MSG_NETPLAY_PEER_PAUSED), connection->nick); netplay_send_raw_cmd_all(netplay, connection, NETPLAY_CMD_PAUSE, connection->nick, NETPLAY_NICK_LEN); @@ -5267,9 +5183,10 @@ static bool netplay_get_cmd(netplay_t *netplay, netplay_send_flush_all(netplay, connection); } else - snprintf(msg, sizeof(msg), - msg_hash_to_str(MSG_NETPLAY_PEER_PAUSED), nick); - RARCH_LOG("%s\n", msg); + { + snprintf(msg, sizeof(msg)-1, msg_hash_to_str(MSG_NETPLAY_PEER_PAUSED), nick); + } + RARCH_LOG("[netplay] %s\n", msg); runloop_msg_queue_push(msg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); break; } @@ -5282,27 +5199,28 @@ static bool netplay_get_cmd(netplay_t *netplay, { uint32_t frames; - if (netplay->is_server) - { - /* Only servers can request a stall! */ - RARCH_ERR("Netplay client requested a stall?\n"); - return netplay_cmd_nak(netplay, connection); - } - - if (cmd_size != sizeof(frames)) + if (cmd_size != sizeof(uint32_t)) { RARCH_ERR("NETPLAY_CMD_STALL with incorrect payload size.\n"); return netplay_cmd_nak(netplay, connection); } RECV(&frames, sizeof(frames)) - return false; - + { + RARCH_ERR("Failed to receive NETPLAY_CMD_STALL payload.\n"); + return netplay_cmd_nak(netplay, connection); + } frames = ntohl(frames); - if (frames > NETPLAY_MAX_REQ_STALL_TIME) frames = NETPLAY_MAX_REQ_STALL_TIME; + if (netplay->is_server) + { + /* Only servers can request a stall! */ + RARCH_ERR("Netplay client requested a stall?\n"); + return netplay_cmd_nak(netplay, connection); + } + /* We can only stall for one reason at a time */ if (!netplay->stall) { @@ -5314,8 +5232,7 @@ static bool netplay_get_cmd(netplay_t *netplay, } default: - RARCH_ERR("%s\n", - msg_hash_to_str(MSG_UNKNOWN_NETPLAY_COMMAND_RECEIVED)); + RARCH_ERR("%s.\n", msg_hash_to_str(MSG_UNKNOWN_NETPLAY_COMMAND_RECEIVED)); return netplay_cmd_nak(netplay, connection); } @@ -5396,14 +5313,10 @@ int netplay_poll_net_input(netplay_t *netplay, bool block) if (socket_select(max_fd, &fds, NULL, NULL, &tv) < 0) return -1; - RARCH_LOG( - "Network is stalling at frame %u, count %u of %d ...\n", - netplay->run_frame_count, - netplay->timeout_cnt, - MAX_RETRIES); + RARCH_LOG("[netplay] Network is stalling at frame %u, count %u of %d ...\n", + netplay->run_frame_count, netplay->timeout_cnt, MAX_RETRIES); - if ( netplay->timeout_cnt >= MAX_RETRIES - && !netplay->remote_paused) + if (netplay->timeout_cnt >= MAX_RETRIES && !netplay->remote_paused) return -1; } } @@ -5489,51 +5402,40 @@ void netplay_handle_slaves(netplay_t *netplay) void netplay_announce_nat_traversal(netplay_t *netplay) { #ifndef HAVE_SOCKET_LEGACY - char msg[512], host[256], port[6]; - const char *dmsg = NULL; - + char msg[4200], host[PATH_MAX_LENGTH], port[6]; + if (netplay->nat_traversal_state.have_inet4) { - if (!getnameinfo( - (const struct sockaddr *) - &netplay->nat_traversal_state.ext_inet4_addr, - sizeof(netplay->nat_traversal_state.ext_inet4_addr), - host, sizeof(host), port, sizeof(port), - NI_NUMERICHOST|NI_NUMERICSERV)) - { - snprintf(msg, sizeof(msg), "%s: %s:%s", - msg_hash_to_str(MSG_PUBLIC_ADDRESS), - host, port); - dmsg = msg; - } - + if (getnameinfo((const struct sockaddr *) &netplay->nat_traversal_state.ext_inet4_addr, + sizeof(struct sockaddr_in), + host, PATH_MAX_LENGTH, port, 6, NI_NUMERICHOST|NI_NUMERICSERV) != 0) + return; } #ifdef HAVE_INET6 else if (netplay->nat_traversal_state.have_inet6) { - if (!getnameinfo( - (const struct sockaddr *) - &netplay->nat_traversal_state.ext_inet6_addr, - sizeof(netplay->nat_traversal_state.ext_inet6_addr), - host, sizeof(host), port, sizeof(port), - NI_NUMERICHOST|NI_NUMERICSERV)) - { - snprintf(msg, sizeof(msg), "%s: %s|%s", - msg_hash_to_str(MSG_PUBLIC_ADDRESS), - host, port); - dmsg = msg; - } + if (getnameinfo((const struct sockaddr *) &netplay->nat_traversal_state.ext_inet6_addr, + sizeof(struct sockaddr_in6), + host, PATH_MAX_LENGTH, port, 6, NI_NUMERICHOST|NI_NUMERICSERV) != 0) + return; + } #endif else - dmsg = msg_hash_to_str(MSG_UPNP_FAILED); - - if (dmsg) { - RARCH_LOG("%s\n", dmsg); - runloop_msg_queue_push(dmsg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + snprintf(msg, sizeof(msg), "%s\n", + msg_hash_to_str(MSG_UPNP_FAILED)); + runloop_msg_queue_push(msg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + RARCH_LOG("[netplay] %s\n", msg); + return; } + + snprintf(msg, sizeof(msg), "%s: %s:%s\n", + msg_hash_to_str(MSG_PUBLIC_ADDRESS), + host, port); + runloop_msg_queue_push(msg, 1, 180, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + RARCH_LOG("[netplay] %s\n", msg); #endif } @@ -5553,20 +5455,26 @@ static int init_tcp_connection(const struct addrinfo *res, bool server, struct sockaddr *other_addr, socklen_t addr_size) { - char host[256], port[6]; - char msg[512]; - const char *dmsg = NULL; - int fd = socket(res->ai_family, - res->ai_socktype, res->ai_protocol); + bool ret = true; + int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (fd < 0) - return -1; + { + ret = false; + goto end; + } #if defined(IPPROTO_TCP) && defined(TCP_NODELAY) { - int on = 1; + int flag = 1; if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, - (const char*) &on, sizeof(on)) < 0) +#ifdef _WIN32 + (const char*) +#else + (const void*) +#endif + &flag, + sizeof(int)) < 0) RARCH_WARN("Could not set netplay TCP socket to nodelay. Expect jitter.\n"); } #endif @@ -5579,125 +5487,83 @@ static int init_tcp_connection(const struct addrinfo *res, if (server) { - if (!socket_connect(fd, (void*)res, false)) - return fd; - - if (!getnameinfo(res->ai_addr, res->ai_addrlen, - host, sizeof(host), port, sizeof(port), - NI_NUMERICHOST|NI_NUMERICSERV)) + if (socket_connect(fd, (void*)res, false) < 0) { - snprintf(msg, sizeof(msg), - "Failed to connect to host %s on port %s.", - host, port); - dmsg = msg; + ret = false; + goto end; } } else { #if defined(HAVE_INET6) && defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) /* Make sure we accept connections on both IPv6 and IPv4 */ + int on = 0; if (res->ai_family == AF_INET6) { - int on = 0; - if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, - (const char*)&on, sizeof(on)) < 0) + if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&on, sizeof(on)) < 0) RARCH_WARN("Failed to listen on both IPv6 and IPv4\n"); } #endif - if (socket_bind(fd, (void*)res)) + if ( !socket_bind(fd, (void*)res) || + listen(fd, 1024) < 0) { - if (!listen(fd, 1024)) - return fd; - } - else - { - if (!getnameinfo(res->ai_addr, res->ai_addrlen, - NULL, 0, port, sizeof(port), NI_NUMERICSERV)) - { - snprintf(msg, sizeof(msg), "Failed to bind port %s.", port); - dmsg = msg; - } + ret = false; + goto end; } } - socket_close(fd); +end: + if (!ret && fd >= 0) + { + socket_close(fd); + fd = -1; + } - if (dmsg) - RARCH_ERR("%s\n", dmsg); - - return -1; + return fd; } static bool init_tcp_socket(netplay_t *netplay, void *direct_host, const char *server, uint16_t port) { - struct addrinfo *res; - const struct addrinfo *tmp_info; - struct sockaddr_storage sad; - struct addrinfo hints = {0}; - int fd = -1; + char port_buf[16]; + bool ret = false; + const struct addrinfo *tmp_info = NULL; + struct addrinfo *res = NULL; + struct addrinfo hints = {0}; + + port_buf[0] = '\0'; if (!direct_host) { #ifdef HAVE_INET6 - char port_buf[6]; - snprintf(port_buf, sizeof(port_buf), "%hu", port); - + /* Default to hosting on IPv6 and IPv4 */ if (!server) - { - hints.ai_flags = AI_PASSIVE; -#ifdef HAVE_INET6 - /* Default to hosting on IPv6 and IPv4 */ hints.ai_family = AF_INET6; -#else - hints.ai_family = AF_INET; -#endif - } #endif hints.ai_socktype = SOCK_STREAM; + if (!server) + hints.ai_flags = AI_PASSIVE; - if (getaddrinfo_retro(server, port_buf, &hints, &res)) + snprintf(port_buf, sizeof(port_buf), "%hu", (unsigned short)port); + if (getaddrinfo_retro(server, port_buf, &hints, &res) != 0) { +#ifdef HAVE_INET6 + try_wildcard: if (!server) { -#ifdef HAVE_INET6 -try_ipv4: - /* Didn't work with IPv6, try IPv4 */ - hints.ai_family = AF_INET; - if (getaddrinfo_retro(server, port_buf, &hints, &res)) -#endif - { - RARCH_ERR("Failed to set a hosting address.\n"); - + /* Didn't work with IPv6, try wildcard */ + hints.ai_family = 0; + if (getaddrinfo_retro(server, port_buf, &hints, &res) != 0) return false; - } } else - { - char msg[512]; - snprintf(msg, sizeof(msg), - "Failed to resolve host: %s\n", server); - RARCH_ERR(msg); - return false; - } +#endif + return false; } if (!res) return false; - /* If we're serving on IPv6, make sure we accept all connections, including - * IPv4 */ -#ifdef HAVE_INET6 - if (!server && res->ai_family == AF_INET6) - { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) res->ai_addr; -#if defined(_MSC_VER) && _MSC_VER <= 1200 - IN6ADDR_SETANY(sin6); -#else - sin6->sin6_addr = in6addr_any; -#endif - } -#endif } else { @@ -5709,47 +5575,68 @@ try_ipv4: hints.ai_addrlen = host->addrlen; hints.ai_addr = &host->addr; res = &hints; + } + /* If we're serving on IPv6, make sure we accept all connections, including + * IPv4 */ +#ifdef HAVE_INET6 + if (!direct_host && !server && res->ai_family == AF_INET6) + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) res->ai_addr; +#if defined(_MSC_VER) && _MSC_VER <= 1200 + IN6ADDR_SETANY(sin6); +#else + sin6->sin6_addr = in6addr_any; +#endif + } +#endif + /* If "localhost" is used, it is important to check every possible * address for IPv4/IPv6. */ tmp_info = res; - do + while (tmp_info) { - fd = init_tcp_connection( - tmp_info, direct_host || server, - (struct sockaddr *) - memset(&sad, 0, sizeof(sad)), sizeof(sad)); + struct sockaddr_storage sad = {0}; + int fd = init_tcp_connection( + tmp_info, + direct_host || server, + (struct sockaddr*)&sad, + sizeof(sad)); if (fd >= 0) + { + ret = true; + if (direct_host || server) + { + netplay->connections[0].active = true; + netplay->connections[0].fd = fd; + netplay->connections[0].addr = sad; + } + else + { + netplay->listen_fd = fd; + } break; - } while ((tmp_info = tmp_info->ai_next)); + } - if (!direct_host) + tmp_info = tmp_info->ai_next; + } + + if (res && !direct_host) freeaddrinfo_retro(res); - res = NULL; - if (fd < 0) + if (!ret) { #ifdef HAVE_INET6 - if (!direct_host && !server && hints.ai_family == AF_INET6) - goto try_ipv4; + if (!direct_host && (hints.ai_family == AF_INET6)) + goto try_wildcard; #endif RARCH_ERR("Failed to set up netplay sockets.\n"); - return false; } - if (direct_host || server) - { - netplay->connections[0].active = true; - netplay->connections[0].fd = fd; - netplay->connections[0].addr = sad; - } - else - netplay->listen_fd = fd; - - return true; + return ret; } static bool init_socket(netplay_t *netplay, void *direct_host, @@ -6095,16 +5982,15 @@ void netplay_free(netplay_t *netplay) free(netplay->zbuffer); if (netplay->compress_nil.compression_stream) - netplay->compress_nil.compression_backend->stream_free( - netplay->compress_nil.compression_stream); - if (netplay->compress_nil.decompression_stream) - netplay->compress_nil.decompression_backend->stream_free( - netplay->compress_nil.decompression_stream); - + { + netplay->compress_nil.compression_backend->stream_free(netplay->compress_nil.compression_stream); + netplay->compress_nil.decompression_backend->stream_free(netplay->compress_nil.decompression_stream); + } if (netplay->compress_zlib.compression_stream) + { netplay->compress_zlib.compression_backend->stream_free(netplay->compress_zlib.compression_stream); - if (netplay->compress_zlib.decompression_stream) netplay->compress_zlib.decompression_backend->stream_free(netplay->compress_zlib.decompression_stream); + } if (netplay->addr) freeaddrinfo_retro(netplay->addr); diff --git a/ui/drivers/qt/qt_options.cpp b/ui/drivers/qt/qt_options.cpp index e6d17a28c8..3f0a5da757 100644 --- a/ui/drivers/qt/qt_options.cpp +++ b/ui/drivers/qt/qt_options.cpp @@ -416,7 +416,6 @@ QWidget *NetplayPage::widget() serverForm->add(MENU_ENUM_LABEL_NETPLAY_IP_ADDRESS); serverForm->add(MENU_ENUM_LABEL_NETPLAY_TCP_UDP_PORT); - serverForm->add(MENU_ENUM_LABEL_NETPLAY_MAX_CONNECTIONS); serverForm->add(MENU_ENUM_LABEL_NETPLAY_PASSWORD); serverForm->add(MENU_ENUM_LABEL_NETPLAY_SPECTATE_PASSWORD); serverForm->add(MENU_ENUM_LABEL_NETPLAY_NAT_TRAVERSAL); @@ -594,7 +593,6 @@ QWidget *NotificationsPage::widget() notificationsGroup->add(MENU_ENUM_LABEL_NOTIFICATION_SHOW_SCREENSHOT_DURATION); notificationsGroup->add(MENU_ENUM_LABEL_NOTIFICATION_SHOW_SCREENSHOT_FLASH); notificationsGroup->add(MENU_ENUM_LABEL_NOTIFICATION_SHOW_REFRESH_RATE); - notificationsGroup->add(MENU_ENUM_LABEL_NOTIFICATION_SHOW_NETPLAY_EXTRA); layout->addWidget(notificationsGroup);