22#define MS_RTC_SCTP_CHUNK_HPP
33
44#include " common.hpp"
5- #include < absl/container/flat_hash_map.h >
5+ #include " RTC/Serializable.hpp "
66#include < string>
7+ #include < unordered_map>
78
89namespace RTC
910{
@@ -21,9 +22,25 @@ namespace RTC
2122 * / Chunk Value /
2223 * \ \
2324 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25+ *
26+ * - Chunk Type (8 bits): Unsigned integer.
27+ * - Chunk Flags (8 bits).
28+ * - Chunk Length (16 bits): Unsigned integer. Total length of the Chunk
29+ * excluding padding bytes. Minimum value is 4 (if Chunk Value is 0
30+ * bytes).
31+ * - Chunk Value (variable length).
32+ * - Padding: Bytes of padding to make the Packet length be multiple of 4
33+ * bytes.
2434 */
25- class Chunk
35+
36+ // Forward declaration.
37+ class Packet ;
38+
39+ class Chunk : public Serializable
2640 {
41+ private:
42+ friend class Packet ;
43+
2744 public:
2845 /* *
2946 * Chunk types.
@@ -50,7 +67,7 @@ namespace RTC
5067 /* *
5168 * Struct of a SCTP Chunk Header.
5269 */
53- struct Header
70+ struct ChunkHeader
5471 {
5572 ChunkType type;
5673 uint8_t flags;
@@ -65,88 +82,97 @@ namespace RTC
6582 };
6683
6784 public:
68- static const size_t HeaderLength { 4 };
85+ static const size_t ChunkHeaderLength { 4 };
6986
87+ public:
7088 /* *
71- * Parses given `data` with length `len` and returns an allocated instance
72- * of Chunk (or nullptr if it's not a valid SCTP chunk).
89+ * Whether given buffer could be a a valid Chunk.
7390 *
74- * If `exactLen` is set to true, then given `len` must be the total length
75- * of this chunk. Otherwise we assume that other chunks could follow this
76- * one.
77- *
78- * So if `exactLen` is set to true, `len` must be multiple of 4 bytes (it
79- * must include padding if needed) .
91+ * @param buffer
92+ * @param bufferLength - Can be greater than real Chunk length.
93+ * @param chunkType - If given buffer is a valid FooItem then `chunkType`
94+ * is rewritten to parsed ChunkType.
95+ * @param valueLength - If given buffer is a valid Chunk then
96+ * `valueLength` is rewritten to the length of the Chunk .
8097 */
81- static Chunk* Parse (const uint8_t * data, size_t len, bool exactLen);
98+ static bool IsChunk (
99+ const uint8_t * buffer, size_t bufferLength, ChunkType& chunkType, uint16_t & chunkLength);
82100
83101 static const std::string& ChunkType2String (ChunkType chunkType);
84102
85103 private:
86- static absl::flat_hash_map<ChunkType, std::string> chunkType2String;
104+ static std::unordered_map<ChunkType, std::string> chunkType2String;
105+
106+ protected:
107+ /* *
108+ * Constructor is protected because we only want to create Chunk
109+ * instances via Parse() and Factory() in subclasses.
110+ */
111+ Chunk (const uint8_t * buffer, size_t bufferLength);
87112
88113 public:
89- Chunk (const uint8_t * data, size_t size) ;
114+ virtual ~ Chunk () override ;
90115
91- virtual ~Chunk ();
116+ /* *
117+ * NOTE: Should be overridden by each subclass.
118+ */
119+ virtual void Dump () const override ;
92120
93- void Dump () const ;
121+ /* *
122+ * Can be overridden by each subclass.
123+ */
124+ virtual Chunk* Clone (uint8_t * buffer, size_t bufferLength) const override ;
94125
95- const uint8_t * GetData () const
126+ virtual ChunkType GetType () const final
96127 {
97- return reinterpret_cast < const uint8_t *>( this -> data ) ;
128+ return GetHeaderPointer ()-> type ;
98129 }
99130
100- size_t GetSize () const
131+ virtual uint8_t GetFlags () const final
101132 {
102- return this -> size ;
133+ return GetHeaderPointer ()-> flags ;
103134 }
104135
105- ChunkType GetType () const
136+ virtual bool HasValue () const final
106137 {
107- return static_cast <ChunkType>( this -> header -> type ) ;
138+ return GetLengthField () > Chunk::ChunkHeaderLength ;
108139 }
109140
110- void SetType (ChunkType type)
141+ virtual uint16_t GetValueLength () const final
111142 {
112- this ->header ->type = static_cast <ChunkType>(type);
113- }
143+ if (!HasValue ())
144+ {
145+ return 0u ;
146+ }
114147
115- uint8_t GetFlags () const
116- {
117- return this ->header ->flags ;
148+ return GetLengthField () - Chunk::ChunkHeaderLength;
118149 }
119150
120- void SetFlags (uint8_t flags)
151+ protected:
152+ virtual void InitializeHeader (ChunkType chunkType, uint8_t flags, uint16_t valueLength) final ;
153+
154+ /* *
155+ * NOTE: Return ChunkHeader* instead of const ChunkHeader* since we may
156+ * want to modify its fields.
157+ */
158+ virtual ChunkHeader* GetHeaderPointer () const final
121159 {
122- this -> header -> flags = flags ;
160+ return reinterpret_cast <ChunkHeader*>( const_cast < uint8_t *>( GetBuffer ())) ;
123161 }
124162
125163 /* *
126- * The length of the Chunk Value field. It does not count any padding.
127- *
128- * @remarks
129- * This is not the value of the Chunk Length field in the Chunk Header
130- * but the real length of the Chunk Value.
164+ * Private private because it returns the value of the Value Length field,
165+ * which is not useful for the application.
131166 */
132- uint16_t GetValueLength () const
167+ virtual uint16_t GetLengthField () const final
133168 {
134- return uint16_t { ntohs ( this -> header -> length ) } - Chunk::HeaderLength ;
169+ return GetHeaderPointer ()-> length ;
135170 }
136171
137- private:
138- void SetSize (size_t size)
172+ virtual void SetLengthField (uint16_t length) final
139173 {
140- this -> size = size ;
174+ GetHeaderPointer ()-> length = length ;
141175 }
142-
143- private:
144- // Pointer to the data buffer containing the chunk.
145- uint8_t * data{ nullptr };
146- // Full size of the chunk in bytes.
147- size_t size{ 0u };
148- // Pointer to the Chunk Header (it points to `data` too).
149- Header* header{ nullptr };
150176 };
151177 } // namespace SCTP
152178} // namespace RTC
0 commit comments