obsolete/registrar/sip_msg.c
d23bed8f
 /*
  * $Id$
  *
  * SIP message related functions
ed346bcc
  *
95072403
  * Copyright (C) 2001-2003 FhG Fokus
ed346bcc
  *
  * 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 
9e1ff448
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
d23bed8f
  */
 
 
ed346bcc
 
e60b65ed
 #include "../../parser/hf.h"
fdac2b59
 #include <dprint.h>
e60b65ed
 #include "../../parser/parse_expires.h"  
 #include "../../ut.h"
1527c494
 #include "../../qvalue.h"
d23bed8f
 #include "reg_mod.h"                     /* Module parameters */
 #include "regtime.h"                     /* act_time */
 #include "rerrno.h"
fdac2b59
 #include "sip_msg.h"
d23bed8f
 
 
 static struct hdr_field* act_contact;
 
 
 /*
  * Return value of Expires header field
  * if the HF exists converted to absolute
  * time, if the HF doesn't exist, returns
  * default value;
  */
 static inline int get_expires_hf(struct sip_msg* _m)
 {
 	exp_body_t* p;
 	
 	if (_m->expires) {
 		p = (exp_body_t*)_m->expires->parsed;
a2d9207f
 		if (p->valid) {
 			if (p->val != 0) {
 				return p->val + act_time;
 			} else return 0;
 		} else return act_time + default_expires;
d23bed8f
 	} else {
 		return act_time + default_expires;
 	}
 }
 
 
 /*
95072403
  * Parse the whole message and bodies of all header fields
d23bed8f
  * that will be needed by registrar
  */
 int parse_message(struct sip_msg* _m)
 {
 	struct hdr_field* ptr;
 	
0bfbf63f
 	if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
d23bed8f
 		rerrno = R_PARSE;
 		LOG(L_ERR, "parse_message(): Error while parsing headers\n");
 		return -1;
 	}
 	
 	if (!_m->to) {
 		rerrno = R_TO_MISS;
 		LOG(L_ERR, "parse_message(): To not found\n");
 		return -2;
 	}
 
 	if (!_m->callid) {
 		rerrno = R_CID_MISS;
 		LOG(L_ERR, "parse_message(): Call-ID not found\n");
 		return -3;
 	}
 
 	if (!_m->cseq) {
 		rerrno = R_CS_MISS;
 		LOG(L_ERR, "parse_message(): CSeq not found\n");
 		return -4;
 	}
 
 	if (_m->expires && !_m->expires->parsed && (parse_expires(_m->expires) < 0)) {
 		rerrno = R_PARSE_EXP;
 		LOG(L_ERR, "parse_message(): Error while parsing expires body\n");
 		return -5;
 	}
 	
 	if (_m->contact) {
 		ptr = _m->contact;
 		while(ptr) {
0bfbf63f
 			if (ptr->type == HDR_CONTACT_T) {
d23bed8f
 				if (!ptr->parsed && (parse_contact(ptr) < 0)) {
 					rerrno = R_PARSE_CONT;
 					LOG(L_ERR, "parse_message(): Error while parsing Contact body\n");
 					return -6;
 				}
 			}
 			ptr = ptr->next;
 		}
 	}
 	
 	return 0;
 }
 
 
 /*
  * Check if the originating REGISTER message was formed correctly
  * The whole message must be parsed before calling the function
  * _s indicates whether the contact was star
  */
 int check_contacts(struct sip_msg* _m, int* _s)
 {
 	struct hdr_field* p;
 	
 	*_s = 0;
 	     /* Message without contacts is OK */
 	if (_m->contact == 0) return 0;
 	
 	if (((contact_body_t*)_m->contact->parsed)->star == 1) { /* The first Contact HF is star */
 		     /* Expires must be zero */
 		if (get_expires_hf(_m) > 0) {
 			rerrno = R_STAR_EXP;
 			return 1;
 		}
 		
 		     /* Message must contain no contacts */
 		if (((contact_body_t*)_m->contact->parsed)->contacts) {
 			rerrno = R_STAR_CONT;
 			return 1;
 		}
 		
 		     /* Message must contain no other Contact HFs */
 		p = _m->contact->next;
 		while(p) {
0bfbf63f
 			if (p->type == HDR_CONTACT_T) {
d23bed8f
 				rerrno = R_STAR_CONT;
 				return 1;
 			}
 			p = p->next;
 		}
 		
 		*_s = 1;
 	} else { /* The first Contact HF is not star */
 		     /* Message must contain no star Contact HF */
 		p = _m->contact->next;
 		while(p) {
0bfbf63f
 			if (p->type == HDR_CONTACT_T) {
d23bed8f
 				if (((contact_body_t*)p->parsed)->star == 1) {
 					rerrno = R_STAR_CONT;
 					return 1;
 				}
 			}
 			p = p->next;
 		}
 	}
 	
 	return 0;
 }
 
 
 /*
  * Get the first contact in message
  */
 contact_t* get_first_contact(struct sip_msg* _m)
 {
 	if (_m->contact == 0) return 0;
 	
 	act_contact = _m->contact;
 	return (((contact_body_t*)_m->contact->parsed)->contacts);
 }
 
 
 /* 
  * Get next contact in message
  */
 contact_t* get_next_contact(contact_t* _c)
 {
 	struct hdr_field* p;
 	if (_c->next == 0) {
 		p = act_contact->next;
 		while(p) {
0bfbf63f
 			if (p->type == HDR_CONTACT_T) {
d23bed8f
 				act_contact = p;
 				return (((contact_body_t*)p->parsed)->contacts);
 			}
 			p = p->next;
 		}
 		return 0;
 	} else {
 		return _c->next;
 	}
 }
 
 
 /*
  * Calculate absolute expires value per contact as follows:
  * 1) If the contact has expires value, use the value. If it
  *    is not zero, add actual time to it
  * 2) If the contact has no expires parameter, use expires
  *    header field in the same way
  * 3) If the message contained no expires header field, use
  *    the default value
  */
0133c358
 int calc_contact_expires(struct sip_msg* _m, param_t* _ep, int* _e)
d23bed8f
 {
15e7bff2
 	if (!_ep || !_ep->body.len) {
d23bed8f
 		*_e = get_expires_hf(_m);
 	} else {
6d2d861f
 		if (str2int(&_ep->body, (unsigned int*)_e) < 0) {
b3234159
 			*_e = 3600;
d23bed8f
 		}
 		     /* Convert to absolute value */
 		if (*_e != 0) *_e += act_time;
 	}		
861fddeb
 
c3b5e57c
 	if ((*_e != 0) && ((*_e - act_time) < min_expires)) {
861fddeb
 		*_e = min_expires + act_time;
 	}
 
6d76a8ff
 	if ((*_e != 0) && max_expires && ((*_e - act_time) > max_expires)) {
 		*_e = max_expires + act_time;
 	}
 
d23bed8f
 	return 0;
 }
 
 
 /*
  * Calculate contact q value as follows:
  * 1) If q parameter exists, use it
1527c494
  * 2) If the parameter doesn't exist, use the default value
d23bed8f
  */
1527c494
 int calc_contact_q(param_t* _q, qvalue_t* _r)
d23bed8f
 {
 	if (!_q || (_q->body.len == 0)) {
1527c494
 		*_r = default_q;
d23bed8f
 	} else {
1527c494
 		if (str2q(_r, _q->body.s, _q->body.len) < 0) {
d23bed8f
 			rerrno = R_INV_Q; /* Invalid q parameter */
 			LOG(L_ERR, "calc_contact_q(): Invalid q parameter\n");
 			return -1;
 		}
 	}
 	return 0;
 }