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 || delta->frame == 1)) { delta->crc = netplay_delta_frame_crc(netplay, delta); netplay_cmd_crc(netplay, delta); } } 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) { 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); } } } }
static bool netplay_net_info_cb(netplay_t* netplay, unsigned frames) { if (!netplay_is_server(netplay)) { if (!netplay_handshake(netplay)) return false; netplay->has_connection = true; } return true; }
static bool netplay_net_info_cb(netplay_t* netplay, unsigned frames) { if (netplay_is_server(netplay)) { if (!netplay_send_info(netplay)) return false; } else { if (!netplay_get_info(netplay)) return false; } netplay->buffer_size = frames + 1; if (!netplay_net_init_buffers(netplay)) return false; netplay->has_connection = true; return true; }
/** * netplay_poll: * @netplay : pointer to netplay object * * Polls network to see if we have anything new. If our * network buffer is full, we simply have to block * for new input data. * * Returns: true (1) if successful, otherwise false (0). **/ static bool netplay_poll(void) { int res; if (!netplay_data->has_connection) return false; netplay_data->can_poll = false; get_self_input_state(netplay_data); /* No network side in spectate mode */ if (netplay_is_server(netplay_data) && netplay_data->spectate.enabled) return true; /* Read Netplay input, block if we're configured to stall for input every * frame */ if (netplay_data->stall_frames == 0 && netplay_data->read_frame_count <= netplay_data->self_frame_count) res = poll_input(netplay_data, true); else res = poll_input(netplay_data, false); if (res == -1) { hangup(netplay_data); return false; } /* Simulate the input if we don't have real input */ if (!netplay_data->buffer[netplay_data->self_ptr].have_remote) netplay_simulate_input(netplay_data, netplay_data->self_ptr); /* Consider stalling */ switch (netplay_data->stall) { case RARCH_NETPLAY_STALL_RUNNING_FAST: if (netplay_data->read_frame_count >= netplay_data->self_frame_count) netplay_data->stall = RARCH_NETPLAY_STALL_NONE; break; default: /* not stalling */ if (netplay_data->read_frame_count + netplay_data->stall_frames <= netplay_data->self_frame_count) { netplay_data->stall = RARCH_NETPLAY_STALL_RUNNING_FAST; netplay_data->stall_time = cpu_features_get_time_usec(); } } /* If we're stalling, consider disconnection */ if (netplay_data->stall) { retro_time_t now = cpu_features_get_time_usec(); /* Don't stall out while they're paused */ if (netplay_data->remote_paused) netplay_data->stall_time = now; else if (now - netplay_data->stall_time >= MAX_STALL_TIME_USEC) { /* Stalled out! */ hangup(netplay_data); return false; } } return true; }