RTS API Documentation  1.10.11
switch_utils.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Juan Jose Comellas <juanjo@comellas.org>
28  * Seven Du <dujinfang@gmail.com>
29  * Windy Wang <xiaofengcanyuexp@163.com>
30  *
31  * switch_utils.c -- Compatibility and Helper Code
32  *
33  */
34 
35 #include <switch.h>
36 #include "private/switch_apr_pvt.h"
37 #ifndef WIN32
38 #include <arpa/inet.h>
39 #if defined(HAVE_SYS_TIME_H) && defined(HAVE_SYS_RESOURCE_H)
40 #include <sys/time.h>
41 #include <sys/resource.h>
42 #endif
43 #include <sys/types.h>
44 #include <unistd.h>
45 #else
46 #include <intsafe.h> /* SIZETMult() */
47  /* process.h is required for _getpid() */
48 #include <process.h>
49 #endif
51 #define ESCAPE_META '\\'
52 #ifdef SWITCH_HAVE_GUMBO
53 #include "gumbo.h"
54 #endif
55 
56 #if defined(HAVE_OPENSSL)
57 #include <openssl/evp.h>
58 #include <openssl/hmac.h>
59 #include <openssl/sha.h>
60 #endif
61 
62 #ifdef __GLIBC__
63 #include <malloc.h> /* mallinfo() */
64 #endif
65 
69  uint32_t bits;
70  int family;
72  char *token;
73  char *str;
76 };
78 
83  char *name;
84 };
85 
86 SWITCH_DECLARE(void *) switch_calloc(size_t nmemb, size_t size)
87 {
88  return calloc(nmemb, size);
89 }
90 
91 #ifndef WIN32
92 SWITCH_DECLARE(int) switch_inet_pton(int af, const char *src, void *dst)
93 {
94  return inet_pton(af, src, dst);
95 }
96 #endif
97 
99 {
100  switch_port_t port;
101 
102  switch_get_addr(buf, len, addr);
103  port = switch_sockaddr_get_port(addr);
104 
105  snprintf(buf + strlen(buf), len - strlen(buf), ":%d", port);
106  return buf;
107 }
108 
110 {
111  switch_frame_t *new_frame;
112 
113  switch_zmalloc(new_frame, sizeof(*new_frame));
114 
115  switch_set_flag(new_frame, SFF_DYNAMIC);
116  new_frame->buflen = (uint32_t)size;
117  new_frame->data = malloc(size);
118  switch_assert(new_frame->data);
119 
120  *frame = new_frame;
121 
122  return SWITCH_STATUS_SUCCESS;
123 }
124 
125 
126 typedef struct switch_frame_node_s {
128  int inuse;
132 
138  uint32_t total;
139 };
140 
142 {
144 
146 
147  for (np = fb->head; np; np = np->next) {
148  if (!np->inuse && ((orig->packet && np->frame->packet) || (!orig->packet && !np->frame->packet))) {
149 
150  if (np == fb->head) {
151  fb->head = np->next;
152  } else if (np->prev) {
153  np->prev->next = np->next;
154  }
155 
156  if (np->next) {
157  np->next->prev = np->prev;
158  }
159 
160  fb->total--;
161  np->prev = np->next = NULL;
162  break;
163  }
164  }
165 
166  if (!np) {
167  np = switch_core_alloc(fb->pool, sizeof(*np));
168  np->frame = switch_core_alloc(fb->pool, sizeof(*np->frame));
169 
170  if (orig->packet) {
172  } else {
173  np->frame->packet = NULL;
176  }
177  }
178 
179  np->frame->samples = orig->samples;
180  np->frame->rate = orig->rate;
181  np->frame->channels = orig->channels;
182  np->frame->payload = orig->payload;
183  np->frame->timestamp = orig->timestamp;
184  np->frame->seq = orig->seq;
185  np->frame->ssrc = orig->ssrc;
186  np->frame->m = orig->m;
187  np->frame->flags = orig->flags;
188  np->frame->codec = orig->codec;
189  np->frame->pmap = orig->pmap;
190  np->frame->img = NULL;
191  np->frame->extra_data = np;
192  np->inuse = 1;
193 
195 
196  if (orig->packet) {
197  memcpy(np->frame->packet, orig->packet, orig->packetlen);
198  np->frame->packetlen = orig->packetlen;
199  np->frame->data = ((unsigned char *)np->frame->packet) + 12;
200  np->frame->datalen = orig->datalen;
201  } else {
202  np->frame->packet = NULL;
203  np->frame->packetlen = 0;
204  memcpy(np->frame->data, orig->data, orig->datalen);
205  np->frame->datalen = orig->datalen;
206  }
207 
208  if (orig->img && !switch_test_flag(orig, SFF_ENCODED)) {
209  switch_img_copy(orig->img, &np->frame->img);
210  }
211 
213 
214  return np->frame;
215 }
216 
218 {
219  switch_frame_t *old_frame;
220  switch_frame_node_t *node;
221 
223 
224  old_frame = *frameP;
225  *frameP = NULL;
226 
227  node = (switch_frame_node_t *) old_frame->extra_data;
228  node->inuse = 0;
229  switch_img_free(&node->frame->img);
230 
231  fb->total++;
232 
233  if (fb->head) {
234  fb->head->prev = node;
235  }
236 
237  node->next = fb->head;
238  node->prev = NULL;
239  fb->head = node;
240 
241  switch_assert(node->next != node);
242  switch_assert(node->prev != node);
243 
244 
246 
247  return SWITCH_STATUS_SUCCESS;
248 }
249 
251 {
252  switch_frame_t *new_frame;
253 
254  if (!orig) {
255  return SWITCH_STATUS_FALSE;
256  }
257 
258  switch_assert(orig->buflen);
259 
260  new_frame = find_free_frame(fb, orig);
261 
262  *clone = new_frame;
263 
264  return SWITCH_STATUS_SUCCESS;
265 }
266 
268 {
269  return switch_queue_push(fb->queue, ptr);
270 }
271 
273 {
274  return switch_queue_trypush(fb->queue, ptr);
275 }
276 
278 {
279  return switch_queue_pop(fb->queue, ptr);
280 }
281 
283 {
284  return switch_queue_trypop(fb->queue, ptr);
285 }
286 
288 {
289  return switch_queue_size(fb->queue);
290 }
291 
293 {
294  switch_frame_buffer_t *fb = *fbP;
296  *fbP = NULL;
297  pool = fb->pool;
299 
300  return SWITCH_STATUS_SUCCESS;
301 }
302 
304 {
307 
308  if (!qlen) qlen = 500;
309 
311  fb = switch_core_alloc(pool, sizeof(*fb));
312  fb->pool = pool;
313  switch_queue_create(&fb->queue, qlen, fb->pool);
315  *fbP = fb;
316 
317  return SWITCH_STATUS_SUCCESS;
318 }
319 
320 
322 {
323  switch_frame_t *new_frame;
324 
325  if (!orig) {
326  return SWITCH_STATUS_FALSE;
327  }
328 
329  switch_assert(orig->buflen);
330 
331  new_frame = malloc(sizeof(*new_frame));
332  switch_assert(new_frame);
333 
334  *new_frame = *orig;
335  switch_set_flag(new_frame, SFF_DYNAMIC);
336 
337  if (orig->packet) {
338  new_frame->packet = malloc(SWITCH_RTP_MAX_BUF_LEN);
339  switch_assert(new_frame->packet);
340  memcpy(new_frame->packet, orig->packet, orig->packetlen);
341  new_frame->data = ((unsigned char *)new_frame->packet) + 12;
342  } else {
343  new_frame->packet = NULL;
344  new_frame->data = malloc(new_frame->buflen);
345  switch_assert(new_frame->data);
346  memcpy(new_frame->data, orig->data, orig->datalen);
347  }
348 
349 
350  new_frame->codec = orig->codec;
351  new_frame->pmap = orig->pmap;
352  new_frame->img = NULL;
353 
354 
355  if (orig->img && !switch_test_flag(orig, SFF_ENCODED)) {
356  switch_img_copy(orig->img, &new_frame->img);
357  }
358  *clone = new_frame;
359 
360  return SWITCH_STATUS_SUCCESS;
361 }
362 
364 {
365  switch_frame_t * f;
366 
367  if (!frame) {
368  return SWITCH_STATUS_FALSE;
369  }
370 
371  f = *frame;
372 
373  if (!f || !switch_test_flag(f, SFF_DYNAMIC)) {
374  return SWITCH_STATUS_FALSE;
375  }
376 
377  *frame = NULL;
378 
379  if (f->img) {
380  switch_img_free(&(f->img));
381  }
382 
383  if (f->packet) {
385  } else {
387  }
388 
389  free(f);
390 
391  return SWITCH_STATUS_SUCCESS;
392 }
393 
395 {
396  va_list ap;
397  const char *next_str = 0;
398  int r = 0;
399 
400  va_start(ap, str);
401 
402  while ((next_str = va_arg(ap, const char *))) {
403  if (!strcasecmp(str, next_str)) {
404  r = 1;
405  break;
406  }
407  }
408 
409  va_end(ap);
410 
411  return r;
412 }
413 
414 
415 SWITCH_DECLARE(char *) switch_find_parameter(const char *str, const char *param, switch_memory_pool_t *pool)
416 {
417  char *e, *r = NULL, *ptr = NULL, *next = NULL;
418  size_t len;
419 
420  ptr = (char *) str;
421 
422  while (ptr) {
423  len = strlen(param);
424  e = ptr+len;
425  next = strchr(ptr, ';');
426 
427  if (!strncasecmp(ptr, param, len) && *e == '=') {
428  size_t mlen;
429 
430  ptr = ++e;
431 
432  if (next) {
433  e = next;
434  } else {
435  e = ptr + strlen(ptr);
436  }
437 
438  mlen = (e - ptr) + 1;
439 
440  if (pool) {
441  r = switch_core_alloc(pool, mlen);
442  } else {
443  r = malloc(mlen);
444  }
445 
446  switch_snprintf(r, mlen, "%s", ptr);
447 
448  break;
449  }
450 
451  if (next) {
452  ptr = next + 1;
453  } else break;
454  }
455 
456  return r;
457 }
458 
461 {
462  switch_network_list_t *new_list;
463 
464  if (!pool) {
466  }
467 
468  new_list = switch_core_alloc(pool, sizeof(**list));
469  new_list->pool = pool;
470  new_list->default_type = default_type;
471  new_list->name = switch_core_strdup(new_list->pool, name);
472 
473  *list = new_list;
474 
475  return SWITCH_STATUS_SUCCESS;
476 }
477 
478 #define IN6_AND_MASK(result, ip, mask) \
479  ((uint32_t *) (result))[0] =((const uint32_t *) (ip))[0] & ((const uint32_t *)(mask))[0]; \
480  ((uint32_t *) (result))[1] =((const uint32_t *) (ip))[1] & ((const uint32_t *)(mask))[1]; \
481  ((uint32_t *) (result))[2] =((const uint32_t *) (ip))[2] & ((const uint32_t *)(mask))[2]; \
482  ((uint32_t *) (result))[3] =((const uint32_t *) (ip))[3] & ((const uint32_t *)(mask))[3];
484  if (!IN6_IS_ADDR_UNSPECIFIED(&_mask.v6)) {
485  struct in6_addr a, b;
486  IN6_AND_MASK(&a, &_net, &_mask);
487  IN6_AND_MASK(&b, &_ip, &_mask);
488  return !memcmp(&a,&b, sizeof(struct in6_addr));
489  } else {
490  if (!IN6_IS_ADDR_UNSPECIFIED(&_net.v6)) {
491  return !memcmp(&_net,&_ip,sizeof(struct in6_addr));
492  }
493  else return SWITCH_TRUE;
494  }
495 }
496 
498 {
499  switch_network_node_t *node;
500  switch_bool_t ok = list->default_type;
501  uint32_t bits = 0;
502 
503  for (node = list->node_head; node; node = node->next) {
504  if (node->family == AF_INET) continue;
505 
506  if (node->bits >= bits && switch_testv6_subnet(ip, node->ip, node->mask)) {
507  if (node->ok) {
508  ok = SWITCH_TRUE;
509  } else {
510  ok = SWITCH_FALSE;
511  }
512 
513  bits = node->bits;
514 
515  if (token) {
516  *token = node->token;
517  }
518  }
519  }
520 
521  return ok;
522 }
523 
525 {
526  if(port == 0)
527  return SWITCH_TRUE;
528  if(node->port_range.port != 0 && node->port_range.port != port)
529  return SWITCH_FALSE;
530  if(node->port_range.ports[0] != 0) {
531  int i;
532  for(i=0; i < MAX_NETWORK_PORTS && node->port_range.ports[i] != 0; i++) {
533  if(port == node->port_range.ports[i])
534  return SWITCH_TRUE;
535  }
536  return SWITCH_FALSE;
537  }
538  if(node->port_range.min_port != 0 || node->port_range.max_port != 0) {
539  if(port >= node->port_range.min_port && port <= node->port_range.max_port)
540  return SWITCH_TRUE;
541  return SWITCH_FALSE;
542  }
543  return SWITCH_TRUE;
544 }
545 
547 {
548  switch_network_node_t *node;
549  switch_bool_t ok = list->default_type;
550  uint32_t bits = 0;
551 
552  for (node = list->node_head; node; node = node->next) {
553  if (node->family == AF_INET6) continue; /* want AF_INET */
554  if (node->bits >= bits && switch_test_subnet(ip, node->ip.v4, node->mask.v4) && is_port_in_node(port, node)) {
555  if (node->ok) {
556  ok = SWITCH_TRUE;
557  } else {
558  ok = SWITCH_FALSE;
559  }
560 
561  bits = node->bits;
562 
563  if (token) {
564  *token = node->token;
565  }
566  }
567  }
568 
569  return ok;
570 }
571 
573 {
574  return switch_network_list_validate_ip6_port_token(list, ip, 0, token);
575 }
576 
578 {
579  return switch_network_list_validate_ip_port_token(list, ip, 0, token);
580 }
581 
583 {
584  /* ipv4 mapped ipv6 address */
585 
586  if (strncasecmp(ip_str, "::ffff:", 7)) {
587  return NULL;
588  }
589 
590  return strdup(ip_str + 7);
591 }
592 
594 {
595  if (!port) {
596  return NULL;
597  }
598 
599  if (port->port != 0) {
600  return switch_mprintf("port: %i ", port->port);
601  }
602 
603  if (port->ports[0] != 0) {
604  int i, written = 0;
605  char buf[MAX_NETWORK_PORTS * 6];
606  for (i = 0; i < MAX_NETWORK_PORTS && port->ports[i] != 0; i++) {
607  written += snprintf(buf + written, sizeof(buf) - written, (i != 0 ? ", %u" : "%u"), port->ports[i]);
608  }
609  return switch_mprintf("ports: [%s] ", buf);
610  }
611 
612  if (port->min_port != 0 || port->max_port != 0) {
613  return switch_mprintf("port range: [%i-%i] ", port->min_port, port->max_port);
614  }
615 
616  return NULL;
617 }
618 
620  const char *token, switch_network_port_range_p port)
621 {
622  ip_t ip, mask;
623  uint32_t bits;
624  switch_network_node_t *node;
625  char *ipv4 = NULL;
626  char *ports = NULL;
627 
628  if ((ipv4 = switch_network_ipv4_mapped_ipv6_addr(cidr_str))) {
629  cidr_str = ipv4;
630  }
631 
633 
634  if (switch_parse_cidr(cidr_str, &ip, &mask, &bits)) {
635  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Adding %s %s(%s) [%s] to list %s\n",
636  cidr_str, ports ? ports : "", ok ? "allow" : "deny", switch_str_nil(token), list->name);
637  switch_safe_free(ipv4);
638  switch_safe_free(ports);
639  return SWITCH_STATUS_GENERR;
640  }
641 
642  node = switch_core_alloc(list->pool, sizeof(*node));
643 
644  node->ip = ip;
645  node->mask = mask;
646  node->ok = ok;
647  node->bits = bits;
648  node->str = switch_core_strdup(list->pool, cidr_str);
649  if(port) {
650  memcpy(&node->port_range, port, sizeof(switch_network_port_range_t));
651  }
652 
653 
654  if (strchr(cidr_str,':')) {
655  node->family = AF_INET6;
656  } else {
657  node->family = AF_INET;
658  }
659 
660  if (!zstr(token)) {
661  node->token = switch_core_strdup(list->pool, token);
662  }
663 
664  node->next = list->node_head;
665  list->node_head = node;
666 
667  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s %s(%s) [%s] to list %s\n",
668  cidr_str, ports ? ports : "", ok ? "allow" : "deny", switch_str_nil(token), list->name);
669 
670  switch_safe_free(ipv4);
671  switch_safe_free(ports);
672  return SWITCH_STATUS_SUCCESS;
673 }
674 
676 {
677  char *cidr_str_dup = NULL;
679 
680  if (strchr(cidr_str, ',')) {
681  char *argv[32] = { 0 };
682  int i, argc;
683  cidr_str_dup = strdup(cidr_str);
684 
685  switch_assert(cidr_str_dup);
686  if ((argc = switch_separate_string(cidr_str_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
687  for (i = 0; i < argc; i++) {
688  switch_status_t this_status;
689  if ((this_status = switch_network_list_perform_add_cidr_token(list, argv[i], ok, token, port)) != SWITCH_STATUS_SUCCESS) {
690  status = this_status;
691  }
692  }
693  }
694  } else {
695  status = switch_network_list_perform_add_cidr_token(list, cidr_str, ok, token, port);
696  }
697 
698  switch_safe_free(cidr_str_dup);
699  return status;
700 }
701 
703 {
704  return switch_network_list_add_cidr_port_token(list, cidr_str, ok, token, NULL);
705 }
706 
708 {
709  ip_t ip, mask;
710  switch_network_node_t *node;
711 
712  switch_inet_pton(AF_INET, host, &ip);
713  switch_inet_pton(AF_INET, mask_str, &mask);
714 
715  node = switch_core_alloc(list->pool, sizeof(*node));
716 
717  node->ip.v4 = ntohl(ip.v4);
718  node->mask.v4 = ntohl(mask.v4);
719  node->ok = ok;
720  if(port) {
721  memcpy(&node->port_range, port, sizeof(switch_network_port_range_t));
722  }
723 
724  /* http://graphics.stanford.edu/~seander/bithacks.html */
725  mask.v4 = mask.v4 - ((mask.v4 >> 1) & 0x55555555);
726  mask.v4 = (mask.v4 & 0x33333333) + ((mask.v4 >> 2) & 0x33333333);
727  node->bits = (((mask.v4 + (mask.v4 >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
728 
729  node->str = switch_core_sprintf(list->pool, "%s:%s", host, mask_str);
730 
731  node->next = list->node_head;
732  list->node_head = node;
733 
734  return SWITCH_STATUS_SUCCESS;
735 }
736 
738 {
739  return switch_network_list_add_host_port_mask(list, host, mask_str, ok, NULL);
740 }
741 
742 
743 SWITCH_DECLARE(int) switch_parse_cidr(const char *string, ip_t *ip, ip_t *mask, uint32_t *bitp)
744 {
745  char host[128];
746  char *bit_str;
747  int32_t bits;
748  const char *ipv6;
749  ip_t *maskv = mask;
750  ip_t *ipv = ip;
751 
752  switch_copy_string(host, string, sizeof(host) - 1);
753  bit_str = strchr(host, '/');
754 
755  if (!bit_str) {
756  return -1;
757  }
758 
759  *bit_str++ = '\0';
760  bits = atoi(bit_str);
761  ipv6 = strchr(string, ':');
762  if (ipv6) {
763  int32_t i, n;
764  uint32_t k;
765 
766  if (bits < 0 || bits > 128) {
767  return -2;
768  }
769 
770  bits = atoi(bit_str);
771  switch_inet_pton(AF_INET6, host, (unsigned char *)ip);
772 
773  for (n = bits, i = 0; i < 16; i++) {
774  k = (n > 8) ? 8 : n;
775  maskv->v6.s6_addr[i] = 0xFF & ~(0xFF >> k); /* k = 0 gives 0x00, k = 8 gives 0xFF */
776  n -= k;
777  }
778  } else {
779  if (bits < 0 || bits > 32) {
780  return -2;
781  }
782 
783  bits = atoi(bit_str);
784  switch_inet_pton(AF_INET, host, (unsigned char *)ip);
785  ipv->v4 = htonl(ipv->v4);
786 
787  maskv->v4 = 0xFFFFFFFF & ~(0xFFFFFFFF >> bits);
788  }
789 
790  *bitp = bits;
791 
792  return 0;
793 }
794 
795 
796 SWITCH_DECLARE(char *) switch_find_end_paren(const char *s, char open, char close)
797 {
798  const char *e = NULL;
799  int depth = 0;
800 
801  while (s && *s && *s == ' ') {
802  s++;
803  }
804 
805  if (s && *s == open) {
806  depth++;
807  for (e = s + 1; e && *e; e++) {
808  if (*e == open && open != close) {
809  depth++;
810  } else if (*e == close) {
811  depth--;
812  if (!depth) {
813  break;
814  }
815  }
816  }
817  }
818 
819  return (e && *e == close) ? (char *) e : NULL;
820 }
821 
823 {
824  char c, *p;
825  int cur;
826  switch_size_t total = 0;
827 
828  p = buf;
829  while (total + 2 < len && (cur = read(fd, &c, 1)) == 1) {
830  total += cur;
831  *p++ = c;
832  if (c == '\r' || c == '\n') {
833  break;
834  }
835  }
836 
837  *p++ = '\0';
838  assert(total < len);
839  return total;
840 }
841 
842 #define DLINE_BLOCK_SIZE 1024
843 #define DLINE_MAX_SIZE 1048576
845 {
846  char c, *p;
847  int cur;
848  switch_size_t total = 0;
849  char *data = *buf;
850  switch_size_t ilen = *len;
851 
852  if (!data) {
853  *len = ilen = DLINE_BLOCK_SIZE;
854  data = malloc(ilen);
855  memset(data, 0, ilen);
856  }
857 
858  p = data;
859  while ((cur = read(fd, &c, 1)) == 1) {
860 
861  if (total + 2 >= ilen) {
862  if (ilen + DLINE_BLOCK_SIZE > DLINE_MAX_SIZE) {
863  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Single line limit reached!\n");
864  break;
865  }
866 
867  ilen += DLINE_BLOCK_SIZE;
868  data = realloc(data, ilen);
869  switch_assert(data);
870  p = data + total;
871 
872  }
873 
874  total += cur;
875  *p++ = c;
876 
877  if (c == '\r' || c == '\n') {
878  break;
879  }
880  }
881 
882  *p++ = '\0';
883 
884  *len = ilen;
885  *buf = data;
886 
887  return total;
888 }
889 
890 
891 
893 {
894  char c, *p;
895  switch_size_t total = 0;
896  char *data = *buf;
897  switch_size_t ilen = *len;
898 
899  if (!data) {
900  *len = ilen = DLINE_BLOCK_SIZE;
901  data = malloc(ilen);
902  memset(data, 0, ilen);
903  }
904 
905  p = data;
906  //while ((c = fgetc(fd)) != EOF) {
907 
908  while (fread(&c, 1, 1, fd) == 1) {
909 
910  if (total + 2 >= ilen) {
911  if (ilen + DLINE_BLOCK_SIZE > DLINE_MAX_SIZE) {
912  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Single line limit reached!\n");
913  break;
914  }
915 
916  ilen += DLINE_BLOCK_SIZE;
917  data = realloc(data, ilen);
918  switch_assert(data);
919  p = data + total;
920 
921  }
922 
923  total++;
924  *p++ = c;
925 
926  if (c == '\r' || c == '\n') {
927  break;
928  }
929  }
930 
931  *p++ = '\0';
932 
933  *len = ilen;
934  *buf = data;
935 
936  return total;
937 }
938 
939 SWITCH_DECLARE(char *) switch_amp_encode(char *s, char *buf, switch_size_t len)
940 {
941  char *p, *q;
942  switch_size_t x = 0;
943  switch_assert(s);
944 
945  q = buf;
946 
947  for (p = s; x < len; p++) {
948  switch (*p) {
949 
950  case '"':
951  if (x + 6 > len - 1) {
952  goto end;
953  }
954  *q++ = '&';
955  *q++ = 'q';
956  *q++ = 'u';
957  *q++ = 'o';
958  *q++ = 't';
959  *q++ = ';';
960  x += 6;
961  break;
962  case '\'':
963  if (x + 6 > len - 1) {
964  goto end;
965  }
966  *q++ = '&';
967  *q++ = 'a';
968  *q++ = 'p';
969  *q++ = 'o';
970  *q++ = 's';
971  *q++ = ';';
972  x += 6;
973  break;
974  case '&':
975  if (x + 5 > len - 1) {
976  goto end;
977  }
978  *q++ = '&';
979  *q++ = 'a';
980  *q++ = 'm';
981  *q++ = 'p';
982  *q++ = ';';
983  x += 5;
984  break;
985  case '<':
986  if (x + 4 > len - 1) {
987  goto end;
988  }
989  *q++ = '&';
990  *q++ = 'l';
991  *q++ = 't';
992  *q++ = ';';
993  x += 4;
994  break;
995  case '>':
996  if (x + 4 > len - 1) {
997  goto end;
998  }
999  *q++ = '&';
1000  *q++ = 'g';
1001  *q++ = 't';
1002  *q++ = ';';
1003  x += 4;
1004  break;
1005  default:
1006  if (x + 1 > len - 1) {
1007  goto end;
1008  }
1009  *q++ = *p;
1010  x++;
1011  if (*p == '\0') {
1012  goto end;
1013  }
1014  break;
1015  }
1016  }
1017 
1018  end:
1019 
1020  return buf;
1021 }
1022 
1023 static const char switch_b64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1024 #define B64BUFFLEN 1024
1025 SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size_t ilen, unsigned char *out, switch_size_t olen)
1026 {
1027  int y = 0, bytes = 0;
1028  size_t x = 0;
1029  unsigned int b = 0, l = 0;
1030 
1031  for (x = 0; x < ilen; x++) {
1032  b = (b << 8) + in[x];
1033  l += 8;
1034 
1035  while (l >= 6) {
1036  out[bytes++] = switch_b64_table[(b >> (l -= 6)) % 64];
1037  if (bytes >= (int)olen - 1) {
1038  goto end;
1039  }
1040  if (++y != 72) {
1041  continue;
1042  }
1043  /* out[bytes++] = '\n'; */
1044  y = 0;
1045  }
1046  }
1047 
1048  if (l > 0) {
1049  out[bytes++] = switch_b64_table[((b % 16) << (6 - l)) % 64];
1050  }
1051  if (l != 0) {
1052  while (l < 6 && bytes < (int)olen - 1) {
1053  out[bytes++] = '=', l += 2;
1054  }
1055  }
1056 
1057  end:
1058 
1059  out[bytes] = '\0';
1060 
1061  return SWITCH_STATUS_SUCCESS;
1062 }
1063 
1065 {
1066 
1067  char l64[256];
1068  int b = 0, c, l = 0, i;
1069  const char *ip;
1070  char *op = out;
1071  size_t ol = 0;
1072 
1073  for (i = 0; i < 256; i++) {
1074  l64[i] = -1;
1075  }
1076 
1077  for (i = 0; i < 64; i++) {
1078  l64[(int) switch_b64_table[i]] = (char) i;
1079  }
1080 
1081  for (ip = in; ip && *ip; ip++) {
1082  c = l64[(int) *ip];
1083  if (c == -1) {
1084  continue;
1085  }
1086 
1087  b = (b << 6) + c;
1088  l += 6;
1089 
1090  while (l >= 8) {
1091  op[ol++] = (char) ((b >> (l -= 8)) % 256);
1092  if (ol >= olen - 1) {
1093  goto end;
1094  }
1095  }
1096  }
1097 
1098  end:
1099 
1100  op[ol+1] = '\0';
1101 
1102  return ol;
1103 }
1104 
1105 static int write_buf(int fd, const char *buf)
1106 {
1107 
1108  int len = (int) strlen(buf);
1109  if (fd && write(fd, buf, len) != len) {
1110  close(fd);
1111  return 0;
1112  }
1113 
1114  return 1;
1115 }
1116 
1118  const char *from,
1119  const char *headers,
1120  const char *body, const char *file, const char *convert_cmd, const char *convert_ext)
1121 {
1122  char *bound = "XXXX_boundary_XXXX";
1123  const char *mime_type = "audio/inline";
1124  char filename[80], buf[B64BUFFLEN];
1125  int fd = -1, ifd = -1;
1126  int x = 0, y = 0, bytes = 0, ilen = 0;
1127  unsigned int b = 0, l = 0;
1128  unsigned char in[B64BUFFLEN];
1129  unsigned char out[B64BUFFLEN + 512];
1130  char *dupfile = NULL, *ext = NULL;
1131  char *newfile = NULL;
1132  switch_bool_t rval = SWITCH_FALSE;
1133  const char *err = NULL;
1134 
1135  filename[0] = '\0';
1136 
1137  if (zstr(to)) {
1138  err = "No to address specified";
1139  goto end;
1140  }
1141 
1142  if (!zstr(file) && !zstr(convert_cmd) && !zstr(convert_ext)) {
1143  if (strrchr(file, '.')) {
1144  dupfile = strdup(file);
1145  if ((ext = strrchr(dupfile, '.'))) {
1146  *ext++ = '\0';
1147  newfile = switch_mprintf("%s.%s", dupfile, convert_ext);
1148  }
1149  }
1150 
1151  if (newfile) {
1152  char cmd[1024] = "";
1153  switch_snprintf(cmd, sizeof(cmd), "%s %s %s", convert_cmd, file, newfile);
1154  switch_system(cmd, SWITCH_TRUE);
1155  if (strcmp(file, newfile)) {
1156  file = newfile;
1157  } else {
1158  switch_safe_free(newfile);
1159  }
1160  }
1161 
1162  switch_safe_free(dupfile);
1163  }
1164 
1165  switch_snprintf(filename, 80, "%s%smail.%d%04x", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, (int)(switch_time_t) switch_epoch_time_now(NULL), rand() & 0xffff);
1166 
1167  if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644)) > -1) {
1168  if (file) {
1169  if ((ifd = open(file, O_RDONLY | O_BINARY)) < 0) {
1170  rval = SWITCH_FALSE;
1171  err = "Cannot open tmp file\n";
1172  goto end;
1173  }
1174  }
1175 
1176  if (!file && (!body || !switch_stristr("content-type", body))) {
1177  bound = NULL;
1178  }
1179 
1180  if (bound) {
1181  switch_snprintf(buf, B64BUFFLEN, "MIME-Version: 1.0\nContent-Type: multipart/mixed; boundary=\"%s\"\n", bound);
1182  if (!write_buf(fd, buf)) {
1183  rval = SWITCH_FALSE;
1184  err = "write error.";
1185  goto end;
1186  }
1187  }
1188 
1189  if (headers && !write_buf(fd, headers)) {
1190  rval = SWITCH_FALSE;
1191  err = "write error.";
1192  goto end;
1193  }
1194 
1195  if (!write_buf(fd, "\n\n")) {
1196  rval = SWITCH_FALSE;
1197  err = "write error.";
1198  goto end;
1199  }
1200 
1201  if (bound) {
1202  if (body && switch_stristr("content-type", body)) {
1203  switch_snprintf(buf, B64BUFFLEN, "--%s\n", bound);
1204  } else {
1205  switch_snprintf(buf, B64BUFFLEN, "--%s\nContent-Type: text/plain\n\n", bound);
1206  }
1207  if (!write_buf(fd, buf)) {
1208  rval = SWITCH_FALSE;
1209  err = "write error.";
1210  goto end;
1211  }
1212  }
1213 
1214  if (body) {
1215  if (!write_buf(fd, body)) {
1216  rval = SWITCH_FALSE;
1217  err = "write error.";
1218  goto end;
1219  }
1220  }
1221 
1222  if (file && bound) {
1223  const char *stipped_file = switch_cut_path(file);
1224  const char *new_type;
1225  char *ext;
1226 
1227  if ((ext = strrchr(stipped_file, '.'))) {
1228  ext++;
1229  if ((new_type = switch_core_mime_ext2type(ext))) {
1230  mime_type = new_type;
1231  }
1232  }
1233 
1235  "\n\n--%s\nContent-Type: %s; name=\"%s\"\n"
1236  "Content-ID: <ATTACHED@freeswitch.org>\n"
1237  "Content-Transfer-Encoding: base64\n"
1238  "Content-Description: Sound attachment.\n"
1239  "Content-Disposition: attachment; filename=\"%s\"\n\n", bound, mime_type, stipped_file, stipped_file);
1240  if (!write_buf(fd, buf)) {
1241  rval = SWITCH_FALSE;
1242  err = "write error.";
1243  goto end;
1244  }
1245 
1246  while ((ilen = read(ifd, in, B64BUFFLEN))) {
1247  for (x = 0; x < ilen; x++) {
1248  b = (b << 8) + in[x];
1249  l += 8;
1250  while (l >= 6) {
1251  out[bytes++] = switch_b64_table[(b >> (l -= 6)) % 64];
1252  if (++y != 72)
1253  continue;
1254  out[bytes++] = '\n';
1255  y = 0;
1256  }
1257  }
1258  if (write(fd, &out, bytes) != bytes) {
1259  rval = -1;
1260  break;
1261  } else {
1262  bytes = 0;
1263  }
1264 
1265  }
1266 
1267  if (l > 0) {
1268  out[bytes++] = switch_b64_table[((b % 16) << (6 - l)) % 64];
1269  }
1270  if (l != 0)
1271  while (l < 6) {
1272  out[bytes++] = '=', l += 2;
1273  }
1274  if (write(fd, &out, bytes) != bytes) {
1275  rval = -1;
1276  }
1277 
1278  }
1279 
1280  if (bound) {
1281  switch_snprintf(buf, B64BUFFLEN, "\n\n--%s--\n.\n", bound);
1282 
1283  if (!write_buf(fd, buf)) {
1284  rval = SWITCH_FALSE;
1285  err = "write error.";
1286  goto end;
1287  }
1288  }
1289  }
1290 
1291  if (fd > -1) {
1292  close(fd);
1293  fd = -1;
1294  }
1295 
1296  if (zstr(from)) {
1297  from = "freeswitch";
1298  }
1299 
1300  {
1301  char *to_arg = switch_util_quote_shell_arg(to);
1302  char *from_arg = switch_util_quote_shell_arg(from);
1303 #ifdef WIN32
1304  switch_snprintf(buf, B64BUFFLEN, "\"\"%s\" -f %s %s %s < \"%s\"\"", runtime.mailer_app, from_arg, runtime.mailer_app_args, to_arg, filename);
1305 #else
1306  switch_snprintf(buf, B64BUFFLEN, "/bin/cat %s | %s -f %s %s %s", filename, runtime.mailer_app, from_arg, runtime.mailer_app_args, to_arg);
1307 #endif
1308  switch_safe_free(to_arg); switch_safe_free(from_arg);
1309  }
1310  if (switch_system(buf, SWITCH_TRUE) < 0) {
1311  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to execute command: %s\n", buf);
1312  err = "execute error";
1313  rval = SWITCH_FALSE;
1314  }
1315 
1316  if (zstr(err)) {
1317  if (file) {
1318  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Emailed file [%s] to [%s]\n", filename, to);
1319  } else {
1320  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Emailed data to [%s]\n", to);
1321  }
1322 
1323  rval = SWITCH_TRUE;
1324  }
1325 
1326  end:
1327 
1328  if (fd > -1) {
1329  close(fd);
1330  }
1331 
1332  if (!zstr_buf(filename) && unlink(filename) != 0) {
1333  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to delete file [%s]\n", filename);
1334  }
1335 
1336  if (ifd > -1) {
1337  close(ifd);
1338  }
1339 
1340 
1341  if (newfile) {
1342  unlink(newfile);
1343  free(newfile);
1344  }
1345 
1346  if (rval != SWITCH_TRUE) {
1347  if (zstr(err)) err = "Unknown Error";
1348 
1349  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "EMAIL NOT SENT, error [%s]\n", err);
1350  }
1351 
1352  return rval;
1353 }
1354 
1356 {
1357  if (zstr(ip))
1358  return SWITCH_FALSE;
1359 
1360  return (strncmp(ip, "10.", 3) && /* 10.0.0.0 - 10.255.255.255 (10/8 prefix) */
1361  strncmp(ip, "192.168.", 8) && /* 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) */
1362  strncmp(ip, "127.", 4) && /* 127.0.0.0 - 127.255.255.255 (127/8 prefix) */
1363  strncmp(ip, "255.", 4) &&
1364  strncmp(ip, "0.", 2) &&
1365  strncmp(ip, "1.", 2) &&
1366  strncmp(ip, "2.", 2) &&
1367  strncmp(ip, "172.16.", 7) && /* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) */
1368  strncmp(ip, "172.17.", 7) &&
1369  strncmp(ip, "172.18.", 7) &&
1370  strncmp(ip, "172.19.", 7) &&
1371  strncmp(ip, "172.20.", 7) &&
1372  strncmp(ip, "172.21.", 7) &&
1373  strncmp(ip, "172.22.", 7) &&
1374  strncmp(ip, "172.23.", 7) &&
1375  strncmp(ip, "172.24.", 7) &&
1376  strncmp(ip, "172.25.", 7) &&
1377  strncmp(ip, "172.26.", 7) &&
1378  strncmp(ip, "172.27.", 7) &&
1379  strncmp(ip, "172.28.", 7) &&
1380  strncmp(ip, "172.29.", 7) &&
1381  strncmp(ip, "172.30.", 7) &&
1382  strncmp(ip, "172.31.", 7) &&
1383  strncmp(ip, "192.0.2.", 8) && /* 192.0.2.0 - 192.0.2.255 (192.0.2/24 prefix) */
1384  strncmp(ip, "169.254.", 8) /* 169.254.0.0 - 169.254.255.255 (169.254/16 prefix) */
1386 }
1387 
1388 SWITCH_DECLARE(switch_bool_t) switch_ast2regex(const char *pat, char *rbuf, size_t len)
1389 {
1390  const char *p = pat;
1391 
1392  if (!pat) {
1393  return SWITCH_FALSE;
1394  }
1395 
1396  memset(rbuf, 0, len);
1397 
1398  *(rbuf + strlen(rbuf)) = '^';
1399 
1400  while (p && *p) {
1401  if (*p == 'N') {
1402  strncat(rbuf, "[2-9]", len - strlen(rbuf));
1403  } else if (*p == 'X') {
1404  strncat(rbuf, "[0-9]", len - strlen(rbuf));
1405  } else if (*p == 'Z') {
1406  strncat(rbuf, "[1-9]", len - strlen(rbuf));
1407  } else if (*p == '.') {
1408  strncat(rbuf, ".*", len - strlen(rbuf));
1409  } else if (strlen(rbuf) < len - 1) {
1410  *(rbuf + strlen(rbuf)) = *p;
1411  }
1412  p++;
1413  }
1414  *(rbuf + strlen(rbuf)) = '$';
1415 
1416  return strcmp(pat, rbuf) ? SWITCH_TRUE : SWITCH_FALSE;
1417 }
1418 
1419 SWITCH_DECLARE(char *) switch_replace_char(char *str, char from, char to, switch_bool_t dup)
1420 {
1421  char *p;
1422 
1423  if (dup) {
1424  p = strdup(str);
1425  switch_assert(p);
1426  } else {
1427  p = str;
1428  }
1429 
1430  for (; p && *p; p++) {
1431  if (*p == from) {
1432  *p = to;
1433  }
1434  }
1435 
1436  return p;
1437 }
1438 
1440 {
1441  const char *sp = str;
1442  char *p, *s = NULL;
1443  size_t len;
1444 
1445  if (zstr(sp)) {
1447  }
1448 
1449  while ((*sp == 13 ) || (*sp == 10 ) || (*sp == 9 ) || (*sp == 32) || (*sp == 11) ) {
1450  sp++;
1451  }
1452 
1453  if (zstr(sp)) {
1455  }
1456 
1457  s = switch_core_strdup(pool, sp);
1458  switch_assert(s);
1459 
1460  if ((len = strlen(s)) > 0) {
1461  p = s + (len - 1);
1462 
1463  while ((p >= s) && ((*p == 13 ) || (*p == 10 ) || (*p == 9 ) || (*p == 32) || (*p == 11))) {
1464  *p-- = '\0';
1465  }
1466  }
1467 
1468  return s;
1469 }
1470 
1472 {
1473  const char *sp = str;
1474  char *p, *s = NULL;
1475  size_t len;
1476 
1477  if (zstr(sp)) {
1478  return strdup(SWITCH_BLANK_STRING);
1479  }
1480 
1481  while ((*sp == 13 ) || (*sp == 10 ) || (*sp == 9 ) || (*sp == 32) || (*sp == 11) ) {
1482  sp++;
1483  }
1484 
1485  if (zstr(sp)) {
1486  return strdup(SWITCH_BLANK_STRING);
1487  }
1488 
1489  s = strdup(sp);
1490  switch_assert(s);
1491 
1492  if ((len = strlen(s)) > 0) {
1493  p = s + (len - 1);
1494 
1495  while ((p >= s) && ((*p == 13 ) || (*p == 10 ) || (*p == 9 ) || (*p == 32) || (*p == 11))) {
1496  *p-- = '\0';
1497  }
1498  }
1499 
1500  return s;
1501 }
1502 
1504 {
1505  char *sp = str;
1506  char *p, *s = NULL;
1507  size_t len;
1508 
1509  if (zstr(sp)) {
1510  return dup ? strdup(SWITCH_BLANK_STRING) : sp;
1511  }
1512 
1513  while (*sp == ' ') {
1514  sp++;
1515  }
1516 
1517  if (dup) {
1518  s = strdup(sp);
1519  switch_assert(s);
1520  } else {
1521  s = sp;
1522  }
1523 
1524  if (zstr(s)) {
1525  return s;
1526  }
1527 
1528  if ((len = strlen(s)) > 0) {
1529  p = s + (len - 1);
1530 
1531  while (p && *p && (p >= s) && *p == ' ') {
1532  *p-- = '\0';
1533  }
1534  }
1535 
1536  return s;
1537 }
1538 
1539 SWITCH_DECLARE(char *) switch_strip_commas(char *in, char *out, switch_size_t len)
1540 {
1541  char *p = in, *q = out;
1542  char *ret = out;
1543  switch_size_t x = 0;
1544 
1545  for (; p && *p; p++) {
1546  if ((*p > 47 && *p < 58)) {
1547  *q++ = *p;
1548 
1549  if (++x > len) {
1550  ret = NULL;
1551  break;
1552  }
1553  } else if (*p != ',') {
1554  ret = NULL;
1555  break;
1556  }
1557  }
1558 
1559  return ret;
1560 }
1561 
1563 {
1564  char *p = in, *q = out;
1565  char *ret = out;
1566  switch_size_t x = 0;
1567  /* valid are 0 - 9, period (.), minus (-), and plus (+) - remove all others */
1568  for (; p && *p; p++) {
1569  if ((*p > 47 && *p < 58) || *p == '.' || *p == '-' || *p == '+') {
1570  *q++ = *p;
1571 
1572  if (++x > len) {
1573  ret = NULL;
1574  break;
1575  }
1576  }
1577  }
1578 
1579  return ret;
1580 }
1581 
1583 {
1584  char *e, *args;
1585  switch_size_t br;
1586 
1587  if ((args = strchr(str, '('))) {
1588  e = args - 1;
1589  *args++ = '\0';
1590  while (*e == ' ') {
1591  *e-- = '\0';
1592  }
1593  e = args;
1594  br = 1;
1595  while (e && *e) {
1596  if (*e == '(') {
1597  br++;
1598  } else if (br > 1 && *e == ')') {
1599  br--;
1600  } else if (br == 1 && *e == ')') {
1601  *e = '\0';
1602  break;
1603  }
1604  e++;
1605  }
1606  }
1607 
1608  return args;
1609 }
1610 
1611 SWITCH_DECLARE(switch_bool_t) switch_is_uint_in_range(const char *str, unsigned int from, unsigned int to)
1612 {
1613  unsigned int number;
1614  const char *original_str = str;
1615 
1616  if (str == NULL || *str == '\0' || from > to) {
1617  return SWITCH_FALSE;
1618  }
1619 
1620  for (; *str != '\0'; str++) {
1621  if (!isdigit(*str)) {
1622  return SWITCH_FALSE;
1623  }
1624  }
1625 
1626  number = atoi(original_str);
1627 
1628  if (number < from || number > to) {
1629  return SWITCH_FALSE;
1630  }
1631 
1632  return SWITCH_TRUE;
1633 }
1634 
1636 {
1637  const char *p;
1639 
1640  if (*str == '-' || *str == '+') {
1641  str++;
1642  }
1643 
1644  for (p = str; p && *p; p++) {
1645  if (!(*p == '.' || (*p > 47 && *p < 58))) {
1646  r = SWITCH_FALSE;
1647  break;
1648  }
1649  }
1650 
1651  return r;
1652 }
1653 
1655 {
1656  const char *p;
1658 
1659  if (*str == '-' || *str == '+') {
1660  str++;
1661  }
1662 
1663  for (p = str; p && *p; p++) {
1664  if ((*p == '.' || (*p > 47 && *p < 58))) {
1665  r = SWITCH_TRUE;
1666  break;
1667  }
1668  }
1669 
1670  return r;
1671 }
1672 
1673 SWITCH_DECLARE(const char *) switch_stristr(const char *instr, const char *str)
1674 {
1675 /*
1676 ** Rev History: 16/07/97 Greg Thayer Optimized
1677 ** 07/04/95 Bob Stout ANSI-fy
1678 ** 02/03/94 Fred Cole Original
1679 ** 09/01/03 Bob Stout Bug fix (lines 40-41) per Fred Bulback
1680 **
1681 ** Hereby donated to public domain.
1682 */
1683  const char *pptr, *sptr, *start;
1684 
1685  if (!str || !instr)
1686  return NULL;
1687 
1688  for (start = str; *start; start++) {
1689  /* find start of pattern in string */
1690  for (; ((*start) && (switch_toupper(*start) != switch_toupper(*instr))); start++);
1691 
1692  if (!*start)
1693  return NULL;
1694 
1695  pptr = instr;
1696  sptr = start;
1697 
1698  while (switch_toupper(*sptr) == switch_toupper(*pptr)) {
1699  sptr++;
1700  pptr++;
1701 
1702  /* if end of pattern then pattern was found */
1703  if (!*pptr)
1704  return (start);
1705 
1706  if (!*sptr)
1707  return NULL;
1708  }
1709  }
1710  return NULL;
1711 }
1712 
1713 #ifdef HAVE_GETIFADDRS
1714 #include <ifaddrs.h>
1715 static int get_netmask(struct sockaddr_in *me, int *mask)
1716 {
1717  struct ifaddrs *ifaddrs, *i = NULL;
1718 
1719  if (!me || getifaddrs(&ifaddrs) < 0) {
1720  return -1;
1721  }
1722 
1723  for (i = ifaddrs; i; i = i->ifa_next) {
1724  struct sockaddr_in *s = (struct sockaddr_in *) i->ifa_addr;
1725  struct sockaddr_in *m = (struct sockaddr_in *) i->ifa_netmask;
1726 
1727  if (s && m && s->sin_family == AF_INET && s->sin_addr.s_addr == me->sin_addr.s_addr) {
1728  *mask = m->sin_addr.s_addr;
1729  freeifaddrs(ifaddrs);
1730  return 0;
1731  }
1732  }
1733 
1734  freeifaddrs(ifaddrs);
1735 
1736  return -2;
1737 }
1738 #elif defined(__linux__)
1739 
1740 #include <sys/ioctl.h>
1741 #include <net/if.h>
1742 static int get_netmask(struct sockaddr_in *me, int *mask)
1743 {
1744 
1745  static struct ifreq ifreqs[20] = { {{{0}}} };
1746  struct ifconf ifconf;
1747  int nifaces, i;
1748  int sock;
1749  int r = -1;
1750 
1751  memset(&ifconf, 0, sizeof(ifconf));
1752  ifconf.ifc_buf = (char *) (ifreqs);
1753  ifconf.ifc_len = sizeof(ifreqs);
1754 
1755 
1756  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
1757  goto end;
1758  }
1759 
1760  if (ioctl(sock, SIOCGIFCONF, (char *) &ifconf) < 0) {
1761  goto end;
1762  }
1763 
1764  nifaces = ifconf.ifc_len / sizeof(struct ifreq);
1765 
1766  for (i = 0; i < nifaces; i++) {
1767  struct sockaddr_in *sin = NULL;
1768  struct in_addr ip;
1769 
1770  ioctl(sock, SIOCGIFADDR, &ifreqs[i]);
1771  sin = (struct sockaddr_in *) &ifreqs[i].ifr_addr;
1772  ip = sin->sin_addr;
1773 
1774  if (ip.s_addr == me->sin_addr.s_addr) {
1775  ioctl(sock, SIOCGIFNETMASK, &ifreqs[i]);
1776  sin = (struct sockaddr_in *) &ifreqs[i].ifr_addr;
1777  /* mask = sin->sin_addr; */
1778  *mask = sin->sin_addr.s_addr;
1779  r = 0;
1780  break;
1781  }
1782 
1783  }
1784 
1785  end:
1786 
1787  close(sock);
1788  return r;
1789 
1790 }
1791 
1792 #elif defined(WIN32)
1793 
1794 static int get_netmask(struct sockaddr_in *me, int *mask)
1795 {
1796  SOCKET sock = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
1797  INTERFACE_INFO interfaces[20];
1798  unsigned long bytes;
1799  int interface_count, x;
1800  int r = -1;
1801 
1802  *mask = 0;
1803 
1804  if (sock == SOCKET_ERROR) {
1805  return -1;
1806  }
1807 
1808  if (WSAIoctl(sock, SIO_GET_INTERFACE_LIST, 0, 0, &interfaces, sizeof(interfaces), &bytes, 0, 0) == SOCKET_ERROR) {
1809  r = -1;
1810  goto end;
1811  }
1812 
1813  interface_count = bytes / sizeof(INTERFACE_INFO);
1814 
1815  for (x = 0; x < interface_count; ++x) {
1816  struct sockaddr_in *addr = (struct sockaddr_in *) &(interfaces[x].iiAddress);
1817 
1818  if (addr->sin_addr.s_addr == me->sin_addr.s_addr) {
1819  struct sockaddr_in *netmask = (struct sockaddr_in *) &(interfaces[x].iiNetmask);
1820  *mask = netmask->sin_addr.s_addr;
1821  r = 0;
1822  break;
1823  }
1824  }
1825 
1826  end:
1827  closesocket(sock);
1828  return r;
1829 }
1830 
1831 #else
1832 
1833 static int get_netmask(struct sockaddr_in *me, int *mask)
1834 {
1835  return -1;
1836 }
1837 
1838 #endif
1839 
1840 
1842 {
1843 
1844  struct addrinfo *ai;
1845 
1846  if (getaddrinfo(host, 0, 0, &ai)) {
1847  return SWITCH_STATUS_FALSE;
1848  }
1849 
1850  get_addr(buf, buflen, ai->ai_addr, sizeof(struct sockaddr_storage));
1851 
1852  freeaddrinfo(ai);
1853 
1854  return SWITCH_STATUS_SUCCESS;
1855 }
1856 
1857 
1859 {
1861  char *base;
1862  char *force_local_ip_v4 = switch_core_get_variable_dup("force_local_ip_v4");
1863  char *force_local_ip_v6 = switch_core_get_variable_dup("force_local_ip_v6");
1864 
1865 #ifdef WIN32
1866  SOCKET tmp_socket;
1867  SOCKADDR_STORAGE l_address;
1868  int l_address_len;
1869  struct addrinfo *address_info;
1870 #else
1871 #ifdef __Darwin__
1872  int ilen;
1873 #else
1874  unsigned int ilen;
1875 #endif
1876  int tmp_socket = -1, on = 1;
1877  char abuf[25] = "";
1878 #endif
1879 
1880  switch (family) {
1881  case AF_INET:
1882  if (force_local_ip_v4) {
1883  switch_copy_string(buf, force_local_ip_v4, len);
1884  switch_safe_free(force_local_ip_v4);
1885  switch_safe_free(force_local_ip_v6);
1886  return SWITCH_STATUS_SUCCESS;
1887  }
1888  case AF_INET6:
1889  if (force_local_ip_v6) {
1890  switch_copy_string(buf, force_local_ip_v6, len);
1891  switch_safe_free(force_local_ip_v4);
1892  switch_safe_free(force_local_ip_v6);
1893  return SWITCH_STATUS_SUCCESS;
1894  }
1895  default:
1896  switch_safe_free(force_local_ip_v4);
1897  switch_safe_free(force_local_ip_v6);
1898  break;
1899  }
1900 
1901 
1902  if (len < 16) {
1903  return status;
1904  }
1905 
1906  switch (family) {
1907  case AF_INET:
1908  switch_copy_string(buf, "127.0.0.1", len);
1909  base = "82.45.148.209";
1910  break;
1911  case AF_INET6:
1912  switch_copy_string(buf, "::1", len);
1913  base = "2001:503:BA3E::2:30"; /* DNS Root server A */
1914  break;
1915  default:
1916  base = "127.0.0.1";
1917  break;
1918  }
1919 
1920 #ifdef WIN32
1921  tmp_socket = socket(family, SOCK_DGRAM, 0);
1922 
1923  getaddrinfo(base, NULL, NULL, &address_info);
1924 
1925  if (!address_info || WSAIoctl(tmp_socket,
1926  SIO_ROUTING_INTERFACE_QUERY,
1927  address_info->ai_addr, (DWORD) address_info->ai_addrlen, &l_address, sizeof(l_address), (LPDWORD) & l_address_len, NULL,
1928  NULL)) {
1929 
1930  closesocket(tmp_socket);
1931  if (address_info)
1932  freeaddrinfo(address_info);
1933  return status;
1934  }
1935 
1936 
1937  closesocket(tmp_socket);
1938  freeaddrinfo(address_info);
1939 
1940  if (!getnameinfo((const struct sockaddr *) &l_address, l_address_len, buf, len, NULL, 0, NI_NUMERICHOST)) {
1941  status = SWITCH_STATUS_SUCCESS;
1942  if (mask) {
1943  get_netmask((struct sockaddr_in *) &l_address, mask);
1944  }
1945  }
1946 #else
1947 
1948  switch (family) {
1949  case AF_INET:
1950  {
1951  struct sockaddr_in iface_out;
1952  struct sockaddr_in remote;
1953  memset(&remote, 0, sizeof(struct sockaddr_in));
1954 
1955  remote.sin_family = AF_INET;
1956  remote.sin_addr.s_addr = inet_addr(base);
1957  remote.sin_port = htons(4242);
1958 
1959  memset(&iface_out, 0, sizeof(iface_out));
1960  if ( (tmp_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ) {
1961  goto doh;
1962  }
1963 
1964  if (setsockopt(tmp_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1) {
1965  goto doh;
1966  }
1967 
1968  if (connect(tmp_socket, (struct sockaddr *) &remote, sizeof(struct sockaddr_in)) == -1) {
1969  goto doh;
1970  }
1971 
1972  ilen = sizeof(iface_out);
1973  if (getsockname(tmp_socket, (struct sockaddr *) &iface_out, &ilen) == -1) {
1974  goto doh;
1975  }
1976 
1977  if (iface_out.sin_addr.s_addr == 0) {
1978  goto doh;
1979  }
1980 
1981  switch_copy_string(buf, get_addr(abuf, sizeof(abuf), (struct sockaddr *) &iface_out, sizeof(struct sockaddr_storage)), len);
1982  if (mask) {
1983  get_netmask((struct sockaddr_in *) &iface_out, mask);
1984  }
1985 
1986  status = SWITCH_STATUS_SUCCESS;
1987  }
1988  break;
1989  case AF_INET6:
1990  {
1991  struct sockaddr_in6 iface_out;
1992  struct sockaddr_in6 remote;
1993  memset(&remote, 0, sizeof(struct sockaddr_in6));
1994 
1995  remote.sin6_family = AF_INET6;
1996  switch_inet_pton(AF_INET6, base, &remote.sin6_addr);
1997  remote.sin6_port = htons(4242);
1998 
1999  memset(&iface_out, 0, sizeof(iface_out));
2000  if ( (tmp_socket = socket(AF_INET6, SOCK_DGRAM, 0)) == -1 ) {
2001  goto doh;
2002  }
2003 
2004  if (connect(tmp_socket, (struct sockaddr *) &remote, sizeof(remote)) == -1) {
2005  goto doh;
2006  }
2007 
2008  ilen = sizeof(iface_out);
2009  if (getsockname(tmp_socket, (struct sockaddr *) &iface_out, &ilen) == -1) {
2010  goto doh;
2011  }
2012 
2013  inet_ntop(AF_INET6, (const void *) &iface_out.sin6_addr, buf, len - 1);
2014  status = SWITCH_STATUS_SUCCESS;
2015  }
2016  break;
2017  }
2018 
2019  doh:
2020  if (tmp_socket > 0) {
2021  close(tmp_socket);
2022  }
2023 #endif
2024 
2025  return status;
2026 }
2027 
2028 #ifdef HAVE_GETIFADDRS
2029 # include <ifaddrs.h>
2030 # include <net/if.h>
2031 #endif
2032 SWITCH_DECLARE(switch_status_t) switch_find_interface_ip(char *buf, int len, int *mask, const char *ifname, int family)
2033 {
2035 
2036 #ifdef HAVE_GETIFADDRS
2037 
2038  struct ifaddrs *addrs, *addr;
2039 
2040  getifaddrs(&addrs);
2041  for(addr = addrs; addr; addr = addr->ifa_next)
2042  {
2043  if (!(addr->ifa_flags & IFF_UP)) continue; // Address is not UP
2044  if (!addr->ifa_addr) continue; // No address set
2045  if (!addr->ifa_netmask) continue; // No netmask set
2046  if (family != AF_UNSPEC && addr->ifa_addr->sa_family != family) continue; // Not the address family we're looking for
2047  if (strcmp(addr->ifa_name, ifname)) continue; // Not the interface we're looking for
2048 
2049  switch(addr->ifa_addr->sa_family) {
2050  case AF_INET:
2051  inet_ntop(AF_INET, &( ((struct sockaddr_in*)(addr->ifa_addr))->sin_addr ), buf, len - 1);
2052  break;
2053  case AF_INET6:
2054  inet_ntop(AF_INET6, &( ((struct sockaddr_in6*)(addr->ifa_addr))->sin6_addr ), buf, len - 1);
2055  break;
2056  default:
2057  continue;
2058  }
2059 
2060  if (mask && addr->ifa_netmask->sa_family == AF_INET) {
2061  *mask = ((struct sockaddr_in*)(addr->ifa_addr))->sin_addr.s_addr;
2062  }
2063 
2064  status = SWITCH_STATUS_SUCCESS;
2065  break;
2066  }
2067  freeifaddrs(addrs);
2068 
2069 #elif defined(__linux__)
2070 
2071  // TODO Not implemented, contributions welcome.
2072 
2073 #elif defined(WIN32)
2074 
2075  // TODO Not implemented, contributions welcome.
2076 
2077 #endif
2078 
2079  return status;
2080 }
2081 
2082 
2084 {
2085  switch_time_exp_t tm = { 0 }, local_tm = { 0 };
2086  int proceed = 0, ovector[30], time_only = 0;
2087  switch_regex_t *re = NULL;
2088  char replace[1024] = "";
2089  switch_time_t ret = 0, local_time = 0;
2090  char *pattern = "^(\\d+)-(\\d+)-(\\d+)\\s*(\\d*):{0,1}(\\d*):{0,1}(\\d*)";
2091  char *pattern2 = "^(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})";
2092  char *pattern3 = "^(\\d*):{0,1}(\\d*):{0,1}(\\d*)$";
2093 
2095 
2096 
2097  if ((time_only = switch_regex_perform(in, pattern3, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
2098  tm.tm_hour = 0;
2099  tm.tm_min = 0;
2100  tm.tm_sec = 0;
2101  } else {
2102  tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = tm.tm_usec = 0;
2103 
2104  if (!(proceed = switch_regex_perform(in, pattern, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
2106  proceed = switch_regex_perform(in, pattern2, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
2107  }
2108  }
2109 
2110  if (proceed || time_only) {
2111 
2112  if (time_only > 1) {
2113  switch_regex_copy_substring(in, ovector, time_only, 1, replace, sizeof(replace));
2114  tm.tm_hour = atoi(replace);
2115  }
2116 
2117  if (time_only > 2) {
2118  switch_regex_copy_substring(in, ovector, time_only, 2, replace, sizeof(replace));
2119  tm.tm_min = atoi(replace);
2120  }
2121 
2122  if (time_only > 3) {
2123  switch_regex_copy_substring(in, ovector, time_only, 3, replace, sizeof(replace));
2124  tm.tm_sec = atoi(replace);
2125  }
2126 
2127  if (proceed > 1) {
2128  switch_regex_copy_substring(in, ovector, proceed, 1, replace, sizeof(replace));
2129  tm.tm_year = atoi(replace) - 1900;
2130  }
2131 
2132  if (proceed > 2) {
2133  switch_regex_copy_substring(in, ovector, proceed, 2, replace, sizeof(replace));
2134  tm.tm_mon = atoi(replace) - 1;
2135  }
2136 
2137  if (proceed > 3) {
2138  switch_regex_copy_substring(in, ovector, proceed, 3, replace, sizeof(replace));
2139  tm.tm_mday = atoi(replace);
2140  }
2141 
2142  if (proceed > 4) {
2143  switch_regex_copy_substring(in, ovector, proceed, 4, replace, sizeof(replace));
2144  tm.tm_hour = atoi(replace);
2145  }
2146 
2147  if (proceed > 5) {
2148  switch_regex_copy_substring(in, ovector, proceed, 5, replace, sizeof(replace));
2149  tm.tm_min = atoi(replace);
2150  }
2151 
2152  if (proceed > 6) {
2153  switch_regex_copy_substring(in, ovector, proceed, 6, replace, sizeof(replace));
2154  tm.tm_sec = atoi(replace);
2155  }
2156 
2158 
2159  switch_time_exp_get(&local_time, &tm);
2160  switch_time_exp_lt(&local_tm, local_time);
2161  tm.tm_isdst = local_tm.tm_isdst;
2162  tm.tm_gmtoff = local_tm.tm_gmtoff;
2163 
2164  switch_time_exp_gmt_get(&ret, &tm);
2165  return ret;
2166  }
2167 
2169 
2170  return ret;
2171 }
2172 
2174 {
2175  switch (priority) { /*lol */
2177  return "NORMAL";
2178  case SWITCH_PRIORITY_LOW:
2179  return "LOW";
2180  case SWITCH_PRIORITY_HIGH:
2181  return "HIGH";
2182  default:
2183  return "INVALID";
2184  }
2185 }
2186 
2187 static char RFC2833_CHARS[] = "0123456789*#ABCDF";
2188 
2189 #ifdef _MSC_VER
2190 /* Copyright (c) 1996 by Internet Software Consortium.
2191  *
2192  * Permission to use, copy, modify, and distribute this software for any
2193  * purpose with or without fee is hereby granted, provided that the above
2194  * copyright notice and this permission notice appear in all copies.
2195  *
2196  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
2197  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
2198  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
2199  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
2200  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
2201  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
2202  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2203  * SOFTWARE.
2204  */
2205 
2206 #include <ctype.h>
2207 #include <errno.h>
2208 #include <stdio.h>
2209 #include <string.h>
2210 #include <stdlib.h>
2211 
2212 #include <sys/types.h>
2213 
2214 /*
2215  * WARNING: Don't even consider trying to compile this on a system where
2216  * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
2217  */
2218 
2219 static const char *switch_inet_ntop4(const unsigned char *src, char *dst, size_t size);
2220 #if HAVE_SIN6
2221 static const char *switch_inet_ntop6(const unsigned char *src, char *dst, size_t size);
2222 #endif
2223 
2224 /* char *
2225  * inet_ntop(af, src, dst, size)
2226  * convert a network format address to presentation format.
2227  * return:
2228  * pointer to presentation format address (`dst'), or NULL (see errno).
2229  * author:
2230  * Paul Vixie, 1996.
2231  */
2232 SWITCH_DECLARE(const char *) switch_inet_ntop(int af, void const *src, char *dst, size_t size)
2233 {
2234 
2235  switch (af) {
2236  case AF_INET:
2237  return switch_inet_ntop4(src, dst, size);
2238 #if HAVE_SIN6
2239  case AF_INET6:
2240  return switch_inet_ntop6(src, dst, size);
2241 #endif
2242  default:
2243  return NULL;
2244  }
2245  /* NOTREACHED */
2246 }
2247 
2248 /* const char *
2249  * inet_ntop4(src, dst, size)
2250  * format an IPv4 address, more or less like inet_ntoa()
2251  * return:
2252  * `dst' (as a const)
2253  * notes:
2254  * (1) uses no statics
2255  * (2) takes a unsigned char* not an in_addr as input
2256  * author:
2257  * Paul Vixie, 1996.
2258  */
2259 static const char *switch_inet_ntop4(const unsigned char *src, char *dst, size_t size)
2260 {
2261  static const char fmt[] = "%u.%u.%u.%u";
2262  char tmp[sizeof "255.255.255.255"];
2263 
2264  if (switch_snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]) >= (int) size) {
2265  return NULL;
2266  }
2267 
2268  return strcpy(dst, tmp);
2269 }
2270 
2271 #if HAVE_SIN6 || defined(NTDDI_VERSION)
2272 /* const char *
2273  * inet_ntop6(src, dst, size)
2274  * convert IPv6 binary address into presentation (printable) format
2275  * author:
2276  * Paul Vixie, 1996.
2277  */
2278 static const char *switch_inet_ntop6(unsigned char const *src, char *dst, size_t size)
2279 {
2280  /*
2281  * Note that int32_t and int16_t need only be "at least" large enough
2282  * to contain a value of the specified size. On some systems, like
2283  * Crays, there is no such thing as an integer variable with 16 bits.
2284  * Keep this in mind if you think this function should have been coded
2285  * to use pointer overlays. All the world's not a VAX.
2286  */
2287  char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
2288  struct {
2289  int base, len;
2290  } best = {
2291  -1, 0}, cur = {
2292  -1, 0};
2293  unsigned int words[8];
2294  int i;
2295 
2296  /*
2297  * Preprocess:
2298  * Copy the input (bytewise) array into a wordwise array.
2299  * Find the longest run of 0x00's in src[] for :: shorthanding.
2300  */
2301  for (i = 0; i < 16; i += 2)
2302  words[i / 2] = (src[i] << 8) | (src[i + 1]);
2303  best.base = -1;
2304  cur.base = -1;
2305  for (i = 0; i < 8; i++) {
2306  if (words[i] == 0) {
2307  if (cur.base == -1)
2308  cur.base = i, cur.len = 1;
2309  else
2310  cur.len++;
2311  } else {
2312  if (cur.base != -1) {
2313  if (best.base == -1 || cur.len > best.len)
2314  best = cur;
2315  cur.base = -1;
2316  }
2317  }
2318  }
2319  if (cur.base != -1) {
2320  if (best.base == -1 || cur.len > best.len)
2321  best = cur;
2322  }
2323  if (best.base != -1 && best.len < 2)
2324  best.base = -1;
2325 
2326  /*
2327  * Format the result.
2328  */
2329  tp = tmp;
2330  for (i = 0; i < 8; i++) {
2331  /* Are we inside the best run of 0x00's? */
2332  if (best.base != -1 && i >= best.base && i < (best.base + best.len)) {
2333  if (i == best.base)
2334  *tp++ = ':';
2335  continue;
2336  }
2337  /* Are we following an initial run of 0x00s or any real hex? */
2338  if (i != 0)
2339  *tp++ = ':';
2340  /* Is this address an encapsulated IPv4? */
2341  if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
2342  if (!switch_inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
2343  return (NULL);
2344  tp += strlen(tp);
2345  break;
2346  }
2347  tp += sprintf(tp, "%x", words[i]);
2348  }
2349  /* Was it a trailing run of 0x00's? */
2350  if (best.base != -1 && (best.base + best.len) == 8)
2351  *tp++ = ':';
2352  *tp++ = '\0';
2353 
2354  /*
2355  * Check for overflow, copy, and we're done.
2356  */
2357  if ((size_t) (tp - tmp) >= size) {
2358  return NULL;
2359  }
2360 
2361  return strcpy(dst, tmp);
2362 }
2363 #endif
2364 
2365 #endif
2366 
2368 {
2369  struct sockaddr_in *s = (struct sockaddr_in *) &sa->sa;
2370 
2371  return ntohs((unsigned short) s->sin_addr.s_addr);
2372 }
2373 
2375 {
2376  struct sockaddr_in *s1;
2377  struct sockaddr_in *s2;
2378 
2379  struct sockaddr_in6 *s16;
2380  struct sockaddr_in6 *s26;
2381 
2382  struct sockaddr *ss1;
2383  struct sockaddr *ss2;
2384 
2385  if (!(sa1 && sa2))
2386  return 0;
2387 
2388  s1 = (struct sockaddr_in *) &sa1->sa;
2389  s2 = (struct sockaddr_in *) &sa2->sa;
2390 
2391  s16 = (struct sockaddr_in6 *) &sa1->sa;
2392  s26 = (struct sockaddr_in6 *) &sa2->sa;
2393 
2394  ss1 = (struct sockaddr *) &sa1->sa;
2395  ss2 = (struct sockaddr *) &sa2->sa;
2396 
2397  if (ss1->sa_family != ss2->sa_family)
2398  return 0;
2399 
2400  switch (ss1->sa_family) {
2401  case AF_INET:
2402  if (ip_only) {
2403  return (s1->sin_addr.s_addr == s2->sin_addr.s_addr);
2404  } else {
2405  return (s1->sin_addr.s_addr == s2->sin_addr.s_addr && s1->sin_port == s2->sin_port);
2406  }
2407  case AF_INET6:
2408  {
2409  int i;
2410 
2411  if (!ip_only) {
2412  if (s16->sin6_port != s26->sin6_port) return 0;
2413  }
2414 
2415  for (i = 0; i < 4; i++) {
2416  if (*((int32_t *) s16->sin6_addr.s6_addr + i) != *((int32_t *) s26->sin6_addr.s6_addr + i)) return 0;
2417  }
2418 
2419  return 1;
2420  }
2421  }
2422 
2423  return 0;
2424 }
2425 
2426 
2428 {
2429  struct sockaddr_in *s1;
2430  struct sockaddr_in *s2;
2431 
2432  struct sockaddr_in6 *s16;
2433  struct sockaddr_in6 *s26;
2434 
2435  struct sockaddr *ss1;
2436  //struct sockaddr *ss2;
2437 
2438  if (!(sa1 && sa2))
2439  return 0;
2440 
2441  s1 = (struct sockaddr_in *) &sa1->sa;
2442  s2 = (struct sockaddr_in *) &sa2->sa;
2443 
2444  s16 = (struct sockaddr_in6 *) &sa1->sa;
2445  s26 = (struct sockaddr_in6 *) &sa2->sa;
2446 
2447  ss1 = (struct sockaddr *) &sa1->sa;
2448  //ss2 = (struct sockaddr *) &sa2->sa;
2449 
2450  sa1->port = sa2->port;
2451  sa1->family = sa2->family;
2452 
2453  sa1->sa.sin.sin_family = sa2->family;
2454 
2455  switch (ss1->sa_family) {
2456  case AF_INET:
2457  s1->sin_addr.s_addr = s2->sin_addr.s_addr;
2458  s1->sin_port = s2->sin_port;
2459 
2460  return 1;
2461  case AF_INET6:
2462  {
2463  int i;
2464 
2465  s16->sin6_port = s26->sin6_port;
2466 
2467  for (i = 0; i < 4; i++) {
2468  *((int32_t *) s16->sin6_addr.s6_addr + i) = *((int32_t *) s26->sin6_addr.s6_addr + i);
2469  }
2470 
2471  return 1;
2472  }
2473  }
2474 
2475  return 0;
2476 }
2477 
2478 SWITCH_DECLARE(char *) get_addr6(char *buf, switch_size_t len, struct sockaddr_in6 *sa, socklen_t salen)
2479 {
2480  switch_assert(buf);
2481  *buf = '\0';
2482 
2483  if (sa) {
2484 #if defined(NTDDI_VERSION)
2485  switch_inet_ntop6((unsigned char*)&(sa->sin6_addr), buf, len);
2486 #else
2487  inet_ntop(AF_INET6, &(sa->sin6_addr), buf, len);
2488 #endif
2489  }
2490 
2491  return buf;
2492 }
2493 
2494 SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, struct sockaddr *sa, socklen_t salen)
2495 {
2496  switch_assert(buf);
2497  *buf = '\0';
2498 
2499  if (sa) {
2500  getnameinfo(sa, salen, buf, (socklen_t) len, NULL, 0, NI_NUMERICHOST);
2501  }
2502  return buf;
2503 }
2504 
2505 SWITCH_DECLARE(unsigned short) get_port(struct sockaddr *sa)
2506 {
2507  unsigned short port = 0;
2508  if (sa) {
2509  switch (sa->sa_family) {
2510  case AF_INET:
2511  port = ntohs(((struct sockaddr_in *) sa)->sin_port);
2512  break;
2513  case AF_INET6:
2514  port = ntohs(((struct sockaddr_in6 *) sa)->sin6_port);
2515  break;
2516  }
2517  }
2518  return port;
2519 }
2520 
2521 SWITCH_DECLARE(int) switch_build_uri(char *uri, switch_size_t size, const char *scheme, const char *user, const switch_sockaddr_t *sa, int flags)
2522 {
2523  char host[NI_MAXHOST], serv[NI_MAXSERV];
2524  struct sockaddr_in6 si6;
2525  const struct sockaddr *addr;
2526  const char *colon;
2527 
2528  if (flags & SWITCH_URI_NO_SCOPE && sa->family == AF_INET6) {
2529  memcpy(&si6, &sa->sa, sa->salen);
2530  si6.sin6_scope_id = 0;
2531 
2532  addr = (const struct sockaddr *) &si6;
2533  } else {
2534  addr = (const struct sockaddr *) (intptr_t) & sa->sa;
2535  }
2536 
2537  if (getnameinfo(addr, sa->salen, host, sizeof(host), serv, sizeof(serv),
2538  ((flags & SWITCH_URI_NUMERIC_HOST) ? NI_NUMERICHOST : 0) | ((flags & SWITCH_URI_NUMERIC_PORT) ? NI_NUMERICSERV : 0)) != 0) {
2539  return 0;
2540  }
2541 
2542  colon = strchr(host, ':');
2543 
2544  return switch_snprintf(uri, size, "%s:%s%s%s%s%s%s%s", scheme,
2545  user ? user : "", user ? "@" : "", colon ? "[" : "", host, colon ? "]" : "", serv[0] ? ":" : "", serv[0] ? serv : "");
2546 }
2547 
2549 {
2550  if (event > -1 && event < (int32_t) sizeof(RFC2833_CHARS)) {
2551  return RFC2833_CHARS[event];
2552  }
2553  return '\0';
2554 }
2555 
2557 {
2558  char *c;
2559  unsigned char counter = 0;
2560 
2561  key = (char) switch_toupper(key);
2562  for (c = RFC2833_CHARS; *c; c++) {
2563  if (*c == key) {
2564  return counter;
2565  }
2566  counter++;
2567  }
2568  return '\0';
2569 }
2570 
2571 SWITCH_DECLARE(char *) switch_escape_char(switch_memory_pool_t *pool, char *in, const char *delim, char esc)
2572 {
2573  char *data;
2574  const char *p, *d;
2575  int count = 1, i = 0;
2576 
2577  p = in;
2578  while (*p) {
2579  d = delim;
2580  while (*d) {
2581  if (*p == *d) {
2582  count++;
2583  }
2584  d++;
2585  }
2586  p++;
2587  }
2588 
2589  if (count == 1) {
2590  return in;
2591  }
2592 
2593  data = switch_core_alloc(pool, strlen(in) + count);
2594 
2595  p = in;
2596  while (*p) {
2597  d = delim;
2598  while (*d) {
2599  if (*p == *d) {
2600  data[i++] = esc;
2601  }
2602  d++;
2603  }
2604  data[i++] = *p;
2605  p++;
2606  }
2607  return data;
2608 }
2609 
2610 /* Helper function used when separating strings to unescape a character. The
2611  supported characters are:
2612 
2613  \n linefeed
2614  \r carriage return
2615  \t tab
2616  \s space
2617 
2618  Any other character is returned as it was received. */
2619 static char unescape_char(char escaped)
2620 {
2621  char unescaped;
2622 
2623  switch (escaped) {
2624  case 'n':
2625  unescaped = '\n';
2626  break;
2627  case 'r':
2628  unescaped = '\r';
2629  break;
2630  case 't':
2631  unescaped = '\t';
2632  break;
2633  case 's':
2634  unescaped = ' ';
2635  break;
2636  default:
2637  unescaped = escaped;
2638  }
2639  return unescaped;
2640 }
2641 
2642 SWITCH_DECLARE(char *) switch_escape_string(const char *in, char *out, switch_size_t outlen)
2643 {
2644  const char *p;
2645  char *o = out;
2646 
2647  for (p = in; *p; p++) {
2648  switch (*p) {
2649  case '\n':
2650  *o++ = '\\';
2651  *o++ = 'n';
2652  break;
2653  case '\r':
2654  *o++ = '\\';
2655  *o++ = 'r';
2656  break;
2657  case '\t':
2658  *o++ = '\\';
2659  *o++ = 't';
2660  break;
2661  case ' ':
2662  *o++ = '\\';
2663  *o++ = 's';
2664  break;
2665  case '$':
2666  *o++ = '\\';
2667  *o++ = '$';
2668  break;
2669  default:
2670  *o++ = *p;
2671  break;
2672  }
2673  }
2674 
2675  *o++ = '\0';
2676 
2677  return out;
2678 }
2679 
2681 {
2682  size_t len = strlen(in) * 2 + 1;
2683  char *buf = switch_core_alloc(pool, len);
2684  return switch_escape_string(in, buf, len);
2685 }
2686 
2687 /* Helper function used when separating strings to remove quotes, leading /
2688  trailing spaces, and to convert escaped characters. */
2689 static char *cleanup_separated_string(char *str, char delim)
2690 {
2691  char *ptr;
2692  char *dest;
2693  char *start;
2694  char *end = NULL;
2695  int inside_quotes = 0;
2696 
2697  /* Skip initial whitespace */
2698  for (ptr = str; *ptr == ' '; ++ptr) {
2699  }
2700 
2701  for (start = dest = ptr; *ptr; ++ptr) {
2702  char e;
2703  int esc = 0;
2704 
2705  if (*ptr == ESCAPE_META) {
2706  e = *(ptr + 1);
2707  if (e == '\'' || e == '"' || (delim && e == delim) || e == ESCAPE_META || (e = unescape_char(*(ptr + 1))) != *(ptr + 1)) {
2708  ++ptr;
2709  *dest++ = e;
2710  end = dest;
2711  esc++;
2712  }
2713  }
2714  if (!esc) {
2715  if (*ptr == '\'' && (inside_quotes || strchr(ptr+1, '\''))) {
2716  if ((inside_quotes = (1 - inside_quotes))) {
2717  end = dest;
2718  }
2719  } else {
2720  *dest++ = *ptr;
2721  if (*ptr != ' ' || inside_quotes) {
2722  end = dest;
2723  }
2724  }
2725  }
2726  }
2727  if (end) {
2728  *end = '\0';
2729  }
2730 
2731  return start;
2732 }
2733 
2734 SWITCH_DECLARE(unsigned int) switch_separate_string_string(char *buf, char *delim, char **array, unsigned int arraylen)
2735 {
2736  unsigned int count = 0;
2737  char *d;
2738  size_t dlen = strlen(delim);
2739 
2740  array[count++] = buf;
2741 
2742  while (count < arraylen && array[count - 1]) {
2743  if ((d = strstr(array[count - 1], delim))) {
2744  *d = '\0';
2745  d += dlen;
2746  array[count++] = d;
2747  } else
2748  break;
2749  }
2750 
2751  return count;
2752 }
2753 
2754 /* Separate a string using a delimiter that is not a space */
2755 static unsigned int separate_string_char_delim(char *buf, char delim, char **array, unsigned int arraylen)
2756 {
2757  enum tokenizer_state {
2758  START,
2759  FIND_DELIM
2760  } state = START;
2761 
2762  unsigned int count = 0;
2763  char *ptr = buf;
2764  int inside_quotes = 0;
2765  unsigned int i;
2766 
2767  while (*ptr && count < arraylen) {
2768  switch (state) {
2769  case START:
2770  array[count++] = ptr;
2771  state = FIND_DELIM;
2772  break;
2773 
2774  case FIND_DELIM:
2775  /* escaped characters are copied verbatim to the destination string */
2776  if (*ptr == ESCAPE_META) {
2777  ++ptr;
2778  } else if (*ptr == '\'' && (inside_quotes || strchr(ptr+1, '\''))) {
2779  inside_quotes = (1 - inside_quotes);
2780  } else if (*ptr == delim && !inside_quotes) {
2781  *ptr = '\0';
2782  state = START;
2783  }
2784  ++ptr;
2785  break;
2786  }
2787  }
2788  /* strip quotes, escaped chars and leading / trailing spaces */
2789 
2790  for (i = 0; i < count; ++i) {
2791  array[i] = cleanup_separated_string(array[i], delim);
2792  }
2793 
2794  return count;
2795 }
2796 
2797 /* Separate a string using a delimiter that is a space */
2798 static unsigned int separate_string_blank_delim(char *buf, char **array, unsigned int arraylen)
2799 {
2800  enum tokenizer_state {
2801  START,
2802  SKIP_INITIAL_SPACE,
2803  FIND_DELIM,
2804  SKIP_ENDING_SPACE
2805  } state = START;
2806 
2807  unsigned int count = 0;
2808  char *ptr = buf;
2809  int inside_quotes = 0;
2810  unsigned int i;
2811 
2812  while (*ptr && count < arraylen) {
2813  switch (state) {
2814  case START:
2815  array[count++] = ptr;
2816  state = SKIP_INITIAL_SPACE;
2817  break;
2818 
2819  case SKIP_INITIAL_SPACE:
2820  if (*ptr == ' ') {
2821  ++ptr;
2822  } else {
2823  state = FIND_DELIM;
2824  }
2825  break;
2826 
2827  case FIND_DELIM:
2828  if (*ptr == ESCAPE_META) {
2829  ++ptr;
2830  } else if (*ptr == '\'') {
2831  inside_quotes = (1 - inside_quotes);
2832  } else if (*ptr == ' ' && !inside_quotes) {
2833  *ptr = '\0';
2834  state = SKIP_ENDING_SPACE;
2835  }
2836  ++ptr;
2837  break;
2838 
2839  case SKIP_ENDING_SPACE:
2840  if (*ptr == ' ') {
2841  ++ptr;
2842  } else {
2843  state = START;
2844  }
2845  break;
2846  }
2847  }
2848  /* strip quotes, escaped chars and leading / trailing spaces */
2849 
2850  for (i = 0; i < count; ++i) {
2851  array[i] = cleanup_separated_string(array[i], 0);
2852  }
2853 
2854  return count;
2855 }
2856 
2857 SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, unsigned int arraylen)
2858 {
2859  if (!buf || !array || !arraylen) {
2860  return 0;
2861  }
2862 
2863 
2864  if (*buf == '^' && *(buf+1) == '^') {
2865  char *p = buf + 2;
2866 
2867  if (*p && *(p+1)) {
2868  buf = p;
2869  delim = *buf++;
2870  }
2871  }
2872 
2873 
2874  memset(array, 0, arraylen * sizeof(*array));
2875 
2876  return (delim == ' ' ? separate_string_blank_delim(buf, array, arraylen) : separate_string_char_delim(buf, delim, array, arraylen));
2877 }
2878 
2879 /* Separate a string using a delimiter that is not a space */
2880 static unsigned int separate_string_char_delim_cheap(const char *buf, char delim, const char **array, unsigned int larray[], unsigned int arraylen)
2881 {
2882  enum tokenizer_state {
2883  START,
2884  FIND_DELIM
2885  } state = START, dstate = START;
2886 
2887  unsigned int count = 0;
2888  const char *ptr = buf;
2889 
2890  while (*ptr && count < arraylen) {
2891  switch (state) {
2892  case START:
2893  array[count] = ptr;
2894  state = FIND_DELIM;
2895  dstate = START;
2896  count++;
2897  ptr++;
2898  break;
2899 
2900  case FIND_DELIM:
2901  if (*ptr == delim) {
2902  larray[count - 1] = (unsigned int)(ptr - array[count - 1]);
2903  dstate = state;
2904  state = START;
2905  }
2906  ++ptr;
2907  break;
2908  }
2909  }
2910 
2911  if (dstate == START) larray[count - 1] = strlen(array[count - 1]);
2912 
2913  /* strip quotes, escaped chars and leading / trailing spaces */
2914 
2915  // for (i = 0; i < count; ++i) {
2916  // array[i] = cleanup_separated_string(array[i], delim);
2917  // }
2918 
2919  return count;
2920 }
2921 
2922 /* Separate a string using a delimiter that is a space */
2923 static unsigned int separate_string_blank_delim_cheap(const char *buf, const char **array, unsigned int larray[], unsigned int arraylen)
2924 {
2925  enum tokenizer_state {
2926  START,
2927  SKIP_INITIAL_SPACE,
2928  FIND_DELIM,
2929  SKIP_ENDING_SPACE
2930  } state = START, dstate = START;
2931 
2932  unsigned int count = 0;
2933  const char *ptr = buf;
2934 
2935  while (*ptr && count < arraylen) {
2936  switch (state) {
2937  case START:
2938  array[count++] = ptr;
2939  dstate = START;
2940  state = SKIP_INITIAL_SPACE;
2941  break;
2942 
2943  case SKIP_INITIAL_SPACE:
2944  if (*ptr == ' ') {
2945  ++ptr;
2946  } else {
2947  state = FIND_DELIM;
2948  }
2949  break;
2950 
2951  case FIND_DELIM:
2952  if (*ptr == ' ') {
2953  larray[count - 1] = (unsigned int)(ptr - array[count - 1]);
2954  dstate = state;
2955  state = SKIP_ENDING_SPACE;
2956  }
2957  ++ptr;
2958  break;
2959 
2960  case SKIP_ENDING_SPACE:
2961  if (*ptr == ' ') {
2962  ++ptr;
2963  } else {
2964  dstate = state;
2965  state = START;
2966  }
2967  break;
2968  }
2969  }
2970  if (dstate == START) larray[count - 1] = strlen(array[count - 1]);
2971 
2972  /* strip quotes, escaped chars and leading / trailing spaces */
2973 
2974  // for (i = 0; i < count; ++i) {
2975  // array[i] = cleanup_separated_string(array[i], 0);
2976  // }
2977 
2978  return count;
2979 }
2980 
2981 
2982 SWITCH_DECLARE(unsigned int) switch_separate_string_cheap(const char *buf, char delim, const char **array, unsigned int larray[], unsigned int arraylen)
2983 {
2984  if (!buf || !array || !arraylen) {
2985  return 0;
2986  }
2987 
2988 
2989  if (*buf == '^' && *(buf+1) == '^') {
2990  const char *p = buf + 2;
2991 
2992  if (*p && *(p+1)) {
2993  buf = p;
2994  delim = *buf++;
2995  }
2996  }
2997 
2998 
2999  memset(array, 0, arraylen * sizeof(*array));
3000 
3001  return (delim == ' ' ? separate_string_blank_delim_cheap(buf, array, larray, arraylen) : separate_string_char_delim_cheap(buf, delim, array, larray, arraylen));
3002 }
3003 
3004 
3005 SWITCH_DECLARE(const char *) switch_cut_path(const char *in)
3006 {
3007  const char *p, *ret = in;
3008  const char delims[] = "/\\";
3009  const char *i;
3010 
3011  if (in) {
3012  for (i = delims; *i; i++) {
3013  p = in;
3014  while ((p = strchr(p, *i)) != 0) {
3015  ret = ++p;
3016  }
3017  }
3018  return ret;
3019  } else {
3020  return NULL;
3021  }
3022 }
3023 
3024 SWITCH_DECLARE(switch_status_t) switch_string_match(const char *string, size_t string_len, const char *search, size_t search_len)
3025 {
3026  size_t i;
3027 
3028  for (i = 0; (i < search_len) && (i < string_len); i++) {
3029  if (string[i] != search[i]) {
3030  return SWITCH_STATUS_FALSE;
3031  }
3032  }
3033 
3034  if (i == search_len) {
3035  return SWITCH_STATUS_SUCCESS;
3036  }
3037 
3038  return SWITCH_STATUS_FALSE;
3039 }
3040 
3041 SWITCH_DECLARE(char *) switch_string_replace(const char *string, const char *search, const char *replace)
3042 {
3043  size_t string_len = strlen(string);
3044  size_t search_len = strlen(search);
3045  size_t replace_len = strlen(replace);
3046  size_t i, n;
3047  size_t dest_len = 0;
3048  char *dest, *tmp;
3049 
3050  dest = (char *) malloc(sizeof(char));
3051  switch_assert(dest);
3052 
3053  for (i = 0; i < string_len; i++) {
3054  if (switch_string_match(string + i, string_len - i, search, search_len) == SWITCH_STATUS_SUCCESS) {
3055  for (n = 0; n < replace_len; n++) {
3056  dest[dest_len] = replace[n];
3057  dest_len++;
3058  tmp = (char *) realloc(dest, sizeof(char) * (dest_len + 1));
3059  switch_assert(tmp);
3060  dest = tmp;
3061  }
3062  i += search_len - 1;
3063  } else {
3064  dest[dest_len] = string[i];
3065  dest_len++;
3066  tmp = (char *) realloc(dest, sizeof(char) * (dest_len + 1));
3067  switch_assert(tmp);
3068  dest = tmp;
3069  }
3070  }
3071 
3072  dest[dest_len] = 0;
3073  return dest;
3074 }
3075 
3076 SWITCH_DECLARE(char *) switch_util_quote_shell_arg(const char *string)
3077 {
3078  return switch_util_quote_shell_arg_pool(string, NULL);
3079 }
3080 
3082 {
3083  size_t string_len = strlen(string);
3084  size_t i;
3085  size_t n = 0;
3086  size_t dest_len = 0;
3087  char *dest;
3088 
3089  /* first pass through, figure out how large to make the allocation */
3090  dest_len = strlen(string) + 1; /* string + null */
3091  dest_len += 1; /* opening quote */
3092  for (i = 0; i < string_len; i++) {
3093  switch (string[i]) {
3094 #ifndef WIN32
3095  case '\'':
3096  /* We replace ' by sq backslace sq sq, so need 3 additional bytes */
3097  dest_len += 3;
3098  break;
3099 #endif
3100  }
3101  }
3102  dest_len += 1; /* closing quote */
3103 
3104  /* if we're given a pool, allocate from it, otherwise use malloc */
3105  if (pool) {
3106  dest = switch_core_alloc(pool, sizeof(char) * dest_len);
3107  } else {
3108  dest = (char *) malloc(sizeof(char) * dest_len);
3109  }
3110  switch_assert(dest);
3111 
3112 #ifdef WIN32
3113  dest[n++] = '"';
3114 #else
3115  dest[n++] = '\'';
3116 #endif
3117 
3118  for (i = 0; i < string_len; i++) {
3119  switch (string[i]) {
3120 #ifdef WIN32
3121  case '"':
3122  case '%':
3123  dest[n++] = ' ';
3124  break;
3125 #else
3126  case '\'':
3127  /* We replace ' by sq backslash sq sq */
3128  dest[n++] = '\'';
3129  dest[n++] = '\\';
3130  dest[n++] = '\'';
3131  dest[n++] = '\'';
3132  break;
3133 #endif
3134  default:
3135  dest[n++] = string[i];
3136  }
3137  }
3138 
3139 #ifdef WIN32
3140  dest[n++] = '"';
3141 #else
3142  dest[n++] = '\'';
3143 #endif
3144  dest[n++] = 0;
3145  switch_assert(n == dest_len);
3146  return dest;
3147 }
3148 
3149 
3150 
3151 #ifdef HAVE_POLL
3152 #include <poll.h>
3153 SWITCH_DECLARE(int) switch_wait_sock(switch_os_socket_t sock, uint32_t ms, switch_poll_t flags)
3154 {
3155  struct pollfd pfds[2] = { { 0 } };
3156  int s = 0, r = 0;
3157 
3158  if (sock == SWITCH_SOCK_INVALID) {
3159  return SWITCH_SOCK_INVALID;
3160  }
3161 
3162  pfds[0].fd = sock;
3163 
3164 
3165  if ((flags & SWITCH_POLL_READ)) {
3166  pfds[0].events |= POLLIN;
3167  }
3168 
3169  if ((flags & SWITCH_POLL_WRITE)) {
3170  pfds[0].events |= POLLOUT;
3171  }
3172 
3173  if ((flags & SWITCH_POLL_ERROR)) {
3174  pfds[0].events |= POLLERR;
3175  }
3176 
3177  if ((flags & SWITCH_POLL_HUP)) {
3178  pfds[0].events |= POLLHUP;
3179  }
3180 
3181  if ((flags & SWITCH_POLL_RDNORM)) {
3182  pfds[0].events |= POLLRDNORM;
3183  }
3184 
3185  if ((flags & SWITCH_POLL_RDBAND)) {
3186  pfds[0].events |= POLLRDBAND;
3187  }
3188 
3189  if ((flags & SWITCH_POLL_PRI)) {
3190  pfds[0].events |= POLLPRI;
3191  }
3192 
3193  s = poll(pfds, 1, ms);
3194 
3195  if (s < 0) {
3197  s = 0;
3198  }
3199  }
3200 
3201  if (s < 0) {
3202  r = s;
3203  } else if (s > 0) {
3204  if ((pfds[0].revents & POLLIN)) {
3205  r |= SWITCH_POLL_READ;
3206  }
3207  if ((pfds[0].revents & POLLOUT)) {
3208  r |= SWITCH_POLL_WRITE;
3209  }
3210  if ((pfds[0].revents & POLLERR)) {
3211  r |= SWITCH_POLL_ERROR;
3212  }
3213  if ((pfds[0].revents & POLLHUP)) {
3214  r |= SWITCH_POLL_HUP;
3215  }
3216  if ((pfds[0].revents & POLLRDNORM)) {
3217  r |= SWITCH_POLL_RDNORM;
3218  }
3219  if ((pfds[0].revents & POLLRDBAND)) {
3220  r |= SWITCH_POLL_RDBAND;
3221  }
3222  if ((pfds[0].revents & POLLPRI)) {
3223  r |= SWITCH_POLL_PRI;
3224  }
3225  if ((pfds[0].revents & POLLNVAL)) {
3226  r |= SWITCH_POLL_INVALID;
3227  }
3228  }
3229 
3230  return r;
3231 
3232 }
3233 
3234 SWITCH_DECLARE(int) switch_wait_socklist(switch_waitlist_t *waitlist, uint32_t len, uint32_t ms)
3235 {
3236  struct pollfd *pfds;
3237  int s = 0, r = 0, i;
3238 
3239  pfds = calloc(len, sizeof(struct pollfd));
3240  switch_assert(pfds);
3241 
3242  for (i = 0; i < len; i++) {
3243  if (waitlist[i].sock == SWITCH_SOCK_INVALID) {
3244  break;
3245  }
3246 
3247  pfds[i].fd = waitlist[i].sock;
3248 
3249  if ((waitlist[i].events & SWITCH_POLL_READ)) {
3250  pfds[i].events |= POLLIN;
3251  }
3252 
3253  if ((waitlist[i].events & SWITCH_POLL_WRITE)) {
3254  pfds[i].events |= POLLOUT;
3255  }
3256 
3257  if ((waitlist[i].events & SWITCH_POLL_ERROR)) {
3258  pfds[i].events |= POLLERR;
3259  }
3260 
3261  if ((waitlist[i].events & SWITCH_POLL_HUP)) {
3262  pfds[i].events |= POLLHUP;
3263  }
3264 
3265  if ((waitlist[i].events & SWITCH_POLL_RDNORM)) {
3266  pfds[i].events |= POLLRDNORM;
3267  }
3268 
3269  if ((waitlist[i].events & SWITCH_POLL_RDBAND)) {
3270  pfds[i].events |= POLLRDBAND;
3271  }
3272 
3273  if ((waitlist[i].events & SWITCH_POLL_PRI)) {
3274  pfds[i].events |= POLLPRI;
3275  }
3276  }
3277 
3278  s = poll(pfds, len, ms);
3279 
3280  if (s < 0) {
3282  s = 0;
3283  }
3284  }
3285 
3286  if (s < 0) {
3287  r = s;
3288  } else if (s > 0) {
3289  for (i = 0; i < len; i++) {
3290  if ((pfds[i].revents & POLLIN)) {
3291  r |= SWITCH_POLL_READ;
3292  waitlist[i].revents |= SWITCH_POLL_READ;
3293  }
3294  if ((pfds[i].revents & POLLOUT)) {
3295  r |= SWITCH_POLL_WRITE;
3296  waitlist[i].revents |= SWITCH_POLL_WRITE;
3297  }
3298  if ((pfds[i].revents & POLLERR)) {
3299  r |= SWITCH_POLL_ERROR;
3300  waitlist[i].revents |= SWITCH_POLL_ERROR;
3301  }
3302  if ((pfds[i].revents & POLLHUP)) {
3303  r |= SWITCH_POLL_HUP;
3304  waitlist[i].revents |= SWITCH_POLL_HUP;
3305  }
3306  if ((pfds[i].revents & POLLRDNORM)) {
3307  r |= SWITCH_POLL_RDNORM;
3308  waitlist[i].revents |= SWITCH_POLL_RDNORM;
3309  }
3310  if ((pfds[i].revents & POLLRDBAND)) {
3311  r |= SWITCH_POLL_RDBAND;
3312  waitlist[i].revents |= SWITCH_POLL_RDBAND;
3313  }
3314  if ((pfds[i].revents & POLLPRI)) {
3315  r |= SWITCH_POLL_PRI;
3316  waitlist[i].revents |= SWITCH_POLL_PRI;
3317  }
3318  if ((pfds[i].revents & POLLNVAL)) {
3319  r |= SWITCH_POLL_INVALID;
3320  waitlist[i].revents |= SWITCH_POLL_INVALID;
3321  }
3322  }
3323  }
3324 
3325  free(pfds);
3326 
3327  return r;
3328 
3329 }
3330 
3331 #else
3332 /* use select instead of poll */
3334 {
3335  int s = 0, r = 0;
3336  fd_set *rfds;
3337  fd_set *wfds;
3338  fd_set *efds;
3339  struct timeval tv;
3340 
3341  if (sock == SWITCH_SOCK_INVALID) {
3342  return SWITCH_SOCK_INVALID;
3343  }
3344 
3345  rfds = malloc(sizeof(fd_set));
3346  wfds = malloc(sizeof(fd_set));
3347  efds = malloc(sizeof(fd_set));
3348 
3349  FD_ZERO(rfds);
3350  FD_ZERO(wfds);
3351  FD_ZERO(efds);
3352 
3353 #ifndef WIN32
3354  /* Wouldn't you rather know?? */
3355  assert(sock <= FD_SETSIZE);
3356 #endif
3357 
3358  if ((flags & SWITCH_POLL_READ)) {
3359 
3360 #ifdef WIN32
3361 #pragma warning( push )
3362 #pragma warning( disable : 4127 )
3363  FD_SET(sock, rfds);
3364 #pragma warning( pop )
3365 #else
3366  FD_SET(sock, rfds);
3367 #endif
3368  }
3369 
3370  if ((flags & SWITCH_POLL_WRITE)) {
3371 
3372 #ifdef WIN32
3373 #pragma warning( push )
3374 #pragma warning( disable : 4127 )
3375  FD_SET(sock, wfds);
3376 #pragma warning( pop )
3377 #else
3378  FD_SET(sock, wfds);
3379 #endif
3380  }
3381 
3382  if ((flags & SWITCH_POLL_ERROR)) {
3383 
3384 #ifdef WIN32
3385 #pragma warning( push )
3386 #pragma warning( disable : 4127 )
3387  FD_SET(sock, efds);
3388 #pragma warning( pop )
3389 #else
3390  FD_SET(sock, efds);
3391 #endif
3392  }
3393 
3394  tv.tv_sec = ms / 1000;
3395  tv.tv_usec = (ms % 1000) * 1000;
3396 
3397  s = select(sock + 1, (flags & SWITCH_POLL_READ) ? rfds : NULL, (flags & SWITCH_POLL_WRITE) ? wfds : NULL, (flags & SWITCH_POLL_ERROR) ? efds : NULL, &tv);
3398 
3399  if (s < 0) {
3401  s = 0;
3402  }
3403  }
3404 
3405  if (s < 0) {
3406  r = s;
3407  } else if (s > 0) {
3408  if ((flags & SWITCH_POLL_READ) && FD_ISSET(sock, rfds)) {
3409  r |= SWITCH_POLL_READ;
3410  }
3411 
3412  if ((flags & SWITCH_POLL_WRITE) && FD_ISSET(sock, wfds)) {
3413  r |= SWITCH_POLL_WRITE;
3414  }
3415 
3416  if ((flags & SWITCH_POLL_ERROR) && FD_ISSET(sock, efds)) {
3417  r |= SWITCH_POLL_ERROR;
3418  }
3419  }
3420 
3421  free(rfds);
3422  free(wfds);
3423  free(efds);
3424 
3425  return r;
3426 
3427 }
3428 
3429 SWITCH_DECLARE(int) switch_wait_socklist(switch_waitlist_t *waitlist, uint32_t len, uint32_t ms)
3430 {
3431  int s = 0, r = 0;
3432  fd_set *rfds;
3433  fd_set *wfds;
3434  fd_set *efds;
3435  struct timeval tv;
3436  unsigned int i;
3437  switch_os_socket_t max_fd = 0;
3438  int flags = 0;
3439 
3440  rfds = malloc(sizeof(fd_set));
3441  wfds = malloc(sizeof(fd_set));
3442  efds = malloc(sizeof(fd_set));
3443 
3444  FD_ZERO(rfds);
3445  FD_ZERO(wfds);
3446  FD_ZERO(efds);
3447 
3448  for (i = 0; i < len; i++) {
3449  if (waitlist[i].sock == SWITCH_SOCK_INVALID) {
3450  break;
3451  }
3452 
3453  if (waitlist[i].sock > max_fd) {
3454  max_fd = waitlist[i].sock;
3455  }
3456 
3457 #ifndef WIN32
3458  /* Wouldn't you rather know?? */
3459  assert(waitlist[i].sock <= FD_SETSIZE);
3460 #endif
3461  flags |= waitlist[i].events;
3462 
3463  if ((waitlist[i].events & SWITCH_POLL_READ)) {
3464 
3465 #ifdef WIN32
3466 #pragma warning( push )
3467 #pragma warning( disable : 4127 )
3468  FD_SET(waitlist[i].sock, rfds);
3469 #pragma warning( pop )
3470 #else
3471  FD_SET(waitlist[i].sock, rfds);
3472 #endif
3473  }
3474 
3475  if ((waitlist[i].events & SWITCH_POLL_WRITE)) {
3476 
3477 #ifdef WIN32
3478 #pragma warning( push )
3479 #pragma warning( disable : 4127 )
3480  FD_SET(waitlist[i].sock, wfds);
3481 #pragma warning( pop )
3482 #else
3483  FD_SET(waitlist[i].sock, wfds);
3484 #endif
3485  }
3486 
3487  if ((waitlist[i].events & SWITCH_POLL_ERROR)) {
3488 
3489 #ifdef WIN32
3490 #pragma warning( push )
3491 #pragma warning( disable : 4127 )
3492  FD_SET(waitlist[i].sock, efds);
3493 #pragma warning( pop )
3494 #else
3495  FD_SET(waitlist[i].sock, efds);
3496 #endif
3497  }
3498  }
3499 
3500  tv.tv_sec = ms / 1000;
3501  tv.tv_usec = (ms % 1000) * 1000;
3502 
3503  s = select(max_fd + 1, (flags & SWITCH_POLL_READ) ? rfds : NULL, (flags & SWITCH_POLL_WRITE) ? wfds : NULL, (flags & SWITCH_POLL_ERROR) ? efds : NULL, &tv);
3504 
3505  if (s < 0) {
3507  s = 0;
3508  }
3509  }
3510 
3511  if (s < 0) {
3512  r = s;
3513  } else if (s > 0) {
3514  for (i = 0; i < len; i++) {
3515  if ((waitlist[i].events & SWITCH_POLL_READ) && FD_ISSET(waitlist[i].sock, rfds)) {
3516  r |= SWITCH_POLL_READ;
3517  waitlist[i].revents |= SWITCH_POLL_READ;
3518  }
3519 
3520  if ((waitlist[i].events & SWITCH_POLL_WRITE) && FD_ISSET(waitlist[i].sock, wfds)) {
3521  r |= SWITCH_POLL_WRITE;
3522  waitlist[i].revents |= SWITCH_POLL_WRITE;
3523  }
3524 
3525  if ((waitlist[i].events & SWITCH_POLL_ERROR) && FD_ISSET(waitlist[i].sock, efds)) {
3526  r |= SWITCH_POLL_ERROR;
3527  waitlist[i].revents |= SWITCH_POLL_ERROR;
3528  }
3529  }
3530  }
3531 
3532  free(rfds);
3533  free(wfds);
3534  free(efds);
3535 
3536  return r;
3537 
3538 }
3539 #endif
3540 
3542 {
3543  int nsds = 0;
3544 
3545  switch_poll(poll, 1, &nsds, ms);
3546 
3547  return nsds;
3548 }
3549 
3551 {
3553 }
3554 
3556 {
3557  return switch_core_url_encode_opt(switch_core_session_get_pool(session), url, double_encode);
3558 }
3559 
3561 {
3562  return switch_core_url_encode_opt(pool, url, SWITCH_FALSE);
3563 }
3564 
3566 {
3567  const char hex[] = "0123456789ABCDEF";
3568  switch_size_t len = 0;
3569  switch_size_t slen = 0;
3570  const char *p, *e;
3571 
3572  if (!url) return NULL;
3573  if (!pool) return NULL;
3574 
3575  e = end_of_p(url);
3576 
3577  for (p = url; *p; p++) {
3578  int ok = 0;
3579 
3580  len++;
3581  slen++;
3582 
3583  if (!double_encode && *p == '%' && e-p > 1) {
3584  if (strchr(hex, *(p+1)) && strchr(hex, *(p+2))) {
3585  ok = 1;
3586  }
3587  }
3588 
3589  if (!ok && (*p < ' ' || *p > '~' || strchr(SWITCH_URL_UNSAFE, *p))) {
3590  len += 2;
3591  }
3592  }
3593 
3594  slen++;
3595  len++; /* NULL Terminatior */
3596 
3597  if (slen == len) {
3598  return switch_core_strdup(pool, url);
3599  } else {
3600  return switch_url_encode_opt(url, switch_core_alloc(pool, sizeof(char) * len), len, double_encode);
3601  }
3602 }
3603 
3604 SWITCH_DECLARE(char *) switch_url_encode_opt(const char *url, char *buf, size_t len, switch_bool_t double_encode)
3605 {
3606  const char *p, *e = end_of_p(url);
3607  size_t x = 0;
3608  const char hex[] = "0123456789ABCDEF";
3609 
3610  if (!buf) {
3611  return 0;
3612  }
3613 
3614  if (!url) {
3615  return 0;
3616  }
3617 
3618  len--;
3619 
3620  for (p = url; *p; p++) {
3621  int ok = 0;
3622 
3623  if (x >= len) {
3624  break;
3625  }
3626 
3627  if (!double_encode && *p == '%' && e-p > 1) {
3628  if (strchr(hex, *(p+1)) && strchr(hex, *(p+2))) {
3629  ok = 1;
3630  }
3631  }
3632 
3633  if (!ok && (*p < ' ' || *p > '~' || strchr(SWITCH_URL_UNSAFE, *p))) {
3634  if ((x + 3) > len) {
3635  break;
3636  }
3637  buf[x++] = '%';
3638  buf[x++] = hex[(*p >> 4) & 0x0f];
3639  buf[x++] = hex[*p & 0x0f];
3640  } else {
3641  buf[x++] = *p;
3642  }
3643  }
3644  buf[x] = '\0';
3645 
3646  return buf;
3647 }
3648 
3649 SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len)
3650 {
3651  return switch_url_encode_opt(url, buf, len, SWITCH_FALSE);
3652 }
3653 
3655 {
3656  char *o;
3657  unsigned int tmp;
3658 
3659  if (zstr(s) || !strchr(s, '%')) {
3660  return s;
3661  }
3662 
3663  for (o = s; *s; s++, o++) {
3664  if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) {
3665  *o = (char) tmp;
3666  s += 2;
3667  } else {
3668  *o = *s;
3669  }
3670  }
3671  *o = '\0';
3672  return s;
3673 }
3674 
3675 SWITCH_DECLARE(void) switch_split_time(const char *exp, int *hour, int *min, int *sec)
3676 {
3677  char *dup = strdup(exp);
3678  char *shour = NULL;
3679  char *smin = NULL;
3680  char *ssec = NULL;
3681 
3682  switch_assert(dup);
3683 
3684  shour = dup;
3685  if ((smin=strchr(dup, ':'))) {
3686  *smin++ = '\0';
3687  if ((ssec=strchr(smin, ':'))) {
3688  *ssec++ = '\0';
3689  } else {
3690  ssec = "00";
3691  }
3692  if (hour) {
3693  *hour = atol(shour);
3694  }
3695  if (min) {
3696  *min = atol(smin);
3697  }
3698  if (sec) {
3699  *sec = atol(ssec);
3700  }
3701 
3702  }
3703  switch_safe_free(dup);
3704  return;
3705 
3706 }
3707 
3708 SWITCH_DECLARE(void) switch_split_date(const char *exp, int *year, int *month, int *day)
3709 {
3710  char *dup = strdup(exp);
3711  char *syear = NULL;
3712  char *smonth = NULL;
3713  char *sday = NULL;
3714 
3715  switch_assert(dup);
3716 
3717  syear = dup;
3718  if ((smonth=strchr(dup, '-'))) {
3719  *smonth++ = '\0';
3720  if ((sday=strchr(smonth, '-'))) {
3721  *sday++ = '\0';
3722  if (year) {
3723  *year = atol(syear);
3724  }
3725  if (month) {
3726  *month = atol(smonth);
3727  }
3728  if (day) {
3729  *day = atol(sday);
3730  }
3731  }
3732  }
3733  switch_safe_free(dup);
3734  return;
3735 
3736 }
3737 
3738 /* Ex exp value "2009-10-10 14:33:22~2009-11-10 17:32:31" */
3740 {
3741  char *dup = strdup(exp);
3742  char *sStart;
3743  char *sEnd;
3744  char *cur;
3745  char *p;
3746  switch_time_t tsStart = 0;
3747  switch_time_t tsEnd = 0;
3748  int ret = 0;
3749 
3750  switch_assert(dup);
3751 
3752  cur = dup;
3753  if ((p = strchr(cur, ','))) {
3754  *p++ = '\0';
3755  }
3756 
3757  while (cur) {
3758  sStart = cur;
3759  if ((sEnd = strchr(cur, '~'))) {
3760  *sEnd++ = '\0';
3761 
3762  tsStart = switch_str_time(sStart);
3763  tsEnd = switch_str_time(sEnd);
3764 
3765 
3766  if (tsStart == 0 || tsEnd == 0) {
3767  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse error for date time range (%s~%s)\n", sStart, sEnd);
3768  break;
3769  }
3770 
3771  if (tsStart <= *ts && tsEnd > *ts) {
3772  ret = 1;
3773  break;
3774  }
3775  }
3776 
3777  if ((cur = p)) {
3778  if ((p = strchr(p, ','))) {
3779  *p++ = '\0';
3780  }
3781  }
3782  }
3783 
3784  switch_safe_free(dup);
3785  return ret;
3786 }
3787 
3788 
3789 /* Written by Marc Espie, public domain */
3790 #define SWITCH_CTYPE_NUM_CHARS 256
3791 
3793  EOF,
3794  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3795  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
3796  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
3797  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
3798  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
3799  0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
3800  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
3801  0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
3802  0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
3803  0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
3804  0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
3805  0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
3806  0x60, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
3807  'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
3808  'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
3809  'X', 'Y', 'Z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
3810  0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
3811  0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
3812  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
3813  0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
3814  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
3815  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
3816  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
3817  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
3818  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
3819  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
3820  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
3821  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
3822  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
3823  0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
3824  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
3825  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
3826 };
3827 
3829 
3831 {
3832  if ((unsigned int) c > 255)
3833  return (c);
3834  if (c < -1)
3835  return EOF;
3836  return ((_switch_toupper_tab_ + 1)[c]);
3837 }
3838 
3840  EOF,
3841  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3842  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
3843  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
3844  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
3845  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
3846  0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
3847  0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
3848  0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
3849  0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
3850  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
3851  'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
3852  'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
3853  0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
3854  0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
3855  0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
3856  0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
3857  0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
3858  0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
3859  0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
3860  0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
3861  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
3862  0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
3863  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
3864  0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
3865  0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
3866  0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
3867  0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
3868  0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
3869  0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
3870  0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
3871  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
3872  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
3873 };
3874 
3876 
3878 {
3879  if ((unsigned int) c > 255)
3880  return (c);
3881  if (c < -1)
3882  return EOF;
3883  return ((_switch_tolower_tab_ + 1)[c]);
3884 }
3885 
3886 /*
3887  * Copyright (c) 1989 The Regents of the University of California.
3888  * All rights reserved.
3889  * (c) UNIX System Laboratories, Inc.
3890  * All or some portions of this file are derived from material licensed
3891  * to the University of California by American Telephone and Telegraph
3892  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
3893  * the permission of UNIX System Laboratories, Inc.
3894  *
3895  * Redistribution and use in source and binary forms, with or without
3896  * modification, are permitted provided that the following conditions
3897  * are met:
3898  * 1. Redistributions of source code must retain the above copyright
3899  * notice, this list of conditions and the following disclaimer.
3900  * 2. Redistributions in binary form must reproduce the above copyright
3901  * notice, this list of conditions and the following disclaimer in the
3902  * documentation and/or other materials provided with the distribution.
3903  * 3. Neither the name of the University nor the names of its contributors
3904  * may be used to endorse or promote products derived from this software
3905  * without specific prior written permission.
3906  *
3907  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
3908  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3909  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3910  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3911  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3912  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3913  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3914  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3915  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3916  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3917  * SUCH DAMAGE.
3918  */
3919 
3920 #undef _U
3921 #undef _L
3922 #undef _N
3923 #undef _S
3924 #undef _P
3925 #undef _C
3926 #undef _X
3927 #undef _B
3928 
3929 #define _U 0x01
3930 #define _L 0x02
3931 #define _N 0x04
3932 #define _S 0x08
3933 #define _P 0x10
3934 #define _C 0x20
3935 #define _X 0x40
3936 #define _B 0x80
3937 
3939  0,
3940  _C, _C, _C, _C, _C, _C, _C, _C,
3941  _C, _C | _S, _C | _S, _C | _S, _C | _S, _C | _S, _C, _C,
3942  _C, _C, _C, _C, _C, _C, _C, _C,
3943  _C, _C, _C, _C, _C, _C, _C, _C,
3944  _S | _B, _P, _P, _P, _P, _P, _P, _P,
3945  _P, _P, _P, _P, _P, _P, _P, _P,
3946  _N, _N, _N, _N, _N, _N, _N, _N,
3947  _N, _N, _P, _P, _P, _P, _P, _P,
3948  _P, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U,
3949  _U, _U, _U, _U, _U, _U, _U, _U,
3950  _U, _U, _U, _U, _U, _U, _U, _U,
3951  _U, _U, _U, _P, _P, _P, _P, _P,
3952  _P, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L,
3953  _L, _L, _L, _L, _L, _L, _L, _L,
3954  _L, _L, _L, _L, _L, _L, _L, _L,
3955 /* determine printability based on the IS0 8859 8-bit standard */
3956  _L, _L, _L, _P, _P, _P, _P, _C,
3957 
3958  _C, _C, _C, _C, _C, _C, _C, _C, /* 80 */
3959  _C, _C, _C, _C, _C, _C, _C, _C, /* 88 */
3960  _C, _C, _C, _C, _C, _C, _C, _C, /* 90 */
3961  _C, _C, _C, _C, _C, _C, _C, _C, /* 98 */
3962  _P, _P, _P, _P, _P, _P, _P, _P, /* A0 */
3963  _P, _P, _P, _P, _P, _P, _P, _P, /* A8 */
3964  _P, _P, _P, _P, _P, _P, _P, _P, /* B0 */
3965  _P, _P, _P, _P, _P, _P, _P, _P, /* B8 */
3966  _P, _P, _P, _P, _P, _P, _P, _P, /* C0 */
3967  _P, _P, _P, _P, _P, _P, _P, _P, /* C8 */
3968  _P, _P, _P, _P, _P, _P, _P, _P, /* D0 */
3969  _P, _P, _P, _P, _P, _P, _P, _P, /* D8 */
3970  _P, _P, _P, _P, _P, _P, _P, _P, /* E0 */
3971  _P, _P, _P, _P, _P, _P, _P, _P, /* E8 */
3972  _P, _P, _P, _P, _P, _P, _P, _P, /* F0 */
3973  _P, _P, _P, _P, _P, _P, _P, _P /* F8 */
3974 };
3975 
3977 
3979 {
3980  return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_U | _L | _N)));
3981 }
3982 
3984 {
3985  return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_U | _L)));
3986 }
3987 
3989 {
3990  return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _C));
3991 }
3992 
3994 {
3995  return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _N));
3996 }
3997 
3999 {
4000  return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_P | _U | _L | _N)));
4001 }
4002 
4004 {
4005  return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _L));
4006 }
4007 
4009 {
4010  return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_P | _U | _L | _N | _B)));
4011 }
4012 
4014 {
4015  return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _P));
4016 }
4017 
4019 {
4020  return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _S));
4021 }
4022 
4024 {
4025  return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & _U));
4026 }
4027 
4029 {
4030  return (c < 0 ? 0 : c > 255 ? 0 : ((_switch_ctype_ + 1)[(unsigned char) c] & (_N | _X)));
4031 }
4032 static const char *DOW[] = {
4033  "sun",
4034  "mon",
4035  "tue",
4036  "wed",
4037  "thu",
4038  "fri",
4039  "sat"
4040 };
4041 
4042 SWITCH_DECLARE(const char *) switch_dow_int2str(int val) {
4043  if (val >= switch_arraylen(DOW)) {
4044  val = val % switch_arraylen(DOW);
4045  }
4046  return DOW[val];
4047 }
4048 
4049 SWITCH_DECLARE(int) switch_dow_str2int(const char *exp) {
4050  int ret = -1;
4051  int x;
4052 
4053  for (x = 0; x < switch_arraylen(DOW); x++) {
4054  if (!strncasecmp(DOW[x], exp, 3)) {
4055  ret = x + 1;
4056  break;
4057  }
4058  }
4059  return ret;
4060 }
4061 
4062 typedef enum {
4063  DOW_ERR = -2,
4064  DOW_EOF = -1,
4065  DOW_SUN = 1,
4072  DOW_HYPHEN = '-',
4073  DOW_COMA = ','
4074 } dow_t;
4075 
4076 static inline dow_t _dow_read_token(const char **s)
4077 {
4078  int i;
4079 
4080  if (**s == '-') {
4081  (*s)++;
4082  return DOW_HYPHEN;
4083  } else if (**s == ',') {
4084  (*s)++;
4085  return DOW_COMA;
4086  } else if (**s >= '1' && **s <= '7') {
4087  dow_t r = **s - '0';
4088  (*s)++;
4089  return r;
4090  } else if ((i = switch_dow_str2int(*s)) && i != -1) {
4091  (*s) += 3;
4092  return i;
4093  } else if (!**s) {
4094  return DOW_EOF;
4095  } else {
4096  return DOW_ERR;
4097  }
4098 }
4099 
4100 SWITCH_DECLARE(switch_bool_t) switch_dow_cmp(const char *exp, int val)
4101 {
4102  dow_t cur, prev = DOW_EOF, range_start = DOW_EOF;
4103  const char *p = exp;
4104 
4105  while ((cur = _dow_read_token(&p)) != DOW_EOF) {
4106  if (cur == DOW_COMA) {
4107  /* Reset state */
4108  cur = DOW_EOF;
4109  } else if (cur == DOW_HYPHEN) {
4110  /* Save the previous token and move to the next one */
4111  range_start = prev;
4112  } else if (cur == DOW_ERR) {
4113  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse error for [%s] at position %ld (%.6s)\n", exp, (long) (p - exp), p);
4114  break;
4115  } else {
4116  /* Valid day found */
4117  if (range_start != DOW_EOF) { /* Evaluating a range */
4118  if (range_start <= cur ? (val >= range_start && val <= cur) : (val >= range_start || val <= cur)) {
4119  return SWITCH_TRUE;
4120  }
4121  range_start = DOW_EOF;
4122  } else if (val == cur) {
4123  return SWITCH_TRUE;
4124  }
4125  }
4126 
4127  prev = cur;
4128  }
4129 
4130  return SWITCH_FALSE;
4131 }
4132 
4133 SWITCH_DECLARE(int) switch_number_cmp(const char *exp, int val)
4134 {
4135  // Expression exp must be a comma separated list of numbers or ranges.
4136  // To match numbers not in range 9-17, enter the reversed range 18-8.
4137  for (;; ++exp) {
4138  int a = strtol(exp, (char **)&exp, 10);
4139  if (*exp != '-') {
4140  if (a == val)
4141  return 1;
4142  } else {
4143  int b = strtol(++exp, (char **)&exp, 10);
4144  if (a <= b ? (val >= a && val <=b ) : (val >= a || val <= b))
4145  return 1;
4146  }
4147  if (*exp != ',')
4148  return 0;
4149  }
4150 }
4151 
4152 SWITCH_DECLARE(int) switch_tod_cmp(const char *exp, int val)
4153 {
4154  char *dup = strdup(exp);
4155  char *minh;
4156  char *minm;
4157  char *mins;
4158  char *maxh;
4159  char *maxm;
4160  char *maxs;
4161  char *cur;
4162  char *p;
4163  int range_start, range_end;
4164 
4165  switch_assert(dup);
4166 
4167  cur = dup;
4168  if ((p = strchr(cur, ','))) {
4169  *p++ = '\0';
4170  }
4171 
4172  while (cur) {
4173  minh = cur;
4174  if ((minm=strchr(cur, ':'))) {
4175  *minm++ = '\0';
4176  if ((maxh=strchr(minm, '-'))) {
4177  if ((maxm=strchr(maxh, ':'))) {
4178  *maxh++ = '\0';
4179  *maxm++ = '\0';
4180  /* Check if min/max seconds are present */
4181  if ((mins=strchr(minm, ':'))) {
4182  *mins++ = '\0';
4183  } else {
4184  mins = "00";
4185  }
4186  if ((maxs=strchr(maxm, ':'))) {
4187  *maxs++ = '\0';
4188  } else {
4189  maxs = "00";
4190  }
4191 
4192  range_start = (atol(minh) * 60 * 60) + (atol(minm) * 60) + atol(mins);
4193  range_end = (atol(maxh) * 60 * 60) + (atol(maxm) * 60) + atol(maxs);
4194  if (range_start <= range_end ? (val >= range_start && val <= range_end) : (val >= range_start || val <= range_end)) {
4195  switch_safe_free(dup);
4196  return 1;
4197  }
4198  }
4199  }
4200  }
4201 
4202  cur = p;
4203  if (p) {
4204  if ((p = strchr(p, ','))) {
4205  *p++ = '\0';
4206  }
4207  }
4208 
4209  }
4210 
4211  switch_safe_free(dup);
4212  return 0;
4213 
4214 }
4215 
4216 SWITCH_DECLARE(int) switch_split_user_domain(char *in, char **user, char **domain)
4217 {
4218  char *p = NULL, *h = NULL, *u = NULL;
4219 
4220  if (!in) return 0;
4221 
4222  /* Remove URL scheme */
4223  if (!strncasecmp(in, "sip:", 4)) in += 4;
4224  else if (!strncasecmp(in, "sips:", 5)) in += 5;
4225 
4226  /* Isolate the host part from the user part */
4227  if ((h = in, p = strchr(h, '@'))) *p = '\0', u = in, h = p+1;
4228 
4229  /* Clean out the host part of any suffix */
4230  for (p = h; *p; p++)
4231  if (*p == ':' || *p == ';' || *p == ' ') {
4232  *p = '\0'; break;
4233  }
4234 
4235  if (user) *user = u;
4236  if (domain) *domain = h;
4237  return 1;
4238 }
4239 
4240 
4242 {
4243  switch_uuid_t uuid;
4244 
4245  if (len < (SWITCH_UUID_FORMATTED_LENGTH + 1)) {
4246  switch_snprintf(buf, len, "INVALID");
4247  } else {
4248  switch_uuid_get(&uuid);
4249  switch_uuid_format(buf, &uuid);
4250  }
4251 
4252  return buf;
4253 }
4254 
4255 
4256 SWITCH_DECLARE(char *) switch_format_number(const char *num)
4257 {
4258  char *r;
4259  size_t len;
4260  const char *p = num;
4261 
4262  if (!p) {
4263  return (char*)p;
4264  }
4265 
4266  if (zstr(p)) {
4267  return strdup(p);
4268  }
4269 
4270  if (*p == '+') {
4271  p++;
4272  }
4273 
4274  if (!switch_is_number(p)) {
4275  return strdup(p);
4276  }
4277 
4278  len = strlen(p);
4279 
4280  /* region 1, TBD add more....*/
4281  if (len == 11 && p[0] == '1') {
4282  r = switch_mprintf("%c (%c%c%c) %c%c%c-%c%c%c%c", p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10]);
4283  } else if (len == 10) {
4284  r = switch_mprintf("1 (%c%c%c) %c%c%c-%c%c%c%c", p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9]);
4285  } else {
4286  r = strdup(num);
4287  }
4288 
4289  return r;
4290 }
4291 
4292 
4293 SWITCH_DECLARE(unsigned int) switch_atoui(const char *nptr)
4294 {
4295  int tmp = atoi(nptr);
4296  if (tmp < 0) return 0;
4297  else return (unsigned int) tmp;
4298 }
4299 
4300 SWITCH_DECLARE(unsigned long) switch_atoul(const char *nptr)
4301 {
4302  long tmp = atol(nptr);
4303  if (tmp < 0) return 0;
4304  else return (unsigned long) tmp;
4305 }
4306 
4307 
4309 {
4310 #ifdef HAVE_STRERROR_R
4311 #ifdef STRERROR_R_CHAR_P
4312  /* GNU variant returning char *, avoids warn-unused-result error */
4313  return strerror_r(errnum, buf, buflen);
4314 #else
4315  /*
4316  * XSI variant returning int, with GNU compatible error string,
4317  * if no message could be found
4318  */
4319  if (strerror_r(errnum, buf, buflen)) {
4320  switch_snprintf(buf, buflen, "Unknown error %d", errnum);
4321  }
4322  return buf;
4323 #endif /* STRERROR_R_CHAR_P */
4324 #elif defined(WIN32)
4325  /* WIN32 variant */
4326  if (strerror_s(buf, buflen, errnum)) {
4327  switch_snprintf(buf, buflen, "Unknown error %d", errnum);
4328  }
4329  return buf;
4330 #else
4331  /* Fallback, copy string into private buffer */
4332  switch_copy_string(buf, strerror(errnum), buflen);
4333  return buf;
4334 #endif
4335 }
4336 
4338 {
4339  char *q;
4340  char *next;
4341  char *name, *val;
4342  char *dup = NULL;
4343 
4344  if (qs) {
4345  q = qs;
4346  } else { /*parse our own qs, dup to avoid modify the original string */
4347  dup = q = strdup(request->qs);
4348  }
4349 
4350  switch_assert(q);
4351  next = q;
4352 
4353  do {
4354  char *p;
4355 
4356  if ((next = strchr(next, '&'))) {
4357  *next++ = '\0';
4358  }
4359 
4360  for (p = q; p && *p; p++) {
4361  if (*p == '+') *p = ' ';
4362  }
4363 
4364  switch_url_decode(q);
4365 
4366  name = q;
4367  if ((val = strchr(name, '='))) {
4368  *val++ = '\0';
4370  }
4371  q = next;
4372  } while (q);
4373 
4374  switch_safe_free(dup);
4375 }
4376 
4377 /* clean the uri to protect us from vulnerability attack */
4379 {
4380  int argc;
4381  char *argv[64];
4382  int last, i, len, uri_len = 0;
4383 
4384  argc = switch_separate_string(uri, '/', argv, sizeof(argv) / sizeof(argv[0]));
4385 
4386  if (argc == sizeof(argv)) { /* too deep */
4387  return SWITCH_STATUS_FALSE;
4388  }
4389 
4390  last = 1;
4391  for(i = 1; i < argc; i++) {
4392  if (*argv[i] == '\0' || !strcmp(argv[i], ".")) {
4393  /* ignore //// or /././././ */
4394  } else if (!strcmp(argv[i], "..")) {
4395  /* got /../, go up one level */
4396  if (last > 1) last--;
4397  } else {
4398  argv[last++] = argv[i];
4399  }
4400  }
4401 
4402  for(i = 1; i < last; i++) {
4403  len = strlen(argv[i]);
4404  sprintf(uri + uri_len, "/%s", argv[i]);
4405  uri_len += (len + 1);
4406  }
4407 
4408  return SWITCH_STATUS_SUCCESS;
4409 }
4410 
4412 {
4414  char *p = buffer;
4415  int i = 10;
4416  char *http = NULL;
4417  int header_count;
4418  char *headers[64] = { 0 };
4419  int argc;
4420  char *argv[2] = { 0 };
4421  char *body = NULL;
4422 
4423  if (datalen < 16) return status; /* minimum GET / HTTP/1.1\r\n */
4424 
4425  while(i--) { // sanity check
4426  if (*p++ == ' ') break;
4427  }
4428 
4429  if (i == 0) return status;
4430 
4431  if ((body = strstr(buffer, "\r\n\r\n"))) {
4432  *body = '\0';
4433  body += 4;
4434  } else if (( body = strstr(buffer, "\n\n"))) {
4435  *body = '\0';
4436  body += 2;
4437  } else {
4438  return status;
4439  }
4440 
4441  request->_buffer = strdup(buffer);
4442  switch_assert(request->_buffer);
4443  request->method = request->_buffer;
4444  request->bytes_buffered = datalen;
4445  request->bytes_header = body - buffer;
4446  request->bytes_read = body - buffer;
4447 
4448  p = strchr(request->method, ' ');
4449 
4450  if (!p) goto err;
4451 
4452  *p++ = '\0';
4453 
4454  if (*p != '/') goto err; /* must start from '/' */
4455 
4456  request->uri = p;
4457  p = strchr(request->uri, ' ');
4458 
4459  if (!p) goto err;
4460 
4461  *p++ = '\0';
4462  http = p;
4463 
4464  p = strchr(request->uri, '?');
4465 
4466  if (p) {
4467  *p++ = '\0';
4468  request->qs = p;
4469  }
4470 
4471  if (clean_uri((char *)request->uri) != SWITCH_STATUS_SUCCESS) {
4472  goto err;
4473  }
4474 
4475  if (!strncmp(http, "HTTP/1.1", 8)) {
4476  request->keepalive = SWITCH_TRUE;
4477  } else if (strncmp(http, "HTTP/1.0", 8)) {
4478  goto err;
4479  }
4480 
4481  if (!request->headers) {
4483  goto err;
4484  }
4485  request->_destroy_headers = SWITCH_TRUE;
4486  }
4487 
4488  p = strchr(http, '\n');
4489 
4490  if (p) {
4491  *p++ = '\0'; // now the first header
4492  } else {
4493  goto noheader;
4494  }
4495 
4496  header_count = switch_separate_string(p, '\n', headers, sizeof(headers)/ sizeof(headers[0]));
4497 
4498  if (header_count < 1) goto err;
4499 
4500  for (i = 0; i < header_count; i++) {
4501  char *header, *value;
4502  int len;
4503 
4504  argc = switch_separate_string(headers[i], ':', argv, 2);
4505 
4506  if (argc != 2) goto err;
4507 
4508  header = argv[0];
4509  value = argv[1];
4510 
4511  if (*value == ' ') value++;
4512 
4513  len = strlen(value);
4514 
4515  if (len && *(value + len - 1) == '\r') *(value + len - 1) = '\0';
4516 
4518 
4519  if (!strncasecmp(header, "User-Agent", 10)) {
4520  request->user_agent = value;
4521  } else if (!strncasecmp(header, "Host", 4)) {
4522  request->host = value;
4523  p = strchr(value, ':');
4524 
4525  if (p) {
4526  *p++ = '\0';
4527 
4528  if (*p) request->port = (switch_port_t)atoi(p);
4529  }
4530  } else if (!strncasecmp(header, "Content-Type", 12)) {
4531  request->content_type = value;
4532  } else if (!strncasecmp(header, "Content-Length", 14)) {
4533  request->content_length = atoi(value);
4534  } else if (!strncasecmp(header, "Referer", 7)) {
4535  request->referer = value;
4536  }
4537  }
4538 
4539 noheader:
4540 
4541  if (request->qs) {
4542  switch_http_parse_qs(request, NULL);
4543  }
4544 
4545  return SWITCH_STATUS_SUCCESS;
4546 
4547 err:
4548  switch_http_free_request(request);
4549  return status;
4550 }
4551 
4553 {
4554  if (request->_buffer) free(request->_buffer);
4555  if (request->_destroy_headers && request->headers) {
4556  switch_event_destroy(&request->headers);
4557  }
4558 }
4559 
4560 /* for debugging only */
4562 {
4563  switch_assert(request->method);
4564 
4565  printf("method: %s\n", request->method);
4566 
4567  if (request->uri) printf("uri: %s\n", request->uri);
4568  if (request->qs) printf("qs: %s\n", request->qs);
4569  if (request->host) printf("host: %s\n", request->host);
4570  if (request->port) printf("port: %d\n", request->port);
4571  if (request->from) printf("from: %s\n", request->from);
4572  if (request->user_agent) printf("user_agent: %s\n", request->user_agent);
4573  if (request->referer) printf("referer: %s\n", request->referer);
4574  if (request->user) printf("user: %s\n", request->user);
4575  if (request->keepalive) printf("uri: %d\n", request->keepalive);
4576  if (request->content_type) printf("uri: %s\n", request->content_type);
4577  if (request->content_length) printf("uri: %" SWITCH_SIZE_T_FMT "\n", request->content_length);
4578 
4579  {
4580  switch_event_header_t *header = request->headers->headers;
4581 
4582  printf("headers:\n-------------------------\n");
4583 
4584  while(header) {
4585  printf("%s: %s\n", header->name, header->value);
4586  header = header->next;
4587  }
4588  }
4589 }
4590 
4592 {
4593 #if defined(_WIN32)
4594  FILETIME ct, et, kt, ut; // Times are in 100-ns ticks (div 10000 to get ms)
4595  GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut);
4596  t->userms = ((int64_t)ut.dwLowDateTime | ((int64_t)ut.dwHighDateTime << 32)) / 10000;
4597  t->kernelms = ((int64_t)kt.dwLowDateTime | ((int64_t)kt.dwHighDateTime << 32)) / 10000;
4598 #elif defined(HAVE_GETRUSAGE)
4599  struct rusage r;
4600  getrusage(RUSAGE_SELF, &r);
4601  t->userms = r.ru_utime.tv_sec * 1000 + r.ru_utime.tv_usec / 1000;
4602  t->kernelms = r.ru_stime.tv_sec * 1000 + r.ru_stime.tv_usec / 1000;
4603 #else
4604  t->userms = -1;
4605  t->kernelms = -1;
4606 #endif
4607 }
4608 
4609 
4610 #ifdef SWITCH_HAVE_GUMBO
4611 static void process(GumboNode *node, switch_stream_handle_t *stream)
4612 {
4613  if (node->type == GUMBO_NODE_TEXT) {
4614  stream->write_function(stream, "%s", node->v.text.text);
4615  return;
4616  } else if (node->type == GUMBO_NODE_ELEMENT && node->v.element.tag != GUMBO_TAG_SCRIPT && node->v.element.tag != GUMBO_TAG_STYLE) {
4617  GumboVector *children = &node->v.element.children;
4618  int i;
4619 
4620  if (node->v.element.tag != GUMBO_TAG_UNKNOWN && node->v.element.tag <= GUMBO_TAG_LAST) {
4621  GumboAttribute* attr = NULL;
4622  const char *aval = NULL;
4623 
4624  if (node->v.element.tag == GUMBO_TAG_SPAN) {
4625  if ((attr = gumbo_get_attribute(&node->v.element.attributes, "class"))) {
4626  aval = attr->value;
4627  }
4628  }
4629 
4630  if (aval && !strcasecmp(aval, "Apple-converted-space")) {
4631  const char *txt = ((GumboNode*)children->data[0])->v.text.text;
4632  int x, len = 0;
4633 
4634  for (x = 0; txt[x]; x++) {
4635  if (txt[x] == ' ') {
4636  len++;
4637  }
4638  }
4639 
4640  for (x = 0; x < len*2; x++) {
4641  stream->write_function(stream, "%s", " ");
4642  }
4643  } else {
4644  for (i = 0; i < children->length; ++i) {
4645  process((GumboNode*) children->data[i], stream);
4646  }
4647  }
4648 
4649  if (node->v.element.tag == GUMBO_TAG_P || node->v.element.tag == GUMBO_TAG_BR) {
4650  stream->write_function(stream, "%s", "\n");
4651  }
4652 
4653  }
4654  }
4655 }
4656 #endif
4657 
4659 {
4660  char *p, *html = NULL, *text = NULL;
4661  int x = 0, got_ct = 0;
4662 #ifdef SWITCH_HAVE_GUMBO
4663  GumboOutput *output;
4664  switch_stream_handle_t stream;
4665 
4666  SWITCH_STANDARD_STREAM(stream);
4667 #endif
4668 
4669  for(p = (char *)str; p && *p; p++) {
4670 
4671  if (!strncasecmp(p, "Content-Type:", 13)) {
4672  got_ct++;
4673  }
4674 
4675  if (!got_ct) continue;
4676 
4677  if (*p == '\n') {
4678  x++;
4679  if (x == 2) {
4680  break;
4681  }
4682  } else if (x && (*p != '\r')) {
4683  x = 0;
4684  }
4685  }
4686 
4687  html = p;
4688 
4689 #ifdef SWITCH_HAVE_GUMBO
4690  if ((output = gumbo_parse_with_options(&kGumboDefaultOptions, html, strlen(html)))) {
4691  process(output->root, &stream);
4692  gumbo_destroy_output(&kGumboDefaultOptions, output);
4693  }
4694 
4695  text = (char *)stream.data;
4696 #else
4697  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Support for html parser is not compiled.\n");
4698  text = switch_safe_strdup(html);
4699 #endif
4700 
4701  return text;
4702 }
4703 
4704 SWITCH_DECLARE(unsigned long) switch_getpid(void)
4705 {
4706 #ifndef WIN32
4707  pid_t pid = getpid();
4708 #else
4709  int pid = _getpid();
4710 #endif
4711 
4712  return (unsigned long)pid;
4713 }
4714 
4715 SWITCH_DECLARE(switch_status_t) switch_digest(const char *digest_name, unsigned char **digest, const void *input, switch_size_t inputLen, unsigned int *outputlen)
4716 {
4717 #if defined(HAVE_OPENSSL)
4718  EVP_MD_CTX *mdctx;
4719  const EVP_MD *md;
4720  int size;
4721 
4722  switch_assert(digest);
4723 
4724  if (!digest_name) {
4725  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Message digest is not set\n");
4726  return SWITCH_STATUS_FALSE;
4727  }
4728 
4729  md = EVP_get_digestbyname(digest_name);
4730 
4731  if (!md) {
4732  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown message digest %s\n", digest_name);
4733  return SWITCH_STATUS_FALSE;
4734  }
4735 
4736  size = EVP_MD_size(md);
4737  if (!size || !(*digest = malloc(size))) {
4738  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Zero digest size or can't allocate memory to store results %s\n", digest_name);
4739  return SWITCH_STATUS_FALSE;
4740  }
4741 
4742 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
4743  mdctx = EVP_MD_CTX_new();
4744 #else
4745  mdctx = EVP_MD_CTX_create();
4746 #endif
4747 
4748  if (!mdctx) {
4749  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "EVP_MD_CTX_new error\n");
4750  switch_safe_free(*digest);
4751  return SWITCH_STATUS_FALSE;
4752  }
4753 
4754  EVP_MD_CTX_init(mdctx);
4755  EVP_DigestInit_ex(mdctx, md, NULL);
4756  EVP_DigestUpdate(mdctx, input, inputLen);
4757  EVP_DigestFinal_ex(mdctx, *digest, outputlen);
4758 
4759 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
4760  EVP_MD_CTX_free(mdctx);
4761 #else
4762  EVP_MD_CTX_destroy(mdctx);
4763 #endif
4764 
4765  return SWITCH_STATUS_SUCCESS;
4766 #else
4767  return SWITCH_STATUS_FALSE;
4768 #endif
4769 }
4770 
4771 SWITCH_DECLARE(switch_status_t) switch_digest_string(const char *digest_name, char **digest_str, const void *input, switch_size_t inputLen, unsigned int *outputlen)
4772 {
4773  unsigned char *digest = NULL;
4774  switch_status_t status;
4775  short i = 0, x;
4776  uint8_t b;
4777 
4778  status = switch_digest(digest_name, &digest, input, inputLen, outputlen);
4779 
4780  if (status == SWITCH_STATUS_SUCCESS) {
4781  if ((*digest_str = malloc(*outputlen * 2 + 1))) {
4782  for (x = i = 0; x < *outputlen; x++) {
4783  b = (digest[x] >> 4) & 15;
4784  (*digest_str)[i++] = b + (b > 9 ? 'a' - 10 : '0');
4785  b = digest[x] & 15;
4786  (*digest_str)[i++] = b + (b > 9 ? 'a' - 10 : '0');
4787  }
4788 
4789  (*digest_str)[i] = '\0';
4790  } else {
4791  switch_safe_free(digest);
4792  *outputlen = 0;
4793  return SWITCH_STATUS_FALSE;
4794  }
4795  }
4796 
4797  switch_safe_free(digest);
4798  *outputlen = i;
4799 
4800  return status;
4801 }
4802 
4803 SWITCH_DECLARE(char *) switch_must_strdup(const char *_s)
4804 {
4805  char *s = strdup(_s);
4806  switch_assert(s);
4807  return s;
4808 }
4809 
4811 {
4812  const char *status = NULL;
4813 #ifdef __GLIBC__
4814 /*
4815  * The mallinfo2() function was added in glibc 2.33.
4816  * https://man7.org/linux/man-pages/man3/mallinfo.3.html
4817  */
4818 #if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 33)
4819  struct mallinfo2 mi;
4820 
4821  mi = mallinfo2();
4822 
4823  stream->write_function(stream, "Total non-mmapped bytes (arena): %" SWITCH_SIZE_T_FMT "\n", mi.arena);
4824  stream->write_function(stream, "# of free chunks (ordblks): %" SWITCH_SIZE_T_FMT "\n", mi.ordblks);
4825  stream->write_function(stream, "# of free fastbin blocks (smblks): %" SWITCH_SIZE_T_FMT "\n", mi.smblks);
4826  stream->write_function(stream, "# of mapped regions (hblks): %" SWITCH_SIZE_T_FMT "\n", mi.hblks);
4827  stream->write_function(stream, "Bytes in mapped regions (hblkhd): %" SWITCH_SIZE_T_FMT "\n", mi.hblkhd);
4828  stream->write_function(stream, "Max. total allocated space (usmblks): %" SWITCH_SIZE_T_FMT "\n", mi.usmblks);
4829  stream->write_function(stream, "Free bytes held in fastbins (fsmblks): %" SWITCH_SIZE_T_FMT "\n", mi.fsmblks);
4830  stream->write_function(stream, "Total allocated space (uordblks): %" SWITCH_SIZE_T_FMT "\n", mi.uordblks);
4831  stream->write_function(stream, "Total free space (fordblks): %" SWITCH_SIZE_T_FMT "\n", mi.fordblks);
4832  stream->write_function(stream, "Topmost releasable block (keepcost): %" SWITCH_SIZE_T_FMT "\n", mi.keepcost);
4833 #else
4834  struct mallinfo mi;
4835 
4836  mi = mallinfo();
4837 
4838  stream->write_function(stream, "Total non-mmapped bytes (arena): %u\n", mi.arena);
4839  stream->write_function(stream, "# of free chunks (ordblks): %u\n", mi.ordblks);
4840  stream->write_function(stream, "# of free fastbin blocks (smblks): %u\n", mi.smblks);
4841  stream->write_function(stream, "# of mapped regions (hblks): %u\n", mi.hblks);
4842  stream->write_function(stream, "Bytes in mapped regions (hblkhd): %u\n", mi.hblkhd);
4843  stream->write_function(stream, "Max. total allocated space (usmblks): %u\n", mi.usmblks);
4844  stream->write_function(stream, "Free bytes held in fastbins (fsmblks): %u\n", mi.fsmblks);
4845  stream->write_function(stream, "Total allocated space (uordblks): %u\n", mi.uordblks);
4846  stream->write_function(stream, "Total free space (fordblks): %u\n", mi.fordblks);
4847  stream->write_function(stream, "Topmost releasable block (keepcost): %u\n", mi.keepcost);
4848 
4849 #endif
4850 
4851  switch_goto_status(NULL, done);
4852 #else
4853 #ifdef WIN32
4854  /* Based on: https://docs.microsoft.com/en-us/windows/win32/memory/enumerating-a-heap and https://docs.microsoft.com/en-us/windows/win32/memory/getting-process-heaps */
4855  PHANDLE aHeaps;
4856  SIZE_T BytesToAllocate;
4857  DWORD HeapsIndex;
4858  DWORD HeapsLength;
4859  DWORD NumberOfHeaps;
4860  HRESULT Result;
4861  HANDLE hDefaultProcessHeap;
4862  size_t CommittedSizeTotal = 0;
4863  size_t UnCommittedSizeTotal = 0;
4864  size_t SizeTotal = 0;
4865  size_t OverheadTotal = 0;
4866 
4867  NumberOfHeaps = GetProcessHeaps(0, NULL);
4868  Result = SIZETMult(NumberOfHeaps, sizeof(*aHeaps), &BytesToAllocate);
4869  if (Result != S_OK) {
4870  switch_goto_status("SIZETMult failed.", done);
4871  }
4872 
4873  hDefaultProcessHeap = GetProcessHeap();
4874  if (hDefaultProcessHeap == NULL) {
4875  switch_goto_status("Failed to retrieve the default process heap", done);
4876  }
4877 
4878  aHeaps = (PHANDLE)HeapAlloc(hDefaultProcessHeap, 0, BytesToAllocate);
4879  if (aHeaps == NULL) {
4880  switch_goto_status("HeapAlloc failed to allocate space for heaps", done);
4881  }
4882 
4883  HeapsLength = NumberOfHeaps;
4884  NumberOfHeaps = GetProcessHeaps(HeapsLength, aHeaps);
4885 
4886  if (NumberOfHeaps == 0) {
4887  switch_goto_status("Failed to retrieve heaps", cleanup);
4888  } else if (NumberOfHeaps > HeapsLength) {
4889  /*
4890  * Compare the latest number of heaps with the original number of heaps.
4891  * If the latest number is larger than the original number, another
4892  * component has created a new heap and the buffer is too small.
4893  */
4894  switch_goto_status("Another component created a heap between calls.", cleanup);
4895  }
4896 
4897  stream->write_function(stream, "Process has %d heaps.\n", HeapsLength);
4898  for (HeapsIndex = 0; HeapsIndex < HeapsLength; ++HeapsIndex) {
4899  PROCESS_HEAP_ENTRY Entry;
4900  HANDLE hHeap = aHeaps[HeapsIndex];
4901 
4902  stream->write_function(stream, "Heap %d at address: %#p.\n", HeapsIndex, aHeaps[HeapsIndex]);
4903 
4904  /* Lock the heap to prevent other threads from accessing the heap during enumeration. */
4905  if (HeapLock(hHeap) == FALSE) {
4906  switch_goto_status("Failed to lock heap.", cleanup);
4907  }
4908 
4909  Entry.lpData = NULL;
4910  while (HeapWalk(hHeap, &Entry) != FALSE) {
4911  if ((Entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
4912  } else if ((Entry.wFlags & PROCESS_HEAP_REGION) != 0) {
4913  CommittedSizeTotal += Entry.Region.dwCommittedSize;
4914  UnCommittedSizeTotal += Entry.Region.dwUnCommittedSize;
4915  }
4916 
4917  SizeTotal += Entry.cbData;
4918  OverheadTotal += Entry.cbOverhead;
4919  }
4920 
4921  /* Unlock the heap to allow other threads to access the heap after enumeration has completed. */
4922  if (HeapUnlock(hHeap) == FALSE) {
4923  abort();
4924  }
4925  }
4926 
4927  stream->write_function(stream, "Committed bytes: %" SWITCH_SIZE_T_FMT "\n", CommittedSizeTotal);
4928  stream->write_function(stream, "Uncommited bytes: %" SWITCH_SIZE_T_FMT "\n", UnCommittedSizeTotal);
4929  stream->write_function(stream, "Size: %" SWITCH_SIZE_T_FMT "\n", SizeTotal);
4930  stream->write_function(stream, "Overhead: %" SWITCH_SIZE_T_FMT"\n", OverheadTotal);
4931 
4932 cleanup:
4933  HeapFree(hDefaultProcessHeap, 0, aHeaps);
4934 #else
4935  switch_goto_status("Memory usage statistics is not implemented on the current platform.", done);
4936 #endif
4937 #endif
4938 done:
4939  return status;
4940 }
4941 
4942 #define SHA256_LENGTH 32
4943 SWITCH_DECLARE(cJSON *) switch_jwt_verify(const char *secret, const char *token)
4944 {
4945  int ok = 0;
4946  cJSON *json = NULL;
4947  cJSON *payload = NULL;
4948  char *out = NULL;
4949  unsigned int len = 0;
4950  unsigned char signature[SHA256_LENGTH];
4951  const char *alg = NULL;
4952  const char *typ = NULL;
4953  char *header = strdup(token);
4954  char *dot;
4955 
4956  switch_assert(header);
4957  dot = strchr(header, '.');
4958  if (!dot) goto end;
4959  *dot = '\0';
4960  out = (char *)switch_must_malloc(strlen(header) + 1);
4961  len = switch_b64_decode((const char *)header, out, strlen(header) + 1);
4962  if (len == 0) goto end;
4963  json = cJSON_Parse(out); // header
4964  free(out);
4965  out = NULL;
4966  if (!json) goto end;
4967  alg = cJSON_GetObjectCstr(json, "alg");
4968  if (!alg || strcmp(alg, "HS256")) goto end;
4969  typ = cJSON_GetObjectCstr(json, "typ");
4970  if (!typ || strcmp(typ, "JWT")) goto end;
4971  cJSON_Delete(json);
4972  json = NULL;
4973  dot++; // payload
4974  dot = strrchr(token, '.');
4975  if (!dot) goto end;
4976  HMAC(EVP_sha256(), secret, strlen(secret), (unsigned char *)token, dot - token, signature, &len);
4977  if (len != SHA256_LENGTH) goto end;
4978  dot++; // signature
4979  out = (char *)switch_must_malloc(strlen(dot) + 1);
4980  len = switch_b64_decode((const char *)dot, out, strlen(dot) + 1);
4981  if (len != SHA256_LENGTH) goto end;
4982  ok = !memcmp(out, signature, len);
4983  free(out);
4984  out = NULL;
4985 
4986  if (ok) {
4987  char *p = strchr(token, '.');
4988 
4989  if (p) {
4990  p++;
4991  out = (char *)switch_must_malloc(strlen(p));
4992  len = switch_b64_decode((const char *)p, out, strlen(p));
4993  payload = cJSON_Parse(out);
4994  free(out);
4995  out = NULL;
4996  }
4997  }
4998 
4999 end:
5000  switch_safe_free(header);
5001  switch_safe_free(out);
5002  if (json) cJSON_Delete(json);
5003 
5004  return payload;
5005 }
5006 
5007 SWITCH_DECLARE(char *) switch_jwt_sign(const char *secret, const uint8_t *payload, switch_size_t size)
5008 {
5009  cJSON *json;
5010  switch_size_t need;
5011  char *header;
5012  uint8_t *bheader;
5013  uint8_t *bpayload;
5014  char *to_sign;
5015  unsigned int len = 0;
5016  unsigned char signature[SHA256_LENGTH];
5017  unsigned char *bsignature;
5018  char *result = NULL;
5019 
5020  if (!secret || !payload) return NULL;
5021 
5022  json = cJSON_CreateObject();
5023  switch_assert(json);
5024  cJSON_AddStringToObject(json, "alg", "HS256");
5025  cJSON_AddStringToObject(json, "typ", "JWT");
5026  header = cJSON_Print(json);
5027  cJSON_Delete(json);
5028  if (!header) return NULL;
5029 
5030  need = ((strlen(header) + 3 - 1) / 3) * 4 + 1; // with extra NULL
5031  bheader = (uint8_t *)switch_must_malloc(need);
5032  switch_b64_encode((unsigned char *)header, strlen(header), bheader, need);
5033  free(header);
5034  header = NULL;
5035 
5036  need = ((size + 3 - 1) / 3) * 4 + 1; // with extra NULL
5037  bpayload = (uint8_t *)switch_must_malloc(need);
5038  switch_b64_encode((unsigned char *)payload, size, bpayload, need);
5039 
5040  to_sign = switch_mprintf("%s.%s", (char *)bheader, (char *)bpayload);
5041  switch_assert(to_sign);
5042 
5043  HMAC(EVP_sha256(), secret, strlen(secret), (unsigned char *)to_sign, strlen(to_sign), signature, &len);
5044  switch_assert(len == SHA256_LENGTH);
5045  free(to_sign);
5046  to_sign = NULL;
5047 
5048  need = ((len + 3 - 1) / 3) * 4 + 1; // with extra NULL
5049  bsignature = (uint8_t *)switch_must_malloc(need);
5050  switch_b64_encode((unsigned char *)signature, len, bsignature, need);
5051  result = switch_mprintf("%s.%s.%s", bheader, bpayload, bsignature);
5052 
5053  free(bheader);
5054  free(bpayload);
5055  free(bsignature);
5056 
5057  return result;
5058 }
5059 
5060 /* For Emacs:
5061  * Local Variables:
5062  * mode:c
5063  * indent-tabs-mode:t
5064  * tab-width:4
5065  * c-basic-offset:4
5066  * End:
5067  * For VIM:
5068  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
5069  */
int switch_isupper(int c)
char * switch_escape_char(switch_memory_pool_t *pool, char *in, const char *delim, char esc)
Escape a string by prefixing a list of characters with an escape character.
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:311
int switch_build_uri(char *uri, switch_size_t size, const char *scheme, const char *user, const switch_sockaddr_t *sa, int flags)
build a URI string from components
#define switch_regex_safe_free(re)
Definition: switch_regex.h:79
switch_status_t switch_digest_string(const char *digest_name, char **digest_str, const void *input, switch_size_t inputLen, unsigned int *outputlen)
unsigned int switch_queue_size(switch_queue_t *queue)
Definition: switch_apr.c:1238
char * switch_escape_string_pool(const char *in, switch_memory_pool_t *pool)
switch_bool_t m
Definition: switch_frame.h:83
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
char * switch_strip_whitespace(const char *str)
switch_status_t switch_time_exp_get(switch_time_t *result, switch_time_exp_t *input)
Definition: switch_apr.c:341
#define switch_inet_ntop
struct switch_network_node * node_head
Definition: switch_utils.c:80
char * switch_url_encode_opt(const char *url, char *buf, size_t len, switch_bool_t double_encode)
uint16_t switch_sockaddr_get_port(switch_sockaddr_t *sa)
Definition: switch_apr.c:1001
int switch_regex_copy_substring(const char *subject, int *ovector, int stringcount, int stringnumber, char *buffer, int size)
Definition: switch_regex.c:44
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700
#define switch_test_subnet(_ip, _net, _mask)
switch_time_t switch_str_time(const char *in)
Converts a string representation of a date into a switch_time_t.
char * switch_amp_encode(char *s, char *buf, switch_size_t len)
Definition: switch_utils.c:939
#define SWITCH_CHANNEL_LOG
int old_switch_tolower(int c)
switch_status_t switch_frame_free(switch_frame_t **frame)
Definition: switch_utils.c:363
char * switch_core_url_encode_opt(switch_memory_pool_t *pool, const char *url, switch_bool_t double_encode)
const char *const const double number
Definition: switch_cJSON.h:254
#define IN6_AND_MASK(result, ip, mask)
Definition: switch_utils.c:478
switch_os_socket_t sock
switch_bool_t switch_is_lan_addr(const char *ip)
void switch_img_free(switch_image_t **img)
Close an image descriptor.
int switch_isspace(int c)
static switch_frame_t * find_free_frame(switch_frame_buffer_t *fb, switch_frame_t *orig)
Definition: switch_utils.c:141
char * switch_string_replace(const char *string, const char *search, const char *replace)
unsigned long switch_atoul(const char *nptr)
switch_size_t bytes_read
static int get_netmask(struct sockaddr_in *me, int *mask)
switch_frame_t * frame
Definition: switch_utils.c:127
static int switch_errno_is_break(int errcode)
Definition: switch_utils.h:649
char * switch_find_end_paren(const char *s, char open, char close)
Definition: switch_utils.c:796
switch_status_t switch_frame_buffer_create(switch_frame_buffer_t **fbP, switch_size_t qlen)
Definition: switch_utils.c:303
switch_bool_t switch_network_list_validate_ip_token(switch_network_list_t *list, uint32_t ip, const char **token)
Definition: switch_utils.c:577
switch_bool_t switch_ast2regex(const char *pat, char *rbuf, size_t len)
void switch_split_date(const char *exp, int *year, int *month, int *day)
char * switch_strip_spaces(char *str, switch_bool_t dup)
int switch_wait_sock(switch_os_socket_t sock, uint32_t ms, switch_poll_t flags)
void switch_http_dump_request(switch_http_request_t *request)
#define O_BINARY
cJSON *const to
#define _X
static const char switch_b64_table[65]
switch_bool_t
Definition: switch_types.h:437
int switch_frame_buffer_size(switch_frame_buffer_t *fb)
Definition: switch_utils.c:287
uint32_t timestamp
Definition: switch_frame.h:80
switch_bool_t is_port_in_node(int port, switch_network_node_t *node)
Definition: switch_utils.c:524
static unsigned int separate_string_char_delim(char *buf, char delim, char **array, unsigned int arraylen)
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:733
const cJSON *const b
Definition: switch_cJSON.h:243
int switch_iscntrl(int c)
char * switch_core_session_url_encode(switch_core_session_t *session, const char *url)
int old_switch_toupper(int c)
switch_priority_t
Priority Indication.
unsigned int switch_atoui(const char *nptr)
switch_bool_t switch_network_list_validate_ip6_port_token(switch_network_list_t *list, ip_t ip, int port, const char **token)
Definition: switch_utils.c:497
struct switch_network_node * next
Definition: switch_utils.c:75
switch_queue_t * queue
Definition: switch_utils.c:136
int switch_islower(int c)
int switch_isalpha(int c)
switch_status_t switch_frame_dup(switch_frame_t *orig, switch_frame_t **clone)
Definition: switch_utils.c:321
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
switch_memory_pool_t * pool
void switch_http_free_request(switch_http_request_t *request)
static unsigned int separate_string_blank_delim_cheap(const char *buf, const char **array, unsigned int larray[], unsigned int arraylen)
switch_status_t switch_find_local_ip(char *buf, int len, int *mask, int family)
An event Header.
Definition: switch_event.h:65
void * switch_calloc(size_t nmemb, size_t size)
Definition: switch_utils.c:86
const char *const const char *const const cJSON *const value
#define SWITCH_RTP_MAX_BUF_LEN
Definition: switch_rtp.h:45
switch_status_t switch_queue_trypop(switch_queue_t *queue, void **data)
Definition: switch_apr.c:1264
int switch_ispunct(int c)
unsigned int switch_separate_string_cheap(const char *buf, char delim, const char **array, unsigned int larray[], unsigned int arraylen)
#define DLINE_BLOCK_SIZE
Definition: switch_utils.c:842
static void * switch_must_malloc(size_t _b)
Definition: switch_core.h:233
char * switch_url_encode(const char *url, char *buf, size_t len)
switch_status_t switch_time_exp_lt(switch_time_exp_t *result, switch_time_t input)
Definition: switch_apr.c:346
int switch_isdigit(int c)
const char * switch_memory_usage_stream(switch_stream_handle_t *stream)
char * switch_separate_paren_args(char *str)
const char * switch_dow_int2str(int val)
int switch_strcasecmp_any(const char *str,...)
Definition: switch_utils.c:394
switch_status_t switch_network_list_add_cidr_port_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok, const char *token, switch_network_port_range_p port)
Definition: switch_utils.c:675
switch_status_t switch_queue_pop(switch_queue_t *queue, void **data)
Definition: switch_apr.c:1243
#define SWITCH_CTYPE_NUM_CHARS
switch_status_t switch_http_parse_header(char *buffer, uint32_t datalen, switch_http_request_t *request)
#define _L
switch_size_t switch_fd_read_dline(int fd, char **buf, switch_size_t *len)
Definition: switch_utils.c:844
struct real_pcre switch_regex_t
Definition: switch_regex.h:43
char * switch_print_host(switch_sockaddr_t *addr, char *buf, switch_size_t len)
Definition: switch_utils.c:98
uint32_t ssrc
Definition: switch_frame.h:82
pack cur
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
int switch_tod_cmp(const char *exp, int val)
struct switch_runtime runtime
Definition: switch_core.c:86
#define SWITCH_SOCK_INVALID
switch_size_t switch_fd_read_line(int fd, char *buf, switch_size_t len)
Definition: switch_utils.c:822
switch_bool_t switch_testv6_subnet(ip_t _ip, ip_t _net, ip_t _mask)
Definition: switch_utils.c:483
int switch_isgraph(int c)
const char * content_type
#define SWITCH_URL_UNSAFE
Definition: switch_utils.h:47
switch_codec_t * codec
Definition: switch_frame.h:56
int switch_split_user_domain(char *in, char **user, char **domain)
Split a user string as user and domain.
const char * user_agent
switch_bool_t _destroy_headers
static dow_t _dow_read_token(const char **s)
#define end_of_p(_s)
Definition: switch_utils.h:686
#define zstr(x)
Definition: switch_utils.h:314
int cJSON_bool fmt
Definition: switch_cJSON.h:150
switch_bool_t switch_simple_email(const char *to, const char *from, const char *headers, const char *body, const char *file, const char *convert_cmd, const char *convert_ext)
char * switch_util_quote_shell_arg_pool(const char *string, switch_memory_pool_t *pool)
Quote shell argument, allocating from pool if provided.
unsigned long switch_getpid(void)
void switch_split_time(const char *exp, int *hour, int *min, int *sec)
void switch_getcputime(switch_cputime *t)
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
int get_addr_int(switch_sockaddr_t *sa)
static char * switch_safe_strdup(const char *it)
Definition: switch_utils.h:887
int switch_system(const char *cmd, switch_bool_t wait)
Definition: switch_core.c:3342
int switch_number_cmp(const char *exp, int val)
switch_bool_t switch_is_leading_number(const char *str)
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
void switch_http_parse_qs(switch_http_request_t *request, char *qs)
char * switch_core_session_url_encode_opt(switch_core_session_t *session, const char *url, switch_bool_t double_encode)
char * switch_escape_string(const char *in, char *out, switch_size_t outlen)
char * get_addr6(char *buf, switch_size_t len, struct sockaddr_in6 *sa, socklen_t salen)
uint16_t seq
Definition: switch_frame.h:81
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:124
int64_t switch_time_t
Definition: switch_apr.h:188
uint32_t buflen
Definition: switch_frame.h:70
switch_status_t switch_b64_encode(unsigned char *in, switch_size_t ilen, unsigned char *out, switch_size_t olen)
switch_byte_t switch_byte_t * buf
#define _U
switch_size_t switch_fp_read_dline(FILE *fd, char **buf, switch_size_t *len)
Definition: switch_utils.c:892
switch_status_t switch_frame_buffer_dup(switch_frame_buffer_t *fb, switch_frame_t *orig, switch_frame_t **clone)
Definition: switch_utils.c:250
uint32_t datalen
Definition: switch_frame.h:68
switch_byte_t in
switch_mutex_t * mutex
Definition: switch_utils.c:137
int switch_isxdigit(int c)
uint32_t packetlen
Definition: switch_frame.h:62
int ports[MAX_NETWORK_PORTS]
Definition: switch_utils.h:53
switch_status_t switch_frame_buffer_destroy(switch_frame_buffer_t **fbP)
Definition: switch_utils.c:292
const int _switch_C_ctype_[1+SWITCH_CTYPE_NUM_CHARS]
switch_frame_node_t * head
Definition: switch_utils.c:134
char * switch_find_parameter(const char *str, const char *param, switch_memory_pool_t *pool)
Definition: switch_utils.c:415
switch_frame_flag_t flags
Definition: switch_frame.h:85
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
switch_status_t switch_network_list_add_host_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok)
Definition: switch_utils.c:737
payload_map_t * pmap
Definition: switch_frame.h:87
uint32_t v4
Definition: switch_utils.h:278
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:684
cJSON * switch_jwt_verify(const char *secret, const char *token)
uint32_t rate
Definition: switch_frame.h:74
const short * _switch_toupper_tab_
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
const char * switch_cut_path(const char *in)
Create a pointer to the file name in a given file path eliminating the directory name.
#define switch_zmalloc(ptr, len)
#define _P
void switch_img_copy(switch_image_t *img, switch_image_t **new_img)
Copy image to a new image.
unsigned short get_port(struct sockaddr *sa)
get the port number of an ip address
int switch_cmp_addr(switch_sockaddr_t *sa1, switch_sockaddr_t *sa2, switch_bool_t ip_only)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
switch_status_t switch_string_match(const char *string, size_t string_len, const char *search, size_t search_len)
static uint32_t switch_toupper(uint32_t eax)
Definition: switch_utils.h:101
#define SHA256_LENGTH
int switch_os_socket_t
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:293
#define switch_errno()
Definition: switch_utils.h:647
#define SWITCH_BLANK_STRING
Definition: switch_types.h:48
switch_status_t switch_network_list_create(switch_network_list_t **list, const char *name, switch_bool_t default_type, switch_memory_pool_t *pool)
Definition: switch_utils.c:459
char * switch_network_port_range_to_string(switch_network_port_range_p port)
Definition: switch_utils.c:593
void * extra_data
Definition: switch_frame.h:64
struct switch_frame_node_s * next
Definition: switch_utils.c:130
char * switch_must_strdup(const char *_s)
#define switch_arraylen(_a)
Definition: switch_utils.h:374
An abstraction of a data frame.
Definition: switch_frame.h:54
uintptr_t switch_size_t
int switch_parse_cidr(const char *string, ip_t *ip, ip_t *mask, uint32_t *bitp)
Definition: switch_utils.c:743
uint16_t switch_port_t
char * switch_util_quote_shell_arg(const char *string)
Quote shell argument.
const char * cJSON_GetObjectCstr(const cJSON *object, const char *string)
Definition: switch_json.c:22
switch_status_t switch_time_exp_gmt_get(switch_time_t *result, switch_time_exp_t *input)
Definition: switch_apr.c:336
switch_byte_t switch_byte_t uint32_t buflen
#define zstr_buf(s)
Definition: switch_utils.h:318
#define SWITCH_STANDARD_STREAM(s)
int switch_regex_perform(const char *field, const char *expression, switch_regex_t **new_re, int *ovector, uint32_t olen)
Definition: switch_regex.c:55
char * get_addr(char *buf, switch_size_t len, struct sockaddr *sa, socklen_t salen)
find the char representation of an ip adress
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
char * switch_core_url_encode(switch_memory_pool_t *pool, const char *url)
#define MAX_NETWORK_PORTS
Definition: switch_utils.h:49
const short _switch_C_tolower_[1+SWITCH_CTYPE_NUM_CHARS]
static char * cleanup_separated_string(char *str, char delim)
static char RFC2833_CHARS[]
int switch_dow_str2int(const char *exp)
switch_status_t switch_frame_buffer_push(switch_frame_buffer_t *fb, void *ptr)
Definition: switch_utils.c:267
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:82
switch_status_t switch_poll(switch_pollfd_t *aprset, int32_t numsock, int32_t *nsds, switch_interval_time_t timeout)
Definition: switch_apr.c:1100
#define DLINE_MAX_SIZE
Definition: switch_utils.c:843
switch_bool_t switch_network_list_validate_ip_port_token(switch_network_list_t *list, uint32_t ip, int port, const char **token)
Definition: switch_utils.c:546
struct fspr_sockaddr_t switch_sockaddr_t
Definition: switch_apr.h:1029
switch_status_t switch_frame_buffer_pop(switch_frame_buffer_t *fb, void **ptr)
Definition: switch_utils.c:277
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:993
struct fspr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
const short _switch_C_toupper_[1+SWITCH_CTYPE_NUM_CHARS]
struct switch_frame_node_s * prev
Definition: switch_utils.c:129
switch_bool_t switch_is_number(const char *str)
void switch_uuid_format(char *buffer, const switch_uuid_t *uuid)
Definition: switch_apr.c:1140
void * packet
Definition: switch_frame.h:60
switch_stream_handle_write_function_t write_function
unsigned char switch_char_to_rfc2833(char key)
Return the RFC2833 event based on an key character.
switch_memory_pool_t * pool
Definition: switch_utils.c:82
switch_size_t content_length
switch_image_t * img
Definition: switch_frame.h:88
#define SWITCH_SIZE_T_FMT
switch_status_t
Common return values.
char * switch_pool_strip_whitespace(switch_memory_pool_t *pool, const char *str)
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:287
#define _C
struct switch_event_header * next
Definition: switch_event.h:76
int switch_socket_waitfor(switch_pollfd_t *poll, int ms)
Wait for a socket.
switch_status_t switch_network_list_add_cidr_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok, const char *token)
Definition: switch_utils.c:702
struct in6_addr v6
Definition: switch_utils.h:279
unsigned int switch_separate_string_string(char *buf, char *delim, char **array, unsigned int arraylen)
char * switch_url_decode(char *s)
char switch_rfc2833_to_char(int event)
Return the RFC2833 character based on an event id.
#define _S
int switch_fulldate_cmp(const char *exp, switch_time_t *ts)
switch_status_t switch_frame_buffer_trypop(switch_frame_buffer_t *fb, void **ptr)
Definition: switch_utils.c:282
#define _B
char * switch_html_strip(const char *str)
#define FALSE
static int write_buf(int fd, const char *buf)
Main Library Header.
switch_status_t switch_frame_alloc(switch_frame_t **frame, switch_size_t size)
Definition: switch_utils.c:109
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:384
unsigned int switch_separate_string(char *buf, char delim, char **array, unsigned int arraylen)
#define SWITCH_DECLARE(type)
#define B64BUFFLEN
const char * filename
uint32_t samples
Definition: switch_frame.h:72
switch_status_t switch_digest(const char *digest_name, unsigned char **digest, const void *input, switch_size_t inputLen, unsigned int *outputlen)
char * switch_network_ipv4_mapped_ipv6_addr(const char *ip_str)
Definition: switch_utils.c:582
void switch_uuid_get(switch_uuid_t *uuid)
Definition: switch_apr.c:1152
switch_status_t switch_resolve_host(const char *host, char *buf, size_t buflen)
char * switch_strip_commas(char *in, char *out, switch_size_t len)
uint32_t channels
Definition: switch_frame.h:76
switch_bool_t switch_is_uint_in_range(const char *str, unsigned int from, unsigned int to)
Check if a 32 bit unsigned number is in a range.
int switch_isalnum(int c)
char * switch_strerror_r(int errnum, char *buf, switch_size_t buflen)
switch_network_port_range_t port_range
Definition: switch_utils.c:74
switch_status_t switch_queue_trypush(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1279
char * switch_jwt_sign(const char *secret, const uint8_t *payload, switch_size_t size)
char * buffer
Definition: switch_cJSON.h:153
const char * switch_core_mime_ext2type(const char *ext)
Definition: switch_core.c:1211
#define _N
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:322
int switch_inet_pton(int af, const char *src, void *dst)
Definition: switch_utils.c:92
switch_bool_t default_type
Definition: switch_utils.c:81
char * key
Definition: switch_msrp.c:64
switch_status_t switch_queue_push(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1253
switch_payload_t payload
Definition: switch_frame.h:78
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
char * switch_uuid_str(char *buf, switch_size_t len)
static const char * DOW[]
switch_bool_t switch_network_list_validate_ip6_token(switch_network_list_t *list, ip_t ip, const char **token)
Definition: switch_utils.c:572
int count
Definition: switch_cJSON.h:204
struct fspr_pool_t switch_memory_pool_t
const char *const name
Definition: switch_cJSON.h:250
const char * switch_get_addr(char *buf, switch_size_t len, switch_sockaddr_t *in)
Definition: switch_apr.c:979
switch_status_t switch_queue_create(switch_queue_t **queue, unsigned int queue_capacity, switch_memory_pool_t *pool)
Definition: switch_apr.c:1233
void switch_event_destroy(switch_event_t **event)
Destroy an event.
switch_bool_t ok
Definition: switch_utils.c:71
switch_status_t clean_uri(char *uri)
struct switch_frame_node_s switch_frame_node_t
switch_bool_t keepalive
switch_status_t switch_frame_buffer_trypush(switch_frame_buffer_t *fb, void *ptr)
Definition: switch_utils.c:272
const short * _switch_tolower_tab_
const char * switch_stristr(const char *instr, const char *str)
switch_poll_t
switch_size_t switch_b64_decode(const char *in, char *out, switch_size_t olen)
dow_t
char * switch_core_sprintf(_In_ switch_memory_pool_t *pool, _In_z_ _Printf_format_string_ const char *fmt,...)
printf-style style printing routine. The data is output to a string allocated from the pool ...
#define switch_assert(expr)
const int * _switch_ctype_
static char unescape_char(char escaped)
switch_status_t switch_find_interface_ip(char *buf, int len, int *mask, const char *ifname, int family)
switch_event_t * headers
int switch_cp_addr(switch_sockaddr_t *sa1, switch_sockaddr_t *sa2)
int switch_isprint(int c)
#define ESCAPE_META
Definition: switch_utils.c:51
switch_status_t switch_frame_buffer_free(switch_frame_buffer_t *fb, switch_frame_t **frameP)
Definition: switch_utils.c:217
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)
memset(buf, 0, buflen)
int switch_wait_socklist(switch_waitlist_t *waitlist, uint32_t len, uint32_t ms)
switch_size_t bytes_header
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
switch_size_t bytes_buffered
switch_status_t switch_network_list_perform_add_cidr_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok, const char *token, switch_network_port_range_p port)
Definition: switch_utils.c:619
#define SWITCH_UUID_FORMATTED_LENGTH
Definition: switch_apr.h:545
switch_bool_t switch_dow_cmp(const char *exp, int val)
switch_event_header_t * headers
Definition: switch_event.h:90
char * switch_strip_nonnumerics(char *in, char *out, switch_size_t len)
static unsigned int separate_string_blank_delim(char *buf, char **array, unsigned int arraylen)
char * switch_core_get_variable_dup(_In_z_ const char *varname)
static unsigned int separate_string_char_delim_cheap(const char *buf, char delim, const char **array, unsigned int larray[], unsigned int arraylen)
char * switch_format_number(const char *num)
switch_status_t switch_network_list_add_host_port_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok, switch_network_port_range_p port)
Definition: switch_utils.c:707
switch_memory_pool_t * pool
Definition: switch_utils.c:135
const char * switch_priority_name(switch_priority_t priority)
Return a printable name of a switch_priority_t.
char * switch_replace_char(char *str, char from, char to, switch_bool_t dup)