mirror of
https://github.com/CTCaer/RetroArch.git
synced 2025-02-06 03:28:20 +00:00
Merge pull request #3630 from GregorR/netplay-connect-late
Support for late connection to Netplay host mode
This commit is contained in:
commit
719533cf50
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user