mirror of
https://github.com/libretro/RetroArch
synced 2025-01-27 12:35:23 +00:00
Correctly walk the addrinfo tree to determine all addresses.
This commit is contained in:
parent
e9cf861f7f
commit
2c674ef8d1
145
netplay.c
145
netplay.c
@ -233,19 +233,86 @@ static void log_connection(const struct sockaddr_storage *their_addr,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int init_tcp_connection(const struct addrinfo *res, bool server, bool spectate,
|
||||||
|
struct sockaddr *other_addr, socklen_t addr_size)
|
||||||
|
{
|
||||||
|
bool ret = true;
|
||||||
|
int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server)
|
||||||
|
{
|
||||||
|
if (connect(fd, res->ai_addr, res->ai_addrlen) < 0)
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (spectate)
|
||||||
|
{
|
||||||
|
int yes = 1;
|
||||||
|
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, CONST_CAST &yes, sizeof(int));
|
||||||
|
|
||||||
|
if (bind(fd, res->ai_addr, res->ai_addrlen) < 0 ||
|
||||||
|
listen(fd, MAX_SPECTATORS) < 0)
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int yes = 1;
|
||||||
|
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, CONST_CAST &yes, sizeof(int));
|
||||||
|
|
||||||
|
if (bind(fd, res->ai_addr, res->ai_addrlen) < 0 ||
|
||||||
|
listen(fd, 1) < 0)
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_fd = accept(fd, other_addr, &addr_size);
|
||||||
|
if (new_fd < 0)
|
||||||
|
{
|
||||||
|
ret = false;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
fd = new_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (!ret && fd >= 0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
static bool init_tcp_socket(netplay_t *handle, const char *server, uint16_t port, bool spectate)
|
static bool init_tcp_socket(netplay_t *handle, const char *server, uint16_t port, bool spectate)
|
||||||
{
|
{
|
||||||
struct addrinfo hints, *res = NULL;
|
struct addrinfo hints, *res = NULL;
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(HAVE_SOCKET_LEGACY)
|
#if defined(_WIN32) || defined(HAVE_SOCKET_LEGACY)
|
||||||
hints.ai_family = AF_INET;
|
hints.ai_family = AF_INET;
|
||||||
#else
|
#else
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
if (!server)
|
if (!server)
|
||||||
hints.ai_flags = AI_PASSIVE;
|
hints.ai_flags = AI_PASSIVE;
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
char port_buf[16];
|
char port_buf[16];
|
||||||
snprintf(port_buf, sizeof(port_buf), "%hu", (unsigned short)port);
|
snprintf(port_buf, sizeof(port_buf), "%hu", (unsigned short)port);
|
||||||
if (getaddrinfo(server, port_buf, &hints, &res) < 0)
|
if (getaddrinfo(server, port_buf, &hints, &res) < 0)
|
||||||
@ -254,75 +321,29 @@ static bool init_tcp_socket(netplay_t *handle, const char *server, uint16_t port
|
|||||||
if (!res)
|
if (!res)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
handle->fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
// If "localhost" is used, it is important to check every possible address for ipv4/ipv6.
|
||||||
if (handle->fd < 0)
|
const struct addrinfo *tmp_info = res;
|
||||||
|
while (tmp_info)
|
||||||
{
|
{
|
||||||
RARCH_ERR("Failed to init socket...\n");
|
int fd;
|
||||||
|
if ((fd = init_tcp_connection(tmp_info, server, handle->spectate,
|
||||||
if (res)
|
(struct sockaddr*)&handle->other_addr, sizeof(handle->other_addr))) >= 0)
|
||||||
freeaddrinfo(res);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server)
|
|
||||||
{
|
|
||||||
if (connect(handle->fd, res->ai_addr, res->ai_addrlen) < 0)
|
|
||||||
{
|
{
|
||||||
RARCH_ERR("Failed to connect to server.\n");
|
ret = true;
|
||||||
close(handle->fd);
|
handle->fd = fd;
|
||||||
handle->fd = -1;
|
break;
|
||||||
freeaddrinfo(res);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (handle->spectate)
|
|
||||||
{
|
|
||||||
int yes = 1;
|
|
||||||
setsockopt(handle->fd, SOL_SOCKET, SO_REUSEADDR, CONST_CAST &yes, sizeof(int));
|
|
||||||
|
|
||||||
if (bind(handle->fd, res->ai_addr, res->ai_addrlen) < 0 ||
|
|
||||||
listen(handle->fd, MAX_SPECTATORS) < 0)
|
|
||||||
{
|
|
||||||
RARCH_ERR("Failed to bind socket.\n");
|
|
||||||
close(handle->fd);
|
|
||||||
handle->fd = -1;
|
|
||||||
freeaddrinfo(res);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int yes = 1;
|
|
||||||
setsockopt(handle->fd, SOL_SOCKET, SO_REUSEADDR, CONST_CAST &yes, sizeof(int));
|
|
||||||
|
|
||||||
if (bind(handle->fd, res->ai_addr, res->ai_addrlen) < 0 ||
|
|
||||||
listen(handle->fd, 1) < 0)
|
|
||||||
{
|
|
||||||
RARCH_ERR("Failed to bind socket.\n");
|
|
||||||
close(handle->fd);
|
|
||||||
handle->fd = -1;
|
|
||||||
freeaddrinfo(res);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
socklen_t addr_size = sizeof(handle->other_addr);
|
tmp_info = tmp_info->ai_next;
|
||||||
int new_fd = accept(handle->fd,
|
|
||||||
(struct sockaddr*)&handle->other_addr, &addr_size);
|
|
||||||
if (new_fd < 0)
|
|
||||||
{
|
|
||||||
RARCH_ERR("Failed to accept socket.\n");
|
|
||||||
close(handle->fd);
|
|
||||||
handle->fd = -1;
|
|
||||||
freeaddrinfo(res);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
close(handle->fd);
|
|
||||||
handle->fd = new_fd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(res);
|
if (res)
|
||||||
|
freeaddrinfo(res);
|
||||||
|
|
||||||
return true;
|
if (!ret)
|
||||||
|
RARCH_ERR("Failed to set up netplay sockets.\n");
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool init_udp_socket(netplay_t *handle, const char *server, uint16_t port)
|
static bool init_udp_socket(netplay_t *handle, const char *server, uint16_t port)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user