modules_k/registrar/save.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Process REGISTER request and send reply
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  * Copyright (C) 2006 Voice Sistem SRL
00008  *
00009  * This file is part of Kamailio, a free SIP server.
00010  *
00011  * Kamailio is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version
00015  *
00016  * Kamailio is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License 
00022  * along with this program; if not, write to the Free Software 
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  *
00025  * History:
00026  * ----------
00027  * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
00028  * 2003-02-28 scrathcpad compatibility abandoned (jiri)
00029  * 2003-03-21 save_noreply added, patch provided by Maxim Sobolev 
00030  *            <sobomax@portaone.com> (janakj)
00031  * 2005-07-11 added sip_natping_flag for nat pinging with SIP method
00032  *            instead of UDP package (bogdan)
00033  * 2006-04-13 added tcp_persistent_flag for keeping the TCP connection as long
00034  *            as a TCP contact is registered (bogdan)
00035  * 2006-11-22 save_noreply and save_memory merged into save() (bogdan)
00036  * 2006-11-28 Added statistic support for the number of accepted/rejected 
00037  *            registrations. (Jeffrey Magder - SOMA Networks) 
00038  * 2007-02-24  sip_natping_flag moved into branch flags, so migrated to 
00039  *             nathelper module (bogdan)
00040  */
00048 #include "../../str.h"
00049 #include "../../socket_info.h"
00050 #include "../../parser/parse_allow.h"
00051 #include "../../parser/parse_methods.h"
00052 #include "../../parser/msg_parser.h"
00053 #include "../../parser/parse_to.h"
00054 #include "../../parser/parse_uri.h"
00055 #include "../../dprint.h"
00056 #include "../../trim.h"
00057 #include "../../ut.h"
00058 #include "../../qvalue.h"
00059 #include "../../dset.h"
00060 #include "../../xavp.h"
00061 #include "../../mod_fix.h"
00062 #include "../../lib/srutils/sruid.h"
00063 #include "../../lib/kcore/cmpapi.h"
00064 #include "../../lib/kcore/statistics.h"
00065 #ifdef USE_TCP
00066 #include "../../tcp_server.h"
00067 #endif
00068 #include "../usrloc/usrloc.h"
00069 #include "common.h"
00070 #include "sip_msg.h"
00071 #include "rerrno.h"
00072 #include "reply.h"
00073 #include "reg_mod.h"
00074 #include "regtime.h"
00075 #include "path.h"
00076 #include "save.h"
00077 #include "config.h"
00078 
00079 static int mem_only = 0;
00080 
00081 extern sruid_t _reg_sruid;
00082 
00088 static inline int star(sip_msg_t *_m, udomain_t* _d, str* _a, str *_h)
00089 {
00090         urecord_t* r;
00091         ucontact_t* c;
00092         
00093         ul.lock_udomain(_d, _a);
00094 
00095         if (!ul.get_urecord(_d, _a, &r)) {
00096                 c = r->contacts;
00097                 while(c) {
00098                         if (mem_only) {
00099                                 c->flags |= FL_MEM;
00100                         } else {
00101                                 c->flags &= ~FL_MEM;
00102                         }
00103                         c = c->next;
00104                 }
00105         } else {
00106                 r = NULL;
00107         }
00108 
00109         if (ul.delete_urecord(_d, _a, r) < 0) {
00110                 LM_ERR("failed to remove record from usrloc\n");
00111                 
00112                      /* Delete failed, try to get corresponding
00113                       * record structure and send back all existing
00114                       * contacts
00115                       */
00116                 rerrno = R_UL_DEL_R;
00117                 if (!ul.get_urecord(_d, _a, &r)) {
00118                         build_contact(_m, r->contacts, _h);
00119                         ul.release_urecord(r);
00120                 }
00121                 ul.unlock_udomain(_d, _a);
00122                 return -1;
00123         }
00124         ul.unlock_udomain(_d, _a);
00125         return 0;
00126 }
00127 
00128 
00131 static struct socket_info *get_sock_hdr(struct sip_msg *msg)
00132 {
00133         struct socket_info *sock;
00134         struct hdr_field *hf;
00135         str socks;
00136         str hosts;
00137         int port;
00138         int proto;
00139         char c;
00140 
00141         if (parse_headers( msg, HDR_EOH_F, 0) == -1) {
00142                 LM_ERR("failed to parse message\n");
00143                 return 0;
00144         }
00145 
00146         for (hf=msg->headers; hf; hf=hf->next) {
00147                 if (cmp_hdrname_str(&hf->name, &sock_hdr_name)==0)
00148                         break;
00149         }
00150 
00151         /* hdr found? */
00152         if (hf==0)
00153                 return 0;
00154 
00155         trim_len( socks.len, socks.s, hf->body );
00156         if (socks.len==0)
00157                 return 0;
00158 
00159         /*FIXME: This is a hack */
00160         c = socks.s[socks.len];
00161         socks.s[socks.len] = '\0';
00162         if (parse_phostport( socks.s, &hosts.s, &hosts.len,
00163         &port, &proto)!=0) {
00164                 socks.s[socks.len] = c;
00165                 LM_ERR("bad socket <%.*s> in \n",
00166                         socks.len, socks.s);
00167                 return 0;
00168         }
00169         socks.s[socks.len] = c;
00170         sock = grep_sock_info(&hosts,(unsigned short)port,(unsigned short)proto);
00171         if (sock==0) {
00172                 LM_ERR("non-local socket <%.*s>\n",     socks.len, socks.s);
00173                 return 0;
00174         }
00175 
00176         LM_DBG("%d:<%.*s>:%d -> p=%p\n", proto,socks.len,socks.s,port_no,sock );
00177 
00178         return sock;
00179 }
00180 
00181 
00182 
00189 static inline int no_contacts(sip_msg_t *_m, udomain_t* _d, str* _a, str* _h)
00190 {
00191         urecord_t* r;
00192         int res;
00193         
00194         ul.lock_udomain(_d, _a);
00195         res = ul.get_urecord(_d, _a, &r);
00196         if (res < 0) {
00197                 rerrno = R_UL_GET_R;
00198                 LM_ERR("failed to retrieve record from usrloc\n");
00199                 ul.unlock_udomain(_d, _a);
00200                 return -1;
00201         }
00202         
00203         if (res == 0) {  /* Contacts found */
00204                 build_contact(_m, r->contacts, _h);
00205                 ul.release_urecord(r);
00206         } else {  /* No contacts found */
00207                 build_contact(_m, NULL, _h);
00208         }
00209         ul.unlock_udomain(_d, _a);
00210         return 0;
00211 }
00212 
00213 
00214 
00218 static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c,
00219                                                                                         unsigned int _e, unsigned int _f)
00220 {
00221         static ucontact_info_t ci;
00222         static str no_ua = str_init("n/a");
00223         static str callid;
00224         static str path_received = {0,0};
00225         static str path;
00226         static str received = {0,0};
00227         static int received_found;
00228         static unsigned int allowed, allow_parsed;
00229         static struct sip_msg *m = 0;
00230         int_str val;
00231 
00232         if (_m!=0) {
00233                 memset( &ci, 0, sizeof(ucontact_info_t));
00234 
00235                 /* Get callid of the message */
00236                 callid = _m->callid->body;
00237                 trim_trailing(&callid);
00238                 if (callid.len > CALLID_MAX_SIZE) {
00239                         rerrno = R_CALLID_LEN;
00240                         LM_ERR("callid too long\n");
00241                         goto error;
00242                 }
00243                 ci.callid = &callid;
00244 
00245                 /* Get CSeq number of the message */
00246                 if (str2int(&get_cseq(_m)->number, (unsigned int*)&ci.cseq) < 0) {
00247                         rerrno = R_INV_CSEQ;
00248                         LM_ERR("failed to convert cseq number\n");
00249                         goto error;
00250                 }
00251 
00252                 /* set received socket */
00253                 if (_m->flags&sock_flag) {
00254                         ci.sock = get_sock_hdr(_m);
00255                         if (ci.sock==0)
00256                                 ci.sock = _m->rcv.bind_address;
00257                 } else {
00258                         ci.sock = _m->rcv.bind_address;
00259                 }
00260 
00261                 /* additional info from message */
00262                 if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent &&
00263                 _m->user_agent->body.len>0 && _m->user_agent->body.len<UA_MAX_SIZE) {
00264                         ci.user_agent = &_m->user_agent->body;
00265                 } else {
00266                         ci.user_agent = &no_ua;
00267                 }
00268 
00269                 /* extract Path headers */
00270                 if (path_enabled) {
00271                         if (build_path_vector(_m, &path, &path_received) < 0) {
00272                                 rerrno = R_PARSE_PATH;
00273                                 goto error;
00274                         }
00275                         if (path.len && path.s) {
00276                                 ci.path = &path;
00277                                 if (path_mode != PATH_MODE_OFF) {
00278                                         /* save in msg too for reply */
00279                                         if (set_path_vector(_m, &path) < 0) {
00280                                                 rerrno = R_PARSE_PATH;
00281                                                 goto error;
00282                                         }
00283                                 }
00284                         }
00285                 }
00286 
00287                 ci.last_modified = act_time;
00288 
00289                 /* set flags */
00290                 ci.flags  = _f;
00291                 getbflagsval(0, &ci.cflags);
00292 
00293                 /* get received */
00294                 if (path_received.len && path_received.s) {
00295                         ci.cflags |= ul.nat_flag;
00296                         ci.received = path_received;
00297                 }
00298 
00299                 allow_parsed = 0; /* not parsed yet */
00300                 received_found = 0; /* not found yet */
00301                 m = _m; /* remember the message */
00302         }
00303 
00304         if(_c!=0) {
00305                 /* Calculate q value of the contact */
00306                 if (calc_contact_q(_c->q, &ci.q) < 0) {
00307                         rerrno = R_INV_Q;
00308                         LM_ERR("failed to calculate q\n");
00309                         goto error;
00310                 }
00311 
00312                 /* set expire time */
00313                 ci.expires = _e;
00314 
00315                 /* Get methods of contact */
00316                 if (_c->methods) {
00317                         if (parse_methods(&(_c->methods->body), &ci.methods) < 0) {
00318                                 rerrno = R_PARSE;
00319                                 LM_ERR("failed to parse contact methods\n");
00320                                 goto error;
00321                         }
00322                 } else {
00323                         /* check on Allow hdr */
00324                         if (allow_parsed == 0) {
00325                                 if (m && parse_allow( m ) != -1) {
00326                                         allowed = get_allow_methods(m);
00327                                 } else {
00328                                         allowed = ALL_METHODS;
00329                                 }
00330                                 allow_parsed = 1;
00331                         }
00332                         ci.methods = allowed;
00333                 }
00334 
00335                 /* get received */
00336                 if (ci.received.len==0) {
00337                         if (_c->received) {
00338                                 ci.received = _c->received->body;
00339                         } else {
00340                                 if (received_found==0) {
00341                                         memset(&val, 0, sizeof(int_str));
00342                                         if (rcv_avp_name.n!=0
00343                                                                 && search_first_avp(rcv_avp_type, rcv_avp_name, &val, 0)
00344                                                                 && val.s.len > 0) {
00345                                                 if (val.s.len>RECEIVED_MAX_SIZE) {
00346                                                         rerrno = R_CONTACT_LEN;
00347                                                         LM_ERR("received too long\n");
00348                                                         goto error;
00349                                                 }
00350                                                 received = val.s;
00351                                         } else {
00352                                                 received.s = 0;
00353                                                 received.len = 0;
00354                                         }
00355                                         received_found = 1;
00356                                 }
00357                                 ci.received = received;
00358                         }
00359                 }
00360                 if(_c->instance!=NULL && _c->instance->body.len>0)
00361                         ci.instance = _c->instance->body;
00362                 if(_c->reg_id!=NULL && _c->reg_id->body.len>0) {
00363                         if(str2int(&_c->reg_id->body, &ci.reg_id)<0)
00364                         {
00365                                 LM_ERR("invalid reg-id value\n");
00366                                 goto error;
00367                         }
00368                 }
00369                 if(sruid_next(&_reg_sruid)<0)
00370                         goto error;
00371                 ci.ruid = _reg_sruid.uid;
00372         }
00373 
00374         return &ci;
00375 error:
00376         return 0;
00377 }
00378 
00379 
00380 int reg_get_crt_max_contacts(void)
00381 {
00382         int n;
00383         sr_xavp_t *ravp=NULL;
00384         sr_xavp_t *vavp=NULL;
00385         str vname = {"max_contacts", 12};
00386 
00387         n = 0;
00388 
00389         if(reg_xavp_cfg.s!=NULL)
00390         {
00391                 ravp = xavp_get(&reg_xavp_cfg, NULL);
00392                 if(ravp!=NULL && ravp->val.type==SR_XTYPE_XAVP)
00393                 {
00394                         vavp = xavp_get(&vname, ravp->val.v.xavp);
00395                         if(vavp!=NULL && vavp->val.type==SR_XTYPE_INT)
00396                         {
00397                                 n = vavp->val.v.i;
00398                                 LM_ERR("using max contacts value from xavp: %d\n", n);
00399                         } else {
00400                                 ravp = NULL;
00401                         }
00402                 } else {
00403                         ravp = NULL;
00404                 }
00405         }
00406 
00407         if(ravp==NULL)
00408         {
00409                 n = cfg_get(registrar, registrar_cfg, max_contacts);
00410         }
00411 
00412         return n;
00413 }
00414 
00421 static inline int insert_contacts(struct sip_msg* _m, udomain_t* _d, str* _a)
00422 {
00423         ucontact_info_t* ci;
00424         urecord_t* r = NULL;
00425         ucontact_t* c;
00426         contact_t* _c;
00427         unsigned int flags;
00428         int num, expires;
00429         int maxc;
00430 #ifdef USE_TCP
00431         int e_max, tcp_check;
00432         struct sip_uri uri;
00433 #endif
00434         sip_uri_t *u;
00435 
00436         u = parse_to_uri(_m);
00437         if(u==NULL)
00438                 goto error;
00439 
00440         flags = mem_only;
00441 #ifdef USE_TCP
00442         if ( (_m->flags&tcp_persistent_flag) &&
00443         (_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS)) {
00444                 e_max = 0;
00445                 tcp_check = 1;
00446         } else {
00447                 e_max = tcp_check = 0;
00448         }
00449 #endif
00450         _c = get_first_contact(_m);
00451         maxc = reg_get_crt_max_contacts();
00452         for( num=0,r=0,ci=0 ; _c ; _c = get_next_contact(_c) ) {
00453                 /* calculate expires */
00454                 calc_contact_expires(_m, _c->expires, &expires);
00455                 /* Skip contacts with zero expires */
00456                 if (expires == 0)
00457                         continue;
00458 
00459 
00460                 if (maxc > 0 && num >= maxc) {
00461                         LM_INFO("too many contacts (%d) for AOR <%.*s>\n", 
00462                                         num, _a->len, _a->s);
00463                         rerrno = R_TOO_MANY;
00464                         goto error;
00465                 }
00466                 num++;
00467 
00468                 if (r==0) {
00469                         if (ul.insert_urecord(_d, _a, &r) < 0) {
00470                                 rerrno = R_UL_NEW_R;
00471                                 LM_ERR("failed to insert new record structure\n");
00472                                 goto error;
00473                         }
00474                 }
00475 
00476                 /* pack the contact_info */
00477                 if ( (ci=pack_ci( (ci==0)?_m:0, _c, expires, flags))==0 ) {
00478                         LM_ERR("failed to extract contact info\n");
00479                         goto error;
00480                 }
00481 
00482                 /* hack to work with buggy clients having many contacts with same
00483                  * address in one REGISTER - increase CSeq to detect if there was
00484                  * one alredy added, then update */
00485                 ci->cseq++;
00486                 if ( r->contacts==0
00487                                 || ul.get_ucontact_by_instance(r, &_c->uri, ci, &c) != 0) {
00488                         ci->cseq--;
00489                         if (ul.insert_ucontact( r, &_c->uri, ci, &c) < 0) {
00490                                 rerrno = R_UL_INS_C;
00491                                 LM_ERR("failed to insert contact\n");
00492                                 goto error;
00493                         }
00494                 } else {
00495                         ci->cseq--;
00496                         if (ul.update_ucontact( r, c, ci) < 0) {
00497                                 rerrno = R_UL_UPD_C;
00498                                 LM_ERR("failed to update contact\n");
00499                                 goto error;
00500                         }
00501                 }
00502 #ifdef USE_TCP
00503                 if (tcp_check) {
00504                         /* parse contact uri to see if transport is TCP */
00505                         if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) {
00506                                 LM_ERR("failed to parse contact <%.*s>\n", 
00507                                                 _c->uri.len, _c->uri.s);
00508                         } else if (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS) {
00509                                 if (e_max) {
00510                                         LM_WARN("multiple TCP contacts on single REGISTER\n");
00511                                         if (expires>e_max) e_max = expires;
00512                                 } else {
00513                                         e_max = expires;
00514                                 }
00515                         }
00516                 }
00517 #endif
00518         }
00519 
00520         if (r) {
00521                 if (r->contacts)
00522                         build_contact(_m, r->contacts, &u->host);
00523                 ul.release_urecord(r);
00524         } else { /* No contacts found */
00525                 build_contact(_m, NULL, &u->host);
00526         }
00527 
00528 #ifdef USE_TCP
00529         if ( tcp_check && e_max>0 ) {
00530                 e_max -= act_time;
00531                 /*FIXME: Do we want this in the sr core?*/
00532                 /*force_tcp_conn_lifetime( &_m->rcv , e_max + 10 );*/
00533         }
00534 #endif
00535 
00536         return 0;
00537 error:
00538         if (r)
00539                 ul.delete_urecord(_d, _a, r);
00540         return -1;
00541 }
00542 
00543 
00544 static int test_max_contacts(struct sip_msg* _m, urecord_t* _r, contact_t* _c,
00545                                                                                 ucontact_info_t *ci, int mc)
00546 {
00547         int num;
00548         int e;
00549         ucontact_t* ptr, *cont;
00550         int ret;
00551         
00552         num = 0;
00553         ptr = _r->contacts;
00554         while(ptr) {
00555                 if (VALID_CONTACT(ptr, act_time)) {
00556                         num++;
00557                 }
00558                 ptr = ptr->next;
00559         }
00560         LM_DBG("%d valid contacts\n", num);
00561         
00562         for( ; _c ; _c = get_next_contact(_c) ) {
00563                 /* calculate expires */
00564                 calc_contact_expires(_m, _c->expires, &e);
00565 
00566                 ret = ul.get_ucontact_by_instance( _r, &_c->uri, ci, &cont);
00567                 if (ret==-1) {
00568                         LM_ERR("invalid cseq for aor <%.*s>\n",_r->aor.len,_r->aor.s);
00569                         rerrno = R_INV_CSEQ;
00570                         return -1;
00571                 } else if (ret==-2) {
00572                         continue;
00573                 }
00574                 if (ret > 0) {
00575                         /* Contact not found */
00576                         if (e != 0) num++;
00577                 } else {
00578                         if (e == 0) num--;
00579                 }
00580         }
00581         
00582         LM_DBG("%d contacts after commit\n", num);
00583         if (num > mc) {
00584                 LM_INFO("too many contacts for AOR <%.*s>\n", _r->aor.len, _r->aor.s);
00585                 rerrno = R_TOO_MANY;
00586                 return -1;
00587         }
00588 
00589         return 0;
00590 }
00591 
00592 
00604 static inline int update_contacts(struct sip_msg* _m, urecord_t* _r,
00605                                                                                 int _mode)
00606 {
00607         ucontact_info_t *ci;
00608         ucontact_t *c, *ptr, *ptr0;
00609         int expires, ret, updated;
00610         unsigned int flags;
00611 #ifdef USE_TCP
00612         int e_max, tcp_check;
00613         struct sip_uri uri;
00614 #endif
00615         int rc;
00616         contact_t* _c;
00617         int maxc;
00618 
00619         /* mem flag */
00620         flags = mem_only;
00621 
00622         rc = 0;
00623         /* pack the contact_info */
00624         if ( (ci=pack_ci( _m, 0, 0, flags))==0 ) {
00625                 LM_ERR("failed to initial pack contact info\n");
00626                 goto error;
00627         }
00628 
00629         if (!_mode) {
00630                 maxc = reg_get_crt_max_contacts();
00631                 if(maxc>0) {
00632                         _c = get_first_contact(_m);
00633                         if(test_max_contacts(_m, _r, _c, ci, maxc) != 0)
00634                                 goto error;
00635                 }
00636         }
00637 
00638 #ifdef USE_TCP
00639         if ( (_m->flags&tcp_persistent_flag) &&
00640         (_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS)) {
00641                 e_max = -1;
00642                 tcp_check = 1;
00643         } else {
00644                 e_max = tcp_check = 0;
00645         }
00646 #endif
00647 
00648         _c = get_first_contact(_m);
00649         updated=0;
00650         for( ; _c ; _c = get_next_contact(_c) ) {
00651                 /* calculate expires */
00652                 calc_contact_expires(_m, _c->expires, &expires);
00653 
00654                 /* search for the contact*/
00655                 ret = ul.get_ucontact_by_instance( _r, &_c->uri, ci, &c);
00656                 if (ret==-1) {
00657                         LM_ERR("invalid cseq for aor <%.*s>\n",_r->aor.len,_r->aor.s);
00658                         rerrno = R_INV_CSEQ;
00659                         goto error;
00660                 } else if (ret==-2) {
00661                         if(expires!=0 && _mode)
00662                                 break;
00663                         continue;
00664                 }
00665 
00666                 if ( ret > 0 ) {
00667                         /* Contact not found -> expired? */
00668                         if (expires==0)
00669                                 continue;
00670 
00671                         /* pack the contact_info */
00672                         if ( (ci=pack_ci( 0, _c, expires, 0))==0 ) {
00673                                 LM_ERR("failed to extract contact info\n");
00674                                 goto error;
00675                         }
00676 
00677                         if (ul.insert_ucontact( _r, &_c->uri, ci, &c) < 0) {
00678                                 rerrno = R_UL_INS_C;
00679                                 LM_ERR("failed to insert contact\n");
00680                                 goto error;
00681                         }
00682                         rc = 1;
00683                         if(_mode)
00684                         {
00685                                 ptr=_r->contacts;
00686                                 while(ptr)
00687                                 {
00688                                         ptr0 = ptr;
00689                                         if(ptr!=c)
00690                                                 ul.delete_ucontact(_r, ptr);
00691                                         ptr=ptr0->next;
00692                                 }
00693                                 updated=1;
00694                         }
00695                 } else {
00696                         /* Contact found */
00697                         if (expires == 0) {
00698                                 /* it's expired */
00699                                 if (mem_only) {
00700                                         c->flags |= FL_MEM;
00701                                 } else {
00702                                         c->flags &= ~FL_MEM;
00703                                 }
00704 
00705                                 if (ul.delete_ucontact(_r, c) < 0) {
00706                                         rerrno = R_UL_DEL_C;
00707                                         LM_ERR("failed to delete contact\n");
00708                                         goto error;
00709                                 }
00710                                 rc = 3;
00711                         } else {
00712                                 /* do update */
00713                                 /* pack the contact specific info */
00714                                 if ( (ci=pack_ci( 0, _c, expires, 0))==0 ) {
00715                                         LM_ERR("failed to pack contact specific info\n");
00716                                         goto error;
00717                                 }
00718 
00719                                 if(_mode)
00720                                 {
00721                                         ptr=_r->contacts;
00722                                         while(ptr)
00723                                         {
00724                                                 ptr0 = ptr;
00725                                                 if(ptr!=c)
00726                                                         ul.delete_ucontact(_r, ptr);
00727                                                 ptr=ptr0->next;
00728                                         }
00729                                         updated=1;
00730                                 }
00731                                 if (ul.update_ucontact(_r, c, ci) < 0) {
00732                                         rerrno = R_UL_UPD_C;
00733                                         LM_ERR("failed to update contact\n");
00734                                         goto error;
00735                                 }
00736                                 rc = 2;
00737                         }
00738                 }
00739 #ifdef USE_TCP
00740                 if (tcp_check) {
00741                         /* parse contact uri to see if transport is TCP */
00742                         if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) {
00743                                 LM_ERR("failed to parse contact <%.*s>\n", 
00744                                                 _c->uri.len, _c->uri.s);
00745                         } else if (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS) {
00746                                 if (e_max>0) {
00747                                         LM_WARN("multiple TCP contacts on single REGISTER\n");
00748                                 }
00749                                 if (expires>e_max) e_max = expires;
00750                         }
00751                 }
00752 #endif
00753                 /* have one contact only -- break */
00754                 if(updated)
00755                         break;
00756         }
00757 
00758 #ifdef USE_TCP
00759         if ( tcp_check && e_max>-1 ) {
00760                 if (e_max) e_max -= act_time;
00761                 /*FIXME: Do we want this in the sr core? */
00762                 /*force_tcp_conn_lifetime( &_m->rcv , e_max + 10 );*/
00763         }
00764 #endif
00765 
00766         return rc;
00767 error:
00768         return -1;
00769 }
00770 
00771 
00776 static inline int add_contacts(struct sip_msg* _m, udomain_t* _d,
00777                 str* _a, int _mode)
00778 {
00779         int res;
00780         int ret;
00781         urecord_t* r;
00782         sip_uri_t *u;
00783 
00784         u = parse_to_uri(_m);
00785         if(u==NULL)
00786                 return -2;
00787 
00788         ret = 0;
00789         ul.lock_udomain(_d, _a);
00790         res = ul.get_urecord(_d, _a, &r);
00791         if (res < 0) {
00792                 rerrno = R_UL_GET_R;
00793                 LM_ERR("failed to retrieve record from usrloc\n");
00794                 ul.unlock_udomain(_d, _a);
00795                 return -2;
00796         }
00797 
00798         if (res == 0) { /* Contacts found */
00799                 if ((ret=update_contacts(_m, r, _mode)) < 0) {
00800                         build_contact(_m, r->contacts, &u->host);
00801                         ul.release_urecord(r);
00802                         ul.unlock_udomain(_d, _a);
00803                         return -3;
00804                 }
00805                 build_contact(_m, r->contacts, &u->host);
00806                 ul.release_urecord(r);
00807         } else {
00808                 if (insert_contacts(_m, _d, _a) < 0) {
00809                         ul.unlock_udomain(_d, _a);
00810                         return -4;
00811                 }
00812                 ret = 1;
00813         }
00814         ul.unlock_udomain(_d, _a);
00815         return ret;
00816 }
00817 
00818 
00822 #define is_cflag_set(_name) (((unsigned int)_cflags)&(_name))
00823 int save(struct sip_msg* _m, udomain_t* _d, int _cflags, str *_uri)
00824 {
00825         contact_t* c;
00826         int st, mode;
00827         str aor;
00828         int ret;
00829         sip_uri_t *u;
00830 
00831         u = parse_to_uri(_m);
00832         if(u==NULL)
00833                 goto error;
00834 
00835         rerrno = R_FINE;
00836         ret = 1;
00837 
00838         if (parse_message(_m) < 0) {
00839                 goto error;
00840         }
00841 
00842         if (check_contacts(_m, &st) > 0) {
00843                 goto error;
00844         }
00845         
00846         get_act_time();
00847         c = get_first_contact(_m);
00848 
00849         if (extract_aor((_uri)?_uri:&get_to(_m)->uri, &aor, NULL) < 0) {
00850                 LM_ERR("failed to extract Address Of Record\n");
00851                 goto error;
00852         }
00853 
00854         mem_only = is_cflag_set(REG_SAVE_MEM_FL)?FL_MEM:FL_NONE;
00855 
00856         if (c == 0) {
00857                 if (st) {
00858                         if (star(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error;
00859                         else ret=3;
00860                 } else {
00861                         if (no_contacts(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error;
00862                         else ret=4;
00863                 }
00864         } else {
00865                 mode = is_cflag_set(REG_SAVE_REPL_FL)?1:0;
00866                 if ((ret=add_contacts(_m, (udomain_t*)_d, &aor, mode)) < 0)
00867                         goto error;
00868                 ret = (ret==0)?1:ret;
00869         }
00870 
00871         update_stat(accepted_registrations, 1);
00872 
00873         /* Only send reply upon request, not upon reply */
00874         if ((is_route_type(REQUEST_ROUTE)) && !is_cflag_set(REG_SAVE_NORPL_FL) && (reg_send_reply(_m) < 0))
00875                 return -1;
00876 
00877         return ret;
00878 error:
00879         update_stat(rejected_registrations, 1);
00880         if (is_route_type(REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) )
00881                 reg_send_reply(_m);
00882 
00883         return 0;
00884 }
00885 
00886 int unregister(struct sip_msg* _m, udomain_t* _d, str* _uri)
00887 {
00888         str aor = {0, 0};
00889         sip_uri_t *u;
00890 
00891         u = parse_to_uri(_m);
00892         if(u==NULL)
00893                 return -2;
00894 
00895 
00896         if (extract_aor(_uri, &aor, NULL) < 0) {
00897                 LM_ERR("failed to extract Address Of Record\n");
00898                 return -1;
00899         }
00900 
00901         if (star(_m, _d, &aor, &u->host) < 0)
00902         {
00903                 LM_ERR("error unregistering user [%.*s]\n", aor.len, aor.s);
00904                 return -1;
00905         }
00906         return 1;
00907 }
00908