diff --git a/network/netplay/netplay.c b/network/netplay/netplay.c index e797b02451..f7066ddf4a 100644 --- a/network/netplay/netplay.c +++ b/network/netplay/netplay.c @@ -143,7 +143,7 @@ static bool send_chunk(netplay_t *netplay) **/ static bool get_self_input_state(netplay_t *netplay) { - uint32_t state[WORDS_PER_FRAME - 1] = {0}; + uint32_t state[WORDS_PER_FRAME - 1] = {0, 0, 0}; struct delta_frame *ptr = &netplay->buffer[netplay->self_ptr]; if (!netplay_delta_frame_ready(netplay, ptr, netplay->self_frame_count)) @@ -261,9 +261,9 @@ static bool netplay_get_cmd(netplay_t *netplay) uint32_t flip_frame; uint32_t cmd_size; - /* If we're not ready for input, wait until we are. Could fill the TCP buffer, stalling the other side. */ - if (!netplay_delta_frame_ready(netplay, &netplay->buffer[netplay->read_ptr], netplay->read_frame_count)) - return false; + /* FIXME: This depends on delta_frame_ready */ + + netplay->timeout_cnt = 0; if (!socket_receive_all_blocking(netplay->fd, &cmd, sizeof(cmd))) return false; @@ -314,7 +314,6 @@ static bool netplay_get_cmd(netplay_t *netplay) memcpy(netplay->buffer[netplay->read_ptr].real_input_state, buffer + 1, sizeof(buffer) - sizeof(uint32_t)); netplay->read_ptr = NEXT_PTR(netplay->read_ptr); netplay->read_frame_count++; - netplay->timeout_cnt = 0; return true; } @@ -409,9 +408,13 @@ static int poll_input(netplay_t *netplay, bool block) * but we aren't using the TCP connection for anything useful atm. */ if (FD_ISSET(netplay->fd, &fds)) { - had_input = true; - if (!netplay_get_cmd(netplay)) - return -1; + /* If we're not ready for input, wait until we are. Could fill the TCP buffer, stalling the other side. */ + if (netplay_delta_frame_ready(netplay, &netplay->buffer[netplay->read_ptr], netplay->read_frame_count)) + { + had_input = true; + if (!netplay_get_cmd(netplay)) + return -1; + } } #if 0 @@ -431,9 +434,9 @@ static int poll_input(netplay_t *netplay, bool block) } #endif - RARCH_LOG("Network is stalling, resending packet... Count %u of %d ...\n", - netplay->timeout_cnt, MAX_RETRIES); - } while (had_input); + RARCH_LOG("Network is stalling at frame %u, count %u of %d ...\n", + netplay->self_frame_count, netplay->timeout_cnt, MAX_RETRIES); + } while (had_input || (block && (netplay->read_frame_count <= netplay->self_frame_count))); /*if (block) return -1;*/ @@ -521,9 +524,13 @@ static bool netplay_poll(netplay_t *netplay) netplay->can_poll = false; +#if 0 if (!get_self_input_state(netplay)) return false; +#endif + get_self_input_state(netplay); +#if 0 /* We skip reading the first frame so the host has a chance to grab * our host info so we don't block forever :') */ if (netplay->self_frame_count == 0) @@ -538,9 +545,11 @@ static bool netplay_poll(netplay_t *netplay) netplay->read_frame_count++; return true; } +#endif - /* Read Netplay input */ - res = poll_input(netplay, 0); /* FIXME: configure stalling intervals */ + /* Read Netplay input, block if we're configured to stall for input every + * frame */ + res = poll_input(netplay, netplay->stall_frames == 0); if (res == -1) { netplay->has_connection = false; @@ -580,8 +589,8 @@ static bool netplay_poll(netplay_t *netplay) if (netplay->read_frame_count < netplay->self_frame_count) simulate_input(netplay); - else - netplay->buffer[PREV_PTR(netplay->self_ptr)].used_real = true; + /*else + netplay->buffer[PREV_PTR(netplay->self_ptr)].used_real = true;*/ /* Consider stalling */ switch (netplay->stall) { @@ -591,7 +600,7 @@ static bool netplay_poll(netplay_t *netplay) break; default: /* not stalling */ - if (netplay->read_frame_count < netplay->self_frame_count - 10) + if (netplay->read_frame_count + netplay->stall_frames <= netplay->self_frame_count) netplay->stall = RARCH_NETPLAY_STALL_RUNNING_FAST; } @@ -774,6 +783,9 @@ static int init_tcp_connection(const struct addrinfo *res, { bool ret = true; int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + int flag = 1; + + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int)); if (fd < 0) { @@ -937,11 +949,9 @@ netplay_t *netplay_new(const char *server, uint16_t port, bool spectate, const char *nick) { + uint32_t buffer_frames; netplay_t *netplay = NULL; - /*if (frames > UDP_FRAME_PACKETS) - frames = UDP_FRAME_PACKETS;*/ - netplay = (netplay_t*)calloc(1, sizeof(*netplay)); if (!netplay) return NULL; @@ -953,6 +963,7 @@ netplay_t *netplay_new(const char *server, uint16_t port, netplay->spectate.enabled = spectate; netplay->is_server = server == NULL; strlcpy(netplay->nick, nick, sizeof(netplay->nick)); + netplay->stall_frames = frames; if(spectate) netplay->net_cbs = netplay_get_cbs_spectate(); diff --git a/network/netplay/netplay_common.c b/network/netplay/netplay_common.c index cbcceedf24..2468c0102c 100644 --- a/network/netplay/netplay_common.c +++ b/network/netplay/netplay_common.c @@ -348,14 +348,18 @@ bool netplay_is_spectate(netplay_t* netplay) bool netplay_delta_frame_ready(netplay_t *netplay, struct delta_frame *delta, uint32_t frame) { void *remember_state; - if (delta->frame == frame) return true; - if (netplay->other_frame_count <= delta->frame) + if (delta->used) { - /* We haven't even replayed this frame yet, so we can't overwrite it! */ - return false; + if (delta->frame == frame) return true; + if (netplay->other_frame_count <= delta->frame) + { + /* We haven't even replayed this frame yet, so we can't overwrite it! */ + return false; + } } remember_state = delta->state; memset(delta, 0, sizeof(struct delta_frame)); + delta->used = true; delta->frame = frame; delta->state = remember_state; return true; diff --git a/network/netplay/netplay_net.c b/network/netplay/netplay_net.c index f02b79ce20..33ef8d521f 100644 --- a/network/netplay/netplay_net.c +++ b/network/netplay/netplay_net.c @@ -36,7 +36,12 @@ static void netplay_net_pre_frame(netplay_t *netplay) serial_info.data = netplay->buffer[netplay->self_ptr].state; serial_info.size = netplay->state_size; - core_serialize(&serial_info); + if (!core_serialize(&serial_info)) + { + /* If the core can't serialize properly, we must stall for the + * remote input on EVERY frame, because we can't recover */ + netplay->stall_frames = 0; + } } netplay->can_poll = true; @@ -55,9 +60,11 @@ static void netplay_net_post_frame(netplay_t *netplay) { netplay->self_frame_count++; +#if 0 /* Nothing to do... */ if (netplay->other_frame_count == netplay->read_frame_count) return; +#endif /* Skip ahead if we predicted correctly. * Skip until our simulation failed. */ @@ -80,8 +87,8 @@ static void netplay_net_post_frame(netplay_t *netplay) /* Replay frames. */ netplay->is_replay = true; - netplay->replay_ptr = PREV_PTR(netplay->other_ptr); - netplay->replay_frame_count = netplay->other_frame_count - 1; + netplay->replay_ptr = netplay->other_ptr; + netplay->replay_frame_count = netplay->other_frame_count; if (netplay->replay_frame_count < netplay->self_frame_count) { @@ -114,7 +121,7 @@ static void netplay_net_post_frame(netplay_t *netplay) /* For the remainder of the frames up to the read count, we can use the real data */ while (netplay->replay_frame_count < netplay->read_frame_count) { - netplay->buffer[netplay->replay_ptr].used_real = true; + /*netplay->buffer[netplay->replay_ptr].used_real = true;*/ netplay->replay_ptr = NEXT_PTR(netplay->replay_ptr); netplay->replay_frame_count++; } @@ -222,7 +229,11 @@ static bool netplay_net_info_cb(netplay_t* netplay, unsigned frames) return false; } - netplay->buffer_size = frames + 1; + /* * 2 + 1 because: + * Self sits in the middle, + * Other is allowed to drift as much as 'frames' frames behind + * Read is allowed to drift as much as 'frames' frames ahead */ + netplay->buffer_size = frames * 2 + 1; if (!netplay_net_init_buffers(netplay)) return false; diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h index 66543e4265..9e6bd71749 100644 --- a/network/netplay/netplay_private.h +++ b/network/netplay/netplay_private.h @@ -41,6 +41,7 @@ struct delta_frame { + bool used; /* a bit derpy, but this is how we know if the delta's been used at all */ uint32_t frame; void *state; @@ -143,6 +144,7 @@ struct netplay uint32_t pause_frame; /* And stalling */ + uint32_t stall_frames; int stall; struct netplay_callbacks* net_cbs;