parser/msg_parser.h
512dcd98
 /*
  * $Id$
7dd0b342
  *
c32feee5
  * Copyright (C) 2001-2003 FhG Fokus
7dd0b342
  *
  * This file is part of ser, a free SIP server.
  *
  * ser is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
  * For a license to use the ser software under conditions
  * other than those described here, or to purchase support for this
  * software, please contact iptel.org by e-mail at the following addresses:
  *    info@iptel.org
  *
  * ser is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
049f64c2
  *
18dbc018
  * History
  * -------
f15bede1
  *  2003-01-28  removed scratchpad (jiri)
4b50480e
  *  2003-02-28  scratchpad compatibility abandoned (jiri)
  *  2003-03-06  enum_request_method changed to begin with 1;
  *               0 reserved for invalid values; (jiri)
f15bede1
  *  2003-03-31  removed sip_msg->repl_add_rm (andrei)
de0062e6
  *  2003-04-01  2 macros added: GET_NEXT_HOP and GET_RURI (janakj)
b2fcef3c
  *  2003-04-04  structure for parsed inbound uri added (jiri)
4b50480e
  *  2003-04-11  updated the  sip_uri structure (lots of fields added) (andrei)
3e8c3475
  *  2003-04-12  added msg_flags to sip_msg (andrei)
dccbcda9
  *  2003-11-02  added diversion header field to sip_msg (jh)
a35ad52c
  *  2004-11-08  added force_send_socket (andrei)
2518c900
  *  2005-02-25  uri types added (sip, sips & tel)  (andrei)
512dcd98
  */
 
7dd0b342
 
512dcd98
 #ifndef msg_parser_h
 #define msg_parser_h
 
049f64c2
 #include "../comp_defs.h"
3881f12c
 #include "../str.h"
4c37101e
 #include "../lump_struct.h"
3881f12c
 #include "../flags.h"
4e2fdd79
 #include "../ip_addr.h"
caf80ae6
 #include "../md5utils.h"
7958eeae
 #include "../config.h"
2bb60634
 #include "parse_def.h"
 #include "parse_cseq.h"
 #include "parse_to.h"
 #include "parse_via.h"
 #include "parse_fline.h"
 #include "hf.h"
831faabf
 
512dcd98
 
1f377e97
 /* convenience short-cut macros */
1400b772
 #define REQ_LINE(_msg) ((_msg)->first_line.u.request)
1f377e97
 #define REQ_METHOD first_line.u.request.method_value
 #define REPLY_STATUS first_line.u.reply.statuscode
 #define REPLY_CLASS(_reply) ((_reply)->REPLY_STATUS/100)
 
3bd0930b
 /* number methods as power of two to allow bitmap matching */
fde02f64
 enum request_method { METHOD_UNDEF=0, METHOD_INVITE=1, METHOD_CANCEL=2, METHOD_ACK=4, 
0f0f44c4
 	METHOD_BYE=8, METHOD_INFO=16, METHOD_OTHER=32 };
f571aa35
 
ef30e43b
 #define FL_FORCE_RPORT 1   /* force rport */
 #define FL_FORCE_ACTIVE 2  /* force active SDP */
 #define FL_SDP_IP_AFS 4    /* SDP IP rewritten */
 #define FL_SDP_PORT_AFS 8  /* SDP port rewritten */
c10a942f
 #define FL_SHM_CLONE   16  /* msg cloned in SHM as a single chunk */
3e8c3475
 
f2f969dd
 
f571aa35
 #define IFISMETHOD(methodname,firstchar)                                  \
 if (  (*tmp==(firstchar) || *tmp==((firstchar) | 32)) &&                  \
         strncasecmp( tmp+1, #methodname +1, methodname##_LEN-1)==0 &&     \
         *(tmp+methodname##_LEN)==' ') {                                   \
                 fl->type=SIP_REQUEST;                                     \
                 fl->u.request.method.len=methodname##_LEN;                \
                 fl->u.request.method_value=METHOD_##methodname;           \
                 tmp=buffer+methodname##_LEN;                              \
 }
f8d46776
 
512dcd98
 
de0062e6
 /*
  * Return a URI to which the message should be really sent (not what should
  * be in the Request URI. The following fields are tried in this order:
  * 1) dst_uri
  * 2) new_uri
  * 3) first_line.u.request.uri
  */
 #define GET_NEXT_HOP(m) \
257181a0
 (((m)->dst_uri.s && (m)->dst_uri.len) ? (&(m)->dst_uri) : \
 (((m)->new_uri.s && (m)->new_uri.len) ? (&(m)->new_uri) : (&(m)->first_line.u.request.uri)))
de0062e6
 
 
 /*
  * Return the Reqeust URI of a message.
  * The following fields are tried in this order:
  * 1) new_uri
  * 2) first_line.u.request.uri
  */
 #define GET_RURI(m) \
257181a0
 (((m)->new_uri.s && (m)->new_uri.len) ? (&(m)->new_uri) : (&(m)->first_line.u.request.uri))
de0062e6
 
855c2e68
 
4b50480e
 #if 0
 	/* old version */
855c2e68
 struct sip_uri {
 	str user;     /* Username */
 	str passwd;   /* Password */
 	str host;     /* Host name */
 	str port;     /* Port number */
 	str params;   /* Parameters */
 	str headers;  
1baa06b5
 	unsigned short port_no;
855c2e68
 };
4b50480e
 #endif
855c2e68
 
f924ae07
 enum _uri_type{ERROR_URI_T=0, SIP_URI_T, SIPS_URI_T, TEL_URI_T, TELS_URI_T};
2518c900
 typedef enum _uri_type uri_type;
 
4b50480e
 struct sip_uri {
 	str user;     /* Username */
 	str passwd;   /* Password */
 	str host;     /* Host name */
 	str port;     /* Port number */
 	str params;   /* Parameters */
 	str headers;  
 	unsigned short port_no;
 	unsigned short proto; /* from transport */
2518c900
 	uri_type type; /* uri scheme */
4b50480e
 	/* parameters */
 	str transport;
 	str ttl;
 	str user_param;
 	str maddr;
 	str method;
 	str lr;
3f601bd0
 	str r2; /* ser specific rr parameter */
4b50480e
 	/* values */
 	str transport_val;
 	str ttl_val;
 	str user_param_val;
 	str maddr_val;
 	str method_val;
3f601bd0
 	str lr_val; /* lr value placeholder for lr=on a.s.o*/
 	str r2_val;
4b50480e
 };
855c2e68
 
 
2bb60634
 struct sip_msg {
 	unsigned int id;               /* message id, unique/process*/
 	struct msg_start first_line;   /* Message first line */
 	struct via_body* via1;         /* The first via */
 	struct via_body* via2;         /* The second via */
 	struct hdr_field* headers;     /* All the parsed headers*/
 	struct hdr_field* last_header; /* Pointer to the last parsed header*/
5c28a534
 	hdr_flags_t parsed_flag;    /* Already parsed header field types */
e4067ffb
 
2bb60634
 	     /* Via, To, CSeq, Call-Id, From, end of header*/
c32feee5
 	     /* pointers to the first occurrences of these headers;
97f17e60
 		  * everything is also saved in 'headers'
 		  * (WARNING: do not deallocate them twice!)*/
e4067ffb
 
e72b5b50
 	struct hdr_field* h_via1;
 	struct hdr_field* h_via2;
 	struct hdr_field* callid;
 	struct hdr_field* to;
 	struct hdr_field* cseq;
 	struct hdr_field* from;
 	struct hdr_field* contact;
10febf05
 	struct hdr_field* maxforwards;
 	struct hdr_field* route;
f2278164
 	struct hdr_field* record_route;
33032483
 	struct hdr_field* content_type;
 	struct hdr_field* content_length;
e3c29827
 	struct hdr_field* authorization;
 	struct hdr_field* expires;
 	struct hdr_field* proxy_auth;
 	struct hdr_field* supported;
 	struct hdr_field* proxy_require;
 	struct hdr_field* unsupported;
 	struct hdr_field* allow;
70ae655f
 	struct hdr_field* event;
71be0c4a
 	struct hdr_field* accept;
2f43c732
 	struct hdr_field* accept_language;
 	struct hdr_field* organization;
 	struct hdr_field* priority;
 	struct hdr_field* subject;
 	struct hdr_field* user_agent;
 	struct hdr_field* content_disposition;
6a2b0dec
 	struct hdr_field* accept_disposition;
dccbcda9
 	struct hdr_field* diversion;
 	struct hdr_field* rpid;
8b482f1a
         struct hdr_field* refer_to;
2bb60634
 
 	char* eoh;        /* pointer to the end of header (if found) or null */
 	char* unparsed;   /* here we stopped parsing*/
f2f969dd
 	
 	struct receive_info rcv; /* source & dest ip, ports, proto a.s.o*/
049f64c2
 
c32feee5
 	char* buf;        /* scratch pad, holds a modified message,
f2f969dd
 					   *  via, etc. point into it */
4ac74c03
 	unsigned int len; /* message len (orig) */
7268726e
 
2bb60634
 	     /* modifications */
 	
6f96d99f
 	str new_uri; /* changed first line uri, when you change this
 	                don't forget to set parsed_uri_ok to 0*/
88edf618
 
695ff13f
 	str dst_uri; /* Destination URI, must be forwarded to this URI if len != 0 */
88edf618
 
b2fcef3c
 	/* current uri */
6f96d99f
 	int parsed_uri_ok; /* 1 if parsed_uri is valid, 0 if not, set if to 0
 	                      if you modify the uri (e.g change new_uri)*/
855c2e68
 	struct sip_uri parsed_uri; /* speed-up > keep here the parsed uri*/
b2fcef3c
 	/* the same for original uri */
 	int parsed_orig_ruri_ok;
 	struct sip_uri parsed_orig_ruri;
2bb60634
 	
f15bede1
 	struct lump* add_rm;       /* used for all the forwarded requests/replies */
4c37101e
 	struct lump* body_lumps;     /* Lumps that update Content-Length */
caf80ae6
 	struct lump_rpl *reply_lump; /* only for localy generated replies !!!*/
 
 	/* str add_to_branch; 
 	   whatever whoever want to append to branch comes here 
 	*/
0a6afa42
 	char add_to_branch_s[MAX_BRANCH_PARAM_LEN];
416db8cd
 	int add_to_branch_len;
2bb60634
 	
c32feee5
 	     /* index to TM hash table; stored in core to avoid unnecessary calculations */
d3b31abd
 	unsigned int  hash_index;
3e8c3475
 	unsigned int msg_flags; /* flags used by core */
2bb60634
 	     /* allows to set various flags on the message; may be used for 
 	      *	simple inter-module communication or remembering processing state
 	      * reached 
 	      */
 	flag_t flags;	
6bfaa042
 	str set_global_address;
 	str set_global_port;
a35ad52c
 	struct socket_info* force_send_socket; /* force sending on this socket,
 											  if ser */
888ca09d
 };
 
caf80ae6
 /* pointer to a fakes message which was never received ;
    (when this message is "relayed", it is generated out
     of the original request)
 */
 #define FAKED_REPLY     ((struct sip_msg *) -1)
 
 extern int via_cnt;
512dcd98
 
888ca09d
 int parse_msg(char* buf, unsigned int len, struct sip_msg* msg);
512dcd98
 
5c28a534
 int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next);
512dcd98
 
363f516f
 char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr);
 
22d4aa5d
 void free_sip_msg(struct sip_msg* msg);
e72b5b50
 
21f03122
 /* make sure all HFs needed for transaction identification have been
    parsed; return 0 if those HFs can't be found
  */
f0631398
 
caf80ae6
 int check_transaction_quadruple( struct sip_msg* msg );
 
 /* calculate characteristic value of a message -- this value
    is used to identify a transaction during the process of
    reply matching
  */
 inline static int char_msg_val( struct sip_msg *msg, char *cv )
 {
 	str src[8];
 
 	if (!check_transaction_quadruple(msg)) {
 		LOG(L_ERR, "ERROR: can't calculate char_value due "
 			"to a parsing error\n");
 		memset( cv, '0', MD5_LEN );
 		return 0;
 	}
 
 	src[0]= msg->from->body;
 	src[1]= msg->to->body;
 	src[2]= msg->callid->body;
 	src[3]= msg->first_line.u.request.uri;
 	src[4]= get_cseq( msg )->number;
ac79e819
 	
caf80ae6
 	/* topmost Via is part of transaction key as well ! */
 	src[5]= msg->via1->host;
 	src[6]= msg->via1->port_str;
 	if (msg->via1->branch) {
 		src[7]= msg->via1->branch->value;
 		MDStringArray ( cv, src, 8 );
 	} else {
 		MDStringArray( cv, src, 7 );
 	}
 	return 1;
 }
 
ec147e2e
 
 /* returns a pointer to the begining of the msg's body
  */
 inline static char* get_body(struct sip_msg *msg)
 {
 	int offset;
0ba367ec
 	unsigned int len;
ec147e2e
 
5c28a534
 	if ( parse_headers(msg, HDR_EOH_F, 0)==-1 )
ec147e2e
 		return 0;
 
f2f969dd
 	if (msg->unparsed){
0ba367ec
 		len=(unsigned int)(msg->unparsed-msg->buf);
f2f969dd
 	}else return 0;
 	if ((len+2<=msg->len) && (strncmp(CRLF,msg->unparsed,CRLF_LEN)==0) )
ec147e2e
 		offset = CRLF_LEN;
f2f969dd
 	else if ( (len+1<=msg->len) &&
 				(*(msg->unparsed)=='\n' || *(msg->unparsed)=='\r' ) )
ec147e2e
 		offset = 1;
 	else
 		return 0;
 
 	return msg->unparsed + offset;
 }
 
846a7aa0
 
 /*
  * Make a private copy of the string and assign it to dst_uri
  */
 int set_dst_uri(struct sip_msg* msg, str* uri);
 
 
512dcd98
 #endif