Skip to content

Commit

Permalink
Updates to the netplay netpacket interface (#15887)
Browse files Browse the repository at this point in the history
* Updates to the netplay netpacket interface
- Switch environment call number from 76 to 78 (retire 76 as it was never used by any core)
- Simplify broadcasts by removing the option to send to all but one client
- Separate explicit flushing and querying of incoming packet into two operations (RETRO_NETPACKET_FLUSH_HINT and retro_netpacket_poll_receive_t)
- Enable a core to specify a protocol version string which can get used instead of core version to determine compatibility between two players
- Log and notify a separate message when there is a content crc mismsatch to convey it being less severe (as different games may be able to do network communication with each other)

* C89 compile fix
  • Loading branch information
schellingb authored Nov 10, 2023
1 parent c976fbb commit 107283e
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 86 deletions.
4 changes: 4 additions & 0 deletions intl/msg_hash_us.h
Original file line number Diff line number Diff line change
Expand Up @@ -13760,6 +13760,10 @@ MSG_HASH(
MSG_CONTENT_CRC32S_DIFFER,
"Content CRC32s differ. Cannot use different games."
)
MSG_HASH(
MSG_CONTENT_NETPACKET_CRC32S_DIFFER,
"Host is running a different game."
)
MSG_HASH(
MSG_PING_TOO_HIGH,
"Your ping is too high for this host."
Expand Down
93 changes: 57 additions & 36 deletions libretro-common/include/libretro.h
Original file line number Diff line number Diff line change
Expand Up @@ -1810,7 +1810,26 @@ enum retro_mod
* even before the microphone driver is ready.
*/

#define RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE 76
/* Environment 76 was an obsolete version of RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE.
* It was not used by any known core at the time, and was removed from the API. */

#define RETRO_ENVIRONMENT_GET_DEVICE_POWER (77 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* struct retro_device_power * --
* Returns the device's current power state as reported by the frontend.
* This is useful for emulating the battery level in handheld consoles,
* or for reducing power consumption when on battery power.
*
* The return value indicates whether the frontend can provide this information,
* even if the parameter is NULL.
*
* If the frontend does not support this functionality,
* then the provided argument will remain unchanged.
*
* Note that this environment call describes the power state for the entire device,
* not for individual peripherals like controllers.
*/

#define RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE 78
/* const struct retro_netpacket_callback * --
* When set, a core gains control over network packets sent and
* received during a multiplayer session. This can be used to
Expand All @@ -1834,22 +1853,6 @@ enum retro_mod
* input devices does not need to take any action on its own.
*/

#define RETRO_ENVIRONMENT_GET_DEVICE_POWER (77 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* struct retro_device_power * --
* Returns the device's current power state as reported by the frontend.
* This is useful for emulating the battery level in handheld consoles,
* or for reducing power consumption when on battery power.
*
* The return value indicates whether the frontend can provide this information,
* even if the parameter is NULL.
*
* If the frontend does not support this functionality,
* then the provided argument will remain unchanged.
*
* Note that this environment call describes the power state for the entire device,
* not for individual peripherals like controllers.
*/

/* VFS functionality */

/* File paths:
Expand Down Expand Up @@ -3078,32 +3081,44 @@ struct retro_disk_control_ext_callback

/* Netpacket flags for retro_netpacket_send_t */
#define RETRO_NETPACKET_UNRELIABLE 0 /* Packet to be sent unreliable, depending on network quality it might not arrive. */
#define RETRO_NETPACKET_RELIABLE (1 << 0) /* Reliable packets are guaranteed to arrive at the target in the order they were send. */
#define RETRO_NETPACKET_RELIABLE (1 << 0) /* Reliable packets are guaranteed to arrive at the target in the order they were sent. */
#define RETRO_NETPACKET_UNSEQUENCED (1 << 1) /* Packet will not be sequenced with other packets and may arrive out of order. Cannot be set on reliable packets. */
#define RETRO_NETPACKET_FLUSH_HINT (1 << 2) /* Request the packet and any previously buffered ones to be sent immediately */

/* Used by the core to send a packet to one or more connected players.
/* Broadcast client_id for retro_netpacket_send_t */
#define RETRO_NETPACKET_BROADCAST 0xFFFF

/* Used by the core to send a packet to one or all connected players.
* A single packet sent via this interface can contain up to 64 KB of data.
*
* The broadcast flag can be set to true to send to multiple connected clients.
* In a broadcast, the client_id argument indicates 1 client NOT to send the
* packet to (pass 0xFFFF to send to everyone). Otherwise, the client_id
* argument indicates a single client to send the packet to.
* The client_id RETRO_NETPACKET_BROADCAST sends the packet as a broadcast to
* all connected players. This is supported from the host as well as clients.
* Otherwise, the argument indicates the player to send the packet to.
*
* A frontend must support sending reliable packets (RETRO_NETPACKET_RELIABLE).
* Unreliable packets might not be supported by the frontend, but the flags can
* still be specified. Reliable transmission will be used instead.
*
* If this function is called passing NULL for buf, it will instead flush all
* previously buffered outgoing packets and instantly read any incoming packets.
* During such a call, retro_netpacket_receive_t and retro_netpacket_stop_t can
* be called. The core can perform this in a loop to do a blocking read, i.e.,
* wait for incoming data, but needs to handle stop getting called and also
* give up after a short while to avoid freezing on a connection problem.
* Calling this with the flag RETRO_NETPACKET_FLUSH_HINT will send off the
* packet and any previously buffered ones immediately and without blocking.
* To only flush previously queued packets, buf or len can be passed as NULL/0.
*
* This function is not guaranteed to be thread-safe and must be called during
* retro_run or any of the netpacket callbacks passed with this interface.
*/
typedef void (RETRO_CALLCONV *retro_netpacket_send_t)(int flags, const void* buf, size_t len, uint16_t client_id, bool broadcast);
typedef void (RETRO_CALLCONV *retro_netpacket_send_t)(int flags, const void* buf, size_t len, uint16_t client_id);

/* Optionally read any incoming packets without waiting for the end of the
* frame. While polling, retro_netpacket_receive_t and retro_netpacket_stop_t
* can be called. The core can perform this in a loop to do a blocking read,
* i.e., wait for incoming data, but needs to handle stop getting called and
* also give up after a short while to avoid freezing on a connection problem.
* It is a good idea to manually flush outgoing packets before calling this.
*
* This function is not guaranteed to be thread-safe and must be called during
* retro_run or any of the netpacket callbacks passed with this interface.
*/
typedef void (RETRO_CALLCONV *retro_netpacket_poll_receive_t)();

/* Called by the frontend to signify that a multiplayer session has started.
* If client_id is 0 the local player is the host of the session and at this
Expand All @@ -3112,11 +3127,12 @@ typedef void (RETRO_CALLCONV *retro_netpacket_send_t)(int flags, const void* buf
* If client_id is > 0 the local player is a client connected to a host and
* at this point is already fully connected to the host.
*
* The core must store the retro_netpacket_send_t function pointer provided
* here and use it whenever it wants to send a packet. This function pointer
* remains valid until the frontend calls retro_netpacket_stop_t.
* The core must store the function pointer send_fn and use it whenever it
* wants to send a packet. Optionally poll_receive_fn can be stored and used
* when regular receiving between frames is not enough. These function pointers
* remain valid until the frontend calls retro_netpacket_stop_t.
*/
typedef void (RETRO_CALLCONV *retro_netpacket_start_t)(uint16_t client_id, retro_netpacket_send_t send_fn);
typedef void (RETRO_CALLCONV *retro_netpacket_start_t)(uint16_t client_id, retro_netpacket_send_t send_fn, retro_netpacket_poll_receive_t poll_receive_fn);

/* Called by the frontend when a new packet arrives which has been sent from
* another player with retro_netpacket_send_t. The client_id argument indicates
Expand All @@ -3125,8 +3141,8 @@ typedef void (RETRO_CALLCONV *retro_netpacket_start_t)(uint16_t client_id, retro
typedef void (RETRO_CALLCONV *retro_netpacket_receive_t)(const void* buf, size_t len, uint16_t client_id);

/* Called by the frontend when the multiplayer session has ended.
* Once this gets called the retro_netpacket_send_t function pointer passed
* to retro_netpacket_start_t will not be valid anymore.
* Once this gets called the function pointers passed to
* retro_netpacket_start_t will not be valid anymore.
*/
typedef void (RETRO_CALLCONV *retro_netpacket_stop_t)(void);

Expand All @@ -3153,6 +3169,10 @@ typedef void (RETRO_CALLCONV *retro_netpacket_disconnected_t)(uint16_t client_id
* network packets during a multiplayer session between two or more instances
* of a libretro frontend.
*
* Normally during connection handshake the frontend will compare library_version
* used by both parties and show a warning if there is a difference. When the core
* supplies protocol_version, the frontend will check against this instead.
*
* @see RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE
*/
struct retro_netpacket_callback
Expand All @@ -3163,6 +3183,7 @@ struct retro_netpacket_callback
retro_netpacket_poll_t poll; /* Optional - may be NULL */
retro_netpacket_connected_t connected; /* Optional - may be NULL */
retro_netpacket_disconnected_t disconnected; /* Optional - may be NULL */
const char* protocol_version; /* Optional - if not NULL will be used instead of core version to decide if communication is compatible */
};

enum retro_pixel_format
Expand Down
1 change: 1 addition & 0 deletions msg_hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ enum msg_hash_enums
MSG_COULD_NOT_FIND_ANY_NEXT_DRIVER,
MSG_MOVIE_FORMAT_DIFFERENT_SERIALIZER_VERSION,
MSG_CONTENT_CRC32S_DIFFER,
MSG_CONTENT_NETPACKET_CRC32S_DIFFER,
MSG_PING_TOO_HIGH,
MSG_RECORDING_TERMINATED_DUE_TO_RESIZE,
MSG_FAILED_TO_START_RECORDING,
Expand Down
Loading

0 comments on commit 107283e

Please sign in to comment.