Пример #1
0
/*
 * Message contained some contacts and appropriate
 * record was found, so we have to walk through
 * all contacts and do the following:
 * 1) If contact in usrloc doesn't exists and
 *    expires > 0, insert new contact
 * 2) If contact in usrloc exists and expires
 *    > 0, update the contact
 * 3) If contact in usrloc exists and expires
 *    == 0, delete contact
 */
static inline int update(struct sip_msg* _m, urecord_t* _r, contact_t* _c, str* _ua)
{
	ucontact_t* c, *c2;
	str callid;
	int cseq, e;
	int set, reset;
	qvalue_t q;
	unsigned int flags;
	str* recv;
	int_str rcv_avp;
	int_str val;
	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;

	if (max_contacts) {
		if (test_max_contacts(_m, _r, _c) != 0 )
			return -1;
	}

	_c = get_first_contact(_m);

	while(_c) {
		if (calc_contact_expires(_m, _c->expires, &e) < 0) {
			LOG(L_ERR, "update(): Error while calculating expires\n");
			return -1;
		}

		if (ul.get_ucontact(_r, &_c->uri, &c) > 0) {
			/* Contact not found */
			if (e != 0) {
				/* Calculate q value of the contact */
				if (calc_contact_q(_c->q, &q) < 0) {
					LOG(L_ERR, "update(): Error while calculating q\n");
					return -2;
				}
				
				/* Get callid of the message */
				callid = _m->callid->body;
				trim_trailing(&callid);
				
				/* Get CSeq number of the message */
				if (str2int(&(((struct cseq_body*)_m->cseq->parsed)->number), 
								(unsigned int*) &cseq) < 0) {
					rerrno = R_INV_CSEQ;
					LOG(L_ERR, "update(): Error while converting cseq number\n");
					return -3;
				}
				
				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 | mem_only, &c2, _ua, recv, sock) < 0) {
					rerrno = R_UL_INS_C;
					LOG(L_ERR, "update(): Error while inserting contact\n");
					return -4;
				}
			}
		} else {
			if (e == 0) {
				if (mem_only) {
					c->flags |= FL_MEM;
				} else {
					c->flags &= ~FL_MEM;
				}

				if (ul.delete_ucontact(_r, c) < 0) {
					rerrno = R_UL_DEL_C;
					LOG(L_ERR, "update(): Error while deleting contact\n");
					return -5;
				}
			} else {
				/* Calculate q value of the contact */
				if (calc_contact_q(_c->q, &q) < 0) {
					LOG(L_ERR, "update(): Error while calculating q\n");
					return -6;
				}
				
				/* Get callid of the message */
				callid = _m->callid->body;
				trim_trailing(&callid);
				
				/* Get CSeq number of the message */
				if (str2int(&(((struct cseq_body*)_m->cseq->parsed)->number),
				(unsigned int*)&cseq) < 0) {
					rerrno = R_INV_CSEQ;
					LOG(L_ERR,"update(): Error while converting cseq number\n");
					return -7;
				}
				
				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;
				}

				set = flags | mem_only;
				reset = ~(flags | mem_only) & (FL_NAT|FL_MEM|FL_NAT_SIPPING);
				if (ul.update_ucontact(c, e, q, &callid, cseq,
						set, reset, _ua, recv, sock) < 0) {
					rerrno = R_UL_UPD_C;
					LOG(L_ERR, "update(): Error while updating contact\n");
					return -8;
				}

				if (desc_time_order) {
					move_on_top(_r, c);
				}
			}
		}
		_c = get_next_contact(_c);
	}

	return 0;
}
Пример #2
0
/*! \brief
 * Fills the common part (for all contacts) of the info structure
 */
static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c,
						unsigned int _e, unsigned int _f, unsigned int _flags)
{
	static ucontact_info_t ci;
	static str no_ua = str_init("n/a");
	static str callid;
	static str path_received = {0,0};
	static str path;
	static str received = {0,0};
	static int received_found;
	static unsigned int allowed, allow_parsed;
	static struct sip_msg *m = 0;
	int_str val;

	if (_m!=0) {
		memset( &ci, 0, sizeof(ucontact_info_t));

		/* Get callid of the message */
		callid = _m->callid->body;
		trim_trailing(&callid);
		if (callid.len > CALLID_MAX_SIZE) {
			rerrno = R_CALLID_LEN;
			LM_ERR("callid too long\n");
			goto error;
		}
		ci.callid = &callid;

		/* Get CSeq number of the message */
		if (str2int(&get_cseq(_m)->number, (unsigned int*)&ci.cseq) < 0) {
			rerrno = R_INV_CSEQ;
			LM_ERR("failed to convert cseq number\n");
			goto error;
		}

		/* set received socket */
		if ( _flags&REG_SAVE_SOCKET_FLAG) {
			ci.sock = get_sock_hdr(_m);
			if (ci.sock==0)
				ci.sock = _m->rcv.bind_address;
		} else {
			ci.sock = _m->rcv.bind_address;
		}

		/* additional info from message */
		if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent &&
		_m->user_agent->body.len>0 && _m->user_agent->body.len<UA_MAX_SIZE) {
			ci.user_agent = &_m->user_agent->body;
		} else {
			ci.user_agent = &no_ua;
		}

		/* extract Path headers */
		if ( _flags&REG_SAVE_PATH_FLAG ) {
			if (build_path_vector(_m, &path, &path_received, _flags) < 0) {
				rerrno = R_PARSE_PATH;
				goto error;
			}
			if (path.len && path.s) {
				ci.path = &path;
				/* save in msg too for reply */
				if (set_path_vector(_m, &path) < 0) {
					rerrno = R_PARSE_PATH;
					goto error;
				}
			}
		}

		ci.last_modified = act_time;

		/* set flags */
		ci.flags  = _f;
		ci.cflags =  getb0flags();

		/* get received */
		if (path_received.len && path_received.s) {
			ci.cflags |= ul.nat_flag;
			ci.received = path_received;
		}

		allow_parsed = 0; /* not parsed yet */
		received_found = 0; /* not found yet */
		m = _m; /* remember the message */
	}

	if(_c!=0) {
		/* Calculate q value of the contact */
		if (calc_contact_q(_c->q, &ci.q) < 0) {
			rerrno = R_INV_Q;
			LM_ERR("failed to calculate q\n");
			goto error;
		}

		/* set expire time */
		ci.expires = _e;

		/* Get methods of contact */
		if (_c->methods) {
			if (parse_methods(&(_c->methods->body), &ci.methods) < 0) {
				rerrno = R_PARSE;
				LM_ERR("failed to parse contact methods\n");
				goto error;
			}
		} else {
			/* check on Allow hdr */
			if (allow_parsed == 0) {
				if (m && parse_allow( m ) != -1) {
					allowed = get_allow_methods(m);
				} else {
					allowed = ALL_METHODS;
				}
				allow_parsed = 1;
			}
			ci.methods = allowed;
		}

		/* get received */
		if (ci.received.len==0) {
			if (_c->received) {
				ci.received = _c->received->body;
			} else {
				if (received_found==0) {
					memset(&val, 0, sizeof(int_str));
					if (rcv_avp_name>=0
								&& search_first_avp(rcv_avp_type, rcv_avp_name, &val, 0)
								&& val.s.len > 0) {
						if (val.s.len>RECEIVED_MAX_SIZE) {
							rerrno = R_CONTACT_LEN;
							LM_ERR("received too long\n");
							goto error;
						}
						received = val.s;
					} else {
						received.s = 0;
						received.len = 0;
					}
					received_found = 1;
				}
				ci.received = received;
			}
		}

	}

	return &ci;
error:
	return 0;
}
Пример #3
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;
}