From ca2c17360df1f1e9da78e12bd395ebe7803854cf Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Wed, 27 Jul 2022 00:57:15 -0700 Subject: [PATCH] fix fault when sending data on closed channel --- src/Channel.cc | 1 + src/IPStackSimulator.cc | 11 +++++++++-- src/IPStackSimulator.hh | 1 + 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Channel.cc b/src/Channel.cc index b26701f9..15b3f9a6 100644 --- a/src/Channel.cc +++ b/src/Channel.cc @@ -247,6 +247,7 @@ void Channel::send(uint16_t cmd, uint32_t flag, const void* data, size_t size, bool print_contents) { if (!this->connected()) { channel_exceptions_log.warning("Attempted to send command on closed channel; dropping data"); + return; } string send_data; diff --git a/src/IPStackSimulator.cc b/src/IPStackSimulator.cc index ed233ed3..5cead96d 100644 --- a/src/IPStackSimulator.cc +++ b/src/IPStackSimulator.cc @@ -553,8 +553,11 @@ void IPStackSimulator::on_client_tcp_frame( conn.next_client_seq = fi.tcp->seq_num + 1; conn.acked_server_seq = random_object(); conn.resend_push_usecs = DEFAULT_RESEND_PUSH_USECS; + conn.next_push_max_frame_size = max_frame_size; conn.awaiting_first_ack = true; conn.max_frame_size = max_frame_size; + conn.bytes_received = 0; + conn.bytes_sent = 0; conn_str = this->str_for_tcp_connection(c, conn); if (this->state->ip_stack_debug) { @@ -622,6 +625,7 @@ void IPStackSimulator::on_client_tcp_frame( evbuffer_drain(conn->pending_data.get(), ack_delta); conn->acked_server_seq += ack_delta; conn->resend_push_usecs = DEFAULT_RESEND_PUSH_USECS; + conn->next_push_max_frame_size = conn->max_frame_size; if (this->state->ip_stack_debug) { ip_stack_simulator_log.info("Removed %08" PRIX32 " bytes from pending buffer and advanced acked_server_seq to %08" PRIX32, @@ -794,7 +798,7 @@ void IPStackSimulator::send_pending_push_frame( return; } - size_t bytes_to_send = min(pending_bytes, conn.max_frame_size); + size_t bytes_to_send = min(pending_bytes, conn.next_push_max_frame_size); if (this->state->ip_stack_debug) { ip_stack_simulator_log.info("Sending PSH frame with seq_num %08" PRIX32 ", 0x%zX/0x%zX data bytes", @@ -809,11 +813,14 @@ void IPStackSimulator::send_pending_push_frame( // If the client isn't responding to our PSHes, back off exponentially up to // a limit of 5 seconds between PSH frames. This window is reset when // acked_server_seq changes (that is, when the client has acknowledged any new - // data) + // data). It seems some situations cause GameCube clients to drop packets more + // often; to alleviate this, we also try to resend less data. conn.resend_push_usecs *= 2; if (conn.resend_push_usecs > 5000000) { conn.resend_push_usecs = 5000000; } + conn.next_push_max_frame_size = max( + 0x100, conn.next_push_max_frame_size - 0x100); } void IPStackSimulator::send_tcp_frame( diff --git a/src/IPStackSimulator.hh b/src/IPStackSimulator.hh index 0c718c73..5dcc03fd 100644 --- a/src/IPStackSimulator.hh +++ b/src/IPStackSimulator.hh @@ -65,6 +65,7 @@ private: uint32_t next_client_seq; uint32_t acked_server_seq; size_t resend_push_usecs; + size_t next_push_max_frame_size; size_t max_frame_size; size_t bytes_received; size_t bytes_sent;