Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

msg.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * msg.c - manipulate messages
00059  *
00060  * This file contains implementations of the functions that create, destroy,
00061  * pack, and unpack messages.
00062  *
00063  * Lars Wirzenius <liw@wapit.com>
00064  */
00065 
00066 #include <errno.h>
00067 #include <stdlib.h>
00068 #include <sys/types.h>
00069 #include <netinet/in.h>
00070 
00071 #include "msg.h"
00072 #include "gwlib/gwlib.h"
00073 
00074 /**********************************************************************
00075  * Prototypes for private functions.
00076  */
00077 
00078 static void append_integer(Octstr *os, long i);
00079 static void append_string(Octstr *os, Octstr *field);
00080 static void append_uuid(Octstr *os, uuid_t id);
00081 
00082 static int parse_integer(long *i, Octstr *packed, int *off);
00083 static int parse_string(Octstr **os, Octstr *packed, int *off);
00084 static int parse_uuid(uuid_t id, Octstr *packed, int *off);
00085 
00086 static char *type_as_str(Msg *msg);
00087 
00088 
00089 /**********************************************************************
00090  * Implementations of the exported functions.
00091  */
00092 
00093 Msg *msg_create_real(enum msg_type type, const char *file, long line,
00094                      const char *func)
00095 {
00096     Msg *msg;
00097 
00098     msg = gw_malloc_trace(sizeof(Msg), file, line, func);
00099 
00100     msg->type = type;
00101 #define INTEGER(name) p->name = MSG_PARAM_UNDEFINED
00102 #define OCTSTR(name) p->name = NULL
00103 #define UUID(name) uuid_generate(p->name)
00104 #define VOID(name) p->name = NULL
00105 #define MSG(type, stmt) { struct type *p = &msg->type; stmt }
00106 #include "msg-decl.h"
00107 
00108     return msg;
00109 }
00110 
00111 Msg *msg_duplicate(Msg *msg)
00112 {
00113     Msg *new;
00114 
00115     new = msg_create(msg->type);
00116 
00117 #define INTEGER(name) p->name = q->name
00118 #define OCTSTR(name) \
00119     if (q->name == NULL) p->name = NULL; \
00120     else p->name = octstr_duplicate(q->name);
00121 #define UUID(name) uuid_copy(p->name, q->name)
00122 #define VOID(name) p->name = q->name
00123 #define MSG(type, stmt) { \
00124     struct type *p = &new->type; \
00125     struct type *q = &msg->type; \
00126     stmt }
00127 #include "msg-decl.h"
00128 
00129     return new;
00130 }
00131 
00132 void msg_destroy(Msg *msg)
00133 {
00134     if (msg == NULL)
00135         return;
00136 
00137 #define INTEGER(name) p->name = 0
00138 #define OCTSTR(name) octstr_destroy(p->name)
00139 #define UUID(name) uuid_clear(p->name)
00140 #define VOID(name)
00141 #define MSG(type, stmt) { struct type *p = &msg->type; stmt }
00142 #include "msg-decl.h"
00143 
00144     gw_free(msg);
00145 }
00146 
00147 void msg_destroy_item(void *msg)
00148 {
00149     msg_destroy(msg);
00150 }
00151 
00152 void msg_dump(Msg *msg, int level)
00153 {
00154     char buf[UUID_STR_LEN + 1];
00155 
00156     debug("gw.msg", 0, "%*sMsg object at %p:", level, "", (void *) msg);
00157     debug("gw.msg", 0, "%*s type: %s", level, "", type_as_str(msg));
00158 #define INTEGER(name) \
00159     debug("gw.msg", 0, "%*s %s.%s: %ld", level, "", t, #name, (long) p->name)
00160 #define OCTSTR(name) \
00161     debug("gw.msg", 0, "%*s %s.%s:", level, "", t, #name); \
00162     octstr_dump(p->name, level + 1)
00163 #define UUID(name) \
00164     uuid_unparse(p->name, buf); \
00165     debug("gw.msg", 0 , "%*s %s.%s: %s", level, "", t, #name, buf)
00166 #define VOID(name) \
00167      debug("gw.msg", 0, "%*s %s.%s: %p", level, "", t, #name, p->name)
00168 #define MSG(tt, stmt) \
00169     if (tt == msg->type) \
00170         { char *t = #tt; struct tt *p = &msg->tt; stmt }
00171 #include "msg-decl.h"
00172     debug("gw.msg", 0, "Msg object ends.");
00173 }
00174 
00175 
00176 enum msg_type msg_type(Msg *msg)
00177 {
00178     return msg->type;
00179 }
00180 
00181 Octstr *msg_pack(Msg *msg)
00182 {
00183     Octstr *os;
00184 
00185     os = octstr_create("");
00186     append_integer(os, msg->type);
00187 
00188 #define INTEGER(name) append_integer(os, p->name)
00189 #define OCTSTR(name) append_string(os, p->name)
00190 #define UUID(name) append_uuid(os, p->name)
00191 #define VOID(name)
00192 #define MSG(type, stmt) \
00193     case type: { struct type *p = &msg->type; stmt } break;
00194 
00195     switch (msg->type) {
00196 #include "msg-decl.h"
00197     default:
00198         panic(0, "Internal error: unknown message type %d",
00199               msg->type);
00200     }
00201 
00202     return os;
00203 }
00204 
00205 
00206 Msg *msg_unpack_real(Octstr *os, const char *file, long line, const char *func)
00207 {
00208     Msg *msg;
00209     int off;
00210     long i;
00211 
00212     msg = msg_create_real(0, file, line, func);
00213     if (msg == NULL)
00214         goto error;
00215 
00216     off = 0;
00217 
00218     if (parse_integer(&i, os, &off) == -1)
00219         goto error;
00220     msg->type = i;
00221 
00222 #define INTEGER(name) \
00223     if (parse_integer(&(p->name), os, &off) == -1) goto error
00224 #define OCTSTR(name) \
00225     if (parse_string(&(p->name), os, &off) == -1) goto error
00226 #define UUID(name) \
00227     if (parse_uuid(p->name, os, &off) == -1) goto error
00228 #define VOID(name)
00229 #define MSG(type, stmt) \
00230     case type: { struct type *p = &(msg->type); stmt } break;
00231 
00232     switch (msg->type) {
00233 #include "msg-decl.h"
00234     default:
00235         panic(0, "Internal error: unknown message type: %d",
00236               msg->type);
00237     }
00238 
00239     return msg;
00240 
00241 error:
00242     if (msg != NULL) msg_destroy(msg);
00243     error(0, "Msg packet was invalid.");
00244     return NULL;
00245 }
00246 
00247 
00248 /*
00249  * Wrapper function needed for function pointer forwarding to storage
00250  * subsystem. We can't pass the msg_unpack() pre-processor macro, so we
00251  * need to wrapp a function arround it.
00252  */
00253 inline Msg *msg_unpack_wrapper(Octstr *os)
00254 {
00255     return msg_unpack(os);
00256 }
00257 
00258 
00259 /**********************************************************************
00260  * Implementations of private functions.
00261  */
00262 
00263 
00264 static void append_integer(Octstr *os, long i)
00265 {
00266     unsigned char buf[4];
00267 
00268     encode_network_long(buf, i);
00269     octstr_append_data(os, (char *)buf, 4);
00270 }
00271 
00272 static void append_string(Octstr *os, Octstr *field)
00273 {
00274     if (field == NULL)
00275         append_integer(os, -1);
00276     else {
00277         append_integer(os, octstr_len(field));
00278         octstr_insert(os, field, octstr_len(os));
00279     }
00280 }
00281 
00282 static void append_uuid(Octstr *os, uuid_t id)
00283 {
00284     char buf[UUID_STR_LEN + 1];
00285 
00286     uuid_unparse(id, buf);
00287     append_integer(os, UUID_STR_LEN);
00288     octstr_append_cstr(os, buf);
00289 }
00290 
00291 static int parse_integer(long *i, Octstr *packed, int *off)
00292 {
00293     unsigned char buf[4];
00294 
00295     gw_assert(*off >= 0);
00296     if (*off + 4 > octstr_len(packed)) {
00297         error(0, "Packet too short while unpacking Msg.");
00298         return -1;
00299     }
00300 
00301     octstr_get_many_chars((char *)buf, packed, *off, 4);
00302     *i = decode_network_long(buf);
00303     *off += 4;
00304     return 0;
00305 }
00306 
00307 
00308 static int parse_string(Octstr **os, Octstr *packed, int *off)
00309 {
00310     long len;
00311 
00312     if (parse_integer(&len, packed, off) == -1)
00313         return -1;
00314 
00315     if (len == -1) {
00316         *os = NULL;
00317         return 0;
00318     }
00319 
00320     /* XXX check that len is ok */
00321 
00322     *os = octstr_copy(packed, *off, len);
00323     if (*os == NULL)
00324         return -1;
00325     *off += len;
00326 
00327     return 0;
00328 }
00329 
00330 
00331 static int parse_uuid(uuid_t id, Octstr *packed, int *off)
00332 {
00333    Octstr *tmp = NULL;
00334 
00335    if (parse_string(&tmp, packed, off) == -1) {
00336        octstr_destroy(tmp);
00337        return -1;
00338    }
00339 
00340    if (uuid_parse(octstr_get_cstr(tmp), id) == -1) {
00341        octstr_destroy(tmp);
00342        return -1;
00343    }
00344 
00345    octstr_destroy(tmp);
00346 
00347    return 0;
00348 }
00349 
00350 static char *type_as_str(Msg *msg)
00351 {
00352     switch (msg->type) {
00353 #define MSG(t, stmt) case t: return #t;
00354 #include "msg-decl.h"
00355     default:
00356         return "unknown type";
00357     }
00358 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.