SIP Witch 1.9.15: service.cpp Source File

SIP Witch 1.9.15
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;
38 unsigned service::callback::sip_prefix = 0;
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;
45 int service::callback::sip_tlsmode = 0;
46 bool service::callback::sip_public = false;
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;
55 char service::callback::session_uuid[40];
56 condlock_t service::locking;
57 service *service::cfg = NULL;
58 volatile service::dialmode_t service::dialmode = service::ALL_DIALING;
59 
60 voip::context_t service::callback::out_context = NULL;
61 voip::context_t service::callback::tcp_context = NULL;
62 voip::context_t service::callback::udp_context = NULL;
63 voip::context_t service::callback::tls_context = NULL;
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 
107  service::usernode::usernode()
108 {
109  keys = NULL;
110  heap = NULL;
111 }
112 
113  service::pointer::pointer()
114 {
115  node = NULL;
116 }
117 
118  service::pointer::pointer(const char *id)
119 {
120  assert(id != NULL && *id != 0);
121 
122  locking.access();
123  node = service::path(id);
124 }
125 
126  service::pointer::pointer(pointer const &copy)
127 {
128  node = copy.node;
129  locking.access();
130 }
131 
132  service::pointer::~pointer()
133 {
134  service::release(node);
135 }
136 
137  void service::pointer::operator=(keynode *p)
138 {
139  service::release(node);
140  node = p;
141 }
142 
143  service::callback::callback(int rl) :
144 OrderedObject()
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 
157  service::callback::~callback()
158 {
159  LinkedObject::delist(&runlevels[runlevel]);
160 }
161 
162  voip::context_t service::callback::getContext(const char *uri)
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 
182  void service::callback::snapshot(FILE *fp)
183 {
184 }
185 
186  bool service::callback::check(void)
187 {
188  return true;
189 }
190 
191  void service::callback::errlog(shell::loglevel_t level, const char *text)
192 {
193 }
194 
195  void service::callback::cdrlog(cdr *cdr)
196 {
197 }
198 
199  void service::callback::reload(service *keys)
200 {
201 }
202 
203  void service::callback::publish(service *keys)
204 {
205 }
206 
207  void service::callback::start(service *keys)
208 {
209 }
210 
211  void service::callback::stop(service *keys)
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 
231  service::instance::instance()
232 {
233  service::locking.access();
234 }
235 
236  service::instance::~instance()
237 {
238  service::locking.release();
239 }
240 
241  void service::keyclone::splice(keyclone *trunk)
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 
264  service::~service()
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 
310  service::keynode *service::path(const char *id)
311 {
312  assert(id != NULL && *id != 0);
313 
314  if(!cfg)
315  return NULL;
316 
317  return cfg->getPath(id);
318 }
319 
320  service::keynode *service::list(const char *id)
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 
335  service::keynode *service::getUser(const char *id)
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 
360  service::keynode *service::getProtected(const char *id)
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 
376  service::keynode *service::getList(const char *path)
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 
387  service::keynode *service::get(void)
388 {
389  if(cfg)
390  locking.access();
391  return &cfg->root;
392 }
393 
394  void service::release(keynode *node)
395 {
396  if(node)
397  locking.release();
398 }
399 
400  service::keynode *service::getPath(const char *id)
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 
458  service::keynode *service::addNode(keynode *base, define *defs)
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 
700  void service::startup(void)
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 
719  void service::shutdown(void)
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 
773  void service::dumpfile(void)
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 
861  void service::snapshot(void)
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 
890  void service::confirm(void)
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
modules.h
Used for definitions of plugin modules.
sipwitch::service::define::value
const char * value
Definition: service.h:96
sipwitch::uri
Some convenience methods for manipulating SIP uri's.
Definition: uri.h:55
sipwitch::service::callback::sip_publish
static volatile char * sip_publish
Definition: service.h:191
sipwitch::service::callback::snapshot
virtual void snapshot(FILE *fp)
Definition: service.cpp:182
sipwitch::service::release
static void release(keynode *node)
Definition: service.cpp:394
sipwitch::service::buffer
stringbuf< 1024 > buffer
Definition: service.h:339
sipwitch::service::addAttributes
void addAttributes(keynode *node, char *attrib)
Add attributes in a XML entity as child nodes of the xml node.
Definition: service.cpp:523
sipwitch::service::callback::udp_context
static voip::context_t udp_context
Definition: service.h:235
sipwitch::service::callback::sip_contact
static volatile char * sip_contact
Definition: service.h:190
sipwitch::service::callback::stop
virtual void stop(service *cfg)
Definition: service.cpp:211
sipwitch::service::usernode::keys
service::keynode * keys
Definition: service.h:122
sipwitch::service::callback::tls_context
static voip::context_t tls_context
Definition: service.h:236
sipwitch::service::dialmode
static volatile dialmode_t dialmode
Definition: service.h:252
sipwitch::service::getInterface
static const char * getInterface(void)
Definition: service.h:312
sipwitch::cdr::start
static void start(void)
Start cdr subsystem and que dispatch thread.
Definition: cdr.cpp:146
sipwitch::service::~service
virtual ~service()
Definition: service.cpp:264
sipwitch::service::startup
static void startup(void)
Definition: service.cpp:700
sipwitch::service::pointer::operator=
void operator=(keynode *node)
Definition: service.cpp:137
sipwitch::service::callback::start
virtual void start(service *cfg)
Definition: service.cpp:207
sipwitch::service::getUser
static keynode * getUser(const char *uid)
Definition: service.cpp:335
sipwitch::service::keyclone
Used to splice new chains onto an existing xml tree.
Definition: service.h:105
sipwitch::service::getList
keynode * getList(const char *path)
Definition: service.cpp:376
sipwitch::service::callback::sip_public
static bool sip_public
Definition: service.h:195
sipwitch::service::callback::sip_prefix
static unsigned sip_prefix
Definition: service.h:204
sipwitch::service::snapshot
static void snapshot(void)
Definition: service.cpp:861
sipwitch::service::publish
static void publish(const char *addr)
Set and publish public "appearing" address of the server.
Definition: service.cpp:272
sipwitch::service::service
service(const char *name, size_t s=0)
Definition: service.cpp:248
sipwitch::service::callback::publish
virtual void publish(service *cfg)
Definition: service.cpp:203
sipwitch::service::callback::bind
static void bind(unsigned short port)
Definition: service.h:238
sipwitch::service::getModules
static LinkedObject * getModules(void)
Definition: service.h:270
sipwitch::events::publish
static void publish(const char *address)
Update publish address...
Definition: events.cpp:380
CONFIG_KEY_SIZE
#define CONFIG_KEY_SIZE
Definition: service.h:65
sipwitch::service::dumpfile
static void dumpfile(void)
Definition: service.cpp:773
sipwitch::service::callback::tcp_context
static voip::context_t tcp_context
Definition: service.h:234
sipwitch::service::callback::sip_iface
static const char * sip_iface
Definition: service.h:189
sipwitch::service::root
keynode root
Definition: service.h:338
sipwitch::service::define
Keyword and value pair definition lists.
Definition: service.h:94
sipwitch::service::dump
static void dump(FILE *fp, keynode *node, unsigned level)
Definition: service.cpp:735
sipwitch::service::callback::runlevels
static LinkedObject * runlevels[4]
Definition: service.h:186
sipwitch::service::callback::sip_realm
static const char * sip_realm
Definition: service.h:197
sipwitch::service::load
bool load(FILE *file, keynode *node=NULL)
Load xml file into xml tree.
Definition: service.cpp:565
sipwitch::events::notice
static void notice(const char *reason)
Send notice to user.
Definition: events.cpp:336
sipwitch::service::shutdown
static void shutdown(void)
Definition: service.cpp:719
sipwitch::service::locking
static condlock_t locking
Definition: service.h:344
sipwitch::service::addNode
keynode * addNode(keynode *base, define *defs)
Definition: service.cpp:458
events.h
Stream events to local clients.
sipwitch::events::reload
static void reload(void)
Refresh clients with any config events...
Definition: events.cpp:363
sipwitch::service::callback::sip_tlsmode
static int sip_tlsmode
Definition: service.h:194
sipwitch::service::uptime
static long uptime(void)
Definition: service.cpp:300
sipwitch::service::cfg
static service * cfg
Definition: service.h:343
sipwitch::service::published
static void published(struct sockaddr_storage *peer)
Definition: service.cpp:295
sipwitch::control::output
static bool static FILE * output(const char *id)
Used to open an output session for returning control data.
Definition: control.cpp:380
sipwitch::service::callback::session_uuid
static char session_uuid[40]
Definition: service.h:206
sipwitch::service::contact
const char * contact
Definition: service.h:341
sipwitch::service::callback::callback
callback(int level=0)
Definition: service.cpp:143
sipwitch::service::callback::check
virtual bool check(void)
Definition: service.cpp:186
sipwitch::service::match
static bool match(const char *digits, const char *pattern, bool partial)
Definition: service.cpp:954
sipwitch::service::path
static keynode * path(const char *p)
Definition: service.cpp:310
sipwitch::stats::period
unsigned long period
Definition: stats.h:69
sipwitch::service::keyclone::splice
void splice(keyclone *trunk)
Definition: service.cpp:241
sipwitch::service::getPort
static unsigned short getPort(void)
Definition: service.h:315
sipwitch::service::define::key
const char * key
Definition: service.h:95
sipwitch::service::callback::sip_tlskey
static const char * sip_tlskey
Definition: service.h:202
sipwitch::service::callback::sip_domain
static const char * sip_domain
Definition: service.h:196
sipwitch::service::callback::sip_tlsdh
static const char * sip_tlsdh
Definition: service.h:201
sipwitch::service::getContact
static string_t getContact(void)
Definition: service.cpp:792
sipwitch::service::list
static keynode * list(const char *p)
Definition: service.cpp:320
sipwitch::cdr::stop
static void stop(void)
Stop cdr subsystem.
Definition: cdr.cpp:151
sipwitch::service::callback::sip_tlsca
static const char * sip_tlsca
Definition: service.h:200
name
char * name[96]
Definition: cgiserver.cpp:88
sipwitch::service::callback::getContext
voip::context_t getContext(const char *uri)
Definition: service.cpp:162
value
char * value[96]
Definition: cgiserver.cpp:90
sipwitch::service::callback::errlog
virtual void errlog(shell::loglevel_t level, const char *text)
Definition: service.cpp:191
RUNLEVELS
#define RUNLEVELS
Definition: service.cpp:31
sipwitch::voip::context_t
void * context_t
Definition: voip.h:53
sipwitch::service::pointer
A pointer to a subtree in the xml configuration tree.
Definition: service.h:130
sipwitch::service::period
static bool period(long slice)
Definition: service.cpp:828
service.h
Service configuration and component callbacks.
sipwitch::service::callback::out_context
static voip::context_t out_context
Definition: service.h:233
sipwitch::service::dialmode_t
dialmode_t
Dialing mode supported.
Definition: service.h:89
sipwitch::service::getNode
keynode * getNode(keynode *base, const char *id, const char *value)
Definition: service.cpp:503
sipwitch::service::check
static bool check(void)
Definition: service.cpp:894
sipwitch::service::callback::sip_tlsdev
static const char * sip_tlsdev
Definition: service.h:199
sipwitch::service::callback::sip_family
static int sip_family
Definition: service.h:193
sipwitch::service::callback::sip_tlscert
static const char * sip_tlscert
Definition: service.h:203
sipwitch::service::callback::sip_protocol
static int sip_protocol
Definition: service.h:192
sipwitch::service
System configuration instance and service functions.
Definition: service.h:78
control.h
Manage control interface.
sipwitch::service::callback::sip_port
static unsigned short sip_port
Definition: service.h:188
sipwitch::service::get
static keynode * get(void)
Definition: service.cpp:387
sipwitch::cdr
Interface class for call detail records.
Definition: cdr.h:56
map
char * map[96]
Definition: cgiserver.cpp:89
sipwitch::service::callback::sip_range
static unsigned sip_range
Definition: service.h:205
sipwitch::service::getValue
static const char * getValue(keynode *base, const char *id)
Definition: service.cpp:446
sipwitch::service::callback::sip_tlspwd
static const char * sip_tlspwd
Definition: service.h:198
sipwitch::service::getPath
keynode * getPath(const char *path)
Definition: service.cpp:400
sipwitch::control::env
static const char * env(const char *id)
Return the value of a server environment variable.
Definition: control.h:131
sipwitch::service::keys
LinkedObject * keys[177]
Definition: service.h:340
sipwitch::service::keynode
treemap< char * > keynode
Definition of a xml node.
Definition: service.h:84
sipwitch::service::commit
void commit(void)
Definition: service.cpp:910
sipwitch::service::getProtected
static keynode * getProtected(const char *path)
Definition: service.cpp:360
sipwitch::service::callback::cdrlog
virtual void cdrlog(cdr *call)
Definition: service.cpp:195
DEBUG1
#define DEBUG1
Definition: control.h:49
sipwitch::service::confirm
virtual void confirm(void)
Definition: service.cpp:890
sipwitch::service::callback::reload
virtual void reload(service *cfg)
Definition: service.cpp:199
sipwitch::service::callback::count
static unsigned count
Definition: service.h:187

Generated on Dec 21, 2017 for sipwitch-1.9.15 (*.h and *.cpp), libosip2-5.0.0 (*.h) and libeXosip2-4.0.0 (*.h), by   doxygen 1.8.6

AltStyle によって変換されたページ (->オリジナル) /