bool netplay_cmd_request_savestate(netplay_t *netplay) { if (netplay->savestate_request_outstanding) return true; netplay->savestate_request_outstanding = true; return netplay_send_raw_cmd(netplay, NETPLAY_CMD_REQUEST_SAVESTATE, NULL, 0); }
bool netplay_cmd_crc(netplay_t *netplay, struct delta_frame *delta) { uint32_t payload[2]; payload[0] = htonl(delta->frame); payload[1] = htonl(delta->crc); return netplay_send_raw_cmd(netplay, NETPLAY_CMD_CRC, payload, sizeof(payload)); }
/** * netplay_frontend_paused * @netplay : pointer to netplay object * @paused : true if frontend is paused * * Inform Netplay of the frontend's pause state (paused or otherwise) */ static void netplay_frontend_paused(netplay_t *netplay, bool paused) { size_t i; uint32_t paused_ct; /* Nothing to do if we already knew this */ if (netplay->local_paused == paused) return; netplay->local_paused = paused; /* Communicating this is a bit odd: If exactly one other connection is * paused, then we must tell them that we're unpaused, as from their * perspective we are. If more than one other connection is paused, then our * status as proxy means we are NOT unpaused to either of them. */ paused_ct = 0; for (i = 0; i < netplay->connections_size; i++) { struct netplay_connection *connection = &netplay->connections[i]; if (connection->active && connection->paused) paused_ct++; } if (paused_ct > 1) return; /* Send our unpaused status. Must send manually because we must immediately * flush the buffer: If we're paused, we won't be polled. */ for (i = 0; i < netplay->connections_size; i++) { struct netplay_connection *connection = &netplay->connections[i]; if (connection->active && connection->mode >= NETPLAY_CONNECTION_CONNECTED) { if (paused) netplay_send_raw_cmd(netplay, connection, NETPLAY_CMD_PAUSE, netplay->nick, NETPLAY_NICK_LEN); else netplay_send_raw_cmd(netplay, connection, NETPLAY_CMD_RESUME, NULL, 0); /* We're not going to be polled, so we need to flush this command now */ netplay_send_flush(&connection->send_packet_buffer, connection->fd, true); } } }
/** * netplay_frontend_paused * @netplay : pointer to netplay object * @paused : true if frontend is paused * * Inform Netplay of the frontend's pause state (paused or otherwise) **/ void netplay_frontend_paused(netplay_t *netplay, bool paused) { /* Nothing to do if we already knew this */ if (netplay->local_paused == paused) return; netplay->local_paused = paused; if (netplay->has_connection && !netplay->spectate.enabled) netplay_send_raw_cmd(netplay, paused ? NETPLAY_CMD_PAUSE : NETPLAY_CMD_RESUME, NULL, 0); }
/** * netplay_command: * @netplay : pointer to netplay object * @cmd : command to send * @data : data to send as argument * @sz : size of data * @command_str : name of action * @success_msg : message to display upon success * * Sends a single netplay command and waits for response. Only actually used * for player flipping. FIXME: Should probably just be removed. */ bool netplay_command(netplay_t* netplay, struct netplay_connection *connection, enum netplay_cmd cmd, void* data, size_t sz, const char* command_str, const char* success_msg) { retro_assert(netplay); if (!netplay_send_raw_cmd(netplay, connection, cmd, data, sz)) return false; runloop_msg_queue_push(success_msg, 1, 180, false); return true; }
/** * netplay_command: * @netplay : pointer to netplay object * @cmd : command to send * @data : data to send as argument * @sz : size of data * @flags : flags of CMD_OPT_* * @command_str : name of action * @success_msg : message to display upon success * * Sends a single netplay command and waits for response. */ bool netplay_command(netplay_t* netplay, enum netplay_cmd cmd, void* data, size_t sz, uint32_t flags, const char* command_str, const char* success_msg) { char m[256]; const char* msg = NULL; bool allowed_spectate = !!(flags & CMD_OPT_ALLOWED_IN_SPECTATE_MODE); bool host_only = !!(flags & CMD_OPT_HOST_ONLY); bool require_sync = !!(flags & CMD_OPT_REQUIRE_SYNC); assert(netplay); if (netplay->spectate.enabled && !allowed_spectate) { msg = "Cannot %s in spectate mode."; goto error; } if (host_only && netplay->port == 0) { msg = "Cannot %s as a client."; goto error; } if(require_sync && check_netplay_synched(netplay)) { msg = "Cannot %s while host and client are not in sync."; goto error; } if(netplay_send_raw_cmd(netplay, cmd, data, sz)) { if(netplay_get_response(netplay)) runloop_msg_queue_push(success_msg, 1, 180, false); else { msg = "Failed to send command \"%s\""; goto error; } } return true; error: snprintf(m, sizeof(m), msg, command_str); RARCH_WARN("%s\n", m); runloop_msg_queue_push(m, 1, 180, false); return false; }
/** * netplay_command: * @netplay : pointer to netplay object * @cmd : command to send * @data : data to send as argument * @sz : size of data * @flags : flags of CMD_OPT_* * @command_str : name of action * @success_msg : message to display upon success * * Sends a single netplay command and waits for response. */ bool netplay_command(netplay_t* netplay, enum netplay_cmd cmd, void* data, size_t sz, uint32_t flags, const char* command_str, const char* success_msg) { char m[256]; const char* msg = NULL; bool allowed_spectate = !!(flags & CMD_OPT_ALLOWED_IN_SPECTATE_MODE); bool host_only = !!(flags & CMD_OPT_HOST_ONLY); retro_assert(netplay); if (netplay->spectate.enabled && !allowed_spectate) { msg = "Cannot %s in spectate mode."; goto error; } if (host_only && netplay->port == 0) { msg = "Cannot %s as a client."; goto error; } if (!netplay_send_raw_cmd(netplay, cmd, data, sz)) goto error; runloop_msg_queue_push(success_msg, 1, 180, false); return true; error: if (msg) snprintf(m, sizeof(m), msg, command_str); RARCH_WARN("%s\n", m); runloop_msg_queue_push(m, 1, 180, false); return false; }
static bool netplay_cmd_nak(netplay_t *netplay) { return netplay_send_raw_cmd(netplay, NETPLAY_CMD_NAK, NULL, 0); }