示例#1
0
/*
 * Message contained some contacts, but record with same address
 * of record was not found so we have to create a new record
 * and insert all contacts from the message that have expires
 * > 0
 */
static inline int insert(struct sip_msg* _m, contact_t* _c, udomain_t* _d, str* _a, str *ua)
{
	urecord_t* r = 0;
	ucontact_t* c;
	int e, cseq;
	qvalue_t q;
	str callid;
	unsigned int flags;
	str* recv;
	int_str rcv_avp;
	int_str val;
	int num;
	struct socket_info *sock;

	rcv_avp.n=rcv_avp_no;
	/* is nated flag */
	if (nat_flag!=-1 && _m->flags&nat_flag)
		flags = FL_NAT;
	else
		flags = FL_NONE;
	/* nat type flag */
	if (sip_natping_flag!=-1 && _m->flags&sip_natping_flag)
		flags |= FL_NAT_SIPPING;

	flags |= mem_only;

	num = 0;
	while(_c) {
		if (calc_contact_expires(_m, _c->expires, &e) < 0) {
			LOG(L_ERR, "insert(): Error while calculating expires\n");
			return -1;
		}
		     /* Skip contacts with zero expires */
		if (e == 0) goto skip;

		if (max_contacts && (num >= max_contacts)) {
			rerrno = R_TOO_MANY;
			ul.delete_urecord(_d, _a);
			return -1;
		}
		num++;
		
	        if (r == 0) {
			if (ul.insert_urecord(_d, _a, &r) < 0) {
				rerrno = R_UL_NEW_R;
				LOG(L_ERR, "insert(): Can't insert new record structure\n");
				return -2;
			}
		}
		
		     /* Calculate q value of the contact */
		if (calc_contact_q(_c->q, &q) < 0) {
			LOG(L_ERR, "insert(): Error while calculating q\n");
			ul.delete_urecord(_d, _a);
			return -3;
		}

		     /* Get callid of the message */
		callid = _m->callid->body;	
		trim_trailing(&callid);
		
		     /* Get CSeq number of the message */
		if (str2int(&get_cseq(_m)->number, (unsigned int*)&cseq) < 0) {
			rerrno = R_INV_CSEQ;
			LOG(L_ERR, "insert(): Error while converting cseq number\n");
			ul.delete_urecord(_d, _a);
			return -4;
		}

		if (_c->received) {
			recv = &_c->received->body;
		} else if (search_first_avp(0, rcv_avp, &val)) {
			recv = val.s;
		} else {
			recv = 0;
		}

		if (sock_flag!=-1 && (_m->flags&sock_flag)!=0) {
			sock = get_sock_hdr(_m);
			if (sock==0)
				sock = _m->rcv.bind_address;
		} else {
			sock = _m->rcv.bind_address;
		}

		if (ul.insert_ucontact(r, &_c->uri, e, q, &callid, cseq, flags, &c,
		ua, recv, sock) < 0) {
			rerrno = R_UL_INS_C;
			LOG(L_ERR, "insert(): Error while inserting contact\n");
			ul.delete_urecord(_d, _a);
			return -5;
		}
		
	skip:
		_c = get_next_contact(_c);
	}
	
	if (r) {
		if (!r->contacts) {
			ul.delete_urecord(_d, _a);
		} else {
			build_contact(r->contacts);
		}
	}
	
	return 0;
}
示例#2
0
文件: save.c 项目: halan/kamailio
/*! \brief
 * Message contained some contacts, but record with same address
 * of record was not found so we have to create a new record
 * and insert all contacts from the message that have expires
 * > 0
 */
static inline int insert_contacts(struct sip_msg* _m, udomain_t* _d, str* _a)
{
	ucontact_info_t* ci;
	urecord_t* r = NULL;
	ucontact_t* c;
	contact_t* _c;
	unsigned int flags;
	int num, expires;
	int maxc;
#ifdef USE_TCP
	int e_max, tcp_check;
	struct sip_uri uri;
#endif
	sip_uri_t *u;

	u = parse_to_uri(_m);
	if(u==NULL)
		goto error;

	flags = mem_only;
#ifdef USE_TCP
	if ( (_m->flags&tcp_persistent_flag)
			&& (_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS
				||_m->rcv.proto==PROTO_WS||_m->rcv.proto==PROTO_WSS)) {
		e_max = 0;
		tcp_check = 1;
	} else {
		e_max = tcp_check = 0;
	}
#endif
	_c = get_first_contact(_m);
	maxc = reg_get_crt_max_contacts();
	for( num=0,r=0,ci=0 ; _c ; _c = get_next_contact(_c) ) {
		/* calculate expires */
		calc_contact_expires(_m, _c->expires, &expires);
		/* Skip contacts with zero expires */
		if (expires == 0)
			continue;


		if (maxc > 0 && num >= maxc) {
			LM_INFO("too many contacts (%d) for AOR <%.*s>\n", 
					num, _a->len, _a->s);
			rerrno = R_TOO_MANY;
			goto error;
		}
		num++;

		if (r==0) {
			if (ul.insert_urecord(_d, _a, &r) < 0) {
				rerrno = R_UL_NEW_R;
				LM_ERR("failed to insert new record structure\n");
				goto error;
			}
		}

		/* pack the contact_info */
		if ( (ci=pack_ci( (ci==0)?_m:0, _c, expires, flags))==0 ) {
			LM_ERR("failed to extract contact info\n");
			goto error;
		}

		/* hack to work with buggy clients having many contacts with same
		 * address in one REGISTER - increase CSeq to detect if there was
		 * one alredy added, then update */
		ci->cseq++;
		if ( r->contacts==0
				|| ul.get_ucontact_by_instance(r, &_c->uri, ci, &c) != 0) {
			ci->cseq--;
			if (ul.insert_ucontact( r, &_c->uri, ci, &c) < 0) {
				rerrno = R_UL_INS_C;
				LM_ERR("failed to insert contact\n");
				goto error;
			}
		} else {
			ci->cseq--;
			if (ul.update_ucontact( r, c, ci) < 0) {
				rerrno = R_UL_UPD_C;
				LM_ERR("failed to update contact\n");
				goto error;
			}
		}
#ifdef USE_TCP
		if (tcp_check) {
			/* parse contact uri to see if transport is TCP */
			if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) {
				LM_ERR("failed to parse contact <%.*s>\n", 
						_c->uri.len, _c->uri.s);
			} else if (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS || uri.proto==PROTO_WS || uri.proto==PROTO_WSS) {
				if (e_max) {
					LM_WARN("multiple TCP contacts on single REGISTER\n");
					if (expires>e_max) e_max = expires;
				} else {
					e_max = expires;
				}
			}
		}
#endif
	}

	if (r) {
		if (r->contacts)
			build_contact(_m, r->contacts, &u->host);
		ul.release_urecord(r);
	} else { /* No contacts found */
		build_contact(_m, NULL, &u->host);
	}

#ifdef USE_TCP
	if ( tcp_check && e_max>0 ) {
		e_max -= act_time;
		/*FIXME: Do we want this in the sr core?*/
		/*force_tcp_conn_lifetime( &_m->rcv , e_max + 10 );*/
	}
#endif

	return 0;
error:
	if (r)
		ul.delete_urecord(_d, _a, r);
	return -1;
}
示例#3
0
/*! \brief
 * Message contained some contacts, but record with same address
 * of record was not found so we have to create a new record
 * and insert all contacts from the message that have expires
 * > 0
 */
static inline int insert_contacts(struct sip_msg* _m, contact_t* _c,
								udomain_t* _d, str* _a, struct save_ctx *_sctx)
{
	ucontact_info_t* ci;
	urecord_t* r;
	ucontact_t* c;
	unsigned int cflags;
	int num;
	int e;
	int e_max;
	int tcp_check;
	struct sip_uri uri;

	cflags = (_sctx->flags&REG_SAVE_MEMORY_FLAG)?FL_MEM:FL_NONE;
	if (is_tcp_based_proto(_m->rcv.proto) && (_m->flags&tcp_persistent_flag)) {
		e_max = 0;
		tcp_check = 1;
	} else {
		e_max = tcp_check = 0;
	}

	for( num=0,r=0,ci=0 ; _c ; _c = get_next_contact(_c) ) {
		/* calculate expires */
		calc_contact_expires(_m, _c->expires, &e, _sctx);
		/* Skip contacts with zero expires */
		if (e == 0)
			continue;

		if (_sctx->max_contacts && (num >= _sctx->max_contacts)) {
			if (_sctx->flags&REG_SAVE_FORCE_REG_FLAG) {
				/* we are overflowing the number of maximum contacts,
				   so remove the first (oldest) one to prevent this */
				if (r==NULL || r->contacts==NULL) {
					LM_CRIT("BUG - overflow detected with r=%p and "
						"contacts=%p\n",r,r->contacts);
					goto error;
				}
				if (ul.delete_ucontact( r, r->contacts, 0)!=0) {
					LM_ERR("failed to remove contact\n");
					goto error;
				}
			} else {
				LM_INFO("too many contacts (%d) for AOR <%.*s>, max=%d\n",
						num, _a->len, _a->s, _sctx->max_contacts);
				rerrno = R_TOO_MANY;
				goto error;
			}
		} else {
			num++;
		}

		if (r==0) {
			if (ul.insert_urecord(_d, _a, &r, 0) < 0) {
				rerrno = R_UL_NEW_R;
				LM_ERR("failed to insert new record structure\n");
				goto error;
			}
		}

		/* pack the contact_info */
		if ( (ci=pack_ci( (ci==0)?_m:0, _c, e, cflags, _sctx->flags))==0 ) {
			LM_ERR("failed to extract contact info\n");
			goto error;
		}

		if ( r->contacts==0 ||
		ul.get_ucontact(r, &_c->uri, ci->callid, ci->cseq+1, &c)!=0 ) {
			if (ul.insert_ucontact( r, &_c->uri, ci, &c, 0) < 0) {
				rerrno = R_UL_INS_C;
				LM_ERR("failed to insert contact\n");
				goto error;
			}
		} else {
			if (ul.update_ucontact( r, c, ci, 0) < 0) {
				rerrno = R_UL_UPD_C;
				LM_ERR("failed to update contact\n");
				goto error;
			}
		}

		if (tcp_check) {
			/* parse contact uri to see if transport is TCP */
			if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) {
				LM_ERR("failed to parse contact <%.*s>\n",
						_c->uri.len, _c->uri.s);
			} else if ( is_tcp_based_proto(uri.proto) ) {
				if (e_max) {
					LM_WARN("multiple TCP contacts on single REGISTER\n");
					if (e>e_max) e_max = e;
				} else {
					e_max = e;
				}
			}
		}
	}

	if (r) {
		if (r->contacts) {
			build_contact(r->contacts,_m);
		}
		ul.release_urecord(r, 0);
	}

	if ( tcp_check && e_max>0 ) {
		e_max -= act_time;
		trans_set_dst_attr( &_m->rcv, DST_FCNTL_SET_LIFETIME,
			(void*)(long)(e_max + 10) );
	}

	return 0;
error:
	if (r)
		ul.delete_urecord(_d, _a, r, 0);
	return -1;
}