2 * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
4 * This file is part of kamailio, a free SIP server.
6 * Kamailio is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version
11 * Kamailio is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * \brief Kamailio uac :: The SIP UA registration client module
30 #include "../../core/dprint.h"
31 #include "../../core/timer.h"
33 #include "../../core/mem/shm_mem.h"
34 #include "../../lib/srdb1/db.h"
35 #include "../../core/ut.h"
36 #include "../../core/trim.h"
37 #include "../../core/hashes.h"
38 #include "../../core/locking.h"
39 #include "../../core/parser/parse_uri.h"
40 #include "../../core/parser/parse_from.h"
41 #include "../../core/parser/parse_to.h"
42 #include "../../core/parser/parse_expires.h"
43 #include "../../core/parser/contact/parse_contact.h"
44 #include "../../core/rpc.h"
45 #include "../../core/rpc_lookup.h"
46 #include "../../core/rand/kam_rand.h"
48 #include "../../modules/tm/tm_load.h"
54 #define UAC_REG_DISABLED (1<<0) /* registration disabled */
55 #define UAC_REG_ONGOING (1<<1) /* registration on progress */
56 #define UAC_REG_ONLINE (1<<2) /* registered */
57 #define UAC_REG_AUTHSENT (1<<3) /* registration with auth in progress */
58 #define UAC_REG_INIT (1<<4) /* registration initialized */
60 #define MAX_UACH_SIZE 2048
61 #define UAC_REG_GC_INTERVAL 150
62 #define UAC_REG_TM_CALLID_SIZE 90
64 typedef struct _reg_uac
82 unsigned int reg_delay;
87 typedef struct _reg_item
90 struct _reg_item *next;
94 typedef struct _reg_entry
103 typedef struct _reg_ht
107 reg_entry_t *entries;
110 static reg_ht_t *_reg_htable = NULL;
111 static reg_ht_t *_reg_htable_gc = NULL;
112 static gen_lock_t *_reg_htable_gc_lock = NULL;
114 int reg_use_domain = 0;
115 int reg_timer_interval = 90;
116 int reg_retry_interval = 0;
117 int reg_htable_size = 4;
118 int reg_fetch_rows = 1000;
119 int reg_keep_callid = 0;
120 int reg_random_delay = 0;
121 int *reg_active = NULL;
122 str reg_contact_addr = STR_NULL;
123 str reg_db_url = STR_NULL;
124 str reg_db_table = str_init("uacreg");
126 str l_uuid_column = str_init("l_uuid");
127 str l_username_column = str_init("l_username");
128 str l_domain_column = str_init("l_domain");
129 str r_username_column = str_init("r_username");
130 str r_domain_column = str_init("r_domain");
131 str realm_column = str_init("realm");
132 str auth_username_column = str_init("auth_username");
133 str auth_password_column = str_init("auth_password");
134 str auth_proxy_column = str_init("auth_proxy");
135 str expires_column = str_init("expires");
136 str flags_column = str_init("flags");
137 str reg_delay_column = str_init("reg_delay");
139 str str_empty = str_init("");
142 INSERT INTO version (table_name, table_version) values ('uacreg','1');
143 CREATE TABLE uacreg (
144 id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
145 l_uuid VARCHAR(64) NOT NULL,
146 l_username VARCHAR(64) NOT NULL,
147 l_domain VARCHAR(128) DEFAULT '' NOT NULL,
148 r_username VARCHAR(64) NOT NULL,
149 r_domain VARCHAR(128) NOT NULL,
150 realm VARCHAR(64) NOT NULL,
151 auth_username VARCHAR(64) NOT NULL,
152 auth_password VARCHAR(64) NOT NULL,
153 auth_proxy VARCHAR(128) DEFAULT '' NOT NULL,
154 expires INT(10) UNSIGNED DEFAULT 0 NOT NULL,
155 flags INT(10) UNSIGNED DEFAULT 0 NOT NULL,
156 reg_delay INT(10) UNSIGNED DEFAULT 0 NOT NULL,
157 CONSTRAINT l_uuid_idx UNIQUE (l_uuid)
162 extern struct tm_binds uac_tmb;
163 extern pv_spec_t auth_username_spec;
164 extern pv_spec_t auth_realm_spec;
165 extern pv_spec_t auth_password_spec;
167 counter_handle_t regtotal; /* Total number of registrations in memory */
168 counter_handle_t regactive; /* Active registrations - 200 OK */
169 counter_handle_t regdisabled; /* Disabled registrations */
171 /* Init reg active mode */
172 int reg_active_init(int mode)
174 if(reg_active!=NULL) {
175 /* already allocated */
179 reg_active = (int*)shm_malloc(sizeof(int));
180 if(reg_active==NULL) {
181 LM_ERR("not enough shared memory\n");
189 static void uac_reg_counter_init()
191 LM_DBG("*** Initializing UAC reg counters\n");
192 counter_register(®total, "uac", "regtotal", 0, 0, 0, "Total number of registration accounts in memory", 0);
193 counter_register(®active, "uac", "regactive", 0, 0, 0, "Number of successfully registered accounts (200 OK)", 0);
194 counter_register(®disabled, "uac", "regdisabled", 0, 0, 0, "Counter of failed registrations (not 200 OK)", 0);
199 * Init the in-memory registration database in hash table
201 int uac_reg_init_ht(unsigned int sz)
205 _reg_htable_gc_lock = (gen_lock_t*)shm_malloc(sizeof(gen_lock_t));
206 if(_reg_htable_gc_lock == NULL)
208 LM_ERR("no more shm for lock\n");
211 if(lock_init(_reg_htable_gc_lock)==0)
213 LM_ERR("cannot init global lock\n");
214 shm_free((void*)_reg_htable_gc_lock);
217 _reg_htable_gc = (reg_ht_t*)shm_malloc(sizeof(reg_ht_t));
218 if(_reg_htable_gc==NULL)
220 LM_ERR("no more shm\n");
221 lock_destroy(_reg_htable_gc_lock);
222 shm_free((void*)_reg_htable_gc_lock);
225 memset(_reg_htable_gc, 0, sizeof(reg_ht_t));
226 _reg_htable_gc->htsize = sz;
228 _reg_htable_gc->entries =
229 (reg_entry_t*)shm_malloc(_reg_htable_gc->htsize*sizeof(reg_entry_t));
230 if(_reg_htable_gc->entries==NULL)
232 LM_ERR("no more shm.\n");
233 shm_free(_reg_htable_gc);
234 lock_destroy(_reg_htable_gc_lock);
235 shm_free((void*)_reg_htable_gc_lock);
238 memset(_reg_htable_gc->entries, 0, _reg_htable_gc->htsize*sizeof(reg_entry_t));
241 _reg_htable = (reg_ht_t*)shm_malloc(sizeof(reg_ht_t));
242 if(_reg_htable==NULL)
244 LM_ERR("no more shm\n");
245 shm_free(_reg_htable_gc->entries);
246 shm_free(_reg_htable_gc);
247 lock_destroy(_reg_htable_gc_lock);
248 shm_free((void*)_reg_htable_gc_lock);
251 memset(_reg_htable, 0, sizeof(reg_ht_t));
252 _reg_htable->htsize = sz;
254 _reg_htable->entries =
255 (reg_entry_t*)shm_malloc(_reg_htable->htsize*sizeof(reg_entry_t));
256 if(_reg_htable->entries==NULL)
258 LM_ERR("no more shm.\n");
259 shm_free(_reg_htable_gc->entries);
260 shm_free(_reg_htable_gc);
261 shm_free(_reg_htable);
262 lock_destroy(_reg_htable_gc_lock);
263 shm_free((void*)_reg_htable_gc_lock);
266 memset(_reg_htable->entries, 0, _reg_htable->htsize*sizeof(reg_entry_t));
267 for(i=0; i<_reg_htable->htsize; i++)
269 if(lock_init(&_reg_htable->entries[i].lock)==0)
271 LM_ERR("cannot initialize lock[%d] n", i);
275 lock_destroy(&_reg_htable->entries[i].lock);
278 shm_free(_reg_htable->entries);
279 shm_free(_reg_htable);
280 shm_free(_reg_htable_gc->entries);
281 shm_free(_reg_htable_gc);
282 lock_destroy(_reg_htable_gc_lock);
283 shm_free((void*)_reg_htable_gc_lock);
288 /* Initialize uac reg counters */
289 uac_reg_counter_init();
297 int uac_reg_free_ht(void)
300 reg_item_t *it = NULL;
301 reg_item_t *it0 = NULL;
303 if(_reg_htable_gc_lock != NULL)
305 lock_destroy(_reg_htable_gc_lock);
306 shm_free((void*)_reg_htable_gc_lock);
307 _reg_htable_gc_lock = NULL;
309 if(_reg_htable_gc!=NULL)
311 for(i=0; i<_reg_htable_gc->htsize; i++)
313 it = _reg_htable_gc->entries[i].byuuid;
320 it = _reg_htable_gc->entries[i].byuser;
329 shm_free(_reg_htable_gc->entries);
330 shm_free(_reg_htable_gc);
331 _reg_htable_gc = NULL;
334 if(_reg_htable==NULL)
336 LM_DBG("no hash table\n");
339 for(i=0; i<_reg_htable->htsize; i++)
341 lock_get(&_reg_htable->entries[i].lock);
343 it = _reg_htable->entries[i].byuuid;
350 it = _reg_htable->entries[i].byuser;
358 lock_destroy(&_reg_htable->entries[i].lock);
360 shm_free(_reg_htable->entries);
361 shm_free(_reg_htable);
369 int uac_reg_reset_ht_gc(void)
372 reg_item_t *it = NULL;
373 reg_item_t *it0 = NULL;
375 if(_reg_htable_gc==NULL)
377 LM_DBG("no hash table\n");
380 for(i=0; i<_reg_htable_gc->htsize; i++)
383 it = _reg_htable_gc->entries[i].byuuid;
390 _reg_htable_gc->entries[i].byuuid = NULL;
391 _reg_htable_gc->entries[i].isize=0;
392 it = _reg_htable_gc->entries[i].byuser;
400 _reg_htable_gc->entries[i].byuser = NULL;
401 _reg_htable_gc->entries[i].usize = 0;
403 /* Reset all counters */
404 counter_reset(regtotal);
405 counter_reset(regactive);
406 counter_reset(regdisabled);
413 int uac_reg_ht_shift(void)
418 if(_reg_htable==NULL || _reg_htable_gc==NULL)
420 LM_ERR("data struct invalid\n");
425 lock_get(_reg_htable_gc_lock);
426 if(_reg_htable_gc->stime > tn-UAC_REG_GC_INTERVAL) {
427 lock_release(_reg_htable_gc_lock);
428 LM_ERR("shifting the memory table is not possible in less than %d secs\n", UAC_REG_GC_INTERVAL);
431 uac_reg_reset_ht_gc();
432 for(i=0; i<_reg_htable->htsize; i++)
435 _reg_htable_gc->entries[i].byuuid = _reg_htable->entries[i].byuuid;
436 _reg_htable_gc->entries[i].byuser = _reg_htable->entries[i].byuser;
437 _reg_htable_gc->stime = time(NULL);
439 /* reset active table entries */
440 _reg_htable->entries[i].byuuid = NULL;
441 _reg_htable->entries[i].isize=0;
442 _reg_htable->entries[i].byuser = NULL;
443 _reg_htable->entries[i].usize = 0;
445 lock_release(_reg_htable_gc_lock);
449 #define reg_compute_hash(_s) get_hash1_raw((_s)->s,(_s)->len)
450 #define reg_get_entry(_h,_size) ((_h)&((_size)-1))
455 int reg_ht_add_byuuid(reg_uac_t *reg)
458 reg_item_t *ri = NULL;
460 if(_reg_htable==NULL)
462 LM_ERR("reg hash table not initialized\n");
466 ri = (reg_item_t*)shm_malloc(sizeof(reg_item_t));
469 LM_ERR("no more shm\n");
472 memset(ri, 0, sizeof(reg_item_t));
473 slot = reg_get_entry(reg->h_uuid, _reg_htable->htsize);
475 lock_get(&_reg_htable->entries[slot].lock);
476 ri->next = _reg_htable->entries[slot].byuuid;
477 _reg_htable->entries[slot].byuuid = ri;
478 _reg_htable->entries[slot].isize++;
479 lock_release(&_reg_htable->entries[slot].lock);
486 int reg_ht_add_byuser(reg_uac_t *reg)
489 reg_item_t *ri = NULL;
491 if(_reg_htable==NULL)
493 LM_ERR("reg hash table not initialized\n");
497 ri = (reg_item_t*)shm_malloc(sizeof(reg_item_t));
500 LM_ERR("no more shm\n");
503 memset(ri, 0, sizeof(reg_item_t));
504 slot = reg_get_entry(reg->h_user, _reg_htable->htsize);
506 lock_get(&_reg_htable->entries[slot].lock);
507 ri->next = _reg_htable->entries[slot].byuser;
508 _reg_htable->entries[slot].byuser = ri;
509 _reg_htable->entries[slot].usize++;
510 lock_release(&_reg_htable->entries[slot].lock);
514 #define reg_copy_shm(dst, src, bsize) do { \
515 if((src)->s!=NULL) { \
517 strncpy((dst)->s, (src)->s, (src)->len); \
518 (dst)->len = (src)->len; \
519 (dst)->s[(dst)->len] = '\0'; \
520 p = p + ((bsize)!=0?(bsize):(dst)->len) + 1; \
527 int reg_ht_add(reg_uac_t *reg)
530 reg_uac_t *nr = NULL;
533 if(reg==NULL || _reg_htable==NULL)
535 LM_ERR("bad parameters: %p/%p\n", reg, _reg_htable);
538 len = reg->l_uuid.len + 1
539 + reg->l_username.len + 1
540 + reg->l_domain.len + 1
541 + reg->r_username.len + 1
542 + reg->r_domain.len + 1
544 + reg->auth_proxy.len + 1
545 + reg->auth_username.len + 1
546 + reg->auth_password.len + 1
547 + (reg_keep_callid ? UAC_REG_TM_CALLID_SIZE : 0) + 1;
548 nr = (reg_uac_t*)shm_malloc(sizeof(reg_uac_t) + len);
551 LM_ERR("no more shm\n");
554 memset(nr, 0, sizeof(reg_uac_t) + len);
555 nr->expires = reg->expires;
556 nr->flags = reg->flags;
558 nr->reg_delay = reg->reg_delay;
559 else if (reg_random_delay>0)
560 nr->reg_delay = kam_rand() % reg_random_delay;
561 nr->reg_init = time(NULL);
562 nr->h_uuid = reg_compute_hash(®->l_uuid);
563 nr->h_user = reg_compute_hash(®->l_username);
565 p = (char*)nr + sizeof(reg_uac_t);
567 reg_copy_shm(&nr->l_uuid, ®->l_uuid, 0);
568 reg_copy_shm(&nr->l_username, ®->l_username, 0);
569 reg_copy_shm(&nr->l_domain, ®->l_domain, 0);
570 reg_copy_shm(&nr->r_username, ®->r_username, 0);
571 reg_copy_shm(&nr->r_domain, ®->r_domain, 0);
572 reg_copy_shm(&nr->realm, ®->realm, 0);
573 reg_copy_shm(&nr->auth_proxy, ®->auth_proxy, 0);
574 reg_copy_shm(&nr->auth_username, ®->auth_username, 0);
575 reg_copy_shm(&nr->auth_password, ®->auth_password, 0);
576 reg_copy_shm(&nr->callid, &str_empty, reg_keep_callid ? UAC_REG_TM_CALLID_SIZE : 0);
578 reg_ht_add_byuser(nr);
579 reg_ht_add_byuuid(nr);
580 counter_inc(regtotal);
582 LM_DBG("added uuid: %.*s - l_user: %.*s\n", nr->l_uuid.len, nr->l_uuid.s,
583 nr->l_username.len, nr->l_username.s);
591 int reg_ht_rm(reg_uac_t *reg)
593 unsigned int slot1, slot2;
594 reg_item_t *it = NULL;
595 reg_item_t *prev = NULL;
600 LM_ERR("bad parameter\n");
605 slot1 = reg_get_entry(reg->h_uuid, _reg_htable->htsize);
606 it = _reg_htable->entries[slot1].byuuid;
614 _reg_htable->entries[slot1].byuuid = it->next;
615 _reg_htable->entries[slot1].isize--;
626 slot2 = reg_get_entry(reg->h_user, _reg_htable->htsize);
627 if (slot2 != slot1) {
628 lock_get(&_reg_htable->entries[slot2].lock);
630 it = _reg_htable->entries[slot2].byuser;
638 _reg_htable->entries[slot2].byuser = it->next;
639 _reg_htable->entries[slot2].usize--;
648 if (slot2 != slot1) {
649 lock_release(&_reg_htable->entries[slot2].lock);
651 lock_release(&_reg_htable->entries[slot1].lock);
654 counter_add(regtotal, -1);
655 if(reg->flags & UAC_REG_ONLINE)
656 counter_add(regactive, -1);
657 if(reg->flags & UAC_REG_DISABLED)
658 counter_add(regdisabled, -1);
664 reg_uac_t *reg_ht_get_byuuid(str *uuid)
668 reg_item_t *it = NULL;
670 if(_reg_htable==NULL)
672 LM_ERR("reg hash table not initialized\n");
676 hash = reg_compute_hash(uuid);
677 slot = reg_get_entry(hash, _reg_htable->htsize);
678 lock_get(&_reg_htable->entries[slot].lock);
679 it = _reg_htable->entries[slot].byuuid;
682 if((it->r->h_uuid==hash) && (it->r->l_uuid.len==uuid->len)
683 && (strncmp(it->r->l_uuid.s, uuid->s, uuid->len)==0))
685 it->r->lock = &_reg_htable->entries[slot].lock;
690 lock_release(&_reg_htable->entries[slot].lock);
697 reg_uac_t *reg_ht_get_byuser(str *user, str *domain)
701 reg_item_t *it = NULL;
703 if(_reg_htable==NULL)
705 LM_ERR("reg hash table not initialized\n");
709 hash = reg_compute_hash(user);
710 slot = reg_get_entry(hash, _reg_htable->htsize);
711 lock_get(&_reg_htable->entries[slot].lock);
712 it = _reg_htable->entries[slot].byuser;
715 if((it->r->h_user==hash) && (it->r->l_username.len==user->len)
716 && (strncmp(it->r->l_username.s, user->s, user->len)==0))
718 if(domain!=NULL && domain->s!=NULL)
720 if((it->r->l_domain.len==domain->len)
721 && (strncmp(it->r->l_domain.s, domain->s, domain->len)==0))
723 it->r->lock = &_reg_htable->entries[slot].lock;
727 it->r->lock = &_reg_htable->entries[slot].lock;
733 lock_release(&_reg_htable->entries[slot].lock);
737 int reg_ht_get_byfilter(reg_uac_t **reg, str *attr, str *val)
743 /* try to use the hash table indices */
744 if(attr->len==6 && strncmp(attr->s, "l_uuid", 6)==0) {
745 *reg = reg_ht_get_byuuid(val);
748 if(attr->len==10 && strncmp(attr->s, "l_username", 10)==0) {
749 *reg = reg_ht_get_byuser(val, NULL);
753 /* check _all_ records */
754 for(i=0; i<_reg_htable->htsize; i++)
756 lock_get(&_reg_htable->entries[i].lock);
757 /* walk through entries */
758 it = _reg_htable->entries[i].byuuid;
761 if(attr->len==10 && strncmp(attr->s, "r_username", 10)==0) {
762 rval = &it->r->r_username;
763 } else if(attr->len==13 && strncmp(attr->s, "auth_username", 13)==0) {
764 rval = &it->r->auth_username;
766 lock_release(&_reg_htable->entries[i].lock);
767 LM_ERR("unsupported filter attribute %.*s\n", attr->len, attr->s);
771 if(rval->len==val->len && strncmp(val->s, rval->s, val->len)==0) {
774 (*reg)->lock = &_reg_htable->entries[i].lock;
779 lock_release(&_reg_htable->entries[i].lock);
785 int uac_reg_tmdlg(dlg_t *tmdlg, sip_msg_t *rpl)
787 if(tmdlg==NULL || rpl==NULL)
790 if (parse_headers(rpl, HDR_EOH_F, 0) < 0) {
791 LM_ERR("error while parsing all headers in the reply\n");
794 if(parse_to_header(rpl)<0 || parse_from_header(rpl)<0) {
795 LM_ERR("error while parsing From/To headers in the reply\n");
798 memset(tmdlg, 0, sizeof(dlg_t));
800 str2int(&(get_cseq(rpl)->number), &tmdlg->loc_seq.value);
801 tmdlg->loc_seq.is_set = 1;
803 tmdlg->id.call_id = rpl->callid->body;
804 trim(&tmdlg->id.call_id);
806 if (get_from(rpl)->tag_value.len) {
807 tmdlg->id.loc_tag = get_from(rpl)->tag_value;
810 if (get_to(rpl)->tag_value.len) {
811 tmdlg->id.rem_tag = get_to(rpl)->tag_value;
814 tmdlg->loc_uri = get_from(rpl)->uri;
815 tmdlg->rem_uri = get_to(rpl)->uri;
816 tmdlg->state= DLG_CONFIRMED;
820 void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
824 reg_uac_t *ri = NULL;
828 struct hdr_field *hdr;
830 str *new_auth_hdr = NULL;
831 static struct authenticate_body auth;
832 struct uac_credential cred;
833 char b_ruri[MAX_URI_SIZE];
836 char b_turi[MAX_URI_SIZE];
839 char b_hdrs[MAX_UACH_SIZE];
842 str method = {"REGISTER", 8};
846 if(ps->param==NULL || *ps->param==0)
848 LM_DBG("uuid not received\n");
851 uuid = *((char**)ps->param);
852 LM_DBG("completed with status %d [uuid: %s]\n",
855 suuid.len = strlen(suuid.s);
856 ri = reg_ht_get_byuuid(&suuid);
860 LM_DBG("no user with uuid %s\n", uuid);
866 if (parse_headers(ps->rpl, HDR_EOH_F, 0) == -1)
868 LM_ERR("failed to parse headers\n");
871 if (ps->rpl->contact==NULL)
873 LM_ERR("no Contact found\n");
876 if (parse_contact(ps->rpl->contact) < 0)
878 LM_ERR("failed to parse Contact HF\n");
881 if (((contact_body_t*)ps->rpl->contact->parsed)->star)
883 LM_DBG("* Contact found\n");
887 if (contact_iterator(&c, ps->rpl, 0) < 0)
891 if(parse_uri(c->uri.s, c->uri.len, &puri)!=0)
893 LM_ERR("failed to parse c-uri\n");
896 if(suuid.len==puri.user.len
897 && (strncmp(puri.user.s, suuid.s, suuid.len)==0))
899 /* calculate expires */
901 if(c->expires==NULL || c->expires->body.len<=0)
903 if(ps->rpl->expires!=NULL && parse_expires(ps->rpl->expires)==0)
904 expires = ((exp_body_t *)ps->rpl->expires->parsed)->val;
906 str2int(&c->expires->body, (unsigned int*)(&expires));
908 ri->timer_expires = ri->timer_expires + expires;
909 ri->flags |= UAC_REG_ONLINE;
910 if (reg_keep_callid && ps->rpl->callid->body.len < UAC_REG_TM_CALLID_SIZE) {
911 ri->callid.len = ps->rpl->callid->body.len;
912 memcpy(ri->callid.s, ps->rpl->callid->body.s, ri->callid.len);
913 str2int(&(get_cseq(ps->rpl)->number), &ri->cseq);
917 if (contact_iterator(&c, ps->rpl, c) < 0)
919 LM_DBG("local contact not found\n");
924 LM_DBG("sip response %d while registering [%.*s] with no match\n",
925 ps->code, ri->l_uuid.len, ri->l_uuid.s);
929 if(ps->code == 401 || ps->code == 407)
931 if(ri->flags & UAC_REG_AUTHSENT)
933 LM_ERR("authentication failed for <%.*s>\n",
934 ri->l_uuid.len, ri->l_uuid.s);
937 hdr = get_autenticate_hdr(ps->rpl, ps->code);
940 LM_ERR("failed to extract authenticate hdr\n");
944 LM_DBG("auth header body [%.*s]\n",
945 hdr->body.len, hdr->body.s);
947 if (parse_authenticate_body(&hdr->body, &auth)<0)
949 LM_ERR("failed to parse auth hdr body\n");
952 if (ri->realm.len>0) {
953 /* only check if realms match if it is non-empty */
954 if(auth.realm.len!=ri->realm.len
955 || strncmp(auth.realm.s, ri->realm.s, ri->realm.len)!=0)
957 LM_ERR("realms do not match. requested realm: [%.*s]\n",
958 auth.realm.len, auth.realm.s);
962 cred.realm = auth.realm;
963 cred.user = ri->auth_username;
964 cred.passwd = ri->auth_password;
967 snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s",
968 ri->r_domain.len, ri->r_domain.s);
969 s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s);
971 do_uac_auth(&method, &s_ruri, &cred, &auth, response);
972 new_auth_hdr=build_authorization_hdr(ps->code, &s_ruri, &cred,
976 LM_ERR("failed to build authorization hdr\n");
981 snprintf(b_turi, MAX_URI_SIZE, "sip:%.*s@%.*s",
982 ri->r_username.len, ri->r_username.s,
983 ri->r_domain.len, ri->r_domain.s);
984 s_turi.s = b_turi; s_turi.len = strlen(s_turi.s);
986 snprintf(b_hdrs, MAX_UACH_SIZE,
987 "Contact: <sip:%.*s@%.*s>\r\n"
990 ri->l_uuid.len, ri->l_uuid.s,
991 reg_contact_addr.len, reg_contact_addr.s,
993 new_auth_hdr->len, new_auth_hdr->s);
994 s_hdrs.s = b_hdrs; s_hdrs.len = strlen(s_hdrs.s);
995 pkg_free(new_auth_hdr->s);
997 memset(&uac_r, 0, sizeof(uac_r));
998 if(uac_reg_tmdlg(&tmdlg, ps->rpl)<0)
1000 LM_ERR("failed to build tm dialog\n");
1003 tmdlg.rem_target = s_ruri;
1004 if(ri->auth_proxy.len)
1005 tmdlg.dst_uri = ri->auth_proxy;
1006 uac_r.method = &method;
1007 uac_r.headers = &s_hdrs;
1008 uac_r.dialog = &tmdlg;
1009 uac_r.cb_flags = TMCB_LOCAL_COMPLETED;
1010 /* Callback function */
1011 uac_r.cb = uac_reg_tm_callback;
1012 /* Callback parameter */
1013 uac_r.cbp = (void*)uuid;
1015 ret = uac_tmb.t_request(&uac_r, /* UAC Req */
1016 &s_ruri, /* Request-URI */
1019 (ri->auth_proxy.len)?&ri->auth_proxy:NULL /* outbound uri */
1022 ret = uac_tmb.t_request_within(&uac_r);
1025 LM_ERR("failed to send request with authentication for [%.*s]",
1026 ri->l_uuid.len, ri->l_uuid.s);
1030 ri->flags |= UAC_REG_AUTHSENT;
1031 lock_release(ri->lock);
1035 if (ps->code == 423) /* Interval too brief, retry with longer expiry */
1037 if (parse_headers(ps->rpl, HDR_EOH_F, 0) == -1) {
1038 LM_ERR("failed to parse headers\n");
1041 if(ps->rpl->min_expires!=NULL && parse_expires(ps->rpl->min_expires)==0) {
1042 ri->expires = ((exp_body_t *)ps->rpl->min_expires->parsed)->val;
1046 LM_DBG("got 423 response while registering [%.*s], set new expires to %d\n",
1047 ri->l_uuid.len, ri->l_uuid.s, ri->expires);
1048 /* Retry will be done on next timer interval */
1052 LM_ERR("got sip response %d while registering [%.*s]\n",
1053 ps->code, ri->l_uuid.len, ri->l_uuid.s);
1058 if(reg_retry_interval) {
1059 ri->timer_expires = time(NULL) + reg_retry_interval;
1061 ri->flags |= UAC_REG_DISABLED;
1062 counter_inc(regdisabled);
1067 ri->flags &= ~(UAC_REG_ONGOING|UAC_REG_AUTHSENT);
1068 lock_release(ri->lock);
1071 counter_inc(regactive);
1074 int uac_reg_update(reg_uac_t *reg, time_t tn)
1078 str method = {"REGISTER", 8};
1080 char b_ruri[MAX_URI_SIZE];
1082 char b_turi[MAX_URI_SIZE];
1084 char b_hdrs[MAX_UACH_SIZE];
1088 if(uac_tmb.t_request==NULL)
1092 if(reg->flags&UAC_REG_ONGOING) {
1093 if (reg->timer_expires > tn - reg_retry_interval)
1095 LM_DBG("record marked as ongoing registration (%d) - resetting\n",
1097 reg->flags &= ~(UAC_REG_ONLINE|UAC_REG_AUTHSENT);
1099 if(reg_active && *reg_active == 0)
1101 if(reg->flags&UAC_REG_DISABLED)
1104 if(!(reg->flags & UAC_REG_INIT)) {
1105 if(reg->reg_delay>0) {
1106 if(tn < reg->reg_init+reg->reg_delay) {
1110 reg->flags |= UAC_REG_INIT;
1113 if(reg->timer_expires > tn + reg_timer_interval + 3)
1115 uuid = (char*)shm_malloc(reg->l_uuid.len+1);
1118 LM_ERR("no more shm\n");
1121 reg->timer_expires = tn;
1122 reg->flags |= UAC_REG_ONGOING;
1123 counter_add(regactive, -1); /* Take it out of the active pool while re-registering */
1124 memcpy(uuid, reg->l_uuid.s, reg->l_uuid.len);
1125 uuid[reg->l_uuid.len] = '\0';
1127 snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s",
1128 reg->r_domain.len, reg->r_domain.s);
1129 s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s);
1131 snprintf(b_turi, MAX_URI_SIZE, "sip:%.*s@%.*s",
1132 reg->r_username.len, reg->r_username.s,
1133 reg->r_domain.len, reg->r_domain.s);
1134 s_turi.s = b_turi; s_turi.len = strlen(s_turi.s);
1136 snprintf(b_hdrs, MAX_UACH_SIZE,
1137 "Contact: <sip:%.*s@%.*s>\r\n"
1139 reg->l_uuid.len, reg->l_uuid.s,
1140 reg_contact_addr.len, reg_contact_addr.s,
1142 s_hdrs.s = b_hdrs; s_hdrs.len = strlen(s_hdrs.s);
1144 memset(&uac_r, '\0', sizeof(uac_r));
1145 uac_r.method = &method;
1146 uac_r.headers = &s_hdrs;
1147 uac_r.cb_flags = TMCB_LOCAL_COMPLETED;
1148 /* Callback function */
1149 uac_r.cb = uac_reg_tm_callback;
1150 /* Callback parameter */
1151 uac_r.cbp = (void*)uuid;
1153 if (reg_keep_callid && reg->flags & UAC_REG_ONLINE
1154 && reg->cseq > 0 && reg->cseq < 2147483638
1155 && reg->callid.len > 0)
1157 /* reregister, reuse callid and cseq */
1158 memset(&tmdlg, 0, sizeof(dlg_t));
1159 tmdlg.id.call_id = reg->callid;
1160 tmdlg.loc_seq.value = reg->cseq;
1161 tmdlg.loc_seq.is_set = 1;
1162 tmdlg.rem_target = s_ruri;
1163 tmdlg.loc_uri = s_turi;
1164 tmdlg.rem_uri = s_turi;
1165 tmdlg.state= DLG_CONFIRMED;
1166 if(reg->auth_proxy.len)
1167 tmdlg.dst_uri = reg->auth_proxy;
1168 uac_r.dialog = &tmdlg;
1170 ret = uac_tmb.t_request_within(&uac_r);
1172 ret = uac_tmb.t_request(&uac_r, /* UAC Req */
1173 &s_ruri, /* Request-URI */
1176 (reg->auth_proxy.len)?®->auth_proxy:NULL /* outbound uri */
1179 reg->flags &= ~UAC_REG_ONLINE;
1183 LM_ERR("failed to send request for [%.*s]", reg->l_uuid.len, reg->l_uuid.s);
1185 if (reg_retry_interval)
1186 reg->timer_expires = (tn ? tn : time(NULL)) + reg_retry_interval;
1188 reg->flags |= UAC_REG_DISABLED;
1189 counter_inc(regdisabled);
1191 reg->flags &= ~UAC_REG_ONGOING;
1200 void uac_reg_timer(unsigned int ticks)
1203 reg_item_t *it = NULL;
1206 if(_reg_htable==NULL)
1210 for(i=0; i<_reg_htable->htsize; i++)
1212 /* walk through entries */
1213 lock_get(&_reg_htable->entries[i].lock);
1214 it = _reg_htable->entries[i].byuuid;
1217 uac_reg_update(it->r, tn);
1220 lock_release(&_reg_htable->entries[i].lock);
1223 if(_reg_htable_gc!=NULL)
1225 lock_get(_reg_htable_gc_lock);
1226 if(_reg_htable_gc->stime!=0
1227 && _reg_htable_gc->stime < tn - UAC_REG_GC_INTERVAL)
1228 uac_reg_reset_ht_gc();
1229 lock_release(_reg_htable_gc_lock);
1233 #define reg_db_set_attr(attr, pos) do { \
1234 if(!VAL_NULL(&RES_ROWS(db_res)[i].values[pos])) { \
1236 (char*)(RES_ROWS(db_res)[i].values[pos].val.string_val); \
1237 reg->attr.len = strlen(reg->attr.s); \
1238 if(reg->attr.len == 0) { \
1239 LM_ERR("empty value not allowed for column[%d]='%.*s' - ignoring record\n", \
1240 pos, db_cols[pos]->len, db_cols[pos]->s); \
1247 static inline int uac_reg_db_to_reg(reg_uac_t *reg, db1_res_t* db_res, int i, db_key_t *db_cols)
1249 memset(reg, 0, sizeof(reg_uac_t));;
1250 /* check for NULL values ?!?! */
1251 reg_db_set_attr(l_uuid, 0);
1252 reg_db_set_attr(l_username, 1);
1253 reg_db_set_attr(l_domain, 2);
1254 reg_db_set_attr(r_username, 3);
1255 reg_db_set_attr(r_domain, 4);
1256 /* realm may be empty */
1257 if(!VAL_NULL(&RES_ROWS(db_res)[i].values[5])) {
1258 reg->realm.s = (char*)(RES_ROWS(db_res)[i].values[5].val.string_val);
1259 reg->realm.len = strlen(reg->realm.s);
1261 reg_db_set_attr(auth_username, 6);
1262 reg_db_set_attr(auth_password, 7);
1263 reg_db_set_attr(auth_proxy, 8);
1264 reg->expires = (unsigned int)RES_ROWS(db_res)[i].values[9].val.int_val;
1265 reg->flags = (unsigned int)RES_ROWS(db_res)[i].values[10].val.int_val;
1266 reg->reg_delay = (unsigned int)RES_ROWS(db_res)[i].values[11].val.int_val;
1274 int uac_reg_load_db(void)
1276 db1_con_t *reg_db_con = NULL;
1279 db_key_t db_cols[12] = {
1286 &auth_username_column,
1287 &auth_password_column,
1293 db1_res_t* db_res = NULL;
1296 /* binding to db module */
1297 if(reg_db_url.s==NULL)
1299 LM_ERR("no db url\n");
1303 if(db_bind_mod(®_db_url, ®_dbf))
1305 LM_ERR("database module not found\n");
1309 if (!DB_CAPABILITY(reg_dbf, DB_CAP_ALL))
1311 LM_ERR("database module does not "
1312 "implement all functions needed by the module\n");
1316 /* open a connection with the database */
1317 reg_db_con = reg_dbf.init(®_db_url);
1318 if(reg_db_con==NULL)
1320 LM_ERR("failed to connect to the database\n");
1323 if (reg_dbf.use_table(reg_db_con, ®_db_table) < 0)
1325 LM_ERR("failed to use_table\n");
1329 if (DB_CAPABILITY(reg_dbf, DB_CAP_FETCH)) {
1330 if(reg_dbf.query(reg_db_con, 0, 0, 0, db_cols, 0, 12, 0, 0) < 0)
1332 LM_ERR("Error while querying db\n");
1335 if(reg_dbf.fetch_result(reg_db_con, &db_res, reg_fetch_rows)<0)
1337 LM_ERR("Error while fetching result\n");
1339 reg_dbf.free_result(reg_db_con, db_res);
1342 if(RES_ROW_N(db_res)==0)
1348 if((ret=reg_dbf.query(reg_db_con, NULL, NULL, NULL, db_cols,
1349 0, 12, 0, &db_res))!=0
1350 || RES_ROW_N(db_res)<=0 )
1352 reg_dbf.free_result(reg_db_con, db_res);
1363 for(i=0; i<RES_ROW_N(db_res); i++)
1365 if(uac_reg_db_to_reg(®, db_res, i, db_cols) < 0)
1367 if(reg_ht_add(®)<0)
1369 LM_ERR("Error adding reg to htable\n");
1373 if (DB_CAPABILITY(reg_dbf, DB_CAP_FETCH)) {
1374 if(reg_dbf.fetch_result(reg_db_con, &db_res, reg_fetch_rows)<0) {
1375 LM_ERR("Error while fetching!\n");
1377 reg_dbf.free_result(reg_db_con, db_res);
1383 } while(RES_ROW_N(db_res)>0);
1384 reg_dbf.free_result(reg_db_con, db_res);
1385 reg_dbf.close(reg_db_con);
1392 reg_dbf.free_result(reg_db_con, db_res);
1393 reg_dbf.close(reg_db_con);
1401 int uac_reg_db_refresh(str *pl_uuid)
1403 db1_con_t *reg_db_con = NULL;
1407 db_key_t db_cols[12] = {
1414 &auth_username_column,
1415 &auth_password_column,
1421 db_key_t db_keys[1] = {&l_uuid_column};
1422 db_val_t db_vals[1];
1424 db1_res_t* db_res = NULL;
1427 /* binding to db module */
1428 if(reg_db_url.s==NULL)
1430 LM_ERR("no db url\n");
1434 if(db_bind_mod(®_db_url, ®_dbf))
1436 LM_ERR("database module not found\n");
1440 if (!DB_CAPABILITY(reg_dbf, DB_CAP_ALL))
1442 LM_ERR("database module does not "
1443 "implement all functions needed by the module\n");
1447 /* open a connection with the database */
1448 reg_db_con = reg_dbf.init(®_db_url);
1449 if(reg_db_con==NULL)
1451 LM_ERR("failed to connect to the database\n");
1454 if (reg_dbf.use_table(reg_db_con, ®_db_table) < 0)
1456 LM_ERR("failed to use_table\n");
1460 db_vals[0].type = DB1_STR;
1462 db_vals[0].val.str_val.s = pl_uuid->s;
1463 db_vals[0].val.str_val.len = pl_uuid->len;
1465 if((ret=reg_dbf.query(reg_db_con, db_keys, NULL, db_vals, db_cols,
1466 1 /*nr keys*/, 12 /*nr cols*/, 0, &db_res))!=0
1467 || RES_ROW_N(db_res)<=0 )
1469 reg_dbf.free_result(reg_db_con, db_res);
1478 if (uac_reg_db_to_reg(®, db_res, 0, db_cols)==0)
1480 lock_get(_reg_htable_gc_lock);
1481 if((cur_reg=reg_ht_get_byuuid(pl_uuid))!=NULL)
1483 reg.flags |= (cur_reg->flags & (UAC_REG_ONGOING | UAC_REG_AUTHSENT));
1486 if(reg_ht_add(®)<0)
1488 lock_release(_reg_htable_gc_lock);
1489 LM_ERR("Error adding reg to htable\n");
1492 lock_release(_reg_htable_gc_lock);
1495 reg_dbf.free_result(reg_db_con, db_res);
1496 reg_dbf.close(reg_db_con);
1502 reg_dbf.free_result(reg_db_con, db_res);
1503 reg_dbf.close(reg_db_con);
1511 int uac_reg_refresh(sip_msg_t *msg, str *l_uuid)
1515 if(l_uuid==NULL || l_uuid->s==NULL || l_uuid->len<=0) {
1516 LM_ERR("invalid parameters\n");
1520 ret = uac_reg_db_refresh(l_uuid);
1522 LM_WARN("record not found: %.*s\n", l_uuid->len, l_uuid->s);
1525 LM_WARN("failed to refresh record: %.*s - check log messages\n",
1526 l_uuid->len, l_uuid->s);
1536 int uac_reg_lookup(struct sip_msg *msg, str *src, pv_spec_t *dst, int mode)
1538 char b_ruri[MAX_URI_SIZE];
1540 struct sip_uri puri;
1541 reg_uac_t *reg = NULL;
1546 LM_ERR("dst is not w/\n");
1551 reg = reg_ht_get_byuuid(src);
1554 LM_DBG("no uuid: %.*s\n", src->len, src->s);
1557 snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s@%.*s",
1558 reg->l_username.len, reg->l_username.s,
1559 reg->l_domain.len, reg->l_domain.s);
1560 s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s);
1562 if(parse_uri(src->s, src->len, &puri)!=0)
1564 LM_ERR("failed to parse uri\n");
1567 reg = reg_ht_get_byuser(&puri.user, (reg_use_domain)?&puri.host:NULL);
1570 LM_DBG("no user: %.*s\n", src->len, src->s);
1573 snprintf(b_ruri, MAX_URI_SIZE, "%.*s",
1574 reg->l_uuid.len, reg->l_uuid.s);
1575 s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s);
1577 lock_release(reg->lock);
1578 memset(&val, 0, sizeof(pv_value_t));
1579 val.flags |= PV_VAL_STR;
1581 if(pv_set_spec_value(msg, dst, 0, &val)!=0)
1590 int uac_reg_status(struct sip_msg *msg, str *src, int mode)
1592 struct sip_uri puri;
1593 reg_uac_t *reg = NULL;
1598 reg = reg_ht_get_byuuid(src);
1601 LM_DBG("no uuid: %.*s\n", src->len, src->s);
1605 if(parse_uri(src->s, src->len, &puri)!=0)
1607 LM_ERR("failed to parse uri\n");
1610 reg = reg_ht_get_byuser(&puri.user, (reg_use_domain)?&puri.host:NULL);
1613 LM_DBG("no user: %.*s\n", src->len, src->s);
1618 if ((reg->flags & UAC_REG_ONLINE) && (reg->timer_expires > time(NULL)))
1620 else if (reg->flags & UAC_REG_ONGOING)
1622 else if (reg->flags & UAC_REG_DISABLED)
1627 lock_release(reg->lock);
1634 int uac_reg_request_to(struct sip_msg *msg, str *src, unsigned int mode)
1636 char ruri[MAX_URI_SIZE];
1637 struct sip_uri puri;
1638 reg_uac_t *reg = NULL;
1641 struct run_act_ctx ra_ctx;
1646 reg = reg_ht_get_byuuid(src);
1651 if (parse_uri(src->s, src->len, &puri)!=0)
1653 LM_ERR("failed to parse uri\n");
1656 reg = reg_ht_get_byuser(&puri.user, &puri.host);
1658 reg = reg_ht_get_byuser(src, NULL);
1662 LM_ERR("unknown mode: %d\n", mode);
1668 LM_DBG("no user: %.*s\n", src->len, src->s);
1673 snprintf(ruri, MAX_URI_SIZE, "sip:%.*s@%.*s",
1674 reg->r_username.len, reg->r_username.s,
1675 reg->r_domain.len, reg->r_domain.s);
1676 memset(&act, 0, sizeof(act));
1677 act.type = SET_URI_T;
1678 act.val[0].type = STRING_ST;
1679 act.val[0].u.string = ruri;
1680 init_run_actions_ctx(&ra_ctx);
1681 if (do_action(&ra_ctx, &act, msg) < 0) {
1682 LM_ERR("error while setting request uri\n");
1686 // Set auth_proxy ($du)
1687 if (set_dst_uri(msg, ®->auth_proxy) < 0) {
1688 LM_ERR("error while setting outbound proxy\n");
1692 memset(&val, 0, sizeof(pv_value_t));
1693 val.flags |= PV_VAL_STR;
1696 val.rs = reg->realm;
1697 if(pv_set_spec_value(msg, &auth_realm_spec, 0, &val)!=0) {
1698 LM_ERR("error while setting auth_realm\n");
1702 // Set auth_username
1703 val.rs = reg->auth_username;
1704 if(pv_set_spec_value(msg, &auth_username_spec, 0, &val)!=0) {
1705 LM_ERR("error while setting auth_username\n");
1709 // Set auth_password
1710 val.rs = reg->auth_password;
1711 if(pv_set_spec_value(msg, &auth_password_spec, 0, &val)!=0) {
1712 LM_ERR("error while setting auth_password\n");
1716 lock_release(reg->lock);
1720 lock_release(reg->lock);
1727 static int uac_reg_update_flag(str *attr, str *val, int mode, int fval)
1729 reg_uac_t *reg = NULL;
1732 if(_reg_htable==NULL) {
1733 LM_ERR("uac remote registrations not enabled\n");
1737 if(attr->len<=0 || attr->s==NULL || val->len<=0 || val->s==NULL) {
1738 LM_ERR("bad parameter values\n");
1742 ret = reg_ht_get_byfilter(®, attr, val);
1744 LM_DBG("record not found for %.*s = %.*s\n", attr->len, attr->s,
1747 } else if (ret < 0) {
1748 LM_DBG("unsupported filter attribute %.*s = %.*s\n", attr->len, attr->s,
1756 reg->flags &= ~fval;
1758 reg->timer_expires = time(NULL) + 1;
1760 lock_release(reg->lock);
1767 int uac_reg_enable(sip_msg_t *msg, str *attr, str *val)
1769 counter_add(regdisabled, -1);
1770 return uac_reg_update_flag(attr, val, 0, UAC_REG_DISABLED);
1776 int uac_reg_disable(sip_msg_t *msg, str *attr, str *val)
1778 counter_inc(regdisabled);
1779 return uac_reg_update_flag(attr, val, 1, UAC_REG_DISABLED);
1785 static int rpc_uac_reg_add_node_helper(rpc_t* rpc, void* ctx, reg_uac_t *reg, time_t tn)
1788 str none = {"none", 4};
1790 /* add entry node */
1791 if (rpc->add(ctx, "{", &th) < 0)
1793 rpc->fault(ctx, 500, "Internal error creating rpc");
1796 if (rpc->struct_add(th, "SSSSSSSSSdddddd",
1797 "l_uuid", ®->l_uuid,
1798 "l_username", ®->l_username,
1799 "l_domain", ®->l_domain,
1800 "r_username", ®->r_username,
1801 "r_domain", ®->r_domain,
1802 "realm", ®->realm,
1803 "auth_username", ®->auth_username,
1804 "auth_password", ®->auth_password,
1805 "auth_proxy", (reg->auth_proxy.len)?
1806 ®->auth_proxy:&none,
1807 "expires", (int)reg->expires,
1808 "flags", (int)reg->flags,
1809 "diff_expires", (int)(reg->timer_expires - tn),
1810 "timer_expires", (int)reg->timer_expires,
1811 "reg_init", (int)reg->reg_init,
1812 "reg_delay", (int)reg->reg_delay
1814 rpc->fault(ctx, 500, "Internal error adding item");
1820 static const char* rpc_uac_reg_dump_doc[2] = {
1821 "Dump the contents of user registrations table.",
1825 static void rpc_uac_reg_dump(rpc_t* rpc, void* ctx)
1828 reg_item_t *reg = NULL;
1831 if(_reg_htable==NULL)
1833 rpc->fault(ctx, 500, "Not enabled");
1839 for(i=0; i<_reg_htable->htsize; i++)
1841 lock_get(&_reg_htable->entries[i].lock);
1842 /* walk through entries */
1843 reg = _reg_htable->entries[i].byuuid;
1846 if (rpc_uac_reg_add_node_helper(rpc, ctx, reg->r, tn)<0)
1848 lock_release(&_reg_htable->entries[i].lock);
1853 lock_release(&_reg_htable->entries[i].lock);
1857 static const char* rpc_uac_reg_info_doc[2] = {
1858 "Return the details of registration for a particular record.",
1862 static void rpc_uac_reg_info(rpc_t* rpc, void* ctx)
1864 reg_uac_t *reg = NULL;
1869 if(_reg_htable==NULL)
1871 rpc->fault(ctx, 500, "Not enabled");
1875 if(rpc->scan(ctx, "S.S", &attr, &val)<2)
1877 rpc->fault(ctx, 400, "Invalid Parameters");
1880 if(attr.len<=0 || attr.s==NULL || val.len<=0 || val.s==NULL)
1882 LM_ERR("bad parameter values\n");
1883 rpc->fault(ctx, 400, "Invalid Parameter Values");
1887 ret = reg_ht_get_byfilter(®, &attr, &val);
1889 rpc->fault(ctx, 404, "Record not found");
1891 } else if (ret < 0) {
1892 rpc->fault(ctx, 400, "Unsupported filter attribute");
1896 rpc_uac_reg_add_node_helper(rpc, ctx, reg, time(NULL));
1897 lock_release(reg->lock);
1902 static void rpc_uac_reg_update_flag(rpc_t* rpc, void* ctx, int mode, int fval)
1904 reg_uac_t *reg = NULL;
1909 if(_reg_htable==NULL)
1911 rpc->fault(ctx, 500, "Not enabled");
1915 if(rpc->scan(ctx, "S.S", &attr, &val)<2)
1917 rpc->fault(ctx, 400, "Invalid Parameters");
1920 if(attr.len<=0 || attr.s==NULL || val.len<=0 || val.s==NULL)
1922 LM_ERR("bad parameter values\n");
1923 rpc->fault(ctx, 400, "Invalid Parameter Values");
1927 ret = reg_ht_get_byfilter(®, &attr, &val);
1929 rpc->fault(ctx, 404, "Record not found");
1931 } else if (ret < 0) {
1932 rpc->fault(ctx, 400, "Unsupported filter attribute");
1939 reg->flags &= ~fval;
1941 reg->timer_expires = time(NULL) + 1;
1943 lock_release(reg->lock);
1947 static const char* rpc_uac_reg_enable_doc[2] = {
1948 "Enable registration for a particular record.",
1952 static void rpc_uac_reg_enable(rpc_t* rpc, void* ctx)
1954 rpc_uac_reg_update_flag(rpc, ctx, 0, UAC_REG_DISABLED);
1955 counter_add(regdisabled, -1);
1958 static const char* rpc_uac_reg_disable_doc[2] = {
1959 "Disable registration for a particular record.",
1963 static void rpc_uac_reg_disable(rpc_t* rpc, void* ctx)
1965 rpc_uac_reg_update_flag(rpc, ctx, 1, UAC_REG_DISABLED);
1966 counter_inc(regdisabled);
1969 static const char* rpc_uac_reg_reload_doc[2] = {
1970 "Reload records from database.",
1974 static void rpc_uac_reg_reload(rpc_t* rpc, void* ctx)
1977 if(uac_reg_ht_shift()<0) {
1978 rpc->fault(ctx, 500, "Failed to shift records - check log messages");
1981 lock_get(_reg_htable_gc_lock);
1982 ret = uac_reg_load_db();
1983 lock_release(_reg_htable_gc_lock);
1985 rpc->fault(ctx, 500, "Failed to reload records - check log messages");
1990 static const char* rpc_uac_reg_refresh_doc[2] = {
1991 "Refresh a record from database.",
1995 static void rpc_uac_reg_refresh(rpc_t* rpc, void* ctx)
2000 if(rpc->scan(ctx, "S", &l_uuid)<1)
2002 rpc->fault(ctx, 400, "Invalid Parameters");
2006 ret = uac_reg_db_refresh(&l_uuid);
2008 rpc->fault(ctx, 404, "Record not found");
2011 rpc->fault(ctx, 500, "Failed to refresh record - check log messages");
2016 static const char* rpc_uac_reg_remove_doc[2] = {
2017 "Remove a record from memory.",
2021 static void rpc_uac_reg_remove(rpc_t* rpc, void* ctx)
2027 if(rpc->scan(ctx, "S", &l_uuid)<1)
2029 rpc->fault(ctx, 400, "Invalid Parameters");
2032 reg = reg_ht_get_byuuid(&l_uuid);
2034 rpc->fault(ctx, 404, "Record not found");
2038 ret = reg_ht_rm(reg);
2040 rpc->fault(ctx, 500, "Failed to remove record - check log messages");
2045 static const char* rpc_uac_reg_add_doc[2] = {
2046 "Add a record to memory.",
2050 static void rpc_uac_reg_add(rpc_t* rpc, void* ctx)
2056 if(rpc->scan(ctx, "SSSSSSSSSddd",
2071 rpc->fault(ctx, 400, "Invalid Parameters");
2075 cur_reg = reg_ht_get_byuuid(®.l_uuid);
2077 lock_release(cur_reg->lock);
2078 rpc->fault(ctx, 409, "uuid already exists");
2082 ret = reg_ht_add(®);
2084 rpc->fault(ctx, 500, "Failed to add record - check log messages");
2090 static const char* rpc_uac_reg_active_doc[2] = {
2091 "Set remote registration active or inactive for all records.",
2095 static void rpc_uac_reg_active(rpc_t* rpc, void* ctx)
2101 if(reg_active==NULL) {
2102 rpc->fault(ctx, 500, "Not initialized");
2105 if(rpc->scan(ctx, "d", &nmode)<1) {
2106 LM_ERR("missing parameter");
2107 rpc->fault(ctx, 500, "Missing parameter");
2110 omode = *reg_active;
2111 *reg_active = (nmode)?1:0;
2113 /* add entry node */
2114 if (rpc->add(ctx, "{", &th) < 0) {
2115 rpc->fault(ctx, 500, "Internal error creating rpc struct");
2118 if(rpc->struct_add(th, "dd", "omode", omode, "nmode", nmode)<0) {
2119 rpc->fault(ctx, 500, "Internal error creating response");
2124 rpc_export_t uac_reg_rpc[] = {
2125 {"uac.reg_dump", rpc_uac_reg_dump, rpc_uac_reg_dump_doc, RET_ARRAY},
2126 {"uac.reg_info", rpc_uac_reg_info, rpc_uac_reg_info_doc, 0},
2127 {"uac.reg_enable", rpc_uac_reg_enable, rpc_uac_reg_enable_doc, 0},
2128 {"uac.reg_disable", rpc_uac_reg_disable, rpc_uac_reg_disable_doc, 0},
2129 {"uac.reg_reload", rpc_uac_reg_reload, rpc_uac_reg_reload_doc, 0},
2130 {"uac.reg_refresh", rpc_uac_reg_refresh, rpc_uac_reg_refresh_doc, 0},
2131 {"uac.reg_remove", rpc_uac_reg_remove, rpc_uac_reg_remove_doc, 0},
2132 {"uac.reg_add", rpc_uac_reg_add, rpc_uac_reg_add_doc, 0},
2133 {"uac.reg_active", rpc_uac_reg_active, rpc_uac_reg_active_doc, 0},
2137 int uac_reg_init_rpc(void)
2139 if (rpc_register_array(uac_reg_rpc)!=0)
2141 LM_ERR("failed to register RPC commands\n");