save.c

Go to the documentation of this file.
00001 /*
00002  * $Id: save.c 5503 2009-01-23 13:07:41Z carstenbock $
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  */
00041 /*!
00042  * \file
00043  * \brief SIP registrar module - Process REGISTER request and send reply
00044  * \ingroup registrar   
00045  */  
00046 
00047 
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_uri.h"
00054 #include "../../dprint.h"
00055 #include "../../trim.h"
00056 #include "../../ut.h"
00057 #include "../../qvalue.h"
00058 #include "../../dset.h"
00059 #include "../../mod_fix.h"
00060 #include "../../cmpapi.h"
00061 #ifdef USE_TCP
00062 #include "../../tcp_server.h"
00063 #endif
00064 #include "../usrloc/usrloc.h"
00065 #include "common.h"
00066 #include "sip_msg.h"
00067 #include "rerrno.h"
00068 #include "reply.h"
00069 #include "reg_mod.h"
00070 #include "regtime.h"
00071 #include "path.h"
00072 #include "save.h"
00073 
00074 static int mem_only = 0;
00075 
00076 /*! \brief
00077  * Process request that contained a star, in that case, 
00078  * we will remove all bindings with the given username 
00079  * from the usrloc and return 200 OK response
00080  */
00081 static inline int star(udomain_t* _d, str* _a)
00082 {
00083    urecord_t* r;
00084    ucontact_t* c;
00085    
00086    ul.lock_udomain(_d, _a);
00087 
00088    if (!ul.get_urecord(_d, _a, &r)) {
00089       c = r->contacts;
00090       while(c) {
00091          if (mem_only) {
00092             c->flags |= FL_MEM;
00093          } else {
00094             c->flags &= ~FL_MEM;
00095          }
00096          c = c->next;
00097       }
00098    } else {
00099       r = NULL;
00100    }
00101 
00102    if (ul.delete_urecord(_d, _a, r) < 0) {
00103       LM_ERR("failed to remove record from usrloc\n");
00104       
00105            /* Delete failed, try to get corresponding
00106             * record structure and send back all existing
00107             * contacts
00108             */
00109       rerrno = R_UL_DEL_R;
00110       if (!ul.get_urecord(_d, _a, &r)) {
00111          build_contact(r->contacts);
00112          ul.release_urecord(r);
00113       }
00114       ul.unlock_udomain(_d, _a);
00115       return -1;
00116    }
00117    ul.unlock_udomain(_d, _a);
00118    return 0;
00119 }
00120 
00121 
00122 /*! \brief
00123  */
00124 static struct socket_info *get_sock_hdr(struct sip_msg *msg)
00125 {
00126    struct socket_info *sock;
00127    struct hdr_field *hf;
00128    str socks;
00129    str hosts;
00130    int port;
00131    int proto;
00132 
00133    if (parse_headers( msg, HDR_EOH_F, 0) == -1) {
00134       LM_ERR("failed to parse message\n");
00135       return 0;
00136    }
00137 
00138    for (hf=msg->headers; hf; hf=hf->next) {
00139       if (cmp_hdrname_str(&hf->name, &sock_hdr_name)==0)
00140          break;
00141    }
00142 
00143    /* hdr found? */
00144    if (hf==0)
00145       return 0;
00146 
00147    trim_len( socks.len, socks.s, hf->body );
00148    if (socks.len==0)
00149       return 0;
00150 
00151    if (parse_phostport( socks.s, socks.len, &hosts.s, &hosts.len, 
00152    &port, &proto)!=0) {
00153       LM_ERR("bad socket <%.*s> in \n",
00154          socks.len, socks.s);
00155       return 0;
00156    }
00157    sock = grep_sock_info(&hosts,(unsigned short)port,(unsigned short)proto);
00158    if (sock==0) {
00159       LM_ERR("non-local socket <%.*s>\n", socks.len, socks.s);
00160       return 0;
00161    }
00162 
00163    LM_DBG("%d:<%.*s>:%d -> p=%p\n", proto,socks.len,socks.s,port_no,sock );
00164 
00165    return sock;
00166 }
00167 
00168 
00169 
00170 /*! \brief
00171  * Process request that contained no contact header
00172  * field, it means that we have to send back a response
00173  * containing a list of all existing bindings for the
00174  * given username (in To HF)
00175  */
00176 static inline int no_contacts(udomain_t* _d, str* _a)
00177 {
00178    urecord_t* r;
00179    int res;
00180    
00181    ul.lock_udomain(_d, _a);
00182    res = ul.get_urecord(_d, _a, &r);
00183    if (res < 0) {
00184       rerrno = R_UL_GET_R;
00185       LM_ERR("failed to retrieve record from usrloc\n");
00186       ul.unlock_udomain(_d, _a);
00187       return -1;
00188    }
00189    
00190    if (res == 0) {  /* Contacts found */
00191       build_contact(r->contacts);
00192       ul.release_urecord(r);
00193    }
00194    ul.unlock_udomain(_d, _a);
00195    return 0;
00196 }
00197 
00198 
00199 
00200 /*! \brief
00201  * Fills the common part (for all contacts) of the info structure
00202  */
00203 static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c,
00204                                  unsigned int _e, unsigned int _f)
00205 {
00206    static ucontact_info_t ci;
00207    static str no_ua = str_init("n/a");
00208    static str callid;
00209    static str path_received = {0,0};
00210    static str path;
00211    static str received = {0,0};
00212    static int received_found;
00213    static unsigned int allowed, allow_parsed;
00214    static struct sip_msg *m = 0;
00215    int_str val;
00216 
00217    if (_m!=0) {
00218       memset( &ci, 0, sizeof(ucontact_info_t));
00219 
00220       /* Get callid of the message */
00221       callid = _m->callid->body;
00222       trim_trailing(&callid);
00223       if (callid.len > CALLID_MAX_SIZE) {
00224          rerrno = R_CALLID_LEN;
00225          LM_ERR("callid too long\n");
00226          goto error;
00227       }
00228       ci.callid = &callid;
00229 
00230       /* Get CSeq number of the message */
00231       if (str2int(&get_cseq(_m)->number, (unsigned int*)&ci.cseq) < 0) {
00232          rerrno = R_INV_CSEQ;
00233          LM_ERR("failed to convert cseq number\n");
00234          goto error;
00235       }
00236 
00237       /* set received socket */
00238       if (_m->flags&sock_flag) {
00239          ci.sock = get_sock_hdr(_m);
00240          if (ci.sock==0)
00241             ci.sock = _m->rcv.bind_address;
00242       } else {
00243          ci.sock = _m->rcv.bind_address;
00244       }
00245 
00246       /* additional info from message */
00247       if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent &&
00248       _m->user_agent->body.len>0 && _m->user_agent->body.len<UA_MAX_SIZE) {
00249          ci.user_agent = &_m->user_agent->body;
00250       } else {
00251          ci.user_agent = &no_ua;
00252       }
00253 
00254       /* extract Path headers */
00255       if (path_enabled) {
00256          if (build_path_vector(_m, &path, &path_received) < 0) {
00257             rerrno = R_PARSE_PATH;
00258             goto error;
00259          }
00260          if (path.len && path.s) {
00261             ci.path = &path;
00262             /* save in msg too for reply */
00263             if (set_path_vector(_m, &path) < 0) {
00264                rerrno = R_PARSE_PATH;
00265                goto error;
00266             }
00267          }
00268       }
00269 
00270       ci.last_modified = act_time;
00271 
00272       /* set flags */
00273       ci.flags  = _f;
00274       ci.cflags =  getb0flags();
00275 
00276       /* get received */
00277       if (path_received.len && path_received.s) {
00278          ci.cflags |= ul.nat_flag;
00279          ci.received = path_received;
00280       }
00281 
00282       allow_parsed = 0; /* not parsed yet */
00283       received_found = 0; /* not found yet */
00284       m = _m; /* remember the message */
00285    }
00286 
00287    if(_c!=0) {
00288       /* Calculate q value of the contact */
00289       if (calc_contact_q(_c->q, &ci.q) < 0) {
00290          rerrno = R_INV_Q;
00291          LM_ERR("failed to calculate q\n");
00292          goto error;
00293       }
00294 
00295       /* set expire time */
00296       ci.expires = _e;
00297 
00298       /* Get methods of contact */
00299       if (_c->methods) {
00300          if (parse_methods(&(_c->methods->body), &ci.methods) < 0) {
00301             rerrno = R_PARSE;
00302             LM_ERR("failed to parse contact methods\n");
00303             goto error;
00304          }
00305       } else {
00306          /* check on Allow hdr */
00307          if (allow_parsed == 0) {
00308             if (m && parse_allow( m ) != -1) {
00309                allowed = get_allow_methods(m);
00310             } else {
00311                allowed = ALL_METHODS;
00312             }
00313             allow_parsed = 1;
00314          }
00315          ci.methods = allowed;
00316       }
00317 
00318       /* get received */
00319       if (ci.received.len==0) {
00320          if (_c->received) {
00321             ci.received = _c->received->body;
00322          } else {
00323             if (received_found==0) {
00324                memset(&val, 0, sizeof(int_str));
00325                if (rcv_avp_name.n!=0
00326                         && search_first_avp(rcv_avp_type, rcv_avp_name, &val, 0)
00327                         && val.s.len > 0) {
00328                   if (val.s.len>RECEIVED_MAX_SIZE) {
00329                      rerrno = R_CONTACT_LEN;
00330                      LM_ERR("received too long\n");
00331                      goto error;
00332                   }
00333                   received = val.s;
00334                } else {
00335                   received.s = 0;
00336                   received.len = 0;
00337                }
00338                received_found = 1;
00339             }
00340             ci.received = received;
00341          }
00342       }
00343 
00344    }
00345 
00346    return &ci;
00347 error:
00348    return 0;
00349 }
00350 
00351 
00352 
00353 /*! \brief
00354  * Message contained some contacts, but record with same address
00355  * of record was not found so we have to create a new record
00356  * and insert all contacts from the message that have expires
00357  * > 0
00358  */
00359 static inline int insert_contacts(struct sip_msg* _m, contact_t* _c,
00360                                        udomain_t* _d, str* _a)
00361 {
00362    ucontact_info_t* ci;
00363    urecord_t* r;
00364    ucontact_t* c;
00365    unsigned int flags;
00366    int num, expires;
00367 #ifdef USE_TCP
00368    int e_max, tcp_check;
00369    struct sip_uri uri;
00370 #endif
00371 
00372    flags = mem_only;
00373 #ifdef USE_TCP
00374    if ( (_m->flags&tcp_persistent_flag) &&
00375    (_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS)) {
00376       e_max = 0;
00377       tcp_check = 1;
00378    } else {
00379       e_max = tcp_check = 0;
00380    }
00381 #endif
00382 
00383    for( num=0,r=0,ci=0 ; _c ; _c = get_next_contact(_c) ) {
00384       /* calculate expires */
00385       calc_contact_expires(_m, _c->expires, &expires);
00386       /* Skip contacts with zero expires */
00387       if (expires == 0)
00388          continue;
00389 
00390       if (max_contacts && (num >= max_contacts)) {
00391          LM_INFO("too many contacts (%d) for AOR <%.*s>\n", 
00392                num, _a->len, _a->s);
00393          rerrno = R_TOO_MANY;
00394          goto error;
00395       }
00396       num++;
00397 
00398       if (r==0) {
00399          if (ul.insert_urecord(_d, _a, &r) < 0) {
00400             rerrno = R_UL_NEW_R;
00401             LM_ERR("failed to insert new record structure\n");
00402             goto error;
00403          }
00404       }
00405 
00406       /* pack the contact_info */
00407       if ( (ci=pack_ci( (ci==0)?_m:0, _c, expires, flags))==0 ) {
00408          LM_ERR("failed to extract contact info\n");
00409          goto error;
00410       }
00411 
00412       if ( r->contacts==0 ||
00413       ul.get_ucontact(r, &_c->uri, ci->callid, ci->cseq+1, &c)!=0 ) {
00414          if (ul.insert_ucontact( r, &_c->uri, ci, &c) < 0) {
00415             rerrno = R_UL_INS_C;
00416             LM_ERR("failed to insert contact\n");
00417             goto error;
00418          }
00419       } else {
00420          if (ul.update_ucontact( r, c, ci) < 0) {
00421             rerrno = R_UL_UPD_C;
00422             LM_ERR("failed to update contact\n");
00423             goto error;
00424          }
00425       }
00426 #ifdef USE_TCP
00427       if (tcp_check) {
00428          /* parse contact uri to see if transport is TCP */
00429          if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) {
00430             LM_ERR("failed to parse contact <%.*s>\n", 
00431                   _c->uri.len, _c->uri.s);
00432          } else if (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS) {
00433             if (e_max) {
00434                LM_WARN("multiple TCP contacts on single REGISTER\n");
00435                if (expires>e_max) e_max = expires;
00436             } else {
00437                e_max = expires;
00438             }
00439          }
00440       }
00441 #endif
00442    }
00443 
00444    if (r) {
00445       if (r->contacts)
00446          build_contact(r->contacts);
00447       ul.release_urecord(r);
00448    }
00449 
00450 #ifdef USE_TCP
00451    if ( tcp_check && e_max>0 ) {
00452       e_max -= act_time;
00453       force_tcp_conn_lifetime( &_m->rcv , e_max + 10 );
00454    }
00455 #endif
00456 
00457    return 0;
00458 error:
00459    if (r)
00460       ul.delete_urecord(_d, _a, r);
00461    return -1;
00462 }
00463 
00464 
00465 static int test_max_contacts(struct sip_msg* _m, urecord_t* _r, contact_t* _c,
00466                                           ucontact_info_t *ci)
00467 {
00468    int num;
00469    int e;
00470    ucontact_t* ptr, *cont;
00471    int ret;
00472    
00473    num = 0;
00474    ptr = _r->contacts;
00475    while(ptr) {
00476       if (VALID_CONTACT(ptr, act_time)) {
00477          num++;
00478       }
00479       ptr = ptr->next;
00480    }
00481    LM_DBG("%d valid contacts\n", num);
00482    
00483    for( ; _c ; _c = get_next_contact(_c) ) {
00484       /* calculate expires */
00485       calc_contact_expires(_m, _c->expires, &e);
00486       
00487       ret = ul.get_ucontact( _r, &_c->uri, ci->callid, ci->cseq, &cont);
00488       if (ret==-1) {
00489          LM_ERR("invalid cseq for aor <%.*s>\n",_r->aor.len,_r->aor.s);
00490          rerrno = R_INV_CSEQ;
00491          return -1;
00492       } else if (ret==-2) {
00493          continue;
00494       }
00495       if (ret > 0) {
00496          /* Contact not found */
00497          if (e != 0) num++;
00498       } else {
00499          if (e == 0) num--;
00500       }
00501    }
00502    
00503    LM_DBG("%d contacts after commit\n", num);
00504    if (num > max_contacts) {
00505       LM_INFO("too many contacts for AOR <%.*s>\n", _r->aor.len, _r->aor.s);
00506       rerrno = R_TOO_MANY;
00507       return -1;
00508    }
00509 
00510    return 0;
00511 }
00512 
00513 
00514 /*! \brief
00515  * Message contained some contacts and appropriate
00516  * record was found, so we have to walk through
00517  * all contacts and do the following:
00518  * 1) If contact in usrloc doesn't exists and
00519  *    expires > 0, insert new contact
00520  * 2) If contact in usrloc exists and expires
00521  *    > 0, update the contact
00522  * 3) If contact in usrloc exists and expires
00523  *    == 0, delete contact
00524  */
00525 static inline int update_contacts(struct sip_msg* _m, urecord_t* _r,
00526                               contact_t* _c, int _mode)
00527 {
00528    ucontact_info_t *ci;
00529    ucontact_t *c, *ptr, *ptr0;
00530    int expires, ret, updated;
00531    unsigned int flags;
00532 #ifdef USE_TCP
00533    int e_max, tcp_check;
00534    struct sip_uri uri;
00535 #endif
00536 
00537    /* mem flag */
00538    flags = mem_only;
00539 
00540    /* pack the contact_info */
00541    if ( (ci=pack_ci( _m, 0, 0, flags))==0 ) {
00542       LM_ERR("failed to initial pack contact info\n");
00543       goto error;
00544    }
00545 
00546    if (max_contacts && test_max_contacts(_m, _r, _c, ci) != 0 )
00547       goto error;
00548 
00549 #ifdef USE_TCP
00550    if ( (_m->flags&tcp_persistent_flag) &&
00551    (_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS)) {
00552       e_max = -1;
00553       tcp_check = 1;
00554    } else {
00555       e_max = tcp_check = 0;
00556    }
00557 #endif
00558 
00559    updated=0;
00560    for( ; _c ; _c = get_next_contact(_c) ) {
00561       /* calculate expires */
00562       calc_contact_expires(_m, _c->expires, &expires);
00563 
00564       /* search for the contact*/
00565       ret = ul.get_ucontact( _r, &_c->uri, ci->callid, ci->cseq, &c);
00566       if (ret==-1) {
00567          LM_ERR("invalid cseq for aor <%.*s>\n",_r->aor.len,_r->aor.s);
00568          rerrno = R_INV_CSEQ;
00569          goto error;
00570       } else if (ret==-2) {
00571          if(expires!=0 && _mode)
00572             break;
00573          continue;
00574       }
00575 
00576       if ( ret > 0 ) {
00577          /* Contact not found -> expired? */
00578          if (expires==0)
00579             continue;
00580 
00581          /* pack the contact_info */
00582          if ( (ci=pack_ci( 0, _c, expires, 0))==0 ) {
00583             LM_ERR("failed to extract contact info\n");
00584             goto error;
00585          }
00586 
00587          if (ul.insert_ucontact( _r, &_c->uri, ci, &c) < 0) {
00588             rerrno = R_UL_INS_C;
00589             LM_ERR("failed to insert contact\n");
00590             goto error;
00591          }
00592          if(_mode)
00593          {
00594             ptr=_r->contacts;
00595             while(ptr)
00596             {
00597                ptr0 = ptr;
00598                if(ptr!=c)
00599                   ul.delete_ucontact(_r, ptr);
00600                ptr=ptr0->next;
00601             }
00602             updated=1;
00603          }
00604       } else {
00605          /* Contact found */
00606          if (expires == 0) {
00607             /* it's expired */
00608             if (mem_only) {
00609                c->flags |= FL_MEM;
00610             } else {
00611                c->flags &= ~FL_MEM;
00612             }
00613 
00614             if (ul.delete_ucontact(_r, c) < 0) {
00615                rerrno = R_UL_DEL_C;
00616                LM_ERR("failed to delete contact\n");
00617                goto error;
00618             }
00619          } else {
00620             /* do update */
00621             /* pack the contact specific info */
00622             if ( (ci=pack_ci( 0, _c, expires, 0))==0 ) {
00623                LM_ERR("failed to pack contact specific info\n");
00624                goto error;
00625             }
00626 
00627             if(_mode)
00628             {
00629                ptr=_r->contacts;
00630                while(ptr)
00631                {
00632                   ptr0 = ptr;
00633                   if(ptr!=c)
00634                      ul.delete_ucontact(_r, ptr);
00635                   ptr=ptr0->next;
00636                }
00637                updated=1;
00638             }
00639             if (ul.update_ucontact(_r, c, ci) < 0) {
00640                rerrno = R_UL_UPD_C;
00641                LM_ERR("failed to update contact\n");
00642                goto error;
00643             }
00644          }
00645       }
00646 #ifdef USE_TCP
00647       if (tcp_check) {
00648          /* parse contact uri to see if transport is TCP */
00649          if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) {
00650             LM_ERR("failed to parse contact <%.*s>\n", 
00651                   _c->uri.len, _c->uri.s);
00652          } else if (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS) {
00653             if (e_max>0) {
00654                LM_WARN("multiple TCP contacts on single REGISTER\n");
00655             }
00656             if (expires>e_max) e_max = expires;
00657          }
00658       }
00659 #endif
00660       /* have one contact only -- break */
00661       if(updated)
00662          break;
00663    }
00664 
00665 #ifdef USE_TCP
00666    if ( tcp_check && e_max>-1 ) {
00667       if (e_max) e_max -= act_time;
00668       force_tcp_conn_lifetime( &_m->rcv , e_max + 10 );
00669    }
00670 #endif
00671 
00672    return 0;
00673 error:
00674    return -1;
00675 }
00676 
00677 
00678 /*! \brief
00679  * This function will process request that
00680  * contained some contact header fields
00681  */
00682 static inline int add_contacts(struct sip_msg* _m, contact_t* _c,
00683                         udomain_t* _d, str* _a, int _mode)
00684 {
00685    int res;
00686    urecord_t* r;
00687 
00688    ul.lock_udomain(_d, _a);
00689    res = ul.get_urecord(_d, _a, &r);
00690    if (res < 0) {
00691       rerrno = R_UL_GET_R;
00692       LM_ERR("failed to retrieve record from usrloc\n");
00693       ul.unlock_udomain(_d, _a);
00694       return -2;
00695    }
00696 
00697    if (res == 0) { /* Contacts found */
00698       if (update_contacts(_m, r, _c, _mode) < 0) {
00699          build_contact(r->contacts);
00700          ul.release_urecord(r);
00701          ul.unlock_udomain(_d, _a);
00702          return -3;
00703       }
00704       build_contact(r->contacts);
00705       ul.release_urecord(r);
00706    } else {
00707       if (insert_contacts(_m, _c, _d, _a) < 0) {
00708          ul.unlock_udomain(_d, _a);
00709          return -4;
00710       }
00711    }
00712    ul.unlock_udomain(_d, _a);
00713    return 0;
00714 }
00715 
00716 
00717 /*!\brief
00718  * Process REGISTER request and save it's contacts
00719  */
00720 #define is_cflag_set(_name) (((unsigned int)(unsigned long)_cflags)&(_name))
00721 int save(struct sip_msg* _m, char* _d, char* _cflags)
00722 {
00723    contact_t* c;
00724    int st, mode;
00725    str aor;
00726 
00727    rerrno = R_FINE;
00728 
00729    if (parse_message(_m) < 0) {
00730       goto error;
00731    }
00732 
00733    if (check_contacts(_m, &st) > 0) {
00734       goto error;
00735    }
00736    
00737    get_act_time();
00738    c = get_first_contact(_m);
00739 
00740    if (extract_aor(&get_to(_m)->uri, &aor) < 0) {
00741       LM_ERR("failed to extract Address Of Record\n");
00742       goto error;
00743    }
00744 
00745    mem_only = is_cflag_set(REG_SAVE_MEM_FL)?FL_MEM:FL_NONE;
00746 
00747    if (c == 0) {
00748       if (st) {
00749          if (star((udomain_t*)_d, &aor) < 0) goto error;
00750       } else {
00751          if (no_contacts((udomain_t*)_d, &aor) < 0) goto error;
00752       }
00753    } else {
00754       mode = is_cflag_set(REG_SAVE_REPL_FL)?1:0;
00755       if (add_contacts(_m, c, (udomain_t*)_d, &aor, mode) < 0) goto error;
00756    }
00757 
00758    update_stat(accepted_registrations, 1);
00759    /* Only send reply upon request, not upon reply */
00760    if ((route_type == REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) && (send_reply(_m) < 0))
00761       return -1;
00762 
00763    return 1;
00764 error:
00765    update_stat(rejected_registrations, 1);
00766 
00767    if ((route_type == REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) )
00768       send_reply(_m);
00769 
00770    return 0;
00771 }
00772 
00773 int unregister(struct sip_msg* _m, char* _d, char* _uri)
00774 {
00775    str aor = {0, 0};
00776    str uri = {0, 0};
00777 
00778    if(fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0)
00779    {
00780       LM_ERR("invalid uri parameter\n");
00781       return -1;
00782    }
00783 
00784    if (extract_aor(&uri, &aor) < 0) {
00785       LM_ERR("failed to extract Address Of Record\n");
00786       return -1;
00787    }
00788 
00789    if (star((udomain_t*)_d, &aor) < 0)
00790    {
00791       LM_ERR("error unregistering user [%.*s]\n", aor.len, aor.s);
00792       return -1;
00793    }
00794    return 1;
00795 }
00796 

Generated on Thu May 24 12:00:30 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6