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_load_savestate
* @netplay : pointer to netplay object * @netplay : pointer to netplay object
@ -623,10 +676,7 @@ void netplay_post_frame(netplay_t *netplay)
void netplay_load_savestate(netplay_t *netplay, void netplay_load_savestate(netplay_t *netplay,
retro_ctx_serialize_info_t *serial_info, bool save) retro_ctx_serialize_info_t *serial_info, bool save)
{ {
uint32_t header[4];
retro_ctx_serialize_info_t tmp_serial_info; retro_ctx_serialize_info_t tmp_serial_info;
uint32_t rd, wn;
size_t i;
/* Record it in our own buffer */ /* Record it in our own buffer */
if (save || !serial_info) if (save || !serial_info)
@ -693,39 +743,12 @@ void netplay_load_savestate(netplay_t *netplay,
| NETPLAY_QUIRK_NO_TRANSMISSION)) | NETPLAY_QUIRK_NO_TRANSMISSION))
return; return;
/* Compress it */ /* Send this to every peer */
if (!netplay->compression_backend) if (netplay->compress_nil.compression_backend)
return; netplay_send_savestate(netplay, serial_info, 0, &netplay->compress_nil);
netplay->compression_backend->set_in(netplay->compression_stream, if (netplay->compress_zlib.compression_backend)
(const uint8_t*)serial_info->data_const, serial_info->size); netplay_send_savestate(netplay, serial_info, NETPLAY_COMPRESSION_ZLIB,
netplay->compression_backend->set_out(netplay->compression_stream, &netplay->compress_zlib);
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);
}
} }
/** /**

View File

@ -301,6 +301,7 @@ bool netplay_handshake_init(netplay_t *netplay,
struct nick_buf_s nick_buf; struct nick_buf_s nick_buf;
uint32_t local_pmagic, remote_pmagic; uint32_t local_pmagic, remote_pmagic;
uint32_t compression; uint32_t compression;
struct compression_transcoder *ctrans;
dmsg = NULL; dmsg = NULL;
@ -334,31 +335,41 @@ bool netplay_handshake_init(netplay_t *netplay,
goto error; 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 */ /* Check what compression is supported */
compression = ntohl(header[2]); compression = ntohl(header[2]);
compression &= NETPLAY_COMPRESSION_SUPPORTED; compression &= NETPLAY_COMPRESSION_SUPPORTED;
if (compression & NETPLAY_COMPRESSION_ZLIB) if (compression & NETPLAY_COMPRESSION_ZLIB)
{ {
netplay->compression_backend = trans_stream_get_zlib_deflate_backend(); ctrans = &netplay->compress_zlib;
if (!netplay->compression_backend) if (!ctrans->compression_backend)
netplay->compression_backend = trans_stream_get_pipe_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 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 */ /* Allocate our compression stream */
netplay->compression_stream = netplay->compression_backend->stream_new(); if (!ctrans->compression_stream)
netplay->decompression_stream = netplay->decompression_backend->stream_new(); {
if (!netplay->compression_stream || !netplay->decompression_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"); RARCH_ERR("Failed to allocate compression transcoder!\n");
return false; return false;

View File

@ -540,8 +540,16 @@ void netplay_free(netplay_t *netplay)
if (netplay->zbuffer) if (netplay->zbuffer)
free(netplay->zbuffer); free(netplay->zbuffer);
if (netplay->compression_stream) if (netplay->compress_nil.compression_stream)
netplay->compression_backend->stream_free(netplay->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) if (netplay->addr)
freeaddrinfo_retro(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 isize;
uint32_t rd, wn; uint32_t rd, wn;
uint32_t player; uint32_t player;
struct compression_transcoder *ctrans;
/* Make sure we're ready for it */ /* Make sure we're ready for it */
if (netplay->quirks & NETPLAY_QUIRK_INITIALIZATION) if (netplay->quirks & NETPLAY_QUIRK_INITIALIZATION)
@ -1101,12 +1102,20 @@ static bool netplay_get_cmd(netplay_t *netplay,
} }
/* And decompress it */ /* 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->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, (uint8_t*)netplay->buffer[netplay->read_ptr[connection->player]].state,
netplay->state_size); netplay->state_size);
netplay->decompression_backend->trans(netplay->decompression_stream, ctrans->decompression_backend->trans(ctrans->decompression_stream,
true, &rd, &wn, NULL); true, &rd, &wn, NULL);
/* Skip ahead if it's past where we are */ /* Skip ahead if it's past where we are */

View File

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