all: updated FSF address in GPL text
[sip-router] / modules / p_usrloc / urecord.c
1 /*
2  * $Id: urecord.c 5241 2008-11-21 12:52:25Z henningw $ 
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License 
19  * along with this program; if not, write to the Free Software 
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  * History:
23  * ---------
24  * 2003-03-12 added replication mark and zombie state support (nils)
25  * 2004-03-17 generic callbacks added (bogdan)
26  * 2004-06-07 updated to the new DB api (andrei)
27  */
28
29 /*! \file
30  *  \brief USRLOC - Usrloc record structure
31  *  \ingroup usrloc
32  *
33  * - Module \ref usrloc
34  */
35
36 #include "../usrloc/usrloc.h"
37 #include "urecord.h"
38 #include <string.h>
39 #include "../../mem/shm_mem.h"
40 #include "../../dprint.h"
41 #include "../../ut.h"
42 #include "../../hashes.h"
43 #include "p_usrloc_mod.h"
44 #include "utime.h"
45 #include "../usrloc/ul_callback.h"
46
47 #include "ul_db_layer.h"
48
49
50 /*! contact matching mode */
51 int matching_mode = CONTACT_ONLY;
52 /*! retransmission detection interval in seconds */
53 int cseq_delay = 20;
54
55 /*!
56  * \brief Create and initialize new record structure
57  * \param _dom domain name
58  * \param _aor address of record
59  * \param _r pointer to the new record
60  * \return 0 on success, negative on failure
61  */
62 int new_urecord(str* _dom, str* _aor, urecord_t** _r)
63 {
64         *_r = (urecord_t*)shm_malloc(sizeof(urecord_t));
65         if (*_r == 0) {
66                 LM_ERR("no more share memory\n");
67                 return -1;
68         }
69         memset(*_r, 0, sizeof(urecord_t));
70
71         (*_r)->aor.s = (char*)shm_malloc(_aor->len);
72         if ((*_r)->aor.s == 0) {
73                 LM_ERR("no more share memory\n");
74                 shm_free(*_r);
75                 *_r = 0;
76                 return -2;
77         }
78         memcpy((*_r)->aor.s, _aor->s, _aor->len);
79         (*_r)->aor.len = _aor->len;
80         (*_r)->domain = _dom;
81         (*_r)->aorhash = ul_get_aorhash(_aor);
82         return 0;
83 }
84
85
86 /*!
87  * \brief Free all memory used by the given structure
88  *
89  * Free all memory used by the given structure.
90  * The structure must be removed from all linked
91  * lists first
92  * \param _r freed record list
93  */
94 void free_urecord(urecord_t* _r)
95 {
96         ucontact_t* ptr;
97
98         while(_r->contacts) {
99                 ptr = _r->contacts;
100                 _r->contacts = _r->contacts->next;
101                 free_ucontact(ptr);
102         }
103         
104         /* if mem cache is not used, the urecord struct is static*/
105         if (db_mode!=DB_ONLY) {
106                 if (_r->aor.s) shm_free(_r->aor.s);
107                 shm_free(_r);
108         }
109 }
110
111
112 /*!
113  * \brief Print a record, useful for debugging
114  * \param _f print output
115  * \param _r printed record
116  */
117 void print_urecord(FILE* _f, urecord_t* _r)
118 {
119         ucontact_t* ptr;
120
121         fprintf(_f, "...Record(%p)...\n", _r);
122         fprintf(_f, "domain : '%.*s'\n", _r->domain->len, ZSW(_r->domain->s));
123         fprintf(_f, "aor    : '%.*s'\n", _r->aor.len, ZSW(_r->aor.s));
124         fprintf(_f, "aorhash: '%u'\n", (unsigned)_r->aorhash);
125         fprintf(_f, "slot:    '%d'\n", _r->aorhash&(_r->slot->d->size-1));
126         
127         if (_r->contacts) {
128                 ptr = _r->contacts;
129                 while(ptr) {
130                         print_ucontact(_f, ptr);
131                         ptr = ptr->next;
132                 }
133         }
134
135         fprintf(_f, ".../Record...\n");
136 }
137
138
139 /*!
140  * \brief Add a new contact in memory
141  *
142  * Add a new contact in memory, contacts are ordered by:
143  * 1) q value, 2) descending modification time
144  * \param _r record this contact belongs to
145  * \param _c contact
146  * \param _ci contact information
147  * \return pointer to new created contact on success, 0 on failure
148  */
149 ucontact_t* mem_insert_ucontact(urecord_t* _r, str* _c, ucontact_info_t* _ci)
150 {
151         ucontact_t* ptr, *prev = 0;
152         ucontact_t* c;
153
154         if ( (c=new_ucontact(_r->domain, &_r->aor, _c, _ci)) == 0) {
155                 LM_ERR("failed to create new contact\n");
156                 return 0;
157         }
158         if_update_stat( _r->slot, _r->slot->d->contacts, 1);
159
160         ptr = _r->contacts;
161
162         if (!desc_time_order) {
163                 while(ptr) {
164                         if (ptr->q < c->q) break;
165                         prev = ptr;
166                         ptr = ptr->next;
167                 }
168         }
169
170         if (ptr) {
171                 if (!ptr->prev) {
172                         ptr->prev = c;
173                         c->next = ptr;
174                         _r->contacts = c;
175                 } else {
176                         c->next = ptr;
177                         c->prev = ptr->prev;
178                         ptr->prev->next = c;
179                         ptr->prev = c;
180                 }
181         } else if (prev) {
182                 prev->next = c;
183                 c->prev = prev;
184         } else {
185                 _r->contacts = c;
186         }
187
188         return c;
189 }
190
191
192 /*!
193  * \brief Remove the contact from lists in memory
194  * \param _r record this contact belongs to
195  * \param _c removed contact
196  */
197 void mem_remove_ucontact(urecord_t* _r, ucontact_t* _c)
198 {
199         if (_c->prev) {
200                 _c->prev->next = _c->next;
201                 if (_c->next) {
202                         _c->next->prev = _c->prev;
203                 }
204         } else {
205                 _r->contacts = _c->next;
206                 if (_c->next) {
207                         _c->next->prev = 0;
208                 }
209         }
210 }       
211
212
213 /*!
214  * \brief Remove contact in memory from the list and delete it
215  * \param _r record this contact belongs to
216  * \param _c deleted contact
217  */
218 void mem_delete_ucontact(urecord_t* _r, ucontact_t* _c)
219 {
220         mem_remove_ucontact(_r, _c);
221         if_update_stat( _r->slot, _r->slot->d->contacts, -1);
222         free_ucontact(_c);
223 }
224
225
226 /*!
227  * \brief Expires timer for NO_DB db_mode
228  *
229  * Expires timer for NO_DB db_mode, process all contacts from
230  * the record, delete the expired ones from memory.
231  * \param _r processed record
232  */
233 static inline void nodb_timer(urecord_t* _r)
234 {
235         ucontact_t* ptr, *t;
236
237         ptr = _r->contacts;
238
239         while(ptr) {
240                 if (!VALID_CONTACT(ptr, act_time)) {
241                         /* run callbacks for EXPIRE event */
242                         if (exists_ulcb_type(UL_CONTACT_EXPIRE))
243                                 run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
244
245                         LM_DBG("Binding '%.*s','%.*s' has expired\n",
246                                 ptr->aor->len, ZSW(ptr->aor->s),
247                                 ptr->c.len, ZSW(ptr->c.s));
248
249                         t = ptr;
250                         ptr = ptr->next;
251
252                         mem_delete_ucontact(_r, t);
253                         update_stat( _r->slot->d->expires, 1);
254                 } else {
255                         ptr = ptr->next;
256                 }
257         }
258 }
259
260
261 /*!
262  * \brief Write through timer, used for WRITE_THROUGH db_mode
263  *
264  * Write through timer, used for WRITE_THROUGH db_mode. Process all
265  * contacts from the record, delete all expired ones from the DB.
266  * \param _r processed record
267  * \note currently unused, this mode is also handled by the wb_timer
268  */
269 static inline void wt_timer(urecord_t* _r)
270 {
271         ucontact_t* ptr, *t;
272
273         ptr = _r->contacts;
274
275         while(ptr) {
276                 if (!VALID_CONTACT(ptr, act_time)) {
277                         /* run callbacks for EXPIRE event */
278                         if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
279                                 run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
280                         }
281
282                         LM_DBG("Binding '%.*s','%.*s' has expired\n",
283                                 ptr->aor->len, ZSW(ptr->aor->s),
284                                 ptr->c.len, ZSW(ptr->c.s));
285
286                         t = ptr;
287                         ptr = ptr->next;
288
289                         if (db_delete_ucontact(t) < 0) {
290                                 LM_ERR("deleting contact from database failed\n");
291                         }
292                         mem_delete_ucontact(_r, t);
293                         update_stat( _r->slot->d->expires, 1);
294                 } else {
295                         ptr = ptr->next;
296                 }
297         }
298 }
299
300
301 /*!
302  * \brief Write-back timer, used for WRITE_BACK db_mode
303  *
304  * Write-back timer, used for WRITE_BACK db_mode. Process
305  * all contacts from the record, delete expired ones from the DB.
306  * Furthermore it updates changed contacts, and also insert new
307  * ones in the DB.
308  * \param _r processed record
309  */
310 static inline void wb_timer(urecord_t* _r)
311 {
312         ucontact_t* ptr, *t;
313         cstate_t old_state;
314         int op;
315
316         ptr = _r->contacts;
317
318         while(ptr) {
319                 if (!VALID_CONTACT(ptr, act_time)) {
320                         /* run callbacks for EXPIRE event */
321                         if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
322                                 run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
323                         }
324
325                         LM_DBG("Binding '%.*s','%.*s' has expired\n",
326                                 ptr->aor->len, ZSW(ptr->aor->s),
327                                 ptr->c.len, ZSW(ptr->c.s));
328                         update_stat( _r->slot->d->expires, 1);
329
330                         t = ptr;
331                         ptr = ptr->next;
332
333                         /* Should we remove the contact from the database ? */
334                         if (st_expired_ucontact(t) == 1) {
335                                 if (db_delete_ucontact(t) < 0) {
336                                         LM_ERR("failed to delete contact from the database\n");
337                                 }
338                         }
339
340                         mem_delete_ucontact(_r, t);
341                 } else {
342                         /* Determine the operation we have to do */
343                         old_state = ptr->state;
344                         op = st_flush_ucontact(ptr);
345
346                         switch(op) {
347                         case 0: /* do nothing, contact is synchronized */
348                                 break;
349
350                         case 1: /* insert */
351                                 if (db_insert_ucontact(ptr) < 0) {
352                                         LM_ERR("inserting contact into database failed\n");
353                                         ptr->state = old_state;
354                                 }
355                                 break;
356
357                         case 2: /* update */
358                                 if (db_update_ucontact(ptr) < 0) {
359                                         LM_ERR("updating contact in db failed\n");
360                                         ptr->state = old_state;
361                                 }
362                                 break;
363                         }
364
365                         ptr = ptr->next;
366                 }
367         }
368 }
369
370
371 /*!
372  * \brief Run timer functions depending on the db_mode setting.
373  *
374  * Helper function that run the appropriate timer function, depending
375  * on the db_mode setting.
376  * \param _r processed record
377  */
378 void timer_urecord(urecord_t* _r)
379 {
380         switch(db_mode) {
381         case NO_DB:         nodb_timer(_r);
382                                                 break;
383         /* use also the write_back timer routine to handle the failed
384          * realtime inserts/updates */
385         case WRITE_THROUGH: wb_timer(_r); /*wt_timer(_r);*/
386                                                 break;
387         case WRITE_BACK:    wb_timer(_r);
388                                                 break;
389         }
390 }
391
392
393 /*!
394  * \brief Delete a record from the database
395  * \param _r deleted record
396  * \return 0 on success, -1 on failure
397  */
398 int db_delete_urecord(udomain_t* _d, urecord_t* _r)
399 {
400         db_key_t keys[2];
401         db_val_t vals[2];
402         char* dom;
403
404         keys[0] = &user_col;
405         keys[1] = &domain_col;
406         vals[0].type = DB1_STR;
407         vals[0].nul = 0;
408         vals[0].val.str_val.s = _r->aor.s;
409         vals[0].val.str_val.len = _r->aor.len;
410
411         if (use_domain) {
412                 dom = memchr(_r->aor.s, '@', _r->aor.len);
413                 vals[0].val.str_val.len = dom - _r->aor.s;
414
415                 vals[1].type = DB1_STR;
416                 vals[1].nul = 0;
417                 vals[1].val.str_val.s = dom + 1;
418                 vals[1].val.str_val.len = _r->aor.s + _r->aor.len - dom - 1;
419         }
420
421         if (ul_db_layer_delete(_d, &vals[0].val.str_val, &vals[1].val.str_val, keys, 0, vals, (use_domain) ? (2) : (1)) < 0) {
422                 return -1;
423         }
424
425         return 0;
426 }
427
428
429 /*!
430  * \brief Release urecord previously obtained through get_urecord
431  * \warning Failing to calls this function after get_urecord will
432  * result in a memory leak when the DB_ONLY mode is used. When
433  * the records is later deleted, e.g. with delete_urecord, then
434  * its not necessary, as this function already releases the record.
435  * \param _r released record
436  */
437 void release_urecord(urecord_t* _r)
438 {
439         if (db_mode==DB_ONLY) {
440                 free_urecord(_r);
441         } else if (_r->contacts == 0) {
442                 mem_delete_urecord(_r->slot->d, _r);
443         }
444 }
445
446
447 /*!
448  * \brief Create and insert new contact into urecord
449  * \param _r record into the new contact should be inserted
450  * \param _contact contact string
451  * \param _ci contact information
452  * \param _c new created contact
453  * \return 0 on success, -1 on failure
454  */
455 int insert_ucontact(urecord_t* _r, str* _contact, ucontact_info_t* _ci,
456                                                                                                                         ucontact_t** _c)
457 {
458         if ( ((*_c)=mem_insert_ucontact(_r, _contact, _ci)) == 0) {
459                 LM_ERR("failed to insert contact\n");
460                 return -1;
461         }
462
463         if (exists_ulcb_type(UL_CONTACT_INSERT)) {
464                 run_ul_callbacks( UL_CONTACT_INSERT, *_c);
465         }
466
467         if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
468                 if (db_insert_ucontact(*_c) < 0) {
469                         LM_ERR("failed to insert in database\n");
470                         return -1;
471                 } else {
472                         (*_c)->state = CS_SYNC;
473                 }
474         }
475
476         return 0;
477 }
478
479
480 /*!
481  * \brief Delete ucontact from urecord
482  * \param _r record where the contact belongs to
483  * \param _c deleted contact
484  * \return 0 on success, -1 on failure
485  */
486 int delete_ucontact(urecord_t* _r, struct ucontact* _c)
487 {
488         int ret = 0;
489
490         if (exists_ulcb_type(UL_CONTACT_DELETE)) {
491                 run_ul_callbacks( UL_CONTACT_DELETE, _c);
492         }
493
494         if (st_delete_ucontact(_c) > 0) {
495                 if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
496                         if (db_delete_ucontact(_c) < 0) {
497                                 LM_ERR("failed to remove contact from database\n");
498                                 ret = -1;
499                         }
500                 }
501
502                 mem_delete_ucontact(_r, _c);
503         }
504
505         return ret;
506 }
507
508
509 /*!
510  * \brief Match a contact record to a contact string
511  * \param ptr contact record
512  * \param _c contact string
513  * \return ptr on successfull match, 0 when they not match
514  */
515 static inline struct ucontact* contact_match( ucontact_t* ptr, str* _c)
516 {
517         while(ptr) {
518                 if ((_c->len == ptr->c.len) && !memcmp(_c->s, ptr->c.s, _c->len)) {
519                         return ptr;
520                 }
521                 
522                 ptr = ptr->next;
523         }
524         return 0;
525 }
526
527
528 /*!
529  * \brief Match a contact record to a contact string and callid
530  * \param ptr contact record
531  * \param _c contact string
532  * \param _callid callid
533  * \return ptr on successfull match, 0 when they not match
534  */
535 static inline struct ucontact* contact_callid_match( ucontact_t* ptr,
536                                                                                                                 str* _c, str *_callid)
537 {
538         while(ptr) {
539                 if ( (_c->len==ptr->c.len) && (_callid->len==ptr->callid.len)
540                 && !memcmp(_c->s, ptr->c.s, _c->len)
541                 && !memcmp(_callid->s, ptr->callid.s, _callid->len)
542                 ) {
543                         return ptr;
544                 }
545                 
546                 ptr = ptr->next;
547         }
548         return 0;
549 }
550
551
552  /*!
553 + * \brief Match a contact record to a contact string and path
554 + * \param ptr contact record
555 + * \param _c contact string
556 + * \param _path path
557 + * \return ptr on successfull match, 0 when they not match
558 + */
559 static inline struct ucontact* contact_path_match( ucontact_t* ptr, str* _c, str *_path)
560 {
561         /* if no path is preset (in REGISTER request) or use_path is not configured
562            in registrar module, default to contact_match() */
563         if( _path == NULL) return contact_match(ptr, _c);
564
565         while(ptr) {
566                 if ( (_c->len==ptr->c.len) && (_path->len==ptr->path.len)
567                 && !memcmp(_c->s, ptr->c.s, _c->len)
568                 && !memcmp(_path->s, ptr->path.s, _path->len)
569                 ) {
570                         return ptr;
571                 }
572
573                 ptr = ptr->next;
574         }
575         return 0;
576 }
577
578 /*!
579  * \brief Get pointer to ucontact with given contact
580  * \param _r record where to search the contacts
581  * \param _c contact string
582  * \param _callid callid
583  * \param _cseq CSEQ number
584  * \param _co found contact
585  * \return 0 - found, 1 - not found, -1 - invalid found, 
586  * -2 - found, but to be skipped (same cseq)
587  */
588 int get_ucontact(urecord_t* _r, str* _c, str* _callid, str* _path, int _cseq,
589                                         struct ucontact** _co)
590 {
591         ucontact_t* ptr;
592         int no_callid;
593
594         ptr = 0;
595         no_callid = 0;
596         *_co = 0;
597
598         switch (matching_mode) {
599                 case CONTACT_ONLY:
600                         ptr = contact_match( _r->contacts, _c);
601                         break;
602                 case CONTACT_CALLID:
603                         ptr = contact_callid_match( _r->contacts, _c, _callid);
604                         no_callid = 1;
605                         break;
606                 case CONTACT_PATH:
607                         ptr = contact_path_match( _r->contacts, _c, _path);
608                         break;
609                 default:
610                         LM_CRIT("unknown matching_mode %d\n", matching_mode);
611                         return -1;
612         }
613
614         if (ptr) {
615                 /* found -> check callid and cseq */
616                 if ( no_callid || (ptr->callid.len==_callid->len
617                 && memcmp(_callid->s, ptr->callid.s, _callid->len)==0 ) ) {
618                         if (_cseq<ptr->cseq)
619                                 return -1;
620                         if (_cseq==ptr->cseq) {
621                                 get_act_time();
622                                 return (ptr->last_modified+cseq_delay>act_time)?-2:-1;
623                         }
624                 }
625                 *_co = ptr;
626                 return 0;
627         }
628
629         return 1;
630 }
631
632
633 /*
634  * Get pointer to ucontact with given info (by address or sip.instance)
635  */
636 int get_ucontact_by_instance(urecord_t* _r, str* _c, ucontact_info_t* _ci,
637                 ucontact_t** _co)
638 {
639         ucontact_t* ptr;
640         str i1;
641         str i2;
642         
643         if (_ci->instance.s == NULL || _ci->instance.len <= 0) {
644                 return get_ucontact(_r, _c, _ci->callid, _ci->path, _ci->cseq, _co);
645         }
646
647         /* find by instance */
648         ptr = _r->contacts;
649         while(ptr) {
650                 if (ptr->instance.len>0 && _ci->reg_id==ptr->reg_id)
651                 {
652                         i1 = _ci->instance;
653                         i2 = ptr->instance;
654                         if(i1.s[0]=='<' && i1.s[i1.len-1]=='>') {
655                                 i1.s++;
656                                 i1.len-=2;
657                         }
658                         if(i2.s[0]=='<' && i2.s[i2.len-1]=='>') {
659                                 i2.s++;
660                                 i2.len-=2;
661                         }
662                         if(i1.len==i2.len && memcmp(i1.s, i2.s, i2.len)==0) {
663                                 *_co = ptr;
664                                 return 0;
665                         }
666                 }
667                 
668                 ptr = ptr->next;
669         }
670         return 1;
671 }
672
673 unsigned int ul_get_aorhash(str *_aor)
674 {
675         return core_hash(_aor, 0, 0);
676 }