blob: b2fe1d2c4546f53a1cfaddd427c19bcb75af099c [file] [log] [blame]
Harald Welteec8b4502010-02-20 20:34:29 +01001/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
Holger Hans Peter Freytheracffb602010-10-18 18:22:31 +02002 * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
Harald Welteec8b4502010-02-20 20:34:29 +01003 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 */
20
Harald Welteba6988b2011-08-17 12:46:48 +020021/*! \addtogroup msgb
22 * @{
23 */
24
25/*! \file msgb.c
26 */
Harald Welteec8b4502010-02-20 20:34:29 +010027
28#include <unistd.h>
29#include <string.h>
30#include <stdlib.h>
Harald Welteec8b4502010-02-20 20:34:29 +010031
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010032#include <osmocom/core/msgb.h>
Harald Welteec8b4502010-02-20 20:34:29 +010033//#include <openbsc/gsm_data.h>
Pablo Neira Ayuso83419342011-03-22 16:36:13 +010034#include <osmocom/core/talloc.h>
Harald Welteec8b4502010-02-20 20:34:29 +010035//#include <openbsc/debug.h>
36
37void *tall_msgb_ctx;
38
Harald Welteba6988b2011-08-17 12:46:48 +020039/*! \brief Allocate a new message buffer
40 * \param[in] size Length in octets, including headroom
41 * \param[in] name Human-readable name to be associated with msgb
42 *
43 * This function allocates a 'struct msgb' as well as the underlying
44 * memory buffer for the actual message data (size specified by \a size)
45 * using the talloc memory context previously set by \ref msgb_set_talloc_ctx
46 */
Harald Welteec8b4502010-02-20 20:34:29 +010047struct msgb *msgb_alloc(uint16_t size, const char *name)
48{
49 struct msgb *msg;
50
51 msg = _talloc_zero(tall_msgb_ctx, sizeof(*msg) + size, name);
52
53 if (!msg) {
54 //LOGP(DRSL, LOGL_FATAL, "unable to allocate msgb\n");
55 return NULL;
56 }
57
58 msg->data_len = size;
59 msg->len = 0;
60 msg->data = msg->_data;
Sylvain Munaut17a5a282010-02-24 22:57:46 +010061 msg->head = msg->_data;
62 msg->tail = msg->_data;
Harald Welteec8b4502010-02-20 20:34:29 +010063
64 return msg;
65}
66
Harald Welteba6988b2011-08-17 12:46:48 +020067/*! \brief Release given message buffer
68 * \param[in] m Message buffer to be free'd
69 */
Harald Welteec8b4502010-02-20 20:34:29 +010070void msgb_free(struct msgb *m)
71{
72 talloc_free(m);
73}
74
Harald Welteba6988b2011-08-17 12:46:48 +020075/*! \brief Enqueue message buffer to tail of a queue
76 * \param[in] queue linked list header of queue
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +010077 * \param[in] msg message buffer to be added to the queue
Harald Welteba6988b2011-08-17 12:46:48 +020078 *
79 * The function will append the specified message buffer \a msg to the
80 * queue implemented by \ref llist_head \a queue
81 */
Harald Welteec8b4502010-02-20 20:34:29 +010082void msgb_enqueue(struct llist_head *queue, struct msgb *msg)
83{
84 llist_add_tail(&msg->list, queue);
85}
86
Harald Welteba6988b2011-08-17 12:46:48 +020087/*! \brief Dequeue message buffer from head of queue
88 * \param[in] queue linked list header of queue
89 * \returns message buffer (if any) or NULL if queue empty
90 *
91 * The function will remove the first message buffer from the queue
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +010092 * implemented by \ref llist_head \a queue.
Harald Welteba6988b2011-08-17 12:46:48 +020093 */
Harald Welteec8b4502010-02-20 20:34:29 +010094struct msgb *msgb_dequeue(struct llist_head *queue)
95{
96 struct llist_head *lh;
97
98 if (llist_empty(queue))
99 return NULL;
100
101 lh = queue->next;
102 llist_del(lh);
103
104 return llist_entry(lh, struct msgb, list);
105}
106
Harald Welteba6988b2011-08-17 12:46:48 +0200107/*! \brief Re-set all message buffer pointers
Katerina Barone-Adesic28c6a02013-02-15 13:27:59 +0100108 * \param[in] msg message buffer that is to be resetted
Harald Welteba6988b2011-08-17 12:46:48 +0200109 *
110 * This will re-set the various internal pointers into the underlying
111 * message buffer, i.e. remvoe all headroom and treat the msgb as
112 * completely empty. It also initializes the control buffer to zero.
113 */
Harald Welteec8b4502010-02-20 20:34:29 +0100114void msgb_reset(struct msgb *msg)
115{
116 msg->len = 0;
Harald Welteec8b4502010-02-20 20:34:29 +0100117 msg->data = msg->_data;
Sylvain Munaut17a5a282010-02-24 22:57:46 +0100118 msg->head = msg->_data;
119 msg->tail = msg->_data;
Harald Welteec8b4502010-02-20 20:34:29 +0100120
Harald Welteec8b4502010-02-20 20:34:29 +0100121 msg->trx = NULL;
122 msg->lchan = NULL;
123 msg->l2h = NULL;
124 msg->l3h = NULL;
Harald Weltebb77c9d2010-04-30 14:26:12 +0200125 msg->l4h = NULL;
Harald Welte95df5c02010-05-01 23:53:26 +0200126
127 memset(&msg->cb, 0, sizeof(msg->cb));
Harald Welteec8b4502010-02-20 20:34:29 +0100128}
Holger Hans Peter Freytheracffb602010-10-18 18:22:31 +0200129
Harald Welteba6988b2011-08-17 12:46:48 +0200130/*! \brief get pointer to data section of message buffer
131 * \param[in] msg message buffer
132 * \returns pointer to data section of message buffer
133 */
Holger Hans Peter Freytheracffb602010-10-18 18:22:31 +0200134uint8_t *msgb_data(const struct msgb *msg)
135{
136 return msg->data;
137}
138
Harald Welteba6988b2011-08-17 12:46:48 +0200139/*! \brief get length of message buffer
140 * \param[in] msg message buffer
141 * \returns length of data section in message buffer
142 */
Holger Hans Peter Freytheracffb602010-10-18 18:22:31 +0200143uint16_t msgb_length(const struct msgb *msg)
144{
145 return msg->len;
146}
Harald Welte9e1f0602011-06-29 18:46:10 +0200147
Harald Welteba6988b2011-08-17 12:46:48 +0200148/*! \brief Set the talloc context for \ref msgb_alloc
149 * \param[in] ctx talloc context to be used as root for msgb allocations
150 */
Harald Welte9e1f0602011-06-29 18:46:10 +0200151void msgb_set_talloc_ctx(void *ctx)
152{
153 tall_msgb_ctx = ctx;
154}
Harald Welteba6988b2011-08-17 12:46:48 +0200155
Jacob Erlbeckbaa225e2014-02-28 15:14:40 +0100156/*! \brief Return a (static) buffer containing a hexdump of the msg
157 * \param[in] msg message buffer
158 * \returns a pointer to a static char array
159 */
160const char *msgb_hexdump(const struct msgb *msg)
161{
162 static char buf[4100];
163 int buf_offs = 0;
164 int nchars;
165 const unsigned char *start = msg->data;
166 const unsigned char *lxhs[4];
167 int i;
168
169 lxhs[0] = msg->l1h;
170 lxhs[1] = msg->l2h;
171 lxhs[2] = msg->l3h;
172 lxhs[3] = msg->l4h;
173
174 for (i = 0; i < ARRAY_SIZE(lxhs); i++) {
175 if (!lxhs[i])
176 continue;
177
178 if (lxhs[i] < msg->data)
179 goto out_of_range;
180 if (lxhs[i] > msg->tail)
181 goto out_of_range;
182 nchars = snprintf(buf + buf_offs, sizeof(buf) - buf_offs,
183 "%s[L%d]> ",
184 osmo_hexdump(start, lxhs[i] - start),
185 i+1);
186 if (nchars < 0 || nchars + buf_offs >= sizeof(buf))
187 return "ERROR";
188
189 buf_offs += nchars;
190 start = lxhs[i];
191 }
192 nchars = snprintf(buf + buf_offs, sizeof(buf) - buf_offs,
193 "%s", osmo_hexdump(start, msg->tail - start));
194 if (nchars < 0 || nchars + buf_offs >= sizeof(buf))
195 return "ERROR";
196
197 return buf;
198
199out_of_range:
200 nchars = snprintf(buf, sizeof(buf) - buf_offs,
201 "!!! L%d out of range", i+1);
202 return buf;
203}
204
Sylvain Munautdca7d2c2012-04-18 21:53:23 +0200205/*! @} */