From 677ffa9ebd0dd19575cb0053dd1853a70f7207a2 Mon Sep 17 00:00:00 2001 From: Gregor Richards Date: Sun, 18 Dec 2016 16:52:21 -0500 Subject: [PATCH] Support different forms of compression from different clients. --- network/netplay/netplay_frontend.c | 95 ++++++++++++++++++----------- network/netplay/netplay_handshake.c | 39 +++++++----- network/netplay/netplay_init.c | 12 +++- network/netplay/netplay_io.c | 15 ++++- network/netplay/netplay_private.h | 18 ++++-- 5 files changed, 120 insertions(+), 59 deletions(-) diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index c5571b0493..63a75c3dae 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -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); } /** diff --git a/network/netplay/netplay_handshake.c b/network/netplay/netplay_handshake.c index 0c5fbac687..7b57aa49e0 100644 --- a/network/netplay/netplay_handshake.c +++ b/network/netplay/netplay_handshake.c @@ -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; diff --git a/network/netplay/netplay_init.c b/network/netplay/netplay_init.c index ceb7b7eb01..650d9f3c78 100644 --- a/network/netplay/netplay_init.c +++ b/network/netplay/netplay_init.c @@ -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); diff --git a/network/netplay/netplay_io.c b/network/netplay/netplay_io.c index 76f2f3b56a..cb92a16eff 100644 --- a/network/netplay/netplay_io.c +++ b/network/netplay/netplay_io.c @@ -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 */ diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h index f43b2d6c11..3133a07e4e 100644 --- a/network/netplay/netplay_private.h +++ b/network/netplay/netplay_private.h @@ -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;