RetroArch/network/netplay/netplay_private.h

539 lines
15 KiB
C
Raw Normal View History

2015-12-23 13:25:28 -07:00
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
2016-01-10 04:06:50 +01:00
* Copyright (C) 2011-2016 - Daniel De Matteis
* Copyright (C) 2016 - Gregor Richards
2015-12-23 13:25:28 -07:00
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RARCH_NETPLAY_PRIVATE_H
#define __RARCH_NETPLAY_PRIVATE_H
2015-12-23 13:25:28 -07:00
#include "netplay.h"
2016-05-09 20:30:47 +02:00
2015-12-23 13:25:28 -07:00
#include <net/net_compat.h>
#include <net/net_natt.h>
#include <features/features_cpu.h>
#include <streams/trans_stream.h>
2015-12-23 13:25:28 -07:00
#include <retro_endianness.h>
2016-05-09 20:30:47 +02:00
2016-09-06 06:11:44 +02:00
#include "../../core.h"
#include "../../msg_hash.h"
#include "../../verbosity.h"
2015-12-23 13:25:28 -07:00
#ifdef ANDROID
#define HAVE_IPV6
#endif
#define WORDS_PER_FRAME 4 /* Allows us to send 128 bits worth of state per frame. */
#define MAX_SPECTATORS 16
#define RARCH_DEFAULT_PORT 55435
2016-12-02 22:40:26 -05:00
#define RARCH_DEFAULT_NICK "Anonymous"
2015-12-23 13:25:28 -07:00
#define NETPLAY_PROTOCOL_VERSION 4
Multitudinous fixes and updates to Netplay. Had to be one commit since they're mostly related: (1) Renamed frame_count to self_frame_count to be consistent with all other names. (2) Previously, it was possible to overwrite data in the ring buffer that hadn't yet been used. Now that's not possible, but that just changes one breakage for another: It's now possible to miss the NEW data. The final resolution for this will probably be requesting stalls. This is accomplished simply by storing frame numbers in the ring buffer and checking them against the 'other' head. (3) In TCP packets, separated cmd_size from cmd. It was beyond pointless for these to be combined, and restricted cmd_size to 16 bits, which will probably fail when/if state loading is supported. (4) Readahead is now allowed. In the past, if the peer got ahead of us, we would simply ignore their data. Thus, if they got too far ahead of us, we'd stop reading their data altogether. Fabulous. Now, we're happy to read future input. (5) If the peer gets too far ahead of us (currently an unconfigurable 10 frames), fast forward to catch up. This should prevent desync due to clock drift or stutter. (6) Used frame_count in a few places where ptr was used. Doing a comparison of pointers on a ring buffer is a far more dangerous way to assure we're done with a task than simply using the count, since the ring buffer is... well, a ring. (7) Renamed tmp_{ptr,frame_count} to replay_{ptr,frame_count} for clarity. (8) Slightly changed the protocol version hash, just to assure that other clients wouldn't think they were compatible with this one. (9) There was an off-by-one error which, under some circumstances, could allow the replay engine to run a complete round through the ring buffer, replaying stale data. Fixed.
2016-09-11 22:01:47 -04:00
2015-12-23 13:25:28 -07:00
#define PREV_PTR(x) ((x) == 0 ? netplay->buffer_size - 1 : (x) - 1)
#define NEXT_PTR(x) ((x + 1) % netplay->buffer_size)
/* Quirks mandated by how particular cores save states. This is distilled from
* the larger set of quirks that the quirks environment can communicate. */
#define NETPLAY_QUIRK_NO_SAVESTATES (1<<0)
#define NETPLAY_QUIRK_NO_TRANSMISSION (1<<1)
#define NETPLAY_QUIRK_INITIALIZATION (1<<2)
#define NETPLAY_QUIRK_ENDIAN_DEPENDENT (1<<3)
#define NETPLAY_QUIRK_PLATFORM_DEPENDENT (1<<4)
/* Mapping of serialization quirks to netplay quirks. */
#define NETPLAY_QUIRK_MAP_UNDERSTOOD \
(RETRO_SERIALIZATION_QUIRK_INCOMPLETE \
|RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE \
|RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION \
|RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT \
|RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT)
#define NETPLAY_QUIRK_MAP_NO_SAVESTATES \
(RETRO_SERIALIZATION_QUIRK_INCOMPLETE)
#define NETPLAY_QUIRK_MAP_NO_TRANSMISSION \
(RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION)
#define NETPLAY_QUIRK_MAP_INITIALIZATION \
(RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE)
#define NETPLAY_QUIRK_MAP_ENDIAN_DEPENDENT \
(RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT)
#define NETPLAY_QUIRK_MAP_PLATFORM_DEPENDENT \
(RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT)
/* Compression protocols supported */
#define NETPLAY_COMPRESSION_ZLIB (1<<0)
#if HAVE_ZLIB
#define NETPLAY_COMPRESSION_SUPPORTED NETPLAY_COMPRESSION_ZLIB
#else
#define NETPLAY_COMPRESSION_SUPPORTED 0
#endif
enum netplay_cmd
{
/* Basic commands */
/* Acknowlegement response */
NETPLAY_CMD_ACK = 0x0000,
/* Failed acknowlegement response */
NETPLAY_CMD_NAK = 0x0001,
/* Gracefully disconnects from host */
NETPLAY_CMD_DISCONNECT = 0x0002,
/* Input data */
NETPLAY_CMD_INPUT = 0x0003,
/* Initialization commands */
/* Inform the other side of our nick (must be first command) */
NETPLAY_CMD_NICK = 0x0020,
/* Initial synchronization info (frame, sram, player info) */
NETPLAY_CMD_SYNC = 0x0021,
/* Join spectator mode */
NETPLAY_CMD_SPECTATE = 0x0022,
/* Join play mode */
NETPLAY_CMD_PLAY = 0x0023,
/* Report player mode */
NETPLAY_CMD_MODE = 0x0024,
/* Loading and synchronization */
/* Send the CRC hash of a frame's state */
NETPLAY_CMD_CRC = 0x0040,
/* Request a savestate */
NETPLAY_CMD_REQUEST_SAVESTATE = 0x0041,
/* Send a savestate for the client to load */
NETPLAY_CMD_LOAD_SAVESTATE = 0x0042,
/* Pauses the game, takes no arguments */
NETPLAY_CMD_PAUSE = 0x0043,
/* Resumes the game, takes no arguments */
NETPLAY_CMD_RESUME = 0x0044,
/* Sends over cheats enabled on client (unsupported) */
NETPLAY_CMD_CHEATS = 0x0045,
/* Misc. commands */
/* Swap inputs between player 1 and player 2 */
NETPLAY_CMD_FLIP_PLAYERS = 0x0060,
/* Sends multiple config requests over,
* See enum netplay_cmd_cfg */
NETPLAY_CMD_CFG = 0x0061,
/* CMD_CFG streamlines sending multiple
configurations. This acknowledges
each one individually */
NETPLAY_CMD_CFG_ACK = 0x0062
};
/* These are the configurations sent by NETPLAY_CMD_CFG. */
enum netplay_cmd_cfg
{
/* Nickname */
NETPLAY_CFG_NICK = 0x0001,
/* input.netplay_client_swap_input */
NETPLAY_CFG_SWAP_INPUT = 0x0002,
/* netplay.delay_frames */
NETPLAY_CFG_DELAY_FRAMES = 0x0004,
/* For more than 2 players */
NETPLAY_CFG_PLAYER_SLOT = 0x0008
};
enum rarch_netplay_connection_mode
{
NETPLAY_CONNECTION_NONE = 0,
/* Initialization: */
NETPLAY_CONNECTION_INIT, /* Waiting for header */
NETPLAY_CONNECTION_PRE_NICK, /* Waiting for nick */
NETPLAY_CONNECTION_PRE_SYNC, /* Waiting for sync */
/* Ready: */
NETPLAY_CONNECTION_CONNECTED, /* Modes above this are connected */
NETPLAY_CONNECTION_SPECTATING, /* Spectator mode */
NETPLAY_CONNECTION_PLAYING /* Normal ready state */
};
enum rarch_netplay_stall_reason
{
NETPLAY_STALL_NONE = 0,
NETPLAY_STALL_RUNNING_FAST,
NETPLAY_STALL_NO_CONNECTION
};
2015-12-23 13:25:28 -07:00
struct delta_frame
{
bool used; /* a bit derpy, but this is how we know if the delta's been used at all */
Multitudinous fixes and updates to Netplay. Had to be one commit since they're mostly related: (1) Renamed frame_count to self_frame_count to be consistent with all other names. (2) Previously, it was possible to overwrite data in the ring buffer that hadn't yet been used. Now that's not possible, but that just changes one breakage for another: It's now possible to miss the NEW data. The final resolution for this will probably be requesting stalls. This is accomplished simply by storing frame numbers in the ring buffer and checking them against the 'other' head. (3) In TCP packets, separated cmd_size from cmd. It was beyond pointless for these to be combined, and restricted cmd_size to 16 bits, which will probably fail when/if state loading is supported. (4) Readahead is now allowed. In the past, if the peer got ahead of us, we would simply ignore their data. Thus, if they got too far ahead of us, we'd stop reading their data altogether. Fabulous. Now, we're happy to read future input. (5) If the peer gets too far ahead of us (currently an unconfigurable 10 frames), fast forward to catch up. This should prevent desync due to clock drift or stutter. (6) Used frame_count in a few places where ptr was used. Doing a comparison of pointers on a ring buffer is a far more dangerous way to assure we're done with a task than simply using the count, since the ring buffer is... well, a ring. (7) Renamed tmp_{ptr,frame_count} to replay_{ptr,frame_count} for clarity. (8) Slightly changed the protocol version hash, just to assure that other clients wouldn't think they were compatible with this one. (9) There was an off-by-one error which, under some circumstances, could allow the replay engine to run a complete round through the ring buffer, replaying stale data. Fixed.
2016-09-11 22:01:47 -04:00
uint32_t frame;
/* The serialized state of the core at this frame, before input */
2015-12-23 13:25:28 -07:00
void *state;
/* The CRC-32 of the serialized state if we've calculated it, else 0 */
uint32_t crc;
uint32_t real_input_state[WORDS_PER_FRAME - 1];
uint32_t simulated_input_state[WORDS_PER_FRAME - 1];
uint32_t self_state[WORDS_PER_FRAME - 1];
2015-12-23 13:25:28 -07:00
/* Have we read local input? */
Multitudinous fixes and updates to Netplay. Had to be one commit since they're mostly related: (1) Renamed frame_count to self_frame_count to be consistent with all other names. (2) Previously, it was possible to overwrite data in the ring buffer that hadn't yet been used. Now that's not possible, but that just changes one breakage for another: It's now possible to miss the NEW data. The final resolution for this will probably be requesting stalls. This is accomplished simply by storing frame numbers in the ring buffer and checking them against the 'other' head. (3) In TCP packets, separated cmd_size from cmd. It was beyond pointless for these to be combined, and restricted cmd_size to 16 bits, which will probably fail when/if state loading is supported. (4) Readahead is now allowed. In the past, if the peer got ahead of us, we would simply ignore their data. Thus, if they got too far ahead of us, we'd stop reading their data altogether. Fabulous. Now, we're happy to read future input. (5) If the peer gets too far ahead of us (currently an unconfigurable 10 frames), fast forward to catch up. This should prevent desync due to clock drift or stutter. (6) Used frame_count in a few places where ptr was used. Doing a comparison of pointers on a ring buffer is a far more dangerous way to assure we're done with a task than simply using the count, since the ring buffer is... well, a ring. (7) Renamed tmp_{ptr,frame_count} to replay_{ptr,frame_count} for clarity. (8) Slightly changed the protocol version hash, just to assure that other clients wouldn't think they were compatible with this one. (9) There was an off-by-one error which, under some circumstances, could allow the replay engine to run a complete round through the ring buffer, replaying stale data. Fixed.
2016-09-11 22:01:47 -04:00
bool have_local;
/* Have we read the real remote input? */
bool have_remote;
/* Is the current state as of self_frame_count using the real remote data? */
2015-12-23 13:25:28 -07:00
bool used_real;
};
struct socket_buffer
{
unsigned char *data;
size_t bufsz;
size_t start, end;
size_t read;
};
2015-12-23 13:25:28 -07:00
struct netplay_callbacks {
bool (*pre_frame) (netplay_t *netplay);
2015-12-23 13:25:28 -07:00
void (*post_frame)(netplay_t *netplay);
bool (*info_cb) (netplay_t *netplay, unsigned frames);
};
/* Each connection gets a connection struct */
struct netplay_connection
{
/* Is this connection buffer in use? */
bool active;
/* fd associated with this connection */
int fd;
/* Address of peer */
struct sockaddr_storage addr;
/* Nickname of peer */
char nick[32];
/* Buffers for sending and receiving data */
struct socket_buffer send_packet_buffer, recv_packet_buffer;
/* Mode of the connection */
enum rarch_netplay_connection_mode mode;
/* Player # of connected player, or -1 if not a player */
int player;
/* Force send a savestate, to this connection only */
bool force_send_savestate;
};
2015-12-23 13:25:28 -07:00
struct netplay
{
/* Our nickname */
2015-12-23 13:25:28 -07:00
char nick[32];
/* TCP connection for listening (server only) */
int listen_fd;
/* Our connection number */
uint32_t self_connection_num;
/* Our mode and status */
enum rarch_netplay_connection_mode self_mode;
/* All of our connections */
struct netplay_connection *connections;
size_t connections_size;
struct netplay_connection one_connection; /* Client only */
/* True if any of our connections are players (i.e., we actually need to do
* netplay) */
bool have_player_connections;
2015-12-23 13:25:28 -07:00
struct retro_callbacks cbs;
/* TCP port (only set if serving) */
uint16_t tcp_port;
/* NAT traversal info (if NAT traversal is used and serving) */
bool nat_traversal;
struct natt_status nat_traversal_state;
2015-12-23 13:25:28 -07:00
/* Which port is governed by netplay (other user)? */
unsigned port;
struct delta_frame *buffer;
size_t buffer_size;
/* Compression transcoder */
const struct trans_stream_backend *compression_backend;
void *compression_stream;
const struct trans_stream_backend *decompression_backend;
void *decompression_stream;
/* A buffer into which to compress frames for transfer */
uint8_t *zbuffer;
size_t zbuffer_size;
/* The size of our packet buffers */
size_t packet_buffer_size;
/* The current frame seen by the frontend */
size_t self_ptr;
uint32_t self_frame_count;
/* The first frame at which some data might be unreliable */
2015-12-23 13:25:28 -07:00
size_t other_ptr;
uint32_t other_frame_count;
/* Pointer to where we are reading.
* Generally, other_ptr <= read_ptr <= self_ptr, but read_ptr can get ahead
* of self_ptr if the peer is running fast. */
2015-12-23 13:25:28 -07:00
size_t read_ptr;
uint32_t read_frame_count;
Multitudinous fixes and updates to Netplay. Had to be one commit since they're mostly related: (1) Renamed frame_count to self_frame_count to be consistent with all other names. (2) Previously, it was possible to overwrite data in the ring buffer that hadn't yet been used. Now that's not possible, but that just changes one breakage for another: It's now possible to miss the NEW data. The final resolution for this will probably be requesting stalls. This is accomplished simply by storing frame numbers in the ring buffer and checking them against the 'other' head. (3) In TCP packets, separated cmd_size from cmd. It was beyond pointless for these to be combined, and restricted cmd_size to 16 bits, which will probably fail when/if state loading is supported. (4) Readahead is now allowed. In the past, if the peer got ahead of us, we would simply ignore their data. Thus, if they got too far ahead of us, we'd stop reading their data altogether. Fabulous. Now, we're happy to read future input. (5) If the peer gets too far ahead of us (currently an unconfigurable 10 frames), fast forward to catch up. This should prevent desync due to clock drift or stutter. (6) Used frame_count in a few places where ptr was used. Doing a comparison of pointers on a ring buffer is a far more dangerous way to assure we're done with a task than simply using the count, since the ring buffer is... well, a ring. (7) Renamed tmp_{ptr,frame_count} to replay_{ptr,frame_count} for clarity. (8) Slightly changed the protocol version hash, just to assure that other clients wouldn't think they were compatible with this one. (9) There was an off-by-one error which, under some circumstances, could allow the replay engine to run a complete round through the ring buffer, replaying stale data. Fixed.
2016-09-11 22:01:47 -04:00
/* A pointer used temporarily for replay. */
size_t replay_ptr;
uint32_t replay_frame_count;
2015-12-23 13:25:28 -07:00
/* Size of savestates */
2015-12-23 13:25:28 -07:00
size_t state_size;
/* Are we replaying old frames? */
bool is_replay;
2015-12-23 13:25:28 -07:00
/* We don't want to poll several times on a frame. */
bool can_poll;
/* Force a rewind to other_frame_count/other_ptr. This is for synchronized
* events, such as player flipping or savestate loading. */
bool force_rewind;
2015-12-23 13:25:28 -07:00
/* Quirks in the savestate implementation */
uint64_t quirks;
/* Force our state to be sent to all connections. Used when we explicitly
* load a state. */
bool force_send_savestate_all;
/* Set if there is at least one client which must be sent the state, usually
* because they've requested it or just connected. */
bool force_send_savestate_one;
/* Have we requested a savestate as a sync point? */
bool savestate_request_outstanding;
/* A buffer for outgoing input packets. */
uint32_t input_packet_buffer[2 + WORDS_PER_FRAME];
/* And socket info */
2015-12-23 13:25:28 -07:00
struct addrinfo *addr;
struct sockaddr_storage their_addr;
bool has_client_addr;
unsigned timeout_cnt;
/* Spectating. */
struct {
bool enabled;
int fds[MAX_SPECTATORS];
uint32_t frames[MAX_SPECTATORS];
2015-12-23 13:25:28 -07:00
uint16_t *input;
size_t input_ptr;
size_t input_sz;
} spectate;
bool is_server;
2015-12-23 13:25:28 -07:00
/* User flipping
* Flipping state. If frame >= flip_frame, we apply the flip.
* If not, we apply the opposite, effectively creating a trigger point. */
2015-12-23 13:25:28 -07:00
bool flip;
uint32_t flip_frame;
/* Netplay pausing
*/
bool local_paused;
bool remote_paused;
2015-12-23 13:25:28 -07:00
/* And stalling */
uint32_t delay_frames;
enum rarch_netplay_stall_reason stall;
retro_time_t stall_time;
/* Frequency with which to check CRCs */
uint32_t check_frames;
2015-12-23 13:25:28 -07:00
struct netplay_callbacks* net_cbs;
};
void input_poll_net(void);
/**
* netplay_new:
* @direct_host : Netplay host discovered from scanning.
* @server : IP address of server.
* @port : Port of server.
* @delay_frames : Amount of delay frames.
* @check_frames : Frequency with which to check CRCs.
* @cb : Libretro callbacks.
* @spectate : If true, enable spectator mode.
* @nat_traversal : If true, attempt NAT traversal.
* @nick : Nickname of user.
* @quirks : Netplay quirks.
*
* Creates a new netplay handle. A NULL host means we're
* hosting (user 1).
*
* Returns: new netplay handle.
**/
netplay_t *netplay_new(void *direct_host, const char *server,
uint16_t port, unsigned delay_frames, unsigned check_frames,
const struct retro_callbacks *cb, bool spectate, bool nat_traversal,
const char *nick, uint64_t quirks);
/**
* netplay_free:
* @netplay : pointer to netplay object
*
* Frees netplay handle.
**/
void netplay_free(netplay_t *handle);
/**
* netplay_pre_frame:
* @netplay : pointer to netplay object
*
* Pre-frame for Netplay.
* Call this before running retro_run().
*
* Returns: true (1) if the frontend is clear to emulate the frame, false (0)
* if we're stalled or paused
**/
bool netplay_pre_frame(netplay_t *handle);
/**
* netplay_post_frame:
* @netplay : pointer to netplay object
*
* Post-frame for Netplay.
* We check if we have new input and replay from recorded input.
* Call this after running retro_run().
**/
void netplay_post_frame(netplay_t *handle);
/**
* 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);
/**
* netplay_load_savestate
* @netplay : pointer to netplay object
* @serial_info : the savestate being loaded, NULL means "load it yourself"
* @save : whether to save the provided serial_info into the frame buffer
*
* Inform Netplay of a savestate load and send it to the other side
**/
void netplay_load_savestate(netplay_t *netplay, retro_ctx_serialize_info_t *serial_info, bool save);
/**
* netplay_disconnect
* @netplay : pointer to netplay object
*
* Disconnect netplay.
*
* Returns: true (1) if successful. At present, cannot fail.
**/
bool netplay_disconnect(netplay_t *netplay);
2015-12-23 13:25:28 -07:00
struct netplay_callbacks* netplay_get_cbs_net(void);
2016-09-03 07:48:25 +02:00
2015-12-23 13:25:28 -07:00
struct netplay_callbacks* netplay_get_cbs_spectate(void);
2016-09-03 07:48:25 +02:00
/* Normally called at init time, unless the INITIALIZATION quirk is set */
bool netplay_init_serialization(netplay_t *netplay);
/* Force serialization to be ready by fast-forwarding the core */
bool netplay_wait_and_init_serialization(netplay_t *netplay);
void netplay_simulate_input(netplay_t *netplay, uint32_t sim_ptr, bool resim);
2016-05-12 12:03:43 +02:00
void netplay_log_connection(const struct sockaddr_storage *their_addr,
2015-12-23 13:25:28 -07:00
unsigned slot, const char *nick);
2016-05-12 12:03:43 +02:00
bool netplay_get_nickname(netplay_t *netplay, int fd);
2016-09-03 07:48:25 +02:00
2016-05-12 12:03:43 +02:00
bool netplay_send_nickname(netplay_t *netplay, int fd);
2016-09-03 07:48:25 +02:00
/* Various netplay initialization modes: */
bool netplay_handshake_init_send(netplay_t *netplay, struct netplay_connection *connection);
bool netplay_handshake_init(netplay_t *netplay, struct netplay_connection *connection, bool *had_input);
bool netplay_handshake_pre_nick(netplay_t *netplay, struct netplay_connection *connection, bool *had_input);
bool netplay_handshake_pre_sync(netplay_t *netplay, struct netplay_connection *connection, bool *had_input);
2016-09-03 07:48:25 +02:00
2016-05-12 12:03:43 +02:00
uint32_t netplay_impl_magic(void);
2016-09-03 07:48:25 +02:00
bool netplay_is_server(netplay_t* netplay);
2016-09-03 07:48:25 +02:00
2016-05-12 12:03:43 +02:00
bool netplay_is_spectate(netplay_t* netplay);
Multitudinous fixes and updates to Netplay. Had to be one commit since they're mostly related: (1) Renamed frame_count to self_frame_count to be consistent with all other names. (2) Previously, it was possible to overwrite data in the ring buffer that hadn't yet been used. Now that's not possible, but that just changes one breakage for another: It's now possible to miss the NEW data. The final resolution for this will probably be requesting stalls. This is accomplished simply by storing frame numbers in the ring buffer and checking them against the 'other' head. (3) In TCP packets, separated cmd_size from cmd. It was beyond pointless for these to be combined, and restricted cmd_size to 16 bits, which will probably fail when/if state loading is supported. (4) Readahead is now allowed. In the past, if the peer got ahead of us, we would simply ignore their data. Thus, if they got too far ahead of us, we'd stop reading their data altogether. Fabulous. Now, we're happy to read future input. (5) If the peer gets too far ahead of us (currently an unconfigurable 10 frames), fast forward to catch up. This should prevent desync due to clock drift or stutter. (6) Used frame_count in a few places where ptr was used. Doing a comparison of pointers on a ring buffer is a far more dangerous way to assure we're done with a task than simply using the count, since the ring buffer is... well, a ring. (7) Renamed tmp_{ptr,frame_count} to replay_{ptr,frame_count} for clarity. (8) Slightly changed the protocol version hash, just to assure that other clients wouldn't think they were compatible with this one. (9) There was an off-by-one error which, under some circumstances, could allow the replay engine to run a complete round through the ring buffer, replaying stale data. Fixed.
2016-09-11 22:01:47 -04:00
bool netplay_delta_frame_ready(netplay_t *netplay, struct delta_frame *delta, uint32_t frame);
uint32_t netplay_delta_frame_crc(netplay_t *netplay, struct delta_frame *delta);
bool netplay_cmd_crc(netplay_t *netplay, struct delta_frame *delta);
bool netplay_cmd_request_savestate(netplay_t *netplay);
/* DISCOVERY: */
bool netplay_lan_ad_server(netplay_t *netplay);
bool netplay_init_socket_buffer(struct socket_buffer *sbuf, size_t size);
bool netplay_resize_socket_buffer(struct socket_buffer *sbuf, size_t newsize);
void netplay_deinit_socket_buffer(struct socket_buffer *sbuf);
void netplay_clear_socket_buffer(struct socket_buffer *sbuf);
bool netplay_send(struct socket_buffer *sbuf, int sockfd, const void *buf, size_t len);
bool netplay_send_flush(struct socket_buffer *sbuf, int sockfd, bool block);
ssize_t netplay_recv(struct socket_buffer *sbuf, int sockfd, void *buf, size_t len, bool block);
void netplay_recv_reset(struct socket_buffer *sbuf);
void netplay_recv_flush(struct socket_buffer *sbuf);
2015-12-26 08:10:37 +01:00
#endif