parse_contact.c

Go to the documentation of this file.
00001 /*
00002  * $Id: parse_contact.c 4518 2008-07-28 15:39:28Z henningw $
00003  *
00004  * Contact header field body parser
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  * History:
00025  * -------
00026  *  2003-03-25 Adapted to use new parameter parser (janakj)
00027  */
00028 
00029 #include <string.h>          /* memset */
00030 #include "../hf.h"     
00031 #include "../../mem/mem.h"   /* pkg_malloc, pkg_free */
00032 #include "../../dprint.h"
00033 #include "../../trim.h"      /* trim_leading */
00034 #include "parse_contact.h"
00035 
00036 
00037 
00038 static inline int contact_parser(char* _s, int _l, contact_body_t* _c)
00039 {
00040    str tmp;
00041 
00042    tmp.s = _s;
00043    tmp.len = _l;
00044 
00045    trim_leading(&tmp);
00046 
00047    if (tmp.len == 0) {
00048       LM_ERR("empty body\n");
00049       return -1;
00050    }
00051 
00052    if (tmp.s[0] == '*') {
00053       _c->star = 1;
00054    } else {
00055       if (parse_contacts(&tmp, &(_c->contacts)) < 0) {
00056          LM_ERR("failed to parse contacts\n");
00057          return -2;
00058       }
00059    }
00060 
00061    return 0;
00062 }
00063 
00064 
00065 /*
00066  * Parse contact header field body
00067  */
00068 int parse_contact(struct hdr_field* _h)
00069 {
00070    contact_body_t* b;
00071 
00072    if (_h->parsed != 0) {
00073       return 0;  /* Already parsed */
00074    }
00075 
00076    b = (contact_body_t*)pkg_malloc(sizeof(contact_body_t));
00077    if (b == 0) {
00078       LM_ERR("no pkg memory left\n");
00079       return -1;
00080    }
00081 
00082    memset(b, 0, sizeof(contact_body_t));
00083 
00084    if (contact_parser(_h->body.s, _h->body.len, b) < 0) {
00085       LM_ERR("failed to parse contact\n");
00086       pkg_free(b);
00087       return -2;
00088    }
00089 
00090    _h->parsed = (void*)b;
00091    return 0;
00092 }
00093 
00094 
00095 /*
00096  * Free all memory
00097  */
00098 void free_contact(contact_body_t** _c)
00099 {
00100    if ((*_c)->contacts) {
00101       free_contacts(&((*_c)->contacts));
00102    }
00103    
00104    pkg_free(*_c);
00105    *_c = 0;
00106 }
00107 
00108 
00109 /*
00110  * Print structure, for debugging only
00111  */
00112 void print_contact(FILE* _o, contact_body_t* _c)
00113 {
00114    fprintf(_o, "===Contact body===\n");
00115    fprintf(_o, "star: %d\n", _c->star);
00116    print_contacts(_o, _c->contacts);
00117    fprintf(_o, "===/Contact body===\n");
00118 }
00119 
00120 
00121 /*
00122  * Contact header field iterator, returns next contact if any, it doesn't
00123  * parse message header if not absolutely necessary
00124  */
00125 int contact_iterator(contact_t** c, struct sip_msg* msg, contact_t* prev)
00126 {
00127    static struct hdr_field* hdr = 0;
00128    struct hdr_field* last;
00129    contact_body_t* cb;
00130 
00131    if (!msg) {
00132       LM_ERR("invalid parameter value\n");
00133       return -1;
00134    }
00135 
00136    if (!prev) {
00137            /* No pointer to previous contact given, find topmost
00138             * contact and return pointer to the first contact
00139             * inside that header field
00140             */
00141       hdr = msg->contact;
00142       if (!hdr) {
00143          if (parse_headers(msg, HDR_CONTACT_F, 0) == -1) {
00144             LM_ERR("failed to parse headers\n");
00145             return -1;
00146          }
00147 
00148          hdr = msg->contact;
00149       }
00150 
00151       if (hdr) {
00152          if (parse_contact(hdr) < 0) {
00153             LM_ERR("failed to parse Contact\n");
00154             return -1;
00155          }
00156       } else {
00157          *c = 0;
00158          return 1;
00159       }
00160 
00161       cb = (contact_body_t*)hdr->parsed;
00162       *c = cb->contacts;
00163       return 0;
00164    } else {
00165            /* Check if there is another contact in the
00166             * same header field and if so then return it
00167             */
00168       if (prev->next) {
00169          *c = prev->next;
00170          return 0;
00171       }
00172 
00173            /* Try to find and parse another Contact
00174             * header field
00175             */
00176       last = hdr;
00177       hdr = hdr->next;
00178 
00179            /* Search another already parsed Contact
00180             * header field
00181             */
00182       while(hdr && hdr->type != HDR_CONTACT_T) {
00183          hdr = hdr->next;
00184       }
00185 
00186       if (!hdr) {
00187               /* Look for another Contact HF in unparsed
00188                * part of the message header
00189                */
00190          if (parse_headers(msg, HDR_CONTACT_F, 1) == -1) {
00191             LM_ERR("failed to parse message header\n");
00192             return -1;
00193          }
00194          
00195               /* Check if last found header field is Contact
00196                * and if it is not the same header field as the
00197                * previous Contact HF (that indicates that the previous 
00198                * one was the last header field in the header)
00199                */
00200          if ((msg->last_header->type == HDR_CONTACT_T) &&
00201              (msg->last_header != last)) {
00202             hdr = msg->last_header;
00203          } else {
00204             *c = 0;
00205             return 1;
00206          }
00207       }
00208       
00209       if (parse_contact(hdr) < 0) {
00210          LM_ERR("failed to parse Contact HF body\n");
00211          return -1;
00212       }
00213       
00214            /* And return first contact within that
00215             * header field
00216             */
00217       cb = (contact_body_t*)hdr->parsed;
00218       *c = cb->contacts;
00219       return 0;
00220    }
00221 }

Generated on Thu May 24 00:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6