@@ -109,6 +109,20 @@ namespace pcpp
109
109
NotApplicable = 255
110
110
};
111
111
112
+ namespace internal
113
+ {
114
+ // / @enum Asn1LoadPolicy
115
+ // / @brief Policy for when to evaluate (decode) ASN.1 record values.
116
+ // / Determines whether the value is decoded immediately (eager) or on first access (lazy).
117
+ enum class Asn1LoadPolicy
118
+ {
119
+ // / The value is evaluated on first access (lazy decoding).
120
+ Lazy,
121
+ // / The value is evaluated immediately on construction (eager decoding).
122
+ Eager
123
+ };
124
+ } // namespace internal
125
+
112
126
// / @class Asn1Record
113
127
// / Represents an ASN.1 record, as described in ITU-T Recommendation X.680:
114
128
// / <https://www.itu.int/rec/T-REC-X.680/en>
@@ -127,7 +141,7 @@ namespace pcpp
127
141
128
142
// / Encode this record and convert it to a byte stream
129
143
// / @return A vector of bytes representing the record
130
- std::vector<uint8_t > encode ();
144
+ std::vector<uint8_t > encode () const ;
131
145
132
146
// / @return The ASN.1 tag class
133
147
Asn1TagClass getTagClass () const
@@ -164,7 +178,7 @@ namespace pcpp
164
178
}
165
179
166
180
// / @return A string representation of the record
167
- std::string toString ();
181
+ std::string toString () const ;
168
182
169
183
// / A templated method that accepts a class derived from Asn1Record as its template argument and attempts
170
184
// / to cast the current instance to that type
@@ -190,26 +204,41 @@ namespace pcpp
190
204
size_t m_ValueLength = 0 ;
191
205
size_t m_TotalLength = 0 ;
192
206
193
- uint8_t const * m_EncodedValue = nullptr ;
194
-
195
207
Asn1Record () = default ;
196
208
197
- static std::unique_ptr<Asn1Record> decodeInternal (const uint8_t * data, size_t dataLen, bool lazy);
209
+ // / @brief Decodes the record value from a byte array into the mutable cache variables.
210
+ // / This method is marked as const as it can be called on a const instance of the record for lazy decoding.
211
+ virtual void decodeValue (uint8_t const * data) const = 0;
198
212
199
- virtual void decodeValue (uint8_t const * data, bool lazy) = 0;
213
+ // / @brief Encodes the record value into a byte array
214
+ // / Prefer using encodeValueSafe() to ensure the value is decoded first if needed
200
215
virtual std::vector<uint8_t > encodeValue () const = 0;
201
216
217
+ // / @brief Encodes the record value into a byte array, ensuring that the value is decoded first if needed
218
+ std::vector<uint8_t > encodeValueSafe () const
219
+ {
220
+ decodeValueIfNeeded ();
221
+ return encodeValue ();
222
+ }
223
+
202
224
static std::unique_ptr<Asn1Record> decodeTagAndCreateRecord (const uint8_t * data, size_t dataLen,
203
225
uint8_t & tagLen);
204
226
uint8_t decodeLength (const uint8_t * data, size_t dataLen);
205
- void decodeValueIfNeeded ();
227
+ void decodeValueIfNeeded () const ;
206
228
207
- uint8_t encodeTag ();
229
+ uint8_t encodeTag () const ;
208
230
std::vector<uint8_t > encodeLength () const ;
209
231
210
- virtual std::vector<std::string> toStringList ();
232
+ // note: Requires the value to be decoded first if lazy decoding is used
233
+ virtual std::vector<std::string> toStringList () const ;
211
234
212
235
friend class Asn1ConstructedRecord ;
236
+
237
+ private:
238
+ void setEncodedValue (uint8_t const * dataSource,
239
+ internal::Asn1LoadPolicy loadPolicy = internal::Asn1LoadPolicy::Lazy);
240
+
241
+ mutable uint8_t const * m_EncodedValue = nullptr ;
213
242
};
214
243
215
244
// / @class Asn1GenericRecord
@@ -248,11 +277,11 @@ namespace pcpp
248
277
protected:
249
278
Asn1GenericRecord () = default ;
250
279
251
- void decodeValue (uint8_t const * data, bool lazy) override ;
280
+ void decodeValue (uint8_t const * data) const override ;
252
281
std::vector<uint8_t > encodeValue () const override ;
253
282
254
283
private:
255
- std::unique_ptr<uint8_t []> m_Value = nullptr ;
284
+ mutable std::unique_ptr<uint8_t []> m_Value = nullptr ;
256
285
257
286
void init (Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const uint8_t * value, size_t valueLen);
258
287
};
@@ -289,10 +318,10 @@ namespace pcpp
289
318
protected:
290
319
Asn1ConstructedRecord () = default ;
291
320
292
- void decodeValue (uint8_t const * data, bool lazy) override ;
321
+ void decodeValue (uint8_t const * data) const override ;
293
322
std::vector<uint8_t > encodeValue () const override ;
294
323
295
- std::vector<std::string> toStringList () override ;
324
+ std::vector<std::string> toStringList () const override ;
296
325
297
326
template <typename Iterator> void init (Asn1TagClass tagClass, uint8_t tagType, Iterator begin, Iterator end)
298
327
{
@@ -304,7 +333,7 @@ namespace pcpp
304
333
for (Iterator recordIter = begin; recordIter != end; ++recordIter)
305
334
{
306
335
auto encodedRecord = (*recordIter)->encode ();
307
- auto copyRecord = Asn1Record::decode (encodedRecord.data (), encodedRecord.size (), false );
336
+ auto copyRecord = Asn1Record::decode (encodedRecord.data (), encodedRecord.size (), LazySubRecordDecoding );
308
337
m_SubRecords.pushBack (std::move (copyRecord));
309
338
recordValueLength += encodedRecord.size ();
310
339
}
@@ -314,7 +343,10 @@ namespace pcpp
314
343
}
315
344
316
345
private:
317
- PointerVector<Asn1Record> m_SubRecords;
346
+ // Set to false as there are issues with lazy decoding of sub-records in some cases.
347
+ static constexpr bool LazySubRecordDecoding = false ;
348
+
349
+ mutable PointerVector<Asn1Record> m_SubRecords;
318
350
};
319
351
320
352
// / @class Asn1SequenceRecord
@@ -389,7 +421,7 @@ namespace pcpp
389
421
390
422
// / @return The integer value of this record
391
423
// / @throw std::invalid_argument if the value doesn't fit the requested integer size
392
- template <typename T, EnableIfUnsignedIntegral<T> = 0 > T getIntValue ()
424
+ template <typename T, EnableIfUnsignedIntegral<T> = 0 > T getIntValue () const
393
425
{
394
426
decodeValueIfNeeded ();
395
427
return m_Value.getInt <T>();
@@ -403,7 +435,7 @@ namespace pcpp
403
435
}
404
436
405
437
// / @return A hex string representation of the record value
406
- std::string getValueAsString ()
438
+ std::string getValueAsString () const
407
439
{
408
440
decodeValueIfNeeded ();
409
441
return m_Value.toString ();
@@ -412,10 +444,10 @@ namespace pcpp
412
444
protected:
413
445
Asn1IntegerRecord () = default ;
414
446
415
- void decodeValue (uint8_t const * data, bool lazy) override ;
447
+ void decodeValue (uint8_t const * data) const override ;
416
448
std::vector<uint8_t > encodeValue () const override ;
417
449
418
- std::vector<std::string> toStringList () override ;
450
+ std::vector<std::string> toStringList () const override ;
419
451
420
452
private:
421
453
class BigInt
@@ -475,7 +507,7 @@ namespace pcpp
475
507
}
476
508
};
477
509
478
- BigInt m_Value;
510
+ mutable BigInt m_Value;
479
511
};
480
512
481
513
// / @class Asn1EnumeratedRecord
@@ -500,7 +532,7 @@ namespace pcpp
500
532
{
501
533
public:
502
534
// / @return The string value of this record
503
- std::string getValue ()
535
+ std::string getValue () const
504
536
{
505
537
decodeValueIfNeeded ();
506
538
return m_Value;
@@ -516,7 +548,7 @@ namespace pcpp
516
548
m_TotalLength = m_ValueLength + 2 ;
517
549
}
518
550
519
- void decodeValue (uint8_t const * data, bool lazy) override
551
+ void decodeValue (uint8_t const * data) const override
520
552
{
521
553
m_Value = std::string (reinterpret_cast <char const *>(data), m_ValueLength);
522
554
}
@@ -525,12 +557,12 @@ namespace pcpp
525
557
return { m_Value.begin (), m_Value.end () };
526
558
}
527
559
528
- std::vector<std::string> toStringList () override
560
+ std::vector<std::string> toStringList () const override
529
561
{
530
562
return { Asn1Record::toStringList ().front () + " , Value: " + getValue () };
531
563
}
532
564
533
- std::string m_Value;
565
+ mutable std::string m_Value;
534
566
};
535
567
536
568
// / @class Asn1OctetStringRecord
@@ -553,13 +585,13 @@ namespace pcpp
553
585
{}
554
586
555
587
protected:
556
- void decodeValue (uint8_t const * data, bool lazy) override ;
588
+ void decodeValue (uint8_t const * data) const override ;
557
589
std::vector<uint8_t > encodeValue () const override ;
558
590
559
591
private:
560
592
Asn1OctetStringRecord () = default ;
561
593
562
- bool m_IsPrintable = true ;
594
+ mutable bool m_IsPrintable = true ;
563
595
};
564
596
565
597
// / @class Asn1UTF8StringRecord
@@ -622,22 +654,22 @@ namespace pcpp
622
654
explicit Asn1BooleanRecord (bool value);
623
655
624
656
// / @return The boolean value of this record
625
- bool getValue ()
657
+ bool getValue () const
626
658
{
627
659
decodeValueIfNeeded ();
628
660
return m_Value;
629
661
};
630
662
631
663
protected:
632
- void decodeValue (uint8_t const * data, bool lazy) override ;
664
+ void decodeValue (uint8_t const * data) const override ;
633
665
std::vector<uint8_t > encodeValue () const override ;
634
666
635
- std::vector<std::string> toStringList () override ;
667
+ std::vector<std::string> toStringList () const override ;
636
668
637
669
private:
638
670
Asn1BooleanRecord () = default ;
639
671
640
- bool m_Value = false ;
672
+ mutable bool m_Value = false ;
641
673
};
642
674
643
675
// / @class Asn1NullRecord
@@ -651,7 +683,7 @@ namespace pcpp
651
683
Asn1NullRecord ();
652
684
653
685
protected:
654
- void decodeValue (uint8_t const * data, bool lazy) override
686
+ void decodeValue (uint8_t const * data) const override
655
687
{}
656
688
std::vector<uint8_t > encodeValue () const override
657
689
{
@@ -728,20 +760,20 @@ namespace pcpp
728
760
explicit Asn1ObjectIdentifierRecord (const Asn1ObjectIdentifier& value);
729
761
730
762
// / @return The OID value of this record
731
- const Asn1ObjectIdentifier& getValue ()
763
+ const Asn1ObjectIdentifier& getValue () const
732
764
{
733
765
decodeValueIfNeeded ();
734
766
return m_Value;
735
767
}
736
768
737
769
protected:
738
- void decodeValue (uint8_t const * data, bool lazy) override ;
770
+ void decodeValue (uint8_t const * data) const override ;
739
771
std::vector<uint8_t > encodeValue () const override ;
740
772
741
- std::vector<std::string> toStringList () override ;
773
+ std::vector<std::string> toStringList () const override ;
742
774
743
775
private:
744
- Asn1ObjectIdentifier m_Value;
776
+ mutable Asn1ObjectIdentifier m_Value;
745
777
746
778
Asn1ObjectIdentifierRecord () = default ;
747
779
};
@@ -756,7 +788,7 @@ namespace pcpp
756
788
// / timezones. The default value is UTC
757
789
// / @return The time-point value of this record
758
790
// / @throws std::invalid_argument if timezone is not in the correct format
759
- std::chrono::system_clock::time_point getValue (const std::string& timezone = " Z" )
791
+ std::chrono::system_clock::time_point getValue (const std::string& timezone = " Z" ) const
760
792
{
761
793
decodeValueIfNeeded ();
762
794
return adjustTimezones (m_Value, " Z" , timezone);
@@ -769,16 +801,16 @@ namespace pcpp
769
801
// / @return The value as string
770
802
// / @throws std::invalid_argument if timezone is not in the correct format
771
803
std::string getValueAsString (const std::string& format = " %Y-%m-%d %H:%M:%S" , const std::string& timezone = " Z" ,
772
- bool includeMilliseconds = false );
804
+ bool includeMilliseconds = false ) const ;
773
805
774
806
protected:
775
807
Asn1TimeRecord () = default ;
776
808
explicit Asn1TimeRecord (Asn1UniversalTagType tagType, const std::chrono::system_clock::time_point& value,
777
809
const std::string& timezone);
778
810
779
- std::chrono::system_clock::time_point m_Value;
811
+ mutable std::chrono::system_clock::time_point m_Value;
780
812
781
- std::vector<std::string> toStringList () override ;
813
+ std::vector<std::string> toStringList () const override ;
782
814
783
815
static void validateTimezone (const std::string& timezone);
784
816
static std::chrono::system_clock::time_point adjustTimezones (const std::chrono::system_clock::time_point& value,
@@ -799,12 +831,12 @@ namespace pcpp
799
831
explicit Asn1UtcTimeRecord (const std::chrono::system_clock::time_point& value, bool withSeconds = true );
800
832
801
833
protected:
802
- void decodeValue (uint8_t const * data, bool lazy) override ;
834
+ void decodeValue (uint8_t const * data) const override ;
803
835
std::vector<uint8_t > encodeValue () const override ;
804
836
805
837
private:
806
838
Asn1UtcTimeRecord () = default ;
807
- bool m_WithSeconds = true ;
839
+ mutable bool m_WithSeconds = true ;
808
840
};
809
841
810
842
// / @class Asn1GeneralizedTimeRecord
@@ -823,12 +855,12 @@ namespace pcpp
823
855
const std::string& timezone = " Z" );
824
856
825
857
protected:
826
- void decodeValue (uint8_t const * data, bool lazy) override ;
858
+ void decodeValue (uint8_t const * data) const override ;
827
859
std::vector<uint8_t > encodeValue () const override ;
828
860
829
861
private:
830
862
Asn1GeneralizedTimeRecord () = default ;
831
- std::string m_Timezone;
863
+ mutable std::string m_Timezone;
832
864
};
833
865
834
866
// / @class Asn1BitStringRecord
@@ -858,10 +890,10 @@ namespace pcpp
858
890
}
859
891
860
892
protected:
861
- void decodeValue (uint8_t const * data, bool lazy) override ;
893
+ void decodeValue (uint8_t const * data) const override ;
862
894
std::vector<uint8_t > encodeValue () const override ;
863
895
864
- std::vector<std::string> toStringList () override ;
896
+ std::vector<std::string> toStringList () const override ;
865
897
866
898
private:
867
899
class BitSet
@@ -890,6 +922,6 @@ namespace pcpp
890
922
891
923
Asn1BitStringRecord () = default ;
892
924
893
- BitSet m_Value;
925
+ mutable BitSet m_Value;
894
926
};
895
927
} // namespace pcpp
0 commit comments