SIP Witch 1.9.15
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
registry.cpp
Go to the documentation of this file.
1 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
2 // Copyright (C) 2015 Cherokees of Idaho.
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 #include "server.h"
18 
19 namespace sipwitch {
20 
21 static volatile unsigned active_routes = 0;
22 static volatile unsigned active_entries = 0;
23 static volatile unsigned active_targets = 0;
24 static volatile unsigned published_routes = 0;
25 static volatile unsigned allocated_routes = 0;
26 static volatile unsigned allocated_targets = 0;
27 static volatile unsigned allocated_entries = 0;
28 static unsigned mapped_entries = 999;
29 
30 static unsigned keysize = 177;
31 static registry::mapped **extmap = NULL;
32 static LinkedObject **addresses = NULL;
33 static LinkedObject **publishing = NULL;
34 static LinkedObject **contacts = NULL;
35 static LinkedObject **primap = NULL;
36 static LinkedObject *freeroutes = NULL;
37 static LinkedObject *freetargets = NULL;
38 static LinkedObject **keys = NULL;
39 static condlock_t locking;
40 static stats *statmap = NULL;
41 static LinkedObject *freelist = NULL;
42 
43 registry registry::reg;
44 
46 {
47  entry = NULL;
48 }
49 
51 {
52  assert(id != NULL && *id != 0);
53 
54  entry = registry::access(id);
55 }
56 
58 {
59  entry = copy.entry;
60  locking.access();
61 }
62 
64 {
65  registry::detach(entry);
66 }
67 
69 {
70  registry::detach(entry);
71  entry = rr;
72 }
73 
74 void *registry::target::operator new(size_t size)
75 {
76  assert(size == sizeof(registry::target));
77 
78  ++active_targets;
79  return server::allocate(size, &freetargets, &allocated_targets);
80 }
81 
82 void registry::target::operator delete(void *obj)
83 {
84  assert(obj != NULL);
85 
86  ((LinkedObject*)(obj))->enlist(&freetargets);
87  --active_targets;
88 }
89 
90 void *registry::route::operator new(size_t size)
91 {
92  assert(size == sizeof(registry::route));
93 
94  ++active_routes;
95  return server::allocate(size, &freeroutes, &allocated_routes);
96 }
97 
98 void registry::route::operator delete(void *obj)
99 {
100  assert(obj != NULL);
101 
102  ((LinkedObject*)(obj))->enlist(&freeroutes);
103  --active_routes;
104 }
105 
108 {
109  prefix = 100;
110  range = 600;
111  expires = 300l;
112  routes = 10;
113 }
114 
115 const char *registry::getDomain(void)
116 {
117  if(!reg.realm || strchr(reg.realm, ' ')) {
118 #ifdef HAVE_GETHOSTNAME
119  static char hostbuf[256] = {0};
120  if(!hostbuf[0])
121  gethostname(hostbuf, sizeof(hostbuf));
122  if(hostbuf[0])
123  return hostbuf;
124  return NULL;
125 #else
126  return NULL;
127 #endif
128  }
129 
130  if(eq(reg.realm, "no"))
131  return NULL;
132 
133  if(eq(reg.realm, "none"))
134  return NULL;
135 
136  return reg.realm;
137 }
138 
140 {
141  if(rr) {
142  Mutex::protect(rr);
143  ++rr->inuse;
144  Mutex::release(rr);
145  switch(rr->type) {
147  if(rr->source.external.statnode) {
148  rr->source.external.statnode->assign(stat);
149  break;
150  }
151  statmap[5].assign(stat);
152  break;
154  statmap[3].assign(stat);
155  break;
157  statmap[2].assign(stat);
158  break;
159  default:
160  statmap[1].assign(stat);
161  }
162  }
163  else
164  statmap[4].assign(stat);
165 }
166 
168 {
169  if(rr) {
170  Mutex::protect(rr);
171  --rr->inuse;
172  Mutex::release(rr);
173  switch(rr->type) {
175  if(rr->source.external.statnode) {
176  rr->source.external.statnode->release(stat);
177  break;
178  }
179  statmap[5].release(stat);
180  break;
182  statmap[3].release(stat);
183  break;
185  statmap[2].release(stat);
186  break;
187  default:
188  statmap[1].release(stat);
189  }
190  }
191  else
192  statmap[4].release(stat);
193 }
194 
196 {
197  assert(id != NULL && *id != 0);
198 
199  linked_pointer<mapped> rp;
200  unsigned path = NamedObject::keyindex(id, keysize);
201  if(!keys)
202  return NULL;
203  rp = keys[path];
204  while(rp) {
205  if(!strcmp(rp->userid, id))
206  break;
207  rp.next();
208  }
209  return *rp;
210 }
211 
213 {
214  assert((caddr_t)rr >= reg.addr());
215 
216  unsigned x = (unsigned)(((caddr_t)rr - reg.addr()) / sizeof(MappedRegistry));
217  return x;
218 }
219 
221 {
222  assert(cfg != NULL);
223 
224  shell::log(DEBUG1, "starting registry; mapping %d entries", mapped_entries);
225  create(control::env("regmap"), mapped_entries);
226  if(!reg)
227  shell::log(shell::FAIL, "registry could not be mapped");
228  initialize();
229  statmap = stats::create();
230 }
231 
232 bool registry::check(void)
233 {
234  shell::log(shell::INFO, "checking registry...");
235  locking.modify();
236  locking.commit();
237  return true;
238 }
239 
241 {
242  assert(cfg != NULL);
243 
244  shell::log(DEBUG1, "stopping registry");
245  MappedMemory::release();
246  MappedMemory::remove(control::env("regmap"));
247  stats::release();
248 }
249 
250 void registry::snapshot(FILE *fp)
251 {
252  assert(fp != NULL);
253 
254  mapped *rr;
255  unsigned regcount = 0;
256  time_t now;
257  linked_pointer<target> tp;
258  linked_pointer<route> rp;
259  char buffer[128];
260 
261  locking.access();
262  fprintf(fp, "Registry:\n");
263  fprintf(fp, " mapped entries: %d\n", mapped_entries);
264  fprintf(fp, " active entries: %d\n", active_entries);
265  fprintf(fp, " active routes: %d\n", active_routes);
266  fprintf(fp, " active targets: %d\n", active_targets);
267  fprintf(fp, " published routes: %d\n", published_routes);
268  fprintf(fp, " allocated routes: %d\n", allocated_routes);
269  fprintf(fp, " allocated targets: %d\n", allocated_targets);
270  fprintf(fp, " allocated entries: %d\n", allocated_entries);
271 
272  while(regcount < mapped_entries) {
273  time(&now);
274  rr = static_cast<mapped*>(reg(regcount++));
275  if(rr->type == MappedRegistry::TEMPORARY) {
276  fprintf(fp, " temp %s; use=%d\n", rr->userid, rr->inuse);
277  }
278  else if(rr->type != MappedRegistry::EXPIRED && (!rr->expires || rr->expires >= now)) {
279  if(rr->ext)
280  snprintf(buffer, sizeof(buffer), "%d", rr->ext);
281  else
282  String::set(buffer, sizeof(buffer), "none");
283  if(rr->type == MappedRegistry::USER)
284  fprintf(fp, " user %s; extension=%s, profile=%s, use=%d,",
285  rr->userid, buffer, rr->profile.id, rr->inuse);
286  else if(rr->type == MappedRegistry::GATEWAY)
287  fprintf(fp, " gateway %s; use=%d,", rr->userid, rr->inuse);
288  else if(rr->type == MappedRegistry::SERVICE)
289  fprintf(fp, " service %s; use=%d", rr->userid, rr->inuse);
290  else if(rr->type == MappedRegistry::REFER)
291  fprintf(fp, " refer %s; extensions=%s,",
292  rr->userid, buffer);
293  else if(rr->type == MappedRegistry::REJECT)
294  fprintf(fp, " reject %s; extension=%s,",
295  rr->userid, buffer);
296  if(!rr->count)
297  fprintf(fp, " address=none\n");
298  else
299  fputc('\n', fp);
300  tp = rr->source.internal.targets;
301  while(is(tp)) {
302  Socket::query((struct sockaddr *)(&tp->address), buffer, sizeof(buffer));
303  fprintf(fp, " address=%s, contact=%s", buffer, tp->contact);
304  if(tp->expires && tp->expires <= now)
305  fprintf(fp, ", expired");
306  else if(tp->expires)
307  fprintf(fp, ", expires %ld", (long)(tp->expires - now));
308  if(tp.getNext())
309  fputc(',', fp);
310  fputc('\n', fp);
311  tp.next();
312  }
313  rp = rr->source.internal.routes;
314  if(is(rp) && rr->type == MappedRegistry::SERVICE)
315  fprintf(fp, " services=");
316  else if(is(rp) && rr->type == MappedRegistry::GATEWAY)
317  fprintf(fp, " routes=");
318  while(is(rp) && (rr->type == MappedRegistry::SERVICE || rr->type == MappedRegistry::GATEWAY)) {
319  fputs(rp->entry.text, fp);
320  if(rp->getNext())
321  fputc(',', fp);
322  else
323  fputc('\n', fp);
324  rp.next();
325  }
326  rp = rr->source.internal.published;
327  if(rp)
328  fprintf(fp, " published=");
329  while(rp) {
330  fputs(rp->entry.text, fp);
331  if(rp->getNext())
332  fputc(',', fp);
333  else
334  fputc('\n', fp);
335  rp.next();
336  }
337  }
338  fflush(fp);
339  Thread::yield();
340  }
341  locking.release();
342 }
343 
345 {
346  assert(rr != NULL);
347 
348  rr->userid[0] = 0;
349  rr->display[0] = 0;
350  rr->remote[0] = 0;
353  rr->hidden = false;
354  rr->rid = -1;
355  rr->ext = 0;
356  rr->count = 0;
357  rr->inuse = 0;
358  rr->created = 0;
359  rr->expires = 0;
360  // this one is safe to clear...
361  memset(&rr->profile, 0, sizeof(profile_t));
362  rr->source.internal.published = rr->source.internal.targets = rr->source.internal.routes = NULL;
363 }
364 
365 bool registry::remove(const char *id)
366 {
367  assert(id != NULL && *id != 0);
368 
369  bool rtn = true;
370  mapped *rr, save;
371 
372  locking.modify();
373  rr = find(id);
374  if(rr && rr->inuse)
375  rtn = false;
376  else if(rr) {
377  store_unsafe<mapped>(save, rr);
378  expire(rr);
379  }
380  else
381  rtn = false;
382  locking.commit();
383  if(rtn)
384  server::expire(&save);
385  return rtn;
386 }
387 
389 {
390  assert(rr != NULL);
391 
392  linked_pointer<target> tp = rr->source.internal.targets;
393  linked_pointer<route> rp = rr->source.internal.routes;
394  unsigned path;
395 
396  --active_entries;
397 
398  while(rp) {
399  route *nr = rp.getNext();
400  if(rr->type == MappedRegistry::SERVICE) {
401  path = NamedObject::keyindex(rp->entry.text, keysize);
402  rp->entry.delist(&contacts[path]);
403  }
404  else
405  rp->entry.delist(&primap[rp->entry.priority]);
406  rp->entry.text[0] = 0;
407  delete *rp;
408  rp = nr;
409  }
410  rp = rr->source.internal.published;
411  while(rp) {
412  route *nr = rp.getNext();
413  --published_routes;
414  path = NamedObject::keyindex(rp->entry.text, keysize);
415  rp->entry.delist(&publishing[path]);
416  rp->entry.text[0] = 0;
417  delete *rp;
418  rp = nr;
419  }
420  while(tp) {
421  // if active address index, delist & clear it
422  if(tp->index.address) {
423  path = Socket::keyindex(tp->index.address, keysize);
424  tp->index.delist(&addresses[path]);
425  tp->index.address = NULL;
426  tp->index.registry = NULL;
427  }
428  target *nt = tp.getNext();
429  delete *tp;
430  tp = nt;
431  }
432  rr->source.internal.routes = NULL;
433  rr->source.internal.targets = NULL;
434  rr->source.internal.published = NULL;
435  rr->count = 0;
436  rr->inuse = 0;
438  if(rr->ext && rr->ext >= reg.prefix && rr->ext < (reg.prefix + reg.range) && extmap[rr->ext - reg.prefix] == rr)
439  extmap[rr->ext - reg.prefix] = NULL;
440  shell::log(shell::INFO, "expiring %s; extension=%d", rr->userid, rr->ext);
441  path = NamedObject::keyindex(rr->userid, keysize);
442  rr->display[0] = 0;
443  rr->userid[0] = 0;
444  rr->ext = 0;
447  rr->rid = -1;
448  rr->delist(&keys[path]);
449  rr->enlist(&freelist);
450 }
451 
452 unsigned registry::cleanup(time_t period)
453 {
454  mapped *rr, save;
455  unsigned regcount = 0;
456  time_t now;
457  bool expired;
458  unsigned expcount = 0;
459 
460  while(regcount < mapped_entries) {
461  expired = false;
462  time(&now);
463  rr = static_cast<mapped*>(reg(regcount++));
464  store_unsafe<mapped>(save, rr);
465  locking.modify();
466  if(rr->type != MappedRegistry::EXPIRED && rr->expires && rr->expires + period < now && !rr->inuse) {
467  expire(rr);
468  expired = true;
469  }
470  else if(!rr->inuse && rr->type == MappedRegistry::EXPIRED && rr->status != MappedRegistry::OFFLINE) {
471  expire(rr);
472  expired = true;
473  }
474  locking.commit();
475  Thread::yield();
476  if(expired) {
477  ++expcount;
478  server::expire(&save);
479  }
480  }
481  return expcount;
482 }
483 
485 {
486  assert(cfg != NULL);
487 
488  static const char *olddigest = "MD5";
489  static const char *oldrealm = "-";
490  const char *key = NULL, *value;
491  linked_pointer<service::keynode> sp = cfg->getList("registry");
492 
493  digest = (char *)"MD5";
494  realm = NULL;
495 
496  while(is(sp)) {
497  key = sp->getId();
498  value = sp->getPointer();
499  if(key && value) {
500  if(!stricmp(key, "mapped") && !is_configured())
501  mapped_entries = atoi(value);
502  else if(!stricmp(key, "digest")) {
503  digest = cfg->dup(value);
504  String::upper((char *)digest);
505  }
506  else if(!stricmp(key, "realm"))
507  realm = cfg->dup(value);
508  else if(!stricmp(key, "prefix") && !is_configured())
509  prefix = atoi(value);
510  else if(!stricmp(key, "range") && !is_configured())
511  range = atoi(value);
512  else if(!stricmp(key, "priorities") && !is_configured())
513  routes = atoi(value);
514  else if(!stricmp(key, "expires"))
515  expires = atoi(value);
516  else if(!stricmp(key, "keysize") && !is_configured())
517  keysize = atoi(value);
518  }
519  sp.next();
520  }
521 
522 // windows may use registry keys?
523 #ifndef _MSWINDOWS_
524  char buffer[256];
525  fsys_t fs;
526  char *cp;
527 
528  if(!getuid() || !realm)
529  fs.open(DEFAULT_CFGPATH "/siprealm", fsys::RDONLY);
530  if(!is(fs) && !realm)
531  fs.open("uuid", fsys::RDONLY);
532  if(is(fs)) {
533  memset(buffer, 0, sizeof(buffer));
534  fs.read(buffer, sizeof(buffer) - 1);
535  fs.close();
536 
537  cp = strchr(buffer, '\n');
538  if(cp)
539  *cp = 0;
540 
541  cp = strchr(buffer, ':');
542  if(cp)
543  *(cp++) = 0;
544  if(buffer[0])
545  realm = cfg->dup(buffer);
546  if(cp && cp[0]) {
547  digest = cfg->dup(cp);
548  String::upper(digest);
549  }
550  }
551  // if not in config file and not set, create one...
552  else if(!realm) {
553  memset(buffer, 0, sizeof(buffer));
554  Random::uuid(buffer);
555  String::add(buffer, sizeof(buffer), ":");
556  String::add(buffer, sizeof(buffer), digest);
557  fs.open("uuid", 0440, fsys::WRONLY);
558  if(is(fs)) {
559  fs.write(buffer, sizeof(buffer));
560  fs.close();
561  }
562  cp = strchr(buffer, ':');
563  if(cp)
564  *cp = 0;
565  realm = cfg->dup(buffer);
566  }
567 
568 #endif
569 
570  if(!String::equal(realm, oldrealm)) {
571  secure::uuid(session_uuid);
572  shell::log(shell::NOTIFY, "new realm %s", realm);
573  digests::reload();
574  } else if(!String::equal(digest, olddigest)) {
575  shell::log(shell::INFO, "digest changed to %s", digest);
576  digests::reload();
577  }
578 
579  oldrealm = realm;
580  olddigest = digest;
581 
582  sip_realm = realm;
583  sip_prefix = prefix;
584  sip_range = range;
586 
587  if(is_configured())
588  return;
589 
590  if(range) {
591  extmap = new mapped *[range];
592  memset(extmap, 0, sizeof(mapped *) * range);
593  }
594  primap = new LinkedObject *[routes];
595  memset(primap, 0, sizeof(LinkedObject *) * routes);
596  keys = new LinkedObject *[keysize];
597  contacts = new LinkedObject *[keysize];
598  publishing = new LinkedObject *[keysize];
599  addresses = new LinkedObject *[keysize];
600  memset(keys, 0, sizeof(LinkedObject *) * keysize);
601  memset(contacts, 0, sizeof(LinkedObject *) * keysize);
602  memset(publishing, 0, sizeof(LinkedObject *) * keysize);
603  memset(addresses, 0, sizeof(LinkedObject *) * keysize);
604 }
605 
606 unsigned registry::getEntries(void)
607 {
608  return mapped_entries;
609 }
610 
612 {
613  assert(id != NULL && *id != 0);
614 
615  mapped *rr = NULL;
616  unsigned path = NamedObject::keyindex(id, keysize);
617  service::usernode user;
618  service::keynode *leaf = NULL;
619  unsigned ext = 0;
620 
621  locking.access();
622  rr = find(id);
623  if(rr) {
624  incUse(rr, stat);
625  locking.release();
626  return rr;
627  }
628 
629  locking.exclusive();
630  if(freelist) {
631  rr = (mapped *)freelist;
632  freelist = rr->getNext();
633  }
634  else if(allocated_entries < mapped_entries)
635  rr = (mapped *)reg(allocated_entries++);
636  else {
637  locking.commit();
638  return NULL;
639  }
640 
641  clear(rr);
643  rr->expires = 0;
644  rr->created = 0;
645  rr->display[0] = 0;
646  rr->inuse = 0;
647  rr->rid = -1;
648 
649  // in case inter-nodel temporary, create properties for call use...
650 
651  server::getProvision(id, user);
652  service::keynode *node = user.keys;
653  if(node)
654  leaf = node->leaf("extension");
655  if(leaf && leaf->getPointer())
656  ext = atoi(leaf->getPointer());
657  if(ext && (ext < reg.prefix || ext >= (reg.prefix + reg.range))) {
658  rr->ext = ext;
659  }
660  else
661  ext = 0;
662  leaf = node->leaf("display");
663  if(leaf && leaf->getPointer())
664  String::set(rr->display, sizeof(rr->display), leaf->getPointer());
665 
666  server::release(user);
667 
668  String::set(rr->userid, sizeof(rr->userid), id);
669  rr->ext = ext;
670  rr->enlist(&keys[path]);
672  incUse(rr, stat);
673 
674  locking.commit();
675  return rr;
676 }
677 
679 {
680  assert(id != NULL && *id != 0);
681 
682  mapped *rr = NULL, *prior;
683  unsigned path = NamedObject::keyindex(id, keysize);
684  linked_pointer<service::keynode> rp;
685  service::keynode *node, *leaf;
686  unsigned ext = 0;
687  const char *cp = "none";
688  const char *cos = "none";
689  profile_t *pro = NULL;
690  bool listed = false;
691  service::usernode user;
692 
693  locking.modify();
694  rr = find(id);
695  if(rr && rr->type != MappedRegistry::TEMPORARY && rr->type != MappedRegistry::EXPIRED) {
696  locking.share();
697  return rr;
698  }
699 
700  if(rr)
701  listed = true;
702  else {
703  if(freelist) {
704  rr = (mapped *)freelist;
705  freelist = rr->getNext();
706  } else if(allocated_entries < mapped_entries)
707  rr = (mapped *)reg(allocated_entries++);
708  if(rr)
709  clear(rr);
710  }
711  if(!rr) {
712  locking.commit();
713  return NULL;
714  }
715 
716  server::getProvision(id, user);
717  node = user.keys;
718  cp = "none";
719  rr->rid = -1;
721  rr->expires = 0;
722  rr->created = 0;
723  rr->display[0] = 0;
724 
725  if(!listed)
726  rr->inuse = 0;
727 
728  if(node)
729  cp = node->getId();
730 
731  cos = cp;
732  if(!stricmp(cp, "admin") || !stricmp(cp, "user"))
734  else if(!stricmp(cp, "refer"))
736  else if(!stricmp(cp, "reject"))
738  else if(!stricmp(cp, "gateway"))
740  else if(!stricmp(cp, "service") || !stricmp(cp, "device"))
742  if(!node || rr->type == MappedRegistry::EXPIRED) {
743  server::release(user);
744  if(listed && rr->inuse)
746  else if(listed) {
747  rr->delist(&keys[path]);
748  listed = false;
749  }
750  if(!listed)
751  rr->enlist(&freelist);
752  locking.commit();
753  return NULL;
754  }
755 
756  // add static services if exist
757  rp = node->leaf("contacts");
758  if(rp)
759  rp = rp->getFirst();
760 
761  while(rp) {
762  if(!stricmp(rp->getId(), "contact") && rp->getPointer())
763  rr->addContact(rp->getPointer());
764  rp.next();
765  }
766 
767  // add published uris
768  rp = node->leaf("published");
769  if(!rp)
770  node->leaf("publish");
771 
772  if(is(rp) && rp->getPointer())
773  rr->addPublished(rp->getPointer());
774 
775  if(is(rp) && !rp->getPointer() && !rp->getFirst())
776  rr->addPublished(id);
777 
778  if(is(rp))
779  rp = rp->getFirst();
780 
781  while(is(rp)) {
782  if(!stricmp(rp->getId(), "contact") && rp->getPointer())
783  rr->addPublished(rp->getPointer());
784  rp.next();
785  }
786 
787  rp = node->leaf("display");
788  if(is(rp) && rp->getPointer())
789  String::set(rr->display, sizeof(rr->display), rp->getPointer());
790 
791  // we add routes while still exclusive owner of registry since
792  // they update priority indexes.
793  rp = node->leaf("routes");
794  if(rp)
795  rp = rp->getFirst();
796 
797  while(rp) {
798  const char *pattern = NULL, *prefix = NULL, *suffix = NULL;
799  unsigned priority = 0;
800  linked_pointer<service::keynode> route;
801 
802  route = static_cast<LinkedObject*>(NULL);
803  if(!stricmp(rp->getId(), "route"))
804  route = rp->getFirst();
805  while(route) {
806  const char *id = route->getId();
807  const char *value = route->getPointer();
808 
809  if(id && value && !stricmp(id, "pattern"))
810  pattern = value;
811  else if(id && value && !stricmp(id, "priority"))
812  priority = atoi(value);
813  else if(id && value && !stricmp(id, "prefix"))
814  prefix = value;
815  else if(id && value && !stricmp(id, "suffix"))
816  suffix = value;
817  route.next();
818  }
819  if(pattern)
820  rr->addRoute(pattern, priority, prefix, suffix);
821  rp.next();
822  }
823  leaf = node->leaf("extension");
824  if(leaf && leaf->getPointer())
825  ext = atoi(leaf->getPointer());
826 
827  if(rr->is_profiled()) {
828  pro = NULL;
829  leaf = node->leaf("profile");
830  if(leaf)
831  pro = server::getProfile(leaf->getPointer());
832  if(!pro)
833  pro = server::getProfile(cos);
834  if(!pro)
835  pro = server::getProfile("*");
836  if(pro)
837  memcpy(&rr->profile, pro, sizeof(rr->profile));
838  }
839 
840  server::release(user);
841  rr->ext = 0;
843 
844  if(!listed) {
845  String::set(rr->userid, sizeof(rr->userid), id);
846  rr->enlist(&keys[path]);
847  }
848 
849  if(ext >= reg.prefix && ext < (reg.prefix + reg.range)) {
850  prior = extmap[ext - reg.prefix];
851  if(prior && prior != rr) {
852  shell::log(shell::INFO, "releasing %s from extension %d", prior->userid, ext);
853  prior->ext = 0;
854  }
855  extmap[ext - reg.prefix] = rr;
856  rr->ext = ext;
857  shell::log(shell::INFO, "activating %s; extension=%d", rr->userid, ext);
858  }
859  ++active_entries;
860 
861  // exchange exclusive mutex lock for registry to shared before return
862  // when registry state is again stable.
863 
864  locking.share();
865 
866  return rr;
867 }
868 
869 registry::mapped *registry::address(const struct sockaddr *addr)
870 {
871  assert(addr != NULL);
872 
873  target *target;
874  linked_pointer<target::indexing> ind;
875  mapped *rr = NULL;
876  unsigned path = Socket::keyindex(addr, keysize);
877  time_t now;
878 
879  locking.access();
880 
881  time(&now);
882  ind = addresses[path];
883 
884  while(ind) {
885  target = ind->getTarget();
886  if(target && target->expires > now && Socket::equal(addr, ind->address)) {
887  rr = ind->registry;
888  break;
889  }
890  ind.next();
891  }
892 
893  if(!rr)
894  locking.release();
895  return rr;
896 }
897 
899 {
900  assert(uri != NULL && *uri != 0);
901 
902  mapped *rr = NULL;
903  const struct sockaddr *addr = NULL;
904  Socket::address *target = NULL;
905  char buffer[MAX_USERID_SIZE];
906  char *cp;
907 
908  if(!strnicmp(uri, "sip:", 4))
909  uri += 4;
910  else if(!strnicmp(uri, "sips:", 5))
911  uri += 5;
912 
913  String::set(buffer, sizeof(buffer), uri);
914  cp = strchr(buffer, '@');
915  if(cp)
916  *cp = 0;
917  if(strchr(uri, '@')) {
918  target = stack::getAddress(uri);
919  if(target)
920  addr = target->getAddr();
921  }
922 
923  if(addr)
924  rr = contact(addr, buffer);
925 
926  if(target)
927  delete target;
928 
929  return rr;
930 }
931 
932 registry::mapped *registry::contact(const struct sockaddr *addr, const char *uid)
933 {
934  assert(addr != NULL);
935  assert(uid != NULL && *uid != 0);
936 
937  mapped *rr;
938  linked_pointer<route> rp;
939  unsigned path = NamedObject::keyindex(uid, keysize);
940  locking.access();
941  rp = contacts[path];
942  while(rp) {
943  if(!stricmp(uid, rp->entry.text) && Socket::equal(addr, (struct sockaddr *)(&rp->entry.registry->contact)))
944  break;
945  rp.next();
946  }
947 
948  if(!rp) {
949  locking.release();
950  return NULL;
951  }
952  rr = rp->entry.registry;
953  return rr;
954 }
955 
956 bool registry::isUserid(const char *id)
957 {
958  assert(id != NULL && *id != 0);
959 
960  if(!id || !*id)
961  return false;
962 
963  if(strlen(id) >= MAX_USERID_SIZE)
964  return false;
965 
966  if(strchr(id, '@') || strchr(id, ':'))
967  return false;
968 
969  return true;
970 }
971 
972 bool registry::isExtension(const char *id)
973 {
974  assert(id != NULL && *id != 0);
975 
976  unsigned ext = atoi(id);
977 
978  while(*id) {
979  if(*id < '0' || *id > '9')
980  return false;
981  ++id;
982  }
983 
984  if(!reg.range)
985  return false;
986 
987  if(ext >= reg.prefix && ext < (reg.prefix + reg.range))
988  return true;
989 
990  return false;
991 }
992 
993 registry::pattern *registry::getRouting(unsigned trs, const char *id)
994 {
995  assert(id != NULL && *id != 0);
996 
997  linked_pointer<pattern> pp;
998  if(trs > reg.routes)
999  trs = reg.routes;
1000 
1001  if(!trs)
1002  return NULL;
1003 
1004  locking.access();
1005  while(trs--) {
1006  pp = primap[trs];
1007  while(pp) {
1008  if(service::match(id, pp->text, false) && pp->registry)
1009  return *pp;
1010  pp.next();
1011  }
1012  }
1013  locking.release();
1014  return NULL;
1015 }
1016 
1018 {
1019  assert(id != NULL && *id != 0);
1020 
1021  unsigned ext = atoi(id);
1022  registry::mapped *rr = NULL;
1023  time_t now;
1024 
1025  locking.access();
1026  time(&now);
1027  rr = extmap[ext - reg.prefix];
1028  if(rr->expires && rr->expires < now)
1029  rr = NULL;
1030  if(!rr)
1031  locking.release();
1032  return rr;
1033 }
1034 
1035 bool registry::exists(const char *id)
1036 {
1037  bool rtn = true;
1038  time_t now;
1039 
1040  mapped *rr = access(id);
1041  if(!rr)
1042  return false;
1043 
1044  time(&now);
1045  if(rr->expires && rr->expires < now)
1046  rtn = false;
1047 
1048  if(rr->status == MappedRegistry::OFFLINE)
1049  rtn = false;
1050 
1051  detach(rr);
1052  return rtn;
1053 }
1054 
1056 {
1057  assert(id != NULL && *id != 0);
1058 
1059  mapped *rr;
1060  unsigned ext = 0;
1061 
1062  if(isExtension(id))
1063  ext = atoi(id);
1064 
1065  locking.access();
1066  rr = find(id);
1067 
1068  // if extension dialing, and we find by id but have ext #, then ignore
1069  if(rr && service::dialmode == service::EXT_DIALING && rr->ext != 0)
1070  rr = NULL;
1071 
1072  // assuming not user id exclusive dialing, then we can try ext...
1073  if(!rr && service::dialmode != service::USER_DIALING && reg.range && ext >= reg.prefix && ext < (reg.prefix + reg.range))
1074  rr = extmap[ext - reg.prefix];
1075  if(!rr)
1076  locking.release();
1077  return rr;
1078 }
1079 
1080 
1082 {
1083  assert(id != NULL && *id != 0);
1084 
1085  mapped *rr;
1086  unsigned ext = 0;
1087 
1088  if(isExtension(id))
1089  ext = atoi(id);
1090 
1091  locking.access();
1092  rr = find(id);
1093  if(!rr && reg.range && ext >= reg.prefix && ext < (reg.prefix + reg.range))
1094  rr = extmap[ext - reg.prefix];
1095  if(!rr)
1096  locking.release();
1097  return rr;
1098 }
1099 
1101 {
1102  // External registries are created in plugins, are not in shared memory,
1103  // and are not locked or otherwise managed under the registry. They are
1104  // used to give an artificial "local call leg" registration entity when
1105  // call legs are extended through plugins, such as for service providers.
1106 
1107  if(!rr || rr->type == MappedRegistry::EXTERNAL)
1108  return;
1109 
1110  locking.release();
1111 }
1112 
1113 unsigned registry::mapped::setTarget(Socket::address& target_addr, time_t lease, const char *target_contact, const char *target_network, struct sockaddr *target_peering, voip::context_t context)
1114 {
1115  assert(!isnull(target_addr));
1116  assert(target_contact != NULL && *target_contact != 0);
1117 
1118  Socket::address *origin = NULL;
1119  const struct sockaddr *ai, *oi = NULL;
1120  linked_pointer<target> tp;
1121  socklen_t len;
1122  bool creating = false;
1123 
1124  ai = target_addr.getAddr();
1125  if(!ai)
1126  return 0;
1127 
1128  if(!context)
1129  context = stack::sip.out_context;
1130 
1131  len = Socket::len(ai);
1132 
1133  locking.exclusive();
1134  tp = source.internal.targets;
1135  while(is(tp) && count > 1) {
1136  delete *tp;
1137  tp.next();
1138  --count;
1139  }
1140 
1141  if(!tp) {
1142  tp = new target;
1143  time(&tp->created);
1144  tp->enlist(&source.internal.targets);
1145  tp->context = context; // make sure def context
1146  count = 1;
1147  tp->status = registry::target::READY;
1148  tp->address.address.sa_family = 0;
1149  creating = true;
1150  }
1151  expires = tp->expires = lease;
1152  if(!Socket::equal((struct sockaddr *)(&tp->address), ai)) {
1153  if(tp->index.address) {
1154  tp->index.delist(&addresses[Socket::keyindex(tp->index.address, keysize)]);
1155  tp->index.address = NULL;
1156  tp->index.registry = NULL;
1157  creating = true;
1158  }
1159 
1160  origin = stack::getAddress(target_contact);
1161  if(origin)
1162  oi = origin->getAddr();
1163  if(!oi)
1164  oi = ai;
1165  memcpy(&tp->address, ai, len);
1166  memcpy(&contact, oi, len);
1167  if(creating) {
1168  tp->index.registry = this;
1169  tp->index.address = (struct sockaddr *)(&tp->address);
1170  tp->index.enlist(&addresses[Socket::keyindex(tp->index.address, keysize)]);
1171  }
1172  if(origin)
1173  delete origin;
1174  }
1175  tp->context = context;
1176  Socket::store(&tp->peering, target_peering);
1177  String::set(tp->network, sizeof(tp->network), target_network);
1178  String::set(tp->contact, sizeof(tp->contact), target_contact);
1179  String::set(network, sizeof(network), target_network);
1180  uri::userid(target_contact, remote, sizeof(remote));
1181  locking.share();
1182  return 1;
1183 }
1184 
1185 void registry::mapped::addRoute(const char *route_pattern, unsigned route_priority, const char *route_prefix, const char *route_suffix)
1186 {
1187  assert(route_pattern != NULL && *route_pattern != 0);
1188 
1189  locking.exclusive();
1190  route *rp = new route;
1191 
1192  if(!route_prefix)
1193  route_prefix = "";
1194  if(!route_suffix)
1195  route_suffix = "";
1196 
1197  String::set(rp->entry.text, MAX_USERID_SIZE, route_pattern);
1198  String::set(rp->entry.prefix, MAX_USERID_SIZE, route_prefix);
1199  String::set(rp->entry.suffix, MAX_USERID_SIZE, route_suffix);
1200  rp->entry.priority = route_priority;
1201  rp->entry.registry = this;
1202  rp->entry.enlist(&primap[route_priority]);
1203  rp->enlist(&source.internal.routes);
1204  locking.share();
1205 }
1206 
1207 void registry::mapped::addPublished(const char *published_id)
1208 {
1209  assert(published_id != NULL && *published_id != 0);
1210 
1211  unsigned path = NamedObject::keyindex(published_id, keysize);
1212  locking.exclusive();
1213  route *rp = new route;
1214  String::set(rp->entry.text, MAX_USERID_SIZE, published_id);
1215  rp->entry.priority = 0;
1216  rp->entry.registry = this;
1217  rp->entry.enlist(&publishing[path]);
1218  rp->enlist(&source.internal.published);
1219  ++published_routes;
1220  locking.share();
1221 }
1222 
1223 void registry::mapped::addContact(const char *contact_id)
1224 {
1225  assert(contact_id != NULL && *contact_id != 0);
1226 
1227  unsigned path = NamedObject::keyindex(contact_id, keysize);
1228 
1229  locking.exclusive();
1230  route *rp = new route;
1231  String::set(rp->entry.text, MAX_USERID_SIZE, contact_id);
1232  rp->entry.priority = 0;
1233  rp->entry.registry = this;
1234  rp->entry.enlist(&contacts[path]);
1235  rp->enlist(&source.internal.routes);
1236  locking.share();
1237 }
1238 
1240 {
1241  linked_pointer<target> tp = source.internal.targets;
1242  time_t now;
1243  status_t prior = status;
1244  const char *text;
1245 
1246  unsigned total = 0, busy = 0, away = 0, dnd = 0, offline = 0;
1247 
1248  time(&now);
1249 
1250  if(type != USER)
1251  return;
1252 
1253  if(type == EXPIRED || !is(tp)) {
1254  offline = total = 1;
1255  }
1256  else while(is(tp)) {
1257  ++total;
1258  if(tp->expires < now || tp->status == registry::target::OFFLINE)
1259  ++offline;
1260  else if(tp->status == registry::target::AWAY)
1261  ++away;
1262  else if(tp->status == registry::target::DND)
1263  ++dnd;
1264  else if(tp->status == registry::target::BUSY)
1265  ++busy;
1266  else if(tp->status == registry::target::UNKNOWN)
1267  --total;
1268  tp.next();
1269  }
1270 
1271  if(offline == total) {
1272  status = OFFLINE;
1273  text = "offline";
1274  }
1275  else if(away + offline == total) {
1276  status = AWAY;
1277  text = "away";
1278  }
1279  else if(away + dnd + offline == total) {
1280  status = DND;
1281  text = "dnd";
1282  }
1283  else if(busy + dnd + offline + away == total) {
1284  status = BUSY;
1285  text = "busy";
1286  }
1287  else {
1288  status = IDLE;
1289  text = "ready";
1290  }
1291 
1292  if(status == prior)
1293  return;
1294 
1295  shell::debug(3, "update: %s changed to %s", userid, text);
1296 }
1297 
1298 bool registry::mapped::expire(Socket::address& saddr)
1299 {
1300  unsigned active_count = 0;
1301  time_t now;
1302  linked_pointer<target> tp;
1303 
1304  time(&now);
1305 
1306  if(!saddr.getAddr() || !expires || expires < now || type == MappedRegistry::EXPIRED || type == MappedRegistry::TEMPORARY)
1307  return false;
1308 
1309  tp = source.internal.targets;
1310  while(tp) {
1311  if(Socket::equal(saddr.getAddr(), (struct sockaddr *)(&tp->address)))
1312  tp->expires = now - 10;
1313  else if(tp->expires >= now)
1314  ++active_count;
1315  tp.next();
1316  }
1317  if(!active_count) {
1318  registry::mapped save;
1319  Mutex::protect(this);
1320  store_unsafe<registry::mapped>(save, this);
1321  type = MappedRegistry::EXPIRED;
1322  expires = 0;
1323  Mutex::release(this);
1324  server::expire(&save);
1325  return true;
1326  }
1327 
1328  return false;
1329 }
1330 
1331 void registry::mapped::update(Socket::address& saddr, int changed)
1332 {
1333  time_t now;
1334  linked_pointer<target> tp;
1335 
1336  time(&now);
1337 
1338  if(changed == registry::target::UNKNOWN || !saddr.getAddr() || !expires || expires < now || !is_user())
1339  return;
1340 
1341  tp = source.internal.targets;
1342  while(tp) {
1343  if(Socket::equal(saddr.getAddr(), (struct sockaddr *)(&tp->address))) {
1344  if(tp->status != changed) {
1345  tp->status = (registry::target::status_t)changed;
1346  update();
1347  return;
1348  }
1349  }
1350  tp.next();
1351  }
1352 }
1353 
1354 bool registry::mapped::refresh(Socket::address& saddr, time_t lease, const char *target_contact)
1355 {
1356  assert(lease > 0);
1357 
1358  time_t now;
1359  linked_pointer<target> tp;
1360 
1361  time(&now);
1362 
1363  if(!saddr.getAddr() || !expires || expires < now || type == MappedRegistry::EXPIRED || type == MappedRegistry::TEMPORARY)
1364  return false;
1365 
1366  tp = source.internal.targets;
1367  while(tp) {
1368  if(Socket::equal(saddr.getAddr(), (struct sockaddr *)(&tp->address))) {
1369  char target_userid[MAX_USERID_SIZE];
1370  char contact_userid[MAX_USERID_SIZE];
1371 
1372  uri::userid(target_contact, target_userid, sizeof(target_userid));
1373  uri::userid(tp->contact, contact_userid, sizeof(contact_userid));
1374  if(String::equal(target_userid, contact_userid)) {
1375  Mutex::protect(this);
1376  if(lease > expires)
1377  expires = lease;
1378  Mutex::release(this);
1379  tp->expires = lease;
1380  return true;
1381  }
1382  }
1383  tp.next();
1384  }
1385  return false;
1386 }
1387 
1388 unsigned registry::mapped::addTarget(Socket::address& target_addr, time_t lease, const char *target_contact, const char *target_network, struct sockaddr *target_peering, voip::context_t context)
1389 {
1390  assert(!isnull(target_addr));
1391  assert(target_contact != NULL && *target_contact != 0);
1392  assert(lease > 0);
1393 
1394  Socket::address *origin;
1395  const struct sockaddr *ai, *oi = NULL;
1396  linked_pointer<target> tp;
1397  target *expired = NULL;
1398  time_t now;
1399  socklen_t len;
1400 
1401  ai = target_addr.getAddr();
1402  if(!ai)
1403  return 0;
1404 
1405  if(!context)
1406  context = stack::sip.out_context;
1407 
1408  locking.exclusive();
1409  tp = source.internal.targets;
1410  if(lease > expires)
1411  expires = lease;
1412 
1413  len = Socket::len(ai);
1414  time(&now);
1415  while(tp) {
1416  if(tp->expires < now)
1417  expired = *tp;
1418  if(Socket::equal((struct sockaddr *)(&tp->address), ai))
1419  break;
1420  tp.next();
1421  }
1422  if(tp) {
1423  if(expired && expired != *tp) {
1424  if(expired->index.address) {
1425  expired->index.delist(&addresses[Socket::keyindex(expired->index.address, keysize)]);
1426  expired->index.address = NULL;
1427  expired->index.registry = NULL;
1428  }
1429  expired->delist(&source.internal.targets);
1430  --count;
1431  delete expired;
1432  }
1433  if(tp->expires < now)
1434  time(&tp->created);
1435  tp->expires = lease;
1436  tp->context = context;
1437  Socket::store(&tp->peering, target_peering);
1438  String::set(tp->contact, sizeof(tp->contact), target_contact);
1439  String::set(tp->network, sizeof(tp->network), target_network);
1440  locking.share();
1441  return count;
1442  }
1443  if(!expired) {
1444  origin = stack::getAddress(target_contact);
1445  if(origin)
1446  oi = origin->getAddr();
1447 
1448  if(!oi)
1449  oi = ai;
1450  expired = new target;
1451  expired->context = context;
1452  expired->enlist(&source.internal.targets);
1453  expired->status = registry::target::READY;
1454  memcpy(&contact, oi, len);
1455  String::set(network, sizeof(network), target_network);
1456  uri::userid(target_contact, remote, sizeof(remote));
1457  if(origin)
1458  delete origin;
1459  ++count;
1460  }
1461  time(&expired->created);
1462  expired->expires = lease;
1463  expired->context = context;
1464  memcpy(&expired->address, ai, len);
1465  Socket::store(&expired->peering, target_peering);
1466  String::set(expired->contact, sizeof(expired->contact), target_contact);
1467  String::set(expired->network, sizeof(expired->network), target_network);
1468  expired->index.registry = this;
1469  expired->index.address = (struct sockaddr *)(&expired->address);
1470  expired->index.enlist(&addresses[Socket::keyindex(expired->index.address, keysize)]);
1471  locking.share();
1472  update();
1473  return count;
1474 }
1475 
1476 unsigned registry::mapped::setTargets(Socket::address& target_addr, voip::context_t context)
1477 {
1478  assert(!isnull(target_addr));
1479 
1480  stack::subnet *subnet;
1481  struct addrinfo *al;
1482  linked_pointer<target> tp;
1483  socklen_t len;
1484 
1485  al = target_addr.getList();
1486  if(!al)
1487  return 0;
1488 
1489  locking.exclusive();
1490  if(expires) {
1491  locking.share();
1492  return 0;
1493  }
1494 
1495  if(!context)
1496  context = stack::sip.out_context;
1497 
1498  tp = source.internal.targets;
1499  while(tp) {
1500  delete *tp;
1501  tp.next();
1502  }
1503  source.internal.targets = NULL;
1504  count = 0;
1505  while(al) {
1506  len = Socket::len(al->ai_addr);
1507 
1508  tp = new target;
1509  tp->context = context;
1510  time(&tp->created);
1511  subnet = server::getPolicy(al->ai_addr);
1512  if(subnet) {
1513  tp->peering = subnet->iface;
1514  String::set(tp->network, sizeof(tp->network), subnet->getId());
1515  }
1516  else {
1517  service::published(&tp->peering);
1518  String::set(tp->network, sizeof(tp->network), "*");
1519  }
1520  server::release(subnet);
1521  String::set(network, sizeof(network), tp->network);
1522  memcpy(&tp->address, al->ai_addr, len);
1523  memcpy(&contact, &tp->address, len);
1524  remote[0] = 0;
1525  stack::sipAddress(&tp->address, tp->contact, userid);
1526 
1527  tp->expires = 0l;
1528  tp->context = context;
1529  tp->status = registry::target::READY;
1530  tp->enlist(&source.internal.targets);
1531  ++count;
1532  al = al->ai_next;
1533  }
1534  expires = 0;
1535  locking.share();
1536  update();
1537  return count;
1538 }
1539 
1541 {
1542  caddr_t cp = (caddr_t)address;
1543  target *tp = NULL;
1544  size_t offset = (size_t)(&tp->address);
1545 
1546  if(!address)
1547  return NULL;
1548 
1549 
1550  cp -= offset;
1551  return reinterpret_cast<target *>(cp);
1552 }
1553 
1554 } // end namespace
void start(service *cfg)
Definition: registry.cpp:220
Some convenience methods for manipulating SIP uri's.
Definition: uri.h:55
struct sockaddr_internet address
Definition: server.h:120
static bool remove(const char *id)
Definition: registry.cpp:365
static stats * create(void)
Create stats in shared memory pool.
Definition: stats.cpp:47
static bool userid(const char *sipuri, char *buffer, size_t size)
Definition: uri.cpp:73
volatile time_t expires
Definition: server.h:126
static const char * getDomain(void)
Definition: registry.cpp:115
static Socket::address * getAddress(const char *uri, Socket::address *addr=NULL)
Definition: stack.cpp:1146
Pointer to a provisioned user xml subtree.
Definition: service.h:119
service::keynode * keys
Definition: service.h:122
User profiles are used to map features and toll restriction level together under a common identifier...
Definition: mapped.h:83
void assign(stat_t element)
Assign a call to inbound or outbound statistic for this stat node.
Definition: stats.cpp:83
static volatile dialmode_t dialmode
Definition: service.h:252
static unsigned getEntries(void)
Definition: registry.cpp:606
bool expire(Socket::address &addr)
Definition: registry.cpp:1298
static void clear(mapped *rr)
Definition: registry.cpp:344
unsigned setTargets(Socket::address &addr, voip::context_t context)
Definition: registry.cpp:1476
char prefix[MAX_USERID_SIZE]
Definition: server.h:141
void snapshot(FILE *fp)
Definition: registry.cpp:250
static stack::subnet * getPolicy(const struct sockaddr *addr)
Definition: server.cpp:686
void addRoute(const char *pat, unsigned pri, const char *prefix, const char *suffix)
Definition: registry.cpp:1185
Representation of a mapped active user record.
Definition: mapped.h:95
unsigned range
Definition: server.h:172
sockaddr_internet contact
Definition: mapped.h:111
keynode * getList(const char *path)
Definition: service.cpp:376
sipwitch::registry::target::indexing index
volatile time_t expires
Definition: mapped.h:113
static void reload(void)
Definition: digests.cpp:43
static unsigned cleanup(time_t period)
Definition: registry.cpp:452
char id[48]
Definition: mapped.h:84
static unsigned sip_prefix
Definition: service.h:204
char *volatile digest
Definition: server.h:169
bool is_profiled(void) const
Definition: mapped.h:131
void reload(service *cfg)
Definition: registry.cpp:484
void operator=(mapped *ptr)
Definition: registry.cpp:68
union sipwitch::MappedRegistry::@6 source
unsigned addTarget(Socket::address &via, time_t expires, const char *contact, const char *policy, struct sockaddr *peer, voip::context_t context)
Definition: registry.cpp:1388
static unsigned getIndex(mapped *rr)
Definition: registry.cpp:212
static registry reg
Definition: server.h:165
struct sockaddr_storage peering
Definition: server.h:121
static unsigned allocate(void)
Definition: server.cpp:1025
void stop(service *cfg)
Definition: registry.cpp:240
static const char * sip_realm
Definition: service.h:197
struct sockaddr_storage iface
Definition: server.h:409
volatile time_t expires
Definition: server.h:167
static mapped * contact(const char *uri)
Definition: registry.cpp:898
char realm[64]
Definition: events.h:104
static stack sip
Definition: server.h:398
static bool isUserid(const char *id)
Definition: registry.cpp:956
static void published(struct sockaddr_storage *peer)
Definition: service.cpp:295
static void expire(mapped *rr)
Definition: registry.cpp:388
static char session_uuid[40]
Definition: service.h:206
#define MAX_USERID_SIZE
Definition: mapped.h:69
char contact[MAX_URI_SIZE]
Definition: server.h:128
static bool match(const char *digits, const char *pattern, bool partial)
Definition: service.cpp:954
struct sipwitch::MappedRegistry::@6::@8 internal
static void release(stack::subnet *access)
Definition: server.cpp:594
static bool is_configured(void)
Definition: service.h:217
static mapped * address(const struct sockaddr *addr)
Definition: registry.cpp:869
char network[MAX_NETWORK_SIZE]
Definition: server.h:129
void release(stat_t element)
Release a call from inbound or outbound stastic for this stat node.
Definition: stats.cpp:104
static void incUse(mapped *rr, stats::stat_t stat)
Definition: registry.cpp:139
voip::context_t context
Definition: server.h:122
static bool isExtension(const char *id)
Definition: registry.cpp:972
static void detach(mapped *m)
Definition: registry.cpp:1100
struct sipwitch::MappedRegistry::@6::@7 external
void addPublished(const char *id)
Definition: registry.cpp:1207
char * value[96]
Definition: cgiserver.cpp:90
const char * getId(void)
Definition: server.h:411
unsigned routes
Definition: server.h:173
static pattern * getRouting(unsigned trs, const char *id)
Definition: registry.cpp:993
static bool exists(const char *id)
Definition: registry.cpp:1035
static void getProvision(const char *id, usernode &user)
Definition: server.cpp:850
void * context_t
Definition: voip.h:53
static mapped * getExtension(const char *id)
Definition: registry.cpp:1017
static char * sipAddress(struct sockaddr_internet *addr, char *buf, const char *user=NULL, size_t size=MAX_URI_SIZE)
Definition: stack.cpp:1079
static voip::context_t out_context
Definition: service.h:233
static void release(void)
Release stat nodes shared memory segment.
Definition: stats.cpp:98
bool refresh(Socket::address &addr, time_t expires, const char *target_contact)
Definition: registry.cpp:1354
char text[MAX_USERID_SIZE]
Definition: server.h:140
unsigned setTarget(Socket::address &via, time_t expires, const char *contact, const char *policy, struct sockaddr *peer, voip::context_t context)
Definition: registry.cpp:1113
static mapped * find(const char *id)
Definition: registry.cpp:195
bool check(void)
Definition: registry.cpp:232
static mapped * access(const char *id)
Definition: registry.cpp:1081
unsigned prefix
Definition: server.h:171
System configuration instance and service functions.
Definition: service.h:78
void addContact(const char *id)
Definition: registry.cpp:1223
char suffix[MAX_USERID_SIZE]
Definition: server.h:142
static void expire(MappedRegistry *rr)
Definition: server.cpp:162
static void decUse(mapped *rr, stats::stat_t stat)
Definition: registry.cpp:167
static unsigned sip_range
Definition: service.h:205
static mapped * dialing(const char *id)
Definition: registry.cpp:1055
static mapped * allocate(const char *id)
Definition: registry.cpp:678
char *volatile realm
Definition: server.h:170
volatile unsigned inuse
Definition: mapped.h:110
static profile_t * getProfile(const char *id)
Definition: server.cpp:703
static const char * env(const char *id)
Return the value of a server environment variable.
Definition: control.h:131
treemap< char * > keynode
Definition of a xml node.
Definition: service.h:84
#define DEBUG1
Definition: control.h:49
enum sipwitch::MappedRegistry::@5 type
static unsigned count
Definition: service.h:187
static mapped * invite(const char *id, stats::stat_t stat)
Definition: registry.cpp:611