123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704 |
- /*
- * $Id$
- *
- * Copyright (C) 2001-2003 FhG Fokus
- *
- * This file is part of Kamailio, a free SIP server.
- *
- * Kamailio 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
- *
- * Kamailio 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * History:
- * ---------
- * 2003-03-12 added replication mark and three zombie states (nils)
- * 2004-03-17 generic callbacks added (bogdan)
- * 2004-06-07 updated to the new DB api (andrei)
- */
- /*! \file
- * \brief USRLOC - Usrloc contact handling functions
- * \ingroup usrloc
- *
- * - Module: \ref usrloc
- */
- #include "ucontact.h"
- #include <string.h> /* memcpy */
- #include "../../mem/shm_mem.h"
- #include "../../ut.h"
- #include "../../ip_addr.h"
- #include "../../socket_info.h"
- #include "../../dprint.h"
- #include "../../lib/srdb1/db.h"
- #include "ul_mod.h"
- #include "ul_callback.h"
- #include "usrloc.h"
- #include "urecord.h"
- #include "ucontact.h"
- #include "usrloc.h"
- extern int ul_db_insert_null;
- static int ul_xavp_contact_clone = 1;
- void ul_set_xavp_contact_clone(int v)
- {
- ul_xavp_contact_clone = v;
- }
- #ifdef WITH_XAVP
- /*!
- * \brief Store xavp list per contact
- * \param _c contact structure
- */
- void ucontact_xavp_store(ucontact_t *_c)
- {
- sr_xavp_t *xavp;
- if(_c==NULL)
- return;
- if(ul_xavp_contact_clone == 0)
- return;
- if(ul_xavp_contact_name.s==NULL)
- return;
- /* remove old list if it is set -- update case */
- if (_c->xavp) xavp_destroy_list(&_c->xavp);
- xavp = xavp_get(&ul_xavp_contact_name, NULL);
- if(xavp==NULL)
- return;
- /* clone the xavp found in core */
- LM_DBG("trying to clone per contact xavps\n");
- _c->xavp = xavp_clone_level_nodata(xavp);
- return;
- }
- #endif
- /*!
- * \brief Create a new contact structure
- * \param _dom domain
- * \param _aor address of record
- * \param _contact contact string
- * \param _ci contact informations
- * \return new created contact on success, 0 on failure
- */
- ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _ci)
- {
- ucontact_t *c;
- if(unlikely(_ci->ruid.len<=0)) {
- LM_ERR("no ruid for aor: %.*s\n", _aor->len, ZSW(_aor->s));
- return 0;
- }
- c = (ucontact_t*)shm_malloc(sizeof(ucontact_t));
- if (!c) {
- LM_ERR("no more shm memory\n");
- return 0;
- }
- memset(c, 0, sizeof(ucontact_t));
- if (shm_str_dup( &c->c, _contact) < 0) goto error;
- if (shm_str_dup( &c->callid, _ci->callid) < 0) goto error;
- if (shm_str_dup( &c->user_agent, _ci->user_agent) < 0) goto error;
- if (_ci->received.s && _ci->received.len) {
- if (shm_str_dup( &c->received, &_ci->received) < 0) goto error;
- }
- if (_ci->path && _ci->path->len) {
- if (shm_str_dup( &c->path, _ci->path) < 0) goto error;
- }
- if (_ci->ruid.s && _ci->ruid.len) {
- if (shm_str_dup( &c->ruid, &_ci->ruid) < 0) goto error;
- }
- if (_ci->instance.s && _ci->instance.len) {
- if (shm_str_dup( &c->instance, &_ci->instance) < 0) goto error;
- }
- c->domain = _dom;
- c->aor = _aor;
- c->expires = _ci->expires;
- c->q = _ci->q;
- c->sock = _ci->sock;
- c->cseq = _ci->cseq;
- c->state = CS_NEW;
- c->flags = _ci->flags;
- c->cflags = _ci->cflags;
- c->methods = _ci->methods;
- c->reg_id = _ci->reg_id;
- c->last_modified = _ci->last_modified;
- c->last_keepalive = _ci->last_modified;
- c->tcpconn_id = _ci->tcpconn_id;
- #ifdef WITH_XAVP
- ucontact_xavp_store(c);
- #endif
- return c;
- error:
- LM_ERR("no more shm memory\n");
- if (c->path.s) shm_free(c->path.s);
- if (c->received.s) shm_free(c->received.s);
- if (c->user_agent.s) shm_free(c->user_agent.s);
- if (c->callid.s) shm_free(c->callid.s);
- if (c->c.s) shm_free(c->c.s);
- if (c->ruid.s) shm_free(c->ruid.s);
- if (c->instance.s) shm_free(c->instance.s);
- #ifdef WITH_XAVP
- if (c->xavp) xavp_destroy_list(&c->xavp);
- #endif
- shm_free(c);
- return 0;
- }
- /*!
- * \brief Free all memory associated with given contact structure
- * \param _c freed contact
- */
- void free_ucontact(ucontact_t* _c)
- {
- if (!_c) return;
- if (_c->path.s) shm_free(_c->path.s);
- if (_c->received.s) shm_free(_c->received.s);
- if (_c->user_agent.s) shm_free(_c->user_agent.s);
- if (_c->callid.s) shm_free(_c->callid.s);
- if (_c->c.s) shm_free(_c->c.s);
- if (_c->ruid.s) shm_free(_c->ruid.s);
- if (_c->instance.s) shm_free(_c->instance.s);
- #ifdef WITH_XAVP
- if (_c->xavp) xavp_destroy_list(&_c->xavp);
- #endif
- shm_free( _c );
- }
- /*!
- * \brief Print contact, for debugging purposes only
- * \param _f output file
- * \param _c printed contact
- */
- void print_ucontact(FILE* _f, ucontact_t* _c)
- {
- time_t t = time(0);
- char* st;
- switch(_c->state) {
- case CS_NEW: st = "CS_NEW"; break;
- case CS_SYNC: st = "CS_SYNC"; break;
- case CS_DIRTY: st = "CS_DIRTY"; break;
- default: st = "CS_UNKNOWN"; break;
- }
- fprintf(_f, "~~~Contact(%p)~~~\n", _c);
- fprintf(_f, "domain : '%.*s'\n", _c->domain->len, ZSW(_c->domain->s));
- fprintf(_f, "aor : '%.*s'\n", _c->aor->len, ZSW(_c->aor->s));
- fprintf(_f, "Contact : '%.*s'\n", _c->c.len, ZSW(_c->c.s));
- fprintf(_f, "Expires : ");
- if (_c->expires == 0) {
- fprintf(_f, "Permanent\n");
- } else if (_c->expires == UL_EXPIRED_TIME) {
- fprintf(_f, "Deleted\n");
- } else if (t > _c->expires) {
- fprintf(_f, "Expired\n");
- } else {
- fprintf(_f, "%u\n", (unsigned int)(_c->expires - t));
- }
- fprintf(_f, "q : %s\n", q2str(_c->q, 0));
- fprintf(_f, "Call-ID : '%.*s'\n", _c->callid.len, ZSW(_c->callid.s));
- fprintf(_f, "CSeq : %d\n", _c->cseq);
- fprintf(_f, "User-Agent: '%.*s'\n",
- _c->user_agent.len, ZSW(_c->user_agent.s));
- fprintf(_f, "received : '%.*s'\n",
- _c->received.len, ZSW(_c->received.s));
- fprintf(_f, "Path : '%.*s'\n",
- _c->path.len, ZSW(_c->path.s));
- fprintf(_f, "State : %s\n", st);
- fprintf(_f, "Flags : %u\n", _c->flags);
- if (_c->sock) {
- fprintf(_f, "Sock : %.*s (%p)\n",
- _c->sock->sock_str.len,_c->sock->sock_str.s,_c->sock);
- } else {
- fprintf(_f, "Sock : none (null)\n");
- }
- fprintf(_f, "Methods : %u\n", _c->methods);
- fprintf(_f, "ruid : '%.*s'\n",
- _c->ruid.len, ZSW(_c->ruid.s));
- fprintf(_f, "instance : '%.*s'\n",
- _c->instance.len, ZSW(_c->instance.s));
- fprintf(_f, "reg-id : %u\n", _c->reg_id);
- fprintf(_f, "next : %p\n", _c->next);
- fprintf(_f, "prev : %p\n", _c->prev);
- fprintf(_f, "~~~/Contact~~~~\n");
- }
- /*!
- * \brief Update existing contact in memory with new values
- * \param _c contact
- * \param _ci contact informations
- * \return 0 on success, -1 on failure
- */
- int mem_update_ucontact(ucontact_t* _c, ucontact_info_t* _ci)
- {
- #define update_str(_old,_new) \
- do{\
- if ((_old)->len < (_new)->len) { \
- ptr = (char*)shm_malloc((_new)->len); \
- if (ptr == 0) { \
- LM_ERR("no more shm memory\n"); \
- return -1; \
- }\
- memcpy(ptr, (_new)->s, (_new)->len);\
- if ((_old)->s) shm_free((_old)->s);\
- (_old)->s = ptr;\
- } else {\
- memcpy((_old)->s, (_new)->s, (_new)->len);\
- }\
- (_old)->len = (_new)->len;\
- } while(0)
- char* ptr;
- if(_ci->instance.s!=NULL && _ci->instance.len>0)
- {
- /* when we have instance set, update contact address */
- if(_ci->c!=NULL && _ci->c->s!=NULL && _ci->c->len>0)
- update_str( &_c->c, _ci->c);
- }
- /* refresh call-id */
- if(_ci->callid!=NULL && _ci->callid->s!=NULL && _ci->callid->len>0)
- update_str( &_c->callid, _ci->callid);
- update_str( &_c->user_agent, _ci->user_agent);
- if (_ci->received.s && _ci->received.len) {
- update_str( &_c->received, &_ci->received);
- } else {
- if (_c->received.s) shm_free(_c->received.s);
- _c->received.s = 0;
- _c->received.len = 0;
- }
-
- if (_ci->path) {
- update_str( &_c->path, _ci->path);
- } else {
- if (_c->path.s) shm_free(_c->path.s);
- _c->path.s = 0;
- _c->path.len = 0;
- }
- #ifdef WITH_XAVP
- ucontact_xavp_store(_c);
- #endif
- _c->sock = _ci->sock;
- _c->expires = _ci->expires;
- _c->q = _ci->q;
- _c->cseq = _ci->cseq;
- _c->methods = _ci->methods;
- _c->last_modified = _ci->last_modified;
- _c->last_keepalive = _ci->last_modified;
- _c->flags = _ci->flags;
- _c->cflags = _ci->cflags;
- _c->tcpconn_id = _ci->tcpconn_id;
- return 0;
- }
- /* ================ State related functions =============== */
- /*!
- * \brief Update state of the contact if we are using write-back scheme
- * \param _c updated contact
- */
- void st_update_ucontact(ucontact_t* _c)
- {
- switch(_c->state) {
- case CS_NEW:
- /* Contact is new and is not in the database yet,
- * we remain in the same state here because the
- * contact must be inserted later in the timer
- */
- break;
- case CS_SYNC:
- /* For db mode 1 & 2 a modified contact needs to be
- * updated also in the database, so transit into
- * CS_DIRTY and let the timer to do the update
- * again. For db mode 1 we try to update right
- * now and if fails, let the timer to do the job
- */
- if (db_mode == WRITE_BACK || db_mode == WRITE_THROUGH) {
- _c->state = CS_DIRTY;
- }
- break;
- case CS_DIRTY:
- /* Modification of dirty contact results in
- * dirty contact again, don't change anything
- */
- break;
- }
- }
- /*!
- * \brief Update state of the contact
- * \param _c updated contact
- * \return 1 if the contact should be deleted from memory immediately, 0 otherwise
- */
- int st_delete_ucontact(ucontact_t* _c)
- {
- switch(_c->state) {
- case CS_NEW:
- /* Contact is new and isn't in the database
- * yet, we can delete it from the memory
- * safely.
- */
- return 1;
- case CS_SYNC:
- case CS_DIRTY:
- /* Contact is in the database,
- * we cannot remove it from the memory
- * directly, but we can set expires to zero
- * and the timer will take care of deleting
- * the contact from the memory as well as
- * from the database
- */
- if (db_mode == WRITE_BACK) {
- _c->expires = UL_EXPIRED_TIME;
- return 0;
- } else {
- /* WRITE_THROUGH or NO_DB -- we can
- * remove it from memory immediately and
- * the calling function would also remove
- * it from the database if needed
- */
- return 1;
- }
- }
- return 0; /* Makes gcc happy */
- }
- /*!
- * \brief Called when the timer is about to delete an expired contact
- * \param _c expired contact
- * \return 1 if the contact should be removed from the database and 0 otherwise
- */
- int st_expired_ucontact(ucontact_t* _c)
- {
- /* There is no need to change contact
- * state, because the contact will
- * be deleted anyway
- */
- switch(_c->state) {
- case CS_NEW:
- /* Contact is not in the database
- * yet, remove it from memory only
- */
- return 0;
- case CS_SYNC:
- case CS_DIRTY:
- /* Remove from database here */
- return 1;
- }
- return 0; /* Makes gcc happy */
- }
- /*!
- * \brief Called when the timer is about flushing the contact, updates contact state
- * \param _c flushed contact
- * \return 1 if the contact should be inserted, 2 if update and 0 otherwise
- */
- int st_flush_ucontact(ucontact_t* _c)
- {
- switch(_c->state) {
- case CS_NEW:
- /* Contact is new and is not in
- * the database yet so we have
- * to insert it
- */
- _c->state = CS_SYNC;
- return 1;
- case CS_SYNC:
- /* Contact is synchronized, do
- * nothing
- */
- return 0;
- case CS_DIRTY:
- /* Contact has been modified and
- * is in the db already so we
- * have to update it
- */
- _c->state = CS_SYNC;
- return 2;
- }
- return 0; /* Makes gcc happy */
- }
- /* ============== Database related functions ================ */
- /*!
- * \brief Insert contact into the database
- * \param _c inserted contact
- * \return 0 on success, -1 on failure
- */
- int db_insert_ucontact(ucontact_t* _c)
- {
- char* dom;
- db_key_t keys[18];
- db_val_t vals[18];
- int nr_cols;
-
- if (_c->flags & FL_MEM) {
- return 0;
- }
- if(unlikely(_c->ruid.len<=0)) {
- LM_ERR("invalid ruid for aor: %.*s\n",
- _c->aor->len, ZSW(_c->aor->s));
- return -1;
- }
- keys[0] = &user_col;
- vals[0].type = DB1_STR;
- vals[0].nul = 0;
- vals[0].val.str_val.s = _c->aor->s;
- vals[0].val.str_val.len = _c->aor->len;
- keys[1] = &contact_col;
- vals[1].type = DB1_STR;
- vals[1].nul = 0;
- vals[1].val.str_val.s = _c->c.s;
- vals[1].val.str_val.len = _c->c.len;
- keys[2] = &expires_col;
- vals[2].nul = 0;
- UL_DB_EXPIRES_SET(&vals[2], _c->expires);
- keys[3] = &q_col;
- vals[3].type = DB1_DOUBLE;
- vals[3].nul = 0;
- vals[3].val.double_val = q2double(_c->q);
- keys[4] = &callid_col;
- vals[4].type = DB1_STR;
- vals[4].nul = 0;
- vals[4].val.str_val.s = _c->callid.s;
- vals[4].val.str_val.len = _c->callid.len;
- keys[5] = &cseq_col;
- vals[5].type = DB1_INT;
- vals[5].nul = 0;
- vals[5].val.int_val = _c->cseq;
- keys[6] = &flags_col;
- vals[6].type = DB1_INT;
- vals[6].nul = 0;
- vals[6].val.bitmap_val = _c->flags;
- keys[7] = &cflags_col;
- vals[7].type = DB1_INT;
- vals[7].nul = 0;
- vals[7].val.bitmap_val = _c->cflags;
- keys[8] = &user_agent_col;
- vals[8].type = DB1_STR;
- vals[8].nul = 0;
- vals[8].val.str_val.s = _c->user_agent.s;
- vals[8].val.str_val.len = _c->user_agent.len;
- nr_cols = 9;
- if (_c->received.s) {
- keys[nr_cols] = &received_col;
- vals[nr_cols].type = DB1_STR;
- vals[nr_cols].nul = 0;
- vals[nr_cols].val.str_val.s = _c->received.s;
- vals[nr_cols].val.str_val.len = _c->received.len;
- nr_cols++;
- } else if(ul_db_insert_null!=0) {
- keys[nr_cols] = &received_col;
- vals[nr_cols].type = DB1_STR;
- vals[nr_cols].nul = 1;
- nr_cols++;
- }
-
- if (_c->path.s) {
- keys[nr_cols] = &path_col;
- vals[nr_cols].type = DB1_STR;
- vals[nr_cols].nul = 0;
- vals[nr_cols].val.str_val.s = _c->path.s;
- vals[nr_cols].val.str_val.len = _c->path.len;
- nr_cols++;
- } else if(ul_db_insert_null!=0) {
- keys[nr_cols] = &path_col;
- vals[nr_cols].type = DB1_STR;
- vals[nr_cols].nul = 1;
- nr_cols++;
- }
- if (_c->sock) {
- keys[nr_cols] = &sock_col;
- vals[nr_cols].type = DB1_STR;
- vals[nr_cols].val.str_val = _c->sock->sock_str;
- vals[nr_cols].nul = 0;
- nr_cols++;
- } else if(ul_db_insert_null!=0) {
- keys[nr_cols] = &sock_col;
- vals[nr_cols].type = DB1_STR;
- vals[nr_cols].nul = 1;
- nr_cols++;
- }
- if (_c->methods != 0xFFFFFFFF) {
- keys[nr_cols] = &methods_col;
- vals[nr_cols].type = DB1_BITMAP;
- vals[nr_cols].val.bitmap_val = _c->methods;
- vals[nr_cols].nul = 0;
- nr_cols++;
- } else if(ul_db_insert_null!=0) {
- keys[nr_cols] = &methods_col;
- vals[nr_cols].type = DB1_BITMAP;
- vals[nr_cols].nul = 1;
- nr_cols++;
- }
- keys[nr_cols] = &last_mod_col;
- vals[nr_cols].nul = 0;
- UL_DB_EXPIRES_SET(&vals[nr_cols], _c->last_modified);
- nr_cols++;
- if(_c->ruid.len>0)
- {
- keys[nr_cols] = &ruid_col;
- vals[nr_cols].type = DB1_STR;
- vals[nr_cols].nul = 0;
- vals[nr_cols].val.str_val = _c->ruid;
- nr_cols++;
- } else if(ul_db_insert_null!=0) {
- keys[nr_cols] = &ruid_col;
- vals[nr_cols].type = DB1_STR;
- vals[nr_cols].nul = 1;
- nr_cols++;
- }
- if(_c->instance.len>0)
- {
- keys[nr_cols] = &instance_col;
- vals[nr_cols].type = DB1_STR;
- vals[nr_cols].nul = 0;
- vals[nr_cols].val.str_val = _c->instance;
- nr_cols++;
- } else if(ul_db_insert_null!=0) {
- keys[nr_cols] = &instance_col;
- vals[nr_cols].type = DB1_STR;
- vals[nr_cols].nul = 1;
- nr_cols++;
- }
- keys[nr_cols] = ®_id_col;
- vals[nr_cols].type = DB1_INT;
- vals[nr_cols].nul = 0;
- vals[nr_cols].val.int_val = (int)_c->reg_id;
- nr_cols++;
- if (use_domain) {
- keys[nr_cols] = &domain_col;
- vals[nr_cols].type = DB1_STR;
- vals[nr_cols].nul = 0;
- dom = memchr(_c->aor->s, '@', _c->aor->len);
- if (dom==0) {
- vals[0].val.str_val.len = 0;
- vals[nr_cols].val.str_val = *_c->aor;
- } else {
- vals[0].val.str_val.len = dom - _c->aor->s;
- vals[nr_cols].val.str_val.s = dom + 1;
- vals[nr_cols].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1;
- }
- nr_cols++;
- }
- if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
- LM_ERR("sql use_table failed\n");
- return -1;
- }
- if (ul_dbf.insert(ul_dbh, keys, vals, nr_cols) < 0) {
- LM_ERR("inserting contact in db failed\n");
- return -1;
- }
- if (ul_xavp_contact_name.s) {
- uldb_insert_attrs(_c->domain, &vals[0].val.str_val,
- &vals[nr_cols-1].val.str_val,
- &_c->ruid, _c->xavp);
- }
- return 0;
- }
- /*!
- * \brief Update contact in the database by address
- * \param _c updated contact
- * \return 0 on success, -1 on failure
- */
- int db_update_ucontact_addr(ucontact_t* _c)
- {
- char* dom;
- db_key_t keys1[4];
- db_val_t vals1[4];
- int n1;
- db_key_t keys2[15];
- db_val_t vals2[15];
- int nr_cols2;
- if (_c->flags & FL_MEM) {
- return 0;
- }
- keys2[0] = &expires_col;
- keys2[1] = &q_col;
- keys2[2] = &cseq_col;
- keys2[3] = &flags_col;
- keys2[4] = &cflags_col;
- keys2[5] = &user_agent_col;
- keys2[6] = &received_col;
- keys2[7] = &path_col;
- keys2[8] = &sock_col;
- keys2[9] = &methods_col;
- keys2[10] = &last_mod_col;
- keys2[11] = &ruid_col;
- keys2[12] = &instance_col;
- keys2[13] = ®_id_col;
- n1 = 0;
- keys1[n1] = &user_col;
- vals1[n1].type = DB1_STR;
- vals1[n1].nul = 0;
- vals1[n1].val.str_val = *_c->aor;
- LM_DBG("aor:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
- n1++;
- keys1[n1] = &contact_col;
- vals1[n1].type = DB1_STR;
- vals1[n1].nul = 0;
- vals1[n1].val.str_val = _c->c;
- LM_DBG("contact:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
- n1++;
- keys1[n1] = &callid_col;
- vals1[n1].type = DB1_STR;
- vals1[n1].nul = 0;
- vals1[n1].val.str_val = _c->callid;
- LM_DBG("callid:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
- n1++;
- vals2[0].nul = 0;
- UL_DB_EXPIRES_SET(&vals2[0], _c->expires);
- vals2[1].type = DB1_DOUBLE;
- vals2[1].nul = 0;
- vals2[1].val.double_val = q2double(_c->q);
- vals2[2].type = DB1_INT;
- vals2[2].nul = 0;
- vals2[2].val.int_val = _c->cseq;
- vals2[3].type = DB1_INT;
- vals2[3].nul = 0;
- vals2[3].val.bitmap_val = _c->flags;
- vals2[4].type = DB1_INT;
- vals2[4].nul = 0;
- vals2[4].val.bitmap_val = _c->cflags;
- vals2[5].type = DB1_STR;
- vals2[5].nul = 0;
- vals2[5].val.str_val = _c->user_agent;
- vals2[6].type = DB1_STR;
- if (_c->received.s == 0) {
- vals2[6].nul = 1;
- } else {
- vals2[6].nul = 0;
- vals2[6].val.str_val = _c->received;
- }
-
- vals2[7].type = DB1_STR;
- if (_c->path.s == 0) {
- vals2[7].nul = 1;
- } else {
- vals2[7].nul = 0;
- vals2[7].val.str_val = _c->path;
- }
- vals2[8].type = DB1_STR;
- if (_c->sock) {
- vals2[8].val.str_val = _c->sock->sock_str;
- vals2[8].nul = 0;
- } else {
- vals2[8].nul = 1;
- }
- vals2[9].type = DB1_BITMAP;
- if (_c->methods == 0xFFFFFFFF) {
- vals2[9].nul = 1;
- } else {
- vals2[9].val.bitmap_val = _c->methods;
- vals2[9].nul = 0;
- }
- vals2[10].nul = 0;
- UL_DB_EXPIRES_SET(&vals2[10], _c->last_modified);
- nr_cols2 = 11;
- if(_c->ruid.len>0)
- {
- vals2[nr_cols2].type = DB1_STR;
- vals2[nr_cols2].nul = 0;
- vals2[nr_cols2].val.str_val = _c->ruid;
- } else {
- vals2[nr_cols2].nul = 1;
- }
- nr_cols2++;
- if(_c->instance.len>0)
- {
- vals2[nr_cols2].type = DB1_STR;
- vals2[nr_cols2].nul = 0;
- vals2[nr_cols2].val.str_val = _c->instance;
- } else {
- vals2[nr_cols2].nul = 1;
- }
- nr_cols2++;
- vals2[nr_cols2].type = DB1_INT;
- vals2[nr_cols2].nul = 0;
- vals2[nr_cols2].val.int_val = (int)_c->reg_id;
- nr_cols2++;
- keys2[nr_cols2] = &contact_col;
- vals2[nr_cols2].type = DB1_STR;
- vals2[nr_cols2].nul = 0;
- vals2[nr_cols2].val.str_val = _c->c;
- LM_DBG("contact:%.*s\n", vals2[nr_cols2].val.str_val.len, vals2[nr_cols2].val.str_val.s);
- nr_cols2++;
- if (use_domain) {
- keys1[n1] = &domain_col;
- vals1[n1].type = DB1_STR;
- vals1[n1].nul = 0;
- dom = memchr(_c->aor->s, '@', _c->aor->len);
- if (dom==0) {
- vals1[0].val.str_val.len = 0;
- vals1[n1].val.str_val = *_c->aor;
- } else {
- vals1[0].val.str_val.len = dom - _c->aor->s;
- vals1[n1].val.str_val.s = dom + 1;
- vals1[n1].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1;
- }
- n1++;
- }
- if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
- LM_ERR("sql use_table failed\n");
- return -1;
- }
- if (ul_dbf.update(ul_dbh, keys1, 0, vals1, keys2, vals2, n1,
- nr_cols2) < 0) {
- LM_ERR("updating database failed\n");
- return -1;
- }
- if (ul_db_check_update==1 && ul_dbf.affected_rows) {
- /* supposed to be an UPDATE, but if affected rows is 0, then try
- * to do an INSERT */
- if(ul_dbf.affected_rows(ul_dbh)==0) {
- LM_DBG("affected rows by UPDATE was 0, doing an INSERT\n");
- if(db_insert_ucontact(_c)<0)
- return -1;
- }
- }
- /* delete old db attrs and add the current list */
- if (ul_xavp_contact_name.s) {
- if (use_domain) {
- uldb_delete_attrs(_c->domain, &vals1[0].val.str_val,
- &vals1[n1-1].val.str_val, &_c->ruid);
- uldb_insert_attrs(_c->domain, &vals1[0].val.str_val,
- &vals1[n1-1].val.str_val,
- &_c->ruid, _c->xavp);
- } else {
- uldb_delete_attrs(_c->domain, &vals1[0].val.str_val,
- NULL, &_c->ruid);
- uldb_insert_attrs(_c->domain, &vals1[0].val.str_val,
- NULL, &_c->ruid, _c->xavp);
- }
- }
- return 0;
- }
- /*!
- * \brief Update contact in the database by ruid
- * \param _c updated contact
- * \return 0 on success, -1 on failure
- */
- int db_update_ucontact_ruid(ucontact_t* _c)
- {
- str auser;
- str adomain;
- db_key_t keys1[1];
- db_val_t vals1[1];
- int n1;
- db_key_t keys2[15];
- db_val_t vals2[15];
- int n2;
- if (_c->flags & FL_MEM) {
- return 0;
- }
- if(_c->ruid.len<=0) {
- LM_ERR("updating record in database failed - empty ruid\n");
- return -1;
- }
- n1 = 0;
- keys1[n1] = &ruid_col;
- vals1[n1].type = DB1_STR;
- vals1[n1].nul = 0;
- vals1[n1].val.str_val = _c->ruid;
- LM_DBG("ruid:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
- n1++;
- n2 = 0;
- keys2[n2] = &expires_col;
- vals2[n2].nul = 0;
- UL_DB_EXPIRES_SET(&vals2[n2], _c->expires);
- n2++;
- keys2[n2] = &q_col;
- vals2[n2].type = DB1_DOUBLE;
- vals2[n2].nul = 0;
- vals2[n2].val.double_val = q2double(_c->q);
- n2++;
- keys2[n2] = &cseq_col;
- vals2[n2].type = DB1_INT;
- vals2[n2].nul = 0;
- vals2[n2].val.int_val = _c->cseq;
- n2++;
- keys2[n2] = &flags_col;
- vals2[n2].type = DB1_INT;
- vals2[n2].nul = 0;
- vals2[n2].val.bitmap_val = _c->flags;
- n2++;
- keys2[n2] = &cflags_col;
- vals2[n2].type = DB1_INT;
- vals2[n2].nul = 0;
- vals2[n2].val.bitmap_val = _c->cflags;
- n2++;
- keys2[n2] = &user_agent_col;
- vals2[n2].type = DB1_STR;
- vals2[n2].nul = 0;
- vals2[n2].val.str_val = _c->user_agent;
- n2++;
- keys2[n2] = &received_col;
- vals2[n2].type = DB1_STR;
- if (_c->received.s == 0) {
- vals2[n2].nul = 1;
- } else {
- vals2[n2].nul = 0;
- vals2[n2].val.str_val = _c->received;
- }
- n2++;
- keys2[n2] = &path_col;
- vals2[n2].type = DB1_STR;
- if (_c->path.s == 0) {
- vals2[n2].nul = 1;
- } else {
- vals2[n2].nul = 0;
- vals2[n2].val.str_val = _c->path;
- }
- n2++;
- keys2[n2] = &sock_col;
- vals2[n2].type = DB1_STR;
- if (_c->sock) {
- vals2[n2].val.str_val = _c->sock->sock_str;
- vals2[n2].nul = 0;
- } else {
- vals2[n2].nul = 1;
- }
- n2++;
- keys2[n2] = &methods_col;
- vals2[n2].type = DB1_BITMAP;
- if (_c->methods == 0xFFFFFFFF) {
- vals2[n2].nul = 1;
- } else {
- vals2[n2].val.bitmap_val = _c->methods;
- vals2[n2].nul = 0;
- }
- n2++;
- keys2[n2] = &last_mod_col;
- vals2[n2].nul = 0;
- UL_DB_EXPIRES_SET(&vals2[n2], _c->last_modified);
- n2++;
- keys2[n2] = &callid_col;
- vals2[n2].type = DB1_STR;
- vals2[n2].nul = 0;
- vals2[n2].val.str_val = _c->callid;
- n2++;
- keys2[n2] = &instance_col;
- if(_c->instance.len>0)
- {
- vals2[n2].type = DB1_STR;
- vals2[n2].nul = 0;
- vals2[n2].val.str_val = _c->instance;
- } else {
- vals2[n2].nul = 1;
- }
- n2++;
- keys2[n2] = ®_id_col;
- vals2[n2].type = DB1_INT;
- vals2[n2].nul = 0;
- vals2[n2].val.int_val = (int)_c->reg_id;
- n2++;
- keys2[n2] = &contact_col;
- vals2[n2].type = DB1_STR;
- vals2[n2].nul = 0;
- vals2[n2].val.str_val = _c->c;
- LM_DBG("contact:%.*s\n", vals2[n2].val.str_val.len, vals2[n2].val.str_val.s);
- n2++;
- if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
- LM_ERR("sql use_table failed\n");
- return -1;
- }
- if (ul_dbf.update(ul_dbh, keys1, 0, vals1, keys2, vals2, n1, n2) < 0) {
- LM_ERR("updating database failed\n");
- return -1;
- }
- if (ul_db_check_update==1 && ul_dbf.affected_rows) {
- /* supposed to be an UPDATE, but if affected rows is 0, then try
- * to do an INSERT */
- if(ul_dbf.affected_rows(ul_dbh)==0) {
- LM_DBG("affected rows by UPDATE was 0, doing an INSERT\n");
- if(db_insert_ucontact(_c)<0)
- return -1;
- }
- }
- /* delete old db attrs and add the current list */
- if (ul_xavp_contact_name.s) {
- auser = *_c->aor;
- if (use_domain) {
- adomain.s = memchr(_c->aor->s, '@', _c->aor->len);
- if (adomain.s==0) {
- auser.len = 0;
- adomain = *_c->aor;
- } else {
- auser.len = adomain.s - _c->aor->s;
- adomain.s++;
- adomain.len = _c->aor->s +
- _c->aor->len - adomain.s;
- }
- uldb_delete_attrs(_c->domain, &auser,
- &adomain, &_c->ruid);
- uldb_insert_attrs(_c->domain, &auser,
- &adomain, &_c->ruid, _c->xavp);
- } else {
- uldb_delete_attrs(_c->domain, &auser,
- NULL, &_c->ruid);
- uldb_insert_attrs(_c->domain, &auser,
- NULL, &_c->ruid, _c->xavp);
- }
- }
- return 0;
- }
- /*!
- * \brief Update contact in the database by instance reg_id
- * \param _c updated contact
- * \return 0 on success, -1 on failure
- */
- int db_update_ucontact_instance(ucontact_t* _c)
- {
- str auser;
- str adomain;
- db_key_t keys1[4];
- db_val_t vals1[4];
- int n1;
- db_key_t keys2[13];
- db_val_t vals2[13];
- int n2;
- if (_c->flags & FL_MEM) {
- return 0;
- }
- if(_c->instance.len<=0) {
- LM_ERR("updating record in database failed - empty instance\n");
- return -1;
- }
- n1 = 0;
- keys1[n1] = &user_col;
- vals1[n1].type = DB1_STR;
- vals1[n1].nul = 0;
- vals1[n1].val.str_val = *_c->aor;
- LM_DBG("aor:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
- n1++;
- keys1[n1] = &instance_col;
- vals1[n1].type = DB1_STR;
- vals1[n1].nul = 0;
- vals1[n1].val.str_val = _c->instance;
- LM_DBG("instance:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
- n1++;
- keys1[n1] = ®_id_col;
- vals1[n1].type = DB1_INT;
- vals1[n1].nul = 0;
- vals1[n1].val.int_val = (int)_c->reg_id;
- LM_DBG("reg-id:%d\n", vals1[n1].val.int_val);
- n1++;
- n2 = 0;
- keys2[n2] = &expires_col;
- vals2[n2].nul = 0;
- UL_DB_EXPIRES_SET(&vals2[n2], _c->expires);
- n2++;
- keys2[n2] = &q_col;
- vals2[n2].type = DB1_DOUBLE;
- vals2[n2].nul = 0;
- vals2[n2].val.double_val = q2double(_c->q);
- n2++;
- keys2[n2] = &cseq_col;
- vals2[n2].type = DB1_INT;
- vals2[n2].nul = 0;
- vals2[n2].val.int_val = _c->cseq;
- n2++;
- keys2[n2] = &flags_col;
- vals2[n2].type = DB1_INT;
- vals2[n2].nul = 0;
- vals2[n2].val.bitmap_val = _c->flags;
- n2++;
- keys2[n2] = &cflags_col;
- vals2[n2].type = DB1_INT;
- vals2[n2].nul = 0;
- vals2[n2].val.bitmap_val = _c->cflags;
- n2++;
- keys2[n2] = &user_agent_col;
- vals2[n2].type = DB1_STR;
- vals2[n2].nul = 0;
- vals2[n2].val.str_val = _c->user_agent;
- n2++;
- keys2[n2] = &received_col;
- vals2[n2].type = DB1_STR;
- if (_c->received.s == 0) {
- vals2[n2].nul = 1;
- } else {
- vals2[n2].nul = 0;
- vals2[n2].val.str_val = _c->received;
- }
- n2++;
- keys2[n2] = &path_col;
- vals2[n2].type = DB1_STR;
- if (_c->path.s == 0) {
- vals2[n2].nul = 1;
- } else {
- vals2[n2].nul = 0;
- vals2[n2].val.str_val = _c->path;
- }
- n2++;
- keys2[n2] = &sock_col;
- vals2[n2].type = DB1_STR;
- if (_c->sock) {
- vals2[n2].val.str_val = _c->sock->sock_str;
- vals2[n2].nul = 0;
- } else {
- vals2[n2].nul = 1;
- }
- n2++;
- keys2[n2] = &methods_col;
- vals2[n2].type = DB1_BITMAP;
- if (_c->methods == 0xFFFFFFFF) {
- vals2[n2].nul = 1;
- } else {
- vals2[n2].val.bitmap_val = _c->methods;
- vals2[n2].nul = 0;
- }
- n2++;
- keys2[n2] = &last_mod_col;
- vals2[n2].nul = 0;
- UL_DB_EXPIRES_SET(&vals2[n2], _c->last_modified);
- n2++;
- keys2[n2] = &callid_col;
- vals2[n2].type = DB1_STR;
- vals2[n2].nul = 0;
- vals2[n2].val.str_val = _c->callid;
- n2++;
- keys2[n2] = &contact_col;
- vals2[n2].type = DB1_STR;
- vals2[n2].nul = 0;
- vals2[n2].val.str_val.s = _c->c.s;
- vals2[n2].val.str_val.len = _c->c.len;
- LM_DBG("contact:%.*s\n", vals2[n2].val.str_val.len, vals2[n2].val.str_val.s);
- n2++;
- auser = *_c->aor;
- if (use_domain) {
- keys1[n1] = &domain_col;
- vals1[n1].type = DB1_STR;
- vals1[n1].nul = 0;
- adomain.s = memchr(_c->aor->s, '@', _c->aor->len);
- if (adomain.s==0) {
- vals1[0].val.str_val.len = 0;
- vals1[n1].val.str_val = *_c->aor;
- auser.len = 0;
- adomain = *_c->aor;
- } else {
- vals1[0].val.str_val.len = adomain.s - _c->aor->s;
- vals1[n1].val.str_val.s = adomain.s + 1;
- vals1[n1].val.str_val.len = _c->aor->s + _c->aor->len - adomain.s - 1;
- auser.len = adomain.s - _c->aor->s;
- adomain.s++;
- adomain.len = _c->aor->s +
- _c->aor->len - adomain.s;
- }
- n1++;
- }
- if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
- LM_ERR("sql use_table failed\n");
- return -1;
- }
- if (ul_dbf.update(ul_dbh, keys1, 0, vals1, keys2, vals2, n1, n2) < 0) {
- LM_ERR("updating database failed\n");
- return -1;
- }
- if (ul_db_check_update==1 && ul_dbf.affected_rows) {
- LM_DBG("update affected_rows 0\n");
- /* supposed to be an UPDATE, but if affected rows is 0, then try
- * to do an INSERT */
- if(ul_dbf.affected_rows(ul_dbh)==0) {
- LM_DBG("affected rows by UPDATE was 0, doing an INSERT\n");
- if(db_insert_ucontact(_c)<0)
- return -1;
- }
- }
- /* delete old db attrs and add the current list */
- if (ul_xavp_contact_name.s) {
- if (use_domain) {
- uldb_delete_attrs(_c->domain, &auser,
- &adomain, &_c->ruid);
- uldb_insert_attrs(_c->domain, &auser,
- &adomain, &_c->ruid, _c->xavp);
- } else {
- uldb_delete_attrs(_c->domain, &auser,
- NULL, &_c->ruid);
- uldb_insert_attrs(_c->domain, &auser,
- NULL, &_c->ruid, _c->xavp);
- }
- }
- return 0;
- }
- /*!
- * \brief Update contact in the database
- * \param _c updated contact
- * \return 0 on success, -1 on failure
- */
- int db_update_ucontact(ucontact_t* _c)
- {
- if(ul_db_ops_ruid==0)
- if (_c->instance.len<=0) {
- return db_update_ucontact_addr(_c);
- }
- else {
- return db_update_ucontact_instance(_c);
- }
- else
- return db_update_ucontact_ruid(_c);
- }
- /*!
- * \brief Delete contact from the database by address
- * \param _c deleted contact
- * \return 0 on success, -1 on failure
- */
- int db_delete_ucontact_addr(ucontact_t* _c)
- {
- char* dom;
- db_key_t keys[4];
- db_val_t vals[4];
- int n;
- if (_c->flags & FL_MEM) {
- return 0;
- }
- n = 0;
- keys[n] = &user_col;
- vals[n].type = DB1_STR;
- vals[n].nul = 0;
- vals[n].val.str_val = *_c->aor;
- n++;
- keys[n] = &contact_col;
- vals[n].type = DB1_STR;
- vals[n].nul = 0;
- vals[n].val.str_val = _c->c;
- n++;
- keys[n] = &callid_col;
- vals[n].type = DB1_STR;
- vals[n].nul = 0;
- vals[n].val.str_val = _c->callid;
- n++;
- if (use_domain) {
- keys[n] = &domain_col;
- vals[n].type = DB1_STR;
- vals[n].nul = 0;
- dom = memchr(_c->aor->s, '@', _c->aor->len);
- if (dom==0) {
- vals[0].val.str_val.len = 0;
- vals[n].val.str_val = *_c->aor;
- } else {
- vals[0].val.str_val.len = dom - _c->aor->s;
- vals[n].val.str_val.s = dom + 1;
- vals[n].val.str_val.len = _c->aor->s +
- _c->aor->len - dom - 1;
- }
- uldb_delete_attrs(_c->domain, &vals[0].val.str_val,
- &vals[n].val.str_val, &_c->ruid);
- n++;
- } else {
- uldb_delete_attrs(_c->domain, &vals[0].val.str_val,
- NULL, &_c->ruid);
- }
- if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
- LM_ERR("sql use_table failed\n");
- return -1;
- }
- if (ul_dbf.delete(ul_dbh, keys, 0, vals, n) < 0) {
- LM_ERR("deleting from database failed\n");
- return -1;
- }
- return 0;
- }
- /*!
- * \brief Delete contact from the database by ruid
- * \param _c deleted contact
- * \return 0 on success, -1 on failure
- */
- int db_delete_ucontact_ruid(ucontact_t* _c)
- {
- db_key_t keys[1];
- db_val_t vals[1];
- int n;
- if (_c->flags & FL_MEM) {
- return 0;
- }
- if(_c->ruid.len<=0) {
- LM_ERR("deleting from database failed - empty ruid\n");
- return -1;
- }
- n = 0;
- keys[n] = &ruid_col;
- vals[n].type = DB1_STR;
- vals[n].nul = 0;
- vals[n].val.str_val = _c->ruid;
- n++;
- if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
- LM_ERR("sql use_table failed\n");
- return -1;
- }
- if (ul_dbf.delete(ul_dbh, keys, 0, vals, n) < 0) {
- LM_ERR("deleting from database failed\n");
- return -1;
- }
- return 0;
- }
- /*!
- * \brief Delete contact from the database
- * \param _c deleted contact
- * \return 0 on success, -1 on failure
- */
- int db_delete_ucontact(ucontact_t* _c)
- {
- if(ul_db_ops_ruid==0)
- return db_delete_ucontact_addr(_c);
- else
- return db_delete_ucontact_ruid(_c);
- }
- /*!
- * \brief Remove a contact from list belonging to a certain record
- * \param _r record the contact belongs
- * \param _c removed contact
- */
- static inline void unlink_contact(struct urecord* _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;
- }
- }
- }
- /*!
- * \brief Insert a new contact into the list at the correct position
- * \param _r record that holds the sorted contacts
- * \param _c new contact
- */
- static inline void update_contact_pos(struct urecord* _r, ucontact_t* _c)
- {
- ucontact_t *pos, *ppos;
- if (desc_time_order) {
- /* order by time - first the newest */
- if (_c->prev==0)
- return;
- unlink_contact(_r, _c);
- /* insert it at the beginning */
- _c->next = _r->contacts;
- _c->prev = 0;
- _r->contacts->prev = _c;
- _r->contacts = _c;
- } else {
- /* order by q - first the smaller q */
- if ( (_c->prev==0 || _c->q<=_c->prev->q)
- && (_c->next==0 || _c->q>=_c->next->q) )
- return;
- /* need to move , but where? */
- unlink_contact(_r, _c);
- _c->next = _c->prev = 0;
- for(pos=_r->contacts,ppos=0;pos&&pos->q<_c->q;ppos=pos,pos=pos->next);
- if (pos) {
- if (!pos->prev) {
- pos->prev = _c;
- _c->next = pos;
- _r->contacts = _c;
- } else {
- _c->next = pos;
- _c->prev = pos->prev;
- pos->prev->next = _c;
- pos->prev = _c;
- }
- } else if (ppos) {
- ppos->next = _c;
- _c->prev = ppos;
- } else {
- _r->contacts = _c;
- }
- }
- }
- /*!
- * \brief Update ucontact with new values
- * \param _r record the contact belongs to
- * \param _c updated contact
- * \param _ci new contact informations
- * \return 0 on success, -1 on failure
- */
- int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci)
- {
- int res;
- /* we have to update memory in any case, but database directly
- * only in db_mode 1 */
- if (mem_update_ucontact( _c, _ci) < 0) {
- LM_ERR("failed to update memory\n");
- return -1;
- }
- /* run callbacks for UPDATE event */
- if (exists_ulcb_type(UL_CONTACT_UPDATE))
- {
- LM_DBG("exists callback for type= UL_CONTACT_UPDATE\n");
- run_ul_callbacks( UL_CONTACT_UPDATE, _c);
- }
- if (_r && db_mode!=DB_ONLY)
- update_contact_pos( _r, _c);
- st_update_ucontact(_c);
- if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
- if (ul_db_update_as_insert)
- res = db_insert_ucontact(_c);
- else
- res = db_update_ucontact(_c);
- if (res < 0) {
- LM_ERR("failed to update database\n");
- return -1;
- } else {
- _c->state = CS_SYNC;
- }
- }
- return 0;
- }
- /*!
- * \brief Load all location attributes from a udomain
- *
- * Load all location attributes from a udomain, useful to populate the
- * memory cache on startup.
- * \param _dname loaded domain name
- * \param _user sip username
- * \param _domain sip domain
- * \param _ruid usrloc record unique id
- * \return 0 on success, -1 on failure
- */
- int uldb_delete_attrs(str* _dname, str *_user, str *_domain, str *_ruid)
- {
- char tname_buf[64];
- str tname;
- db_key_t keys[3];
- db_val_t vals[3];
- LM_DBG("trying to delete location attributes\n");
- if(ul_xavp_contact_name.s==NULL) {
- /* feature disabled by mod param */
- return 0;
- }
- if(_dname->len+6>=64) {
- LM_ERR("attributes table name is too big\n");
- return -1;
- }
- strncpy(tname_buf, _dname->s, _dname->len);
- tname_buf[_dname->len] = '\0';
- strcat(tname_buf, "_attrs");
- tname.s = tname_buf;
- tname.len = _dname->len + 6;
- keys[0] = &ulattrs_user_col;
- keys[1] = &ulattrs_ruid_col;
- keys[2] = &ulattrs_domain_col;
- vals[0].type = DB1_STR;
- vals[0].nul = 0;
- vals[0].val.str_val = *_user;
- vals[1].type = DB1_STR;
- vals[1].nul = 0;
- vals[1].val.str_val = *_ruid;
- if (use_domain) {
- vals[2].type = DB1_STR;
- vals[2].nul = 0;
- vals[2].val.str_val = *_domain;
- }
- if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
- LM_ERR("sql use_table failed\n");
- return -1;
- }
- if (ul_dbf.delete(ul_dbh, keys, 0, vals, (use_domain) ? (3) : (2)) < 0) {
- LM_ERR("deleting from database failed\n");
- return -1;
- }
- return 0;
- }
- /*!
- * \brief Insert contact attributes into the database
- * \param _dname loaded domain name
- * \param _user sip username
- * \param _domain sip domain
- * \param _ruid record unique id
- * \param _xhead head of xavp list
- * \return 0 on success, -1 on failure
- */
- int uldb_insert_attrs(str *_dname, str *_user, str *_domain,
- str *_ruid, sr_xavp_t *_xhead)
- {
- char tname_buf[64];
- str tname;
- str avalue;
- sr_xavp_t *xavp;
- db_key_t keys[7];
- db_val_t vals[7];
- int nr_cols;
- LM_DBG("trying to insert location attributes\n");
- if(ul_xavp_contact_name.s==NULL) {
- /* feature disabled by mod param */
- LM_DBG("location attributes disabled\n");
- return 0;
- }
- if(_xhead==NULL || _xhead->val.type!=SR_XTYPE_XAVP
- || _xhead->val.v.xavp==NULL) {
- /* nothing to write */
- LM_DBG("no location attributes\n");
- return 0;
- }
- if(_dname->len+6>=64) {
- LM_ERR("attributes table name is too big\n");
- return -1;
- }
- strncpy(tname_buf, _dname->s, _dname->len);
- tname_buf[_dname->len] = '\0';
- strcat(tname_buf, "_attrs");
- tname.s = tname_buf;
- tname.len = _dname->len + 6;
- if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
- LM_ERR("sql use_table failed for %.*s\n", tname.len, tname.s);
- return -1;
- }
- keys[0] = &ulattrs_user_col;
- keys[1] = &ulattrs_ruid_col;
- keys[2] = &ulattrs_last_mod_col;
- keys[3] = &ulattrs_aname_col;
- keys[4] = &ulattrs_atype_col;
- keys[5] = &ulattrs_avalue_col;
- keys[6] = &ulattrs_domain_col;
- vals[0].type = DB1_STR;
- vals[0].nul = 0;
- vals[0].val.str_val = *_user;
- vals[1].type = DB1_STR;
- vals[1].nul = 0;
- vals[1].val.str_val = *_ruid;
- vals[2].nul = 0;
- UL_DB_EXPIRES_SET(&vals[2], time(NULL));
- if (use_domain && _domain!=NULL && _domain->s!=NULL) {
- nr_cols = 7;
- vals[6].type = DB1_STR;
- vals[6].nul = 0;
- vals[6].val.str_val = *_domain;
- } else {
- nr_cols = 6;
- }
- for(xavp=_xhead->val.v.xavp; xavp; xavp=xavp->next) {
- vals[3].type = DB1_STR;
- vals[3].nul = 0;
- vals[3].val.str_val = xavp->name;
- vals[4].type = DB1_INT;
- vals[4].nul = 0;
- if(xavp->val.type==SR_XTYPE_STR) {
- vals[4].val.int_val = 0;
- avalue = xavp->val.v.s;
- } else if(xavp->val.type==SR_XTYPE_INT) {
- vals[4].val.int_val = 1;
- avalue.s = sint2str((long)xavp->val.v.i, &avalue.len);
- } else {
- continue;
- }
- vals[5].type = DB1_STR;
- vals[5].nul = 0;
- vals[5].val.str_val = avalue;
- if (ul_dbf.insert(ul_dbh, keys, vals, nr_cols) < 0) {
- LM_ERR("inserting contact in db failed\n");
- return -1;
- }
- }
- return 0;
- }
|