mirror of
https://github.com/libretro/RetroArch
synced 2025-03-20 10:20:51 +00:00
Cleanups
This commit is contained in:
parent
9c5f365b2b
commit
808f326209
@ -85,325 +85,6 @@ static struct ad_packet ad_packet_buffer;
|
||||
static struct netplay_host_list discovered_hosts;
|
||||
static size_t discovered_hosts_allocated;
|
||||
|
||||
/* Forward declarations */
|
||||
#ifdef HAVE_NETPLAYDISCOVERY
|
||||
static bool netplay_lan_ad_client(void);
|
||||
#endif
|
||||
|
||||
/** Initialize Netplay discovery (client) */
|
||||
bool init_netplay_discovery(void)
|
||||
{
|
||||
struct addrinfo *addr = NULL;
|
||||
int fd = socket_init((void **) &addr, 0, NULL, SOCKET_TYPE_DATAGRAM);
|
||||
|
||||
if (fd < 0)
|
||||
goto error;
|
||||
|
||||
if (!socket_bind(fd, (void*)addr))
|
||||
{
|
||||
socket_close(fd);
|
||||
goto error;
|
||||
}
|
||||
|
||||
lan_ad_client_fd = fd;
|
||||
freeaddrinfo_retro(addr);
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (addr)
|
||||
freeaddrinfo_retro(addr);
|
||||
RARCH_ERR("[discovery] Failed to initialize netplay advertisement client socket.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Deinitialize and free Netplay discovery */
|
||||
void deinit_netplay_discovery(void)
|
||||
{
|
||||
if (lan_ad_client_fd >= 0)
|
||||
{
|
||||
socket_close(lan_ad_client_fd);
|
||||
lan_ad_client_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Discovery control */
|
||||
/* Todo: implement net_ifinfo and ntohs for consoles */
|
||||
bool netplay_discovery_driver_ctl(enum rarch_netplay_discovery_ctl_state state, void *data)
|
||||
{
|
||||
#ifdef HAVE_NETPLAYDISCOVERY
|
||||
char port_str[6];
|
||||
int ret;
|
||||
unsigned k = 0;
|
||||
|
||||
if (lan_ad_client_fd < 0)
|
||||
return false;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case RARCH_NETPLAY_DISCOVERY_CTL_LAN_SEND_QUERY:
|
||||
{
|
||||
net_ifinfo_t interfaces;
|
||||
struct addrinfo hints = {0}, *addr;
|
||||
int canBroadcast = 1;
|
||||
|
||||
if (!net_ifinfo_new(&interfaces))
|
||||
return false;
|
||||
|
||||
/* Get the broadcast address (IPv4 only for now) */
|
||||
snprintf(port_str, 6, "%hu", (unsigned short) RARCH_DEFAULT_PORT);
|
||||
if (getaddrinfo_retro("255.255.255.255", port_str, &hints, &addr) < 0)
|
||||
return false;
|
||||
|
||||
/* Make it broadcastable */
|
||||
#if defined(SOL_SOCKET) && defined(SO_BROADCAST)
|
||||
if (setsockopt(lan_ad_client_fd, SOL_SOCKET, SO_BROADCAST,
|
||||
(const char *)&canBroadcast, sizeof(canBroadcast)) < 0)
|
||||
RARCH_WARN("[discovery] Failed to set netplay discovery port to broadcast\n");
|
||||
#endif
|
||||
|
||||
/* Put together the request */
|
||||
memcpy((void *) &ad_packet_buffer, "RANQ", 4);
|
||||
ad_packet_buffer.protocol_version = htonl(NETPLAY_PROTOCOL_VERSION);
|
||||
|
||||
for (k = 0; k < (unsigned)interfaces.size; k++)
|
||||
{
|
||||
strlcpy(ad_packet_buffer.address, interfaces.entries[k].host,
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
|
||||
/* And send it off */
|
||||
ret = (int)sendto(lan_ad_client_fd, (const char *) &ad_packet_buffer,
|
||||
sizeof(struct ad_packet), 0, addr->ai_addr, addr->ai_addrlen);
|
||||
if (ret < (ssize_t) (2*sizeof(uint32_t)))
|
||||
RARCH_WARN("[discovery] Failed to send netplay discovery query (error: %d)\n", errno);
|
||||
}
|
||||
|
||||
freeaddrinfo_retro(addr);
|
||||
net_ifinfo_free(&interfaces);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case RARCH_NETPLAY_DISCOVERY_CTL_LAN_GET_RESPONSES:
|
||||
if (!netplay_lan_ad_client())
|
||||
return false;
|
||||
*((struct netplay_host_list **) data) = &discovered_hosts;
|
||||
break;
|
||||
|
||||
case RARCH_NETPLAY_DISCOVERY_CTL_LAN_CLEAR_RESPONSES:
|
||||
discovered_hosts.size = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_NETPLAYDISCOVERY
|
||||
static bool init_lan_ad_server_socket(netplay_t *netplay, uint16_t port)
|
||||
{
|
||||
struct addrinfo *addr = NULL;
|
||||
int fd = socket_init((void **) &addr, port, NULL, SOCKET_TYPE_DATAGRAM);
|
||||
|
||||
if (fd < 0)
|
||||
goto error;
|
||||
|
||||
if (!socket_bind(fd, (void*)addr))
|
||||
{
|
||||
socket_close(fd);
|
||||
goto error;
|
||||
}
|
||||
|
||||
lan_ad_server_fd = fd;
|
||||
freeaddrinfo_retro(addr);
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (addr)
|
||||
freeaddrinfo_retro(addr);
|
||||
RARCH_ERR("[discovery] Failed to initialize netplay advertisement socket\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* netplay_lan_ad_server
|
||||
*
|
||||
* Respond to any LAN ad queries that the netplay server has received.
|
||||
*/
|
||||
bool netplay_lan_ad_server(netplay_t *netplay)
|
||||
{
|
||||
/* Todo: implement net_ifinfo and ntohs for consoles */
|
||||
#ifdef HAVE_NETPLAYDISCOVERY
|
||||
fd_set fds;
|
||||
int ret;
|
||||
unsigned i;
|
||||
char buf[4096];
|
||||
net_ifinfo_t interfaces;
|
||||
socklen_t addr_size;
|
||||
char reply_addr[NETPLAY_HOST_STR_LEN], port_str[6];
|
||||
struct sockaddr their_addr;
|
||||
struct timeval tmp_tv = {0};
|
||||
unsigned k = 0;
|
||||
struct addrinfo *our_addr, hints = {0};
|
||||
struct string_list *subsystem = path_get_subsystem_list();
|
||||
|
||||
interfaces.entries = NULL;
|
||||
interfaces.size = 0;
|
||||
|
||||
their_addr.sa_family = 0;
|
||||
for (i = 0; i < 14; i++)
|
||||
their_addr.sa_data[i] = 0;
|
||||
|
||||
if (!net_ifinfo_new(&interfaces))
|
||||
return false;
|
||||
|
||||
if ( (lan_ad_server_fd < 0)
|
||||
&& !init_lan_ad_server_socket(netplay, RARCH_DEFAULT_PORT))
|
||||
return false;
|
||||
|
||||
/* Check for any ad queries */
|
||||
for (;;)
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(lan_ad_server_fd, &fds);
|
||||
if (socket_select(lan_ad_server_fd + 1, &fds, NULL, NULL, &tmp_tv) <= 0)
|
||||
break;
|
||||
if (!FD_ISSET(lan_ad_server_fd, &fds))
|
||||
break;
|
||||
|
||||
/* Somebody queried, so check that it's valid */
|
||||
addr_size = sizeof(their_addr);
|
||||
ret = (int)recvfrom(lan_ad_server_fd, (char*)&ad_packet_buffer,
|
||||
sizeof(struct ad_packet), 0, &their_addr, &addr_size);
|
||||
if (ret >= (ssize_t) (2 * sizeof(uint32_t)))
|
||||
{
|
||||
char s[NETPLAY_HOST_STR_LEN];
|
||||
uint32_t content_crc = 0;
|
||||
|
||||
/* Make sure it's a valid query */
|
||||
if (memcmp((void *) &ad_packet_buffer, "RANQ", 4))
|
||||
{
|
||||
RARCH_LOG("[discovery] invalid query\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* For this version */
|
||||
if (ntohl(ad_packet_buffer.protocol_version) !=
|
||||
NETPLAY_PROTOCOL_VERSION)
|
||||
{
|
||||
RARCH_LOG("[discovery] invalid protocol version\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string_is_empty(ad_packet_buffer.address))
|
||||
strlcpy(reply_addr, ad_packet_buffer.address, NETPLAY_HOST_STR_LEN);
|
||||
|
||||
for (k = 0; k < interfaces.size; k++)
|
||||
{
|
||||
char *p;
|
||||
char sub[NETPLAY_HOST_STR_LEN];
|
||||
char frontend_architecture_tmp[32];
|
||||
char frontend[256];
|
||||
const frontend_ctx_driver_t *frontend_drv =
|
||||
(const frontend_ctx_driver_t*)
|
||||
frontend_driver_get_cpu_architecture_str(
|
||||
frontend_architecture_tmp, sizeof(frontend_architecture_tmp));
|
||||
snprintf(frontend, sizeof(frontend), "%s %s",
|
||||
frontend_drv->ident, frontend_architecture_tmp);
|
||||
|
||||
p=strrchr(reply_addr,'.');
|
||||
if (p)
|
||||
{
|
||||
strlcpy(sub, reply_addr, p - reply_addr + 1);
|
||||
if (strstr(interfaces.entries[k].host, sub) &&
|
||||
!strstr(interfaces.entries[k].host, "127.0.0.1"))
|
||||
{
|
||||
struct retro_system_info *info = runloop_get_libretro_system_info();
|
||||
|
||||
RARCH_LOG ("[discovery] query received on common interface: %s/%s (theirs / ours) \n",
|
||||
reply_addr, interfaces.entries[k].host);
|
||||
|
||||
/* Now build our response */
|
||||
buf[0] = '\0';
|
||||
content_crc = content_get_crc();
|
||||
|
||||
memset(&ad_packet_buffer, 0, sizeof(struct ad_packet));
|
||||
memcpy(&ad_packet_buffer, "RANS", 4);
|
||||
|
||||
if (subsystem)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < subsystem->size; i++)
|
||||
{
|
||||
strlcat(buf, path_basename(subsystem->elems[i].data), NETPLAY_HOST_LONGSTR_LEN);
|
||||
if (i < subsystem->size - 1)
|
||||
strlcat(buf, "|", NETPLAY_HOST_LONGSTR_LEN);
|
||||
}
|
||||
strlcpy(ad_packet_buffer.content, buf,
|
||||
NETPLAY_HOST_LONGSTR_LEN);
|
||||
strlcpy(ad_packet_buffer.subsystem_name, path_get(RARCH_PATH_SUBSYSTEM),
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(ad_packet_buffer.content, !string_is_empty(
|
||||
path_basename(path_get(RARCH_PATH_BASENAME)))
|
||||
? path_basename(path_get(RARCH_PATH_BASENAME)) : "N/A",
|
||||
NETPLAY_HOST_LONGSTR_LEN);
|
||||
strlcpy(ad_packet_buffer.subsystem_name, "N/A", NETPLAY_HOST_STR_LEN);
|
||||
}
|
||||
|
||||
strlcpy(ad_packet_buffer.address, interfaces.entries[k].host,
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
ad_packet_buffer.protocol_version =
|
||||
htonl(NETPLAY_PROTOCOL_VERSION);
|
||||
ad_packet_buffer.port = htonl(netplay->tcp_port);
|
||||
strlcpy(ad_packet_buffer.retroarch_version, PACKAGE_VERSION,
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
strlcpy(ad_packet_buffer.nick, netplay->nick, NETPLAY_HOST_STR_LEN);
|
||||
strlcpy(ad_packet_buffer.frontend, frontend, NETPLAY_HOST_STR_LEN);
|
||||
|
||||
if (info)
|
||||
{
|
||||
strlcpy(ad_packet_buffer.core, info->library_name,
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
strlcpy(ad_packet_buffer.core_version, info->library_version,
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
}
|
||||
|
||||
snprintf(s, sizeof(s), "%d", content_crc);
|
||||
strlcpy(ad_packet_buffer.content_crc, s,
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
|
||||
/* Build up the destination address*/
|
||||
snprintf(port_str, 6, "%hu", ntohs(((struct sockaddr_in*)(&their_addr))->sin_port));
|
||||
if (getaddrinfo_retro(reply_addr, port_str, &hints, &our_addr) < 0)
|
||||
continue;
|
||||
|
||||
RARCH_LOG ("[discovery] sending reply to %s \n", reply_addr);
|
||||
|
||||
/* And send it */
|
||||
sendto(lan_ad_server_fd, (const char*)&ad_packet_buffer,
|
||||
sizeof(struct ad_packet), 0, our_addr->ai_addr, our_addr->ai_addrlen);
|
||||
freeaddrinfo_retro(our_addr);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
net_ifinfo_free(&interfaces);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SOCKET_LEGACY
|
||||
|
||||
#ifndef htons
|
||||
@ -464,7 +145,8 @@ static bool netplay_lan_ad_client(void)
|
||||
continue;
|
||||
|
||||
/* For this version */
|
||||
if (ntohl(ad_packet_buffer.protocol_version) != NETPLAY_PROTOCOL_VERSION)
|
||||
if (ntohl(ad_packet_buffer.protocol_version)
|
||||
!= NETPLAY_PROTOCOL_VERSION)
|
||||
continue;
|
||||
|
||||
/* And that we know how to handle it */
|
||||
@ -472,7 +154,7 @@ static bool netplay_lan_ad_client(void)
|
||||
{
|
||||
struct sockaddr_in *sin = NULL;
|
||||
|
||||
RARCH_WARN ("[discovery] using IPv4 for discovery\n");
|
||||
RARCH_WARN ("[Discovery] Using IPv4 for discovery\n");
|
||||
sin = (struct sockaddr_in *) &their_addr;
|
||||
sin->sin_port = htons(ntohl(ad_packet_buffer.port));
|
||||
|
||||
@ -481,7 +163,7 @@ static bool netplay_lan_ad_client(void)
|
||||
else if (their_addr.sa_family == AF_INET6)
|
||||
{
|
||||
struct sockaddr_in6 *sin6 = NULL;
|
||||
RARCH_WARN ("[discovery] using IPv6 for discovery\n");
|
||||
RARCH_WARN ("[Discovery] Using IPv6 for discovery\n");
|
||||
sin6 = (struct sockaddr_in6 *) &their_addr;
|
||||
sin6->sin6_port = htons(ad_packet_buffer.port);
|
||||
|
||||
@ -505,7 +187,8 @@ static bool netplay_lan_ad_client(void)
|
||||
realloc(discovered_hosts.hosts, allocated * sizeof(struct
|
||||
netplay_host));
|
||||
else
|
||||
/* Should be equivalent to realloc, but I don't trust screwy libcs */
|
||||
/* Should be equivalent to realloc,
|
||||
* but I don't trust screwy libcs */
|
||||
new_hosts = (struct netplay_host *)
|
||||
malloc(allocated * sizeof(struct netplay_host));
|
||||
|
||||
@ -552,3 +235,321 @@ static bool netplay_lan_ad_client(void)
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Initialize Netplay discovery (client) */
|
||||
bool init_netplay_discovery(void)
|
||||
{
|
||||
struct addrinfo *addr = NULL;
|
||||
int fd = socket_init((void **)&addr, 0, NULL, SOCKET_TYPE_DATAGRAM);
|
||||
|
||||
if (fd < 0)
|
||||
goto error;
|
||||
|
||||
if (!socket_bind(fd, (void*)addr))
|
||||
{
|
||||
socket_close(fd);
|
||||
goto error;
|
||||
}
|
||||
|
||||
lan_ad_client_fd = fd;
|
||||
freeaddrinfo_retro(addr);
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (addr)
|
||||
freeaddrinfo_retro(addr);
|
||||
RARCH_ERR("[Discovery] Failed to initialize netplay advertisement client socket.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Deinitialize and free Netplay discovery */
|
||||
/* TODO/FIXME - this is apparently never called? */
|
||||
void deinit_netplay_discovery(void)
|
||||
{
|
||||
if (lan_ad_client_fd >= 0)
|
||||
{
|
||||
socket_close(lan_ad_client_fd);
|
||||
lan_ad_client_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Discovery control */
|
||||
/* TODO/FIXME: implement net_ifinfo and ntohs for consoles */
|
||||
bool netplay_discovery_driver_ctl(
|
||||
enum rarch_netplay_discovery_ctl_state state, void *data)
|
||||
{
|
||||
#ifdef HAVE_NETPLAYDISCOVERY
|
||||
int ret;
|
||||
char port_str[6];
|
||||
unsigned k = 0;
|
||||
|
||||
if (lan_ad_client_fd < 0)
|
||||
return false;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case RARCH_NETPLAY_DISCOVERY_CTL_LAN_SEND_QUERY:
|
||||
{
|
||||
net_ifinfo_t interfaces;
|
||||
struct addrinfo hints = {0}, *addr;
|
||||
int can_broadcast = 1;
|
||||
|
||||
if (!net_ifinfo_new(&interfaces))
|
||||
return false;
|
||||
|
||||
/* Get the broadcast address (IPv4 only for now) */
|
||||
snprintf(port_str, 6, "%hu", (unsigned short) RARCH_DEFAULT_PORT);
|
||||
if (getaddrinfo_retro("255.255.255.255", port_str, &hints, &addr) < 0)
|
||||
return false;
|
||||
|
||||
/* Make it broadcastable */
|
||||
#if defined(SOL_SOCKET) && defined(SO_BROADCAST)
|
||||
if (setsockopt(lan_ad_client_fd, SOL_SOCKET, SO_BROADCAST,
|
||||
(const char *)&can_broadcast, sizeof(can_broadcast)) < 0)
|
||||
RARCH_WARN("[Discovery] Failed to set netplay discovery port to broadcast\n");
|
||||
#endif
|
||||
|
||||
/* Put together the request */
|
||||
memcpy((void *) &ad_packet_buffer, "RANQ", 4);
|
||||
ad_packet_buffer.protocol_version = htonl(NETPLAY_PROTOCOL_VERSION);
|
||||
|
||||
for (k = 0; k < (unsigned)interfaces.size; k++)
|
||||
{
|
||||
strlcpy(ad_packet_buffer.address, interfaces.entries[k].host,
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
|
||||
/* And send it off */
|
||||
ret = (int)sendto(lan_ad_client_fd, (const char *) &ad_packet_buffer,
|
||||
sizeof(struct ad_packet), 0, addr->ai_addr, addr->ai_addrlen);
|
||||
if (ret < (ssize_t) (2*sizeof(uint32_t)))
|
||||
RARCH_WARN("[Discovery] Failed to send netplay discovery query (error: %d)\n", errno);
|
||||
}
|
||||
|
||||
freeaddrinfo_retro(addr);
|
||||
net_ifinfo_free(&interfaces);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case RARCH_NETPLAY_DISCOVERY_CTL_LAN_GET_RESPONSES:
|
||||
if (!netplay_lan_ad_client())
|
||||
return false;
|
||||
*((struct netplay_host_list **) data) = &discovered_hosts;
|
||||
break;
|
||||
|
||||
case RARCH_NETPLAY_DISCOVERY_CTL_LAN_CLEAR_RESPONSES:
|
||||
discovered_hosts.size = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_NETPLAYDISCOVERY
|
||||
static bool init_lan_ad_server_socket(netplay_t *netplay, uint16_t port)
|
||||
{
|
||||
struct addrinfo *addr = NULL;
|
||||
int fd = socket_init((void **) &addr, port, NULL, SOCKET_TYPE_DATAGRAM);
|
||||
|
||||
if (fd < 0)
|
||||
goto error;
|
||||
|
||||
if (!socket_bind(fd, (void*)addr))
|
||||
{
|
||||
socket_close(fd);
|
||||
goto error;
|
||||
}
|
||||
|
||||
lan_ad_server_fd = fd;
|
||||
freeaddrinfo_retro(addr);
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (addr)
|
||||
freeaddrinfo_retro(addr);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* netplay_lan_ad_server
|
||||
*
|
||||
* Respond to any LAN ad queries that the netplay server has received.
|
||||
*/
|
||||
bool netplay_lan_ad_server(netplay_t *netplay)
|
||||
{
|
||||
/* Todo: implement net_ifinfo and ntohs for consoles */
|
||||
#ifdef HAVE_NETPLAYDISCOVERY
|
||||
fd_set fds;
|
||||
int ret;
|
||||
unsigned i;
|
||||
char buf[4096];
|
||||
net_ifinfo_t interfaces;
|
||||
socklen_t addr_size;
|
||||
char reply_addr[NETPLAY_HOST_STR_LEN], port_str[6];
|
||||
struct sockaddr their_addr;
|
||||
struct timeval tmp_tv = {0};
|
||||
unsigned k = 0;
|
||||
struct addrinfo *our_addr, hints = {0};
|
||||
struct string_list *subsystem = path_get_subsystem_list();
|
||||
|
||||
interfaces.entries = NULL;
|
||||
interfaces.size = 0;
|
||||
|
||||
their_addr.sa_family = 0;
|
||||
for (i = 0; i < 14; i++)
|
||||
their_addr.sa_data[i] = 0;
|
||||
|
||||
if (!net_ifinfo_new(&interfaces))
|
||||
return false;
|
||||
|
||||
if ( (lan_ad_server_fd < 0)
|
||||
&& !init_lan_ad_server_socket(netplay, RARCH_DEFAULT_PORT))
|
||||
{
|
||||
RARCH_ERR("[Discovery] Failed to initialize netplay advertisement socket\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check for any ad queries */
|
||||
for (;;)
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(lan_ad_server_fd, &fds);
|
||||
if (socket_select(lan_ad_server_fd + 1, &fds, NULL, NULL, &tmp_tv) <= 0)
|
||||
break;
|
||||
if (!FD_ISSET(lan_ad_server_fd, &fds))
|
||||
break;
|
||||
|
||||
/* Somebody queried, so check that it's valid */
|
||||
addr_size = sizeof(their_addr);
|
||||
ret = (int)recvfrom(lan_ad_server_fd, (char*)&ad_packet_buffer,
|
||||
sizeof(struct ad_packet), 0, &their_addr, &addr_size);
|
||||
if (ret >= (ssize_t) (2 * sizeof(uint32_t)))
|
||||
{
|
||||
char s[NETPLAY_HOST_STR_LEN];
|
||||
uint32_t content_crc = 0;
|
||||
|
||||
/* Make sure it's a valid query */
|
||||
if (memcmp((void *) &ad_packet_buffer, "RANQ", 4))
|
||||
{
|
||||
RARCH_LOG("[Discovery] Invalid query\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* For this version */
|
||||
if (ntohl(ad_packet_buffer.protocol_version) !=
|
||||
NETPLAY_PROTOCOL_VERSION)
|
||||
{
|
||||
RARCH_LOG("[Discovery] Invalid protocol version\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string_is_empty(ad_packet_buffer.address))
|
||||
strlcpy(reply_addr, ad_packet_buffer.address, NETPLAY_HOST_STR_LEN);
|
||||
|
||||
for (k = 0; k < interfaces.size; k++)
|
||||
{
|
||||
char *p;
|
||||
char sub[NETPLAY_HOST_STR_LEN];
|
||||
char frontend_architecture_tmp[32];
|
||||
char frontend[256];
|
||||
const frontend_ctx_driver_t *frontend_drv =
|
||||
(const frontend_ctx_driver_t*)
|
||||
frontend_driver_get_cpu_architecture_str(
|
||||
frontend_architecture_tmp, sizeof(frontend_architecture_tmp));
|
||||
snprintf(frontend, sizeof(frontend), "%s %s",
|
||||
frontend_drv->ident, frontend_architecture_tmp);
|
||||
|
||||
p=strrchr(reply_addr,'.');
|
||||
if (p)
|
||||
{
|
||||
strlcpy(sub, reply_addr, p - reply_addr + 1);
|
||||
if (strstr(interfaces.entries[k].host, sub) &&
|
||||
!strstr(interfaces.entries[k].host, "127.0.0.1"))
|
||||
{
|
||||
struct retro_system_info *info = runloop_get_libretro_system_info();
|
||||
|
||||
RARCH_LOG ("[Discovery] Query received on common interface: %s/%s (theirs / ours) \n",
|
||||
reply_addr, interfaces.entries[k].host);
|
||||
|
||||
/* Now build our response */
|
||||
buf[0] = '\0';
|
||||
content_crc = content_get_crc();
|
||||
|
||||
memset(&ad_packet_buffer, 0, sizeof(struct ad_packet));
|
||||
memcpy(&ad_packet_buffer, "RANS", 4);
|
||||
|
||||
if (subsystem)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < subsystem->size; i++)
|
||||
{
|
||||
strlcat(buf, path_basename(subsystem->elems[i].data), NETPLAY_HOST_LONGSTR_LEN);
|
||||
if (i < subsystem->size - 1)
|
||||
strlcat(buf, "|", NETPLAY_HOST_LONGSTR_LEN);
|
||||
}
|
||||
strlcpy(ad_packet_buffer.content, buf,
|
||||
NETPLAY_HOST_LONGSTR_LEN);
|
||||
strlcpy(ad_packet_buffer.subsystem_name, path_get(RARCH_PATH_SUBSYSTEM),
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(ad_packet_buffer.content, !string_is_empty(
|
||||
path_basename(path_get(RARCH_PATH_BASENAME)))
|
||||
? path_basename(path_get(RARCH_PATH_BASENAME)) : "N/A",
|
||||
NETPLAY_HOST_LONGSTR_LEN);
|
||||
strlcpy(ad_packet_buffer.subsystem_name, "N/A", NETPLAY_HOST_STR_LEN);
|
||||
}
|
||||
|
||||
strlcpy(ad_packet_buffer.address, interfaces.entries[k].host,
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
ad_packet_buffer.protocol_version =
|
||||
htonl(NETPLAY_PROTOCOL_VERSION);
|
||||
ad_packet_buffer.port = htonl(netplay->tcp_port);
|
||||
strlcpy(ad_packet_buffer.retroarch_version, PACKAGE_VERSION,
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
strlcpy(ad_packet_buffer.nick, netplay->nick, NETPLAY_HOST_STR_LEN);
|
||||
strlcpy(ad_packet_buffer.frontend, frontend, NETPLAY_HOST_STR_LEN);
|
||||
|
||||
if (info)
|
||||
{
|
||||
strlcpy(ad_packet_buffer.core, info->library_name,
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
strlcpy(ad_packet_buffer.core_version, info->library_version,
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
}
|
||||
|
||||
snprintf(s, sizeof(s), "%d", content_crc);
|
||||
strlcpy(ad_packet_buffer.content_crc, s,
|
||||
NETPLAY_HOST_STR_LEN);
|
||||
|
||||
/* Build up the destination address*/
|
||||
snprintf(port_str, 6, "%hu", ntohs(((struct sockaddr_in*)(&their_addr))->sin_port));
|
||||
if (getaddrinfo_retro(reply_addr, port_str, &hints, &our_addr) < 0)
|
||||
continue;
|
||||
|
||||
RARCH_LOG ("[Discovery] Sending reply to %s \n", reply_addr);
|
||||
|
||||
/* And send it */
|
||||
sendto(lan_ad_server_fd, (const char*)&ad_packet_buffer,
|
||||
sizeof(struct ad_packet), 0, our_addr->ai_addr, our_addr->ai_addrlen);
|
||||
freeaddrinfo_retro(our_addr);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
net_ifinfo_free(&interfaces);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -128,15 +128,11 @@ static void netplay_log_connection(
|
||||
}
|
||||
|
||||
if (str)
|
||||
{
|
||||
snprintf(s, len, msg_hash_to_str(MSG_GOT_CONNECTION_FROM_NAME),
|
||||
nick, str);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(s, len, msg_hash_to_str(MSG_GOT_CONNECTION_FROM),
|
||||
nick);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void netplay_log_connection(
|
||||
|
@ -56,48 +56,44 @@ static struct netplay_rooms *netplay_rooms_data;
|
||||
|
||||
static bool netplay_json_boolean(void* ctx, bool value)
|
||||
{
|
||||
struct netplay_json_context* pCtx = (struct netplay_json_context*)ctx;
|
||||
struct netplay_json_context* p_ctx = (struct netplay_json_context*)ctx;
|
||||
|
||||
if (pCtx->state == STATE_FIELDS_OBJECT_START)
|
||||
if (pCtx->cur_member_bool)
|
||||
*pCtx->cur_member_bool = value;
|
||||
if (p_ctx->state == STATE_FIELDS_OBJECT_START)
|
||||
if (p_ctx->cur_member_bool)
|
||||
*p_ctx->cur_member_bool = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool netplay_json_string(void* ctx, const char* pValue, size_t length)
|
||||
static bool netplay_json_string(void* ctx, const char *p_value, size_t len)
|
||||
{
|
||||
struct netplay_json_context* pCtx = (struct netplay_json_context*)ctx;
|
||||
struct netplay_json_context* p_ctx = (struct netplay_json_context*)ctx;
|
||||
|
||||
if (pCtx->state == STATE_FIELDS_OBJECT_START)
|
||||
if (p_ctx->state == STATE_FIELDS_OBJECT_START)
|
||||
{
|
||||
if (pValue && length)
|
||||
if (p_value && len)
|
||||
{
|
||||
if (pCtx->cur_member_inthex)
|
||||
{
|
||||
/* CRC comes in as a string but it is stored
|
||||
* as an unsigned casted to int. */
|
||||
*pCtx->cur_member_inthex = (int)strtoul(pValue, NULL, 16);
|
||||
}
|
||||
if (pCtx->cur_member_string)
|
||||
{
|
||||
strlcpy(pCtx->cur_member_string, pValue, pCtx->cur_member_size);
|
||||
}
|
||||
/* CRC comes in as a string but it is stored
|
||||
* as an unsigned casted to int. */
|
||||
if (p_ctx->cur_member_inthex)
|
||||
*p_ctx->cur_member_inthex = (int)strtoul(p_value, NULL, 16);
|
||||
if (p_ctx->cur_member_string)
|
||||
strlcpy(p_ctx->cur_member_string, p_value, p_ctx->cur_member_size);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool netplay_json_number(void* ctx, const char* pValue, size_t length)
|
||||
static bool netplay_json_number(void* ctx, const char *p_value, size_t len)
|
||||
{
|
||||
struct netplay_json_context* pCtx = (struct netplay_json_context*)ctx;
|
||||
struct netplay_json_context *p_ctx = (struct netplay_json_context*)ctx;
|
||||
|
||||
if (pCtx->state == STATE_FIELDS_OBJECT_START)
|
||||
if (p_ctx->state == STATE_FIELDS_OBJECT_START)
|
||||
{
|
||||
if (pValue && length)
|
||||
if (pCtx->cur_member_int)
|
||||
*pCtx->cur_member_int = (int)strtol(pValue, NULL, 10);
|
||||
if (p_value && len)
|
||||
if (p_ctx->cur_member_int)
|
||||
*p_ctx->cur_member_int = (int)strtol(p_value, NULL, 10);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -105,11 +101,11 @@ static bool netplay_json_number(void* ctx, const char* pValue, size_t length)
|
||||
|
||||
static bool netplay_json_start_object(void* ctx)
|
||||
{
|
||||
struct netplay_json_context* pCtx = (struct netplay_json_context*)ctx;
|
||||
struct netplay_json_context *p_ctx = (struct netplay_json_context*)ctx;
|
||||
|
||||
if (pCtx->state == STATE_FIELDS_START)
|
||||
if (p_ctx->state == STATE_FIELDS_START)
|
||||
{
|
||||
pCtx->state = STATE_FIELDS_OBJECT_START;
|
||||
p_ctx->state = STATE_FIELDS_OBJECT_START;
|
||||
|
||||
if (!netplay_rooms_data->head)
|
||||
{
|
||||
@ -122,119 +118,120 @@ static bool netplay_json_start_object(void* ctx)
|
||||
netplay_rooms_data->cur = netplay_rooms_data->cur->next;
|
||||
}
|
||||
}
|
||||
else if (pCtx->state == STATE_ARRAY_START)
|
||||
pCtx->state = STATE_OBJECT_START;
|
||||
else if (p_ctx->state == STATE_ARRAY_START)
|
||||
p_ctx->state = STATE_OBJECT_START;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool netplay_json_end_object(void* ctx)
|
||||
{
|
||||
struct netplay_json_context* pCtx = (struct netplay_json_context*)ctx;
|
||||
struct netplay_json_context *p_ctx = (struct netplay_json_context*)ctx;
|
||||
|
||||
if (pCtx->state == STATE_FIELDS_OBJECT_START)
|
||||
pCtx->state = STATE_ARRAY_START;
|
||||
if (p_ctx->state == STATE_FIELDS_OBJECT_START)
|
||||
p_ctx->state = STATE_ARRAY_START;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool netplay_json_object_member(void* ctx, const char* pValue, size_t length)
|
||||
static bool netplay_json_object_member(void *ctx, const char *p_value,
|
||||
size_t len)
|
||||
{
|
||||
struct netplay_json_context* pCtx = (struct netplay_json_context*)ctx;
|
||||
struct netplay_json_context* p_ctx = (struct netplay_json_context*)ctx;
|
||||
|
||||
if (!pValue || !length)
|
||||
if (!p_value || !len)
|
||||
return true;
|
||||
|
||||
if (pCtx->state == STATE_OBJECT_START && !string_is_empty(pValue)
|
||||
&& string_is_equal(pValue, "fields"))
|
||||
pCtx->state = STATE_FIELDS_START;
|
||||
if (p_ctx->state == STATE_OBJECT_START && !string_is_empty(p_value)
|
||||
&& string_is_equal(p_value, "fields"))
|
||||
p_ctx->state = STATE_FIELDS_START;
|
||||
|
||||
if (pCtx->state == STATE_FIELDS_OBJECT_START)
|
||||
if (p_ctx->state == STATE_FIELDS_OBJECT_START)
|
||||
{
|
||||
pCtx->cur_member_bool = NULL;
|
||||
pCtx->cur_member_int = NULL;
|
||||
pCtx->cur_member_inthex = NULL;
|
||||
pCtx->cur_member_string = NULL;
|
||||
p_ctx->cur_member_bool = NULL;
|
||||
p_ctx->cur_member_int = NULL;
|
||||
p_ctx->cur_member_inthex = NULL;
|
||||
p_ctx->cur_member_string = NULL;
|
||||
|
||||
if (!string_is_empty(pValue))
|
||||
if (!string_is_empty(p_value))
|
||||
{
|
||||
if (string_is_equal(pValue, "username"))
|
||||
if (string_is_equal(p_value, "username"))
|
||||
{
|
||||
pCtx->cur_member_string = netplay_rooms_data->cur->nickname;
|
||||
pCtx->cur_member_size = sizeof(netplay_rooms_data->cur->nickname);
|
||||
p_ctx->cur_member_string = netplay_rooms_data->cur->nickname;
|
||||
p_ctx->cur_member_size = sizeof(netplay_rooms_data->cur->nickname);
|
||||
}
|
||||
else if (string_is_equal(pValue, "game_name"))
|
||||
else if (string_is_equal(p_value, "game_name"))
|
||||
{
|
||||
pCtx->cur_member_string = netplay_rooms_data->cur->gamename;
|
||||
pCtx->cur_member_size = sizeof(netplay_rooms_data->cur->gamename);
|
||||
p_ctx->cur_member_string = netplay_rooms_data->cur->gamename;
|
||||
p_ctx->cur_member_size = sizeof(netplay_rooms_data->cur->gamename);
|
||||
}
|
||||
else if (string_is_equal(pValue, "core_name"))
|
||||
else if (string_is_equal(p_value, "core_name"))
|
||||
{
|
||||
pCtx->cur_member_string = netplay_rooms_data->cur->corename;
|
||||
pCtx->cur_member_size = sizeof(netplay_rooms_data->cur->corename);
|
||||
p_ctx->cur_member_string = netplay_rooms_data->cur->corename;
|
||||
p_ctx->cur_member_size = sizeof(netplay_rooms_data->cur->corename);
|
||||
}
|
||||
else if (string_is_equal(pValue, "ip"))
|
||||
else if (string_is_equal(p_value, "ip"))
|
||||
{
|
||||
pCtx->cur_member_string = netplay_rooms_data->cur->address;
|
||||
pCtx->cur_member_size = sizeof(netplay_rooms_data->cur->address);
|
||||
p_ctx->cur_member_string = netplay_rooms_data->cur->address;
|
||||
p_ctx->cur_member_size = sizeof(netplay_rooms_data->cur->address);
|
||||
}
|
||||
else if (string_is_equal(pValue, "port"))
|
||||
else if (string_is_equal(p_value, "port"))
|
||||
{
|
||||
pCtx->cur_member_int = &netplay_rooms_data->cur->port;
|
||||
p_ctx->cur_member_int = &netplay_rooms_data->cur->port;
|
||||
}
|
||||
else if (string_is_equal(pValue, "game_crc"))
|
||||
else if (string_is_equal(p_value, "game_crc"))
|
||||
{
|
||||
pCtx->cur_member_inthex = &netplay_rooms_data->cur->gamecrc;
|
||||
p_ctx->cur_member_inthex = &netplay_rooms_data->cur->gamecrc;
|
||||
}
|
||||
else if (string_is_equal(pValue, "core_version"))
|
||||
else if (string_is_equal(p_value, "core_version"))
|
||||
{
|
||||
pCtx->cur_member_string = netplay_rooms_data->cur->coreversion;
|
||||
pCtx->cur_member_size = sizeof(netplay_rooms_data->cur->coreversion);
|
||||
p_ctx->cur_member_string = netplay_rooms_data->cur->coreversion;
|
||||
p_ctx->cur_member_size = sizeof(netplay_rooms_data->cur->coreversion);
|
||||
}
|
||||
else if (string_is_equal(pValue, "has_password"))
|
||||
else if (string_is_equal(p_value, "has_password"))
|
||||
{
|
||||
pCtx->cur_member_bool = &netplay_rooms_data->cur->has_password;
|
||||
p_ctx->cur_member_bool = &netplay_rooms_data->cur->has_password;
|
||||
}
|
||||
else if (string_is_equal(pValue, "has_spectate_password"))
|
||||
else if (string_is_equal(p_value, "has_spectate_password"))
|
||||
{
|
||||
pCtx->cur_member_bool = &netplay_rooms_data->cur->has_spectate_password;
|
||||
p_ctx->cur_member_bool = &netplay_rooms_data->cur->has_spectate_password;
|
||||
}
|
||||
else if (string_is_equal(pValue, "fixed"))
|
||||
else if (string_is_equal(p_value, "fixed"))
|
||||
{
|
||||
pCtx->cur_member_bool = &netplay_rooms_data->cur->fixed;
|
||||
p_ctx->cur_member_bool = &netplay_rooms_data->cur->fixed;
|
||||
}
|
||||
else if (string_is_equal(pValue, "mitm_ip"))
|
||||
else if (string_is_equal(p_value, "mitm_ip"))
|
||||
{
|
||||
pCtx->cur_member_string = netplay_rooms_data->cur->mitm_address;
|
||||
pCtx->cur_member_size = sizeof(netplay_rooms_data->cur->mitm_address);
|
||||
p_ctx->cur_member_string = netplay_rooms_data->cur->mitm_address;
|
||||
p_ctx->cur_member_size = sizeof(netplay_rooms_data->cur->mitm_address);
|
||||
}
|
||||
else if (string_is_equal(pValue, "mitm_port"))
|
||||
else if (string_is_equal(p_value, "mitm_port"))
|
||||
{
|
||||
pCtx->cur_member_int = &netplay_rooms_data->cur->mitm_port;
|
||||
p_ctx->cur_member_int = &netplay_rooms_data->cur->mitm_port;
|
||||
}
|
||||
else if (string_is_equal(pValue, "host_method"))
|
||||
else if (string_is_equal(p_value, "host_method"))
|
||||
{
|
||||
pCtx->cur_member_int = &netplay_rooms_data->cur->host_method;
|
||||
p_ctx->cur_member_int = &netplay_rooms_data->cur->host_method;
|
||||
}
|
||||
else if (string_is_equal(pValue, "retroarch_version"))
|
||||
else if (string_is_equal(p_value, "retroarch_version"))
|
||||
{
|
||||
pCtx->cur_member_string = netplay_rooms_data->cur->retroarch_version;
|
||||
pCtx->cur_member_size = sizeof(netplay_rooms_data->cur->retroarch_version);
|
||||
p_ctx->cur_member_string = netplay_rooms_data->cur->retroarch_version;
|
||||
p_ctx->cur_member_size = sizeof(netplay_rooms_data->cur->retroarch_version);
|
||||
}
|
||||
else if (string_is_equal(pValue, "country"))
|
||||
else if (string_is_equal(p_value, "country"))
|
||||
{
|
||||
pCtx->cur_member_string = netplay_rooms_data->cur->country;
|
||||
pCtx->cur_member_size = sizeof(netplay_rooms_data->cur->country);
|
||||
p_ctx->cur_member_string = netplay_rooms_data->cur->country;
|
||||
p_ctx->cur_member_size = sizeof(netplay_rooms_data->cur->country);
|
||||
}
|
||||
else if (string_is_equal(pValue, "frontend"))
|
||||
else if (string_is_equal(p_value, "frontend"))
|
||||
{
|
||||
pCtx->cur_member_string = netplay_rooms_data->cur->frontend;
|
||||
pCtx->cur_member_size = sizeof(netplay_rooms_data->cur->frontend);
|
||||
p_ctx->cur_member_string = netplay_rooms_data->cur->frontend;
|
||||
p_ctx->cur_member_size = sizeof(netplay_rooms_data->cur->frontend);
|
||||
}
|
||||
else if (string_is_equal(pValue, "subsystem_name"))
|
||||
else if (string_is_equal(p_value, "subsystem_name"))
|
||||
{
|
||||
pCtx->cur_member_string = netplay_rooms_data->cur->subsystem_name;
|
||||
pCtx->cur_member_size = sizeof(netplay_rooms_data->cur->subsystem_name);
|
||||
p_ctx->cur_member_string = netplay_rooms_data->cur->subsystem_name;
|
||||
p_ctx->cur_member_size = sizeof(netplay_rooms_data->cur->subsystem_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -244,15 +241,16 @@ static bool netplay_json_object_member(void* ctx, const char* pValue, size_t len
|
||||
|
||||
static bool netplay_json_start_array(void* ctx)
|
||||
{
|
||||
struct netplay_json_context* pCtx = (struct netplay_json_context*)ctx;
|
||||
struct netplay_json_context* p_ctx = (struct netplay_json_context*)ctx;
|
||||
|
||||
if (pCtx->state == STATE_START)
|
||||
pCtx->state = STATE_ARRAY_START;
|
||||
if (p_ctx->state == STATE_START)
|
||||
p_ctx->state = STATE_ARRAY_START;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void netplay_rooms_error(void *context, int line, int col, const char* error)
|
||||
static void netplay_rooms_error(void *context,
|
||||
int line, int col, const char* error)
|
||||
{
|
||||
RARCH_ERR("[netplay] Error: Invalid JSON at line %d, column %d - %s.\n",
|
||||
line, col, error);
|
||||
|
Loading…
x
Reference in New Issue
Block a user