fix BB data server proxy behavior

This commit is contained in:
Martin Michelsen
2023-03-09 21:07:57 -08:00
parent 60dd22a7f6
commit eebffc0d13
4 changed files with 38 additions and 11 deletions
+10 -3
View File
@@ -150,8 +150,15 @@ static void server_command_lobby_info(shared_ptr<ServerState>, shared_ptr<Lobby>
static void proxy_command_lobby_info(shared_ptr<ServerState>,
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<ServerState>,
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();
}
}
+2 -2
View File
@@ -116,7 +116,7 @@ static HandlerResult S_invalid(shared_ptr<ServerState>,
static HandlerResult C_05(shared_ptr<ServerState>,
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<ServerState>,
// 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;
}
+19 -5
View File
@@ -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);
}
+7 -1
View File
@@ -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;