From eebffc0d13e3ab174265a4145b6ea2039aac6c50 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Thu, 9 Mar 2023 21:07:57 -0800 Subject: [PATCH] fix BB data server proxy behavior --- src/ChatCommands.cc | 13 ++++++++++--- src/ProxyCommands.cc | 4 ++-- src/ProxyServer.cc | 24 +++++++++++++++++++----- src/ProxyServer.hh | 8 +++++++- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/ChatCommands.cc b/src/ChatCommands.cc index 12746a78..6c4a5306 100644 --- a/src/ChatCommands.cc +++ b/src/ChatCommands.cc @@ -150,8 +150,15 @@ static void server_command_lobby_info(shared_ptr, shared_ptr static void proxy_command_lobby_info(shared_ptr, ProxyServer::LinkedSession& session, const std::u16string&) { - string msg = string_printf("$C7GC: $C6%" PRId64 "$C7\nSlots: ", - session.remote_guild_card_number); + string msg; + // On non-masked-GC sessions (BB), there is no remote Guild Card number, so we + // don't show it. (The user can see it in the pause menu, unlike in masked-GC + // sessions like GC.) + if (session.remote_guild_card_number >= 0) { + msg = string_printf("$C7GC: $C6%" PRId64 "$C7\n", + session.remote_guild_card_number); + } + msg += "Slots: "; for (size_t z = 0; z < session.lobby_players.size(); z++) { bool is_self = z == session.lobby_client_id; @@ -324,7 +331,7 @@ static void proxy_command_exit(shared_ptr, send_text_message(session.client_channel, u"$C6You must return to\nthe lobby first"); } } else { - session.close_on_disconnect = true; + session.disconnect_action = ProxyServer::LinkedSession::DisconnectAction::CLOSE_IMMEDIATELY; session.send_to_game_server(); } } diff --git a/src/ProxyCommands.cc b/src/ProxyCommands.cc index d86bef2a..3cc909f7 100644 --- a/src/ProxyCommands.cc +++ b/src/ProxyCommands.cc @@ -116,7 +116,7 @@ static HandlerResult S_invalid(shared_ptr, static HandlerResult C_05(shared_ptr, ProxyServer::LinkedSession& session, uint16_t, uint32_t, string&) { - session.close_on_disconnect = true; + session.disconnect_action = ProxyServer::LinkedSession::DisconnectAction::SHORT_TIMEOUT; return HandlerResult::Type::FORWARD; } @@ -1662,7 +1662,7 @@ static HandlerResult C_V123_A0_A1(shared_ptr, // For licensed sessions, send them back to newserv's main menu instead of // going to the remote server's ship/block select menu session.send_to_game_server(); - session.close_on_disconnect = true; + session.disconnect_action = ProxyServer::LinkedSession::DisconnectAction::CLOSE_IMMEDIATELY; return HandlerResult::Type::SUPPRESS; } diff --git a/src/ProxyServer.cc b/src/ProxyServer.cc index e277dda7..97fa851d 100644 --- a/src/ProxyServer.cc +++ b/src/ProxyServer.cc @@ -475,7 +475,7 @@ ProxyServer::LinkedSession::LinkedSession( TerminalFormat::FG_YELLOW, TerminalFormat::FG_RED), local_port(local_port), - close_on_disconnect(false), + disconnect_action(DisconnectAction::LONG_TIMEOUT), remote_ip_crc(0), enable_remote_ip_crc_patch(false), version(version), @@ -672,7 +672,7 @@ void ProxyServer::LinkedSession::on_error(Channel& ch, short events) { session->send_to_game_server("The server has\ndisconnected."); } session->disconnect(); - if (session->close_on_disconnect) { + if (session->disconnect_action == ProxyServer::LinkedSession::DisconnectAction::CLOSE_IMMEDIATELY) { session->server->delete_session(session->id); } } @@ -685,6 +685,19 @@ void ProxyServer::LinkedSession::clear_lobby_players(size_t num_slots) { } void ProxyServer::LinkedSession::send_to_game_server(const char* error_message) { + // If there is no license, do nothing - we can't return to the game server + // from unlicensed sessions + if (!this->license) { + this->disconnect(); + return; + } + // On BB, do nothing - we can't return to the game server since the remote + // server likely sent different game data than what newserv would have sent + if (this->version == GameVersion::BB) { + this->disconnect(); + return; + } + // Delete all the other players for (size_t x = 0; x < this->lobby_players.size(); x++) { if (this->lobby_players[x].guild_card_number == 0) { @@ -741,18 +754,19 @@ void ProxyServer::LinkedSession::send_to_game_server(const char* error_message) } this->client_channel.send(0x19, 0x00, &reconnect_cmd, sizeof(reconnect_cmd)); - this->close_on_disconnect = true; + this->disconnect_action = DisconnectAction::CLOSE_IMMEDIATELY; } } void ProxyServer::LinkedSession::disconnect() { - // Forward the disconnection to the other end + // Disconnect both ends this->client_channel.disconnect(); this->server_channel.disconnect(); // Set a timeout to delete the session entirely (in case the client doesn't // reconnect) - struct timeval tv = usecs_to_timeval(this->license.get() + bool use_long_timeout = (this->license.get() && (this->disconnect_action == DisconnectAction::LONG_TIMEOUT)); + struct timeval tv = usecs_to_timeval(use_long_timeout ? LICENSED_SESSION_TIMEOUT_USECS : UNLICENSED_SESSION_TIMEOUT_USECS); event_add(this->timeout_event.get(), &tv); } diff --git a/src/ProxyServer.hh b/src/ProxyServer.hh index 1375914e..0a5df9f5 100644 --- a/src/ProxyServer.hh +++ b/src/ProxyServer.hh @@ -46,7 +46,13 @@ public: Channel server_channel; uint16_t local_port; struct sockaddr_storage next_destination; - bool close_on_disconnect; + + enum class DisconnectAction { + LONG_TIMEOUT = 0, + SHORT_TIMEOUT, + CLOSE_IMMEDIATELY, + }; + DisconnectAction disconnect_action; uint8_t prev_server_command_bytes[6]; uint32_t remote_ip_crc;