@@ -603,4 +603,159 @@ void PacketSerializer::parseChannelAnnouncePayload(const std::vector<uint8_t> &p
603603 }
604604}
605605
606+ std::vector<uint8_t > PacketSerializer::makeVersionHelloPayload (const std::vector<uint8_t > &supportedVersions, uint8_t preferredVersion, const std::string &clientVersion, const std::string &platform, const std::vector<std::string> &capabilities)
607+ {
608+ std::vector<uint8_t > data;
609+
610+ // Flags byte: bit 0 = hasCapabilities
611+ uint8_t flags = 0 ;
612+ if (!capabilities.empty ())
613+ {
614+ flags |= 0x01 ;
615+ }
616+ writeUint8 (data, flags);
617+
618+ // Supported versions array
619+ writeUint8 (data, static_cast <uint8_t >(supportedVersions.size ()));
620+ for (uint8_t version : supportedVersions)
621+ {
622+ writeUint8 (data, version);
623+ }
624+
625+ // Preferred version
626+ writeUint8 (data, preferredVersion);
627+
628+ // Client version (string with length prefix)
629+ writeUint8 (data, static_cast <uint8_t >(std::min (static_cast <size_t >(255 ), clientVersion.length ())));
630+ data.insert (data.end (), clientVersion.begin (), clientVersion.begin () + std::min (static_cast <size_t >(255 ), clientVersion.length ()));
631+
632+ // Platform (string with length prefix)
633+ writeUint8 (data, static_cast <uint8_t >(std::min (static_cast <size_t >(255 ), platform.length ())));
634+ data.insert (data.end (), platform.begin (), platform.begin () + std::min (static_cast <size_t >(255 ), platform.length ()));
635+
636+ // Capabilities (if present)
637+ if (!capabilities.empty ())
638+ {
639+ writeUint8 (data, static_cast <uint8_t >(capabilities.size ()));
640+ for (const std::string &capability : capabilities)
641+ {
642+ writeUint8 (data, static_cast <uint8_t >(std::min (static_cast <size_t >(255 ), capability.length ())));
643+ data.insert (data.end (), capability.begin (), capability.begin () + std::min (static_cast <size_t >(255 ), capability.length ()));
644+ }
645+ }
646+
647+ return data;
648+ }
649+
650+ void PacketSerializer::parseVersionHelloPayload (const std::vector<uint8_t > &payload, std::vector<uint8_t > &supportedVersions, uint8_t &preferredVersion, std::string &clientVersion, std::string &platform, std::vector<std::string> &capabilities)
651+ {
652+ // Minimum size check: flags(1) + versionCount(1) + at least one version(1) + preferredVersion(1) + min strings
653+ if (payload.size () < 4 )
654+ {
655+ spdlog::error (" Version hello payload too short" );
656+ return ;
657+ }
658+
659+ size_t offset = 0 ;
660+
661+ // Flags byte
662+ uint8_t flags = readUint8 (payload, offset);
663+ bool hasCapabilities = (flags & 0x01 ) != 0 ;
664+
665+ // Supported versions count
666+ uint8_t versionCount = readUint8 (payload, offset);
667+ supportedVersions.clear ();
668+
669+ for (uint8_t i = 0 ; i < versionCount; i++)
670+ {
671+ if (offset >= payload.size ())
672+ {
673+ spdlog::error (" Version hello payload buffer overflow reading supported versions" );
674+ return ;
675+ }
676+
677+ supportedVersions.push_back (readUint8 (payload, offset));
678+ }
679+
680+ // Preferred version
681+ if (offset >= payload.size ())
682+ {
683+ spdlog::error (" Version hello payload buffer overflow reading preferred version" );
684+ return ;
685+ }
686+
687+ preferredVersion = readUint8 (payload, offset);
688+
689+ // Client version (string with length prefix)
690+ if (offset >= payload.size ())
691+ {
692+ spdlog::error (" Version hello payload buffer overflow reading client version length" );
693+ return ;
694+ }
695+
696+ uint8_t clientVersionLen = readUint8 (payload, offset);
697+
698+ if (offset + clientVersionLen > payload.size ())
699+ {
700+ spdlog::error (" Version hello payload buffer overflow reading client version" );
701+ return ;
702+ }
703+
704+ clientVersion = std::string (payload.begin () + offset, payload.begin () + offset + clientVersionLen);
705+ offset += clientVersionLen;
706+
707+ // Platform (string with length prefix)
708+ if (offset >= payload.size ())
709+ {
710+ spdlog::error (" Version hello payload buffer overflow reading platform length" );
711+ return ;
712+ }
713+
714+ uint8_t platformLen = readUint8 (payload, offset);
715+
716+ if (offset + platformLen > payload.size ())
717+ {
718+ spdlog::error (" Version hello payload buffer overflow reading platform" );
719+ return ;
720+ }
721+
722+ platform = std::string (payload.begin () + offset, payload.begin () + offset + platformLen);
723+ offset += platformLen;
724+
725+ // Capabilities (if present)
726+ capabilities.clear ();
727+
728+ if (hasCapabilities)
729+ {
730+ if (offset >= payload.size ())
731+ {
732+ spdlog::error (" Version hello payload buffer overflow reading capabilities count" );
733+ return ;
734+ }
735+
736+ uint8_t capCount = readUint8 (payload, offset);
737+
738+ for (uint8_t i = 0 ; i < capCount; i++)
739+ {
740+ if (offset >= payload.size ())
741+ {
742+ spdlog::error (" Version hello payload buffer overflow reading capability length" );
743+ return ;
744+ }
745+
746+ uint8_t capLen = readUint8 (payload, offset);
747+
748+ if (offset + capLen > payload.size ())
749+ {
750+ spdlog::error (" Version hello payload buffer overflow reading capability" );
751+ return ;
752+ }
753+
754+ capabilities.push_back (std::string (payload.begin () + offset, payload.begin () + offset + capLen));
755+
756+ offset += capLen;
757+ }
758+ }
759+ }
760+
606761} // namespace bitchat
0 commit comments