Support different forms of compression from different clients.

This commit is contained in:
Gregor Richards 2016-12-18 16:52:21 -05:00
parent 84c33634a6
commit 677ffa9ebd
5 changed files with 120 additions and 59 deletions

View File

@ -610,6 +610,59 @@ void netplay_post_frame(netplay_t *netplay)
}
}
/**
* netplay_send_savestate
* @netplay : pointer to netplay object
* @serial_info : the savestate being loaded
* @cx : compression type
* @z : compression backend to use
*
* Send a loaded savestate to those connected peers using the given compression
* scheme.
*/
void netplay_send_savestate(netplay_t *netplay,
retro_ctx_serialize_info_t *serial_info, uint32_t cx,
struct compression_transcoder *z)
{
uint32_t header[4];
uint32_t rd, wn;
size_t i;
/* Compress it */
z->compression_backend->set_in(z->compression_stream,
(const uint8_t*)serial_info->data_const, serial_info->size);
z->compression_backend->set_out(z->compression_stream,
netplay->zbuffer, netplay->zbuffer_size);
if (!z->compression_backend->trans(z->compression_stream, true, &rd,
&wn, NULL))
{
/* Catastrophe! */
for (i = 0; i < netplay->connections_size; i++)
netplay_hangup(netplay, &netplay->connections[i]);
return;
}
/* Send it to relevant peers */
header[0] = htonl(NETPLAY_CMD_LOAD_SAVESTATE);
header[1] = htonl(wn + 2*sizeof(uint32_t));
header[2] = htonl(netplay->self_frame_count);
header[3] = htonl(serial_info->size);
for (i = 0; i < netplay->connections_size; i++)
{
struct netplay_connection *connection = &netplay->connections[i];
if (!connection->active ||
connection->mode < NETPLAY_CONNECTION_CONNECTED ||
connection->compression_supported != cx) continue;
if (!netplay_send(&connection->send_packet_buffer, connection->fd, header,
sizeof(header)) ||
!netplay_send(&connection->send_packet_buffer, connection->fd,
netplay->zbuffer, wn))
netplay_hangup(netplay, connection);
}
}
/**
* netplay_load_savestate
* @netplay : pointer to netplay object
@ -623,10 +676,7 @@ void netplay_post_frame(netplay_t *netplay)
void netplay_load_savestate(netplay_t *netplay,
retro_ctx_serialize_info_t *serial_info, bool save)
{
uint32_t header[4];
retro_ctx_serialize_info_t tmp_serial_info;
uint32_t rd, wn;
size_t i;
/* Record it in our own buffer */
if (save || !serial_info)
@ -693,39 +743,12 @@ void netplay_load_savestate(netplay_t *netplay,
| NETPLAY_QUIRK_NO_TRANSMISSION))
return;
/* Compress it */
if (!netplay->compression_backend)
return;
netplay->compression_backend->set_in(netplay->compression_stream,
(const uint8_t*)serial_info->data_const, serial_info->size);
netplay->compression_backend->set_out(netplay->compression_stream,
netplay->zbuffer, netplay->zbuffer_size);
if (!netplay->compression_backend->trans(netplay->compression_stream,
true, &rd, &wn, NULL))
{
/* Catastrophe! */
for (i = 0; i < netplay->connections_size; i++)
netplay_hangup(netplay, &netplay->connections[i]);
return;
}
/* And send it to the peers */
header[0] = htonl(NETPLAY_CMD_LOAD_SAVESTATE);
header[1] = htonl(wn + 2*sizeof(uint32_t));
header[2] = htonl(netplay->self_frame_count);
header[3] = htonl(serial_info->size);
for (i = 0; i < netplay->connections_size; i++)
{
struct netplay_connection *connection = &netplay->connections[i];
if (!connection->active || connection->mode < NETPLAY_CONNECTION_CONNECTED) continue;
if (!netplay_send(&connection->send_packet_buffer, connection->fd, header,
sizeof(header)) ||
!netplay_send(&connection->send_packet_buffer, connection->fd,
netplay->zbuffer, wn))
netplay_hangup(netplay, connection);
}
/* Send this to every peer */
if (netplay->compress_nil.compression_backend)
netplay_send_savestate(netplay, serial_info, 0, &netplay->compress_nil);
if (netplay->compress_zlib.compression_backend)
netplay_send_savestate(netplay, serial_info, NETPLAY_COMPRESSION_ZLIB,
&netplay->compress_zlib);
}
/**

View File

@ -301,6 +301,7 @@ bool netplay_handshake_init(netplay_t *netplay,
struct nick_buf_s nick_buf;
uint32_t local_pmagic, remote_pmagic;
uint32_t compression;
struct compression_transcoder *ctrans;
dmsg = NULL;
@ -334,31 +335,41 @@ bool netplay_handshake_init(netplay_t *netplay,
goto error;
}
/* Clear any existing compression */
if (netplay->compression_stream)
netplay->compression_backend->stream_free(netplay->compression_stream);
if (netplay->decompression_stream)
netplay->decompression_backend->stream_free(netplay->decompression_stream);
/* Check what compression is supported */
compression = ntohl(header[2]);
compression &= NETPLAY_COMPRESSION_SUPPORTED;
if (compression & NETPLAY_COMPRESSION_ZLIB)
{
netplay->compression_backend = trans_stream_get_zlib_deflate_backend();
if (!netplay->compression_backend)
netplay->compression_backend = trans_stream_get_pipe_backend();
ctrans = &netplay->compress_zlib;
if (!ctrans->compression_backend)
{
ctrans->compression_backend =
trans_stream_get_zlib_deflate_backend();
if (!ctrans->compression_backend)
ctrans->compression_backend = trans_stream_get_pipe_backend();
}
connection->compression_supported = NETPLAY_COMPRESSION_ZLIB;
}
else
{
netplay->compression_backend = trans_stream_get_pipe_backend();
ctrans = &netplay->compress_nil;
if (!ctrans->compression_backend)
{
ctrans->compression_backend =
trans_stream_get_pipe_backend();
}
connection->compression_supported = 0;
}
netplay->decompression_backend = netplay->compression_backend->reverse;
if (!ctrans->decompression_backend)
ctrans->decompression_backend = ctrans->compression_backend->reverse;
/* Allocate our compression stream */
netplay->compression_stream = netplay->compression_backend->stream_new();
netplay->decompression_stream = netplay->decompression_backend->stream_new();
if (!netplay->compression_stream || !netplay->decompression_stream)
if (!ctrans->compression_stream)
{
ctrans->compression_stream = ctrans->compression_backend->stream_new();
ctrans->decompression_stream = ctrans->decompression_backend->stream_new();
}
if (!ctrans->compression_stream || !ctrans->decompression_stream)
{
RARCH_ERR("Failed to allocate compression transcoder!\n");
return false;

View File

@ -540,8 +540,16 @@ void netplay_free(netplay_t *netplay)
if (netplay->zbuffer)
free(netplay->zbuffer);
if (netplay->compression_stream)
netplay->compression_backend->stream_free(netplay->compression_stream);
if (netplay->compress_nil.compression_stream)
{
netplay->compress_nil.compression_backend->stream_free(netplay->compress_nil.compression_stream);
netplay->compress_nil.decompression_backend->stream_free(netplay->compress_nil.decompression_stream);
}
if (netplay->compress_zlib.compression_stream)
{
netplay->compress_zlib.compression_backend->stream_free(netplay->compress_zlib.compression_stream);
netplay->compress_zlib.decompression_backend->stream_free(netplay->compress_zlib.decompression_stream);
}
if (netplay->addr)
freeaddrinfo_retro(netplay->addr);

View File

@ -1013,6 +1013,7 @@ static bool netplay_get_cmd(netplay_t *netplay,
uint32_t isize;
uint32_t rd, wn;
uint32_t player;
struct compression_transcoder *ctrans;
/* Make sure we're ready for it */
if (netplay->quirks & NETPLAY_QUIRK_INITIALIZATION)
@ -1101,12 +1102,20 @@ static bool netplay_get_cmd(netplay_t *netplay,
}
/* And decompress it */
netplay->decompression_backend->set_in(netplay->decompression_stream,
switch (connection->compression_supported)
{
case NETPLAY_COMPRESSION_ZLIB:
ctrans = &netplay->compress_zlib;
break;
default:
ctrans = &netplay->compress_nil;
}
ctrans->decompression_backend->set_in(ctrans->decompression_stream,
netplay->zbuffer, cmd_size - 2*sizeof(uint32_t));
netplay->decompression_backend->set_out(netplay->decompression_stream,
ctrans->decompression_backend->set_out(ctrans->decompression_stream,
(uint8_t*)netplay->buffer[netplay->read_ptr[connection->player]].state,
netplay->state_size);
netplay->decompression_backend->trans(netplay->decompression_stream,
ctrans->decompression_backend->trans(ctrans->decompression_stream,
true, &rd, &wn, NULL);
/* Skip ahead if it's past where we are */

View File

@ -274,6 +274,9 @@ struct netplay_connection
/* Player # of connected player */
int player;
/* What compression does this peer support? */
uint32_t compression_supported;
/* Is this player paused? */
bool paused;
@ -282,6 +285,15 @@ struct netplay_connection
retro_time_t stall_time;
};
/* Compression transcoder */
struct compression_transcoder
{
const struct trans_stream_backend *compression_backend;
void *compression_stream;
const struct trans_stream_backend *decompression_backend;
void *decompression_stream;
};
struct netplay
{
/* Are we the server? */
@ -330,10 +342,8 @@ struct netplay
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;
struct compression_transcoder compress_nil,
compress_zlib;
/* A buffer into which to compress frames for transfer */
uint8_t *zbuffer;