encode_uri.c

Go to the documentation of this file.
00001 /* $Id: encode_uri.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:  xuri.c
00026  * 
00027  *     Description:  first trial to implement xuri
00028  * 
00029  *         Version:  1.0
00030  *         Created:  16/11/05 18:07:24 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 <assert.h>
00043 #include <string.h>
00044 #include <netinet/in.h>
00045 #include "../../mem/mem.h"
00046 #include "../../parser/msg_parser.h"
00047 #include "../../dprint.h"
00048 #include "encode_uri.h"
00049 #include "encode_parameters.h"
00050 #include "encode_header.h"
00051 #include "xaddress.h"
00052 
00053 #define REL_PTR(a,b) ((unsigned char)(b-a))
00054 
00055 /*The XURI is one of the most important parts in SEAS, as
00056  * most of the SIP MESSAGE structured headers (that is,
00057  * headers which have a well-specified body construction)
00058  * use the URI as the body (ie. via, route, record-route,
00059  * contact, from, to, RURI)
00060  *
00061  * the XURI is a codified structure of flags and pointers
00062  * that ease the parsing of the URI string.
00063  *
00064  * 1: The first byte of the structure, is a
00065  * HEADER_START-based pointer to the beginning of the URI
00066  * (including the "sip:").  
00067  * 1: The next byte is the length of the uri, so URIMAX 
00068  * is 256 (enough...) 
00069  * 2: Flags specifying the parts that are present in the URI
00070  *
00071  * as follows:
00072  *    1: first byte
00073  *       SIP_OR_TEL_F   0x01 it is SIP or TEL uri.
00074  *    SECURE_F 0x02 it is secure or not (SIPS,TELS)
00075  *    USER_F      0x04 it as a user part (user@host)
00076  *    PASSWORD_F  0x08 it has a password part
00077  *    HOST_F      0x10 it has a host part
00078  *    PORT_F      0x20 it has a port part
00079  *    PARAMETERS_F   0x40 it has a port part
00080  *    HEADERS_F   0x80 it has a port part
00081  * 1: second byte
00082  *    TRANSPORT_F 0x01 it has other parameters
00083  *    TTL_F    0x02 it has headers
00084  *    USER_F      0x04 it has the transport parameter
00085  *    METHOD_F 0x08 it has the ttl parameter
00086  *    MADDR_F     0x10 it has the user parameter
00087  *    LR_F     0x20 it has the method parameter
00088  *
00089  * All the following bytes are URI_START-based pointers to
00090  * the fields that are present in the uri, as specified by
00091  * the flags. They must appear in the same order shown in
00092  * the flags, and only appear if the flag was set to 1.
00093  *
00094  * the end of the field, will be the place where the
00095  * following pointer points to, minus one (note that all the
00096  * fields present in a URI are preceded by 1 character, ie
00097  * sip[:user][:passwod][@host][:port][;param1=x][;param2=y][?hdr1=a][&hdr2=b]$p
00098  * it will be necessary to have a pointer at the end,
00099  * pointing two past the end of the uri, so that the length
00100  * of the last header can be computed.
00101  *
00102  * The reason to have the OTHER and HEADERS flags at the
00103  * beginning(just after the strictly-uri stuff), is that it
00104  * will be necessary to know the length of the parameters
00105  * section and the headers section.  
00106  *
00107  * The parameters can
00108  * appear in an arbitrary order, so they won't be following
00109  * the convention of transport-ttl-user-method-maddr-lr, so
00110  * we can't rely on the next pointer to compute the length
00111  * of the previous pointer field, as the ttl param can 
00112  * appear before the transport param. so the parameter 
00113  * pointers must have 2 bytes: pointer+length.
00114  *
00115  */
00116 int encode_uri2(char *hdr,int hdrlen,str uri_str, struct sip_uri *uri_parsed,unsigned char *payload)
00117 {
00118    int i=4,j;/* 1*pointer+1*len+2*flags*/
00119    unsigned int scheme;
00120    unsigned char flags1=0,flags2=0,uriptr;
00121 
00122    uriptr=REL_PTR(hdr,uri_str.s);
00123    if(uri_str.len>255 || uriptr>hdrlen){
00124       LM_ERR("uri too long, or out of the sip_msg bounds\n");
00125       return -1;
00126    }
00127    payload[0]=uriptr;
00128    payload[1]=(unsigned char)uri_str.len;
00129    if(uri_parsed->user.s && uri_parsed->user.len){
00130       flags1 |= USER_F;
00131       payload[i++]=REL_PTR(uri_str.s,uri_parsed->user.s);
00132    }
00133    if(uri_parsed->passwd.s && uri_parsed->passwd.len){
00134       flags1 |= PASSWORD_F;
00135       payload[i++]=REL_PTR(uri_str.s,uri_parsed->passwd.s);
00136    }
00137    if(uri_parsed->host.s && uri_parsed->host.len){
00138       flags1 |= HOST_F;
00139       payload[i++]=REL_PTR(uri_str.s,uri_parsed->host.s);
00140    }
00141    if(uri_parsed->port.s && uri_parsed->port.len){
00142       flags1 |= PORT_F;
00143       payload[i++]=REL_PTR(uri_str.s,uri_parsed->port.s);
00144    }
00145    if(uri_parsed->params.s && uri_parsed->params.len){
00146       flags1 |= PARAMETERS_F;
00147       payload[i++]=REL_PTR(uri_str.s,uri_parsed->params.s);
00148    }
00149    if(uri_parsed->headers.s && uri_parsed->headers.len){
00150       flags1 |= HEADERS_F;
00151       payload[i++]=REL_PTR(uri_str.s,uri_parsed->headers.s);
00152    }
00153    payload[i]=(unsigned char)(uri_str.len+1);
00154    i++;
00155 
00156    if(uri_parsed->transport.s && uri_parsed->transport.len){
00157       flags2 |= TRANSPORT_F;
00158       payload[i]=REL_PTR(uri_str.s,uri_parsed->transport.s);
00159       payload[i+1]=(unsigned char)(uri_parsed->transport.len);
00160       i+=2;
00161    }
00162    if(uri_parsed->ttl.s && uri_parsed->ttl.len){
00163       flags2 |= TTL_F;
00164       payload[i]=REL_PTR(uri_str.s,uri_parsed->ttl.s);
00165       payload[i+1]=(unsigned char)uri_parsed->ttl.len;
00166       i+=2;
00167    }
00168    if(uri_parsed->user_param.s && uri_parsed->user_param.len){
00169       flags2 |= USER_F;
00170       payload[i]=REL_PTR(uri_str.s,uri_parsed->user_param.s);
00171       payload[i+1]=(unsigned char)uri_parsed->user_param.len;
00172       i+=2;
00173    }
00174    if(uri_parsed->method.s && uri_parsed->method.len){
00175       flags2 |= METHOD_F;
00176       payload[i]=REL_PTR(uri_str.s,uri_parsed->method.s);
00177       payload[i+1]=(unsigned char)uri_parsed->method.len;
00178       i+=2;
00179    }
00180    if(uri_parsed->maddr.s && uri_parsed->maddr.len){
00181       flags2 |= MADDR_F;
00182       payload[i]=REL_PTR(uri_str.s,uri_parsed->maddr.s);
00183       payload[i+1]=(unsigned char)uri_parsed->maddr.len;
00184       i+=2;
00185    }
00186    if(uri_parsed->lr.s && uri_parsed->lr.len){
00187       flags2 |= LR_F;
00188       payload[i]=REL_PTR(uri_str.s,uri_parsed->lr.s);
00189       payload[i+1]=(unsigned char)uri_parsed->lr.len;
00190       i+=2;
00191    }
00192    /*in parse_uri, when there's a user=phone, the type
00193     * is set to TEL_URI_T, even if there's a sip: in the beginning
00194     * so lets check it by ourselves:
00195    switch(uri_parsed->type){
00196       case SIP_URI_T:
00197     flags1 |= SIP_OR_TEL_F;
00198     break;
00199       case SIPS_URI_T:
00200     flags1 |= (SIP_OR_TEL_F|SECURE_F);
00201     break;
00202       case TEL_URI_T:
00203     break;
00204       case TELS_URI_T:
00205     flags1 |= SECURE_F;
00206     break;
00207       default:
00208     return -1;
00209    }*/
00210 #define SIP_SCH      0x3a706973
00211 #define SIPS_SCH  0x73706973
00212 #define TEL_SCH      0x3a6c6574
00213 #define TELS_SCH  0x736c6574
00214    scheme=uri_str.s[0]+(uri_str.s[1]<<8)+(uri_str.s[2]<<16)+(uri_str.s[3]<<24);
00215    scheme|=0x20202020;
00216    if (scheme==SIP_SCH){
00217       flags1 |= SIP_OR_TEL_F;
00218    }else if(scheme==SIPS_SCH){
00219       if(uri_str.s[4]==':'){
00220     flags1 |= (SIP_OR_TEL_F|SECURE_F);
00221       }else goto error;
00222    }else if (scheme==TEL_SCH){
00223       /*nothing*/
00224    }else if (scheme==TELS_SCH){
00225       if(uri_str.s[4]==':'){
00226     flags1 |= SECURE_F;
00227       }
00228    }else goto error;
00229    
00230    payload[2]=flags1;
00231    payload[3]=flags2;
00232    j=i;
00233    i+=encode_parameters(&payload[i],uri_parsed->params.s,uri_str.s,&uri_parsed->params.len,'u');
00234    if(i<j)
00235       goto error;
00236    return i;
00237 error:
00238    return -1;
00239 }
00240 
00241 int print_encoded_uri(FILE *fd,unsigned char *payload,int paylen,char *hdrstart,int hdrlen,char *prefix)
00242 {
00243    int i=4,j=0;/*1*pointer+1*len+2*flags*/
00244    unsigned char uriidx=0,flags1=0,flags2=0,urilen;
00245    char *ch_uriptr,*uritype=NULL,*secure=NULL;
00246 
00247    uriidx=payload[0];
00248    fprintf(fd,"%s",prefix);
00249    for(j=0;j<paylen;j++)
00250       fprintf(fd,"%s%d%s",j==0?"ENCODED-URI:[":":",payload[j],j==paylen-1?"]\n":"");
00251    if(uriidx>hdrlen){
00252       fprintf(fd,"bad index for start of uri: hdrlen=%d uri_index=%d\n",hdrlen,uriidx);
00253       return -1;
00254    }
00255    ch_uriptr = hdrstart+uriidx;
00256    urilen=payload[1];
00257    flags1=payload[2];
00258    flags2=payload[3];
00259    fprintf(fd,"%sURI:[%.*s]\n",prefix,urilen,ch_uriptr);
00260    uritype=flags1&SIP_OR_TEL_F?"SIP":"TEL";
00261    secure=flags1&SECURE_F?"S":"";
00262    fprintf(fd,"%s  TYPE:[%s%s]\n",prefix,uritype,secure);
00263    if(flags1 & USER_F){
00264       fprintf(fd,"%s  USER:[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
00265       ++i;
00266    }
00267    if(flags1 & PASSWORD_F){
00268       fprintf(fd,"%s  PASSWORD=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
00269       ++i;
00270    }
00271    if(flags1 & HOST_F){
00272       fprintf(fd,"%s  HOST=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
00273       ++i;
00274    }
00275    if(flags1 & PORT_F){
00276       fprintf(fd,"%s  PORT=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
00277       ++i;
00278    }
00279    if(flags1 & PARAMETERS_F){
00280       fprintf(fd,"%s  PARAMETERS=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
00281       ++i;
00282    }
00283    if(flags1 & HEADERS_F){
00284       fprintf(fd,"%s  HEADERS=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
00285       ++i;
00286    }
00287    ++i;
00288    if(flags2 & TRANSPORT_F){
00289       fprintf(fd,"%s  TRANSPORT=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]);
00290       i+=2;
00291    }
00292    if(flags2 & TTL_F){
00293       fprintf(fd,"%s  TTL_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]);
00294       i+=2;
00295    }
00296    if(flags2 & USER_F){
00297       fprintf(fd,"%s  USER_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]);
00298       i+=2;
00299    }
00300    if(flags2 & METHOD_F){
00301       fprintf(fd,"%s  METHOD_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]);
00302       i+=2;
00303    }
00304    if(flags2 & MADDR_F){
00305       fprintf(fd,"%s  MADDR_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]);
00306       i+=2;
00307    }
00308    if(flags2 & LR_F){
00309       fprintf(fd,"%s  LR_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]);
00310       i+=2;
00311    }
00312    print_encoded_parameters(fd,&payload[i],ch_uriptr,paylen-i,prefix);
00313    return 0;
00314 }
00315 
00316 
00317 int print_uri_junit_tests(char *hdrstart,int hdrlen,unsigned char *payload,int paylen,FILE *fd,char also_hdr,char *prefix)
00318 {
00319    int i=4,k=0,m=0;/*1*pointer+1*len+2*flags*/
00320    unsigned char uriidx=0,flags1=0,flags2=0,urilen;
00321    char *ch_uriptr,*aux,*aux2,*aux3,*uritype=NULL,*secure=NULL;
00322 
00323    uriidx=payload[0];
00324    if(uriidx>hdrlen){
00325       fprintf(fd,"bad index for start of uri: hdrlen=%d uri_index=%d\n",hdrlen,uriidx);
00326       return -1;
00327    }
00328 
00329    if(also_hdr)
00330       dump_standard_hdr_test(hdrstart,hdrlen,payload,paylen,fd);
00331    ch_uriptr = hdrstart+uriidx;
00332    urilen=payload[1];
00333    flags1=payload[2];
00334    flags2=payload[3];
00335    fprintf(fd,"%stoString=(S)%.*s\n",prefix,urilen,ch_uriptr);
00336    uritype=flags1&SIP_OR_TEL_F?"sip":"tel";
00337    secure=flags1&SECURE_F?"s":"";
00338    fprintf(fd,"%sgetScheme=(S)%s%s\n",prefix,uritype,secure);
00339    fprintf(fd,"%sisSecure=(B)%s\n",prefix,flags1&SECURE_F?"true":"false");
00340    fprintf(fd,"%sisSipURI=(B)%s\n",prefix,"true");
00341    fprintf(fd,"%sgetUser=(S)",prefix);
00342    if(flags1 & USER_F){
00343       fprintf(fd,"%.*s\n",(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
00344       ++i;
00345    }else 
00346       fprintf(fd,"(null)\n");
00347    fprintf(fd,"%sgetUserPassword=(S)",prefix);
00348    if(flags1 & PASSWORD_F){
00349       fprintf(fd,"%.*s\n",(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
00350       ++i;
00351    }else
00352       fprintf(fd,"(null)\n");
00353    fprintf(fd,"%sgetHost=(S)",prefix);
00354    if(flags1 & HOST_F){
00355       fprintf(fd,"%.*s\n",(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
00356       ++i;
00357    }else
00358       fprintf(fd,"(null)\n");/*can't happen*/
00359    fprintf(fd,"%sgetPort=(I)",prefix);
00360    if(flags1 & PORT_F){
00361       fprintf(fd,"%.*s\n",(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]);
00362       ++i;
00363    }else
00364       fprintf(fd,"(null)\n");
00365    /*user=phone;transport=udp*/
00366    if(flags1 & PARAMETERS_F){
00367       aux=&ch_uriptr[payload[i]];
00368       aux2=NULL;
00369       aux3=aux;
00370       m=(payload[i+1]-1-payload[i]);
00371       fprintf(fd,"%sgetParameter=(SAVP)",prefix);/*SVP = Attribute Value Pair*/
00372       for(k=0;k<=m;k++){
00373     if((aux3[k]==';'||(k==m)) && aux2==NULL){/*no parameterValue was found*/
00374        fprintf(fd,"%.*s=;",(int)(aux3-aux+k),aux);
00375        aux2=NULL;/*resets the parameterValue-start pointer*/
00376        aux=aux3+1+k;/*points to the next parameter*/
00377     }else 
00378        if((aux3[k]==';'||(k==m)) && aux2!=NULL){
00379           fprintf(fd,"%.*s=%.*s;",(int)(aux2-aux),aux,(int)(aux3-aux2-1+k),aux2+1);
00380           aux2=NULL;
00381           aux=aux3+1+k;
00382        } else 
00383           if(aux3[k]=='='){
00384         aux2=aux3+k;
00385           }
00386       }
00387       fprintf(fd,"\n");
00388       ++i;
00389    }
00390    if(flags1 & HEADERS_F){
00391       aux=&ch_uriptr[payload[i]];
00392       aux2=NULL;
00393       aux3=aux;
00394       m=(payload[i+1]-1-payload[i]);
00395       fprintf(fd,"%sgetHeader=(SAVP)",prefix);
00396       for(k=0;k<=m;k++){
00397     if((aux3[k]==';'||(k==m)) && aux2==NULL){/*no parameterValue was found*/
00398        fprintf(fd,"%.*s=;",(int)(aux3-aux+k),aux);
00399        aux2=NULL;/*resets the parameterValue-start pointer*/
00400        aux=aux3+1+k;/*points to the next parameter*/
00401     }else 
00402        if((aux3[k]==';'||(k==m)) && aux2!=NULL){
00403           fprintf(fd,"%.*s=%.*s;",(int)(aux2-aux),aux,(int)(aux3-aux2-1+k),aux2+1);
00404           aux2=NULL;
00405           aux=aux3+1+k;
00406        } else 
00407           if(aux3[k]=='='){
00408         aux2=aux3+k;
00409           }
00410       }
00411       fprintf(fd,"\n");
00412       ++i;
00413    }
00414    ++i;
00415    fprintf(fd,"%sgetTransportParam=(S)",prefix);
00416    if(flags2 & TRANSPORT_F){
00417       fprintf(fd,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]);
00418       i+=2;
00419    }else
00420       fprintf(fd,"(null)\n");
00421    fprintf(fd,"%sgetTTLparam=(I)",prefix);
00422    if(flags2 & TTL_F){
00423       fprintf(fd,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]);
00424       i+=2;
00425    }else
00426       fprintf(fd,"(null)\n");
00427    fprintf(fd,"%sgetUserParam=(S)",prefix);
00428    if(flags2 & USER_F){
00429       fprintf(fd,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]);
00430       i+=2;
00431    }else
00432       fprintf(fd,"(null)\n");
00433    fprintf(fd,"%sgetMethodParam=(S)",prefix);
00434    if(flags2 & METHOD_F){
00435       fprintf(fd,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]);
00436       i+=2;
00437    }else
00438       fprintf(fd,"(null)\n");
00439    fprintf(fd,"%sgetMAddrParam=(S)",prefix);
00440    if(flags2 & MADDR_F){
00441       fprintf(fd,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]);
00442       i+=2;
00443    }else
00444       fprintf(fd,"(null)\n");
00445    if(flags2 & LR_F){
00446       i+=2;
00447    }
00448    fprintf(fd,"\n");
00449    return 0;
00450 }

Generated on Wed May 23 06:00:45 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6