libosmocore  0.9.3
Osmocom core library
include/osmocom/core/msgb.h
Go to the documentation of this file.
00001 #pragma once
00002 
00003 /* (C) 2008 by Harald Welte <laforge@gnumonks.org>
00004  * All Rights Reserved
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00019  *
00020  */
00021 
00022 #include <stdint.h>
00023 #include <osmocom/core/linuxlist.h>
00024 #include <osmocom/core/utils.h>
00025 #include <osmocom/core/bits.h>
00026 
00039 #define MSGB_DEBUG
00040 
00042 struct msgb {
00043         struct llist_head list; 
00046         /* Part of which TRX logical channel we were received / transmitted */
00047         /* FIXME: move them into the control buffer */
00048         union {
00049                 void *dst; 
00050                 struct gsm_bts_trx *trx;
00051         };
00052         struct gsm_lchan *lchan; 
00054         unsigned char *l1h; 
00055         unsigned char *l2h; 
00056         unsigned char *l3h; 
00057         unsigned char *l4h; 
00059         unsigned long cb[5]; 
00061         uint16_t data_len;   
00062         uint16_t len;        
00064         unsigned char *head;    
00065         unsigned char *tail;    
00066         unsigned char *data;    
00067         unsigned char _data[0]; 
00068 };
00069 
00070 extern struct msgb *msgb_alloc(uint16_t size, const char *name);
00071 extern void msgb_free(struct msgb *m);
00072 extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);
00073 extern struct msgb *msgb_dequeue(struct llist_head *queue);
00074 extern void msgb_reset(struct msgb *m);
00075 uint16_t msgb_length(const struct msgb *msg);
00076 extern const char *msgb_hexdump(const struct msgb *msg);
00077 
00078 #ifdef MSGB_DEBUG
00079 #include <osmocom/core/panic.h>
00080 #define MSGB_ABORT(msg, fmt, args ...) do {             \
00081         osmo_panic("msgb(%p): " fmt, msg, ## args);     \
00082         } while(0)
00083 #else
00084 #define MSGB_ABORT(msg, fmt, args ...)
00085 #endif
00086 
00088 #define msgb_l1(m)      ((void *)(m->l1h))
00089 
00090 #define msgb_l2(m)      ((void *)(m->l2h))
00091 
00092 #define msgb_l3(m)      ((void *)(m->l3h))
00093 
00094 #define msgb_sms(m)     ((void *)(m->l4h))
00095 
00103 static inline unsigned int msgb_l1len(const struct msgb *msgb)
00104 {
00105         return msgb->tail - (uint8_t *)msgb_l1(msgb);
00106 }
00107 
00115 static inline unsigned int msgb_l2len(const struct msgb *msgb)
00116 {
00117         return msgb->tail - (uint8_t *)msgb_l2(msgb);
00118 }
00119 
00127 static inline unsigned int msgb_l3len(const struct msgb *msgb)
00128 {
00129         return msgb->tail - (uint8_t *)msgb_l3(msgb);
00130 }
00131 
00139 static inline unsigned int msgb_headlen(const struct msgb *msgb)
00140 {
00141         return msgb->len - msgb->data_len;
00142 }
00143 
00151 static inline int msgb_tailroom(const struct msgb *msgb)
00152 {
00153         return (msgb->head + msgb->data_len) - msgb->tail;
00154 }
00155 
00163 static inline int msgb_headroom(const struct msgb *msgb)
00164 {
00165         return (msgb->data - msgb->head);
00166 }
00167 
00180 static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len)
00181 {
00182         unsigned char *tmp = msgb->tail;
00183         if (msgb_tailroom(msgb) < (int) len)
00184                 MSGB_ABORT(msgb, "Not enough tailroom msgb_push (%u < %u)\n",
00185                            msgb_tailroom(msgb), len);
00186         msgb->tail += len;
00187         msgb->len += len;
00188         return tmp;
00189 }
00190 
00195 static inline void msgb_put_u8(struct msgb *msgb, uint8_t word)
00196 {
00197         uint8_t *space = msgb_put(msgb, 1);
00198         space[0] = word & 0xFF;
00199 }
00200 
00205 static inline void msgb_put_u16(struct msgb *msgb, uint16_t word)
00206 {
00207         uint8_t *space = msgb_put(msgb, 2);
00208         osmo_store16be(word, space);
00209 }
00210 
00215 static inline void msgb_put_u32(struct msgb *msgb, uint32_t word)
00216 {
00217         uint8_t *space = msgb_put(msgb, 4);
00218         osmo_store32be(word, space);
00219 }
00220 
00225 static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len)
00226 {
00227         unsigned char *tmp = msgb->tail - len;
00228         if (msgb_length(msgb) < len)
00229                 MSGB_ABORT(msgb, "msgb too small to get %u (len %u)\n",
00230                            len, msgb_length(msgb));
00231         msgb->tail -= len;
00232         msgb->len -= len;
00233         return tmp;
00234 }
00235 
00240 static inline uint8_t msgb_get_u8(struct msgb *msgb)
00241 {
00242         uint8_t *space = msgb_get(msgb, 1);
00243         return space[0];
00244 }
00245 
00250 static inline uint16_t msgb_get_u16(struct msgb *msgb)
00251 {
00252         uint8_t *space = msgb_get(msgb, 2);
00253         return osmo_load16be(space);
00254 }
00255 
00260 static inline uint32_t msgb_get_u32(struct msgb *msgb)
00261 {
00262         uint8_t *space = msgb_get(msgb, 4);
00263         return osmo_load32be(space);
00264 }
00265 
00278 static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
00279 {
00280         if (msgb_headroom(msgb) < (int) len)
00281                 MSGB_ABORT(msgb, "Not enough headroom msgb_push (%u < %u)\n",
00282                            msgb_headroom(msgb), len);
00283         msgb->data -= len;
00284         msgb->len += len;
00285         return msgb->data;
00286 }
00287 
00297 static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len)
00298 {
00299         msgb->len -= len;
00300         return msgb->data += len;
00301 }
00302 
00311 static inline unsigned char *msgb_pull_to_l3(struct msgb *msg)
00312 {
00313         unsigned char *ret = msgb_pull(msg, msg->l3h - msg->data);
00314         msg->l1h = msg->l2h = NULL;
00315         return ret;
00316 }
00317 
00322 static inline uint8_t msgb_pull_u8(struct msgb *msgb)
00323 {
00324         uint8_t *space = msgb_pull(msgb, 1) - 1;
00325         return space[0];
00326 }
00327 
00332 static inline uint16_t msgb_pull_u16(struct msgb *msgb)
00333 {
00334         uint8_t *space = msgb_pull(msgb, 2) - 2;
00335         return osmo_load16be(space);
00336 }
00337 
00342 static inline uint32_t msgb_pull_u32(struct msgb *msgb)
00343 {
00344         uint8_t *space = msgb_pull(msgb, 4) - 4;
00345         return osmo_load32be(space);
00346 }
00347 
00359 static inline void msgb_reserve(struct msgb *msg, int len)
00360 {
00361         msg->data += len;
00362         msg->tail += len;
00363 }
00364 
00370 static inline int msgb_trim(struct msgb *msg, int len)
00371 {
00372         if (len > msg->data_len)
00373                 return -1;
00374 
00375         msg->len = len;
00376         msg->tail = msg->data + len;
00377 
00378         return 0;
00379 }
00380 
00386 static inline int msgb_l3trim(struct msgb *msg, int l3len)
00387 {
00388         return msgb_trim(msg, (msg->l3h - msg->data) + l3len);
00389 }
00390 
00401 static inline struct msgb *msgb_alloc_headroom(int size, int headroom,
00402                                                 const char *name)
00403 {
00404         osmo_static_assert(size > headroom, headroom_bigger);
00405 
00406         struct msgb *msg = msgb_alloc(size, name);
00407         if (msg)
00408                 msgb_reserve(msg, headroom);
00409         return msg;
00410 }
00411 
00412 /* non inline functions to ease binding */
00413 
00414 uint8_t *msgb_data(const struct msgb *msg);
00415 void msgb_set_talloc_ctx(void *ctx);
00416