ROHC compression/decompression library
rohc_buf.h
Go to the documentation of this file.
1 /*
2  * Copyright 2014,2016 Didier Barvaux
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /**
20  * @file common/rohc_buf.h
21  * @brief Define a network buffer for the ROHC library
22  * @author Didier Barvaux <didier@barvaux.org>
23  */
24 
25 #ifndef ROHC_BUF_H
26 #define ROHC_BUF_H
27 
28 #ifdef __cplusplus
29 extern "C"
30 {
31 #endif
32 
33 /** Macro that handles DLL export declarations gracefully */
34 #ifdef DLL_EXPORT /* passed by autotools on command line */
35 # define ROHC_EXPORT __declspec(dllexport)
36 #else
37 # define ROHC_EXPORT
38 #endif
39 
40 #include <rohc/rohc_time.h> /* for struct rohc_ts */
41 
42 #include <stdbool.h>
43 #include <stdlib.h>
44 #ifndef __KERNEL__
45 # include <string.h>
46 #endif
47 #include <assert.h>
48 
49 
50 /**
51  * @brief A network buffer for the ROHC library
52  *
53  * May represent one uncompressed packet, one ROHC packet, or a ROHC feedback.
54  *
55  * The network buffer does not contain the packet data itself. It only has
56  * a pointer on it. This is designed this way for performance reasons: no copy
57  * required to initialize a network buffer, the struct is small and may be
58  * passed as copy to function.
59  *
60  * The network buffer is able to keep some free space at its beginning. The
61  * unused space at the beginning of the buffer may be used to prepend a
62  * network header at the very end of the packet handling.
63  *
64  * The beginning of the network buffer may also be shifted forward with the
65  * \ref rohc_buf_pull function or shifted backward with the \ref rohc_buf_push
66  * function. This is useful when parsing a network packet (once bytes are
67  * read, shift them forward) for example.
68  *
69  * The network buffer may be initialized manually (see below) or with the
70  * helper functions \ref rohc_buf_init_empty or \ref rohc_buf_init_full.
71  * \code
72  struct rohc_buf packet;
73  ...
74  packet.time.sec = 0;
75  packet.time.nsec = 0;
76  packet.max_len = 100;
77  packet.data = malloc(packet.max_len);
78  packet.offset = 2;
79  packet.len = 2;
80  packet[packet.offset] = 0x01;
81  packet[packet.offset + 1] = 0x02;
82  ...
83 \endcode
84  *
85  * or as below:
86  * \code
87  struct rohc_buf packet;
88  unsigned char input[100];
89  ...
90  input[2] = 0x01;
91  input[3] = 0x02;
92  ...
93  packet.time.sec = 0;
94  packet.time.nsec = 0;
95  packet.max_len = 100;
96  packet.data = input;
97  packet.offset = 2;
98  packet.len = 2;
99  ...
100 \endcode
101  *
102  * @ingroup rohc
103  */
104 struct rohc_buf
105 {
106  struct rohc_ts time; /**< The timestamp associated to the data */
107  uint8_t *data; /**< The buffer data */
108  size_t max_len; /**< The maximum length of the buffer */
109  size_t offset; /**< The offset for the beginning of the data */
110  size_t len; /**< The data length (in bytes) */
111 };
112 
113 
114 /**
115  * @brief Initialize the given network buffer with no data
116  *
117  * This method is used to initialize an empty network buffer that will be used
118  * to create a packet. For example, the ROHC packet for a compression
119  * operation, or the uncompressed packet for a decompression operation.
120  *
121  * @param __data The packet data to point to
122  * @param __max_len The maxmimum length (in bytes) of the packet data
123  *
124  * \par Example:
125  * \code
126  #define PKT_DATA_LEN 145U
127  uint8_t pkt_data[PKT_DATA_LEN];
128  struct rohc_buf packet = rohc_buf_init_empty(pkt_data, PKT_DATA_LEN);
129 \endcode
130  *
131  * @ingroup rohc
132  */
133 #define rohc_buf_init_empty(__data, __max_len) \
134  { \
135  .time = { .sec = 0, .nsec = 0, }, \
136  .data = (__data), \
137  .max_len = (__max_len), \
138  .offset = 0, \
139  .len = 0, \
140  }
141 
142 
143 /**
144  * @brief Initialize the given network buffer with all its data
145  *
146  * This method is used to initialize a network buffer that will be used for
147  * parsing only. For example, the uncompressed packet for a compression
148  * operation, or the ROHC packet for a decompression operation.
149  *
150  * @param __data The packet data to point to
151  * @param __len The maxmimum length (in bytes) of the packet data
152  * @param __time The timestamp at which the packet was received/handled
153  *
154  * \par Example:
155  * \code
156  #define PKT_DATA_LEN 145U
157  const uint8_t pkt_data[PKT_DATA_LEN];
158  const struct rohc_ts arrival_time = { .sec = 1399745625, .nsec = 42 };
159  const struct rohc_buf packet =
160  rohc_buf_init_full(pkt_data, PKT_DATA_LEN, arrival_time);
161 \endcode
162  *
163  * @ingroup rohc
164  */
165 #define rohc_buf_init_full(__data, __len, __time) \
166  { \
167  .time = (__time), \
168  .data = (__data), \
169  .max_len = (__len), \
170  .offset = 0, \
171  .len = (__len), \
172  }
173 
174 
175 /**
176  * @brief Get the byte at the given offset in the given network buffer
177  *
178  * @param __buf The network buffer to get a byte from
179  * @param __offset The offset to get bytes at
180  * @return The byte stored in the network buffer at the offset
181  *
182  * @ingroup rohc
183  */
184 #define rohc_buf_byte_at(__buf, __offset) \
185  ((__buf).data)[(__buf).offset + (__offset)]
186 
187 
188 /**
189  * @brief Get the next byte in the given network buffer
190  *
191  * @param __buf The network buffer to get the next byte from
192  * @return The next byte stored in the network buffer
193  *
194  * @ingroup rohc
195  */
196 #define rohc_buf_byte(__buf) \
197  rohc_buf_byte_at((__buf), 0)
198 
199 
200 
201 static inline bool rohc_buf_is_malformed(const struct rohc_buf buf)
202  __attribute__((warn_unused_result, pure));
203 
204 static inline bool rohc_buf_is_empty(const struct rohc_buf buf)
205  __attribute__((warn_unused_result, const));
206 
207 static inline void rohc_buf_pull(struct rohc_buf *const buf, const size_t offset)
208  __attribute__((nonnull(1)));
209 static inline void rohc_buf_push(struct rohc_buf *const buf, const size_t offset)
210  __attribute__((nonnull(1)));
211 
212 static inline size_t rohc_buf_avail_len(const struct rohc_buf buf)
213  __attribute__((warn_unused_result, const));
214 
215 static inline uint8_t * rohc_buf_data_at(const struct rohc_buf buf,
216  const size_t offset)
217  __attribute__((warn_unused_result, const));
218 static inline uint8_t * rohc_buf_data(const struct rohc_buf buf)
219  __attribute__((warn_unused_result, const));
220 
221 static inline void rohc_buf_prepend(struct rohc_buf *const buf,
222  const uint8_t *const data,
223  const size_t len)
224  __attribute__((nonnull(1, 2)));
225 static inline void rohc_buf_append(struct rohc_buf *const buf,
226  const uint8_t *const data,
227  const size_t len)
228  __attribute__((nonnull(1, 2)));
229 static inline void rohc_buf_append_buf(struct rohc_buf *const dst,
230  const struct rohc_buf src)
231  __attribute__((nonnull(1)));
232 
233 static inline void rohc_buf_reset(struct rohc_buf *const buf)
234  __attribute__((nonnull(1)));
235 
236 
237 /**
238  * @brief Is the given network buffer malformed?
239  *
240  * @param buf The network buffer to check for
241  * @return true if the given network is malformed, false if not
242  *
243  * @ingroup rohc
244  */
245 static inline bool rohc_buf_is_malformed(const struct rohc_buf buf)
246 {
247  return (buf.data == NULL ||
248  buf.max_len == 0 ||
249  (buf.offset + buf.len) > buf.max_len);
250 }
251 
252 
253 /**
254  * @brief Is the given network buffer empty?
255  *
256  * Empty means no data at all.
257  *
258  * @param buf The network buffer to check for
259  * @return true if the given network is empty, false if not
260  *
261  * @ingroup rohc
262  */
263 static inline bool rohc_buf_is_empty(const struct rohc_buf buf)
264 {
265  return (buf.len == 0);
266 }
267 
268 
269 /**
270  * @brief Pull the beginning of the given network buffer
271  *
272  * Pulling the beginning of the buffer increases the space at the beginning
273  * of the buffer. This is useful when parsing a network packet (once bytes
274  * are read, pull them) for example.
275  *
276  * @param buf The network buffer to check for
277  * @param offset The offset to pull the beginning of the buffer of
278  *
279  * @ingroup rohc
280  */
281 static inline void rohc_buf_pull(struct rohc_buf *const buf, const size_t offset)
282 {
283 #if defined(ROHC_EXTRA_ASSERT) && ROHC_EXTRA_ASSERT == 1
284  /* not enabled by default for perfs */
285  assert((buf->offset + offset) <= buf->max_len);
286  assert(buf->len >= offset);
287 #endif
288  buf->offset += offset;
289  buf->len -= offset;
290 }
291 
292 
293 /**
294  * @brief Push the beginning of the given network buffer
295  *
296  * Pushing the beginning of the buffer decreases the space at the beginning
297  * of the buffer. This is useful to prepend a network header before the
298  * network buffer.
299  *
300  * @param buf The network buffer to check for
301  * @param offset The offset to push the beginning of the buffer of
302  *
303  * @ingroup rohc
304  */
305 static inline void rohc_buf_push(struct rohc_buf *const buf, const size_t offset)
306 {
307 #if defined(ROHC_EXTRA_ASSERT) && ROHC_EXTRA_ASSERT == 1
308  /* not enabled by default for perfs */
309  assert(buf->offset >= offset);
310  assert((buf->len + offset) <= buf->max_len);
311 #endif
312  buf->offset -= offset;
313  buf->len += offset;
314 }
315 
316 
317 /**
318  * @brief How many bytes the given network buffer may contain?
319  *
320  * @param buf The network buffer to check
321  * @return The number of bytes one may write to the given network buffer
322  *
323  * @ingroup rohc
324  */
325 static inline size_t rohc_buf_avail_len(const struct rohc_buf buf)
326 {
327  return (buf.max_len - buf.offset);
328 }
329 
330 
331 /**
332  * @brief Get the bytes in the given network buffer
333  *
334  * This function is a shortcut for:
335  * \code
336  rohc_buf_data_at(buf, 0);
337 \endcode
338  *
339  * @param buf The network buffer to get bytes from
340  * @return The bytes stored in the network buffer
341  *
342  * @ingroup rohc
343  */
344 static inline uint8_t * rohc_buf_data(const struct rohc_buf buf)
345 {
346  return rohc_buf_data_at(buf, 0);
347 }
348 
349 
350 /**
351  * @brief Get the bytes at the given offset in the given network buffer
352  *
353  * @param buf The network buffer to get bytes from
354  * @param offset The offset to get bytes at
355  * @return The bytes stored in the network buffer at the offset
356  *
357  * @ingroup rohc
358  */
359 static inline uint8_t * rohc_buf_data_at(const struct rohc_buf buf,
360  const size_t offset)
361 {
362  return (buf.data + buf.offset + offset);
363 }
364 
365 
366 /**
367  * @brief Add data at the beginning of the given network buffer
368  *
369  * @param buf The network buffer to prepend data to
370  * @param data The data to prepend
371  * @param len The length (in bytes) of the data to prepend
372  *
373  * @ingroup rohc
374  */
375 static inline void rohc_buf_prepend(struct rohc_buf *const buf,
376  const uint8_t *const data,
377  const size_t len)
378 {
379  rohc_buf_push(buf, len);
380  memcpy(rohc_buf_data(*buf), data, len);
381 }
382 
383 
384 /**
385  * @brief Add data at the end of the given network buffer
386  *
387  * @param buf The network buffer to append data to
388  * @param data The data to append
389  * @param len The length (in bytes) of the data to append
390  *
391  * @ingroup rohc
392  */
393 static inline void rohc_buf_append(struct rohc_buf *const buf,
394  const uint8_t *const data,
395  const size_t len)
396 {
397 #if defined(ROHC_EXTRA_ASSERT) && ROHC_EXTRA_ASSERT == 1
398  /* not enabled by default for perfs */
399  assert((buf->len + len) <= rohc_buf_avail_len(*buf));
400 #endif
401  memcpy(rohc_buf_data_at(*buf, buf->len), data, len);
402  buf->len += len;
403 }
404 
405 
406 /**
407  * @brief Add a network buffer at the end of the given network buffer
408  *
409  * @param dst The network buffer to append data to
410  * @param src The network buffer to append data from
411  *
412  * @ingroup rohc
413  */
414 static inline void rohc_buf_append_buf(struct rohc_buf *const dst,
415  const struct rohc_buf src)
416 {
417 #if defined(ROHC_EXTRA_ASSERT) && ROHC_EXTRA_ASSERT == 1
418  /* not enabled by default for perfs */
419  assert((dst->len + src.len) <= rohc_buf_avail_len(*dst));
420 #endif
421  memcpy(rohc_buf_data_at(*dst, dst->len), rohc_buf_data(src), src.len);
422  dst->len += src.len;
423 }
424 
425 
426 /**
427  * @brief Reset the given network buffer
428  *
429  * @param buf The network buffer to remove all data from
430  *
431  * @ingroup rohc
432  */
433 static inline void rohc_buf_reset(struct rohc_buf *const buf)
434 {
435  buf->len = 0;
436 }
437 
438 
439 #undef ROHC_EXPORT /* do not pollute outside this header */
440 
441 #ifdef __cplusplus
442 }
443 #endif
444 
445 #endif /* ROHC_BUF_H */
446 
static uint8_t * rohc_buf_data(const struct rohc_buf buf)
Get the bytes in the given network buffer.
Definition: rohc_buf.h:344
static void rohc_buf_append(struct rohc_buf *const buf, const uint8_t *const data, const size_t len)
Add data at the end of the given network buffer.
Definition: rohc_buf.h:393
static void rohc_buf_prepend(struct rohc_buf *const buf, const uint8_t *const data, const size_t len)
Add data at the beginning of the given network buffer.
Definition: rohc_buf.h:375
size_t offset
Definition: rohc_buf.h:109
size_t len
Definition: rohc_buf.h:110
static uint8_t * rohc_buf_data_at(const struct rohc_buf buf, const size_t offset)
Get the bytes at the given offset in the given network buffer.
Definition: rohc_buf.h:359
struct rohc_ts time
Definition: rohc_buf.h:106
uint8_t * data
Definition: rohc_buf.h:107
static void rohc_buf_reset(struct rohc_buf *const buf)
Reset the given network buffer.
Definition: rohc_buf.h:433
static bool rohc_buf_is_empty(const struct rohc_buf buf)
Is the given network buffer empty?
Definition: rohc_buf.h:263
static void rohc_buf_push(struct rohc_buf *const buf, const size_t offset)
Push the beginning of the given network buffer.
Definition: rohc_buf.h:305
static size_t rohc_buf_avail_len(const struct rohc_buf buf)
How many bytes the given network buffer may contain?
Definition: rohc_buf.h:325
A network buffer for the ROHC library.
Definition: rohc_buf.h:104
A timestamp for the ROHC library.
Definition: rohc_time.h:51
size_t max_len
Definition: rohc_buf.h:108
static void rohc_buf_append_buf(struct rohc_buf *const dst, const struct rohc_buf src)
Add a network buffer at the end of the given network buffer.
Definition: rohc_buf.h:414
static void rohc_buf_pull(struct rohc_buf *const buf, const size_t offset)
Pull the beginning of the given network buffer.
Definition: rohc_buf.h:281
static bool rohc_buf_is_malformed(const struct rohc_buf buf)
Is the given network buffer malformed?
Definition: rohc_buf.h:245