From 49b41436871f20d445aa026f03882b10b4be56f4 Mon Sep 17 00:00:00 2001 From: Gregor Richards Date: Wed, 5 Oct 2016 07:52:14 -0400 Subject: [PATCH 1/3] Reviving netplay_log_connection, i.e. connection messages on the host --- network/netplay/netplay.c | 29 +++++++++++++++++++++++++---- network/netplay/netplay_common.c | 2 -- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/network/netplay/netplay.c b/network/netplay/netplay.c index e4f5c90f86..d8593fcd5f 100644 --- a/network/netplay/netplay.c +++ b/network/netplay/netplay.c @@ -898,6 +898,7 @@ void netplay_log_connection(const struct sockaddr_storage *their_addr, const char *str = NULL; char buf_v4[INET_ADDRSTRLEN] = {0}; char buf_v6[INET6_ADDRSTRLEN] = {0}; + char msg[512] = {0}; u.storage = their_addr; @@ -937,14 +938,34 @@ void netplay_log_connection(const struct sockaddr_storage *their_addr, if (str) { - char msg[512] = {0}; - - snprintf(msg, sizeof(msg), "Got connection from: \"%s (%s)\" (#%u)", - nick, str, slot); + snprintf(msg, sizeof(msg), "Got connection from: \"%s (%s)\"", + nick, str); runloop_msg_queue_push(msg, 1, 180, false); RARCH_LOG("%s\n", msg); } + else + { + snprintf(msg, sizeof(msg), "Got connection from: \"%s\"", + nick); + runloop_msg_queue_push(msg, 1, 180, false); + RARCH_LOG("%s\n", msg); + } + RARCH_LOG("Connection slot %u\n", slot); } + +#else +void netplay_log_connection(const struct sockaddr_storage *their_addr, + unsigned slot, const char *nick) +{ + char msg[512] = {0}; + + snprintf(msg, sizeof(msg), "Got connection from: \"%s\"", + nick); + runloop_msg_queue_push(msg, 1, 180, false); + RARCH_LOG("%s\n", msg); + RARCH_LOG("Connection slot %u\n", slot); +} + #endif diff --git a/network/netplay/netplay_common.c b/network/netplay/netplay_common.c index 03c01afd21..dc2033978b 100644 --- a/network/netplay/netplay_common.c +++ b/network/netplay/netplay_common.c @@ -339,9 +339,7 @@ bool netplay_get_info(netplay_t *netplay) } } -#ifndef HAVE_SOCKET_LEGACY netplay_log_connection(&netplay->other_addr, 0, netplay->other_nick); -#endif return true; } From 60153e703511e49d4c2c56831954e498b5dac047 Mon Sep 17 00:00:00 2001 From: Gregor Richards Date: Wed, 5 Oct 2016 07:55:30 -0400 Subject: [PATCH 2/3] Ignore check_frames if CRCs are utterly inconsistent This effectively disables check_frames if frame 1's CRC differs between host and client. This is necessary because some important cores have nondeterminism in core_run, thus mandating check_frames, while some important cores have nondeterminism in core_serialize, thus mandating no check_frames. --- network/netplay/netplay_net.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/network/netplay/netplay_net.c b/network/netplay/netplay_net.c index 2562f48231..0b544f95b4 100644 --- a/network/netplay/netplay_net.c +++ b/network/netplay/netplay_net.c @@ -31,22 +31,33 @@ static void netplay_handle_frame_hash(netplay_t *netplay, struct delta_frame *delta) { + static bool crcs_valid = true; if (netplay_is_server(netplay)) { - if (netplay->check_frames && delta->frame % netplay->check_frames == 0) + if (netplay->check_frames && + (delta->frame % netplay->check_frames == 0 || delta->frame == 1)) { delta->crc = netplay_delta_frame_crc(netplay, delta); netplay_cmd_crc(netplay, delta); } } - else if (delta->crc) + else if (delta->crc && crcs_valid) { /* We have a remote CRC, so check it */ uint32_t local_crc = netplay_delta_frame_crc(netplay, delta); if (local_crc != delta->crc) { - /* Fix this! */ - netplay_cmd_request_savestate(netplay); + if (delta->frame == 1) + { + /* We check frame 1 just to make sure the CRCs make sense at all. + * If we've diverged at frame 1, we assume CRCs are not useful. */ + crcs_valid = false; + } + else if (crcs_valid) + { + /* Fix this! */ + netplay_cmd_request_savestate(netplay); + } } } } From e65a63e5d511f0b0b4794cd3ed74ba73b46fa675 Mon Sep 17 00:00:00 2001 From: Gregor Richards Date: Wed, 5 Oct 2016 07:58:01 -0400 Subject: [PATCH 3/3] Add support for debugging core nondeterminism This adds a debug flag to netplay_net (DEBUG_NONDETERMINISTIC_CORES) which helps determine if a core has nondeterminism. --- network/netplay/netplay_net.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/network/netplay/netplay_net.c b/network/netplay/netplay_net.c index 0b544f95b4..dbb82e910b 100644 --- a/network/netplay/netplay_net.c +++ b/network/netplay/netplay_net.c @@ -27,7 +27,9 @@ #include "../../autosave.h" -#define TOO_EARLY_TO_SAVE 60 +#if 0 +#define DEBUG_NONDETERMINISTIC_CORES +#endif static void netplay_handle_frame_hash(netplay_t *netplay, struct delta_frame *delta) { @@ -195,6 +197,7 @@ static void netplay_net_post_frame(netplay_t *netplay) return; } +#ifndef DEBUG_NONDETERMINISTIC_CORES if (!netplay->force_rewind) { /* Skip ahead if we predicted correctly. @@ -213,6 +216,7 @@ static void netplay_net_post_frame(netplay_t *netplay) netplay->other_frame_count++; } } +#endif /* Now replay the real input if we've gotten ahead of it */ if (netplay->force_rewind || @@ -257,6 +261,22 @@ static void netplay_net_post_frame(netplay_t *netplay) autosave_unlock(); netplay->replay_ptr = NEXT_PTR(netplay->replay_ptr); netplay->replay_frame_count++; + +#ifdef DEBUG_NONDETERMINISTIC_CORES + if (ptr->have_remote && netplay_delta_frame_ready(netplay, &netplay->buffer[netplay->replay_ptr], netplay->replay_frame_count)) + { + RARCH_LOG("PRE %u: %X\n", netplay->replay_frame_count-1, netplay_delta_frame_crc(netplay, ptr)); + if (netplay->is_server) + RARCH_LOG("INP %X %X\n", ptr->real_input_state[0], ptr->self_state[0]); + else + RARCH_LOG("INP %X %X\n", ptr->self_state[0], ptr->real_input_state[0]); + ptr = &netplay->buffer[netplay->replay_ptr]; + serial_info.data = ptr->state; + memset(serial_info.data, 0, serial_info.size); + core_serialize(&serial_info); + RARCH_LOG("POST %u: %X\n", netplay->replay_frame_count-1, netplay_delta_frame_crc(netplay, ptr)); + } +#endif } if (netplay->read_frame_count < netplay->self_frame_count)