⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 save.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
字号:
/* * $Id: save.c,v 1.37.2.3 2005/05/18 12:06:25 janakj Exp $ * * Process REGISTER request and send reply * * Copyright (C) 2001-2003 FhG Fokus * * 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 * * History: * ---------- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri) * 2003-02-28 scrathcpad compatibility abandoned (jiri) * 2003-03-21  save_noreply added, patch provided by Maxim Sobolev <sobomax@portaone.com> (janakj) */#include "../../comp_defs.h"#include "../../str.h"#include "../../parser/parse_to.h"#include "../../dprint.h"#include "../../trim.h"#include "../../ut.h"#include "../usrloc/usrloc.h"#include "../../qvalue.h"#include "common.h"#include "sip_msg.h"#include "rerrno.h"#include "reply.h"#include "reg_mod.h"#include "regtime.h"#include "save.h"static int mem_only = 0;void remove_cont(urecord_t* _r, ucontact_t* _c){	if (_c->prev) {		_c->prev->next = _c->next;		if (_c->next) {			_c->next->prev = _c->prev;		}	} else {		_r->contacts = _c->next;		if (_c->next) {			_c->next->prev = 0;		}	}}void move_on_top(urecord_t* _r, ucontact_t* _c){	ucontact_t* prev;	if (!_r->contacts) return;	if (_c->prev == 0) return;	prev = _c->prev;	remove_cont(_r, _c);		_c->next = _r->contacts;	_c->prev = 0;	_r->contacts->prev = _c;	_r->contacts = _c;}/* * Process request that contained a star, in that case,  * we will remove all bindings with the given username  * from the usrloc and return 200 OK response */static inline int star(udomain_t* _d, str* _a){	urecord_t* r;	ucontact_t* c;		ul.lock_udomain(_d);	if (!ul.get_urecord(_d, _a, &r)) {		c = r->contacts;		while(c) {			if (mem_only) {				c->flags |= FL_MEM;			} else {				c->flags &= ~FL_MEM;			}			c = c->next;		}	}	if (ul.delete_urecord(_d, _a) < 0) {		LOG(L_ERR, "star(): Error while removing record from usrloc\n");				     /* Delete failed, try to get corresponding		      * record structure and send back all existing		      * contacts		      */		rerrno = R_UL_DEL_R;		if (!ul.get_urecord(_d, _a, &r)) {			build_contact(r->contacts);		}		ul.unlock_udomain(_d);		return -1;	}	ul.unlock_udomain(_d);	return 0;}/* * Process request that contained no contact header * field, it means that we have to send back a response * containing a list of all existing bindings for the * given username (in To HF) */static inline int no_contacts(udomain_t* _d, str* _a){	urecord_t* r;	int res;		ul.lock_udomain(_d);	res = ul.get_urecord(_d, _a, &r);	if (res < 0) {		rerrno = R_UL_GET_R;		LOG(L_ERR, "no_contacts(): Error while retrieving record from usrloc\n");		ul.unlock_udomain(_d);		return -1;	}		if (res == 0) {  /* Contacts found */		build_contact(r->contacts);	}	ul.unlock_udomain(_d);	return 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;	rcv_avp.n=rcv_avp_no;	if (isflagset(_m, nat_flag) == 1) flags = FL_NAT;	else flags = FL_NONE;	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 (ul.insert_ucontact(r, &_c->uri, e, q, &callid, cseq, flags, &c, ua, recv) < 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;}static int test_max_contacts(struct sip_msg* _m, urecord_t* _r, contact_t* _c){	int num;	int e;	ucontact_t* ptr, *cont;		num = 0;	ptr = _r->contacts;	while(ptr) {		if (VALID_CONTACT(ptr, act_time)) {			num++;		}		ptr = ptr->next;	}	DBG("test_max_contacts: %d valid contacts\n", num);		while(_c) {		if (calc_contact_expires(_m, _c->expires, &e) < 0) {			LOG(L_ERR, "test_max_contacts: Error while calculating expires\n");			return -1;		}				if (ul.get_ucontact(_r, &_c->uri, &cont) > 0) {			     /* Contact not found */			if (e != 0) num++;		} else {			if (e == 0) num--;		}				_c = get_next_contact(_c);	}		DBG("test_max_contacts: %d contacts after commit\n", num);	if (num > max_contacts) {		rerrno = R_TOO_MANY;		return 1;	}		return 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, ret;	int set, reset;	qvalue_t q;	unsigned int nated;	str* recv;	int_str rcv_avp;	int_str val;		rcv_avp.n=rcv_avp_no;	if (isflagset(_m, nat_flag) == 1) {		nated = FL_NAT;	} else {		nated = FL_NONE;	}	if (max_contacts) {		ret = test_max_contacts(_m, _r, _c);		if (ret != 0) {			build_contact(_r->contacts);			return -1;		}	}	_c = get_first_contact(_m);	while(_c) {		if (calc_contact_expires(_m, _c->expires, &e) < 0) {			build_contact(_r->contacts);			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 (ul.insert_ucontact(_r, &_c->uri, e, q, &callid, cseq,						       nated | mem_only, 						       &c2, _ua, recv) < 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;				}				set = nated | mem_only;				reset = ~(nated | mem_only) & (FL_NAT | FL_MEM);				if (ul.update_ucontact(c, e, q, &callid, cseq, set, reset, _ua, recv) < 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;}/*  * This function will process request that * contained some contact header fields */static inline int contacts(struct sip_msg* _m, contact_t* _c, udomain_t* _d, str* _a, str* _ua){	int res;	urecord_t* r;	ul.lock_udomain(_d);	res = ul.get_urecord(_d, _a, &r);	if (res < 0) {		rerrno = R_UL_GET_R;		LOG(L_ERR, "contacts(): Error while retrieving record from usrloc\n");		ul.unlock_udomain(_d);		return -2;	}	if (res == 0) { /* Contacts found */		if (update(_m, r, _c, _ua) < 0) {			LOG(L_ERR, "contacts(): Error while updating record\n");			build_contact(r->contacts);			ul.release_urecord(r);			ul.unlock_udomain(_d);			return -3;		}		build_contact(r->contacts);		ul.release_urecord(r);	} else {		if (insert(_m, _c, _d, _a, _ua) < 0) {			LOG(L_ERR, "contacts(): Error while inserting record\n");			ul.unlock_udomain(_d);			return -4;		}	}	ul.unlock_udomain(_d);	return 0;}#define UA_DUMMY_STR "Unknown"#define UA_DUMMY_LEN 7/* * Process REGISTER request and save it's contacts */static inline int save_real(struct sip_msg* _m, udomain_t* _t, char* _s, int doreply){	contact_t* c;	int st;	str aor, ua;	rerrno = R_FINE;	if (parse_message(_m) < 0) {		goto error;	}	if (check_contacts(_m, &st) > 0) {		goto error;	}		get_act_time();	c = get_first_contact(_m);	if (extract_aor(&get_to(_m)->uri, &aor) < 0) {		LOG(L_ERR, "save(): Error while extracting Address Of Record\n");		goto error;	}	ua.len = 0;	if (parse_headers(_m, HDR_USERAGENT, 0) != -1 && _m->user_agent &&	    _m->user_agent->body.len > 0) {		ua.len = _m->user_agent->body.len;		ua.s = _m->user_agent->body.s;	}	if (ua.len == 0) {		ua.len = UA_DUMMY_LEN;		ua.s = UA_DUMMY_STR;	}	if (c == 0) {		if (st) {			if (star(_t, &aor) < 0) goto error;		} else {			if (no_contacts(_t, &aor) < 0) goto error;		}	} else {		if (contacts(_m, c, _t, &aor, &ua) < 0) goto error;	}	if (doreply && (send_reply(_m) < 0)) return -1;	else return 1;	 error:	if (doreply) send_reply(_m);	return 0;}/* * Process REGISTER request and save it's contacts */int save(struct sip_msg* _m, char* _t, char* _s){	mem_only = 0;	return save_real(_m, (udomain_t*)_t, _s, 1);}/* * Process REGISTER request and save it's contacts, do not send any replies */int save_noreply(struct sip_msg* _m, char* _t, char* _s){	mem_only = 0;	return save_real(_m, (udomain_t*)_t, _s, 0);}/* * Update memory cache only */int save_memory(struct sip_msg* _m, char* _t, char* _s){	mem_only = FL_MEM;	return save_real(_m, (udomain_t*)_t, _s, 1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -