SIP Witch 1.9.15
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
service.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 <sipwitch-config.h>
18 #include <ucommon/ucommon.h>
19 #include <ucommon/export.h>
20 #include <sipwitch/control.h>
21 #include <sipwitch/service.h>
22 #include <sipwitch/modules.h>
23 #include <sipwitch/events.h>
24 #include <ctype.h>
25 #include <errno.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <fcntl.h>
29 #include <new>
30 
31 #define RUNLEVELS (sizeof(callback::runlevels) / sizeof(LinkedObject *))
32 
33 namespace sipwitch {
34 
35 LinkedObject *service::callback::runlevels[4] = {NULL, NULL, NULL, NULL};
36 unsigned service::callback::count = 0;
37 unsigned short service::callback::sip_port = 5060;
39 unsigned service::callback::sip_range = 0;
40 const char *service::callback::sip_iface = NULL;
41 volatile char *service::callback::sip_contact = NULL;
42 volatile char *service::callback::sip_publish = NULL;
43 int service::callback::sip_protocol = IPPROTO_UDP;
44 int service::callback::sip_family = AF_INET;
47 const char *service::callback::sip_tlspwd = "";
48 const char *service::callback::sip_tlsdev = "/dev/random";
49 const char *service::callback::sip_tlsca = "/etc/ssl/ca.pem";
50 const char *service::callback::sip_tlsdh = "/etc/ssl/dh1024.pem";
51 const char *service::callback::sip_tlscert = "/etc/ssl/sipwitch.pem";
52 const char *service::callback::sip_tlskey = "/etc/ssl/private/sipwitch.key";
53 const char *service::callback::sip_realm = "unknown";
54 const char *service::callback::sip_domain = NULL;
56 condlock_t service::locking;
57 service *service::cfg = NULL;
59 
64 
65 static struct sockaddr_storage peering;
66 static time_t started = 0l;
67 static time_t periodic = 0l;
68 
69 static size_t xmldecode(char *out, size_t limit, const char *src)
70 {
71  assert(out != NULL);
72  assert(limit > 0);
73  assert(src != NULL);
74 
75  char *ret = out;
76 
77  if(*src == '\'' || *src == '\"')
78  ++src;
79  while(src && limit-- > 1 && !strchr("<\'\">", *src)) {
80  if(!strncmp(src, "&amp;", 5)) {
81  *(out++) = '&';
82  src += 5;
83  }
84  else if(!strncmp(src, "&lt;", 4)) {
85  src += 4;
86  *(out++) = '<';
87  }
88  else if(!strncmp(src, "&gt;", 4)) {
89  src += 4;
90  *(out++) = '>';
91  }
92  else if(!strncmp(src, "&quot;", 6)) {
93  src += 6;
94  *(out++) = '\"';
95  }
96  else if(!strncmp(src, "&apos;", 6)) {
97  src += 6;
98  *(out++) = '\'';
99  }
100  else
101  *(out++) = *(src++);
102  }
103  *out = 0;
104  return out - ret;
105 }
106 
108 {
109  keys = NULL;
110  heap = NULL;
111 }
112 
114 {
115  node = NULL;
116 }
117 
119 {
120  assert(id != NULL && *id != 0);
121 
122  locking.access();
123  node = service::path(id);
124 }
125 
127 {
128  node = copy.node;
129  locking.access();
130 }
131 
133 {
134  service::release(node);
135 }
136 
138 {
139  service::release(node);
140  node = p;
141 }
142 
145 {
146  crit(rl < (int)RUNLEVELS, "service runlevel invalid");
147  if(rl < 0) {
148  rl += RUNLEVELS;
149  crit(rl > 0, "service runlevel invalid");
150  }
151  LinkedObject::enlist(&runlevels[rl]);
152  active_flag = false;
153  runlevel = rl;
154  ++count;
155 }
156 
158 {
159  LinkedObject::delist(&runlevels[runlevel]);
160 }
161 
163 {
164  if(!uri)
165  return NULL;
166 
167  if(eq(uri, "sip:", 4) || eq(uri, "sip"))
168  return out_context;
169 
170  if(eq(uri, "sips:", 5) || eq(uri, "sips"))
171  return tls_context;
172 
173  if(eq(uri, "tcp:", 4) || eq(uri, "tcp"))
174  return tcp_context;
175 
176  if(eq(uri, "udp:", 4) || eq(uri, "udp"))
177  return udp_context;
178 
179  return NULL;
180 }
181 
183 {
184 }
185 
187 {
188  return true;
189 }
190 
191 void service::callback::errlog(shell::loglevel_t level, const char *text)
192 {
193 }
194 
196 {
197 }
198 
200 {
201 }
202 
204 {
205 }
206 
208 {
209 }
210 
212 {
213 }
214 
215 void service::callback::bind(const char *addr)
216 {
217  if(!addr)
218  return;
219 
220 #ifdef AF_INET6
221  if(strchr(addr, ':'))
222  sip_family = AF_INET6;
223 #endif
224 
225  if(eq(addr, ":::") || eq(addr, "::0") || eq(addr, "::*") || eq(addr, "*") || eq(addr, "0.0.0.0") || !*addr)
226  addr = NULL;
227 
228  sip_iface = addr;
229 }
230 
232 {
233  service::locking.access();
234 }
235 
237 {
238  service::locking.release();
239 }
240 
242 {
243  Parent = trunk;
244  if(Parent)
245  enlistTail(&trunk->Child);
246 }
247 
248 service::service(const char *name, size_t s) :
249 memalloc(s), root()
250 {
251  assert(name != NULL && *name != 0);
252 
253  root.setId((char *)name);
254  root.setPointer(NULL);
255 
256  contact = NULL;
257 
258  if(!started) {
259  time(&started);
260  time(&periodic);
261  }
262 }
263 
265 {
266  // we must zap the xml tree root node, lest it try to delete it's "id"
267  // or child nodes, since all was allocated from the "pager" heap.
268  reset_unsafe<keynode>(root);
269  memalloc::purge();
270 }
271 
272 void service::publish(const char *addr)
273 {
274  Socket::address resolver;
275  const struct sockaddr *host;
276 
277  if(!addr) {
278  memset(&peering, 0, sizeof(peering));
279  return;
280  }
281 
282  int i = 0;
283  resolver.set(addr, i);
284  host = resolver.getAddr();
285  if(host) {
286  volatile char *old = callback::sip_publish;
287  callback::sip_publish = strdup(addr);
288  if(old)
289  free((char *)old);
290  Socket::store(&peering, host);
291  events::publish(addr);
292  }
293 }
294 
295 void service::published(struct sockaddr_storage *peer)
296 {
297  memcpy(peer, &peering, sizeof(peering));
298 }
299 
300 long service::uptime(void)
301 {
302  time_t now;
303  time(&now);
304  if(!started)
305  return 0l;
306 
307  return (long)(now - started);
308 }
309 
311 {
312  assert(id != NULL && *id != 0);
313 
314  if(!cfg)
315  return NULL;
316 
317  return cfg->getPath(id);
318 }
319 
321 {
322  assert(id != NULL && *id != 0);
323 
324  keynode *node;
325 
326  if(!cfg)
327  return NULL;
328 
329  node = cfg->getPath(id);
330  if(node)
331  return node->getFirst();
332  return NULL;
333 }
334 
336 {
337  assert(id != NULL && *id != 0);
338  unsigned path;
339  linked_pointer<keymap> map;
340 
341  if(!cfg)
342  goto bail;
343 
344  locking.access();
345 
346  path = NamedObject::keyindex(id, CONFIG_KEY_SIZE);
347  map = cfg->keys[path];
348 
349  while(map) {
350  if(!stricmp(map->id, id))
351  return map->node;
352  map.next();
353  }
354 
355 bail:
356  locking.release();
357  return NULL;
358 }
359 
361 {
362  assert(id != NULL && *id != 0);
363 
364  keynode *node;
365 
366  if(!cfg)
367  return NULL;
368 
369  locking.access();
370  node = cfg->getPath(id);
371  if(!node)
372  locking.release();
373  return node;
374 }
375 
377 {
378  assert(path != NULL && *path != 0);
379 
380  keynode *base = getPath(path);
381  if(!base)
382  return NULL;
383 
384  return base->getFirst();
385 }
386 
388 {
389  if(cfg)
390  locking.access();
391  return &cfg->root;
392 }
393 
395 {
396  if(node)
397  locking.release();
398 }
399 
401 {
402  assert(id != NULL && *id != 0);
403 
404  const char *np;
405  char buf[65];
406  char *ep;
407  keynode *node = &root, *child;
408 
409  while(id && *id && node) {
410  String::set(buf, sizeof(buf), id);
411  ep = strchr(buf, '.');
412  if(ep)
413  *ep = 0;
414  np = strchr(id, '.');
415  if(np)
416  id = ++np;
417  else
418  id = NULL;
419  child = node->getChild(buf);
420  if(!child)
421  child = addNode(node, buf, NULL);
422  node = child;
423  }
424  return node;
425 }
426 
427 service::keynode *service::addNode(keynode *base, const char *id, const char *value)
428 {
429  assert(base != NULL);
430  assert(id != NULL && *id != 0);
431 
432  void *mp;
433  keynode *node;
434  char *cp;
435 
436  mp = memalloc::alloc(sizeof(keynode));
437  cp = dup(id);
438  node = new(mp) keynode(base, cp);
439  if(value)
440  node->setPointer(dup(value));
441  else
442  node->setPointer(NULL);
443  return node;
444 }
445 
446 const char *service::getValue(keynode *node, const char *id)
447 {
448  assert(node != NULL);
449  assert(id != NULL && *id != 0);
450 
451  node = node->getChild(id);
452  if(!node)
453  return NULL;
454 
455  return node->getPointer();
456 }
457 
459 {
460  assert(base != NULL);
461  assert(defs != NULL);
462 
463  keynode *node = getNode(base, defs->key, defs->value);
464  if(!node)
465  node = addNode(base, defs->key, defs->value);
466 
467  for(;;) {
468  ++defs;
469  if(!defs->key)
470  return base;
471  if(node->getChild(defs->key))
472  continue;
473  addNode(node, defs->key, defs->value);
474  }
475  return node;
476 }
477 
478 service::keynode *service::getNode(keynode *base, const char *id, const char *attr, const char *value)
479 {
480  assert(base != NULL);
481  assert(id != NULL && *id != 0);
482  assert(attr != NULL);
483  assert(value != NULL);
484 
485  linked_pointer<keynode> node = base->getFirst();
486  keynode *leaf;
487  char *cp;
488 
489  while(node) {
490  if(!strcmp(id, node->getId())) {
491  leaf = node->getLeaf(attr);
492  if(leaf) {
493  cp = leaf->getPointer();
494  if(cp && !stricmp(cp, value))
495  return *node;
496  }
497  }
498  node.next();
499  }
500  return NULL;
501 }
502 
503 service::keynode *service::getNode(keynode *base, const char *id, const char *text)
504 {
505  assert(base != NULL);
506  assert(id != NULL && *id != 0);
507  assert(text != NULL && *text != 0);
508 
509  linked_pointer<keynode> node = base->getFirst();
510  char *cp;
511 
512  while(node) {
513  if(!strcmp(id, node->getId())) {
514  cp = node->getPointer();
515  if(cp && !stricmp(cp, text))
516  return *node;
517  }
518  node.next();
519  }
520  return NULL;
521 }
522 
523 void service::addAttributes(keynode *node, char *attr)
524 {
525  assert(node != NULL);
526  assert(attr != NULL);
527 
528  char *ep, *qt;
529  char *id;
530  int len;
531 
532  while(attr && *attr && *attr != '>') {
533  while(isspace(*attr))
534  ++attr;
535 
536  if(!*attr || *attr == '>')
537  return;
538 
539  id = attr;
540  while(*attr && *attr != '=' && *attr != '>')
541  ++attr;
542 
543  if(*attr != '=')
544  return;
545 
546  *(attr++) = 0;
547  id = String::trim(id, " \t\r\n");
548  while(isspace(*attr))
549  ++attr;
550 
551  qt = attr;
552  ep = strchr(++attr, *qt);
553  if(!ep)
554  return;
555 
556  *(ep++) = 0;
557  len = strlen(attr);
558  qt = (char *)memalloc::alloc(len + 1);
559  xmldecode(qt, len + 1, attr);
560  addNode(node, id, qt);
561  attr = ep;
562  }
563 }
564 
565 bool service::load(FILE *fp, keynode *node)
566 {
567  assert(fp != NULL);
568 
569  char *cp, *ep, *bp, *id;
570  ssize_t len = 0;
571  bool rtn = false;
572  bool document = false, empty;
573  keynode *top;
574 
575  if(!node) {
576  node = &root;
577  top = NULL;
578  }
579  else
580  top = node->getParent();
581 
582  if(!fp)
583  return false;
584 
585  buffer = "";
586 
587  while(node != top) {
588  cp = buffer.c_mem() + buffer.len();
589  if(buffer.len() < 1024 - 5) {
590  len = fread(cp, 1, 1024 - buffer.len() - 1, fp);
591  }
592  else
593  len = 0;
594 
595  if(len < 0)
596  goto exit;
597 
598  cp[len] = 0;
599  if(!buffer.chr('<'))
600  goto exit;
601 
602  cp = buffer.c_mem();
603 
604  while(node != top && cp && *cp)
605  {
606  cp = String::trim(cp, " \t\r\n");
607 
608  if(cp && *cp && !node)
609  goto exit;
610 
611  bp = strchr(cp, '<');
612  if(bp == cp && String::equal(bp, "<!--", 4)) {
613  ep = strstr(cp, "-->");
614  if(ep) {
615  cp = ep + 3;
616  continue; // obscure bug?...
617  }
618  }
619  else
620  ep = strchr(cp, '>');
621  if(!ep && bp == cp)
622  break;
623  if(!bp ) {
624  cp = cp + strlen(cp);
625  break;
626  }
627  if(bp > cp) {
628  if(node->getPointer() != NULL)
629  goto exit;
630 
631  *bp = 0;
632  cp = String::chop(cp, " \r\n\t");
633  len = strlen(cp);
634  ep = (char *)memalloc::alloc(len + 1);
635  xmldecode(ep, len + 1, cp);
636  node->setPointer(ep);
637  *bp = '<';
638  cp = bp;
639  continue;
640  }
641 
642  empty = false;
643  *ep = 0;
644  if(*(ep - 1) == '/') {
645  *(ep - 1) = 0;
646  empty = true;
647  }
648  cp = ++ep;
649 
650  if(!strncmp(bp, "</", 2)) {
651  if(strcmp(bp + 2, node->getId())) {
652  shell::log(shell::ERR, "%s: %s\n",
653  _TEXT("No matching opening token found for"), node->getId());
654  goto exit;
655  }
656 
657  node = node->getParent();
658  continue;
659  }
660 
661  ++bp;
662 
663  // if comment/control field...
664  if(!isalnum(*bp))
665  continue;
666 
667  ep = bp;
668  while(isalnum(*ep))
669  ++ep;
670 
671  id = NULL;
672  if(isspace(*ep))
673  id = ep;
674 
675  while(id && *id && isspace(*id))
676  *(id++) = 0;
677 
678  if(!document) {
679  if(strcmp(node->getId(), bp))
680  goto exit;
681  document = true;
682  continue;
683  }
684 
685  node = addNode(node, bp, NULL);
686  if(id)
687  addAttributes(node, id);
688  if(empty)
689  node = node->getParent();
690  }
691  buffer = cp;
692  }
693  if(node == top)
694  rtn = true;
695 exit:
696  fclose(fp);
697  return rtn;
698 }
699 
701 {
702  linked_pointer<callback> sp;
703 
704  memset(&peering, 0, sizeof(peering));
705 
706  shell::log(shell::NOTIFY, "startup");
707 
708  cdr::start();
709 
710  for(unsigned int level = 0;level < (sizeof(callback::runlevels) / sizeof(LinkedObject *));++level) {
711  sp = callback::runlevels[level];
712  while(sp) {
713  sp->start(cfg);
714  sp.next();
715  }
716  }
717 }
718 
720 {
721  linked_pointer<callback> sp;
722  unsigned level = RUNLEVELS;
723 
724  while(level--) {
725  sp = callback::runlevels[level];
726  while(sp) {
727  sp->stop(cfg);
728  sp.next();
729  }
730  }
731 
732  cdr::stop();
733 }
734 
735 void service::dump(FILE *fp, service::keynode *root, unsigned level)
736 {
737  assert(fp != NULL);
738  assert(root != NULL);
739 
740  unsigned offset;
741  const char *id, *value;
742  service::keynode *child;
743  linked_pointer<service::keynode> node = root;
744  while(node) {
745  id = node->getId();
746  value = node->getPointer();
747  child = node->getFirst();
748  offset = level;
749  while(offset--)
750  fputc(' ', fp);
751  if(child && value && id)
752  fprintf(fp, "%s(%s):\n", id, value);
753  else if(child && id)
754  fprintf(fp, "%s:\n", id);
755  else if(value && id)
756  fprintf(fp, "%s=%s\n", id, value);
757  else if(id)
758  fprintf(fp, "%s\n", id);
759  if(child)
760  dump(fp, child, level + 2);
761  node.next();
762  }
763 }
764 
765 void service::dump(FILE *fp)
766 {
767  assert(fp != NULL);
768 
769  fprintf(fp, "Config ");
770  dump(fp, &root, 0);
771 }
772 
774 {
775  FILE *fp = control::output("dumpfile");
776 
777  if(!fp) {
778  shell::log(shell::ERR, "%s\n",
779  _TEXT("dump cannot access file"));
780  return;
781  }
782 
783  shell::log(DEBUG1, "%s\n",
784  _TEXT("dumping config"));
785  locking.access();
786  if(cfg)
787  cfg->service::dump(fp);
788  locking.release();
789  fclose(fp);
790 }
791 
792 string_t service::getContact(void)
793 {
794  string_t uri;
795  volatile char *vaddr = callback::sip_contact;
796  unsigned short port;
797  const char *addr = (const char *)vaddr;
798 
799  if(!addr)
800  addr = getInterface();
801 
802  if(!addr || eq(addr, "*")) {
803 #ifdef HAVE_GETHOSTNAME
804  static char hostbuf[256] = {0};
805  gethostname(hostbuf, sizeof(hostbuf));
806  if(hostbuf[0])
807  addr = hostbuf;
808  else
809  addr = "localhost";
810 #else
811  addr = "localhost";
812 #endif
813  }
814 
815  port = getPort();
816  if(port && port != 5060) {
817  if(strchr(addr, ':'))
818  uri = str("sip:[") + addr + "]:" + str(port);
819  else
820  uri = str("sip:") + addr + ":" + str(port);
821  }
822  else
823  uri = str("sip:") + addr;
824 
825  return uri;
826 }
827 
828 bool service::period(long slice)
829 {
830  assert(slice > 0);
831 
832  time_t now, next;
833 
834  slice *= 60l; // convert to minute intervals...
835  time(&now);
836  next = ((periodic / slice) + 1l) * slice;
837  if(now < next)
838  return false;
839 
840  next = (now / slice) * slice;
841 
842  FILE *fp = fopen(control::env("stats"), "a");
843 
844  if(fp) {
845  DateTimeString dt(periodic);
846  fprintf(fp, "%s %ld\n", (const char *)dt, (long)(next - periodic));
847  }
848  periodic = next;
849  stats::period(fp);
850  if(fp)
851  fclose(fp);
852 
853  linked_pointer<modules::sipwitch> cb = service::getModules();
854  while(is(cb)) {
855  cb->period(slice);
856  cb.next();
857  }
858  return true;
859 }
860 
862 {
863  linked_pointer<callback> cb;
864  unsigned rl = 0;
865  FILE *fp = control::output("snapshot");
866 
867  if(!fp) {
868  shell::log(shell::ERR, "%s\n",
869  _TEXT("snapshot; cannot access file"));
870  return;
871  }
872 
873  shell::log(DEBUG1, "%s\n", _TEXT("snapshot started"));
874 
875  while(rl < RUNLEVELS) {
876  cb = callback::runlevels[rl++];
877  while(cb) {
878  cb->snapshot(fp);
879  cb.next();
880  }
881  }
882  locking.access();
883  if(cfg)
884  cfg->dump(fp);
885  locking.release();
886  fclose(fp);
887  shell::log(DEBUG1, "%s\n", _TEXT("snapshot completed"));
888 }
889 
891 {
892 }
893 
894 bool service::check(void)
895 {
896  linked_pointer<callback> cb;
897  unsigned rl = 0;
898  bool rtn = true;
899 
900  while(rtn && rl < RUNLEVELS) {
901  cb = callback::runlevels[rl++];
902  while(rtn && is(cb)) {
903  rtn = cb->check();
904  cb.next();
905  }
906  }
907  return rtn;
908 }
909 
910 void service::commit(void)
911 {
912  service *orig;
913  linked_pointer<callback> cb;
914  unsigned rl = 0;
915 
916  events::notice("reloading config");
917 
918  while(rl < RUNLEVELS) {
919  cb = callback::runlevels[rl++];
920  while(is(cb)) {
921  cb->reload(this);
922  cb.next();
923  }
924  }
925 
926  confirm();
927 
928  locking.modify();
929  if(contact)
930  callback::sip_contact = (volatile char *)(contact);
931  orig = cfg;
932  cfg = this;
933  locking.commit();
934 
935  rl = 0;
936  while(rl < RUNLEVELS) {
937  cb = callback::runlevels[rl++];
938  while(is(cb)) {
939  cb->publish(this);
940  cb.next();
941  }
942  }
943 
944  // send any config related reload events...
945  events::reload();
946 
947  // let short-term volatile references settle before we delete it...
948  if(orig) {
949  Thread::sleep(1000);
950  delete orig;
951  }
952 }
953 
954 bool service::match(const char *digits, const char *match, bool partial)
955 {
956  assert(digits != NULL);
957  assert(match != NULL);
958 
959  unsigned len = strlen(match);
960  unsigned dlen = 0;
961  bool inc;
962  const char *d = digits;
963  char dbuf[32];
964 
965  if(*d == '+')
966  ++d;
967 
968  while(*d && dlen < sizeof(dbuf) - 1) {
969  if(isdigit(*d) || *d == '*' || *d == '#') {
970  dbuf[dlen++] = *(d++);
971  continue;
972  }
973 
974  if(*d == ' ' || *d == ',') {
975  ++d;
976  continue;
977  }
978 
979  if(*d == '!')
980  break;
981 
982  if(!stricmp(digits, match))
983  return true;
984 
985  return false;
986  }
987 
988  if(*d && *d != '!')
989  return false;
990 
991  digits = dbuf;
992  dbuf[dlen] = 0;
993 
994  if(*match == '+') {
995  ++match;
996  --len;
997  if(dlen < len)
998  return false;
999  digits += (len - dlen);
1000  }
1001 
1002  while(*match && *digits) {
1003  inc = true;
1004  switch(*match) {
1005  case 'x':
1006  case 'X':
1007  if(!isdigit(*digits))
1008  return false;
1009  break;
1010  case 'N':
1011  case 'n':
1012  if(*digits < '2' || *digits > '9')
1013  return false;
1014  break;
1015  case 'O':
1016  case 'o':
1017  if(*digits && *digits != '1')
1018  inc = false;
1019  break;
1020  case 'Z':
1021  case 'z':
1022  if(*digits < '1' || *digits > '9')
1023  return false;
1024  break;
1025  case '?':
1026  if(!*digits)
1027  return false;
1028  break;
1029  default:
1030  if(*digits != *match)
1031  return false;
1032  }
1033  if(*digits && inc)
1034  ++digits;
1035  ++match;
1036  }
1037  if(*match && !*digits)
1038  return partial;
1039 
1040  if(*match && *digits)
1041  return false;
1042 
1043  return true;
1044 }
1045 
1046 } // end namespace
Used for definitions of plugin modules.
const char * value
Definition: service.h:96
Some convenience methods for manipulating SIP uri's.
Definition: uri.h:55
static volatile char * sip_publish
Definition: service.h:191
virtual void snapshot(FILE *fp)
Definition: service.cpp:182
static void release(keynode *node)
Definition: service.cpp:394
stringbuf< 1024 > buffer
Definition: service.h:339
void addAttributes(keynode *node, char *attrib)
Add attributes in a XML entity as child nodes of the xml node.
Definition: service.cpp:523
static voip::context_t udp_context
Definition: service.h:235
static volatile char * sip_contact
Definition: service.h:190
virtual void stop(service *cfg)
Definition: service.cpp:211
service::keynode * keys
Definition: service.h:122
static voip::context_t tls_context
Definition: service.h:236
static volatile dialmode_t dialmode
Definition: service.h:252
static const char * getInterface(void)
Definition: service.h:312
static void start(void)
Start cdr subsystem and que dispatch thread.
Definition: cdr.cpp:146
virtual ~service()
Definition: service.cpp:264
static void startup(void)
Definition: service.cpp:700
void operator=(keynode *node)
Definition: service.cpp:137
virtual void start(service *cfg)
Definition: service.cpp:207
static keynode * getUser(const char *uid)
Definition: service.cpp:335
Used to splice new chains onto an existing xml tree.
Definition: service.h:105
keynode * getList(const char *path)
Definition: service.cpp:376
static unsigned sip_prefix
Definition: service.h:204
static void snapshot(void)
Definition: service.cpp:861
static void publish(const char *addr)
Set and publish public "appearing" address of the server.
Definition: service.cpp:272
service(const char *name, size_t s=0)
Definition: service.cpp:248
virtual void publish(service *cfg)
Definition: service.cpp:203
static void bind(unsigned short port)
Definition: service.h:238
static LinkedObject * getModules(void)
Definition: service.h:270
static void publish(const char *address)
Update publish address...
Definition: events.cpp:380
#define CONFIG_KEY_SIZE
Definition: service.h:65
static void dumpfile(void)
Definition: service.cpp:773
static voip::context_t tcp_context
Definition: service.h:234
static const char * sip_iface
Definition: service.h:189
keynode root
Definition: service.h:338
Keyword and value pair definition lists.
Definition: service.h:94
static void dump(FILE *fp, keynode *node, unsigned level)
Definition: service.cpp:735
static LinkedObject * runlevels[4]
Definition: service.h:186
static const char * sip_realm
Definition: service.h:197
bool load(FILE *file, keynode *node=NULL)
Load xml file into xml tree.
Definition: service.cpp:565
static void notice(const char *reason)
Send notice to user.
Definition: events.cpp:336
static void shutdown(void)
Definition: service.cpp:719
static condlock_t locking
Definition: service.h:344
keynode * addNode(keynode *base, define *defs)
Definition: service.cpp:458
Stream events to local clients.
static void reload(void)
Refresh clients with any config events...
Definition: events.cpp:363
static long uptime(void)
Definition: service.cpp:300
static service * cfg
Definition: service.h:343
static void published(struct sockaddr_storage *peer)
Definition: service.cpp:295
static bool static FILE * output(const char *id)
Used to open an output session for returning control data.
Definition: control.cpp:380
static char session_uuid[40]
Definition: service.h:206
const char * contact
Definition: service.h:341
virtual bool check(void)
Definition: service.cpp:186
static bool match(const char *digits, const char *pattern, bool partial)
Definition: service.cpp:954
static keynode * path(const char *p)
Definition: service.cpp:310
unsigned long period
Definition: stats.h:69
void splice(keyclone *trunk)
Definition: service.cpp:241
static unsigned short getPort(void)
Definition: service.h:315
const char * key
Definition: service.h:95
static const char * sip_tlskey
Definition: service.h:202
static const char * sip_domain
Definition: service.h:196
static const char * sip_tlsdh
Definition: service.h:201
static string_t getContact(void)
Definition: service.cpp:792
static keynode * list(const char *p)
Definition: service.cpp:320
static void stop(void)
Stop cdr subsystem.
Definition: cdr.cpp:151
static const char * sip_tlsca
Definition: service.h:200
char * name[96]
Definition: cgiserver.cpp:88
voip::context_t getContext(const char *uri)
Definition: service.cpp:162
char * value[96]
Definition: cgiserver.cpp:90
virtual void errlog(shell::loglevel_t level, const char *text)
Definition: service.cpp:191
#define RUNLEVELS
Definition: service.cpp:31
void * context_t
Definition: voip.h:53
A pointer to a subtree in the xml configuration tree.
Definition: service.h:130
static bool period(long slice)
Definition: service.cpp:828
Service configuration and component callbacks.
static voip::context_t out_context
Definition: service.h:233
dialmode_t
Dialing mode supported.
Definition: service.h:89
keynode * getNode(keynode *base, const char *id, const char *value)
Definition: service.cpp:503
static bool check(void)
Definition: service.cpp:894
static const char * sip_tlsdev
Definition: service.h:199
static const char * sip_tlscert
Definition: service.h:203
System configuration instance and service functions.
Definition: service.h:78
Manage control interface.
static unsigned short sip_port
Definition: service.h:188
static keynode * get(void)
Definition: service.cpp:387
Interface class for call detail records.
Definition: cdr.h:56
char * map[96]
Definition: cgiserver.cpp:89
static unsigned sip_range
Definition: service.h:205
static const char * getValue(keynode *base, const char *id)
Definition: service.cpp:446
static const char * sip_tlspwd
Definition: service.h:198
keynode * getPath(const char *path)
Definition: service.cpp:400
static const char * env(const char *id)
Return the value of a server environment variable.
Definition: control.h:131
LinkedObject * keys[177]
Definition: service.h:340
treemap< char * > keynode
Definition of a xml node.
Definition: service.h:84
void commit(void)
Definition: service.cpp:910
static keynode * getProtected(const char *path)
Definition: service.cpp:360
virtual void cdrlog(cdr *call)
Definition: service.cpp:195
#define DEBUG1
Definition: control.h:49
virtual void confirm(void)
Definition: service.cpp:890
virtual void reload(service *cfg)
Definition: service.cpp:199
static unsigned count
Definition: service.h:187