@@ -186,33 +186,73 @@ class Packet : public PacketIP4 {
186186 inline Byte* tcp_data ()
187187 { return ip_data () + tcp_header_length (); }
188188
189+ inline const Byte* tcp_data () const
190+ { return ip_data () + tcp_header_length (); }
191+
189192 // Length of data in packet when header has been accounted for
190193 inline uint16_t tcp_data_length () const
191194 { return ip_data_length () - tcp_header_length (); }
192195
193196 inline bool has_tcp_data () const
194197 { return tcp_data_length () > 0 ; }
195198
196- template <typename T, typename ... Args>
199+ /* *
200+ * @brief Adds a tcp option.
201+ *
202+ * @todo It's probably a better idea to make the option include
203+ * the padding for it to be aligned, and avoid two mem operations
204+ *
205+ * @tparam T TCP Option
206+ * @tparam Padding padding in bytes to be put infront of the option
207+ * @tparam Args construction args to option T
208+ */
209+ template <typename T, int Padding = 0 , typename ... Args>
197210 inline void add_tcp_option (Args&&... args) {
198211 // to avoid headache, options need to be added BEFORE any data.
199212 assert (!has_tcp_data ());
213+ struct NOP {
214+ uint8_t kind{0x01 };
215+ };
200216 // option address
201217 auto * addr = tcp_options ()+tcp_options_length ();
202- // emplace the option
203- const auto & opt = *(new (addr) T (args...));
218+ // if to use pre padding
219+ if (Padding)
220+ new (addr) NOP[Padding];
221+
222+ // emplace the option after pre padding
223+ const auto & opt = *(new (addr + Padding) T (args...));
204224
205225 // find number of NOP to pad with
206- const auto nops = opt.length % 4 ;
226+ const auto nops = ( opt.length + Padding) % 4 ;
207227 if (nops) {
208- struct NOP {
209- uint8_t kind{0x01 };
210- };
211- new (addr + opt.length ) NOP[nops];
228+ new (addr + Padding + opt.length ) NOP[nops];
212229 }
213230
214231 // update offset
215- set_offset (offset () + round_up (opt.length , 4 ));
232+ set_offset (offset () + round_up (opt.length + Padding, 4 ));
233+
234+ set_length (); // update
235+ }
236+
237+ /* *
238+ * @brief Adds a tcp option aligned.
239+ * Assumes the user knows what he's doing.
240+ *
241+ * @tparam T An aligned TCP option
242+ * @tparam Args construction args to option T
243+ */
244+ template <typename T, typename ... Args>
245+ inline void add_tcp_option_aligned (Args&&... args) {
246+ // to avoid headache, options need to be added BEFORE any data.
247+ Expects (!has_tcp_data () and sizeof (T) % 4 == 0 );
248+
249+ // option address
250+ auto * addr = tcp_options ()+tcp_options_length ();
251+ // emplace the option
252+ new (addr) T (args...);
253+
254+ // update offset
255+ set_offset (offset () + (sizeof (T) / 4 ));
216256
217257 set_length (); // update
218258 }
@@ -228,6 +268,9 @@ class Packet : public PacketIP4 {
228268 inline uint8_t * tcp_options ()
229269 { return (uint8_t *) tcp_header ().options ; }
230270
271+ inline const uint8_t * tcp_options () const
272+ { return (const uint8_t *) tcp_header ().options ; }
273+
231274 inline uint8_t tcp_options_length () const
232275 { return tcp_header_length () - sizeof (Header); }
233276
0 commit comments