Check HAVE_ZLIB and only do zlib compression if it's supported by both

sides.
This commit is contained in:
Gregor Richards 2016-11-25 11:03:12 -05:00
parent db437047f8
commit da0b958aeb
4 changed files with 89 additions and 32 deletions

View File

@ -151,7 +151,8 @@ Payload:
}
Description:
Cause the other side to load a savestate, notionally one which the sending
side has also loaded. The serialized savestate is zlib compressed.
side has also loaded. If both sides support zlib compression, the
serialized state is zlib compressed. Otherwise it is uncompressed.
Command: PAUSE
Payload: None

View File

@ -23,13 +23,16 @@
#include <string.h>
#include <compat/strl.h>
#include <compat/zlib.h>
#include <retro_assert.h>
#include <net/net_compat.h>
#include <net/net_socket.h>
#include <features/features_cpu.h>
#include <retro_endianness.h>
#if HAVE_ZLIB
#include <compat/zlib.h>
#endif
#include "netplay_private.h"
#include "../../autosave.h"
@ -586,7 +589,9 @@ static bool netplay_get_cmd(netplay_t *netplay)
{
uint32_t frame;
uint32_t isize;
#if HAVE_ZLIB
z_stream stream;
#endif
/* Make sure we're ready for it */
if (netplay->quirks & NETPLAY_QUIRK_INITIALIZATION)
@ -655,24 +660,33 @@ static bool netplay_get_cmd(netplay_t *netplay)
}
/* And uncompress it */
memset(&stream, 0, sizeof(stream));
inflateInit(&stream);
stream.next_in = netplay->zbuffer;
stream.avail_in = cmd_size - 2*sizeof(uint32_t);
stream.next_out = (Bytef *) netplay->buffer[netplay->read_ptr].state;
stream.avail_out = netplay->state_size;
if (inflate(&stream, 1) == Z_STREAM_ERROR)
#if HAVE_ZLIB
if (netplay->compression == NETPLAY_COMPRESSION_ZLIB)
{
RARCH_ERR("CMD_LOAD_SAVESTATE failed to uncompress savestate.\n");
return netplay_cmd_nak(netplay);
}
memset(&stream, 0, sizeof(stream));
inflateInit(&stream);
stream.next_in = netplay->zbuffer;
stream.avail_in = cmd_size - 2*sizeof(uint32_t);
stream.next_out = (Bytef *) netplay->buffer[netplay->read_ptr].state;
stream.avail_out = netplay->state_size;
if (inflate(&stream, 1) == Z_STREAM_ERROR)
{
RARCH_ERR("CMD_LOAD_SAVESTATE failed to uncompress savestate.\n");
return netplay_cmd_nak(netplay);
}
if (stream.total_out != netplay->state_size)
{
RARCH_ERR("CMD_LOAD_SAVESTATE received too-short savestate.\n");
return netplay_cmd_nak(netplay);
if (stream.total_out != netplay->state_size)
{
RARCH_ERR("CMD_LOAD_SAVESTATE received too-short savestate.\n");
return netplay_cmd_nak(netplay);
}
inflateEnd(&stream);
}
else
#endif
{
memcpy(netplay->buffer[netplay->read_ptr].state, netplay->zbuffer, netplay->state_size);
}
inflateEnd(&stream);
/* Skip ahead if it's past where we are */
if (frame > netplay->self_frame_count)
@ -1441,7 +1455,10 @@ void netplay_load_savestate(netplay_t *netplay,
{
uint32_t header[4];
retro_ctx_serialize_info_t tmp_serial_info;
size_t zbuffer_used;
#if HAVE_ZLIB
z_stream stream;
#endif
if (!netplay->has_connection)
return;
@ -1492,23 +1509,42 @@ void netplay_load_savestate(netplay_t *netplay,
return;
/* Compress it */
memset(&stream, 0, sizeof(stream));
deflateInit(&stream, Z_DEFAULT_COMPRESSION);
stream.next_in = (Bytef *) serial_info->data_const;
stream.avail_in = serial_info->size;
stream.next_out = netplay->zbuffer;
stream.avail_out = netplay->zbuffer_size;
if (deflate(&stream, 1) == Z_STREAM_ERROR)
#if HAVE_ZLIB
if (netplay->compression == NETPLAY_COMPRESSION_ZLIB)
{
hangup(netplay);
return;
memset(&stream, 0, sizeof(stream));
deflateInit(&stream, Z_DEFAULT_COMPRESSION);
stream.next_in = (Bytef *) serial_info->data_const;
stream.avail_in = serial_info->size;
stream.next_out = netplay->zbuffer;
stream.avail_out = netplay->zbuffer_size;
if (deflate(&stream, 1) == Z_STREAM_ERROR)
{
hangup(netplay);
return;
}
if (stream.total_in != serial_info->size)
{
hangup(netplay);
return;
}
zbuffer_used = stream.total_out;
deflateEnd(&stream);
}
if (stream.total_in != serial_info->size)
else
#endif
{
hangup(netplay);
return;
if (serial_info->size < netplay->zbuffer_size)
{
memcpy(netplay->zbuffer, serial_info->data_const, serial_info->size);
zbuffer_used = serial_info->size;
}
else
{
memcpy(netplay->zbuffer, serial_info->data_const, netplay->zbuffer_size);
zbuffer_used = netplay->zbuffer_size;
}
}
deflateEnd(&stream);
/* And send it to the peer */
header[0] = htonl(NETPLAY_CMD_LOAD_SAVESTATE);
@ -1523,7 +1559,7 @@ void netplay_load_savestate(netplay_t *netplay,
}
if (!socket_send_all_blocking(netplay->fd,
netplay->zbuffer, stream.total_out, false))
netplay->zbuffer, zbuffer_used, false))
{
hangup(netplay);
return;

View File

@ -166,8 +166,9 @@ bool netplay_handshake(netplay_t *netplay)
char msg[512];
uint32_t *content_crc_ptr = NULL;
void *sram = NULL;
uint32_t header[4] = {0};
uint32_t header[5] = {0};
bool is_server = netplay->is_server;
int compression = 0;
msg[0] = '\0';
@ -182,6 +183,7 @@ bool netplay_handshake(netplay_t *netplay)
header[1] = htonl(netplay_impl_magic());
header[2] = htonl(mem_info.size);
header[3] = htonl(local_pmagic);
header[4] = htonl(NETPLAY_COMPRESSION_SUPPORTED);
if (!socket_send_all_blocking(netplay->fd, header, sizeof(header), false))
return false;
@ -230,6 +232,13 @@ bool netplay_handshake(netplay_t *netplay)
return false;
}
/* Check what compression is supported */
compression = ntohl(header[4]);
compression &= NETPLAY_COMPRESSION_SUPPORTED;
/* If multiple compression algorithms were supported, we would need to
* explicitly choose the best here */
netplay->compression = compression;
/* Client sends nickname first, server replies with nickname */
if (!is_server)
{

View File

@ -66,6 +66,14 @@
#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
struct delta_frame
{
bool used; /* a bit derpy, but this is how we know if the delta's been used at all */
@ -122,6 +130,9 @@ struct netplay
struct delta_frame *buffer;
size_t buffer_size;
/* Which compression algorithm are we using for this connection? */
int compression;
/* A buffer into which to compress frames for transfer */
uint8_t *zbuffer;
size_t zbuffer_size;