Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
msg.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * msg.c - manipulate messages
59  *
60  * This file contains implementations of the functions that create, destroy,
61  * pack, and unpack messages.
62  *
63  * Lars Wirzenius <liw@wapit.com>
64  */
65 
66 #include <errno.h>
67 #include <stdlib.h>
68 #include <sys/types.h>
69 #include <netinet/in.h>
70 
71 #include "msg.h"
72 #include "gwlib/gwlib.h"
73 
74 /**********************************************************************
75  * Prototypes for private functions.
76  */
77 
78 static void append_integer(Octstr *os, long i);
79 static void append_string(Octstr *os, Octstr *field);
80 static void append_uuid(Octstr *os, uuid_t id);
81 
82 static int parse_integer(long *i, Octstr *packed, int *off);
83 static int parse_string(Octstr **os, Octstr *packed, int *off);
84 static int parse_uuid(uuid_t id, Octstr *packed, int *off);
85 
86 static char *type_as_str(Msg *msg);
87 
88 
89 /**********************************************************************
90  * Implementations of the exported functions.
91  */
92 
93 Msg *msg_create_real(enum msg_type type, const char *file, long line,
94  const char *func)
95 {
96  Msg *msg;
97 
98  msg = gw_malloc_trace(sizeof(Msg), file, line, func);
99 
100  msg->type = type;
101 #define INTEGER(name) p->name = MSG_PARAM_UNDEFINED;
102 #define OCTSTR(name) p->name = NULL;
103 #define UUID(name) uuid_generate(p->name);
104 #define VOID(name) p->name = NULL;
105 #define MSG(type, stmt) { struct type *p = &msg->type; stmt }
106 #include "msg-decl.h"
107 
108  return msg;
109 }
110 
112 {
113  Msg *new;
114 
115  new = msg_create(msg->type);
116 
117 #define INTEGER(name) p->name = q->name;
118 #define OCTSTR(name) \
119  if (q->name == NULL) p->name = NULL; \
120  else p->name = octstr_duplicate(q->name);
121 #define UUID(name) uuid_copy(p->name, q->name);
122 #define VOID(name) p->name = q->name;
123 #define MSG(type, stmt) { \
124  struct type *p = &new->type; \
125  struct type *q = &msg->type; \
126  stmt }
127 #include "msg-decl.h"
128 
129  return new;
130 }
131 
133 {
134  if (msg == NULL)
135  return;
136 
137 #define INTEGER(name) p->name = 0;
138 #define OCTSTR(name) octstr_destroy(p->name);
139 #define UUID(name) uuid_clear(p->name);
140 #define VOID(name)
141 #define MSG(type, stmt) { struct type *p = &msg->type; stmt }
142 #include "msg-decl.h"
143 
144  gw_free(msg);
145 }
146 
148 {
149  msg_destroy(msg);
150 }
151 
152 void msg_dump(Msg *msg, int level)
153 {
154  char buf[UUID_STR_LEN + 1];
155 
156  debug("gw.msg", 0, "%*sMsg object at %p:", level, "", (void *) msg);
157  debug("gw.msg", 0, "%*s type: %s", level, "", type_as_str(msg));
158 #define INTEGER(name) \
159  debug("gw.msg", 0, "%*s %s.%s: %ld", level, "", t, #name, (long) p->name);
160 #define OCTSTR(name) \
161  debug("gw.msg", 0, "%*s %s.%s:", level, "", t, #name); \
162  octstr_dump(p->name, level + 1);
163 #define UUID(name) \
164  uuid_unparse(p->name, buf); \
165  debug("gw.msg", 0 , "%*s %s.%s: %s", level, "", t, #name, buf);
166 #define VOID(name) \
167  debug("gw.msg", 0, "%*s %s.%s: %p", level, "", t, #name, p->name);
168 #define MSG(tt, stmt) \
169  if (tt == msg->type) \
170  { char *t = #tt; struct tt *p = &msg->tt; stmt }
171 #include "msg-decl.h"
172  debug("gw.msg", 0, "Msg object ends.");
173 }
174 
175 
177 {
178  return msg->type;
179 }
180 
182 {
183  Octstr *os;
184 
185  os = octstr_create("");
186  append_integer(os, msg->type);
187 
188 #define INTEGER(name) append_integer(os, p->name);
189 #define OCTSTR(name) append_string(os, p->name);
190 #define UUID(name) append_uuid(os, p->name);
191 #define VOID(name)
192 #define MSG(type, stmt) \
193  case type: { struct type *p = &msg->type; stmt } break;
194 
195  switch (msg->type) {
196 #include "msg-decl.h"
197  default:
198  panic(0, "Internal error: unknown message type: %d",
199  msg->type);
200  }
201 
202  return os;
203 }
204 
205 
206 Msg *msg_unpack_real(Octstr *os, const char *file, long line, const char *func)
207 {
208  Msg *msg;
209  int off;
210  long i;
211 
212  msg = msg_create_real(0, file, line, func);
213  if (msg == NULL)
214  goto error;
215 
216  off = 0;
217 
218  if (parse_integer(&i, os, &off) == -1)
219  goto error;
220  msg->type = i;
221 
222 #define INTEGER(name) \
223  if (parse_integer(&(p->name), os, &off) == -1) goto error;
224 #define OCTSTR(name) \
225  if (parse_string(&(p->name), os, &off) == -1) goto error;
226 #define UUID(name) \
227  if (parse_uuid(p->name, os, &off) == -1) goto error;
228 #define VOID(name)
229 #define MSG(type, stmt) \
230  case type: { struct type *p = &(msg->type); stmt } break;
231 
232  switch (msg->type) {
233 #include "msg-decl.h"
234  default:
235  error(0, "Internal error: unknown message type: %d",
236  msg->type);
237  msg->type = 0;
238  msg_destroy(msg);
239  return NULL;
240  }
241 
242  return msg;
243 
244 error:
245  if (msg != NULL) msg_destroy(msg);
246  error(0, "Msg packet was invalid.");
247  return NULL;
248 }
249 
250 
251 /*
252  * Wrapper function needed for function pointer forwarding to storage
253  * subsystem. We can't pass the msg_unpack() pre-processor macro, so we
254  * need to wrapp a function arround it.
255  */
257 {
258  return msg_unpack(os);
259 }
260 
261 
262 /**********************************************************************
263  * Implementations of private functions.
264  */
265 
266 
267 static void append_integer(Octstr *os, long i)
268 {
269  unsigned char buf[4];
270 
271  encode_network_long(buf, i);
272  octstr_append_data(os, (char *)buf, 4);
273 }
274 
275 static void append_string(Octstr *os, Octstr *field)
276 {
277  if (field == NULL)
278  append_integer(os, -1);
279  else {
280  append_integer(os, octstr_len(field));
281  octstr_insert(os, field, octstr_len(os));
282  }
283 }
284 
285 static void append_uuid(Octstr *os, uuid_t id)
286 {
287  char buf[UUID_STR_LEN + 1];
288 
289  uuid_unparse(id, buf);
291  octstr_append_cstr(os, buf);
292 }
293 
294 static int parse_integer(long *i, Octstr *packed, int *off)
295 {
296  unsigned char buf[4];
297 
298  gw_assert(*off >= 0);
299  if (*off + 4 > octstr_len(packed)) {
300  error(0, "Packet too short while unpacking Msg.");
301  return -1;
302  }
303 
304  octstr_get_many_chars((char *)buf, packed, *off, 4);
305  *i = decode_network_long(buf);
306  *off += 4;
307  return 0;
308 }
309 
310 
311 static int parse_string(Octstr **os, Octstr *packed, int *off)
312 {
313  long len;
314 
315  if (parse_integer(&len, packed, off) == -1)
316  return -1;
317 
318  if (len == -1) {
319  *os = NULL;
320  return 0;
321  }
322 
323  /* XXX check that len is ok */
324 
325  *os = octstr_copy(packed, *off, len);
326  if (*os == NULL)
327  return -1;
328  *off += len;
329 
330  return 0;
331 }
332 
333 
334 static int parse_uuid(uuid_t id, Octstr *packed, int *off)
335 {
336  Octstr *tmp = NULL;
337 
338  if (parse_string(&tmp, packed, off) == -1) {
339  octstr_destroy(tmp);
340  return -1;
341  }
342 
343  if (uuid_parse(octstr_get_cstr(tmp), id) == -1) {
344  octstr_destroy(tmp);
345  return -1;
346  }
347 
348  octstr_destroy(tmp);
349 
350  return 0;
351 }
352 
353 static char *type_as_str(Msg *msg)
354 {
355  switch (msg->type) {
356 #define MSG(t, stmt) case t: return #t;
357 #include "msg-decl.h"
358  default:
359  return "unknown type";
360  }
361 }
void msg_dump(Msg *msg, int level)
Definition: msg.c:152
void error(int err, const char *fmt,...)
Definition: log.c:612
Msg * msg_duplicate(Msg *msg)
Definition: msg.c:111
static char * type_as_str(Msg *msg)
Definition: msg.c:353
void octstr_append_data(Octstr *ostr, const char *data, long len)
Definition: octstr.c:1495
#define msg_unpack(os)
Definition: msg.h:183
void encode_network_long(unsigned char *data, unsigned long value)
Definition: utils.c:940
Msg * msg_unpack_wrapper(Octstr *os)
Definition: msg.c:256
static void append_integer(Octstr *os, long i)
Definition: msg.c:267
msg_type
Definition: msg.h:73
int type
Definition: smsc_cimd2.c:215
void uuid_unparse(const uuid_t uu, char *out)
Definition: gw_uuid.c:561
#define msg_create(type)
Definition: msg.h:136
void octstr_append_cstr(Octstr *ostr, const char *cstr)
Definition: octstr.c:1509
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
#define octstr_copy(ostr, from, len)
Definition: octstr.h:178
Msg * msg_create_real(enum msg_type type, const char *file, long line, const char *func)
Definition: msg.c:93
FILE * file
Definition: log.c:133
int uuid_parse(const char *in, uuid_t uu)
Definition: gw_uuid.c:475
static int parse_string(Octstr **os, Octstr *packed, int *off)
Definition: msg.c:311
void msg_destroy_item(void *msg)
Definition: msg.c:147
Definition: msg.h:79
void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos)
Definition: octstr.c:1301
static int parse_uuid(uuid_t id, Octstr *packed, int *off)
Definition: msg.c:334
void msg_destroy(Msg *msg)
Definition: msg.c:132
static void append_string(Octstr *os, Octstr *field)
Definition: msg.c:275
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
gw_assert(wtls_machine->packet_to_send!=NULL)
#define UUID_STR_LEN
Definition: gw_uuid.h:19
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
long decode_network_long(unsigned char *data)
Definition: utils.c:935
Definition: octstr.c:118
static int parse_integer(long *i, Octstr *packed, int *off)
Definition: msg.c:294
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
#define panic
Definition: log.h:87
Msg * msg_unpack_real(Octstr *os, const char *file, long line, const char *func)
Definition: msg.c:206
Octstr * msg_pack(Msg *msg)
Definition: msg.c:181
enum msg_type type
Definition: msg.h:80
unsigned char uuid_t[16]
Definition: gw_uuid.h:32
void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
Definition: octstr.c:423
static void append_uuid(Octstr *os, uuid_t id)
Definition: msg.c:285
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
enum msg_type msg_type(Msg *msg)
Definition: msg.c:176
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.