mirror of
https://github.com/libretro/RetroArch
synced 2025-03-20 19:21:27 +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 struct netplay_host_list discovered_hosts;
|
||||||
static size_t discovered_hosts_allocated;
|
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
|
#ifdef HAVE_SOCKET_LEGACY
|
||||||
|
|
||||||
#ifndef htons
|
#ifndef htons
|
||||||
@ -464,7 +145,8 @@ static bool netplay_lan_ad_client(void)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* For this version */
|
/* For this version */
|
||||||
if (ntohl(ad_packet_buffer.protocol_version) != NETPLAY_PROTOCOL_VERSION)
|
if (ntohl(ad_packet_buffer.protocol_version)
|
||||||
|
!= NETPLAY_PROTOCOL_VERSION)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* And that we know how to handle it */
|
/* And that we know how to handle it */
|
||||||
@ -472,7 +154,7 @@ static bool netplay_lan_ad_client(void)
|
|||||||
{
|
{
|
||||||
struct sockaddr_in *sin = NULL;
|
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 = (struct sockaddr_in *) &their_addr;
|
||||||
sin->sin_port = htons(ntohl(ad_packet_buffer.port));
|
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)
|
else if (their_addr.sa_family == AF_INET6)
|
||||||
{
|
{
|
||||||
struct sockaddr_in6 *sin6 = NULL;
|
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 = (struct sockaddr_in6 *) &their_addr;
|
||||||
sin6->sin6_port = htons(ad_packet_buffer.port);
|
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
|
realloc(discovered_hosts.hosts, allocated * sizeof(struct
|
||||||
netplay_host));
|
netplay_host));
|
||||||
else
|
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 *)
|
new_hosts = (struct netplay_host *)
|
||||||
malloc(allocated * sizeof(struct netplay_host));
|
malloc(allocated * sizeof(struct netplay_host));
|
||||||
|
|
||||||
@ -552,3 +235,321 @@ static bool netplay_lan_ad_client(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
if (str)
|
||||||
{
|
|
||||||
snprintf(s, len, msg_hash_to_str(MSG_GOT_CONNECTION_FROM_NAME),
|
snprintf(s, len, msg_hash_to_str(MSG_GOT_CONNECTION_FROM_NAME),
|
||||||
nick, str);
|
nick, str);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
snprintf(s, len, msg_hash_to_str(MSG_GOT_CONNECTION_FROM),
|
snprintf(s, len, msg_hash_to_str(MSG_GOT_CONNECTION_FROM),
|
||||||
nick);
|
nick);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void netplay_log_connection(
|
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)
|
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 (p_ctx->state == STATE_FIELDS_OBJECT_START)
|
||||||
if (pCtx->cur_member_bool)
|
if (p_ctx->cur_member_bool)
|
||||||
*pCtx->cur_member_bool = value;
|
*p_ctx->cur_member_bool = value;
|
||||||
|
|
||||||
return true;
|
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. */
|
||||||
/* CRC comes in as a string but it is stored
|
if (p_ctx->cur_member_inthex)
|
||||||
* as an unsigned casted to int. */
|
*p_ctx->cur_member_inthex = (int)strtoul(p_value, NULL, 16);
|
||||||
*pCtx->cur_member_inthex = (int)strtoul(pValue, NULL, 16);
|
if (p_ctx->cur_member_string)
|
||||||
}
|
strlcpy(p_ctx->cur_member_string, p_value, p_ctx->cur_member_size);
|
||||||
if (pCtx->cur_member_string)
|
|
||||||
{
|
|
||||||
strlcpy(pCtx->cur_member_string, pValue, pCtx->cur_member_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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 (p_value && len)
|
||||||
if (pCtx->cur_member_int)
|
if (p_ctx->cur_member_int)
|
||||||
*pCtx->cur_member_int = (int)strtol(pValue, NULL, 10);
|
*p_ctx->cur_member_int = (int)strtol(p_value, NULL, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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)
|
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)
|
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;
|
netplay_rooms_data->cur = netplay_rooms_data->cur->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pCtx->state == STATE_ARRAY_START)
|
else if (p_ctx->state == STATE_ARRAY_START)
|
||||||
pCtx->state = STATE_OBJECT_START;
|
p_ctx->state = STATE_OBJECT_START;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool netplay_json_end_object(void* ctx)
|
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)
|
if (p_ctx->state == STATE_FIELDS_OBJECT_START)
|
||||||
pCtx->state = STATE_ARRAY_START;
|
p_ctx->state = STATE_ARRAY_START;
|
||||||
|
|
||||||
return true;
|
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;
|
return true;
|
||||||
|
|
||||||
if (pCtx->state == STATE_OBJECT_START && !string_is_empty(pValue)
|
if (p_ctx->state == STATE_OBJECT_START && !string_is_empty(p_value)
|
||||||
&& string_is_equal(pValue, "fields"))
|
&& string_is_equal(p_value, "fields"))
|
||||||
pCtx->state = STATE_FIELDS_START;
|
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;
|
p_ctx->cur_member_bool = NULL;
|
||||||
pCtx->cur_member_int = NULL;
|
p_ctx->cur_member_int = NULL;
|
||||||
pCtx->cur_member_inthex = NULL;
|
p_ctx->cur_member_inthex = NULL;
|
||||||
pCtx->cur_member_string = 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;
|
p_ctx->cur_member_string = netplay_rooms_data->cur->nickname;
|
||||||
pCtx->cur_member_size = sizeof(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;
|
p_ctx->cur_member_string = netplay_rooms_data->cur->gamename;
|
||||||
pCtx->cur_member_size = sizeof(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;
|
p_ctx->cur_member_string = netplay_rooms_data->cur->corename;
|
||||||
pCtx->cur_member_size = sizeof(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;
|
p_ctx->cur_member_string = netplay_rooms_data->cur->address;
|
||||||
pCtx->cur_member_size = sizeof(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;
|
p_ctx->cur_member_string = netplay_rooms_data->cur->coreversion;
|
||||||
pCtx->cur_member_size = sizeof(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;
|
p_ctx->cur_member_string = netplay_rooms_data->cur->mitm_address;
|
||||||
pCtx->cur_member_size = sizeof(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;
|
p_ctx->cur_member_string = netplay_rooms_data->cur->retroarch_version;
|
||||||
pCtx->cur_member_size = sizeof(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;
|
p_ctx->cur_member_string = netplay_rooms_data->cur->country;
|
||||||
pCtx->cur_member_size = sizeof(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;
|
p_ctx->cur_member_string = netplay_rooms_data->cur->frontend;
|
||||||
pCtx->cur_member_size = sizeof(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;
|
p_ctx->cur_member_string = netplay_rooms_data->cur->subsystem_name;
|
||||||
pCtx->cur_member_size = sizeof(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)
|
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)
|
if (p_ctx->state == STATE_START)
|
||||||
pCtx->state = STATE_ARRAY_START;
|
p_ctx->state = STATE_ARRAY_START;
|
||||||
|
|
||||||
return true;
|
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",
|
RARCH_ERR("[netplay] Error: Invalid JSON at line %d, column %d - %s.\n",
|
||||||
line, col, error);
|
line, col, error);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user