Merge pull request #3630 from GregorR/netplay-connect-late

Support for late connection to Netplay host mode
This commit is contained in:
Twinaphex 2016-09-22 01:45:43 +02:00 committed by GitHub
commit 719533cf50
4 changed files with 98 additions and 23 deletions

View File

@ -823,18 +823,6 @@ static int init_tcp_connection(const struct addrinfo *res,
goto end;
}
if (!spectate)
{
int new_fd = accept(fd, other_addr, &addr_size);
if (new_fd < 0)
{
ret = false;
goto end;
}
socket_close(fd);
fd = new_fd;
}
}
end:
@ -973,6 +961,7 @@ netplay_t *netplay_new(const char *server, uint16_t port,
netplay->port = server ? 0 : 1;
netplay->spectate.enabled = spectate;
netplay->is_server = server == NULL;
netplay->savestates_work = true;
strlcpy(netplay->nick, nick, sizeof(netplay->nick));
netplay->stall_frames = frames;
netplay->check_frames = check_frames;
@ -1289,7 +1278,12 @@ bool init_netplay(void)
global->netplay.is_client = true;
}
else
{
RARCH_LOG("Waiting for client...\n");
runloop_msg_queue_push(
"Waiting for client...",
0, 180, false);
}
netplay_data = (netplay_t*)netplay_new(
global->netplay.is_client ? global->netplay.server : NULL,

View File

@ -185,6 +185,7 @@ bool netplay_get_info(netplay_t *netplay)
retro_ctx_memory_info_t mem_info;
uint32_t *content_crc_ptr = NULL;
const void *sram = NULL;
size_t i;
if (!socket_receive_all_blocking(netplay->fd, header, sizeof(header)))
{
@ -243,6 +244,20 @@ bool netplay_get_info(netplay_t *netplay)
return false;
}
/* Reset our frame count so it's consistent with the client */
netplay->self_frame_count = netplay->read_frame_count = netplay->other_frame_count = 0;
for (i = 0; i < netplay->buffer_size; i++)
{
if (i == netplay->self_ptr)
{
netplay->buffer[i].frame = 0;
}
else
{
netplay->buffer[i].used = false;
}
}
#ifndef HAVE_SOCKET_LEGACY
netplay_log_connection(&netplay->other_addr, 0, netplay->other_nick);
#endif

View File

@ -18,6 +18,9 @@
#include <compat/strl.h>
#include <stdio.h>
#include <net/net_compat.h>
#include <net/net_socket.h>
#include "netplay_private.h"
#include "retro_assert.h"
@ -76,15 +79,80 @@ static bool netplay_net_pre_frame(netplay_t *netplay)
{
/* If the core can't serialize properly, we must stall for the
* remote input on EVERY frame, because we can't recover */
netplay->savestates_work = false;
netplay->stall_frames = 0;
if (!netplay->has_connection)
netplay->stall = RARCH_NETPLAY_STALL_NO_CONNECTION;
}
}
if (netplay->is_server && !netplay->has_connection)
{
fd_set fds;
struct timeval tmp_tv = {0};
int new_fd, idx, i;
struct sockaddr_storage their_addr;
socklen_t addr_size;
/* Check for a connection */
FD_ZERO(&fds);
FD_SET(netplay->fd, &fds);
if (socket_select(netplay->fd + 1, &fds, NULL, NULL, &tmp_tv) > 0 &&
FD_ISSET(netplay->fd, &fds))
{
addr_size = sizeof(their_addr);
new_fd = accept(netplay->fd, (struct sockaddr*)&their_addr, &addr_size);
if (new_fd < 0)
{
RARCH_ERR("%s\n", msg_hash_to_str(MSG_NETPLAY_FAILED));
return true;
}
socket_close(netplay->fd);
netplay->fd = new_fd;
#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
{
int flag = 1;
setsockopt(netplay->fd, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(int));
}
#endif
/* Connection header */
if (netplay_get_info(netplay))
{
netplay->has_connection = true;
/* If we're not at frame 0, send them the savestate */
if (netplay->self_frame_count != 0 && netplay->savestates_work)
{
serial_info.size = netplay->state_size;
serial_info.data_const = netplay->buffer[netplay->self_ptr].state;
netplay_load_savestate(netplay, &serial_info, false);
}
/* And expect the current frame from the other side */
netplay->read_frame_count = netplay->other_frame_count = netplay->self_frame_count;
netplay->read_ptr = netplay->other_ptr = netplay->read_ptr;
/* Unstall if we were waiting for this */
if (netplay->stall == RARCH_NETPLAY_STALL_NO_CONNECTION)
netplay->stall = 0;
}
else
{
socket_close(netplay->fd);
/* FIXME: Get in a state to accept another client */
}
}
}
netplay->can_poll = true;
input_poll_net();
return true;
return (netplay->stall != RARCH_NETPLAY_STALL_NO_CONNECTION);
}
/**
@ -195,18 +263,12 @@ static void netplay_net_post_frame(netplay_t *netplay)
static bool netplay_net_info_cb(netplay_t* netplay, unsigned frames)
{
if (netplay_is_server(netplay))
if (!netplay_is_server(netplay))
{
if (!netplay_send_info(netplay))
return false;
netplay->has_connection = true;
}
else
{
if (!netplay_get_info(netplay))
return false;
}
netplay->has_connection = true;
return true;
}

View File

@ -74,7 +74,8 @@ struct netplay_callbacks {
enum rarch_netplay_stall_reasons
{
RARCH_NETPLAY_STALL_NONE = 0,
RARCH_NETPLAY_STALL_RUNNING_FAST
RARCH_NETPLAY_STALL_RUNNING_FAST,
RARCH_NETPLAY_STALL_NO_CONNECTION
};
struct netplay
@ -115,6 +116,9 @@ struct netplay
* events, such as player flipping or savestate loading. */
bool force_rewind;
/* Does the core support savestates? */
bool savestates_work;
/* Force our state to be sent to the other side. Used when they request a
* savestate, to send at the next pre-frame. */
bool force_send_savestate;