@@ -117,6 +117,11 @@ std::string Wireshark::wiresharkPacketIdFuncName(const WiresharkGenerator& gener
117117 return wiresharkLocalNamespaceName (generator) + " .packet_id" ;
118118}
119119
120+ std::string Wireshark::wiresharkCreateCrcFuncName (const WiresharkGenerator& generator)
121+ {
122+ return wiresharkLocalNamespaceName (generator) + " .create_crc_calc" ;
123+ }
124+
120125bool Wireshark::wiresharkWriteInternal () const
121126{
122127 auto fileName = wiresharkFileName (m_wiresharkGenerator);
@@ -138,6 +143,7 @@ bool Wireshark::wiresharkWriteInternal() const
138143 " #^#PROT_VERSION#$#\n "
139144 " #^#STATUS_CODE#$#\n "
140145 " #^#OPT_MODE#$#\n "
146+ " #^#CRC#$#\n "
141147 " #^#FIELDS_REG#$#\n "
142148 " #^#EXTRACTORS_DECL#$#\n "
143149 " #^#FIELD_VALUE_FUNC#$#\n "
@@ -165,6 +171,7 @@ bool Wireshark::wiresharkWriteInternal() const
165171 {" FIELD_VALUE_FUNC" , wiresharkFieldValueFuncInternal ()},
166172 {" PROT_VERSION" , wiresharkProtocolVersionDefInternal ()},
167173 {" PINFO" , wiresharkPinfoDefInternal ()},
174+ {" CRC" , wiresharkCrcCodeDefInternal ()},
168175 };
169176
170177 auto str = commsdsl::gen::util::genProcessTemplate (Templ, repl, true );
@@ -517,6 +524,110 @@ std::string Wireshark::wiresharkPinfoDefInternal() const
517524 return util::genProcessTemplate (Templ, repl);
518525}
519526
527+ std::string Wireshark::wiresharkCrcCodeDefInternal () const
528+ {
529+ auto & schemas = m_wiresharkGenerator.genSchemas ();
530+ bool hasCrc =
531+ std::any_of (
532+ schemas.begin (), schemas.end (),
533+ [](auto & sPtr )
534+ {
535+ return WiresharkSchema::wiresharkCast (*sPtr ).wiresharkNeedsCrcCalc ();
536+ });
537+
538+ if (!hasCrc) {
539+ return strings::genEmptyString ();
540+ }
541+
542+ const std::string Templ =
543+ " function #^#NAME#$#(width, poly, init, ref_in, ref_out, xor_out)\n "
544+ " local function reflect(val, w)\n "
545+ " local res = 0\n "
546+ " for i = 0, w - 1 do\n "
547+ " if bit32.band(bit32.rshift(val, i), 1) == 1 then\n "
548+ " res = bit32.bor(res, bit32.lshift(1, w - 1 - i))\n "
549+ " end\n "
550+ " end\n "
551+ " return res\n "
552+ " end\n "
553+ " \n "
554+ " local tbl = {}\n "
555+ " local mask = (width == 32) and 0xFFFFFFFF or (bit32.lshift(1, width) - 1)\n "
556+ " local msb_mask = bit32.lshift(1, width - 1)\n "
557+ " \n "
558+ " -- Precompute the 256-value lookup table for this specific CRC profile\n "
559+ " for i = 0, 255 do\n "
560+ " local crc\n "
561+ " if ref_in then\n "
562+ " crc = i\n "
563+ " local ref_poly = reflect(poly, width)\n "
564+ " for j = 1, 8 do\n "
565+ " if bit32.band(crc, 1) == 1 then\n "
566+ " crc = bit32.bxor(bit32.rshift(crc, 1), ref_poly)\n "
567+ " else\n "
568+ " crc = bit32.rshift(crc, 1)\n "
569+ " end\n "
570+ " end\n "
571+ " else\n "
572+ " crc = bit32.lshift(i, width - 8)\n "
573+ " for j = 1, 8 do\n "
574+ " if bit32.band(crc, msb_mask) ~= 0 then\n "
575+ " crc = bit32.bxor(bit32.lshift(crc, 1), poly)\n "
576+ " else\n "
577+ " crc = bit32.lshift(crc, 1)\n "
578+ " end\n "
579+ " end\n "
580+ " end\n "
581+ " tbl[i] = bit32.band(crc, mask)\n "
582+ " end\n "
583+ " \n "
584+ " -- Return the actual high-speed checksum function\n "
585+ " -- Accepts tvb, offset, and offset_limit (exclusive end index)\n "
586+ " return function(tvb, offset, offset_limit)\n "
587+ " local crc = init\n "
588+ " local length = offset_limit - offset\n "
589+ " if length <= 0 then\n "
590+ " return init\n "
591+ " end\n "
592+ " \n "
593+ " -- Extracting raw bytes once is massively faster than calling tvb:range(i, 1) in a loop\n "
594+ " local data = tvb:range(offset, length):raw()\n "
595+ " \n "
596+ " for i = 1, #data do\n "
597+ " local byte = data:byte(i)\n "
598+ " if ref_in then\n "
599+ " local idx = bit32.band(bit32.bxor(crc, byte), 0xFF)\n "
600+ " crc = bit32.bxor(bit32.rshift(crc, 8), tbl[idx])\n "
601+ " else\n "
602+ " local idx = bit32.band(bit32.bxor(bit32.rshift(crc, width - 8), byte), 0xFF)\n "
603+ " crc = bit32.bxor(bit32.lshift(crc, 8), tbl[idx])\n "
604+ " end\n "
605+ " crc = bit32.band(crc, mask)\n "
606+ " end\n "
607+ " \n "
608+ " -- If output reflection differs from input reflection, we must reflect it\n "
609+ " if ref_out ~= ref_in then\n "
610+ " crc = reflect(crc, width)\n "
611+ " end\n "
612+ " \n "
613+ " crc = bit32.bxor(crc, xor_out)\n "
614+ " \n "
615+ " -- Force unsigned 32-bit (for environments where bitwise ops return signed 32-bit)\n "
616+ " if crc < 0 then\n "
617+ " crc = crc + 4294967296\n "
618+ " end\n "
619+ " \n "
620+ " return bit32.band(crc, mask)\n "
621+ " end\n "
622+ " end\n " ;
623+
624+ util::GenReplacementMap repl = {
625+ {" NAME" , wiresharkCreateCrcFuncName (m_wiresharkGenerator)},
626+ };
627+
628+ return util::genProcessTemplate (Templ, repl);
629+ }
630+
520631const std::string& Wireshark::wiresharkStatusCodeStrInternal (WiresharkStatusCode code)
521632{
522633 static const std::string Map[] = {
@@ -525,7 +636,9 @@ const std::string& Wireshark::wiresharkStatusCodeStrInternal(WiresharkStatusCode
525636 /* MalformedData */ " MALFORMED_PACKET" ,
526637 /* InvalidMsgId */ " INVALID_MSG_ID" ,
527638 /* InvalidMsgData */ " INVALID_MSG_DATA" ,
639+ /* ChecksumError */ " CHECKSUM_ERROR" ,
528640 /* CodegenError */ " CODEGEN_ERROR" ,
641+ /* InvalidFrame */ " INVALID_FRAME" ,
529642 };
530643 static const std::size_t MapSize = std::extent_v<decltype (Map)>;
531644 static_assert (MapSize == static_cast <unsigned >(WiresharkStatusCode::ValuesLimit));
0 commit comments