RetroArch/network/netplay/netplay_room_parse.c

347 lines
10 KiB
C
Raw Normal View History

2017-03-04 01:31:24 -05:00
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2016-2017 - Gregor Richards
2019-02-22 10:07:32 -05:00
* Copyright (C) 2016-2019 - Brad Parker
2017-03-04 01:31:24 -05:00
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string/stdstring.h>
#include <compat/strl.h>
#include <formats/rjson.h>
#include "netplay.h"
2017-03-04 01:31:24 -05:00
#include "../../verbosity.h"
enum netplay_parse_state
2017-03-04 01:31:24 -05:00
{
STATE_START = 0,
STATE_ARRAY_START,
STATE_OBJECT_START,
STATE_FIELDS_START,
STATE_FIELDS_OBJECT_START,
STATE_END
};
struct netplay_json_context
2017-03-04 01:31:24 -05:00
{
bool *cur_member_bool;
int *cur_member_int;
int *cur_member_inthex;
char *cur_member_string;
size_t cur_member_size;
enum netplay_parse_state state;
};
2017-03-04 01:31:24 -05:00
static bool netplay_json_boolean(void* ctx, bool value)
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
struct netplay_json_context* p_ctx = (struct netplay_json_context*)ctx;
2017-03-04 01:31:24 -05:00
2021-04-08 19:24:19 +02:00
if (p_ctx->state == STATE_FIELDS_OBJECT_START)
if (p_ctx->cur_member_bool)
*p_ctx->cur_member_bool = value;
2017-03-04 01:31:24 -05:00
return true;
2017-03-04 01:31:24 -05:00
}
2021-04-08 19:24:19 +02:00
static bool netplay_json_string(void* ctx, const char *p_value, size_t len)
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
struct netplay_json_context* p_ctx = (struct netplay_json_context*)ctx;
2017-03-04 01:31:24 -05:00
2021-04-08 19:24:19 +02:00
if (p_ctx->state == STATE_FIELDS_OBJECT_START)
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
if (p_value && len)
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
/* 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);
2017-03-04 01:31:24 -05:00
}
}
return true;
2017-03-04 01:31:24 -05:00
}
2021-04-08 19:24:19 +02:00
static bool netplay_json_number(void* ctx, const char *p_value, size_t len)
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
struct netplay_json_context *p_ctx = (struct netplay_json_context*)ctx;
2017-03-04 01:31:24 -05:00
2021-04-08 19:24:19 +02:00
if (p_ctx->state == STATE_FIELDS_OBJECT_START)
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
if (p_value && len)
if (p_ctx->cur_member_int)
*p_ctx->cur_member_int = (int)strtol(p_value, NULL, 10);
2017-03-04 01:31:24 -05:00
}
return true;
2017-03-04 01:31:24 -05:00
}
static bool netplay_json_start_object(void* ctx)
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
struct netplay_json_context *p_ctx = (struct netplay_json_context*)ctx;
2021-11-06 00:27:33 +01:00
net_driver_state_t *net_st = networking_state_get_ptr();
2017-03-04 01:31:24 -05:00
2021-04-08 19:24:19 +02:00
if (p_ctx->state == STATE_FIELDS_START)
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
p_ctx->state = STATE_FIELDS_OBJECT_START;
2017-03-04 01:31:24 -05:00
2021-11-06 00:27:33 +01:00
if (!net_st->rooms_data->head)
2017-03-04 01:31:24 -05:00
{
2021-11-06 00:27:33 +01:00
net_st->rooms_data->head = (struct netplay_room*)calloc(1, sizeof(*net_st->rooms_data->head));
net_st->rooms_data->cur = net_st->rooms_data->head;
2017-03-04 01:31:24 -05:00
}
2021-11-06 00:27:33 +01:00
else if (!net_st->rooms_data->cur->next)
2017-03-04 01:31:24 -05:00
{
2021-11-06 00:27:33 +01:00
net_st->rooms_data->cur->next = (struct netplay_room*)calloc(1, sizeof(*net_st->rooms_data->cur->next));
net_st->rooms_data->cur = net_st->rooms_data->cur->next;
2017-03-04 01:31:24 -05:00
}
}
2021-04-08 19:24:19 +02:00
else if (p_ctx->state == STATE_ARRAY_START)
p_ctx->state = STATE_OBJECT_START;
2017-03-04 01:31:24 -05:00
return true;
2017-03-04 01:31:24 -05:00
}
static bool netplay_json_end_object(void* ctx)
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
struct netplay_json_context *p_ctx = (struct netplay_json_context*)ctx;
2017-03-04 01:31:24 -05:00
2021-04-08 19:24:19 +02:00
if (p_ctx->state == STATE_FIELDS_OBJECT_START)
p_ctx->state = STATE_ARRAY_START;
2017-03-04 01:31:24 -05:00
return true;
2017-03-04 01:31:24 -05:00
}
2021-04-08 19:24:19 +02:00
static bool netplay_json_object_member(void *ctx, const char *p_value,
size_t len)
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
struct netplay_json_context* p_ctx = (struct netplay_json_context*)ctx;
2021-11-06 00:27:33 +01:00
net_driver_state_t *net_st = networking_state_get_ptr();
2017-03-04 01:31:24 -05:00
2021-04-08 19:24:19 +02:00
if (!p_value || !len)
return true;
2017-03-04 01:31:24 -05:00
2021-04-08 19:24:19 +02:00
if (p_ctx->state == STATE_OBJECT_START && !string_is_empty(p_value)
&& string_is_equal(p_value, "fields"))
p_ctx->state = STATE_FIELDS_START;
2017-03-04 01:31:24 -05:00
2021-04-08 19:24:19 +02:00
if (p_ctx->state == STATE_FIELDS_OBJECT_START)
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
p_ctx->cur_member_bool = NULL;
p_ctx->cur_member_int = NULL;
p_ctx->cur_member_inthex = NULL;
p_ctx->cur_member_string = NULL;
2017-03-04 01:31:24 -05:00
2021-04-08 19:24:19 +02:00
if (!string_is_empty(p_value))
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
if (string_is_equal(p_value, "username"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_string = net_st->rooms_data->cur->nickname;
p_ctx->cur_member_size = sizeof(net_st->rooms_data->cur->nickname);
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "game_name"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_string = net_st->rooms_data->cur->gamename;
p_ctx->cur_member_size = sizeof(net_st->rooms_data->cur->gamename);
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "core_name"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_string = net_st->rooms_data->cur->corename;
p_ctx->cur_member_size = sizeof(net_st->rooms_data->cur->corename);
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "ip"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_string = net_st->rooms_data->cur->address;
p_ctx->cur_member_size = sizeof(net_st->rooms_data->cur->address);
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "port"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_int = &net_st->rooms_data->cur->port;
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "game_crc"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_inthex = &net_st->rooms_data->cur->gamecrc;
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "core_version"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_string = net_st->rooms_data->cur->coreversion;
p_ctx->cur_member_size = sizeof(net_st->rooms_data->cur->coreversion);
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "has_password"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_bool = &net_st->rooms_data->cur->has_password;
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "has_spectate_password"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_bool = &net_st->rooms_data->cur->has_spectate_password;
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "fixed"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_bool = &net_st->rooms_data->cur->fixed;
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "mitm_ip"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_string = net_st->rooms_data->cur->mitm_address;
p_ctx->cur_member_size = sizeof(net_st->rooms_data->cur->mitm_address);
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "mitm_port"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_int = &net_st->rooms_data->cur->mitm_port;
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "host_method"))
2017-05-28 18:00:47 +02:00
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_int = &net_st->rooms_data->cur->host_method;
2017-05-28 18:00:47 +02:00
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "retroarch_version"))
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_string = net_st->rooms_data->cur->retroarch_version;
p_ctx->cur_member_size = sizeof(net_st->rooms_data->cur->retroarch_version);
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "country"))
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_string = net_st->rooms_data->cur->country;
p_ctx->cur_member_size = sizeof(net_st->rooms_data->cur->country);
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "frontend"))
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_string = net_st->rooms_data->cur->frontend;
p_ctx->cur_member_size = sizeof(net_st->rooms_data->cur->frontend);
}
2021-04-08 19:24:19 +02:00
else if (string_is_equal(p_value, "subsystem_name"))
{
2021-11-06 00:27:33 +01:00
p_ctx->cur_member_string = net_st->rooms_data->cur->subsystem_name;
p_ctx->cur_member_size = sizeof(net_st->rooms_data->cur->subsystem_name);
}
2017-03-04 01:31:24 -05:00
}
}
return true;
2017-03-04 01:31:24 -05:00
}
static bool netplay_json_start_array(void* ctx)
2017-03-04 01:31:24 -05:00
{
2021-04-08 19:24:19 +02:00
struct netplay_json_context* p_ctx = (struct netplay_json_context*)ctx;
2017-03-04 01:31:24 -05:00
2021-04-08 19:24:19 +02:00
if (p_ctx->state == STATE_START)
p_ctx->state = STATE_ARRAY_START;
2017-03-04 01:31:24 -05:00
return true;
2017-03-04 01:31:24 -05:00
}
2021-04-08 19:24:19 +02:00
static void netplay_rooms_error(void *context,
int line, int col, const char* error)
2017-03-04 01:31:24 -05:00
{
RARCH_ERR("[netplay] Error: Invalid JSON at line %d, column %d - %s.\n",
line, col, error);
2017-03-04 01:31:24 -05:00
}
2019-06-26 07:13:50 +02:00
void netplay_rooms_free(void)
2017-03-04 01:31:24 -05:00
{
2021-11-06 00:27:33 +01:00
net_driver_state_t *net_st = networking_state_get_ptr();
if (net_st->rooms_data)
2017-03-04 01:31:24 -05:00
{
2021-11-06 00:27:33 +01:00
struct netplay_room *room = net_st->rooms_data->head;
2017-03-04 01:31:24 -05:00
if (room)
{
while (room)
2017-03-04 01:31:24 -05:00
{
struct netplay_room *next = room->next;
free(room);
room = next;
}
}
2021-11-06 00:27:33 +01:00
free(net_st->rooms_data);
2017-03-04 01:31:24 -05:00
}
2021-11-06 00:27:33 +01:00
net_st->rooms_data = NULL;
2017-03-04 01:31:24 -05:00
}
int netplay_rooms_parse(const char *buf)
{
struct netplay_json_context ctx;
2021-11-06 00:27:33 +01:00
net_driver_state_t *net_st = networking_state_get_ptr();
2017-03-04 01:31:24 -05:00
memset(&ctx, 0, sizeof(ctx));
ctx.state = STATE_START;
/* delete any previous rooms */
netplay_rooms_free();
2021-11-06 00:27:33 +01:00
net_st->rooms_data = (struct netplay_rooms*)
calloc(1, sizeof(*net_st->rooms_data));
2017-03-04 01:31:24 -05:00
rjson_parse_quick(buf, &ctx, 0,
netplay_json_object_member,
netplay_json_string,
netplay_json_number,
netplay_json_start_object,
netplay_json_end_object,
netplay_json_start_array,
NULL /* end_array_handler */,
netplay_json_boolean,
NULL /* null handler */,
netplay_rooms_error);
2017-03-04 01:31:24 -05:00
return 0;
}
struct netplay_room* netplay_room_get(int index)
{
2021-11-06 00:27:33 +01:00
int cur = 0;
net_driver_state_t *net_st = networking_state_get_ptr();
struct netplay_room *room = net_st->rooms_data->head;
2017-03-04 01:31:24 -05:00
if (index < 0)
return NULL;
2020-05-19 21:15:06 +02:00
while (room)
2017-03-04 01:31:24 -05:00
{
if (cur == index)
break;
room = room->next;
cur++;
}
return room;
}
2019-06-26 07:13:50 +02:00
int netplay_rooms_get_count(void)
2017-03-04 01:31:24 -05:00
{
int count = 0;
2021-11-06 00:27:33 +01:00
struct netplay_room *room = NULL;
net_driver_state_t *net_st = networking_state_get_ptr();
2017-03-04 01:31:24 -05:00
2021-11-06 00:27:33 +01:00
if (!net_st || !net_st->rooms_data)
2017-03-04 01:31:24 -05:00
return count;
2021-11-06 00:27:33 +01:00
if (!(room = net_st->rooms_data->head))
2017-03-04 01:31:24 -05:00
return count;
2020-05-19 21:15:06 +02:00
while (room)
2017-03-04 01:31:24 -05:00
{
count++;
room = room->next;
}
return count;
}