diff --git a/network/netplay/README b/network/netplay/README index a1b5d52e44..096aaf3ded 100644 --- a/network/netplay/README +++ b/network/netplay/README @@ -214,6 +214,14 @@ Description: players the frame number must be later than the last frame of the relevant player's input that has been transmitted. +Command: MODE_REFUSED +Payload: + { + reason: uint32 + } +Description: + Inform a client that its request to change modes has been refused. + Command: CRC Payload: { diff --git a/network/netplay/netplay_io.c b/network/netplay/netplay_io.c index f114d09d73..9db7631e3f 100644 --- a/network/netplay/netplay_io.c +++ b/network/netplay/netplay_io.c @@ -588,7 +588,12 @@ static bool netplay_get_cmd(netplay_t *netplay, return netplay_cmd_nak(netplay, connection); if (!connection->can_play) + { + /* Not allowed to play */ + payload[0] = htonl(NETPLAY_CMD_MODE_REFUSED_REASON_UNPRIVILEGED); + netplay_send_raw_cmd(netplay, connection, NETPLAY_CMD_MODE_REFUSED, payload, sizeof(uint32_t)); break; + } /* Find an available player slot */ for (player = 0; player <= netplay->player_max; player++) @@ -600,7 +605,9 @@ static bool netplay_get_cmd(netplay_t *netplay, } if (player > netplay->player_max) { - /* Sorry, you can't play! */ + /* No slots free! */ + payload[0] = htonl(NETPLAY_CMD_MODE_REFUSED_REASON_NO_SLOTS); + netplay_send_raw_cmd(netplay, connection, NETPLAY_CMD_MODE_REFUSED, payload, sizeof(uint32_t)); break; } @@ -780,6 +787,37 @@ static bool netplay_get_cmd(netplay_t *netplay, #undef NEXT } + case NETPLAY_CMD_MODE_REFUSED: + { + uint32_t reason; + char msg[512]; + + if (cmd_size != sizeof(uint32_t)) + return netplay_cmd_nak(netplay, connection); + + RECV(&reason, sizeof(reason)) + return netplay_cmd_nak(netplay, connection); + reason = ntohl(reason); + + switch (reason) + { + case NETPLAY_CMD_MODE_REFUSED_REASON_UNPRIVILEGED: + strlcpy(msg, "You do not have permission to play.", sizeof(msg)); + break; + + case NETPLAY_CMD_MODE_REFUSED_REASON_NO_SLOTS: + strlcpy(msg, "There are no free player slots.", sizeof(msg)); + break; + + default: + strlcpy(msg, "Cannot switch to play mode.", sizeof(msg)); + } + + RARCH_LOG("%s\n", msg); + runloop_msg_queue_push(msg, 1, 180, false); + break; + } + case NETPLAY_CMD_DISCONNECT: netplay_hangup(netplay, connection); return true; diff --git a/network/netplay/netplay_private.h b/network/netplay/netplay_private.h index 0e1c1c666a..25f16ab8cc 100644 --- a/network/netplay/netplay_private.h +++ b/network/netplay/netplay_private.h @@ -121,6 +121,9 @@ enum netplay_cmd /* Report player mode */ NETPLAY_CMD_MODE = 0x0025, + /* Report player mode refused */ + NETPLAY_CMD_MODE_REFUSED = 0x0026, + /* Loading and synchronization */ /* Send the CRC hash of a frame's state */ @@ -160,6 +163,19 @@ enum netplay_cmd #define NETPLAY_CMD_MODE_BIT_PLAYING (1U<<17) #define NETPLAY_CMD_MODE_BIT_YOU (1U<<16) +/* These are the reasons given for mode changes to be rejected */ +enum netplay_cmd_mode_reasons +{ + /* Other/unknown reason */ + NETPLAY_CMD_MODE_REFUSED_REASON_OTHER, + + /* You don't have permission to play */ + NETPLAY_CMD_MODE_REFUSED_REASON_UNPRIVILEGED, + + /* There are no free player slots */ + NETPLAY_CMD_MODE_REFUSED_REASON_NO_SLOTS +}; + /* These are the configurations sent by NETPLAY_CMD_CFG. */ enum netplay_cmd_cfg {