encode_contact.c

Go to the documentation of this file.
00001 /* $Id: encode_contact.c 5192 2008-11-13 10:18:48Z eliasbaixas $
00002  *
00003  * Copyright (C) 2006-2007 VozTelecom Sistemas S.L
00004  *
00005  * This file is part of Kamailio, a free SIP server.
00006  *
00007  * Kamailio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version
00011  *
00012  * Kamailio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License 
00018  * along with this program; if not, write to the Free Software 
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 /*
00023  * =====================================================================================
00024  * 
00025  *        Filename:  encode_contact.c
00026  * 
00027  *     Description:  functions to encode/decode/print the contact header
00028  * 
00029  *         Version:  1.0
00030  *         Created:  20/11/05 04:24:55 CET
00031  *        Revision:  none
00032  *        Compiler:  gcc
00033  * 
00034  *          Author:  Elias Baixas (EB), elias@conillera.net
00035  *         Company:  VozTele.com
00036  * 
00037  * =====================================================================================
00038  */
00039 
00040 #define _GNU_SOURCE
00041 #include <stdio.h>
00042 #include "../../parser/contact/parse_contact.h"
00043 #include "../../parser/contact/contact.h"
00044 #include "../../parser/parse_uri.h"
00045 #include "encode_contact.h"
00046 #include "encode_uri.h"
00047 #include "xaddress.h"
00048 #include "encode_header.h"
00049 #include "encode_parameters.h"
00050 
00051 #define HAS_NAME_F      0x01
00052 #define HAS_Q_F         0x02
00053 #define HAS_EXPIRES_F      0x04
00054 #define HAS_RECEIVED_F     0x08
00055 #define HAS_METHOD_F    0x10
00056 /*
00057  * encodes a (maybe aggregated) contact header.
00058  * encoding is:
00059  * 1: flags
00060  *    0x01 this is a star contact (*)
00061  *[ 
00062  * 1: number of contacts present
00063  * N: fore each contact present, the length of the contact structure
00064  * N*M: the contact structures concatenated
00065  *]
00066  */
00067 int encode_contact_body(char *hdr,int hdrlen,contact_body_t *contact_parsed,unsigned char *where)
00068 {
00069    int i=0,k,contact_offset;
00070    unsigned char flags=0,tmp[500];
00071    contact_t *mycontact;
00072 
00073    if(contact_parsed->star){
00074       flags|=STAR_F;
00075       where[0]=flags;
00076       return 1;
00077    }
00078    for(contact_offset=0,i=0,mycontact=contact_parsed->contacts;mycontact;mycontact=mycontact->next,i++){
00079       if((k=encode_contact(hdr,hdrlen,mycontact,&tmp[contact_offset]))<0){
00080     LM_ERR("parsing contact number %d\n",i);
00081     return -1;
00082       }
00083       where[2+i]=k;
00084       contact_offset+=k;
00085    }
00086    where[1]=(unsigned char)i;
00087    memcpy(&where[2+i],tmp,contact_offset);
00088    return 2+i+contact_offset;
00089 }
00090 
00091 /* Encoder for contacts.
00092  * Returns the length of the encoded structure in bytes
00093  * FORMAT (byte meanings):
00094  * 1: flags
00095  *    0x01 :   there is a Display Name
00096  *    0x02 :   there is a Q parameter
00097  *    0x04 :   there is an EXPIRES parameter
00098  *    0x08 :   there is a RECEIVED parameter
00099  *    0x10 :   there is a METHOD parameter
00100  * 1: length of the XURI-encoded uri in bytes.
00101  * [2]: optionally, 1 HDR-based ptr to the displayname + the length of the name
00102  * [2]: optionally, 1 HDR-based ptr to the q + the length of the q
00103  * [2]: optionally, 1 HDR-based ptr to the expires + the length of the expires
00104  * [2]: optionally, 1 HDR-based ptr to the received param + the length of the param
00105  * [2]: optionally, 1 HDR-based ptr to the method + the length of the method parameter
00106  * N: the XURI-encoded URI.
00107  * [N:] optionally, HDR-based pointers to the different header-parameters
00108  *
00109  */
00110 int encode_contact(char *hdrstart,int hdrlen,contact_t *body,unsigned char *where)
00111 {
00112    int i=2,j=0;/* 1*flags + 1*URI_len*/
00113    unsigned char flags=0;
00114    struct sip_uri puri;
00115 
00116    if(body->name.s && body->name.len){
00117       flags|=HAS_NAME_F;
00118       where[i++]=(unsigned char)(body->name.s-hdrstart);
00119       where[i++]=(unsigned char)body->name.len;
00120    }
00121    if(body->q){
00122       flags|=HAS_Q_F;
00123       where[i++]=(unsigned char)(body->q->name.s-hdrstart);
00124       where[i++]=(unsigned char)body->q->len;
00125    }
00126    if(body->expires){
00127       flags|=HAS_EXPIRES_F;
00128       where[i++]=(unsigned char)(body->expires->name.s-hdrstart);
00129       where[i++]=(unsigned char)body->expires->len;
00130    }
00131    if(body->received){
00132       flags|=HAS_RECEIVED_F;
00133       where[i++]=(unsigned char)(body->received->name.s-hdrstart);
00134       where[i++]=(unsigned char)body->received->len;
00135    }
00136    if(body->methods){
00137       flags|=HAS_METHOD_F;
00138       where[i++]=(unsigned char)(body->methods->name.s-hdrstart);
00139       where[i++]=(unsigned char)body->methods->len;
00140    }
00141 
00142    if (parse_uri(body->uri.s, body->uri.len,&puri) < 0 ) {
00143       LM_ERR("Bad URI in address\n");
00144       return -1;
00145    }else{
00146       if((j=encode_uri2(hdrstart,hdrlen,body->uri,&puri,&where[i]))<0){
00147     LM_ERR("failed to codify the URI\n");
00148     return -1;
00149       }else{
00150     i+=j;
00151       }
00152    }
00153    where[0]=flags;
00154    where[1]=(unsigned char)j;
00155    /*CAUTION the  parameters are in reversed order !!! */
00156    /*TODO parameter encoding logic should be moved to a specific function...*/
00157 
00158    i+=encode_parameters(&where[i],body->params,hdrstart,body,'n');
00159    return i;
00160 }
00161 
00162 int print_encoded_contact_body(FILE *fd,char *hdr,int hdrlen,unsigned char *payload,int paylen,char *prefix)
00163 {
00164    unsigned char flags, numcontacts;
00165    int i,offset;
00166 
00167    flags=payload[0];
00168    fprintf(fd,"%s",prefix);
00169    for(i=0;i<paylen;i++)
00170       fprintf(fd,"%s%d%s",i==0?"ENCODED CONTACT BODY:[":":",payload[i],i==paylen-1?"]\n":"");
00171 
00172    if(flags & STAR_F){
00173       fprintf(fd,"%sSTART CONTACT\n",prefix);
00174       return 1;
00175    }
00176    numcontacts=payload[1];
00177    if(numcontacts==0){
00178       LM_ERR("no contacts present?\n");
00179       return -1;
00180    }
00181    for(i=0,offset=2+numcontacts;i<numcontacts;i++){
00182       print_encoded_contact(fd,hdr,hdrlen,&payload[offset],payload[2+i],strcat(prefix,"  "));
00183       offset+=payload[2+i];
00184       prefix[strlen(prefix)-2]=0;
00185    }
00186    return 1;
00187 }
00188 int print_encoded_contact(FILE *fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix)
00189 {
00190    int i=2;/* flags + urilength */
00191    unsigned char flags=0;
00192 
00193    flags=payload[0];
00194    fprintf(fd,"%s",prefix);
00195    for(i=0;i<paylen;i++)
00196       fprintf(fd,"%s%d%s",i==0?"ENCODED CONTACT=[":":",payload[i],i==paylen-1?"]\n":"");
00197    i=2;
00198    if(flags & HAS_NAME_F){
00199       fprintf(fd,"%sCONTACT NAME=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00200       i+=2;
00201    }
00202    if(flags & HAS_Q_F){
00203       fprintf(fd,"%sCONTACT Q=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00204       i+=2;
00205    }
00206    if(flags & HAS_EXPIRES_F){
00207       fprintf(fd,"%sCONTACT EXPIRES=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00208       i+=2;
00209    }
00210    if(flags & HAS_RECEIVED_F){
00211       fprintf(fd,"%sCONTACT RECEIVED=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00212       i+=2;
00213    }
00214    if(flags & HAS_METHOD_F){
00215       fprintf(fd,"%sCONTACT METHOD=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00216       i+=2;
00217    }
00218    if(print_encoded_uri(fd,&payload[i],payload[1],hdr,hdrlen,strcat(prefix,"  "))<0){
00219       prefix[strlen(prefix)-2]=0;
00220       fprintf(fd,"Error parsing URI\n");
00221       return -1;
00222    }
00223    prefix[strlen(prefix)-2]=0;
00224 
00225    print_encoded_parameters(fd,(unsigned char*)&payload[i+payload[1]],hdr,paylen-i-payload[1],prefix);
00226    return 0;
00227 }
00228 
00229 
00230 /**
00231  *
00232  */
00233 int dump_contact_body_test(char *hdr,int hdrlen,unsigned char *payload,int paylen,FILE *fd,char segregationLevel,char *prefix)
00234 {
00235    unsigned char flags, numcontacts;
00236    int i,offset;
00237 
00238    flags=payload[0];
00239 
00240    if(!segregationLevel){
00241       return dump_standard_hdr_test(hdr,hdrlen,payload,paylen,fd);
00242    }
00243    if(flags & STAR_F){
00244       return 1;
00245    }
00246    numcontacts=payload[1];
00247    if(numcontacts==0){
00248       LM_ERR("no contacts present?\n");
00249       return -1;
00250    }
00251    if(segregationLevel & (JUNIT|SEGREGATE|ONLY_URIS)){
00252       for(i=0,offset=2+numcontacts;i<numcontacts;i++){
00253     dump_contact_test(hdr,hdrlen,&payload[offset],payload[2+i],fd,segregationLevel,prefix);
00254     offset+=payload[2+i];
00255       }
00256    }
00257    return 1;
00258 }
00259 
00260 int dump_contact_test(char *hdr,int hdrlen,unsigned char* payload,int paylen,FILE *fd,char segregationLevel,char *prefix)
00261 {
00262    int i=2;/* flags + urilength */
00263    unsigned char flags=0;
00264 
00265    flags=payload[0];
00266    if((segregationLevel & SEGREGATE)&& !(segregationLevel & ONLY_URIS))
00267       return dump_standard_hdr_test(hdr,hdrlen,payload,paylen,fd);
00268    i=2;
00269    if(flags & HAS_NAME_F)
00270       i+=2;
00271    if(flags & HAS_Q_F)
00272       i+=2;
00273    if(flags & HAS_EXPIRES_F)
00274       i+=2;
00275    if(flags & HAS_RECEIVED_F)
00276       i+=2;
00277    if(flags & HAS_METHOD_F)
00278       i+=2;
00279    if(!(segregationLevel & JUNIT) && (segregationLevel & ONLY_URIS))
00280       return dump_standard_hdr_test(hdr,hdrlen,(&payload[i]),(int)payload[1],fd);
00281    if((segregationLevel & JUNIT) && (segregationLevel & ONLY_URIS))
00282       return print_uri_junit_tests(hdr,hdrlen,&payload[i],payload[1],fd,1,"");
00283    if((segregationLevel & JUNIT) && !(segregationLevel & ONLY_URIS)){
00284       i=2;
00285       fprintf(fd,"%sgetAddress.getDisplayName=(S)",prefix);
00286       if(flags & HAS_NAME_F){
00287     fprintf(fd,"%.*s\n",payload[i+1],&hdr[payload[i]]);
00288     i+=2;
00289       }else
00290     fprintf(fd,"(null)\n");
00291       fprintf(fd,"%sgetQValue=(F)",prefix);
00292       if(flags & HAS_Q_F){
00293     fprintf(fd,"%.*s\n",payload[i+1],&hdr[payload[i]]);
00294     i+=2;
00295       }else
00296     fprintf(fd,"(null)\n");
00297       fprintf(fd,"%sgetExpires=(I)",prefix);
00298       if(flags & HAS_EXPIRES_F){
00299     fprintf(fd,"%.*s\n",payload[i+1],&hdr[payload[i]]);
00300     i+=2;
00301       }else
00302     fprintf(fd,"(null)\n");
00303       if(flags & HAS_RECEIVED_F){
00304     i+=2;
00305       }
00306       if(flags & HAS_METHOD_F){
00307     i+=2;
00308       }
00309       fprintf(fd,"%sgetParameter=(SAVP)",prefix);
00310       for(i+=payload[1];i<paylen-1;i+=2){
00311     printf("%.*s=",payload[i+1]-payload[i]-1,&hdr[payload[i]]);
00312     printf("%.*s;",(payload[i+2]-payload[i+1])==0?0:(payload[i+2]-payload[i+1]-1),&hdr[payload[i+1]]);
00313       }
00314       fprintf(fd,"\n");
00315    }
00316    return 0;
00317 }

Generated on Tue May 22 16:00:27 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6