📄 save.c
字号:
/* * $Id: save.c,v 1.31 2006/07/04 10:58:32 bogdan_iancu Exp $ * * Process REGISTER request and send reply * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of openser, a free SIP server. * * openser 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 * * openser 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) * 2005-07-11 added sip_natping_flag for nat pinging with SIP method * instead of UDP package (bogdan) * 2006-04-13 added tcp_persistent_flag for keeping the TCP connection as long * as a TCP contact is registered (bogdan) */#include "../../str.h"#include "../../socket_info.h"#include "../../parser/parse_allow.h"#include "../../parser/parse_methods.h"#include "../../parser/msg_parser.h"#include "../../parser/parse_uri.h"#include "../../dprint.h"#include "../../trim.h"#include "../../ut.h"#include "../../qvalue.h"#ifdef USE_TCP#include "../../tcp_server.h"#endif#include "../usrloc/usrloc.h"#include "common.h"#include "sip_msg.h"#include "rerrno.h"#include "reply.h"#include "reg_mod.h"#include "regtime.h"#include "path.h"#include "save.h"static int mem_only = 0;int_str rcv_avp;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) < 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;}/* */static struct socket_info *get_sock_hdr(struct sip_msg *msg){ struct socket_info *sock; struct hdr_field *hf; str socks; str hosts; int port; int proto; if (parse_headers( msg, HDR_EOH_F, 0) == -1) { LOG(L_ERR,"ERROR:registrar:get_sock_hdr: failed to parse message\n"); return 0; } for (hf=msg->headers; hf; hf=hf->next) { if (hf->name.len==sock_hdr_name.len && strncasecmp(hf->name.s, sock_hdr_name.s, sock_hdr_name.len)==0 ) break; } /* hdr found? */ if (hf==0) return 0; trim_len( socks.len, socks.s, hf->body ); if (socks.len==0) return 0; if (parse_phostport( socks.s, socks.len, &hosts.s, &hosts.len, &port, &proto)!=0) { LOG(L_ERR,"ERROR:registrar:get_sock_hdr: bad socket <%.*s> in \n", socks.len, socks.s); return 0; } sock = grep_sock_info(&hosts,(unsigned short)port,(unsigned short)proto); if (sock==0) { LOG(L_WARN,"ERROR:registrar:get_sock_hdr: non-local socket <%.*s>\n", socks.len, socks.s); return 0; } DBG("DEBUG:registrar:get_sock_hdr: %d:<%.*s>:%d -> p=%p\n", proto,socks.len,socks.s,port_no,sock ); return sock;}/* * 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, "ERROR:registrar:no_contacts: failed to retrieve 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;}/* * 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, int _e, int _f1, int _f2){ 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; LOG(L_ERR, "ERROR:registrar:pack_ci: 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; LOG(L_ERR, "ERROR:registrar:pack_ci: failed to convert " "cseq number\n"); goto error; } /* set received socket */ if (_m->flags&sock_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 (path_enabled) { if (build_path_vector(_m, &path, &path_received) < 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; 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; LOG(L_ERR, "ERROR:registrar:pack_ci: failed to calculate q\n"); goto error; } /* set expire time */ ci.expires = _e; /* set flags */ ci.flags1 = _f1; ci.flags2 = _f2; /* Get methods of contact */ if (_c->methods) { if (parse_methods(&(_c->methods->body), &ci.methods) < 0) { rerrno = R_PARSE; LOG(L_ERR, "ERROR:usrloc:pack_ci: 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 (path_received.len && path_received.s) { ci.flags1 |= FL_NAT; ci.flags2 &= ~FL_NAT; ci.received = path_received; } else if (_c->received) { ci.received = _c->received->body; } else { if (received_found==0) { if (search_first_avp(0, rcv_avp, &val, 0) && val.s.s) { if (val.s.len>RECEIVED_MAX_SIZE) { rerrno = R_CONTACT_LEN; LOG(L_ERR,"ERROR:registrar:pack_ci: 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;}/* * 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){ ucontact_info_t* ci; urecord_t* r; ucontact_t* c; unsigned int flags; int num; int e;#ifdef USE_TCP int e_max; int tcp_check; struct sip_uri uri;#endif /* is nated flag */ if (_m->flags&nat_flag) flags = FL_NAT; else flags = FL_NONE; /* nat type flag */ if (_m->flags&sip_natping_flag) flags |= FL_NAT_SIPPING; flags |= mem_only;#ifdef USE_TCP if ( (_m->flags&tcp_persistent_flag) && (_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS)) { e_max = 0; tcp_check = 1; } else { e_max = tcp_check = 0; }#endif for( num=0,r=0,ci=0 ; _c ; _c = get_next_contact(_c) ) { /* calculate expires */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -