libosmocore  0.6.3
Osmocom core library
msgb.h
Go to the documentation of this file.
1 #ifndef _MSGB_H
2 #define _MSGB_H
3 
4 /* (C) 2008 by Harald Welte <laforge@gnumonks.org>
5  * All Rights Reserved
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  */
22 
23 #include <stdint.h>
24 #include <osmocom/core/linuxlist.h>
25 #include <osmocom/core/utils.h>
26 
39 #define MSGB_DEBUG
40 
42 struct msgb {
43  struct llist_head list;
46  /* Part of which TRX logical channel we were received / transmitted */
47  /* FIXME: move them into the control buffer */
48  union {
49  void *dst;
50  struct gsm_bts_trx *trx;
51  };
52  struct gsm_lchan *lchan;
54  unsigned char *l1h;
55  unsigned char *l2h;
56  unsigned char *l3h;
57  unsigned char *l4h;
59  unsigned long cb[5];
61  uint16_t data_len;
62  uint16_t len;
64  unsigned char *head;
65  unsigned char *tail;
66  unsigned char *data;
67  unsigned char _data[0];
68 };
69 
70 extern struct msgb *msgb_alloc(uint16_t size, const char *name);
71 extern void msgb_free(struct msgb *m);
72 extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);
73 extern struct msgb *msgb_dequeue(struct llist_head *queue);
74 extern void msgb_reset(struct msgb *m);
75 uint16_t msgb_length(const struct msgb *msg);
76 
77 #ifdef MSGB_DEBUG
78 #include <osmocom/core/panic.h>
79 #define MSGB_ABORT(msg, fmt, args ...) do { \
80  osmo_panic("msgb(%p): " fmt, msg, ## args); \
81  } while(0)
82 #else
83 #define MSGB_ABORT(msg, fmt, args ...)
84 #endif
85 
87 #define msgb_l1(m) ((void *)(m->l1h))
88 
89 #define msgb_l2(m) ((void *)(m->l2h))
90 
91 #define msgb_l3(m) ((void *)(m->l3h))
92 
93 #define msgb_sms(m) ((void *)(m->l4h))
94 
102 static inline unsigned int msgb_l1len(const struct msgb *msgb)
103 {
104  return msgb->tail - (uint8_t *)msgb_l1(msgb);
105 }
106 
114 static inline unsigned int msgb_l2len(const struct msgb *msgb)
115 {
116  return msgb->tail - (uint8_t *)msgb_l2(msgb);
117 }
118 
126 static inline unsigned int msgb_l3len(const struct msgb *msgb)
127 {
128  return msgb->tail - (uint8_t *)msgb_l3(msgb);
129 }
130 
138 static inline unsigned int msgb_headlen(const struct msgb *msgb)
139 {
140  return msgb->len - msgb->data_len;
141 }
142 
150 static inline int msgb_tailroom(const struct msgb *msgb)
151 {
152  return (msgb->head + msgb->data_len) - msgb->tail;
153 }
154 
162 static inline int msgb_headroom(const struct msgb *msgb)
163 {
164  return (msgb->data - msgb->head);
165 }
166 
179 static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len)
180 {
181  unsigned char *tmp = msgb->tail;
182  if (msgb_tailroom(msgb) < (int) len)
183  MSGB_ABORT(msgb, "Not enough tailroom msgb_push (%u < %u)\n",
184  msgb_tailroom(msgb), len);
185  msgb->tail += len;
186  msgb->len += len;
187  return tmp;
188 }
189 
194 static inline void msgb_put_u8(struct msgb *msgb, uint8_t word)
195 {
196  uint8_t *space = msgb_put(msgb, 1);
197  space[0] = word & 0xFF;
198 }
199 
204 static inline void msgb_put_u16(struct msgb *msgb, uint16_t word)
205 {
206  uint8_t *space = msgb_put(msgb, 2);
207  space[0] = word >> 8 & 0xFF;
208  space[1] = word & 0xFF;
209 }
210 
215 static inline void msgb_put_u32(struct msgb *msgb, uint32_t word)
216 {
217  uint8_t *space = msgb_put(msgb, 4);
218  space[0] = word >> 24 & 0xFF;
219  space[1] = word >> 16 & 0xFF;
220  space[2] = word >> 8 & 0xFF;
221  space[3] = word & 0xFF;
222 }
223 
228 static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len)
229 {
230  unsigned char *tmp = msgb->data - len;
231  if (msgb_length(msgb) < len)
232  MSGB_ABORT(msgb, "msgb too small to get %u (len %u)\n",
233  len, msgb_length(msgb));
234  msgb->tail -= len;
235  msgb->len -= len;
236  return tmp;
237 }
242 static inline uint8_t msgb_get_u8(struct msgb *msgb)
243 {
244  uint8_t *space = msgb_get(msgb, 1);
245  return space[0];
246 }
251 static inline uint16_t msgb_get_u16(struct msgb *msgb)
252 {
253  uint8_t *space = msgb_get(msgb, 2);
254  return space[0] << 8 | space[1];
255 }
260 static inline uint32_t msgb_get_u32(struct msgb *msgb)
261 {
262  uint8_t *space = msgb_get(msgb, 4);
263  return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3];
264 }
265 
278 static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
279 {
280  if (msgb_headroom(msgb) < (int) len)
281  MSGB_ABORT(msgb, "Not enough headroom msgb_push (%u < %u)\n",
282  msgb_headroom(msgb), len);
283  msgb->data -= len;
284  msgb->len += len;
285  return msgb->data;
286 }
296 static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len)
297 {
298  msgb->len -= len;
299  return msgb->data += len;
300 }
301 
306 static inline uint8_t msgb_pull_u8(struct msgb *msgb)
307 {
308  uint8_t *space = msgb_pull(msgb, 1) - 1;
309  return space[0];
310 }
315 static inline uint16_t msgb_pull_u16(struct msgb *msgb)
316 {
317  uint8_t *space = msgb_pull(msgb, 2) - 2;
318  return space[0] << 8 | space[1];
319 }
324 static inline uint32_t msgb_pull_u32(struct msgb *msgb)
325 {
326  uint8_t *space = msgb_pull(msgb, 4) - 4;
327  return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3];
328 }
329 
341 static inline void msgb_reserve(struct msgb *msg, int len)
342 {
343  msg->data += len;
344  msg->tail += len;
345 }
346 
352 static inline int msgb_trim(struct msgb *msg, int len)
353 {
354  if (len > msg->data_len)
355  return -1;
356 
357  msg->len = len;
358  msg->tail = msg->data + len;
359 
360  return 0;
361 }
362 
368 static inline int msgb_l3trim(struct msgb *msg, int l3len)
369 {
370  return msgb_trim(msg, (msg->l3h - msg->data) + l3len);
371 }
372 
383 static inline struct msgb *msgb_alloc_headroom(int size, int headroom,
384  const char *name)
385 {
386  osmo_static_assert(size > headroom, headroom_bigger);
387 
388  struct msgb *msg = msgb_alloc(size, name);
389  if (msg)
390  msgb_reserve(msg, headroom);
391  return msg;
392 }
393 
394 /* non inline functions to ease binding */
395 
396 uint8_t *msgb_data(const struct msgb *msg);
397 void msgb_set_talloc_ctx(void *ctx);
398 
401 #endif /* _MSGB_H */