From 521a97c8d5e2a060f89b5d767efc400a2f106bd4 Mon Sep 17 00:00:00 2001 From: Alexander Yee Date: Fri, 1 May 2026 01:46:49 -0700 Subject: [PATCH 1/4] Seed CRC with a session ID to prevent session cross-talk. --- Common/CRC32/pabb_CRC32_AVR8.h | 4 +- Common/CRC32/pabb_CRC32_Basic.h | 3 +- Common/CRC32/pabb_CRC32_x86_SSE4.1.h | 3 +- .../PABotBase2/PABotBase2_MessageProtocol.h | 2 +- .../PABotBase2CC_ReliableStreamConnection.cpp | 18 +++-- .../PABotBase2FW_ReliableStreamConnection.cpp | 27 +++++-- .../PABotBase2_PacketParser.cpp | 10 ++- .../PABotBase2_PacketParser.h | 2 + .../PABotBase2_PacketProtocol.h | 42 ++++------- .../PABotBase2_PacketSender.cpp | 71 ++++++++++++++----- .../PABotBase2_PacketSender.h | 14 +++- .../Connection/PABotBaseConnection.cpp | 2 +- 12 files changed, 127 insertions(+), 71 deletions(-) diff --git a/Common/CRC32/pabb_CRC32_AVR8.h b/Common/CRC32/pabb_CRC32_AVR8.h index b83228dfd9..4ce96261c3 100644 --- a/Common/CRC32/pabb_CRC32_AVR8.h +++ b/Common/CRC32/pabb_CRC32_AVR8.h @@ -20,11 +20,11 @@ extern const PROGMEM uint32_t PABB_CRC32_TABLE8[]; void pabb_crc32_buffer(uint32_t* crc, const void* data, uint8_t length); -static inline void pabb_crc32_write_to_message(void* data, size_t full_message_length){ +static inline void pabb_crc32_write_to_message(uint32_t seed, void* data, size_t full_message_length){ char* ptr = (char*)data; size_t length_before_crc = full_message_length - sizeof(uint32_t); uint32_t* crc = (uint32_t*)(ptr + length_before_crc); - *crc = 0xffffffff; + *crc = seed; pabb_crc32_buffer(crc, ptr, length_before_crc); } diff --git a/Common/CRC32/pabb_CRC32_Basic.h b/Common/CRC32/pabb_CRC32_Basic.h index 6eed5958af..0f91603733 100644 --- a/Common/CRC32/pabb_CRC32_Basic.h +++ b/Common/CRC32/pabb_CRC32_Basic.h @@ -20,10 +20,9 @@ extern const uint32_t PABB_CRC32_TABLE8[]; void pabb_crc32_buffer(uint32_t* crc, const void* data, uint8_t length); -static inline void pabb_crc32_write_to_message(void* data, size_t full_message_length){ +static inline void pabb_crc32_write_to_message(uint32_t crc, void* data, size_t full_message_length){ char* ptr = (char*)data; size_t length_before_crc = full_message_length - sizeof(uint32_t); - uint32_t crc = 0xffffffff; pabb_crc32_buffer(&crc, ptr, length_before_crc); memcpy(ptr + length_before_crc, &crc, sizeof(uint32_t)); } diff --git a/Common/CRC32/pabb_CRC32_x86_SSE4.1.h b/Common/CRC32/pabb_CRC32_x86_SSE4.1.h index 4faaf501da..e5c4283fa5 100644 --- a/Common/CRC32/pabb_CRC32_x86_SSE4.1.h +++ b/Common/CRC32/pabb_CRC32_x86_SSE4.1.h @@ -26,10 +26,9 @@ static inline void pabb_crc32_buffer(uint32_t* crc, const void* data, size_t len *crc = tmp; } -static inline void pabb_crc32_write_to_message(void* data, size_t full_message_length){ +static inline void pabb_crc32_write_to_message(uint32_t crc, void* data, size_t full_message_length){ char* ptr = (char*)data; size_t length_before_crc = full_message_length - sizeof(uint32_t); - uint32_t crc = 0xffffffff; pabb_crc32_buffer(&crc, ptr, length_before_crc); memcpy(ptr + length_before_crc, &crc, sizeof(uint32_t)); } diff --git a/Common/PABotBase2/PABotBase2_MessageProtocol.h b/Common/PABotBase2/PABotBase2_MessageProtocol.h index 9b4cd48902..a9d9221379 100644 --- a/Common/PABotBase2/PABotBase2_MessageProtocol.h +++ b/Common/PABotBase2/PABotBase2_MessageProtocol.h @@ -23,7 +23,7 @@ namespace PABotBase2{ -#define PABB2_MESSAGE_PROTOCOL_VERSION 2026041105 +#define PABB2_MESSAGE_PROTOCOL_VERSION 2026041106 struct PABB_PACK MessageHeader{ diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.cpp b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.cpp index 172def0556..8c354c3593 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.cpp +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.cpp @@ -8,6 +8,7 @@ #include "Common/Cpp/PrettyPrint.h" //#include "Common/Cpp/Exceptions.h" #include "Common/PABotBase2/PABotBase2CC_MessageDumper.h" +#include "CommonTools/Random.h" //#include "PABotBase2_ConnectionDebug.h" #include "PABotBase2CC_ReliableStreamConnection.h" @@ -32,7 +33,7 @@ ReliableStreamConnection::ReliableStreamConnection( , m_unreliable_connection(unreliable_connection) , m_retransmit_timeout(retransmit_timeout) , m_print_lock(print_lock) - , m_reliable_sender(*this, 20) + , m_reliable_sender(*this, 24, random_u32()) , m_log_everything(log_everything) // , m_version_verified(false) , m_remote_protocol_compatible(false) @@ -123,7 +124,11 @@ void ReliableStreamConnection::on_recv(const void* data, size_t bytes){ cout << "ReliableStreamConnection::on_recv(): " << bytes << endl; } #endif - m_parser.push_bytes(*this, (const uint8_t*)data, bytes); + m_parser.push_bytes( + *this, + m_reliable_sender.session_id(), + (const uint8_t*)data, bytes + ); } @@ -168,11 +173,11 @@ size_t ReliableStreamConnection::unreliable_send(const void* data, size_t bytes) bool ReliableStreamConnection::reset(WallDuration timeout){ { std::lock_guard lg(m_lock); - m_reliable_sender.reset(); + m_reliable_sender.reset(m_reliable_sender.session_id() + 1); m_parser.reset(); m_stream_coalescer.reset(); throw_if_cancelled(); - m_reliable_sender.send_packet(PABB2_CONNECTION_OPCODE_ASK_RESET, 0, nullptr); + m_reliable_sender.send_reset(); } m_cv.notify_all(); return wait_for_pending(timeout); @@ -217,7 +222,7 @@ void ReliableStreamConnection::send_ack(uint8_t seqnum, uint8_t opcode){ packet.header.seqnum = seqnum; packet.header.packet_bytes = sizeof(packet); packet.header.opcode = opcode; - pabb_crc32_write_to_message(&packet, sizeof(packet)); + pabb_crc32_write_to_message(m_reliable_sender.session_id(), &packet, sizeof(packet)); unreliable_send(&packet, sizeof(packet)); } void ReliableStreamConnection::send_ack_u16(uint8_t seqnum, uint8_t opcode, uint16_t data){ @@ -231,7 +236,7 @@ void ReliableStreamConnection::send_ack_u16(uint8_t seqnum, uint8_t opcode, uint packet.header.packet_bytes = sizeof(packet); packet.header.opcode = opcode; packet.header.data = data; - pabb_crc32_write_to_message(&packet, sizeof(packet)); + pabb_crc32_write_to_message(m_reliable_sender.session_id(), &packet, sizeof(packet)); unreliable_send(&packet, sizeof(packet)); } @@ -376,6 +381,7 @@ void ReliableStreamConnection::on_packet(const PacketHeader* packet){ case PABB2_CONNECTION_OPCODE_INFO_LABEL_H32: case PABB2_CONNECTION_OPCODE_INFO_LABEL_U32: case PABB2_CONNECTION_OPCODE_INFO_LABEL_I32: +// case PABB2_CONNECTION_OPCODE_WRONG_SESSION: // cout << "Received ack" << endl; if (!m_log_everything){ m_logger.log("[RSC]: Receive: (0x" + tostr_hex(packet->opcode) + ") " + tostr(packet), COLOR_PURPLE); diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2FW_ReliableStreamConnection.cpp b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2FW_ReliableStreamConnection.cpp index a84d214e3c..171b1a6650 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2FW_ReliableStreamConnection.cpp +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2FW_ReliableStreamConnection.cpp @@ -113,7 +113,11 @@ bool ReliableStreamConnectionFW::run_recv_events(const WallDuration& timeout){ ? POLL_RATE : timeout; - const PacketHeader* header = m_parser.pull_bytes(m_unreliable_connection, adjusted_timeout); + const PacketHeader* header = m_parser.pull_bytes( + m_unreliable_connection, + m_reliable_sender.session_id(), + adjusted_timeout + ); if (header == nullptr){ return false; } @@ -149,22 +153,33 @@ bool ReliableStreamConnectionFW::run_recv_events(const WallDuration& timeout){ // Now handle the different opcodes. uint8_t opcode = header->opcode & PABB2_CONNECTION_OPCODE_MASK; + switch (opcode){ - case PABB2_CONNECTION_OPCODE_ASK_RESET: + case PABB2_CONNECTION_OPCODE_ASK_RESET:{ + if (header->packet_bytes < sizeof(PacketHeader_u32)){ + return true; + } + + const PacketHeader_u32* packet = (const PacketHeader_u32*)header; + +#ifdef PABB2_SUPPORTS_PRINTF_LOGGING + printf("Resetting to session ID: %zx\n", (size_t)packet->data); +#endif m_stream_ready = false; m_send_is_currently_full = false; - m_reliable_sender.reset(); + m_reliable_sender.reset(packet->data); m_parser.reset(); m_stream_coalescer.reset(); m_stream_coalescer.push_packet(0); +#ifdef PABB2_ENABLE + issue_reset_to_all(); +#endif m_reliable_sender.send_oob_packet_empty( header->seqnum, PABB2_CONNECTION_OPCODE_RET_RESET ); -#ifdef PABB2_ENABLE - issue_reset_to_all(); -#endif return true; + } case PABB2_CONNECTION_OPCODE_ASK_VERSION: m_stream_coalescer.push_packet(header->seqnum); m_reliable_sender.send_oob_packet_u32( diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketParser.cpp b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketParser.cpp index c5baaf7495..7b72bb38bc 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketParser.cpp +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketParser.cpp @@ -25,6 +25,7 @@ namespace PABotBase2{ const PacketHeader* PacketParser::pull_bytes( UnreliableStreamConnectionPolling& connection, + const uint32_t& session_id, WallDuration timeout ){ const uint8_t MIN_PACKET_SIZE = sizeof(PacketHeader) + sizeof(uint32_t); @@ -114,7 +115,9 @@ const PacketHeader* PacketParser::pull_bytes( // Verify the CRC. - uint32_t actual_crc = 0xffffffff; + uint32_t actual_crc = header->opcode == PABB2_CONNECTION_OPCODE_ASK_RESET + ? 0xffffffff + : session_id; pabb_crc32_buffer(&actual_crc, m_buffer, packet_bytes - sizeof(uint32_t)); uint32_t expected_crc; @@ -137,6 +140,7 @@ const PacketHeader* PacketParser::pull_bytes( void PacketParser::push_bytes( PacketRunner& packet_runner, + const uint32_t& session_id, const uint8_t* data, size_t bytes ){ // cout << std::string((const char*)data, bytes) << endl; @@ -206,7 +210,9 @@ void PacketParser::push_bytes( // Verify the CRC. - uint32_t actual_crc = 0xffffffff; + uint32_t actual_crc = header->opcode == PABB2_CONNECTION_OPCODE_ASK_RESET + ? 0xffffffff + : session_id; pabb_crc32_buffer(&actual_crc, m_buffer, packet_bytes - sizeof(uint32_t)); uint32_t expected_crc; diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketParser.h b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketParser.h index a431b1a8a4..52ccedc4de 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketParser.h +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketParser.h @@ -62,6 +62,7 @@ struct PacketParser{ // const PacketHeader* pull_bytes( UnreliableStreamConnectionPolling& connection, + const uint32_t& session_id, WallDuration timeout ); @@ -72,6 +73,7 @@ struct PacketParser{ // void push_bytes( PacketRunner& packet_runner, + const uint32_t& session_id, const uint8_t* data, size_t bytes ); diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketProtocol.h b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketProtocol.h index 3bf614c091..a69d29a37e 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketProtocol.h +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketProtocol.h @@ -32,17 +32,21 @@ namespace PABotBase2{ // #define PABB2_CONNECTION_MAGIC_NUMBER 0x81 -#define PABB2_CONNECTION_PROTOCOL_VERSION 2026041102 +#define PABB2_CONNECTION_PROTOCOL_VERSION 2026050100 #define PABB2_CONNECTION_RETRANSMIT_FLAG 0x80 #define PABB2_CONNECTION_OPCODE_MASK 0x7f +#define PABB2_CONNECTION_OPCODE_INVALID 0x00 + // -// Special +// Packets // +using SessionId = uint32_t; + struct PABB_PACK PacketHeader{ uint8_t magic_number; uint8_t seqnum; @@ -50,31 +54,13 @@ struct PABB_PACK PacketHeader{ uint8_t opcode; }; -#define PABB2_CONNECTION_OPCODE_INVALID 0x00 - -#define PABB2_CONNECTION_OPCODE_ASK_RESET 0x01 -#define PABB2_CONNECTION_OPCODE_RET_RESET 0x41 - - -struct PABB_PACK PacketHeader_u8{ - uint8_t magic_number; - uint8_t seqnum; - uint8_t packet_bytes; - uint8_t opcode; +struct PABB_PACK PacketHeader_u8 : PacketHeader{ uint8_t data; }; -struct PABB_PACK PacketHeader_u16{ - uint8_t magic_number; - uint8_t seqnum; - uint8_t packet_bytes; - uint8_t opcode; +struct PABB_PACK PacketHeader_u16 : PacketHeader{ uint16_t data; }; -struct PABB_PACK PacketHeader_u32{ - uint8_t magic_number; - uint8_t seqnum; - uint8_t packet_bytes; - uint8_t opcode; +struct PABB_PACK PacketHeader_u32 : PacketHeader{ uint32_t data; }; @@ -84,6 +70,9 @@ struct PABB_PACK PacketHeader_u32{ // Requests (acks required) // +#define PABB2_CONNECTION_OPCODE_ASK_RESET 0x01 +#define PABB2_CONNECTION_OPCODE_RET_RESET 0x41 + #define PABB2_CONNECTION_OPCODE_ASK_VERSION 0x02 #define PABB2_CONNECTION_OPCODE_RET_VERSION 0x42 @@ -99,11 +88,7 @@ struct PABB_PACK PacketHeader_u32{ #define PABB2_CONNECTION_OPCODE_ASK_STREAM_DATA 0x12 #define PABB2_CONNECTION_OPCODE_RET_STREAM_DATA 0x52 #define PABB2_CONNECTION_OPCODE_ASK_STREAM_REQUEST 0x13 // Unused for now. -struct PABB_PACK PacketHeaderData{ - uint8_t magic_number; - uint8_t seqnum; - uint8_t packet_bytes; - uint8_t opcode; +struct PABB_PACK PacketHeaderData : PacketHeader{ uint16_t stream_offset; }; @@ -135,7 +120,6 @@ struct PABB_PACK PacketHeaderData{ #define PABB2_CONNECTION_OPCODE_UNKNOWN_OPCODE 0x32 - } } diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp index 24667d7c08..a324e90179 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp @@ -19,6 +19,7 @@ namespace PokemonAutomation{ namespace PABotBase2{ + PacketSender::PacketSender( UnreliableStreamSender& connection, uint8_t max_packet_size @@ -26,9 +27,20 @@ PacketSender::PacketSender( : m_connection(connection) , m_max_packet_size(max_packet_size) { - reset(); + reset(0); } -void PacketSender::reset(){ +PacketSender::PacketSender( + UnreliableStreamSender& connection, + uint8_t max_packet_size, + SessionId session_id +) + : m_connection(connection) + , m_max_packet_size(max_packet_size) +{ + reset(session_id); +} +void PacketSender::reset(const SessionId& session_id){ + memcpy(&m_session_id, &session_id, sizeof(SessionId)); m_slot_head = 0; m_slot_tail = 0; m_slot_tail_uncommitted = 0; @@ -50,10 +62,10 @@ PA_NO_INLINE void PacketSender::send_oob_packet_empty(uint8_t seqnum, uint8_t op uint8_t crc32[sizeof(uint32_t)]; } packet; packet.header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; + packet.header.opcode = opcode; packet.header.seqnum = seqnum; packet.header.packet_bytes = sizeof(packet); - packet.header.opcode = opcode; - pabb_crc32_write_to_message(&packet, sizeof(packet)); + pabb_crc32_write_to_message(m_session_id, &packet, sizeof(packet)); m_connection.unreliable_send(&packet, sizeof(packet)); } PA_NO_INLINE void PacketSender::send_oob_packet_u8(uint8_t seqnum, uint8_t opcode, uint8_t data){ @@ -62,11 +74,11 @@ PA_NO_INLINE void PacketSender::send_oob_packet_u8(uint8_t seqnum, uint8_t opcod uint8_t crc32[sizeof(uint32_t)]; } packet; packet.header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; + packet.header.opcode = opcode; packet.header.seqnum = seqnum; packet.header.packet_bytes = sizeof(packet); - packet.header.opcode = opcode; packet.header.data = data; - pabb_crc32_write_to_message(&packet, sizeof(packet)); + pabb_crc32_write_to_message(m_session_id, &packet, sizeof(packet)); m_connection.unreliable_send(&packet, sizeof(packet)); } PA_NO_INLINE void PacketSender::send_oob_packet_u16(uint8_t seqnum, uint8_t opcode, const uint16_t& data){ @@ -75,11 +87,11 @@ PA_NO_INLINE void PacketSender::send_oob_packet_u16(uint8_t seqnum, uint8_t opco uint8_t crc32[sizeof(uint32_t)]; } packet; packet.header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; + packet.header.opcode = opcode; packet.header.seqnum = seqnum; packet.header.packet_bytes = sizeof(packet); - packet.header.opcode = opcode; memcpy(&packet.header.data, &data, sizeof(uint16_t)); - pabb_crc32_write_to_message(&packet, sizeof(packet)); + pabb_crc32_write_to_message(m_session_id, &packet, sizeof(packet)); m_connection.unreliable_send(&packet, sizeof(packet)); } PA_NO_INLINE void PacketSender::send_oob_packet_u32(uint8_t seqnum, uint8_t opcode, const uint32_t& data){ @@ -88,11 +100,11 @@ PA_NO_INLINE void PacketSender::send_oob_packet_u32(uint8_t seqnum, uint8_t opco uint8_t crc32[sizeof(uint32_t)]; } packet; packet.header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; + packet.header.opcode = opcode; packet.header.seqnum = seqnum; packet.header.packet_bytes = sizeof(packet); - packet.header.opcode = opcode; memcpy(&packet.header.data, &data, sizeof(uint32_t)); - pabb_crc32_write_to_message(&packet, sizeof(packet)); + pabb_crc32_write_to_message(m_session_id, &packet, sizeof(packet)); m_connection.unreliable_send(&packet, sizeof(packet)); } PA_NO_INLINE void PacketSender::send_oob_packet_data( @@ -101,10 +113,10 @@ PA_NO_INLINE void PacketSender::send_oob_packet_data( ){ PacketHeader header; header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; + header.opcode = opcode; header.seqnum = seqnum; header.packet_bytes = sizeof(PacketHeader) + sizeof(uint32_t) + bytes; - header.opcode = opcode; - uint32_t crc = 0xffffffff; + uint32_t crc = m_session_id; pabb_crc32_buffer(&crc, &header, sizeof(PacketHeader)); pabb_crc32_buffer(&crc, data, bytes); m_connection.unreliable_send(&header, sizeof(header)); @@ -118,11 +130,11 @@ PA_NO_INLINE void PacketSender::send_oob_packet_u32_data( ){ PacketHeader_u32 header; header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; + header.opcode = opcode; header.seqnum = seqnum; header.packet_bytes = sizeof(PacketHeader_u32) + sizeof(uint32_t) + bytes; - header.opcode = opcode; memcpy(&header.data, &u32, sizeof(uint32_t)); - uint32_t crc = 0xffffffff; + uint32_t crc = m_session_id; pabb_crc32_buffer(&crc, &header, sizeof(PacketHeader_u32)); pabb_crc32_buffer(&crc, data, bytes); m_connection.unreliable_send(&header, sizeof(header)); @@ -185,6 +197,27 @@ bool PacketSender::remove(uint8_t seqnum){ } } +void PacketSender::send_reset(){ + PacketHeader_u32* packet = (PacketHeader_u32*)reserve_packet( + PABB2_CONNECTION_OPCODE_ASK_RESET, + sizeof(PacketHeader_u32) - sizeof(PacketHeader) + ); + if (packet == NULL){ + return; + } + + memcpy(&packet->data, &m_session_id, sizeof(uint32_t)); + + // We temporarily change the session ID to 0xffffffff + // so that the CRC is generated correctly. + uint32_t tmp = m_session_id; + m_session_id = 0xffffffff; + + commit_packet(packet); + + m_session_id = tmp; + +} bool PacketSender::send_packet( uint8_t opcode, uint8_t extra_bytes, const void* extra_data ){ @@ -253,15 +286,15 @@ PacketHeader* PacketSender::reserve_packet( PacketHeader* ret = (PacketHeader*)(m_buffer + offset); ret->magic_number = PABB2_CONNECTION_MAGIC_NUMBER; + ret->opcode = opcode; ret->seqnum = m_slot_tail++; ret->packet_bytes = packet_bytes; - ret->opcode = opcode; m_slot_tail_uncommitted = m_slot_tail; return ret; } void PacketSender::commit_packet(PacketHeader* packet){ - pabb_crc32_write_to_message(packet, packet->packet_bytes); + pabb_crc32_write_to_message(m_session_id, packet, packet->packet_bytes); m_connection.unreliable_send(packet, packet->packet_bytes); @@ -311,7 +344,7 @@ bool PacketSender::iterate_retransmits(){ packet->opcode |= PABB2_CONNECTION_RETRANSMIT_FLAG; packet->magic_number = PABB2_CONNECTION_MAGIC_NUMBER; uint8_t packet_bytes = packet->packet_bytes; - pabb_crc32_write_to_message(packet, packet_bytes); + pabb_crc32_write_to_message(m_session_id, packet, packet_bytes); #if 0 printf("Retransmitting: %u\n", packet->seqnum); @@ -408,9 +441,9 @@ bool PacketSender::enqueue_uncommitted_send_stream(const void* data, size_t byte // Build the packet header. PacketHeaderData* packet = (PacketHeaderData*)(m_buffer + offset); packet->magic_number = PABB2_CONNECTION_MAGIC_NUMBER; + packet->opcode = PABB2_CONNECTION_OPCODE_ASK_STREAM_DATA; packet->seqnum = m_slot_tail_uncommitted++; packet->packet_bytes = (uint8_t)packet_bytes; // 256 overflows to 0 - packet->opcode = PABB2_CONNECTION_OPCODE_ASK_STREAM_DATA; memcpy(&packet->stream_offset, &m_stream_offset_uncommitted, sizeof(uint16_t)); // May be misaligned. // Copy stream data. @@ -418,7 +451,7 @@ bool PacketSender::enqueue_uncommitted_send_stream(const void* data, size_t byte m_stream_offset_uncommitted += (uint16_t)current; // Build CRC - pabb_crc32_write_to_message(packet, packet_bytes); + pabb_crc32_write_to_message(m_session_id, packet, packet_bytes); data = (const char*)data + current; bytes -= current; diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.h b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.h index c673e96062..9bc1bd647a 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.h +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.h @@ -46,12 +46,20 @@ class PacketSender{ UnreliableStreamSender& connection, uint8_t max_packet_size ); - void reset(); + PacketSender( + UnreliableStreamSender& connection, + uint8_t max_packet_size, + SessionId session_id + ); + void reset(const SessionId& session_id); void set_max_packet_size(uint8_t max_packet_size){ m_max_packet_size = max_packet_size; } + const SessionId& session_id() const{ + return m_session_id; + } uint8_t slots_used() const{ return m_slot_tail - m_slot_head; } @@ -88,6 +96,8 @@ class PacketSender{ // Returns true is successful, false if seqnum is not in the queue. bool remove(uint8_t seqnum); + void send_reset(); + // // Send a packet with the specified opcode and extra data after the header. // Returns true if successful. (enters the queue) @@ -155,6 +165,8 @@ class PacketSender{ private: UnreliableStreamSender& m_connection; + SessionId m_session_id; + uint8_t m_max_packet_size; // 0 = 256 bytes uint8_t m_slot_head; diff --git a/SerialPrograms/Source/Controllers/SerialPABotBase/Connection/PABotBaseConnection.cpp b/SerialPrograms/Source/Controllers/SerialPABotBase/Connection/PABotBaseConnection.cpp index c6b6932191..d6f8a2c80f 100644 --- a/SerialPrograms/Source/Controllers/SerialPABotBase/Connection/PABotBaseConnection.cpp +++ b/SerialPrograms/Source/Controllers/SerialPABotBase/Connection/PABotBaseConnection.cpp @@ -93,7 +93,7 @@ void PABotBaseConnection::send_message(const BotBaseMessage& message, bool is_re buffer += message.type; buffer += message.body; buffer += std::string(sizeof(uint32_t), 0); - pabb_crc32_write_to_message(&buffer[0], buffer.size()); + pabb_crc32_write_to_message(0xffffffff, &buffer[0], buffer.size()); m_connection->unreliable_send(&buffer[0], buffer.size()); } From f281330cc03ddf48403c3c9fe4ee8707e8156bc4 Mon Sep 17 00:00:00 2001 From: Alexander Yee Date: Fri, 1 May 2026 20:39:14 -0700 Subject: [PATCH 2/4] Make it backwards compatible with no session ID. --- Common/PABotBase2/PABotBase2_MessageProtocol.h | 2 +- .../PABotBase2CC_ReliableStreamConnection.cpp | 14 +++++++++++--- .../PABotBase2CC_ReliableStreamConnection.h | 2 +- .../PABotBase2_PacketProtocol.h | 2 +- .../PABotBase2/PABotBase2_DeviceHandle.cpp | 5 ++++- .../PABotBase2/SerialPABotBase2_Connection.cpp | 10 ++++++++-- .../DevPrograms/TestProgramComputer.cpp | 2 +- 7 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Common/PABotBase2/PABotBase2_MessageProtocol.h b/Common/PABotBase2/PABotBase2_MessageProtocol.h index a9d9221379..9b4cd48902 100644 --- a/Common/PABotBase2/PABotBase2_MessageProtocol.h +++ b/Common/PABotBase2/PABotBase2_MessageProtocol.h @@ -23,7 +23,7 @@ namespace PABotBase2{ -#define PABB2_MESSAGE_PROTOCOL_VERSION 2026041106 +#define PABB2_MESSAGE_PROTOCOL_VERSION 2026041105 struct PABB_PACK MessageHeader{ diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.cpp b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.cpp index 8c354c3593..54a0cd16db 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.cpp +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.cpp @@ -170,14 +170,22 @@ size_t ReliableStreamConnection::unreliable_send(const void* data, size_t bytes) // Send Path // -bool ReliableStreamConnection::reset(WallDuration timeout){ +bool ReliableStreamConnection::reset(bool random_session_id, WallDuration timeout){ { std::lock_guard lg(m_lock); - m_reliable_sender.reset(m_reliable_sender.session_id() + 1); + if (random_session_id){ + m_reliable_sender.reset(m_reliable_sender.session_id() + 1); + }else{ + m_reliable_sender.reset(0xffffffff); + } m_parser.reset(); m_stream_coalescer.reset(); throw_if_cancelled(); - m_reliable_sender.send_reset(); + if (random_session_id){ + m_reliable_sender.send_reset(); + }else{ + m_reliable_sender.send_packet(PABB2_CONNECTION_OPCODE_ASK_RESET, 0, nullptr); + } } m_cv.notify_all(); return wait_for_pending(timeout); diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.h b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.h index e0d93b7a22..62aa94e8bd 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.h +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.h @@ -47,7 +47,7 @@ class ReliableStreamConnection final } virtual bool cancel(std::exception_ptr exception) noexcept override; - bool reset(WallDuration timeout = WallDuration::max()); + bool reset(bool random_session_id, WallDuration timeout = WallDuration::max()); bool remote_protocol_is_compatible() const{ return m_remote_protocol_compatible; diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketProtocol.h b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketProtocol.h index a69d29a37e..995fcb866b 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketProtocol.h +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketProtocol.h @@ -32,7 +32,7 @@ namespace PABotBase2{ // #define PABB2_CONNECTION_MAGIC_NUMBER 0x81 -#define PABB2_CONNECTION_PROTOCOL_VERSION 2026050100 +#define PABB2_CONNECTION_PROTOCOL_VERSION 2026041102 #define PABB2_CONNECTION_RETRANSMIT_FLAG 0x80 diff --git a/SerialPrograms/Source/Controllers/PABotBase2/PABotBase2_DeviceHandle.cpp b/SerialPrograms/Source/Controllers/PABotBase2/PABotBase2_DeviceHandle.cpp index 3348efed1f..5e4d34dcc6 100644 --- a/SerialPrograms/Source/Controllers/PABotBase2/PABotBase2_DeviceHandle.cpp +++ b/SerialPrograms/Source/Controllers/PABotBase2/PABotBase2_DeviceHandle.cpp @@ -223,7 +223,10 @@ void DeviceHandle::connect(){ query_controller_list(); query_command_queue(); - set_logging_flag(GlobalSettings::instance().DEVICE_LOGGING_FLAG); + + if (m_device_firmware_version >= 2026050100){ + set_logging_flag(GlobalSettings::instance().DEVICE_LOGGING_FLAG); + } } void DeviceHandle::try_set_controller_type( ControllerType controller_type, diff --git a/SerialPrograms/Source/Controllers/PABotBase2/SerialPABotBase2_Connection.cpp b/SerialPrograms/Source/Controllers/PABotBase2/SerialPABotBase2_Connection.cpp index 821ef6fa58..a9c50e9423 100644 --- a/SerialPrograms/Source/Controllers/PABotBase2/SerialPABotBase2_Connection.cpp +++ b/SerialPrograms/Source/Controllers/PABotBase2/SerialPABotBase2_Connection.cpp @@ -121,11 +121,17 @@ bool SerialPABotBase2_Connection::connect_to_device(){ std::string str; WallClock start = current_time(); while (current_time() - start < std::chrono::seconds(5)){ + m_logger.log("Trying baud " + tostr_u_commas(921600) + " (no session ID)..."); + m_unreliable_connection->set_baud_rate(921600); + if (m_stream_connection->reset(false, std::chrono::milliseconds(100))){ + return true; + } + for (size_t c = 0; c < sizeof(BAUD_RATES) / sizeof(uint32_t); c++){ uint32_t baud_rate = BAUD_RATES[c]; - m_logger.log("Trying baud " + tostr_u_commas(baud_rate) + "..."); + m_logger.log("Trying baud " + tostr_u_commas(baud_rate) + " (with session ID)..."); m_unreliable_connection->set_baud_rate(baud_rate); - if (m_stream_connection->reset(std::chrono::milliseconds(100))){ + if (m_stream_connection->reset(true, std::chrono::milliseconds(100))){ return true; } } diff --git a/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramComputer.cpp b/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramComputer.cpp index ceeab77fee..7fb331b7f6 100644 --- a/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramComputer.cpp +++ b/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramComputer.cpp @@ -321,7 +321,7 @@ void stress_test(Logger& logger, CancellableScope& scope){ ); // Connect - connection.reset(); + connection.reset(true); connection.send_request(PABB2_CONNECTION_OPCODE_ASK_VERSION); connection.wait_for_pending(); connection.send_request(PABB2_CONNECTION_OPCODE_ASK_PACKET_SIZE); From 1986d80455f05d3caf27a54d156846bfdc1e1c00 Mon Sep 17 00:00:00 2001 From: Alexander Yee Date: Fri, 1 May 2026 20:42:28 -0700 Subject: [PATCH 3/4] Undo order change. --- .../PABotBase2_PacketSender.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp index a324e90179..e209910fa1 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp @@ -62,9 +62,9 @@ PA_NO_INLINE void PacketSender::send_oob_packet_empty(uint8_t seqnum, uint8_t op uint8_t crc32[sizeof(uint32_t)]; } packet; packet.header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; - packet.header.opcode = opcode; packet.header.seqnum = seqnum; packet.header.packet_bytes = sizeof(packet); + packet.header.opcode = opcode; pabb_crc32_write_to_message(m_session_id, &packet, sizeof(packet)); m_connection.unreliable_send(&packet, sizeof(packet)); } @@ -74,9 +74,9 @@ PA_NO_INLINE void PacketSender::send_oob_packet_u8(uint8_t seqnum, uint8_t opcod uint8_t crc32[sizeof(uint32_t)]; } packet; packet.header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; - packet.header.opcode = opcode; packet.header.seqnum = seqnum; packet.header.packet_bytes = sizeof(packet); + packet.header.opcode = opcode; packet.header.data = data; pabb_crc32_write_to_message(m_session_id, &packet, sizeof(packet)); m_connection.unreliable_send(&packet, sizeof(packet)); @@ -87,9 +87,9 @@ PA_NO_INLINE void PacketSender::send_oob_packet_u16(uint8_t seqnum, uint8_t opco uint8_t crc32[sizeof(uint32_t)]; } packet; packet.header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; - packet.header.opcode = opcode; packet.header.seqnum = seqnum; packet.header.packet_bytes = sizeof(packet); + packet.header.opcode = opcode; memcpy(&packet.header.data, &data, sizeof(uint16_t)); pabb_crc32_write_to_message(m_session_id, &packet, sizeof(packet)); m_connection.unreliable_send(&packet, sizeof(packet)); @@ -100,9 +100,9 @@ PA_NO_INLINE void PacketSender::send_oob_packet_u32(uint8_t seqnum, uint8_t opco uint8_t crc32[sizeof(uint32_t)]; } packet; packet.header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; - packet.header.opcode = opcode; packet.header.seqnum = seqnum; packet.header.packet_bytes = sizeof(packet); + packet.header.opcode = opcode; memcpy(&packet.header.data, &data, sizeof(uint32_t)); pabb_crc32_write_to_message(m_session_id, &packet, sizeof(packet)); m_connection.unreliable_send(&packet, sizeof(packet)); @@ -113,9 +113,9 @@ PA_NO_INLINE void PacketSender::send_oob_packet_data( ){ PacketHeader header; header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; - header.opcode = opcode; header.seqnum = seqnum; header.packet_bytes = sizeof(PacketHeader) + sizeof(uint32_t) + bytes; + header.opcode = opcode; uint32_t crc = m_session_id; pabb_crc32_buffer(&crc, &header, sizeof(PacketHeader)); pabb_crc32_buffer(&crc, data, bytes); @@ -130,9 +130,9 @@ PA_NO_INLINE void PacketSender::send_oob_packet_u32_data( ){ PacketHeader_u32 header; header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; - header.opcode = opcode; header.seqnum = seqnum; header.packet_bytes = sizeof(PacketHeader_u32) + sizeof(uint32_t) + bytes; + header.opcode = opcode; memcpy(&header.data, &u32, sizeof(uint32_t)); uint32_t crc = m_session_id; pabb_crc32_buffer(&crc, &header, sizeof(PacketHeader_u32)); From 8ac3fc61110551c1e9de70300a6daf13bcf3f060 Mon Sep 17 00:00:00 2001 From: Alexander Yee Date: Fri, 1 May 2026 20:49:03 -0700 Subject: [PATCH 4/4] More order undo. --- .../ReliableConnectionLayer/PABotBase2_PacketSender.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp index e209910fa1..d1fdb33ad3 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp @@ -286,9 +286,9 @@ PacketHeader* PacketSender::reserve_packet( PacketHeader* ret = (PacketHeader*)(m_buffer + offset); ret->magic_number = PABB2_CONNECTION_MAGIC_NUMBER; - ret->opcode = opcode; ret->seqnum = m_slot_tail++; ret->packet_bytes = packet_bytes; + ret->opcode = opcode; m_slot_tail_uncommitted = m_slot_tail; return ret; @@ -441,9 +441,9 @@ bool PacketSender::enqueue_uncommitted_send_stream(const void* data, size_t byte // Build the packet header. PacketHeaderData* packet = (PacketHeaderData*)(m_buffer + offset); packet->magic_number = PABB2_CONNECTION_MAGIC_NUMBER; - packet->opcode = PABB2_CONNECTION_OPCODE_ASK_STREAM_DATA; packet->seqnum = m_slot_tail_uncommitted++; packet->packet_bytes = (uint8_t)packet_bytes; // 256 overflows to 0 + packet->opcode = PABB2_CONNECTION_OPCODE_ASK_STREAM_DATA; memcpy(&packet->stream_offset, &m_stream_offset_uncommitted, sizeof(uint16_t)); // May be misaligned. // Copy stream data.