00001 /* 00002 * Copyright 2014,2016 Didier Barvaux 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00017 */ 00018 00019 /** 00020 * @file common/rohc_buf.h 00021 * @brief Define a network buffer for the ROHC library 00022 * @author Didier Barvaux <didier@barvaux.org> 00023 */ 00024 00025 #ifndef ROHC_BUF_H 00026 #define ROHC_BUF_H 00027 00028 #ifdef __cplusplus 00029 extern "C" 00030 { 00031 #endif 00032 00033 /** Macro that handles DLL export declarations gracefully */ 00034 #ifdef DLL_EXPORT /* passed by autotools on command line */ 00035 # define ROHC_EXPORT __declspec(dllexport) 00036 #else 00037 # define ROHC_EXPORT 00038 #endif 00039 00040 #include <rohc/rohc_time.h> /* for struct rohc_ts */ 00041 00042 #include <stdbool.h> 00043 #include <stdlib.h> 00044 #ifndef __KERNEL__ 00045 # include <string.h> 00046 #endif 00047 #include <assert.h> 00048 00049 00050 /** 00051 * @brief A network buffer for the ROHC library 00052 * 00053 * May represent one uncompressed packet, one ROHC packet, or a ROHC feedback. 00054 * 00055 * The network buffer does not contain the packet data itself. It only has 00056 * a pointer on it. This is designed this way for performance reasons: no copy 00057 * required to initialize a network buffer, the struct is small and may be 00058 * passed as copy to function. 00059 * 00060 * The network buffer is able to keep some free space at its beginning. The 00061 * unused space at the beginning of the buffer may be used to prepend a 00062 * network header at the very end of the packet handling. 00063 * 00064 * The beginning of the network buffer may also be shifted forward with the 00065 * \ref rohc_buf_pull function or shifted backward with the \ref rohc_buf_push 00066 * function. This is useful when parsing a network packet (once bytes are 00067 * read, shift them forward) for example. 00068 * 00069 * The network buffer may be initialized manually (see below) or with the 00070 * helper functions \ref rohc_buf_init_empty or \ref rohc_buf_init_full. 00071 * \code 00072 struct rohc_buf packet; 00073 ... 00074 packet.time.sec = 0; 00075 packet.time.nsec = 0; 00076 packet.max_len = 100; 00077 packet.data = malloc(packet.max_len); 00078 packet.offset = 2; 00079 packet.len = 2; 00080 packet[packet.offset] = 0x01; 00081 packet[packet.offset + 1] = 0x02; 00082 ... 00083 \endcode 00084 * 00085 * or as below: 00086 * \code 00087 struct rohc_buf packet; 00088 unsigned char input[100]; 00089 ... 00090 input[2] = 0x01; 00091 input[3] = 0x02; 00092 ... 00093 packet.time.sec = 0; 00094 packet.time.nsec = 0; 00095 packet.max_len = 100; 00096 packet.data = input; 00097 packet.offset = 2; 00098 packet.len = 2; 00099 ... 00100 \endcode 00101 * 00102 * @ingroup rohc 00103 */ 00104 struct rohc_buf 00105 { 00106 struct rohc_ts time; /**< The timestamp associated to the data */ 00107 uint8_t *data; /**< The buffer data */ 00108 size_t max_len; /**< The maximum length of the buffer */ 00109 size_t offset; /**< The offset for the beginning of the data */ 00110 size_t len; /**< The data length (in bytes) */ 00111 }; 00112 00113 00114 /** 00115 * @brief Initialize the given network buffer with no data 00116 * 00117 * This method is used to initialize an empty network buffer that will be used 00118 * to create a packet. For example, the ROHC packet for a compression 00119 * operation, or the uncompressed packet for a decompression operation. 00120 * 00121 * @param __data The packet data to point to 00122 * @param __max_len The maxmimum length (in bytes) of the packet data 00123 * 00124 * \par Example: 00125 * \code 00126 #define PKT_DATA_LEN 145U 00127 uint8_t pkt_data[PKT_DATA_LEN]; 00128 struct rohc_buf packet = rohc_buf_init_empty(pkt_data, PKT_DATA_LEN); 00129 \endcode 00130 * 00131 * @ingroup rohc 00132 */ 00133 #define rohc_buf_init_empty(__data, __max_len) \ 00134 { \ 00135 .time = { .sec = 0, .nsec = 0, }, \ 00136 .data = (__data), \ 00137 .max_len = (__max_len), \ 00138 .offset = 0, \ 00139 .len = 0, \ 00140 } 00141 00142 00143 /** 00144 * @brief Initialize the given network buffer with all its data 00145 * 00146 * This method is used to initialize a network buffer that will be used for 00147 * parsing only. For example, the uncompressed packet for a compression 00148 * operation, or the ROHC packet for a decompression operation. 00149 * 00150 * @param __data The packet data to point to 00151 * @param __len The maxmimum length (in bytes) of the packet data 00152 * @param __time The timestamp at which the packet was received/handled 00153 * 00154 * \par Example: 00155 * \code 00156 #define PKT_DATA_LEN 145U 00157 const uint8_t pkt_data[PKT_DATA_LEN]; 00158 const struct rohc_ts arrival_time = { .sec = 1399745625, .nsec = 42 }; 00159 const struct rohc_buf packet = 00160 rohc_buf_init_full(pkt_data, PKT_DATA_LEN, arrival_time); 00161 \endcode 00162 * 00163 * @ingroup rohc 00164 */ 00165 #define rohc_buf_init_full(__data, __len, __time) \ 00166 { \ 00167 .time = (__time), \ 00168 .data = (__data), \ 00169 .max_len = (__len), \ 00170 .offset = 0, \ 00171 .len = (__len), \ 00172 } 00173 00174 00175 /** 00176 * @brief Get the byte at the given offset in the given network buffer 00177 * 00178 * @param __buf The network buffer to get a byte from 00179 * @param __offset The offset to get bytes at 00180 * @return The byte stored in the network buffer at the offset 00181 * 00182 * @ingroup rohc 00183 */ 00184 #define rohc_buf_byte_at(__buf, __offset) \ 00185 ((__buf).data)[(__buf).offset + (__offset)] 00186 00187 00188 /** 00189 * @brief Get the next byte in the given network buffer 00190 * 00191 * @param __buf The network buffer to get the next byte from 00192 * @return The next byte stored in the network buffer 00193 * 00194 * @ingroup rohc 00195 */ 00196 #define rohc_buf_byte(__buf) \ 00197 rohc_buf_byte_at((__buf), 0) 00198 00199 00200 00201 static inline bool rohc_buf_is_malformed(const struct rohc_buf buf) 00202 __attribute__((warn_unused_result, pure)); 00203 00204 static inline bool rohc_buf_is_empty(const struct rohc_buf buf) 00205 __attribute__((warn_unused_result, const)); 00206 00207 static inline void rohc_buf_pull(struct rohc_buf *const buf, const size_t offset) 00208 __attribute__((nonnull(1))); 00209 static inline void rohc_buf_push(struct rohc_buf *const buf, const size_t offset) 00210 __attribute__((nonnull(1))); 00211 00212 static inline size_t rohc_buf_avail_len(const struct rohc_buf buf) 00213 __attribute__((warn_unused_result, const)); 00214 00215 static inline uint8_t * rohc_buf_data_at(const struct rohc_buf buf, 00216 const size_t offset) 00217 __attribute__((warn_unused_result, const)); 00218 static inline uint8_t * rohc_buf_data(const struct rohc_buf buf) 00219 __attribute__((warn_unused_result, const)); 00220 00221 static inline void rohc_buf_prepend(struct rohc_buf *const buf, 00222 const uint8_t *const data, 00223 const size_t len) 00224 __attribute__((nonnull(1, 2))); 00225 static inline void rohc_buf_append(struct rohc_buf *const buf, 00226 const uint8_t *const data, 00227 const size_t len) 00228 __attribute__((nonnull(1, 2))); 00229 static inline void rohc_buf_append_buf(struct rohc_buf *const dst, 00230 const struct rohc_buf src) 00231 __attribute__((nonnull(1))); 00232 00233 static inline void rohc_buf_reset(struct rohc_buf *const buf) 00234 __attribute__((nonnull(1))); 00235 00236 00237 /** 00238 * @brief Is the given network buffer malformed? 00239 * 00240 * @param buf The network buffer to check for 00241 * @return true if the given network is malformed, false if not 00242 * 00243 * @ingroup rohc 00244 */ 00245 static inline bool rohc_buf_is_malformed(const struct rohc_buf buf) 00246 { 00247 return (buf.data == NULL || 00248 buf.max_len == 0 || 00249 (buf.offset + buf.len) > buf.max_len); 00250 } 00251 00252 00253 /** 00254 * @brief Is the given network buffer empty? 00255 * 00256 * Empty means no data at all. 00257 * 00258 * @param buf The network buffer to check for 00259 * @return true if the given network is empty, false if not 00260 * 00261 * @ingroup rohc 00262 */ 00263 static inline bool rohc_buf_is_empty(const struct rohc_buf buf) 00264 { 00265 return (buf.len == 0); 00266 } 00267 00268 00269 /** 00270 * @brief Pull the beginning of the given network buffer 00271 * 00272 * Pulling the beginning of the buffer increases the space at the beginning 00273 * of the buffer. This is useful when parsing a network packet (once bytes 00274 * are read, pull them) for example. 00275 * 00276 * @param buf The network buffer to check for 00277 * @param offset The offset to pull the beginning of the buffer of 00278 * 00279 * @ingroup rohc 00280 */ 00281 static inline void rohc_buf_pull(struct rohc_buf *const buf, const size_t offset) 00282 { 00283 #if defined(ROHC_EXTRA_ASSERT) && ROHC_EXTRA_ASSERT == 1 00284 /* not enabled by default for perfs */ 00285 assert((buf->offset + offset) <= buf->max_len); 00286 assert(buf->len >= offset); 00287 #endif 00288 buf->offset += offset; 00289 buf->len -= offset; 00290 } 00291 00292 00293 /** 00294 * @brief Push the beginning of the given network buffer 00295 * 00296 * Pushing the beginning of the buffer decreases the space at the beginning 00297 * of the buffer. This is useful to prepend a network header before the 00298 * network buffer. 00299 * 00300 * @param buf The network buffer to check for 00301 * @param offset The offset to push the beginning of the buffer of 00302 * 00303 * @ingroup rohc 00304 */ 00305 static inline void rohc_buf_push(struct rohc_buf *const buf, const size_t offset) 00306 { 00307 #if defined(ROHC_EXTRA_ASSERT) && ROHC_EXTRA_ASSERT == 1 00308 /* not enabled by default for perfs */ 00309 assert(buf->offset >= offset); 00310 assert((buf->len + offset) <= buf->max_len); 00311 #endif 00312 buf->offset -= offset; 00313 buf->len += offset; 00314 } 00315 00316 00317 /** 00318 * @brief How many bytes the given network buffer may contain? 00319 * 00320 * @param buf The network buffer to check 00321 * @return The number of bytes one may write to the given network buffer 00322 * 00323 * @ingroup rohc 00324 */ 00325 static inline size_t rohc_buf_avail_len(const struct rohc_buf buf) 00326 { 00327 return (buf.max_len - buf.offset); 00328 } 00329 00330 00331 /** 00332 * @brief Get the bytes in the given network buffer 00333 * 00334 * This function is a shortcut for: 00335 * \code 00336 rohc_buf_data_at(buf, 0); 00337 \endcode 00338 * 00339 * @param buf The network buffer to get bytes from 00340 * @return The bytes stored in the network buffer 00341 * 00342 * @ingroup rohc 00343 */ 00344 static inline uint8_t * rohc_buf_data(const struct rohc_buf buf) 00345 { 00346 return rohc_buf_data_at(buf, 0); 00347 } 00348 00349 00350 /** 00351 * @brief Get the bytes at the given offset in the given network buffer 00352 * 00353 * @param buf The network buffer to get bytes from 00354 * @param offset The offset to get bytes at 00355 * @return The bytes stored in the network buffer at the offset 00356 * 00357 * @ingroup rohc 00358 */ 00359 static inline uint8_t * rohc_buf_data_at(const struct rohc_buf buf, 00360 const size_t offset) 00361 { 00362 return (buf.data + buf.offset + offset); 00363 } 00364 00365 00366 /** 00367 * @brief Add data at the beginning of the given network buffer 00368 * 00369 * @param buf The network buffer to prepend data to 00370 * @param data The data to prepend 00371 * @param len The length (in bytes) of the data to prepend 00372 * 00373 * @ingroup rohc 00374 */ 00375 static inline void rohc_buf_prepend(struct rohc_buf *const buf, 00376 const uint8_t *const data, 00377 const size_t len) 00378 { 00379 rohc_buf_push(buf, len); 00380 memcpy(rohc_buf_data(*buf), data, len); 00381 } 00382 00383 00384 /** 00385 * @brief Add data at the end of the given network buffer 00386 * 00387 * @param buf The network buffer to append data to 00388 * @param data The data to append 00389 * @param len The length (in bytes) of the data to append 00390 * 00391 * @ingroup rohc 00392 */ 00393 static inline void rohc_buf_append(struct rohc_buf *const buf, 00394 const uint8_t *const data, 00395 const size_t len) 00396 { 00397 #if defined(ROHC_EXTRA_ASSERT) && ROHC_EXTRA_ASSERT == 1 00398 /* not enabled by default for perfs */ 00399 assert((buf->len + len) <= rohc_buf_avail_len(*buf)); 00400 #endif 00401 memcpy(rohc_buf_data_at(*buf, buf->len), data, len); 00402 buf->len += len; 00403 } 00404 00405 00406 /** 00407 * @brief Add a network buffer at the end of the given network buffer 00408 * 00409 * @param dst The network buffer to append data to 00410 * @param src The network buffer to append data from 00411 * 00412 * @ingroup rohc 00413 */ 00414 static inline void rohc_buf_append_buf(struct rohc_buf *const dst, 00415 const struct rohc_buf src) 00416 { 00417 #if defined(ROHC_EXTRA_ASSERT) && ROHC_EXTRA_ASSERT == 1 00418 /* not enabled by default for perfs */ 00419 assert((dst->len + src.len) <= rohc_buf_avail_len(*dst)); 00420 #endif 00421 memcpy(rohc_buf_data_at(*dst, dst->len), rohc_buf_data(src), src.len); 00422 dst->len += src.len; 00423 } 00424 00425 00426 /** 00427 * @brief Reset the given network buffer 00428 * 00429 * @param buf The network buffer to remove all data from 00430 * 00431 * @ingroup rohc 00432 */ 00433 static inline void rohc_buf_reset(struct rohc_buf *const buf) 00434 { 00435 buf->len = 0; 00436 } 00437 00438 00439 #undef ROHC_EXPORT /* do not pollute outside this header */ 00440 00441 #ifdef __cplusplus 00442 } 00443 #endif 00444 00445 #endif /* ROHC_BUF_H */ 00446
1.6.1