contact.c

Go to the documentation of this file.
00001 /*
00002  * $Id: contact.c 4518 2008-07-28 15:39:28Z henningw $
00003  *
00004  * Parses one Contact in Contact HF body
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 "../../mem/mem.h" /* pkg_malloc, pkg_free */
00031 #include "../../dprint.h"
00032 #include "../../trim.h"    /* trim_leading, trim_trailing */
00033 #include "contact.h"
00034 
00035 
00036 #define ST1 1 /* Basic state */
00037 #define ST2 2 /* Quoted */
00038 #define ST3 3 /* Angle quoted */
00039 #define ST4 4 /* Angle quoted and quoted */
00040 #define ST5 5 /* Escape in quoted */
00041 #define ST6 6 /* Escape in angle quoted and quoted */
00042 
00043 
00044 /*
00045  * Skip URI, stops when , (next contact)
00046  * or ; (parameter) is found
00047  */
00048 static inline int skip_uri(str* _s)
00049 {
00050    register int st = ST1;
00051 
00052    while(_s->len) {
00053       switch(*(_s->s)) {
00054       case ',':
00055       case ';':
00056          if (st == ST1) return 0;
00057          break;
00058 
00059       case '\"':
00060          switch(st) {
00061          case ST1: st = ST2; break;
00062          case ST2: st = ST1; break;
00063          case ST3: st = ST4; break;
00064          case ST4: st = ST3; break;
00065          case ST5: st = ST2; break;
00066          case ST6: st = ST4; break;
00067          }
00068          break;
00069 
00070       case '<':
00071          switch(st) {
00072          case ST1: st = ST3; break;
00073          case ST3: 
00074             LM_ERR("second < found\n");
00075             return -1;
00076          case ST5: st = ST2; break;
00077          case ST6: st = ST4; break;
00078          }
00079          break;
00080          
00081       case '>':
00082          switch(st) {
00083          case ST1: 
00084             LM_ERR("> is first\n");
00085             return -2;
00086 
00087          case ST3: st = ST1; break;
00088          case ST5: st = ST2; break;
00089          case ST6: st = ST4; break;
00090          }
00091          break;
00092 
00093       case '\\':
00094          switch(st) {
00095          case ST2: st = ST5; break;
00096          case ST4: st = ST6; break;
00097          case ST5: st = ST2; break;
00098          case ST6: st = ST4; break;
00099          }
00100          break;
00101 
00102       default: break;
00103 
00104       }
00105 
00106       _s->s++;
00107       _s->len--;
00108    }
00109 
00110    if (st != ST1) {
00111       LM_ERR("< or \" not closed\n");
00112       return -3;
00113    }
00114 
00115    return 0;
00116 }
00117 
00118 
00119 /*
00120  * Skip name part
00121  *
00122  * _s will be adjusted to point at the beginning
00123  * of URI
00124  */
00125 static inline int skip_name(str* _s)
00126 {
00127    char* last_wsp, *p;
00128    int i, quoted = 0;
00129    
00130 
00131    if (!_s) {
00132       LM_ERR("invalid parameter value\n");
00133       return -1;
00134    }
00135 
00136    p = _s->s;
00137 
00138    last_wsp = 0;
00139 
00140    for(i = 0; i < _s->len; i++) {
00141       if (!quoted) {
00142          if ((*p == ' ') || (*p == '\t')) {
00143             last_wsp = p;
00144          } else {
00145             if (*p == '<') {
00146                _s->s = p;
00147                _s->len -= i;
00148                return 0;
00149             }
00150             
00151             if (*p == ':') {
00152                if (last_wsp) {
00153                   _s->s = last_wsp;
00154                   _s->len -= last_wsp - _s->s + 1;
00155                }
00156                return 0;
00157             }
00158 
00159             if (*p == '\"') {
00160                quoted = 1;
00161             }
00162          }
00163       } else {
00164          if ((*p == '\"') && (*(p-1) != '\\')) quoted = 0;
00165       }
00166       p++;
00167    }
00168 
00169    if (quoted) {
00170       LM_ERR("closing quote missing in name part of Contact\n");
00171    } else {
00172       LM_ERR("error in contact, scheme separator not found\n");
00173    }
00174 
00175    return -1;
00176 }
00177 
00178 
00179 /*
00180  * Parse contacts in a Contact HF
00181  */
00182 int parse_contacts(str* _s, contact_t** _c)
00183 {
00184    contact_t* c;
00185    param_hooks_t hooks;
00186 
00187    while(1) {
00188            /* Allocate and clear contact structure */
00189       c = (contact_t*)pkg_malloc(sizeof(contact_t));
00190       if (c == 0) {
00191          LM_ERR("no pkg memory left\n");
00192          goto error;
00193       }
00194       memset(c, 0, sizeof(contact_t));
00195       
00196       c->name.s = _s->s;
00197 
00198       if (skip_name(_s) < 0) {
00199          LM_ERR("failed to skip name part\n");
00200          goto error;
00201       }
00202 
00203       c->uri.s = _s->s;
00204       c->name.len = _s->s - c->name.s;
00205       trim_trailing(&c->name);
00206       
00207            /* Find the end of the URI */
00208       if (skip_uri(_s) < 0) {
00209          LM_ERR("failed to skip URI\n");
00210          goto error;
00211       }
00212       
00213       c->uri.len = _s->s - c->uri.s; /* Calculate URI length */
00214       trim_trailing(&(c->uri));      /* Remove any trailing spaces from URI */
00215 
00216            /* Remove <> if any */
00217       if ((c->uri.len >= 2) && (c->uri.s[0] == '<') && (c->uri.s[c->uri.len - 1] == '>')) {
00218          c->uri.s++;
00219          c->uri.len -= 2;
00220       }
00221 
00222       trim(&c->uri);
00223       
00224       if (_s->len == 0) goto ok;
00225       
00226       if (_s->s[0] == ';') {         /* Contact parameter found */
00227          _s->s++;
00228          _s->len--;
00229          trim_leading(_s);
00230          
00231          if (_s->len == 0) {
00232             LM_ERR("failed to parse params\n");
00233             goto error;
00234          }
00235 
00236          if (parse_params(_s, CLASS_CONTACT, &hooks, &c->params) < 0) {
00237             LM_ERR("failed to parse contact parameters\n");
00238             goto error;
00239          }
00240 
00241          c->q = hooks.contact.q;
00242          c->expires = hooks.contact.expires;
00243          c->received = hooks.contact.received;
00244          c->methods = hooks.contact.methods;
00245 
00246          if (_s->len == 0) goto ok;
00247       }
00248 
00249            /* Next character is comma */
00250       c->len = _s->s - c->name.s;
00251       _s->s++;
00252       _s->len--;
00253       trim_leading(_s);
00254 
00255       if (_s->len == 0) {
00256          LM_ERR("text after comma missing\n");
00257          goto error;
00258       }
00259 
00260       c->next = *_c;
00261       *_c = c;
00262    }
00263 
00264  error:
00265    if (c) pkg_free(c);
00266    free_contacts(_c); /* Free any contacts created so far */
00267    return -1;
00268 
00269  ok:
00270    c->len = _s->s - c->name.s;
00271    c->next = *_c;
00272    *_c = c;
00273    return 0;
00274 }
00275 
00276 
00277 /*
00278  * Free list of contacts
00279  * _c is head of the list
00280  */
00281 void free_contacts(contact_t** _c)
00282 {
00283    contact_t* ptr;
00284 
00285    while(*_c) {
00286       ptr = *_c;
00287       *_c = (*_c)->next;
00288       if (ptr->params) {
00289          free_params(ptr->params);
00290       }
00291       pkg_free(ptr);
00292    }
00293 }
00294 
00295 
00296 /*
00297  * Print list of contacts, just for debugging
00298  */
00299 void print_contacts(FILE* _o, contact_t* _c)
00300 {
00301    contact_t* ptr;
00302 
00303    ptr = _c;
00304 
00305    while(ptr) {
00306       fprintf(_o, "---Contact---\n");
00307       fprintf(_o, "name    : '%.*s'\n", ptr->name.len, ptr->name.s);
00308       fprintf(_o, "URI     : '%.*s'\n", ptr->uri.len, ptr->uri.s);
00309       fprintf(_o, "q       : %p\n", ptr->q);
00310       fprintf(_o, "expires : %p\n", ptr->expires);
00311       fprintf(_o, "received: %p\n", ptr->received);
00312       fprintf(_o, "method  : %p\n", ptr->methods);
00313       fprintf(_o, "len     : %d\n", ptr->len);
00314       if (ptr->params) {
00315          print_params(_o, ptr->params);
00316       }
00317       fprintf(_o, "---/Contact---\n");
00318       ptr = ptr->next;
00319    }
00320 }

Generated on Mon May 21 18:00:25 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6