ucontact.c

Go to the documentation of this file.
00001 /*
00002  * $Id: ucontact.c 5272 2008-11-27 12:32:26Z henningw $ 
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History:
00023  * ---------
00024  * 2003-03-12 added replication mark and three zombie states (nils)
00025  * 2004-03-17 generic callbacks added (bogdan)
00026  * 2004-06-07 updated to the new DB api (andrei)
00027  */
00028 
00029 /*! \file
00030  *  \brief USRLOC - Usrloc contact handling functions
00031  *  \ingroup usrloc
00032  *
00033  * - Module: \ref usrloc
00034  */
00035 
00036 #include "ucontact.h"
00037 #include <string.h>             /* memcpy */
00038 #include "../../mem/shm_mem.h"
00039 #include "../../ut.h"
00040 #include "../../ip_addr.h"
00041 #include "../../socket_info.h"
00042 #include "../../dprint.h"
00043 #include "../../db/db.h"
00044 #include "ul_mod.h"
00045 #include "ul_callback.h"
00046 #include "urecord.h"
00047 #include "ucontact.h"
00048 
00049 
00050 /*!
00051  * \brief Create a new contact structure
00052  * \param _dom domain
00053  * \param _aor address of record
00054  * \param _contact contact string
00055  * \param _ci contact informations
00056  * \return new created contact on success, 0 on failure
00057  */
00058 ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _ci)
00059 {
00060    ucontact_t *c;
00061 
00062    c = (ucontact_t*)shm_malloc(sizeof(ucontact_t));
00063    if (!c) {
00064       LM_ERR("no more shm memory\n");
00065       return 0;
00066    }
00067    memset(c, 0, sizeof(ucontact_t));
00068 
00069    if (shm_str_dup( &c->c, _contact) < 0) goto error;
00070    if (shm_str_dup( &c->callid, _ci->callid) < 0) goto error;
00071    if (shm_str_dup( &c->user_agent, _ci->user_agent) < 0) goto error;
00072 
00073    if (_ci->received.s && _ci->received.len) {
00074       if (shm_str_dup( &c->received, &_ci->received) < 0) goto error;
00075    }
00076    if (_ci->path && _ci->path->len) {
00077       if (shm_str_dup( &c->path, _ci->path) < 0) goto error;
00078    }
00079 
00080    c->domain = _dom;
00081    c->aor = _aor;
00082    c->expires = _ci->expires;
00083    c->q = _ci->q;
00084    c->sock = _ci->sock;
00085    c->cseq = _ci->cseq;
00086    c->state = CS_NEW;
00087    c->flags = _ci->flags;
00088    c->cflags = _ci->cflags;
00089    c->methods = _ci->methods;
00090    c->last_modified = _ci->last_modified;
00091 
00092    return c;
00093 error:
00094    LM_ERR("no more shm memory\n");
00095    if (c->path.s) shm_free(c->path.s);
00096    if (c->received.s) shm_free(c->received.s);
00097    if (c->user_agent.s) shm_free(c->user_agent.s);
00098    if (c->callid.s) shm_free(c->callid.s);
00099    if (c->c.s) shm_free(c->c.s);
00100    shm_free(c);
00101    return 0;
00102 }
00103 
00104 
00105 
00106 /*!
00107  * \brief Free all memory associated with given contact structure
00108  * \param _c freed contact
00109  */
00110 void free_ucontact(ucontact_t* _c)
00111 {
00112    if (!_c) return;
00113    if (_c->path.s) shm_free(_c->path.s);
00114    if (_c->received.s) shm_free(_c->received.s);
00115    if (_c->user_agent.s) shm_free(_c->user_agent.s);
00116    if (_c->callid.s) shm_free(_c->callid.s);
00117    if (_c->c.s) shm_free(_c->c.s);
00118    shm_free( _c );
00119 }
00120 
00121 
00122 /*!
00123  * \brief Print contact, for debugging purposes only
00124  * \param _f output file
00125  * \param _c printed contact
00126  */
00127 void print_ucontact(FILE* _f, ucontact_t* _c)
00128 {
00129    time_t t = time(0);
00130    char* st;
00131 
00132    switch(_c->state) {
00133    case CS_NEW:   st = "CS_NEW";     break;
00134    case CS_SYNC:  st = "CS_SYNC";    break;
00135    case CS_DIRTY: st = "CS_DIRTY";   break;
00136    default:       st = "CS_UNKNOWN"; break;
00137    }
00138 
00139    fprintf(_f, "~~~Contact(%p)~~~\n", _c);
00140    fprintf(_f, "domain    : '%.*s'\n", _c->domain->len, ZSW(_c->domain->s));
00141    fprintf(_f, "aor       : '%.*s'\n", _c->aor->len, ZSW(_c->aor->s));
00142    fprintf(_f, "Contact   : '%.*s'\n", _c->c.len, ZSW(_c->c.s));
00143    fprintf(_f, "Expires   : ");
00144    if (_c->expires == 0) {
00145       fprintf(_f, "Permanent\n");
00146    } else if (_c->expires == UL_EXPIRED_TIME) {
00147       fprintf(_f, "Deleted\n");
00148    } else if (t > _c->expires) {
00149       fprintf(_f, "Expired\n");
00150    } else {
00151       fprintf(_f, "%u\n", (unsigned int)(_c->expires - t));
00152    }
00153    fprintf(_f, "q         : %s\n", q2str(_c->q, 0));
00154    fprintf(_f, "Call-ID   : '%.*s'\n", _c->callid.len, ZSW(_c->callid.s));
00155    fprintf(_f, "CSeq      : %d\n", _c->cseq);
00156    fprintf(_f, "User-Agent: '%.*s'\n",
00157       _c->user_agent.len, ZSW(_c->user_agent.s));
00158    fprintf(_f, "received  : '%.*s'\n",
00159       _c->received.len, ZSW(_c->received.s));
00160    fprintf(_f, "Path      : '%.*s'\n",
00161       _c->path.len, ZSW(_c->path.s));
00162    fprintf(_f, "State     : %s\n", st);
00163    fprintf(_f, "Flags     : %u\n", _c->flags);
00164    if (_c->sock) {
00165       fprintf(_f, "Sock      : %.*s (%p)\n",
00166             _c->sock->sock_str.len,_c->sock->sock_str.s,_c->sock);
00167    } else {
00168       fprintf(_f, "Sock      : none (null)\n");
00169    }
00170    fprintf(_f, "Methods   : %u\n", _c->methods);
00171    fprintf(_f, "next      : %p\n", _c->next);
00172    fprintf(_f, "prev      : %p\n", _c->prev);
00173    fprintf(_f, "~~~/Contact~~~~\n");
00174 }
00175 
00176 
00177 /*!
00178  * \brief Update existing contact in memory with new values
00179  * \param _c contact
00180  * \param _ci contact informations
00181  * \return 0 on success, -1 on failure
00182  */
00183 int mem_update_ucontact(ucontact_t* _c, ucontact_info_t* _ci)
00184 {
00185 #define update_str(_old,_new) \
00186    do{\
00187       if ((_old)->len < (_new)->len) { \
00188          ptr = (char*)shm_malloc((_new)->len); \
00189          if (ptr == 0) { \
00190             LM_ERR("no more shm memory\n"); \
00191             return -1; \
00192          }\
00193          memcpy(ptr, (_new)->s, (_new)->len);\
00194          if ((_old)->s) shm_free((_old)->s);\
00195          (_old)->s = ptr;\
00196       } else {\
00197          memcpy((_old)->s, (_new)->s, (_new)->len);\
00198       }\
00199       (_old)->len = (_new)->len;\
00200    } while(0)
00201 
00202    char* ptr;
00203 
00204    /* No need to update Callid as it is constant 
00205     * per ucontact (set at insert time)  -bogdan */
00206 
00207    update_str( &_c->user_agent, _ci->user_agent);
00208 
00209    if (_ci->received.s && _ci->received.len) {
00210       update_str( &_c->received, &_ci->received);
00211    } else {
00212       if (_c->received.s) shm_free(_c->received.s);
00213       _c->received.s = 0;
00214       _c->received.len = 0;
00215    }
00216    
00217    if (_ci->path) {
00218       update_str( &_c->path, _ci->path);
00219    } else {
00220       if (_c->path.s) shm_free(_c->path.s);
00221       _c->path.s = 0;
00222       _c->path.len = 0;
00223    }
00224 
00225    _c->sock = _ci->sock;
00226    _c->expires = _ci->expires;
00227    _c->q = _ci->q;
00228    _c->cseq = _ci->cseq;
00229    _c->methods = _ci->methods;
00230    _c->last_modified = _ci->last_modified;
00231    _c->flags = _ci->flags;
00232    _c->cflags = _ci->cflags;
00233 
00234    return 0;
00235 }
00236 
00237 
00238 /* ================ State related functions =============== */
00239 
00240 /*!
00241  * \brief Update state of the contact if we are using write-back scheme
00242  * \param _c updated contact
00243  */
00244 void st_update_ucontact(ucontact_t* _c)
00245 {
00246    switch(_c->state) {
00247    case CS_NEW:
00248           /* Contact is new and is not in the database yet,
00249            * we remain in the same state here because the
00250            * contact must be inserted later in the timer
00251            */
00252       break;
00253 
00254    case CS_SYNC:
00255           /* For db mode 1 & 2 a modified contact needs to be 
00256            * updated also in the database, so transit into 
00257            * CS_DIRTY and let the timer to do the update 
00258            * again. For db mode 1 we try to update right
00259            * now and if fails, let the timer to do the job
00260            */
00261       if (db_mode == WRITE_BACK || db_mode == WRITE_THROUGH) {
00262          _c->state = CS_DIRTY;
00263       }
00264       break;
00265 
00266    case CS_DIRTY:
00267           /* Modification of dirty contact results in
00268            * dirty contact again, don't change anything
00269            */
00270       break;
00271    }
00272 }
00273 
00274 
00275 /*!
00276  * \brief Update state of the contact
00277  * \param _c updated contact
00278  * \return 1 if the contact should be deleted from memory immediately, 0 otherwise
00279  */
00280 int st_delete_ucontact(ucontact_t* _c)
00281 {
00282    switch(_c->state) {
00283    case CS_NEW:
00284            /* Contact is new and isn't in the database
00285             * yet, we can delete it from the memory
00286             * safely.
00287             */
00288       return 1;
00289 
00290    case CS_SYNC:
00291    case CS_DIRTY:
00292            /* Contact is in the database,
00293             * we cannot remove it from the memory 
00294             * directly, but we can set expires to zero
00295             * and the timer will take care of deleting 
00296             * the contact from the memory as well as 
00297             * from the database
00298             */
00299       if (db_mode == WRITE_BACK) {
00300          _c->expires = UL_EXPIRED_TIME;
00301          return 0;
00302       } else {
00303               /* WRITE_THROUGH or NO_DB -- we can
00304                * remove it from memory immediately and
00305                * the calling function would also remove
00306                * it from the database if needed
00307                */
00308          return 1;
00309       }
00310    }
00311 
00312    return 0; /* Makes gcc happy */
00313 }
00314 
00315 
00316 /*!
00317  * \brief Called when the timer is about to delete an expired contact
00318  * \param _c expired contact
00319  * \return 1 if the contact should be removed from the database and 0 otherwise
00320  */
00321 int st_expired_ucontact(ucontact_t* _c)
00322 {
00323         /* There is no need to change contact
00324          * state, because the contact will
00325          * be deleted anyway
00326          */
00327 
00328    switch(_c->state) {
00329    case CS_NEW:
00330            /* Contact is not in the database
00331             * yet, remove it from memory only
00332             */
00333       return 0;
00334 
00335    case CS_SYNC:
00336    case CS_DIRTY:
00337            /* Remove from database here */
00338       return 1;
00339    }
00340 
00341    return 0; /* Makes gcc happy */
00342 }
00343 
00344 
00345 /*!
00346  * \brief Called when the timer is about flushing the contact, updates contact state
00347  * \param _c flushed contact
00348  * \return 1 if the contact should be inserted, 2 if update and 0 otherwise
00349  */
00350 int st_flush_ucontact(ucontact_t* _c)
00351 {
00352    switch(_c->state) {
00353    case CS_NEW:
00354            /* Contact is new and is not in
00355             * the database yet so we have
00356             * to insert it
00357             */
00358       _c->state = CS_SYNC;
00359       return 1;
00360 
00361    case CS_SYNC:
00362            /* Contact is synchronized, do
00363             * nothing
00364             */
00365       return 0;
00366 
00367    case CS_DIRTY:
00368            /* Contact has been modified and
00369             * is in the db already so we
00370             * have to update it
00371             */
00372       _c->state = CS_SYNC;
00373       return 2;
00374    }
00375 
00376    return 0; /* Makes gcc happy */
00377 }
00378 
00379 
00380 /* ============== Database related functions ================ */
00381 
00382 /*!
00383  * \brief Insert contact into the database
00384  * \param _c inserted contact
00385  * \return 0 on success, -1 on failure
00386  */
00387 int db_insert_ucontact(ucontact_t* _c)
00388 {
00389    char* dom;
00390    db_key_t keys[15];
00391    db_val_t vals[15];
00392    
00393    if (_c->flags & FL_MEM) {
00394       return 0;
00395    }
00396 
00397    keys[0] = &user_col;
00398    keys[1] = &contact_col;
00399    keys[2] = &expires_col;
00400    keys[3] = &q_col;
00401    keys[4] = &callid_col;
00402    keys[5] = &cseq_col;
00403    keys[6] = &flags_col;
00404    keys[7] = &cflags_col;
00405    keys[8] = &user_agent_col;
00406    keys[9] = &received_col;
00407    keys[10] = &path_col;
00408    keys[11] = &sock_col;
00409    keys[12] = &methods_col;
00410    keys[13] = &last_mod_col;
00411    keys[14] = &domain_col;
00412 
00413    vals[0].type = DB_STR;
00414    vals[0].nul = 0;
00415    vals[0].val.str_val.s = _c->aor->s;
00416    vals[0].val.str_val.len = _c->aor->len;
00417 
00418    vals[1].type = DB_STR;
00419    vals[1].nul = 0;
00420    vals[1].val.str_val.s = _c->c.s; 
00421    vals[1].val.str_val.len = _c->c.len;
00422 
00423    vals[2].type = DB_DATETIME;
00424    vals[2].nul = 0;
00425    vals[2].val.time_val = _c->expires;
00426 
00427    vals[3].type = DB_DOUBLE;
00428    vals[3].nul = 0;
00429    vals[3].val.double_val = q2double(_c->q);
00430 
00431    vals[4].type = DB_STR;
00432    vals[4].nul = 0;
00433    vals[4].val.str_val.s = _c->callid.s;
00434    vals[4].val.str_val.len = _c->callid.len;
00435 
00436    vals[5].type = DB_INT;
00437    vals[5].nul = 0;
00438    vals[5].val.int_val = _c->cseq;
00439 
00440    vals[6].type = DB_INT;
00441    vals[6].nul = 0;
00442    vals[6].val.bitmap_val = _c->flags;
00443 
00444    vals[7].type = DB_INT;
00445    vals[7].nul = 0;
00446    vals[7].val.bitmap_val = _c->cflags;
00447 
00448    vals[8].type = DB_STR;
00449    vals[8].nul = 0;
00450    vals[8].val.str_val.s = _c->user_agent.s;
00451    vals[8].val.str_val.len = _c->user_agent.len;
00452 
00453    vals[9].type = DB_STR;
00454    if (_c->received.s == 0) {
00455       vals[9].nul = 1;
00456    } else {
00457       vals[9].nul = 0;
00458       vals[9].val.str_val.s = _c->received.s;
00459       vals[9].val.str_val.len = _c->received.len;
00460    }
00461    
00462    vals[10].type = DB_STR;
00463    if (_c->path.s == 0) {
00464       vals[10].nul = 1;
00465    } else {
00466       vals[10].nul = 0;
00467       vals[10].val.str_val.s = _c->path.s;
00468       vals[10].val.str_val.len = _c->path.len;
00469    }
00470 
00471    vals[11].type = DB_STR;
00472    if (_c->sock) {
00473       vals[11].val.str_val = _c->sock->sock_str;
00474       vals[11].nul = 0;
00475    } else {
00476       vals[11].nul = 1;
00477    }
00478 
00479    vals[12].type = DB_BITMAP;
00480    if (_c->methods == 0xFFFFFFFF) {
00481       vals[12].nul = 1;
00482    } else {
00483       vals[12].val.bitmap_val = _c->methods;
00484       vals[12].nul = 0;
00485    }
00486 
00487    vals[13].type = DB_DATETIME;
00488    vals[13].nul = 0;
00489    vals[13].val.time_val = _c->last_modified;
00490 
00491    if (use_domain) {
00492       vals[14].type = DB_STR;
00493       vals[14].nul = 0;
00494 
00495       dom = memchr(_c->aor->s, '@', _c->aor->len);
00496       if (dom==0) {
00497          vals[0].val.str_val.len = 0;
00498          vals[14].val.str_val = *_c->aor;
00499       } else {
00500          vals[0].val.str_val.len = dom - _c->aor->s;
00501          vals[14].val.str_val.s = dom + 1;
00502          vals[14].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1;
00503       }
00504    }
00505    
00506    if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
00507       LM_ERR("sql use_table failed\n");
00508       return -1;
00509    }
00510 
00511    if (ul_dbf.insert(ul_dbh, keys, vals, (use_domain) ? (15) : (14)) < 0) {
00512       LM_ERR("inserting contact in db failed\n");
00513       return -1;
00514    }
00515 
00516    return 0;
00517 }
00518 
00519 
00520 /*!
00521  * \brief Update contact in the database
00522  * \param _c updated contact
00523  * \return 0 on success, -1 on failure
00524  */
00525 int db_update_ucontact(ucontact_t* _c)
00526 {
00527    char* dom;
00528    db_key_t keys1[4];
00529    db_val_t vals1[4];
00530 
00531    db_key_t keys2[11];
00532    db_val_t vals2[11];
00533 
00534    if (_c->flags & FL_MEM) {
00535       return 0;
00536    }
00537 
00538    keys1[0] = &user_col;
00539    keys1[1] = &contact_col;
00540    keys1[2] = &callid_col;
00541    keys1[3] = &domain_col;
00542    keys2[0] = &expires_col;
00543    keys2[1] = &q_col;
00544    keys2[2] = &cseq_col;
00545    keys2[3] = &flags_col;
00546    keys2[4] = &cflags_col;
00547    keys2[5] = &user_agent_col;
00548    keys2[6] = &received_col;
00549    keys2[7] = &path_col;
00550    keys2[8] = &sock_col;
00551    keys2[9] = &methods_col;
00552    keys2[10] = &last_mod_col;
00553 
00554    vals1[0].type = DB_STR;
00555    vals1[0].nul = 0;
00556    vals1[0].val.str_val = *_c->aor;
00557 
00558    vals1[1].type = DB_STR;
00559    vals1[1].nul = 0;
00560    vals1[1].val.str_val = _c->c;
00561 
00562    vals1[2].type = DB_STR;
00563    vals1[2].nul = 0;
00564    vals1[2].val.str_val = _c->callid;
00565 
00566    vals2[0].type = DB_DATETIME;
00567    vals2[0].nul = 0;
00568    vals2[0].val.time_val = _c->expires;
00569 
00570    vals2[1].type = DB_DOUBLE;
00571    vals2[1].nul = 0;
00572    vals2[1].val.double_val = q2double(_c->q);
00573 
00574    vals2[2].type = DB_INT;
00575    vals2[2].nul = 0;
00576    vals2[2].val.int_val = _c->cseq;
00577 
00578    vals2[3].type = DB_INT;
00579    vals2[3].nul = 0;
00580    vals2[3].val.bitmap_val = _c->flags;
00581 
00582    vals2[4].type = DB_INT;
00583    vals2[4].nul = 0;
00584    vals2[4].val.bitmap_val = _c->cflags;
00585 
00586    vals2[5].type = DB_STR;
00587    vals2[5].nul = 0;
00588    vals2[5].val.str_val = _c->user_agent;
00589 
00590    vals2[6].type = DB_STR;
00591    if (_c->received.s == 0) {
00592       vals2[6].nul = 1;
00593    } else {
00594       vals2[6].nul = 0;
00595       vals2[6].val.str_val = _c->received;
00596    }
00597    
00598    vals2[7].type = DB_STR;
00599    if (_c->path.s == 0) {
00600       vals2[7].nul = 1;
00601    } else {
00602       vals2[7].nul = 0;
00603       vals2[7].val.str_val = _c->path;
00604    }
00605 
00606    vals2[8].type = DB_STR;
00607    if (_c->sock) {
00608       vals2[8].val.str_val = _c->sock->sock_str;
00609       vals2[8].nul = 0;
00610    } else {
00611       vals2[8].nul = 1;
00612    }
00613 
00614    vals2[9].type = DB_BITMAP;
00615    if (_c->methods == 0xFFFFFFFF) {
00616       vals2[9].nul = 1;
00617    } else {
00618       vals2[9].val.bitmap_val = _c->methods;
00619       vals2[9].nul = 0;
00620    }
00621 
00622    vals2[10].type = DB_DATETIME;
00623    vals2[10].nul = 0;
00624    vals2[10].val.time_val = _c->last_modified;
00625 
00626    if (use_domain) {
00627       vals1[3].type = DB_STR;
00628       vals1[3].nul = 0;
00629       dom = memchr(_c->aor->s, '@', _c->aor->len);
00630       if (dom==0) {
00631          vals1[0].val.str_val.len = 0;
00632          vals1[3].val.str_val = *_c->aor;
00633       } else {
00634          vals1[0].val.str_val.len = dom - _c->aor->s;
00635          vals1[3].val.str_val.s = dom + 1;
00636          vals1[3].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1;
00637       }
00638    }
00639 
00640    if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
00641       LM_ERR("sql use_table failed\n");
00642       return -1;
00643    }
00644 
00645    if (ul_dbf.update(ul_dbh, keys1, 0, vals1, keys2, vals2, 
00646    (use_domain) ? (4) : (3), 11) < 0) {
00647       LM_ERR("updating database failed\n");
00648       return -1;
00649    }
00650 
00651    return 0;
00652 }
00653 
00654 
00655 /*!
00656  * \brief Delete contact from the database
00657  * \param _c deleted contact
00658  * \return 0 on success, -1 on failure
00659  */
00660 int db_delete_ucontact(ucontact_t* _c)
00661 {
00662    char* dom;
00663    db_key_t keys[4];
00664    db_val_t vals[4];
00665 
00666    if (_c->flags & FL_MEM) {
00667       return 0;
00668    }
00669 
00670    keys[0] = &user_col;
00671    keys[1] = &contact_col;
00672    keys[2] = &callid_col;
00673    keys[3] = &domain_col;
00674 
00675    vals[0].type = DB_STR;
00676    vals[0].nul = 0;
00677    vals[0].val.str_val = *_c->aor;
00678 
00679    vals[1].type = DB_STR;
00680    vals[1].nul = 0;
00681    vals[1].val.str_val = _c->c;
00682 
00683    vals[2].type = DB_STR;
00684    vals[2].nul = 0;
00685    vals[2].val.str_val = _c->callid;
00686 
00687    if (use_domain) {
00688       vals[3].type = DB_STR;
00689       vals[3].nul = 0;
00690       dom = memchr(_c->aor->s, '@', _c->aor->len);
00691       if (dom==0) {
00692          vals[0].val.str_val.len = 0;
00693          vals[3].val.str_val = *_c->aor;
00694       } else {
00695          vals[0].val.str_val.len = dom - _c->aor->s;
00696          vals[3].val.str_val.s = dom + 1;
00697          vals[3].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1;
00698       }
00699    }
00700 
00701    if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
00702       LM_ERR("sql use_table failed\n");
00703       return -1;
00704    }
00705 
00706    if (ul_dbf.delete(ul_dbh, keys, 0, vals, (use_domain) ? (4) : (3)) < 0) {
00707       LM_ERR("deleting from database failed\n");
00708       return -1;
00709    }
00710 
00711    return 0;
00712 }
00713 
00714 
00715 /*!
00716  * \brief Remove a contact from list belonging to a certain record
00717  * \param _r record the contact belongs
00718  * \param _c removed contact
00719  */
00720 static inline void unlink_contact(struct urecord* _r, ucontact_t* _c)
00721 {
00722    if (_c->prev) {
00723       _c->prev->next = _c->next;
00724       if (_c->next) {
00725          _c->next->prev = _c->prev;
00726       }
00727    } else {
00728       _r->contacts = _c->next;
00729       if (_c->next) {
00730          _c->next->prev = 0;
00731       }
00732    }
00733 }
00734 
00735 
00736 /*!
00737  * \brief Insert a new contact into the list at the correct position
00738  * \param _r record that holds the sorted contacts
00739  * \param _c new contact
00740  */
00741 static inline void update_contact_pos(struct urecord* _r, ucontact_t* _c)
00742 {
00743    ucontact_t *pos, *ppos;
00744 
00745    if (desc_time_order) {
00746       /* order by time - first the newest */
00747       if (_c->prev==0)
00748          return;
00749       unlink_contact(_r, _c);
00750       /* insert it at the beginning */
00751       _c->next = _r->contacts;
00752       _c->prev = 0;
00753       _r->contacts->prev = _c;
00754       _r->contacts = _c;
00755    } else {
00756       /* order by q - first the smaller q */
00757       if ( (_c->prev==0 || _c->q<=_c->prev->q)
00758       && (_c->next==0 || _c->q>=_c->next->q)  )
00759          return;
00760       /* need to move , but where? */
00761       unlink_contact(_r, _c);
00762       _c->next = _c->prev = 0;
00763       for(pos=_r->contacts,ppos=0;pos&&pos->q<_c->q;ppos=pos,pos=pos->next);
00764       if (pos) {
00765          if (!pos->prev) {
00766             pos->prev = _c;
00767             _c->next = pos;
00768             _r->contacts = _c;
00769          } else {
00770             _c->next = pos;
00771             _c->prev = pos->prev;
00772             pos->prev->next = _c;
00773             pos->prev = _c;
00774          }
00775       } else if (ppos) {
00776          ppos->next = _c;
00777          _c->prev = ppos;
00778       } else {
00779          _r->contacts = _c;
00780       }
00781    }
00782 }
00783 
00784 
00785 /*!
00786  * \brief Update ucontact with new values
00787  * \param _r record the contact belongs to
00788  * \param _c updated contact
00789  * \param _ci new contact informations
00790  * \return 0 on success, -1 on failure
00791  */
00792 int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci)
00793 {
00794    /* we have to update memory in any case, but database directly
00795     * only in db_mode 1 */
00796    if (mem_update_ucontact( _c, _ci) < 0) {
00797       LM_ERR("failed to update memory\n");
00798       return -1;
00799    }
00800 
00801    /* run callbacks for UPDATE event */
00802    if (exists_ulcb_type(UL_CONTACT_UPDATE))
00803    {
00804       LM_DBG("exists callback for type= UL_CONTACT_UPDATE\n");
00805       run_ul_callbacks( UL_CONTACT_UPDATE, _c);
00806    }
00807 
00808    if (_r && db_mode!=DB_ONLY)
00809       update_contact_pos( _r, _c);
00810 
00811    st_update_ucontact(_c);
00812 
00813    if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
00814       if (db_update_ucontact(_c) < 0) {
00815          LM_ERR("failed to update database\n");
00816          return -1;
00817       } else {
00818          _c->state = CS_SYNC;
00819       }
00820    }
00821    return 0;
00822 }

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