/* 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 * * 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 . */ #ifndef __RARCH_NETPLAY_H #define __RARCH_NETPLAY_H #include #include #include #ifdef HAVE_CONFIG_H #include "../../config.h" #endif #include #include #include "../../msg_hash.h" #include "../natt.h" #ifndef HAVE_DYNAMIC #define NETPLAY_FORK_MAX_ARGS 64 #endif #define NETPLAY_NICK_LEN 32 #define NETPLAY_HOST_STR_LEN 32 #define NETPLAY_HOST_LONGSTR_LEN 256 #define NETPLAY_MITM_SERVERS 5 #define NETPLAY_CHAT_MAX_MESSAGES 5 #define NETPLAY_CHAT_MAX_SIZE 96 #define NETPLAY_CHAT_FRAME_TIME 900 enum rarch_netplay_ctl_state { RARCH_NETPLAY_CTL_NONE = 0, RARCH_NETPLAY_CTL_GAME_WATCH, RARCH_NETPLAY_CTL_PLAYER_CHAT, RARCH_NETPLAY_CTL_POST_FRAME, RARCH_NETPLAY_CTL_PRE_FRAME, RARCH_NETPLAY_CTL_ENABLE_SERVER, RARCH_NETPLAY_CTL_ENABLE_CLIENT, RARCH_NETPLAY_CTL_DISABLE, #ifndef HAVE_DYNAMIC RARCH_NETPLAY_CTL_ADD_FORK_ARG, RARCH_NETPLAY_CTL_GET_FORK_ARGS, RARCH_NETPLAY_CTL_CLEAR_FORK_ARGS, #endif RARCH_NETPLAY_CTL_REFRESH_CLIENT_INFO, RARCH_NETPLAY_CTL_IS_ENABLED, RARCH_NETPLAY_CTL_IS_REPLAYING, RARCH_NETPLAY_CTL_IS_SERVER, RARCH_NETPLAY_CTL_IS_CONNECTED, RARCH_NETPLAY_CTL_IS_PLAYING, RARCH_NETPLAY_CTL_IS_SPECTATING, RARCH_NETPLAY_CTL_IS_DATA_INITED, RARCH_NETPLAY_CTL_ALLOW_PAUSE, RARCH_NETPLAY_CTL_PAUSE, RARCH_NETPLAY_CTL_UNPAUSE, RARCH_NETPLAY_CTL_LOAD_SAVESTATE, RARCH_NETPLAY_CTL_RESET, RARCH_NETPLAY_CTL_DISCONNECT, RARCH_NETPLAY_CTL_FINISHED_NAT_TRAVERSAL, RARCH_NETPLAY_CTL_DESYNC_PUSH, RARCH_NETPLAY_CTL_DESYNC_POP, RARCH_NETPLAY_CTL_KICK_CLIENT, RARCH_NETPLAY_CTL_BAN_CLIENT }; /* The current status of a connection */ enum rarch_netplay_connection_mode { NETPLAY_CONNECTION_NONE = 0, NETPLAY_CONNECTION_DELAYED_DISCONNECT, /* The connection is dead, but data is still waiting to be forwarded */ /* Initialization: */ NETPLAY_CONNECTION_INIT, /* Waiting for header */ NETPLAY_CONNECTION_PRE_NICK, /* Waiting for nick */ NETPLAY_CONNECTION_PRE_PASSWORD, /* Waiting for password */ NETPLAY_CONNECTION_PRE_INFO, /* Waiting for core/content info */ NETPLAY_CONNECTION_PRE_SYNC, /* Waiting for sync */ /* Ready: */ NETPLAY_CONNECTION_CONNECTED, /* Modes above this are connected */ NETPLAY_CONNECTION_SPECTATING, /* Spectator mode */ NETPLAY_CONNECTION_SLAVE, /* Playing in slave mode */ NETPLAY_CONNECTION_PLAYING /* Normal ready state */ }; /* Preferences for sharing digital devices */ enum rarch_netplay_share_digital_preference { RARCH_NETPLAY_SHARE_DIGITAL_NO_SHARING = 0, RARCH_NETPLAY_SHARE_DIGITAL_NO_PREFERENCE, RARCH_NETPLAY_SHARE_DIGITAL_OR, RARCH_NETPLAY_SHARE_DIGITAL_XOR, RARCH_NETPLAY_SHARE_DIGITAL_VOTE, RARCH_NETPLAY_SHARE_DIGITAL_LAST }; /* Preferences for sharing analog devices */ enum rarch_netplay_share_analog_preference { RARCH_NETPLAY_SHARE_ANALOG_NO_SHARING = 0, RARCH_NETPLAY_SHARE_ANALOG_NO_PREFERENCE, RARCH_NETPLAY_SHARE_ANALOG_MAX, RARCH_NETPLAY_SHARE_ANALOG_AVERAGE, RARCH_NETPLAY_SHARE_ANALOG_LAST }; enum netplay_host_method { NETPLAY_HOST_METHOD_UNKNOWN = 0, NETPLAY_HOST_METHOD_MANUAL, NETPLAY_HOST_METHOD_UPNP, NETPLAY_HOST_METHOD_MITM }; enum rarch_netplay_discovery_ctl_state { RARCH_NETPLAY_DISCOVERY_CTL_NONE = 0, RARCH_NETPLAY_DISCOVERY_CTL_LAN_SEND_QUERY, RARCH_NETPLAY_DISCOVERY_CTL_LAN_GET_RESPONSES, RARCH_NETPLAY_DISCOVERY_CTL_LAN_CLEAR_RESPONSES }; typedef struct netplay netplay_t; typedef struct netplay_client_info { uint32_t protocol; uint32_t devices; uint32_t slowdowns; int32_t ping; int id; enum rarch_netplay_connection_mode mode; char name[NETPLAY_NICK_LEN]; } netplay_client_info_t; typedef struct mitm_server { const char *name; enum msg_hash_enums description; } mitm_server_t; #ifndef HAVE_DYNAMIC struct netplay_fork_args { size_t size; char args[PATH_MAX_LENGTH]; }; #endif struct netplay_room { struct netplay_room *next; int id; int gamecrc; int port; int mitm_port; int host_method; char nickname[NETPLAY_NICK_LEN]; char frontend[NETPLAY_HOST_STR_LEN]; char corename[NETPLAY_HOST_STR_LEN]; char coreversion[NETPLAY_HOST_STR_LEN]; char retroarch_version[NETPLAY_HOST_STR_LEN]; char gamename[NETPLAY_HOST_LONGSTR_LEN]; char subsystem_name[NETPLAY_HOST_LONGSTR_LEN]; char country[3]; char address[NETPLAY_HOST_LONGSTR_LEN]; char mitm_handle[NETPLAY_HOST_STR_LEN]; char mitm_address[NETPLAY_HOST_LONGSTR_LEN]; char mitm_session[NETPLAY_HOST_STR_LEN]; bool has_password; bool has_spectate_password; bool connectable; bool is_retroarch; bool lan; }; struct netplay_rooms { struct netplay_room *head; struct netplay_room *cur; }; struct netplay_host { int content_crc; int port; char address[16]; char nick[NETPLAY_NICK_LEN]; char frontend[NETPLAY_HOST_STR_LEN]; char core[NETPLAY_HOST_STR_LEN]; char core_version[NETPLAY_HOST_STR_LEN]; char retroarch_version[NETPLAY_HOST_STR_LEN]; char content[NETPLAY_HOST_LONGSTR_LEN]; char subsystem_name[NETPLAY_HOST_LONGSTR_LEN]; bool has_password; bool has_spectate_password; }; struct netplay_host_list { struct netplay_host *hosts; size_t allocated; size_t size; }; struct netplay_chat_buffer { struct { uint8_t alpha; char nick[NETPLAY_NICK_LEN]; char msg[NETPLAY_CHAT_MAX_SIZE]; } messages[NETPLAY_CHAT_MAX_MESSAGES]; uint32_t color_name; uint32_t color_msg; }; enum net_driver_state_flags { NET_DRIVER_ST_FLAG_NETPLAY_CLIENT_DEFERRED = (1 << 0), /* Only used before init_netplay */ NET_DRIVER_ST_FLAG_NETPLAY_ENABLED = (1 << 1), NET_DRIVER_ST_FLAG_NETPLAY_IS_CLIENT = (1 << 2), NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_MODE = (1 << 3), NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_IP_ADDRESS = (1 << 4), NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_IP_PORT = (1 << 5), NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_CHECK_FRAMES = (1 << 6) }; typedef struct { #ifndef HAVE_DYNAMIC struct netplay_fork_args fork_args; #endif /* NAT traversal info (if NAT traversal is used and serving) */ struct nat_traversal_data nat_traversal_request; #ifdef HAVE_NETPLAYDISCOVERY /* List of discovered hosts */ struct netplay_host_list discovered_hosts; #endif struct netplay_chat_buffer chat_buffer; struct netplay_room host_room; struct netplay_room *room_list; struct netplay_rooms *rooms_data; /* Used while Netplay is running */ netplay_t *data; netplay_client_info_t *client_info; size_t client_info_count; #ifdef HAVE_NETPLAYDISCOVERY /* LAN discovery sockets */ int lan_ad_server_fd; int lan_ad_client_fd; #endif int room_count; int latest_ping; unsigned server_port_deferred; uint8_t flags; char server_address_deferred[256]; char server_session_deferred[32]; } net_driver_state_t; net_driver_state_t *networking_state_get_ptr(void); bool netplay_compatible_version(const char *version); bool netplay_decode_hostname(const char *hostname, char *address, unsigned *port, char *session, size_t len); int netplay_rooms_parse(const char *buf, size_t len); int netplay_rooms_get_count(void); struct netplay_room *netplay_room_get(int index); void netplay_rooms_free(void); /** * init_netplay * @server : server address to connect to (client only) * @port : TCP port to host on/connect to * @mitm_session : Session id for MITM/tunnel (client only). * * Initializes netplay. * * If netplay is already initialized, will return false (0). * * Returns: true (1) if successful, otherwise false (0). **/ bool init_netplay(const char *server, unsigned port, const char *mitm_session); bool init_netplay_deferred(const char *server, unsigned port, const char *mitm_session); void deinit_netplay(void); bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data); #ifdef HAVE_NETPLAYDISCOVERY /** Initialize Netplay discovery */ bool init_netplay_discovery(void); /** Deinitialize and free Netplay discovery */ void deinit_netplay_discovery(void); /** Discovery control */ bool netplay_discovery_driver_ctl(enum rarch_netplay_discovery_ctl_state state, void *data); #endif extern const mitm_server_t netplay_mitm_server_list[NETPLAY_MITM_SERVERS]; #endif