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