msg_parser.h

Go to the documentation of this file.
00001 /*
00002  * $Id: msg_parser.h 5146 2008-10-31 10:43:11Z miconda $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History
00023  * -------
00024  *  2003-01-28  removed scratchpad (jiri)
00025  *  2003-02-28  scratchpad compatibility abandoned (jiri)
00026  *  2003-03-06  enum_request_method changed to begin with 1;
00027  *               0 reserved for invalid values; (jiri)
00028  *  2003-03-31  removed sip_msg->repl_add_rm (andrei)
00029  *  2003-04-01  2 macros added: GET_NEXT_HOP and GET_RURI (janakj)
00030  *  2003-04-04  structure for parsed inbound uri added (jiri)
00031  *  2003-04-11  updated the  sip_uri structure (lots of fields added) (andrei)
00032  *  2003-04-12  added msg_flags to sip_msg (andrei)
00033  *  2003-11-02  added diversion header field to sip_msg (jh)
00034  *  2004-11-08  added force_send_socket (andrei)
00035  *  2005-02-25  uri types added (sip, sips & tel)  (andrei)
00036  *  2006-02-17  Session-Expires, Min-SE (dhsueh@somanetworks.com)
00037  *  2007-09-09  added sdp structure (osas)
00038  */
00039 
00040 /*!
00041  * \file
00042  * \brief SIP message parser
00043  * \ingroup parser
00044  */
00045 
00046 #ifndef MSG_PARSER_H
00047 #define MSG_PARSER_H
00048 
00049 #include "../str.h"
00050 #include "../lump_struct.h"
00051 #include "../flags.h"
00052 #include "../ip_addr.h"
00053 #include "../md5utils.h"
00054 #include "../config.h"
00055 #include "parse_def.h"
00056 #include "parse_cseq.h"
00057 #include "parse_via.h"
00058 #include "parse_fline.h"
00059 #include "hf.h"
00060 #include "sdp/sdp.h"
00061 
00062 
00063 /* convenience short-cut macros */
00064 #define REQ_LINE(_msg) ((_msg)->first_line.u.request)
00065 #define REQ_METHOD first_line.u.request.method_value
00066 #define REPLY_STATUS first_line.u.reply.statuscode
00067 #define REPLY_CLASS(_reply) ((_reply)->REPLY_STATUS/100)
00068 
00069 /* number methods as power of two to allow bitmap matching */
00070 enum request_method {
00071    METHOD_UNDEF=0,           /* 0 - --- */
00072    METHOD_INVITE=1,          /* 1 - 2^0 */
00073    METHOD_CANCEL=2,          /* 2 - 2^1 */
00074    METHOD_ACK=4,             /* 3 - 2^2 */
00075    METHOD_BYE=8,             /* 4 - 2^3 */
00076    METHOD_INFO=16,           /* 5 - 2^4 */
00077    METHOD_OPTIONS=32,        /* 6 - 2^5 */
00078    METHOD_UPDATE=64,         /* 7 - 2^6 */
00079    METHOD_REGISTER=128,      /* 8 - 2^7 */
00080    METHOD_MESSAGE=256,       /* 9 - 2^8 */
00081    METHOD_SUBSCRIBE=512,     /* 10 - 2^9 */
00082    METHOD_NOTIFY=1024,       /* 11 - 2^10 */
00083    METHOD_PRACK=2048,        /* 12 - 2^11 */
00084    METHOD_REFER=4096,        /* 13 - 2^12 */
00085    METHOD_PUBLISH=8192,      /* 14 - 2^13 */
00086    METHOD_OTHER=16384        /* 15 - 2^14 */
00087 };
00088 
00089 #define FL_FORCE_RPORT       (1<<0)  /*!< force rport (top via) */
00090 #define FL_FORCE_ACTIVE      (1<<1)  /*!< force active SDP */
00091 #define FL_FORCE_LOCAL_RPORT (1<<2)  /*!< force local rport (local via) */
00092 #define FL_SDP_IP_AFS        (1<<3)  /*!< SDP IP rewritten */
00093 #define FL_SDP_PORT_AFS      (1<<4)  /*!< SDP port rewritten */
00094 #define FL_SHM_CLONE         (1<<5)  /*!< msg cloned in SHM as a single chunk */
00095 #define FL_USE_UAC_FROM      (1<<6)  /*!< take FROM hdr from UAC insteas of UAS*/
00096 #define FL_USE_UAC_TO        (1<<7)  /*!< take TO hdr from UAC insteas of UAS */
00097 #define FL_USE_UAC_CSEQ      (1<<8)  /*!< take CSEQ hdr from UAC insteas of UAS*/
00098 #define FL_REQ_UPSTREAM      (1<<9)  /*!< it's an upstream going request */
00099 #define FL_DO_KEEPALIVE      (1<<10) /*!< keepalive request's source after a
00100                  positive reply */
00101 #define FL_USE_MEDIA_PROXY   (1<<11) /*!< use mediaproxy on all messages during a dialog */
00102 
00103 
00104 #define IFISMETHOD(methodname,firstchar)                                  \
00105 if (  (*tmp==(firstchar) || *tmp==((firstchar) | 32)) &&                  \
00106         strncasecmp( tmp+1, #methodname +1, methodname##_LEN-1)==0 &&     \
00107         *(tmp+methodname##_LEN)==' ') {                                   \
00108                 fl->type=SIP_REQUEST;                                     \
00109                 fl->u.request.method.len=methodname##_LEN;                \
00110                 fl->u.request.method_value=METHOD_##methodname;           \
00111                 tmp=buffer+methodname##_LEN;                              \
00112 }
00113 
00114 
00115 /*!
00116  * Return a URI to which the message should be really sent (not what should
00117  * be in the Request URI. The following fields are tried in this order:
00118  * 1) dst_uri
00119  * 2) new_uri
00120  * 3) first_line.u.request.uri
00121  */
00122 #define GET_NEXT_HOP(m) \
00123 (((m)->dst_uri.s && (m)->dst_uri.len) ? (&(m)->dst_uri) : \
00124 (((m)->new_uri.s && (m)->new_uri.len) ? (&(m)->new_uri) : (&(m)->first_line.u.request.uri)))
00125 
00126 
00127 /*!
00128  * Return the Reqeust URI of a message.
00129  * The following fields are tried in this order:
00130  * 1) new_uri
00131  * 2) first_line.u.request.uri
00132  */
00133 #define GET_RURI(m) \
00134 (((m)->new_uri.s && (m)->new_uri.len) ? (&(m)->new_uri) : (&(m)->first_line.u.request.uri))
00135 
00136 
00137 enum _uri_type{ERROR_URI_T=0, SIP_URI_T, SIPS_URI_T, TEL_URI_T, TELS_URI_T};
00138 typedef enum _uri_type uri_type;
00139 
00140 struct sip_uri {
00141    str user;     /*!< Username */
00142    str passwd;   /*!< Password */
00143    str host;     /*!< Host name */
00144    str port;     /*!< Port number */
00145    str params;   /*!< Parameters */
00146    str headers;
00147    unsigned short port_no;
00148    unsigned short proto; /*!< from transport */
00149    uri_type type; /*!< uri scheme */
00150    /* parameters */
00151    str transport;
00152    str ttl;
00153    str user_param;
00154    str maddr;
00155    str method;
00156    str lr;
00157    str r2; /*!< ser specific rr parameter */
00158    /* values */
00159    str transport_val;
00160    str ttl_val;
00161    str user_param_val;
00162    str maddr_val;
00163    str method_val;
00164    str lr_val; /*!< lr value placeholder for lr=on a.s.o*/
00165    str r2_val;
00166 };
00167 
00168 
00169 #include "parse_to.h"
00170 
00171 struct sip_msg {
00172    unsigned int id;               /*!< message id, unique/process*/
00173    struct msg_start first_line;   /*!< Message first line */
00174    struct via_body* via1;         /*!< The first via */
00175    struct via_body* via2;         /*!< The second via */
00176    struct hdr_field* headers;     /*!< All the parsed headers*/
00177    struct hdr_field* last_header; /*!< Pointer to the last parsed header*/
00178    hdr_flags_t parsed_flag;       /*!< Already parsed header field types */
00179 
00180    /* Via, To, CSeq, Call-Id, From, end of header*/
00181    /* pointers to the first occurrences of these headers;
00182     * everything is also saved in 'headers'
00183     * (WARNING: do not deallocate them twice!)*/
00184 
00185    struct hdr_field* h_via1;
00186    struct hdr_field* h_via2;
00187    struct hdr_field* callid;
00188    struct hdr_field* to;
00189    struct hdr_field* cseq;
00190    struct hdr_field* from;
00191    struct hdr_field* contact;
00192    struct hdr_field* maxforwards;
00193    struct hdr_field* route;
00194    struct hdr_field* record_route;
00195    struct hdr_field* path;
00196    struct hdr_field* content_type;
00197    struct hdr_field* content_length;
00198    struct hdr_field* authorization;
00199    struct hdr_field* expires;
00200    struct hdr_field* proxy_auth;
00201    struct hdr_field* supported;
00202    struct hdr_field* proxy_require;
00203    struct hdr_field* unsupported;
00204    struct hdr_field* allow;
00205    struct hdr_field* event;
00206    struct hdr_field* accept;
00207    struct hdr_field* accept_language;
00208    struct hdr_field* organization;
00209    struct hdr_field* priority;
00210    struct hdr_field* subject;
00211    struct hdr_field* user_agent;
00212    struct hdr_field* content_disposition;
00213    struct hdr_field* accept_disposition;
00214    struct hdr_field* diversion;
00215    struct hdr_field* rpid;
00216    struct hdr_field* refer_to;
00217    struct hdr_field* session_expires;
00218    struct hdr_field* min_se;
00219    struct hdr_field* ppi;
00220    struct hdr_field* pai;
00221    struct hdr_field* privacy;
00222 
00223    struct sdp_info* sdp;
00224 
00225    char* eoh;        /*!< pointer to the end of header (if found) or null */
00226    char* unparsed;   /*!< here we stopped parsing*/
00227    
00228    struct receive_info rcv; /*!< source & dest ip, ports, proto a.s.o */
00229 
00230    char* buf;        /*!< scratch pad, holds a unmodified message,
00231             via, etc. point into it */
00232    unsigned int len; /*!< message len (orig) */
00233 
00234    /* modifications */
00235 
00236    str new_uri; /*!< changed first line uri, when you change this
00237            don't forget to set parsed_uri_ok to 0 */
00238 
00239    str dst_uri; /*!< Destination URI, must be forwarded to this URI if len!=0 */
00240    
00241    /* current uri */
00242    int parsed_uri_ok; /*!< 1 if parsed_uri is valid, 0 if not, set it to 0
00243                          if you modify the uri (e.g change new_uri)*/
00244    struct sip_uri parsed_uri; /*!< speed-up > keep here the parsed uri*/
00245 
00246    /* the same for original uri */
00247    int parsed_orig_ruri_ok;
00248    struct sip_uri parsed_orig_ruri;
00249 
00250    struct lump* add_rm;         /*!< used for all the forwarded requests/replies */
00251    struct lump* body_lumps;     /*!< Lumps that update Content-Length */
00252    struct lump_rpl *reply_lump; /*!< only for localy generated replies !!!*/
00253 
00254    /*! whatever whoever want to append to branch comes here */
00255    char add_to_branch_s[MAX_BRANCH_PARAM_LEN];
00256    int add_to_branch_len;
00257    
00258    /*! index to TM hash table; stored in core to avoid 
00259     * unnecessary calculations */
00260    unsigned int  hash_index;
00261    int  branch_index; /* sip reply matching branch */
00262 
00263    /*! flags used from script */
00264    flag_t flags;
00265 
00266    /*! flags used by core - allows to set various flags on the message; may 
00267     * be used for simple inter-module communication or remembering 
00268     * processing state reached */
00269    unsigned int msg_flags;
00270 
00271    str set_global_address;
00272    str set_global_port;
00273 
00274    /*! force sending on this socket */
00275    struct socket_info* force_send_socket;
00276 
00277    /*! create a route HF out of this path vector */
00278    str path_vec;
00279 };
00280 
00281 
00282 /*! pointer to a fakes message which was never received ;
00283    (when this message is "relayed", it is generated out
00284     of the original request)
00285 */
00286 #define FAKED_REPLY     ((struct sip_msg *) -1)
00287 
00288 extern int via_cnt;
00289 
00290 int parse_msg(char* buf, unsigned int len, struct sip_msg* msg);
00291 
00292 int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next);
00293 
00294 char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr);
00295 
00296 void free_sip_msg(struct sip_msg* msg);
00297 
00298 /* make sure all HFs needed for transaction identification have been
00299    parsed; return 0 if those HFs can't be found
00300  */
00301 
00302 int check_transaction_quadruple( struct sip_msg* msg );
00303 
00304 /*! calculate characteristic value of a message -- this value
00305    is used to identify a transaction during the process of
00306    reply matching
00307  */
00308 inline static int char_msg_val( struct sip_msg *msg, char *cv )
00309 {
00310    str src[8];
00311 
00312    if (!check_transaction_quadruple(msg)) {
00313       LM_ERR("can't calculate char_value due to a parsing error\n");
00314       memset( cv, '0', MD5_LEN );
00315       return 0;
00316    }
00317 
00318    src[0]= msg->from->body;
00319    src[1]= msg->to->body;
00320    src[2]= msg->callid->body;
00321    src[3]= msg->first_line.u.request.uri;
00322    src[4]= get_cseq( msg )->number;
00323    
00324    /* topmost Via is part of transaction key as well ! */
00325    src[5]= msg->via1->host;
00326    src[6]= msg->via1->port_str;
00327    if (msg->via1->branch) {
00328       src[7]= msg->via1->branch->value;
00329       MD5StringArray ( cv, src, 8 );
00330    } else {
00331       MD5StringArray( cv, src, 7 );
00332    }
00333    return 1;
00334 }
00335 
00336 
00337 /*! returns a pointer to the begining of the msg's body
00338  */
00339 inline static char* get_body(struct sip_msg *msg)
00340 {
00341    int offset;
00342    unsigned int len;
00343 
00344    if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
00345       return 0;
00346 
00347    if (msg->unparsed){
00348       len=(unsigned int)(msg->unparsed-msg->buf);
00349    }else return 0;
00350    if ((len+2<=msg->len) && (strncmp(CRLF,msg->unparsed,CRLF_LEN)==0) )
00351       offset = CRLF_LEN;
00352    else if ( (len+1<=msg->len) &&
00353             (*(msg->unparsed)=='\n' || *(msg->unparsed)=='\r' ) )
00354       offset = 1;
00355    else
00356       return 0;
00357 
00358    return msg->unparsed + offset;
00359 }
00360 
00361 
00362 /*!
00363  * Make a private copy of the string and assign it to dst_uri
00364  */
00365 int set_dst_uri(struct sip_msg* msg, str* uri);
00366 
00367 /*!
00368  * Make a private copy of the string and assign it to path_vec
00369  */
00370 int set_path_vector(struct sip_msg* msg, str* path);
00371 
00372 
00373 #endif

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