diff --git a/Common/Cpp/Concurrency/Mutex.h b/Common/Cpp/Concurrency/Mutex.h index 7a714c6c26..2de67402be 100644 --- a/Common/Cpp/Concurrency/Mutex.h +++ b/Common/Cpp/Concurrency/Mutex.h @@ -26,4 +26,11 @@ namespace PokemonAutomation{ #endif + +namespace PokemonAutomation{ + template + using LockGuard = std::lock_guard; +} + + #endif diff --git a/Common/Cpp/StreamConnections/PollingStreamConnections.h b/Common/Cpp/StreamConnections/PollingStreamConnections.h index 48155e4b11..dac127714b 100644 --- a/Common/Cpp/StreamConnections/PollingStreamConnections.h +++ b/Common/Cpp/StreamConnections/PollingStreamConnections.h @@ -27,6 +27,14 @@ class UnreliableStreamConnectionPolling : public UnreliableStreamSender{ class ReliableStreamConnectionPolling{ public: + virtual void lock() noexcept = 0; + virtual void unlock() noexcept = 0; + + // + // These 3 functions are not thread/IRQ safe with anything else. + // If needed call these under the lock above. + // + // Enqueue the specified data into the uncommitted stream. // On success, returns true. // On fail, return false and aborts all uncommitted sends. @@ -38,12 +46,16 @@ class ReliableStreamConnectionPolling{ // Commits all uncommitted sends to stream. virtual void commit_uncommitted_reliable_sends() noexcept = 0; + +public: virtual bool reliable_send_all_or_nothing(const void* data, size_t bytes) noexcept{ - if (!enqueue_uncommitted_reliable_sends(data, bytes)){ - return false; + lock(); + bool success = enqueue_uncommitted_reliable_sends(data, bytes); + if (success){ + commit_uncommitted_reliable_sends(); } - commit_uncommitted_reliable_sends(); - return true; + unlock(); + return success; } @@ -53,10 +65,10 @@ class ReliableStreamConnectionPolling{ virtual bool reset_flag_set() const{ return false; } virtual void clear_reset_flag(){} - virtual bool run_send_events(const WallDuration& timeout){ + virtual bool run_send_events(const WallDuration& timeout) noexcept{ return false; } - virtual bool run_recv_events(const WallDuration& timeout){ + virtual bool run_recv_events(const WallDuration& timeout) noexcept{ return false; } }; diff --git a/Common/PABotBase2/PABotBase2CC_MessageDumper.cpp b/Common/PABotBase2/PABotBase2CC_MessageDumper.cpp index 6a20285c75..66056ca99d 100644 --- a/Common/PABotBase2/PABotBase2CC_MessageDumper.cpp +++ b/Common/PABotBase2/PABotBase2CC_MessageDumper.cpp @@ -51,7 +51,7 @@ std::string tostr(const PacketHeader* header){ case PABB2_CONNECTION_OPCODE_RET_PACKET_SIZE: str += "PABB2_CONNECTION_OPCODE_RET_PACKET_SIZE: seqnum = "; str += std::to_string(header->seqnum); - str += ", bytes = " + std::to_string(((const PacketHeader_u16*)header)->data); + str += ", bytes = " + std::to_string(((const PacketHeader_u32*)header)->data); return str; case PABB2_CONNECTION_OPCODE_ASK_BUFFER_SLOTS: @@ -61,7 +61,7 @@ std::string tostr(const PacketHeader* header){ case PABB2_CONNECTION_OPCODE_RET_BUFFER_SLOTS: str += "PABB2_CONNECTION_OPCODE_RET_BUFFER_SLOTS: seqnum = "; str += std::to_string(header->seqnum); - str += ", slots = " + std::to_string(((const PacketHeader_u8*)header)->data); + str += ", slots = " + std::to_string(((const PacketHeader_u32*)header)->data); return str; case PABB2_CONNECTION_OPCODE_ASK_BUFFER_BYTES: @@ -71,7 +71,7 @@ std::string tostr(const PacketHeader* header){ case PABB2_CONNECTION_OPCODE_RET_BUFFER_BYTES: str += "PABB2_CONNECTION_OPCODE_RET_BUFFER_BYTES: seqnum = "; str += std::to_string(header->seqnum); - str += ", bytes = " + std::to_string(((const PacketHeader_u16*)header)->data); + str += ", bytes = " + std::to_string(((const PacketHeader_u32*)header)->data); return str; case PABB2_CONNECTION_OPCODE_ASK_STREAM_DATA: @@ -112,16 +112,6 @@ std::string tostr(const PacketHeader* header){ str += "PABB2_CONNECTION_OPCODE_INFO: seqnum = "; str += std::to_string(header->seqnum); return str; - case PABB2_CONNECTION_OPCODE_INFO_U8: - str += "PABB2_CONNECTION_OPCODE_INFO_U8: seqnum = "; - str += std::to_string(header->seqnum); - str += ", data = " + std::to_string(((const PacketHeader_u8*)header)->data); - return str; - case PABB2_CONNECTION_OPCODE_INFO_U16: - str += "PABB2_CONNECTION_OPCODE_INFO_U16: seqnum = "; - str += std::to_string(header->seqnum); - str += ", data = " + std::to_string(((const PacketHeader_u16*)header)->data); - return str; case PABB2_CONNECTION_OPCODE_INFO_H32: str += "PABB2_CONNECTION_OPCODE_INFO_H32: seqnum = "; str += std::to_string(header->seqnum); diff --git a/Common/PABotBase2/PABotBase2_MessageProtocol.h b/Common/PABotBase2/PABotBase2_MessageProtocol.h index 75d68fe620..a179547d0d 100644 --- a/Common/PABotBase2/PABotBase2_MessageProtocol.h +++ b/Common/PABotBase2/PABotBase2_MessageProtocol.h @@ -23,7 +23,7 @@ namespace PABotBase2{ -#define PABB2_MESSAGE_PROTOCOL_VERSION 2026050905 +#define PABB2_MESSAGE_PROTOCOL_VERSION 2026052100 struct PABB_PACK MessageHeader{ diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.cpp b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.cpp index 2d4605943f..4ee0d6449b 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.cpp +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.cpp @@ -201,12 +201,10 @@ void ReliableStreamConnection::on_cancellable_cancel( // Send Path // -bool ReliableStreamConnection::reset(bool random_session_id, WallDuration timeout){ +bool ReliableStreamConnection::reset(WallDuration timeout){ { std::lock_guard lg(m_lock); - if (!random_session_id){ - m_reliable_sender.reset(0xffffffff); - }else if (m_reliable_sender.session_id() == 0xffffffff){ + if (m_reliable_sender.session_id() == 0xffffffff){ m_reliable_sender.reset(random_u32()); }else{ m_reliable_sender.reset(m_reliable_sender.session_id() + 1); @@ -215,11 +213,7 @@ bool ReliableStreamConnection::reset(bool random_session_id, WallDuration timeou m_parser.reset(); m_stream_coalescer.reset(); throw_if_cancelled(); - if (random_session_id){ - m_reliable_sender.send_reset(); - }else{ - 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); @@ -267,10 +261,10 @@ void ReliableStreamConnection::send_ack(uint8_t seqnum, uint8_t opcode){ 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){ +void ReliableStreamConnection::send_ack_u32(uint8_t seqnum, uint8_t opcode, uint32_t data){ // Must call inside lock. struct{ - PacketHeader_u16 header; + PacketHeader_u32 header; uint8_t crc[sizeof(uint32_t)]; } packet; packet.header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; @@ -414,8 +408,6 @@ void ReliableStreamConnection::on_packet(const PacketHeader* packet){ case PABB2_CONNECTION_OPCODE_INFO_STREAM_SEND_FULL: case PABB2_CONNECTION_OPCODE_INFO_STREAM_RECV_FULL: case PABB2_CONNECTION_OPCODE_INFO: - case PABB2_CONNECTION_OPCODE_INFO_U8: - case PABB2_CONNECTION_OPCODE_INFO_U16: case PABB2_CONNECTION_OPCODE_INFO_H32: case PABB2_CONNECTION_OPCODE_INFO_U32: case PABB2_CONNECTION_OPCODE_INFO_I32: @@ -440,13 +432,13 @@ void ReliableStreamConnection::on_packet(const PacketHeader* packet){ } void ReliableStreamConnection::process_UNKNOWN_OPCODE(const PacketHeader* packet){ std::lock_guard lg(m_lock); - if (packet->packet_bytes < sizeof(PacketHeader_u8) + sizeof(uint32_t)){ + if (packet->packet_bytes < sizeof(PacketHeader_u32) + sizeof(uint32_t)){ m_error = "Unknown opcode packet is too small: " + std::to_string(packet->packet_bytes); m_logger.log("[RSC]: " + m_error, COLOR_RED); return; } - const PacketHeader_u8* message = (const PacketHeader_u8*)packet; + const PacketHeader_u32* message = (const PacketHeader_u32*)packet; m_logger.log( "[RSC]: PABB2_CONNECTION_OPCODE_INVALID_OPCODE: Device reported an invalid opcode: " + std::to_string(message->data), @@ -493,14 +485,14 @@ void ReliableStreamConnection::process_RET_VERSION(const PacketHeader* packet){ m_cv.notify_all(); } void ReliableStreamConnection::process_RET_PACKET_SIZE(const PacketHeader* packet){ - if (packet->packet_bytes < sizeof(PacketHeader_u16) + sizeof(uint32_t)){ + if (packet->packet_bytes < sizeof(PacketHeader_u32) + sizeof(uint32_t)){ m_logger.log( "[RSC]: Packet size response is too small: " + std::to_string(packet->packet_bytes), COLOR_RED ); return; } - const PacketHeader_u16* message = (const PacketHeader_u16*)packet; + const PacketHeader_u32* message = (const PacketHeader_u32*)packet; m_logger.log( "[RSC]: Setting Packet Size: " + std::to_string(message->data) + " bytes", COLOR_BLUE @@ -513,14 +505,14 @@ void ReliableStreamConnection::process_RET_PACKET_SIZE(const PacketHeader* packe m_cv.notify_all(); } void ReliableStreamConnection::process_RET_BUFFER_SLOTS(const PacketHeader* packet){ - if (packet->packet_bytes < sizeof(PacketHeader_u8) + sizeof(uint32_t)){ + if (packet->packet_bytes < sizeof(PacketHeader_u32) + sizeof(uint32_t)){ m_logger.log( "[RSC]: Buffer slot response is too small: " + std::to_string(packet->packet_bytes), COLOR_RED ); return; } - const PacketHeader_u8* message = (const PacketHeader_u8*)packet; + const PacketHeader_u32* message = (const PacketHeader_u32*)packet; { std::lock_guard lg(m_lock); m_reliable_sender.remove(packet->seqnum); @@ -533,14 +525,14 @@ void ReliableStreamConnection::process_RET_BUFFER_SLOTS(const PacketHeader* pack m_cv.notify_all(); } void ReliableStreamConnection::process_RET_BUFFER_BYTES(const PacketHeader* packet){ - if (packet->packet_bytes < sizeof(PacketHeader_u16) + sizeof(uint32_t)){ + if (packet->packet_bytes < sizeof(PacketHeader_u32) + sizeof(uint32_t)){ m_logger.log( "[RSC]: Buffer slot response is too small: " + std::to_string(packet->packet_bytes), COLOR_RED ); return; } - const PacketHeader_u16* message = (const PacketHeader_u16*)packet; + const PacketHeader_u32* message = (const PacketHeader_u32*)packet; { std::lock_guard lg(m_lock); m_reliable_sender.remove(packet->seqnum); @@ -570,7 +562,7 @@ void ReliableStreamConnection::process_ASK_STREAM_DATA(const PacketHeader* packe // cout << "Calling: send_ack_u16()" << endl; { std::lock_guard lg(m_lock); - send_ack_u16( + send_ack_u32( packet->seqnum, PABB2_CONNECTION_OPCODE_RET_STREAM_DATA, m_stream_coalescer.free_bytes() diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.h b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.h index 405d07cae7..5f13aaac82 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.h +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2CC_ReliableStreamConnection.h @@ -48,7 +48,7 @@ class ReliableStreamConnection final } virtual bool cancel(std::exception_ptr exception) noexcept override; - bool reset(bool random_session_id, WallDuration timeout = WallDuration::max()); + bool reset(WallDuration timeout = WallDuration::max()); bool remote_protocol_is_compatible() const{ return m_remote_protocol_compatible; @@ -89,7 +89,7 @@ class ReliableStreamConnection final // Send void send_ack(uint8_t seqnum, uint8_t opcode); - void send_ack_u16(uint8_t seqnum, uint8_t opcode, uint16_t data); + void send_ack_u32(uint8_t seqnum, uint8_t opcode, uint32_t data); void retransmit_thread(); diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2FW_ReliableStreamConnection.cpp b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2FW_ReliableStreamConnection.cpp index 8529b18d0c..9fbdbbe546 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2FW_ReliableStreamConnection.cpp +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2FW_ReliableStreamConnection.cpp @@ -66,8 +66,13 @@ void ReliableStreamConnectionFW::commit_uncommitted_reliable_sends() noexcept{ + +void ReliableStreamConnectionFW::send_oob_info_u32(uint32_t data){ + send_oob_packet_u32(0, PABB2_CONNECTION_OPCODE_INFO_U32, data); +} void ReliableStreamConnectionFW::send_oob_info_binary(const void* data, uint8_t bytes){ const size_t MAX_LENGTH = 256 - sizeof(PacketHeader) - sizeof(uint32_t); + LockGuard lg(m_sender_lock); m_reliable_sender.send_oob_packet_data( 0, PABB2_CONNECTION_OPCODE_INFO_BINARY, (uint8_t)std::min(bytes, MAX_LENGTH), data @@ -76,6 +81,7 @@ void ReliableStreamConnectionFW::send_oob_info_binary(const void* data, uint8_t void ReliableStreamConnectionFW::send_oob_info_str(const char* str){ const size_t MAX_LENGTH = 256 - sizeof(PacketHeader) - sizeof(uint32_t); size_t len = strlen(str); + LockGuard lg(m_sender_lock); m_reliable_sender.send_oob_packet_data( 0, PABB2_CONNECTION_OPCODE_INFO_STR, (uint8_t)std::min(len, MAX_LENGTH), str @@ -84,6 +90,7 @@ void ReliableStreamConnectionFW::send_oob_info_str(const char* str){ void ReliableStreamConnectionFW::send_oob_info_label_i32(uint8_t opcode, const char* str, uint32_t data){ const size_t MAX_LENGTH = 256 - sizeof(PacketHeader_u32) - sizeof(uint32_t); size_t len = strlen(str); + LockGuard lg(m_sender_lock); m_reliable_sender.send_oob_packet_u32_data( 0, opcode, data, @@ -92,8 +99,18 @@ void ReliableStreamConnectionFW::send_oob_info_label_i32(uint8_t opcode, const c } +void ReliableStreamConnectionFW::send_oob_packet_empty(uint8_t seqnum, uint8_t opcode) noexcept{ + LockGuard lg(m_sender_lock); + m_reliable_sender.send_oob_packet_empty(seqnum, opcode); +} +void ReliableStreamConnectionFW::send_oob_packet_u32(uint8_t seqnum, uint8_t opcode, const uint32_t& data) noexcept{ + LockGuard lg(m_sender_lock); + m_reliable_sender.send_oob_packet_u32(seqnum, opcode, data); +} + + -bool ReliableStreamConnectionFW::run_send_events(const WallDuration& timeout){ +bool ReliableStreamConnectionFW::run_send_events(const WallDuration& timeout) noexcept{ constexpr WallDuration POLL_RATE = milliseconds_to_duration(PABB2_ReliableConnectionFW_POLL_MS); WallClock now = current_time(); @@ -103,20 +120,27 @@ bool ReliableStreamConnectionFW::run_send_events(const WallDuration& timeout){ } m_last_retransmit = now; + + LockGuard lg(m_sender_lock); return m_reliable_sender.iterate_retransmits(); } -bool ReliableStreamConnectionFW::run_recv_events(const WallDuration& timeout){ +bool ReliableStreamConnectionFW::run_recv_events(const WallDuration& timeout) noexcept{ // If we have unacked sends, we cap the wait time since those may need to // be retransmitted. static constexpr WallDuration POLL_RATE = milliseconds_to_duration(PABB2_ReliableConnectionFW_POLL_MS); - const WallDuration& adjusted_timeout = m_reliable_sender.slots_used() != 0 && timeout > POLL_RATE - ? POLL_RATE - : timeout; + + const WallDuration* adjusted_timeout = &timeout; + if (timeout > POLL_RATE){ + LockGuard lg(m_sender_lock); + if (m_reliable_sender.slots_used() != 0){ + adjusted_timeout = &POLL_RATE; + } + } const PacketHeader* header = m_parser.pull_bytes( m_unreliable_connection, m_reliable_sender.session_id(), - adjusted_timeout + *adjusted_timeout ); if (header == nullptr){ return false; @@ -130,7 +154,7 @@ bool ReliableStreamConnectionFW::run_recv_events(const WallDuration& timeout){ break; case PABB2_PacketParser_RESULT_INVALID: // printf("PABB2_PacketParser_RESULT_INVALID\n"); - m_reliable_sender.send_oob_packet_empty( + send_oob_packet_empty( header->seqnum, PABB2_CONNECTION_OPCODE_INVALID_LENGTH ); @@ -139,7 +163,7 @@ bool ReliableStreamConnectionFW::run_recv_events(const WallDuration& timeout){ #ifdef PABB2_SUPPORTS_PRINTF_LOGGING printf("PABB2_PacketParser_RESULT_CHECKSUM_FAIL\n"); #endif - m_reliable_sender.send_oob_packet_empty( + send_oob_packet_empty( header->seqnum, PABB2_CONNECTION_OPCODE_INVALID_CHECKSUM_FAIL ); @@ -175,7 +199,7 @@ bool ReliableStreamConnectionFW::run_recv_events(const WallDuration& timeout){ #ifdef PABB2_ENABLE issue_reset_to_all(); #endif - m_reliable_sender.send_oob_packet_empty( + send_oob_packet_empty( header->seqnum, PABB2_CONNECTION_OPCODE_RET_RESET ); @@ -183,7 +207,7 @@ bool ReliableStreamConnectionFW::run_recv_events(const WallDuration& timeout){ } case PABB2_CONNECTION_OPCODE_ASK_VERSION: m_stream_coalescer.push_packet(header->seqnum); - m_reliable_sender.send_oob_packet_u32( + send_oob_packet_u32( header->seqnum, PABB2_CONNECTION_OPCODE_RET_VERSION, PABB2_CONNECTION_PROTOCOL_VERSION @@ -191,7 +215,7 @@ bool ReliableStreamConnectionFW::run_recv_events(const WallDuration& timeout){ return true; case PABB2_CONNECTION_OPCODE_ASK_PACKET_SIZE: m_stream_coalescer.push_packet(header->seqnum); - m_reliable_sender.send_oob_packet_u16( + send_oob_packet_u32( header->seqnum, PABB2_CONNECTION_OPCODE_RET_PACKET_SIZE, PABB2_MAX_INCOMING_PACKET_SIZE @@ -199,7 +223,7 @@ bool ReliableStreamConnectionFW::run_recv_events(const WallDuration& timeout){ return true; case PABB2_CONNECTION_OPCODE_ASK_BUFFER_SLOTS: m_stream_coalescer.push_packet(header->seqnum); - m_reliable_sender.send_oob_packet_u8( + send_oob_packet_u32( header->seqnum, PABB2_CONNECTION_OPCODE_RET_BUFFER_SLOTS, PABB2_StreamCoalescer_REORDER_WINDOW @@ -207,7 +231,7 @@ bool ReliableStreamConnectionFW::run_recv_events(const WallDuration& timeout){ return true; case PABB2_CONNECTION_OPCODE_ASK_BUFFER_BYTES: m_stream_coalescer.push_packet(header->seqnum); - m_reliable_sender.send_oob_packet_u16( + send_oob_packet_u32( header->seqnum, PABB2_CONNECTION_OPCODE_RET_BUFFER_BYTES, PABB2_StreamCoalescer_BUFFER_SIZE @@ -220,17 +244,19 @@ bool ReliableStreamConnectionFW::run_recv_events(const WallDuration& timeout){ send_oob_info_label_u32("Push Stream Failed", m_stream_coalescer.free_bytes()); return true; } - m_reliable_sender.send_oob_packet_u16( + send_oob_packet_u32( header->seqnum, PABB2_CONNECTION_OPCODE_RET_STREAM_DATA, m_stream_coalescer.free_bytes() ); return true; - case PABB2_CONNECTION_OPCODE_RET_STREAM_DATA: + case PABB2_CONNECTION_OPCODE_RET_STREAM_DATA:{ + LockGuard lg(m_sender_lock); m_reliable_sender.remove(header->seqnum); return true; + } default: - m_reliable_sender.send_oob_packet_u8( + send_oob_packet_u32( header->seqnum, PABB2_CONNECTION_OPCODE_UNKNOWN_OPCODE, header->opcode diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2FW_ReliableStreamConnection.h b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2FW_ReliableStreamConnection.h index e5b96978a8..3eef937556 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2FW_ReliableStreamConnection.h +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2FW_ReliableStreamConnection.h @@ -18,9 +18,11 @@ #ifdef PABB2_ENABLE #include "PabbTime.h" +#include "LocalMutex.h" #include "Tools/ResetListener.h" #else #include "Common/Cpp/Time.h" +#include "Common/Cpp/Concurrency/Mutex.h" #endif namespace PokemonAutomation{ @@ -46,25 +48,33 @@ class ReliableStreamConnectionFW final public: + virtual void lock() noexcept override{ + m_sender_lock.lock(); + } + virtual void unlock() noexcept override{ + m_sender_lock.unlock(); + } + + // Must be called under the lock above. virtual bool enqueue_uncommitted_reliable_sends(const void* data, size_t bytes) noexcept override; virtual void abort_uncommitted_reliable_sends() noexcept override; virtual void commit_uncommitted_reliable_sends() noexcept override; + +public: virtual size_t reliable_recv(void* data, size_t bytes) override{ return m_stream_coalescer.read(data, bytes); } - virtual bool run_send_events(const WallDuration& timeout) override; - virtual bool run_recv_events(const WallDuration& timeout) override; + virtual bool run_send_events(const WallDuration& timeout) noexcept override; + virtual bool run_recv_events(const WallDuration& timeout) noexcept override; public: // Send out-of-band messages. // These are not part of the reliable protocol and may be dropped. - void send_oob_info_u32(uint32_t data){ - m_reliable_sender.send_oob_packet_u32(0, PABB2_CONNECTION_OPCODE_INFO_U32, data); - } + void send_oob_info_u32(uint32_t data); void send_oob_info_binary(const void* data, uint8_t bytes); void send_oob_info_str(const char* str); void send_oob_info_label_h32(const char* str, const uint32_t& data){ @@ -88,6 +98,9 @@ class ReliableStreamConnectionFW final private: void send_oob_info_label_i32(uint8_t opcode, const char* str, uint32_t data); + void send_oob_packet_empty(uint8_t seqnum, uint8_t opcode) noexcept; + void send_oob_packet_u32(uint8_t seqnum, uint8_t opcode, const uint32_t& data) noexcept; + private: UnreliableStreamConnectionPolling& m_unreliable_connection; @@ -104,6 +117,8 @@ class ReliableStreamConnectionFW final // Don't allow any stream traffic until CC is ready. // The MLC layer will get stuck in a bad state if we end up between packets. bool m_stream_ready = false; + + Mutex m_sender_lock; }; diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketProtocol.h b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketProtocol.h index 6e4cc5b263..eee287cdd8 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 2026041102 +#define PABB2_CONNECTION_PROTOCOL_VERSION 2026052100 #define PABB2_CONNECTION_RETRANSMIT_FLAG 0x80 @@ -54,12 +54,6 @@ struct PABB_PACK PacketHeader{ uint8_t opcode; }; -struct PABB_PACK PacketHeader_u8 : PacketHeader{ - uint8_t data; -}; -struct PABB_PACK PacketHeader_u16 : PacketHeader{ - uint16_t data; -}; struct PABB_PACK PacketHeader_u32 : PacketHeader{ uint32_t data; }; @@ -104,16 +98,14 @@ struct PABB_PACK PacketHeaderData : PacketHeader{ #define PABB2_CONNECTION_OPCODE_INFO_STREAM_RECV_FULL 0x19 #define PABB2_CONNECTION_OPCODE_INFO 0x20 -#define PABB2_CONNECTION_OPCODE_INFO_U8 0x21 -#define PABB2_CONNECTION_OPCODE_INFO_U16 0x22 -#define PABB2_CONNECTION_OPCODE_INFO_H32 0x23 -#define PABB2_CONNECTION_OPCODE_INFO_U32 0x24 -#define PABB2_CONNECTION_OPCODE_INFO_I32 0x25 -#define PABB2_CONNECTION_OPCODE_INFO_BINARY 0x26 -#define PABB2_CONNECTION_OPCODE_INFO_STR 0x27 -#define PABB2_CONNECTION_OPCODE_INFO_LABEL_H32 0x28 -#define PABB2_CONNECTION_OPCODE_INFO_LABEL_U32 0x29 -#define PABB2_CONNECTION_OPCODE_INFO_LABEL_I32 0x2a +#define PABB2_CONNECTION_OPCODE_INFO_H32 0x21 +#define PABB2_CONNECTION_OPCODE_INFO_U32 0x22 +#define PABB2_CONNECTION_OPCODE_INFO_I32 0x23 +#define PABB2_CONNECTION_OPCODE_INFO_BINARY 0x24 +#define PABB2_CONNECTION_OPCODE_INFO_STR 0x25 +#define PABB2_CONNECTION_OPCODE_INFO_LABEL_H32 0x26 +#define PABB2_CONNECTION_OPCODE_INFO_LABEL_U32 0x27 +#define PABB2_CONNECTION_OPCODE_INFO_LABEL_I32 0x28 #define PABB2_CONNECTION_OPCODE_INVALID_LENGTH 0x30 #define PABB2_CONNECTION_OPCODE_INVALID_CHECKSUM_FAIL 0x31 diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp index ac9132045b..8a4bb698c8 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.cpp @@ -56,7 +56,7 @@ void PacketSender::reset(const SessionId& session_id){ -PA_NO_INLINE void PacketSender::send_oob_packet_empty(uint8_t seqnum, uint8_t opcode){ +PA_NO_INLINE void PacketSender::send_oob_packet_empty(uint8_t seqnum, uint8_t opcode) noexcept{ struct{ PacketHeader header; uint8_t crc32[sizeof(uint32_t)]; @@ -68,33 +68,7 @@ PA_NO_INLINE void PacketSender::send_oob_packet_empty(uint8_t seqnum, uint8_t op 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){ - struct{ - PacketHeader_u8 header; - uint8_t crc32[sizeof(uint32_t)]; - } packet; - packet.header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; - 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)); -} -PA_NO_INLINE void PacketSender::send_oob_packet_u16(uint8_t seqnum, uint8_t opcode, const uint16_t& data){ - struct{ - PacketHeader_u16 header; - uint8_t crc32[sizeof(uint32_t)]; - } packet; - packet.header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; - 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)); -} -PA_NO_INLINE void PacketSender::send_oob_packet_u32(uint8_t seqnum, uint8_t opcode, const uint32_t& data){ +PA_NO_INLINE void PacketSender::send_oob_packet_u32(uint8_t seqnum, uint8_t opcode, const uint32_t& data) noexcept{ struct{ PacketHeader_u32 header; uint8_t crc32[sizeof(uint32_t)]; @@ -110,7 +84,7 @@ PA_NO_INLINE void PacketSender::send_oob_packet_u32(uint8_t seqnum, uint8_t opco PA_NO_INLINE void PacketSender::send_oob_packet_data( uint8_t seqnum, uint8_t opcode, uint8_t bytes, const void* data -){ +) noexcept{ PacketHeader header; header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; header.seqnum = seqnum; @@ -127,7 +101,7 @@ PA_NO_INLINE void PacketSender::send_oob_packet_u32_data( uint8_t seqnum, uint8_t opcode, const uint32_t& u32, uint8_t bytes, const void* data -){ +) noexcept{ PacketHeader_u32 header; header.magic_number = PABB2_CONNECTION_MAGIC_NUMBER; header.seqnum = seqnum; @@ -145,7 +119,7 @@ PA_NO_INLINE void PacketSender::send_oob_packet_u32_data( -bool PacketSender::remove(uint8_t seqnum){ +bool PacketSender::remove(uint8_t seqnum) noexcept{ // { // std::lock_guard lg(print_lock); // cout << "PacketSender::remove(" << this << "): " << (int)seqnum << endl; @@ -182,6 +156,7 @@ bool PacketSender::remove(uint8_t seqnum){ if (seqnum == m_slot_tail){ m_buffer_head = 0; m_buffer_tail = 0; + m_buffer_tail_uncommitted = 0; return true; } @@ -197,7 +172,7 @@ bool PacketSender::remove(uint8_t seqnum){ } } -void PacketSender::send_reset(){ +void PacketSender::send_reset() noexcept{ PacketHeader_u32* packet = (PacketHeader_u32*)reserve_packet( PABB2_CONNECTION_OPCODE_ASK_RESET, sizeof(PacketHeader_u32) - sizeof(PacketHeader) @@ -220,7 +195,7 @@ void PacketSender::send_reset(){ } bool PacketSender::send_packet( uint8_t opcode, uint8_t extra_bytes, const void* extra_data -){ +) noexcept{ PacketHeader* packet = reserve_packet(opcode, extra_bytes); if (packet == NULL){ return false; @@ -232,7 +207,7 @@ bool PacketSender::send_packet( PacketHeader* PacketSender::reserve_packet( uint8_t opcode, uint8_t extra_bytes -){ +) noexcept{ // No slots available. uint8_t slots_used = m_slot_tail - m_slot_head; if (slots_used == REORDER_WINDOW){ @@ -293,7 +268,7 @@ PacketHeader* PacketSender::reserve_packet( return ret; } -void PacketSender::commit_packet(PacketHeader* packet){ +void PacketSender::commit_packet(PacketHeader* packet) noexcept{ pabb_crc32_write_to_message(m_session_id, packet, packet->packet_bytes); m_connection.unreliable_send(packet, packet->packet_bytes); @@ -306,7 +281,7 @@ void PacketSender::commit_packet(PacketHeader* packet){ -bool PacketSender::iterate_retransmits(){ +bool PacketSender::iterate_retransmits() noexcept{ uint8_t head = m_slot_head; uint8_t tail = m_slot_tail; @@ -463,7 +438,7 @@ bool PacketSender::enqueue_uncommitted_send_stream(const void* data, size_t byte abort_uncommitted_send_stream(); return false; } -void PacketSender::abort_uncommitted_send_stream(){ +void PacketSender::abort_uncommitted_send_stream() noexcept{ m_slot_tail_uncommitted = m_slot_tail; m_buffer_tail_uncommitted = m_buffer_tail; m_stream_offset_uncommitted = m_stream_offset; diff --git a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.h b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.h index 7687085b53..71bd74af3a 100644 --- a/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.h +++ b/Common/PABotBase2/ReliableConnectionLayer/PABotBase2_PacketSender.h @@ -80,19 +80,17 @@ class PacketSender{ // Out-of-band messages that bypass the queue and go out as-is. // These may be dropped. // - void send_oob_packet_empty(uint8_t seqnum, uint8_t opcode); - void send_oob_packet_u8(uint8_t seqnum, uint8_t opcode, uint8_t data); - void send_oob_packet_u16(uint8_t seqnum, uint8_t opcode, const uint16_t& data); - void send_oob_packet_u32(uint8_t seqnum, uint8_t opcode, const uint32_t& data); + void send_oob_packet_empty(uint8_t seqnum, uint8_t opcode) noexcept; + void send_oob_packet_u32(uint8_t seqnum, uint8_t opcode, const uint32_t& data) noexcept; void send_oob_packet_data( uint8_t seqnum, uint8_t opcode, uint8_t bytes, const void* data - ); + ) noexcept; void send_oob_packet_u32_data( uint8_t seqnum, uint8_t opcode, const uint32_t& u32, uint8_t bytes, const void* data - ); + ) noexcept; public: @@ -102,15 +100,15 @@ class PacketSender{ // Remove the packet corresponding to the specified seqnum from the queue. // Returns true is successful, false if seqnum is not in the queue. - bool remove(uint8_t seqnum); + bool remove(uint8_t seqnum) noexcept; - void send_reset(); + void send_reset() noexcept; // // Send a packet with the specified opcode and extra data after the header. // Returns true if successful. (enters the queue) // - bool send_packet(uint8_t opcode, uint8_t extra_bytes, const void* extra_data); + bool send_packet(uint8_t opcode, uint8_t extra_bytes, const void* extra_data) noexcept; // // Send a single packet in two parts: @@ -133,12 +131,12 @@ class PacketSender{ // function can be called on this queue. It is undefined behavior to separate // "reserve()" and "commit()" with another function on the same queue. // - PacketHeader* reserve_packet(uint8_t opcode, uint8_t extra_bytes); - void commit_packet(PacketHeader* packet); + PacketHeader* reserve_packet(uint8_t opcode, uint8_t extra_bytes) noexcept; + void commit_packet(PacketHeader* packet) noexcept; // Returns true if something was retransmitted. - bool iterate_retransmits(); + bool iterate_retransmits() noexcept; public: @@ -154,7 +152,7 @@ class PacketSender{ // bool enqueue_uncommitted_send_stream(const void* data, size_t bytes) noexcept; - void abort_uncommitted_send_stream(); + void abort_uncommitted_send_stream() noexcept; void commit_uncommitted_send_stream() noexcept; // diff --git a/SerialPrograms/Source/Controllers/PABotBase2/SerialPABotBase2_Connection.cpp b/SerialPrograms/Source/Controllers/PABotBase2/SerialPABotBase2_Connection.cpp index a9c50e9423..0cd00f157f 100644 --- a/SerialPrograms/Source/Controllers/PABotBase2/SerialPABotBase2_Connection.cpp +++ b/SerialPrograms/Source/Controllers/PABotBase2/SerialPABotBase2_Connection.cpp @@ -121,17 +121,11 @@ 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) + " (with session ID)..."); m_unreliable_connection->set_baud_rate(baud_rate); - if (m_stream_connection->reset(true, std::chrono::milliseconds(100))){ + if (m_stream_connection->reset(std::chrono::milliseconds(100))){ return true; } } diff --git a/SerialPrograms/Source/Controllers/SerialPABotBase/SerialPABotBase.cpp b/SerialPrograms/Source/Controllers/SerialPABotBase/SerialPABotBase.cpp index 132e92e989..3d60b92f03 100644 --- a/SerialPrograms/Source/Controllers/SerialPABotBase/SerialPABotBase.cpp +++ b/SerialPrograms/Source/Controllers/SerialPABotBase/SerialPABotBase.cpp @@ -57,11 +57,11 @@ const std::map>& SUPPORTED_VERSIONS( // These version #'s are for the MLC layer. const std::map& SUPPORTED_DEVICES2(){ static const std::map database{ - {PABB_PID_UNSPECIFIED, 2026050901}, - {PABB_PID_PABOTBASE_ESP32, 2026050901}, - {PABB_PID_PABOTBASE_ESP32S3, 2026050901}, - {PABB_PID_PABOTBASE_Pico1, 2026050901}, - {PABB_PID_PABOTBASE_Pico2, 2026050901}, + {PABB_PID_UNSPECIFIED, 2026052100}, + {PABB_PID_PABOTBASE_ESP32, 2026052100}, + {PABB_PID_PABOTBASE_ESP32S3, 2026052100}, + {PABB_PID_PABOTBASE_Pico1, 2026052100}, + {PABB_PID_PABOTBASE_Pico2, 2026052100}, }; return database; } diff --git a/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramComputer.cpp b/SerialPrograms/Source/NintendoSwitch/DevPrograms/TestProgramComputer.cpp index 5b544326c5..42a9457b35 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(true); + connection.reset(); connection.send_request(PABB2_CONNECTION_OPCODE_ASK_VERSION); connection.wait_for_pending(); connection.send_request(PABB2_CONNECTION_OPCODE_ASK_PACKET_SIZE);