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

smasi_pdu.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  * smsc_smasi.c - parse and generate SMASI PDUs
00059  *
00060  * Stipe Tolj <stolj@wapme.de>
00061  */
00062 
00063 
00064 #include <string.h>
00065 #include "smasi_pdu.h"
00066 
00067 
00068 static Octstr *decode_type(Octstr *os)
00069 {
00070     long p1, p2;
00071     Octstr *temp;
00072 
00073     if ((p2 = octstr_search_char(os, ':', 0)) == -1)
00074         return NULL;
00075 
00076     if ((p1 = octstr_search_char(os, '!', 0)) != -1 && p1 < p2) {
00077         p1++;
00078     } else {
00079         p1 = 0;
00080     }
00081 
00082     temp = octstr_copy(os, p1, p2 - p1);
00083 
00084     return temp;
00085 }
00086 
00087 
00088 static Octstr *copy_until_coma(Octstr *os, long *pos)
00089 {
00090     long nul;
00091     Octstr *data;
00092 
00093     nul = octstr_search_char(os, ',', *pos);
00094     if (nul == -1) {
00095         warning(0, "SMASI: Parameter without value or value not properly terminated: %s", octstr_get_cstr(os));
00096         return NULL;
00097     }
00098     data = octstr_copy(os, *pos, nul - *pos);
00099     *pos = nul + 1;
00100     return data;
00101 }
00102 
00103 
00104 static Octstr *copy_until_assign(Octstr *os, long *pos) 
00105 {
00106     long nul;
00107     Octstr *data;
00108 
00109     nul = octstr_search_char(os, '=', *pos);
00110     if (nul == -1 && (octstr_len(os) - *pos) > 1) {
00111         warning(0, "SMASI: Garbage at end of parameter list: %s", octstr_get_cstr(os));
00112         *pos = octstr_len(os);
00113         return NULL;
00114     }
00115     data = octstr_copy(os, *pos, nul - *pos);
00116     *pos = nul + 1;
00117     return data;
00118 }
00119 
00120 
00121 static void skip_until_after_colon(Octstr *os, long *pos) 
00122 {
00123     long colon = octstr_search_char(os, ':', *pos);
00124 
00125     if (colon == -1) warning(0, "SMASI: No colon after SMASI PDU name: %s", octstr_get_cstr(os));
00126 
00127     *pos = colon + 1;
00128 
00129 }
00130 
00131 
00132 SMASI_PDU *smasi_pdu_create(unsigned long type) 
00133 {
00134     SMASI_PDU *pdu;
00135 
00136     pdu = gw_malloc(sizeof(*pdu));
00137     pdu->type = type;
00138 
00139     switch (type) {
00140     #define NONTERMINATED(name) p->name = NULL;
00141     #define COMATERMINATED(name) p->name = NULL;
00142     #define PDU(name, id, fields) \
00143         case id: { \
00144         struct name *p = &pdu->u.name; \
00145         pdu->type_name = #name; \
00146         pdu->needs_hyphen = (id < SMASI_HYPHEN_ID ? 1 : 0); \
00147         fields \
00148     } break;
00149     #include "smasi_pdu.def"
00150     default:
00151         warning(0, "Unknown SMASI_PDU type, internal error.");
00152         gw_free(pdu);
00153     return NULL;
00154     }
00155 
00156     return pdu;
00157 }
00158 
00159 
00160 void smasi_pdu_destroy(SMASI_PDU *pdu)
00161 {
00162     if (pdu == NULL)
00163         return;
00164 
00165     switch (pdu->type) {
00166     #define NONTERMINATED(name) octstr_destroy(p->name);
00167     #define COMATERMINATED(name) octstr_destroy(p->name);
00168     #define PDU(name, id, fields) \
00169         case id: { struct name *p = &pdu->u.name; fields } break;
00170     #include "smasi_pdu.def"
00171     default:
00172         error(0, "Unknown SMASI_PDU type, internal error while destroying.");
00173     }
00174     gw_free(pdu);
00175 }
00176 
00177 
00178 Octstr *smasi_pdu_pack(SMASI_PDU *pdu)
00179 {
00180     Octstr *os;
00181     Octstr *temp;
00182 
00183     os = octstr_create("");
00184 
00185     /*
00186      * Fix lengths of octet string fields.
00187      */
00188     switch (pdu->type) {
00189     #define NONTERMINATED(name) p = *(&p);
00190     #define COMATERMINATED(name) p = *(&p);
00191     #define PDU(name, id, fields) \
00192         case id: { struct name *p = &pdu->u.name; fields } break;
00193     #include "smasi_pdu.def"
00194     default:
00195         error(0, "Unknown SMASI_PDU type, internal error while packing.");
00196     }
00197 
00198     switch (pdu->type) {
00199     #define NONTERMINATED(name) p = *(&p);
00200     #define COMATERMINATED(name) \
00201     if (p->name != NULL) { octstr_append_cstr(os, #name); \
00202     octstr_append_char(os, '='); \
00203     octstr_append(os, p->name); \
00204     octstr_append_char(os, ','); }
00205     #define PDU(name, id, fields) \
00206         case id: { struct name *p = &pdu->u.name; fields } break;
00207     #include "smasi_pdu.def"
00208     default:
00209         error(0, "Unknown SMASI_PDU type, internal error while packing.");
00210     }
00211 
00212     octstr_append_char(os, '\n');
00213     temp = pdu->needs_hyphen ? octstr_create("!") : octstr_create("");
00214     octstr_append_cstr(temp, pdu->type_name); 
00215     octstr_append_char(temp, ':');
00216     octstr_insert(os, temp, 0);
00217     octstr_destroy(temp);
00218 
00219     return os;
00220 }
00221 
00222 
00223 SMASI_PDU *smasi_pdu_unpack(Octstr *data_without_len)
00224 {
00225     SMASI_PDU *pdu;
00226     char *type_name;
00227     Octstr *temp;
00228     long pos;
00229     unsigned long type = 0;
00230 
00231     /* extract the PDU type identifier */
00232     temp = decode_type(data_without_len);
00233     type_name = (temp ? octstr_get_cstr(temp) : "");
00234 
00235     if (strcmp(type_name, "dummy") == 0) type = 0;
00236     #define NONTERMINATED(name) p = *(&p);
00237     #define COMATERMINATED(name) p = *(&p);
00238     #define PDU(name, id, fields) \
00239     else if (strcmp(type_name, #name) == 0) type = id;
00240     #include "smasi_pdu.def"
00241     else warning(0, "unknown SMASI PDU type");
00242 
00243     pdu = smasi_pdu_create(type);
00244     if (pdu == NULL) return NULL;
00245 
00246     pos = 0;
00247     skip_until_after_colon(data_without_len, &pos);
00248 
00249     switch (type) {
00250     #define NONTERMINATED(name) p = *(&p);
00251     #define COMATERMINATED(name) \
00252                 if (octstr_str_compare(field_name, #name) == 0 && field_value != NULL) \
00253                     p->name = octstr_duplicate(field_value);
00254     #define PDU(name, id, fields) \
00255         case id: { \
00256             Octstr * field_name = NULL; \
00257             Octstr * field_value = NULL; \
00258             struct name *p = &pdu->u.name; \
00259             while (pos < octstr_len(data_without_len)) { \
00260                 field_name = copy_until_assign(data_without_len, &pos); \
00261                 if (field_name == NULL) break; \
00262                 field_value = copy_until_coma(data_without_len, &pos); \
00263                 if (field_value == NULL) continue; \
00264                 fields \
00265                 octstr_destroy(field_name); \
00266                 octstr_destroy(field_value); \
00267             } \
00268         } break;
00269     #include "smasi_pdu.def"
00270     default:
00271         warning(0, "Unknown SMASI_PDU type, internal error while unpacking.");
00272     }
00273 
00274     octstr_destroy(temp);
00275 
00276     return pdu;
00277 }
00278 
00279 
00280 void smasi_pdu_dump(SMASI_PDU *pdu)
00281 {
00282     debug("sms.smasi", 0, "SMASI PDU %p dump:", (void *) pdu);
00283     debug("sms.smasi", 0, "  type_name: %s", pdu->type_name);
00284     switch (pdu->type) {
00285     #define NONTERMINATED(name) p = *(&p);
00286     #define COMATERMINATED(name) \
00287     octstr_dump_short(p->name, 2, #name);
00288     #define PDU(name, id, fields) \
00289         case id: { struct name *p = &pdu->u.name; fields } break;
00290     #include "smasi_pdu.def"
00291     default:
00292         warning(0, "Unknown SMASI_PDU type, internal error.");
00293     break;
00294     }
00295     debug("sms.smasi", 0, "SMASI PDU dump ends.");
00296 }
00297 
00298 
00299 Octstr *smasi_pdu_read(Connection *conn)
00300 {
00301     Octstr *line;
00302 
00303     line = conn_read_line(conn);    /* read one line */
00304     return line;
00305 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.