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 * Seven Du <dujinfang@gmail.com>
28 *
29 *
30 * switch_utils.h -- Compatability and Helper Code
31 *
32 */
33 /*! \file switch_utils.h
34 \brief Compatability and Helper Code
35
36 Just a miscelaneaous set of general utility/helper functions.
37
38 */
39 #ifndef SWITCH_UTILS_H
40 #define SWITCH_UTILS_H
41
42 #include <switch.h>
43 #include <math.h>
44
45 SWITCH_BEGIN_EXTERN_C
46
47 #define SWITCH_URL_UNSAFE "\r\n #%&+:;<=>?@[\\]^`{|}\""
48
49 #define MAX_NETWORK_PORTS 10
50
51 struct switch_network_port_range {
52 int port;
53 int ports[MAX_NETWORK_PORTS];
54 int min_port;
55 int max_port;
56 };
57 typedef struct switch_network_port_range switch_network_port_range_t;
58 typedef switch_network_port_range_t* switch_network_port_range_p;
59
switch_get_hex_bytes(switch_byte_t * buf,switch_size_t datalen,char * new_buf,switch_size_t new_datalen)60 static inline char *switch_get_hex_bytes(switch_byte_t *buf, switch_size_t datalen, char *new_buf, switch_size_t new_datalen)
61 {
62 switch_byte_t *p, *e;
63 char *pp, *ee;
64
65 e = buf + datalen;
66 ee = new_buf + new_datalen;
67 pp = new_buf;
68
69 for (p = buf; p < e && pp < ee - 4; p++) {
70 if (snprintf(pp, 4, "%.2x ", (int)*p) < 0) {
71 return NULL;
72 }
73 pp += 3;
74 }
75 *(pp-1) = '\0';
76
77 return new_buf;
78 }
79
80
switch_round_to_step(uint32_t num,uint32_t step)81 static inline uint32_t switch_round_to_step(uint32_t num, uint32_t step)
82 {
83 uint32_t r;
84 uint32_t x;
85
86 if (!num) return 0;
87
88 r = (num % step);
89 x = num - r;
90
91 if (r > step / 2) {
92 x += step;
93 }
94
95 return x;
96 }
97
98 /* https://code.google.com/p/stringencoders/wiki/PerformanceAscii
99 http://www.azillionmonkeys.com/qed/asmexample.html
100 */
switch_toupper(uint32_t eax)101 static inline uint32_t switch_toupper(uint32_t eax)
102 {
103 uint32_t ebx = (0x7f7f7f7ful & eax) + 0x05050505ul;
104 ebx = (0x7f7f7f7ful & ebx) + 0x1a1a1a1aul;
105 ebx = ((ebx & ~eax) >> 2 ) & 0x20202020ul;
106 return eax - ebx;
107 }
108
109 /* https://code.google.com/p/stringencoders/wiki/PerformanceAscii
110 http://www.azillionmonkeys.com/qed/asmexample.html
111 */
switch_tolower(uint32_t eax)112 static inline uint32_t switch_tolower(uint32_t eax)
113 {
114 uint32_t ebx = (0x7f7f7f7ful & eax) + 0x25252525ul;
115 ebx = (0x7f7f7f7ful & ebx) + 0x1a1a1a1aul;
116 ebx = ((ebx & ~eax) >> 2) & 0x20202020ul;
117 return eax + ebx;
118 }
119
120
121 #ifdef FS_64BIT
122
123 /* https://code.google.com/p/stringencoders/wiki/PerformanceAscii
124 http://www.azillionmonkeys.com/qed/asmexample.html
125 */
switch_toupper64(uint64_t eax)126 static inline uint64_t switch_toupper64(uint64_t eax)
127 {
128 uint64_t ebx = (0x7f7f7f7f7f7f7f7full & eax) + 0x0505050505050505ull;
129 ebx = (0x7f7f7f7f7f7f7f7full & ebx) + 0x1a1a1a1a1a1a1a1aull;
130 ebx = ((ebx & ~eax) >> 2 ) & 0x2020202020202020ull;
131 return eax - ebx;
132 }
133
134 /* https://code.google.com/p/stringencoders/wiki/PerformanceAscii
135 http://www.azillionmonkeys.com/qed/asmexample.html
136 */
switch_tolower64(uint64_t eax)137 static inline uint64_t switch_tolower64(uint64_t eax)
138 {
139 uint64_t ebx = (0x7f7f7f7f7f7f7f7full & eax) + 0x2525252525252525ull;
140 ebx = (0x7f7f7f7f7f7f7f7full & ebx) + 0x1a1a1a1a1a1a1a1aull;
141 ebx = ((ebx & ~eax) >> 2) & 0x2020202020202020ull;
142 return eax + ebx;
143 }
144
switch_toupper_max(char * s)145 static inline void switch_toupper_max(char *s)
146 {
147 uint64_t *b,*p;
148 char *c;
149 size_t l;
150
151 l = strlen(s);
152
153 p = (uint64_t *) s;
154
155 while (l > 8) {
156 b = p;
157 *b = (uint64_t) switch_toupper64(*b);
158 b++;
159 p++;
160 l -= 8;
161 }
162
163 c = (char *)p;
164
165 while(l > 0) {
166 *c = (char) switch_toupper(*c);
167 c++;
168 l--;
169 }
170
171 }
172
switch_tolower_max(char * s)173 static inline void switch_tolower_max(char *s)
174 {
175 uint64_t *b,*p;
176 char *c;
177 size_t l;
178
179 l = strlen(s);
180
181 p = (uint64_t *) s;
182
183 while (l > 8) {
184 b = p;
185 *b = (uint64_t) switch_tolower64(*b);
186 b++;
187 p++;
188 l -= 8;
189 }
190
191 c = (char *)p;
192
193 while(l > 0) {
194 *c = (char) switch_tolower(*c);
195 c++;
196 l--;
197 }
198
199 }
200
201 #else
202
switch_toupper_max(char * s)203 static inline void switch_toupper_max(char *s)
204 {
205 uint32_t *b,*p;
206 char *c;
207 size_t l;
208
209 l = strlen(s);
210
211 p = (uint32_t *) s;
212
213 while (l > 4) {
214 b = p;
215 *b = (uint32_t) switch_toupper(*b);
216 b++;
217 p++;
218 l -= 4;
219 }
220
221 c = (char *)p;
222
223 while(l > 0) {
224 *c = (char) switch_toupper(*c);
225 c++;
226 l--;
227 }
228
229 }
230
switch_tolower_max(char * s)231 static inline void switch_tolower_max(char *s)
232 {
233 uint32_t *b,*p;
234 char *c;
235 size_t l;
236
237 l = strlen(s);
238
239 p = (uint32_t *) s;
240
241 while (l > 4) {
242 b = p;
243 *b = (uint32_t) switch_tolower(*b);
244 b++;
245 p++;
246 l -= 4;
247 }
248
249 c = (char *)p;
250
251 while(l > 0) {
252 *c = (char) switch_tolower(*c);
253 c++;
254 l--;
255 }
256
257 }
258 #endif
259
260
261
262
263 SWITCH_DECLARE(int) old_switch_toupper(int c);
264 SWITCH_DECLARE(int) old_switch_tolower(int c);
265 SWITCH_DECLARE(int) switch_isalnum(int c);
266 SWITCH_DECLARE(int) switch_isalpha(int c);
267 SWITCH_DECLARE(int) switch_iscntrl(int c);
268 SWITCH_DECLARE(int) switch_isdigit(int c);
269 SWITCH_DECLARE(int) switch_isgraph(int c);
270 SWITCH_DECLARE(int) switch_islower(int c);
271 SWITCH_DECLARE(int) switch_isprint(int c);
272 SWITCH_DECLARE(int) switch_ispunct(int c);
273 SWITCH_DECLARE(int) switch_isspace(int c);
274 SWITCH_DECLARE(int) switch_isupper(int c);
275 SWITCH_DECLARE(int) switch_isxdigit(int c);
276
277 typedef union{
278 uint32_t v4;
279 struct in6_addr v6;
280 } ip_t;
281
282 SWITCH_DECLARE(switch_bool_t) switch_testv6_subnet(ip_t _ip, ip_t _net, ip_t _mask);
283
284
285 SWITCH_DECLARE(char *) switch_print_host(switch_sockaddr_t *addr, char *buf, switch_size_t len);
286
287 #define switch_goto_status(_status, _label) status = _status; goto _label
288 #define switch_goto_int(_n, _i, _label) _n = _i; goto _label
289 #define switch_samples_per_packet(rate, interval) ((uint32_t)((float)rate / (1000.0f / (float)interval)))
290 #define SWITCH_SMAX 32767
291 #define SWITCH_SMIN -32768
292 #define switch_normalize_to_16bit(n) if (n > SWITCH_SMAX) n = SWITCH_SMAX; else if (n < SWITCH_SMIN) n = SWITCH_SMIN;
293 #define switch_codec2str(codec,buf,len) snprintf(buf, len, "%s@%uh@%ui", \
294 codec->implementation->iananame, \
295 codec->implementation->samples_per_second, \
296 codec->implementation->microseconds_per_packet / 1000)
297
298
299
300 /*!
301 \brief Test for NULL or zero length string
302 \param s the string to test
303 \return true value if the string is NULL or zero length
304 */
_zstr(_In_opt_z_ const char * s)305 _Check_return_ static inline int _zstr(_In_opt_z_ const char *s)
306 {
307 if (!s) return 1;
308 if (*s == '\0') return 1;
309 return 0;
310 }
311 #ifdef _PREFAST_
312 #define zstr(x) (_zstr(x) ? 1 : __analysis_assume(x),0)
313 #else
314 #define zstr(x) _zstr(x)
315 #endif
316 #define switch_strlen_zero(x) zstr(x)
317 #define switch_strlen_zero_buf(x) zstr_buf(x)
318 #define zstr_buf(s) (*(s) == '\0')
switch_is_moh(const char * s)319 static inline switch_bool_t switch_is_moh(const char *s)
320 {
321 if (zstr(s) || !strcasecmp(s, "silence") || !strcasecmp(s, "indicate_hold")) {
322 return SWITCH_FALSE;
323 }
324 return SWITCH_TRUE;
325 }
326
327
328 #define zset(_a, _b) if (!zstr(_b)) _a = _b
329
330
331 /* find a character (find) in a string (in) and return a pointer to that point in the string where the character was found
332 using the array (allowed) as allowed non-matching characters, when (allowed) is NULL, behaviour should be identical to strchr()
333 */
switch_strchr_strict(const char * in,char find,const char * allowed)334 static inline char *switch_strchr_strict(const char *in, char find, const char *allowed)
335 {
336 const char *p;
337
338 switch_assert(in);
339
340 p = in;
341
342 if (!*p) return NULL;
343
344 while(p && *p) {
345 const char *a = allowed;
346 int acceptable = 0;
347
348 if (*p == find) break;
349
350 if (!a) {
351 acceptable = 1;
352 } else {
353
354 while(a && *a) {
355
356 if (*p == *a) {
357 acceptable = 1;
358 break;
359 }
360
361 a++;
362 }
363
364 }
365
366 if (!acceptable) return NULL;
367
368 p++;
369 }
370
371 return (char *) p;
372 }
373
374 #define switch_arraylen(_a) (sizeof(_a) / sizeof(_a[0]))
375 #define switch_split(_data, _delim, _array) switch_separate_string(_data, _delim, _array, switch_arraylen(_array))
376
377 #define switch_is_valid_rate(_tmp) (_tmp == 8000 || _tmp == 12000 || _tmp == 16000 || _tmp == 24000 || _tmp == 32000 || _tmp == 11025 || _tmp == 22050 || _tmp == 44100 || _tmp == 48000)
378
379
380 #ifdef _MSC_VER
381 #pragma warning(disable:6011)
382 #endif
switch_string_has_escaped_data(const char * in)383 static inline int switch_string_has_escaped_data(const char *in)
384 {
385 const char *i;
386
387 switch_assert(in);
388
389 i = strchr(in, '\\');
390
391 while (i && *i == '\\') {
392 i++;
393 if (*i == '\\' || *i == 'n' || *i == 's' || *i == 't' || *i == '\'') {
394 return 1;
395 }
396 i = strchr(i, '\\');
397 }
398
399 return 0;
400 }
401 #ifdef _MSC_VER
402 #pragma warning(default:6011)
403 #endif
404
405 SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size_t ilen, unsigned char *out, switch_size_t olen);
406 SWITCH_DECLARE(switch_size_t) switch_b64_decode(const char *in, char *out, switch_size_t olen);
407 SWITCH_DECLARE(char *) switch_amp_encode(char *s, char *buf, switch_size_t len);
408
409
410
switch_print_bits(const unsigned char * byte,char * buf,switch_size_t buflen)411 static inline char *switch_print_bits(const unsigned char *byte, char *buf, switch_size_t buflen)
412 {
413 int i;
414 switch_size_t j = 0, k = 0, l = 0;
415
416 while(k < buflen) {
417 l = 0;
418 for (i = 7; i >= 0; i--) {
419 buf[j++] = (*byte & (1 << i)) ? '1' : '0';
420 if (++l % 4 == 0) {
421 buf[j++] = ' ';
422 }
423 }
424 k++;
425 byte++;
426 }
427
428 if (buf[j-1] == ' ') j--;
429 buf[j++] = '\0';
430 return buf;
431 }
432
433
434
435
switch_is_digit_string(const char * s)436 static inline switch_bool_t switch_is_digit_string(const char *s)
437 {
438
439 while (s && *s) {
440 if (*s < 48 || *s > 57) {
441 return SWITCH_FALSE;
442 }
443 s++;
444 }
445
446 return SWITCH_TRUE;
447 }
448
switch_itodtmf(char i)449 static inline char switch_itodtmf(char i)
450 {
451 char r = i;
452
453 if (i > 9 && i < 14) {
454 r += 55;
455 } else {
456 r += 48;
457 }
458
459 return r;
460 }
461
switch_dtmftoi(char * s)462 static inline int switch_dtmftoi(char *s)
463 {
464 int r;
465
466 switch_assert(s);
467
468 if (!(r = atoi(s))) {
469 int l = tolower((unsigned char)*s);
470 if (l > 96 && l < 101) {
471 r = l - 87;
472 }
473 }
474
475 return r;
476 }
477
switch_known_bitrate(switch_payload_t payload)478 static inline uint32_t switch_known_bitrate(switch_payload_t payload)
479 {
480 switch(payload) {
481 case 0: /* PCMU */ return 64000;
482 case 3: /* GSM */ return 13200;
483 case 4: /* G723 */ return 6300;
484 case 7: /* LPC */ return 2400;
485 case 8: /* PCMA */ return 64000;
486 case 9: /* G722 */ return 64000;
487 case 18: /* G729 */ return 8000;
488 default: break;
489 }
490
491 return 0;
492 }
493
494 SWITCH_DECLARE(switch_size_t) switch_fd_read_line(int fd, char *buf, switch_size_t len);
495 SWITCH_DECLARE(switch_size_t) switch_fd_read_dline(int fd, char **buf, switch_size_t *len);
496 SWITCH_DECLARE(switch_size_t) switch_fp_read_dline(FILE *fd, char **buf, switch_size_t *len);
497
498 SWITCH_DECLARE(switch_status_t) switch_frame_alloc(switch_frame_t **frame, switch_size_t size);
499 SWITCH_DECLARE(switch_status_t) switch_frame_dup(switch_frame_t *orig, switch_frame_t **clone);
500 SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame);
501 SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str);
502 SWITCH_DECLARE(switch_bool_t) switch_is_leading_number(const char *str);
503 SWITCH_DECLARE(char *) switch_find_parameter(const char *str, const char *param, switch_memory_pool_t *pool);
504
505 /*!
506 \brief Evaluate the truthfullness of a string expression
507 \param expr a string expression
508 \return true or false
509 */
switch_true(const char * expr)510 static inline switch_bool_t switch_true(const char *expr)
511 {
512 return ((expr && ( !strcasecmp(expr, "yes") ||
513 !strcasecmp(expr, "on") ||
514 !strcasecmp(expr, "true") ||
515 !strcasecmp(expr, "t") ||
516 !strcasecmp(expr, "enabled") ||
517 !strcasecmp(expr, "active") ||
518 !strcasecmp(expr, "allow") ||
519 (switch_is_number(expr) && atoi(expr)))) ? SWITCH_TRUE : SWITCH_FALSE);
520 }
521
switch_true_byte(const char * expr)522 static inline switch_byte_t switch_true_byte(const char *expr)
523 {
524 return (switch_byte_t)switch_true(expr);
525 }
526
527 #define switch_true_buf(expr)\
528 ((( !strcasecmp(expr, "yes") ||\
529 !strcasecmp(expr, "on") ||\
530 !strcasecmp(expr, "true") ||\
531 !strcasecmp(expr, "t") ||\
532 !strcasecmp(expr, "enabled") ||\
533 !strcasecmp(expr, "active") ||\
534 !strcasecmp(expr, "allow") ||\
535 (switch_is_number(expr) && atoi(expr)))) ? SWITCH_TRUE : SWITCH_FALSE)
536
537 /*!
538 \brief Evaluate the falsefullness of a string expression
539 \param expr a string expression
540 \return true or false
541 */
switch_false(const char * expr)542 static inline int switch_false(const char *expr)
543 {
544 return ((expr && ( !strcasecmp(expr, "no") ||
545 !strcasecmp(expr, "off") ||
546 !strcasecmp(expr, "false") ||
547 !strcasecmp(expr, "f") ||
548 !strcasecmp(expr, "disabled") ||
549 !strcasecmp(expr, "inactive") ||
550 !strcasecmp(expr, "disallow") ||
551 (switch_is_number(expr) && !atoi(expr)))) ? SWITCH_TRUE : SWITCH_FALSE);
552 }
553
554
555 SWITCH_DECLARE(switch_status_t) switch_resolve_host(const char *host, char *buf, size_t buflen);
556
557
558 /*!
559 \brief find local ip of the box
560 \param buf the buffer to write the ip address found into
561 \param len the length of the buf
562 \param mask the CIDR found (AF_INET only)
563 \param family the address family to return (AF_INET or AF_INET6)
564 \return SWITCH_STATUS_SUCCESSS for success, otherwise failure
565 */
566 SWITCH_DECLARE(switch_status_t) switch_find_local_ip(_Out_opt_bytecapcount_(len)
567 char *buf, _In_ int len, _In_opt_ int *mask, _In_ int family);
568
569 /*!
570 \brief find primary ip of the specified interface
571 \param buf the buffer to write the ip address found into
572 \param len the length of the buf
573 \param mask the CIDR found (AF_INET only)
574 \param ifname interface name to check
575 \param family the address family to return (AF_INET or AF_INET6)
576 \return SWITCH_STATUS_SUCCESSS for success, otherwise failure
577 */
578 SWITCH_DECLARE(switch_status_t) switch_find_interface_ip(_Out_opt_bytecapcount_(len)
579 char *buf, _In_ int len, _In_opt_ int *mask, _In_ const char *ifname, _In_ int family);
580
581 /*!
582 \brief find the char representation of an ip adress
583 \param buf the buffer to write the ip adress found into
584 \param len the length of the buf
585 \param sa the struct sockaddr * to get the adress from
586 \param salen the length of sa
587 \return the ip adress string
588 */
589 SWITCH_DECLARE(char *) get_addr(char *buf, switch_size_t len, struct sockaddr *sa, socklen_t salen);
590 SWITCH_DECLARE(char *) get_addr6(char *buf, switch_size_t len, struct sockaddr_in6 *sa, socklen_t salen);
591
592 SWITCH_DECLARE(int) get_addr_int(switch_sockaddr_t *sa);
593 SWITCH_DECLARE(int) switch_cmp_addr(switch_sockaddr_t *sa1, switch_sockaddr_t *sa2);
594 SWITCH_DECLARE(int) switch_cp_addr(switch_sockaddr_t *sa1, switch_sockaddr_t *sa2);
595
596 /*!
597 \brief get the port number of an ip address
598 \param sa the struct sockaddr * to get the port from
599 \return the ip adress string
600 */
601 SWITCH_DECLARE(unsigned short) get_port(struct sockaddr *sa);
602
603 /*!
604 \brief flags to be used with switch_build_uri()
605 */
606 enum switch_uri_flags {
607 SWITCH_URI_NUMERIC_HOST = 1,
608 SWITCH_URI_NUMERIC_PORT = 2,
609 SWITCH_URI_NO_SCOPE = 4
610 };
611
612 /*!
613 \brief build a URI string from components
614 \param uri output string
615 \param size maximum size of output string (including trailing null)
616 \param scheme URI scheme
617 \param user user part or null if none
618 \param sa host address
619 \param flags logical OR-ed combination of flags from \ref switch_uri_flags
620 \return number of characters printed (not including the trailing null)
621 */
622 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);
623
624 #define SWITCH_STATUS_IS_BREAK(x) (x == SWITCH_STATUS_BREAK || x == 730035 || x == 35 || x == SWITCH_STATUS_INTR)
625
626
627 #ifdef _MSC_VER
628
629 #define switch_errno() WSAGetLastError()
630
switch_errno_is_break(int errcode)631 static inline int switch_errno_is_break(int errcode)
632 {
633 return errcode == WSAEWOULDBLOCK || errcode == WSAEINPROGRESS || errcode == WSAEINTR;
634 }
635
636 #else
637
638 #define switch_errno() errno
639
switch_errno_is_break(int errcode)640 static inline int switch_errno_is_break(int errcode)
641 {
642 return errcode == EAGAIN || errcode == EWOULDBLOCK || errcode == EINPROGRESS || errcode == EINTR || errcode == ETIMEDOUT;
643 }
644
645 #endif
646
647
648 /*!
649 \brief Return a printable name of a switch_priority_t
650 \param priority the priority to get the name of
651 \return the printable form of the priority
652 */
653 SWITCH_DECLARE(const char *) switch_priority_name(switch_priority_t priority);
654
655 /*!
656 \brief Return the RFC2833 character based on an event id
657 \param event the event id to convert
658 \return the character represented by the event or null for an invalid event
659 */
660 SWITCH_DECLARE(char) switch_rfc2833_to_char(int event);
661
662 /*!
663 \brief Return the RFC2833 event based on an key character
664 \param key the charecter to encode
665 \return the event id for the specified character or -1 on an invalid input
666 */
667 SWITCH_DECLARE(unsigned char) switch_char_to_rfc2833(char key);
668
669 /*!
670 \brief determine if a character is a valid DTMF key
671 \param key the key to test
672 \return TRUE or FALSE
673 */
674 #define is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119 || key == 70 || key == 102)
675
676 #define end_of(_s) *(*_s == '\0' ? _s : _s + strlen(_s) - 1)
677 #define end_of_p(_s) (*_s == '\0' ? _s : _s + strlen(_s) - 1)
678 /*!
679 \brief Test for the existance of a flag on an arbitary object
680 \param obj the object to test
681 \param flag the or'd list of flags to test
682 \return true value if the object has the flags defined
683 */
684 #define switch_test_flag(obj, flag) ((obj)->flags & flag)
685
686 /*!
687 \brief Set a flag on an arbitrary object
688 \param obj the object to set the flags on
689 \param flag the or'd list of flags to set
690 */
691 #define switch_set_flag(obj, flag) (obj)->flags |= (flag)
692
693 /*!
694 \brief Set a flag on an arbitrary object while locked
695 \param obj the object to set the flags on
696 \param flag the or'd list of flags to set
697 */
698 #define switch_set_flag_locked(obj, flag) assert((obj)->flag_mutex != NULL); \
699 switch_mutex_lock((obj)->flag_mutex); \
700 (obj)->flags |= (flag);\
701 switch_mutex_unlock((obj)->flag_mutex);
702
703 /*!
704 \brief Clear a flag on an arbitrary object
705 \param obj the object to test
706 \param flag the or'd list of flags to clear
707 */
708 #define switch_clear_flag_locked(obj, flag) switch_mutex_lock((obj)->flag_mutex); (obj)->flags &= ~(flag); switch_mutex_unlock((obj)->flag_mutex);
709
710 /*!
711 \brief Clear a flag on an arbitrary object while locked
712 \param obj the object to test
713 \param flag the or'd list of flags to clear
714 */
715 #define switch_clear_flag(obj, flag) (obj)->flags &= ~(flag)
716
717 /*!
718 \brief Copy flags from one arbitrary object to another
719 \param dest the object to copy the flags to
720 \param src the object to copy the flags from
721 \param flags the flags to copy
722 */
723 #define switch_copy_flags(dest, src, flags) (dest)->flags &= ~(flags); (dest)->flags |= ((src)->flags & (flags))
724
725 #define switch_set_string(_dst, _src) switch_copy_string(_dst, _src, sizeof(_dst))
726
727
switch_sanitize_number(char * number)728 static inline char *switch_sanitize_number(char *number)
729 {
730 char *p = number, *q;
731 char warp[] = "/:";
732 int i;
733
734 switch_assert(number);
735
736 if (!(strchr(p, '/') || strchr(p, ':') || strchr(p, '@'))) {
737 return number;
738 }
739
740 while ((q = strrchr(p, '@')))
741 *q = '\0';
742
743 for (i = 0; i < (int) strlen(warp); i++) {
744 while (p && (q = strchr(p, warp[i])))
745 p = q + 1;
746 }
747
748 return p;
749 }
750
switch_string_var_check(char * s,switch_bool_t disable)751 static inline switch_bool_t switch_string_var_check(char *s, switch_bool_t disable)
752 {
753 char *p;
754 char *dol = NULL;
755
756 for (p = s; p && *p; p++) {
757 if (*p == '$') {
758 dol = p;
759 } else if (dol) {
760 if (*p == '{') {
761 if (disable) {
762 *dol = '%';
763 dol = NULL;
764 } else {
765 return SWITCH_TRUE;
766 }
767 } else if (*p != '\\') {
768 dol = NULL;
769 }
770 }
771 }
772 return SWITCH_FALSE;
773 }
774
775
switch_string_var_check_const(const char * s)776 static inline switch_bool_t switch_string_var_check_const(const char *s)
777 {
778 const char *p;
779 int dol = 0;
780
781 for (p = s; p && *p; p++) {
782 if (*p == '$') {
783 dol = 1;
784 } else if (dol) {
785 if (*p == '{') {
786 return SWITCH_TRUE;
787 } else if (*p != '\\') {
788 dol = 0;
789 }
790 }
791 }
792 return SWITCH_FALSE;
793 }
794
switch_var_clean_string(char * s)795 static inline char *switch_var_clean_string(char *s)
796 {
797 switch_string_var_check(s, SWITCH_TRUE);
798 return s;
799 }
800
switch_clean_string(char * s)801 static inline char *switch_clean_string(char *s)
802 {
803 char *p;
804 for (p = s; p && *p; p++) {
805 uint8_t x = (uint8_t) * p;
806 if ((x < 32) && x != '\n' && x != '\r') {
807 *p = ' ';
808 }
809 }
810
811 return s;
812 }
813
814
switch_clean_name_string(char * s)815 static inline char *switch_clean_name_string(char *s)
816 {
817 char *p;
818 for (p = s; p && *p; p++) {
819 uint8_t x = (uint8_t) * p;
820 if ((x < 32) || x == '\'' || x == '"' || x == '<' || x == '>' || x == '\\' || x == ':' || x == '@' || x == '/') {
821 *p = ' ';
822 }
823 if ( (p == s) && (*p == ' ') ) {
824 s++;
825 }
826 }
827
828 return s;
829 }
830
831
832
833 /*!
834 \brief Turn a string into a number (default if NULL)
835 \param nptr the string
836 \param dft the default
837 \return the number version of the string or the default
838 */
switch_safe_atoi(const char * nptr,int dft)839 static inline int switch_safe_atoi(const char *nptr, int dft)
840 {
841 return nptr ? atoi(nptr) : dft;
842 }
843
844
845 /*!
846 \brief Free a pointer and set it to NULL unless it already is NULL
847 \param it the pointer
848 */
849 #define switch_safe_free(it) if (it) {free(it);it=NULL;}
850
switch_safe_strdup(const char * it)851 static inline char *switch_safe_strdup(const char *it)
852 {
853 if (it) {
854 return strdup(it);
855 }
856
857 return NULL;
858 }
859
860
861 #ifdef _MSC_VER
862 #pragma warning(disable:6011)
863 #endif
switch_lc_strdup(const char * it)864 static inline char *switch_lc_strdup(const char *it)
865 {
866 char *dup;
867 char *p;
868
869 if (it) {
870 dup = strdup(it);
871 for (p = dup; p && *p; p++) {
872 *p = (char) switch_tolower(*p);
873 }
874 return dup;
875 }
876
877 return NULL;
878 }
879
880
switch_uc_strdup(const char * it)881 static inline char *switch_uc_strdup(const char *it)
882 {
883 char *dup;
884 char *p;
885
886 if (it) {
887 dup = strdup(it);
888 for (p = dup; p && *p; p++) {
889 *p = (char) switch_toupper(*p);
890 }
891 return dup;
892 }
893
894 return NULL;
895 }
896 #ifdef _MSC_VER
897 #pragma warning(default:6011)
898 #endif
899
900
901 /*!
902 \brief Test if one string is inside another with extra case checking
903 \param s the inner string
904 \param q the big string
905 \return SWITCH_TRUE or SWITCH_FALSE
906 */
switch_strstr(char * s,char * q)907 static inline switch_bool_t switch_strstr(char *s, char *q)
908 {
909 char *p, *S = NULL, *Q = NULL;
910 switch_bool_t tf = SWITCH_FALSE;
911
912 if (!s || !q) {
913 return SWITCH_FALSE;
914 }
915
916 if (strstr(s, q)) {
917 return SWITCH_TRUE;
918 }
919
920 S = strdup(s);
921
922 switch_assert(S != NULL);
923
924 for (p = S; p && *p; p++) {
925 *p = (char) switch_toupper(*p);
926 }
927
928 if (strstr(S, q)) {
929 tf = SWITCH_TRUE;
930 goto done;
931 }
932
933 Q = strdup(q);
934 switch_assert(Q != NULL);
935
936 for (p = Q; p && *p; p++) {
937 *p = (char) switch_toupper(*p);
938 }
939
940 if (strstr(s, Q)) {
941 tf = SWITCH_TRUE;
942 goto done;
943 }
944
945 if (strstr(S, Q)) {
946 tf = SWITCH_TRUE;
947 goto done;
948 }
949
950 done:
951 switch_safe_free(S);
952 switch_safe_free(Q);
953
954 return tf;
955 }
956
957
958 /*!
959 \brief Make a null string a blank string instead
960 \param s the string to test
961 \return the original string or blank string.
962 */
963 #define switch_str_nil(s) (s ? s : "")
964
965 /*!
966 \brief Wait a desired number of microseconds and yield the CPU
967 */
968 #define switch_yield(ms) switch_sleep(ms);
969
970 /*!
971 \brief Converts a string representation of a date into a switch_time_t
972 \param in the string
973 \return the epoch time in usec
974 */
975 SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in);
976 #define switch_time_from_sec(sec) ((switch_time_t)(sec) * 1000000)
977
978 /*!
979 \brief Declares a function designed to set a dynamic global string
980 \param fname the function name to declare
981 \param vname the name of the global pointer to modify with the new function
982 */
983 #define SWITCH_DECLARE_GLOBAL_STRING_FUNC(fname, vname) static void fname(const char *string) { if (!string) return;\
984 if (vname) {free(vname); vname = NULL;}vname = strdup(string);} static void fname(const char *string)
985
986 /*!
987 \brief Separate a string into an array based on a character delimiter
988 \param buf the string to parse
989 \param delim the character delimiter
990 \param array the array to split the values into
991 \param arraylen the max number of elements in the array
992 \return the number of elements added to the array
993 */
994 SWITCH_DECLARE(unsigned int) switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen);
995 SWITCH_DECLARE(unsigned int) switch_separate_string_string(char *buf, char *delim, _Post_count_(return) char **array, unsigned int arraylen);
996
997
998 SWITCH_DECLARE(char *) switch_strip_spaces(char *str, switch_bool_t dup);
999 SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str);
1000 SWITCH_DECLARE(char *) switch_strip_commas(char *in, char *out, switch_size_t len);
1001 SWITCH_DECLARE(char *) switch_strip_nonnumerics(char *in, char *out, switch_size_t len);
1002 SWITCH_DECLARE(char *) switch_separate_paren_args(char *str);
1003 SWITCH_DECLARE(const char *) switch_stristr(const char *instr, const char *str);
1004 SWITCH_DECLARE(switch_bool_t) switch_is_lan_addr(const char *ip);
1005 SWITCH_DECLARE(char *) switch_replace_char(char *str, char from, char to, switch_bool_t dup);
1006 SWITCH_DECLARE(switch_bool_t) switch_ast2regex(const char *pat, char *rbuf, size_t len);
1007 SWITCH_DECLARE(char *) switch_pool_strip_whitespace(switch_memory_pool_t *pool, const char *str);
1008
1009 /*!
1010 \brief Escape a string by prefixing a list of characters with an escape character
1011 \param pool a memory pool to use
1012 \param in the string
1013 \param delim the list of characters to escape
1014 \param esc the escape character
1015 \return the escaped string
1016 */
1017 SWITCH_DECLARE(char *) switch_escape_char(switch_memory_pool_t *pool, char *in, const char *delim, char esc);
1018
1019 SWITCH_DECLARE(char *) switch_escape_string(const char *in, char *out, switch_size_t outlen);
1020 SWITCH_DECLARE(char *) switch_escape_string_pool(const char *in, switch_memory_pool_t *pool);
1021
1022 /*!
1023 \brief Wait for a socket
1024 \param poll the pollfd to wait on
1025 \param ms the number of milliseconds to wait
1026 \return the requested condition
1027 */
1028 SWITCH_DECLARE(int) switch_socket_waitfor(switch_pollfd_t *poll, int ms);
1029
1030 /*!
1031 \brief Create a pointer to the file name in a given file path eliminating the directory name
1032 \return the pointer to the next character after the final / or \\ characters
1033 */
1034 SWITCH_DECLARE(const char *) switch_cut_path(const char *in);
1035
1036 SWITCH_DECLARE(char *) switch_string_replace(const char *string, const char *search, const char *replace);
1037 SWITCH_DECLARE(switch_status_t) switch_string_match(const char *string, size_t string_len, const char *search, size_t search_len);
1038 SWITCH_DECLARE(int) switch_strcasecmp_any(const char *str, ...);
1039
1040 /*!
1041 \brief Quote shell argument
1042 \param string the string to quote (example: a ' b"' c)
1043 \return the quoted string (gives: 'a '\'' b"'\'' c' for unices, "a ' b ' c" for MS Windows), should be freed
1044 */
1045 SWITCH_DECLARE(char *) switch_util_quote_shell_arg(const char *string);
1046
1047 /*!
1048 \brief Quote shell argument, allocating from pool if provided
1049 \param string the string to quote (example: a ' b"' c)
1050 \param pool a memory pool to use
1051 \return the quoted string (gives: 'a '\'' b"'\'' c' for unices, "a ' b ' c" for MS Windows), if pool not provided, returned value should be freed
1052 */
1053 SWITCH_DECLARE(char *) switch_util_quote_shell_arg_pool(const char *string, switch_memory_pool_t *pool);
1054
1055
1056 #define SWITCH_READ_ACCEPTABLE(status) (status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK || status == SWITCH_STATUS_INUSE)
1057
1058
switch_calc_bitrate(int w,int h,float quality,double fps)1059 static inline int32_t switch_calc_bitrate(int w, int h, float quality, double fps)
1060 {
1061 int r;
1062
1063 if (quality == 0) {
1064 quality = 1;
1065 }
1066
1067 /* KUSH GAUGE*/
1068
1069 if (!fps) fps = 15;
1070
1071 r = (int32_t)((double)(w * h * fps * quality) * 0.07) / 1000;
1072
1073 if (!quality) r /= 2;
1074
1075 if (quality < 0.0f) {
1076 r = (int) ((float)r * quality);
1077 }
1078
1079 return r;
1080
1081 }
1082
switch_calc_fps(switch_fps_t * fpsP,float fps,int samplerate)1083 static inline void switch_calc_fps(switch_fps_t *fpsP, float fps, int samplerate)
1084 {
1085 /*
1086 implicit/truncf() - leave us with equal-or-smaller ms and thus equal-or-bigger fps, which is better for quality (than roundf()).
1087 also equal-or-bigger fps is better for things like (int)fps
1088 */
1089 fpsP->ms = (int)(1000.0f / fps);
1090 fpsP->fps = 1000.0f / fpsP->ms;
1091 fpsP->samples = (int)(samplerate / 1000 * fpsP->ms); // samplerate 99.99% is a factor of 1000, so we safe here with integer div by 1000
1092 return;
1093 }
1094 #define switch_calc_video_fps(fpsP, fps) switch_calc_fps(fpsP, fps, 90000)
1095
switch_parse_bandwidth_string(const char * bwv)1096 static inline int32_t switch_parse_bandwidth_string(const char *bwv)
1097 {
1098 float bw = 0;
1099
1100 if (!bwv) return 0;
1101
1102 if (!strcasecmp(bwv, "auto")) {
1103 return -1;
1104 }
1105
1106 if ((bw = (float) atof(bwv))) {
1107 if (bw < 0) return 0;
1108
1109 if (strstr(bwv, "KB")) {
1110 bw *= 8;
1111 } else if (strstr(bwv, "mb")) {
1112 bw *= 1024;
1113 } else if (strstr(bwv, "MB")) {
1114 bw *= 8192;
1115 }
1116 }
1117
1118 return (int32_t) roundf(bw);
1119 }
1120
switch_parse_cpu_string(const char * cpu)1121 static inline uint32_t switch_parse_cpu_string(const char *cpu)
1122 {
1123 int cpu_count = switch_core_cpu_count();
1124 int ncpu;
1125
1126 if (!cpu) return 1;
1127
1128 if (!strcasecmp(cpu, "auto")) {
1129 if (cpu_count > 4) return 4;
1130 if (cpu_count <= 2) return 1;
1131
1132 return (uint32_t)(cpu_count / 2);
1133 }
1134
1135 if (!strncasecmp(cpu, "cpu/", 4)) { /* cpu/2 or cpu/2/<max> */
1136 const char *has_max = cpu;
1137 float divisor;
1138 int max = cpu_count;
1139
1140 cpu +=4;
1141
1142 has_max = strchr(cpu, '/');
1143
1144 if (has_max > cpu) {
1145 max = atoi(has_max + 1);
1146 }
1147
1148 divisor = (float)atof(cpu);
1149
1150 if (divisor <= 0) divisor = 1;
1151
1152 ncpu = (int)(cpu_count / divisor);
1153
1154 if (ncpu <= 0) return 1;
1155
1156 if (ncpu > max) return (uint32_t)max;
1157
1158 return (uint32_t)ncpu;
1159 } else if (!strcasecmp(cpu, "cpu")) {
1160 ncpu = cpu_count;
1161 } else {
1162 ncpu = atoi(cpu);
1163
1164 if (strrchr(cpu, '%')) {
1165 ncpu = (int) (cpu_count * ((float)ncpu / 100));
1166 }
1167 }
1168
1169 if (ncpu > cpu_count) return (uint32_t)cpu_count;
1170
1171 if (ncpu <= 0) return 1;
1172
1173 return ncpu;
1174 }
1175
switch_needs_url_encode(const char * s)1176 static inline int switch_needs_url_encode(const char *s)
1177 {
1178 const char hex[] = "0123456789ABCDEF";
1179 const char *p, *e = end_of_p(s);
1180
1181
1182 for(p = s; p && *p; p++) {
1183 if (*p == '%' && e-p > 1) {
1184 if (strchr(hex, *(p+1)) && strchr(hex, *(p+2))) {
1185 p++;
1186 continue;
1187 }
1188 }
1189
1190 if (strchr(SWITCH_URL_UNSAFE, *p)) {
1191 return 1;
1192 }
1193 }
1194
1195 return 0;
1196 }
1197
1198 SWITCH_DECLARE(char *) switch_url_encode_opt(const char *url, char *buf, size_t len, switch_bool_t double_encode);
1199 SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len);
1200 SWITCH_DECLARE(char *) switch_url_decode(char *s);
1201
1202 SWITCH_DECLARE(char *) switch_core_url_encode_opt(switch_memory_pool_t *pool, const char *url, switch_bool_t double_encode);
1203 SWITCH_DECLARE(char *) switch_core_url_encode(switch_memory_pool_t *pool, const char *url);
1204 SWITCH_DECLARE(char *) switch_core_session_url_encode_opt(switch_core_session_t *session, const char *url, switch_bool_t double_encode);
1205 SWITCH_DECLARE(char *) switch_core_session_url_encode(switch_core_session_t *session, const char *url);
1206
1207
1208 SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to,
1209 const char *from,
1210 const char *headers,
1211 const char *body, const char *file, const char *convert_cmd, const char *convert_ext);
1212 SWITCH_DECLARE(char *) switch_find_end_paren(const char *s, char open, char close);
1213
switch_separate_file_params(const char * file,char ** file_portion,char ** params_portion)1214 static inline void switch_separate_file_params(const char *file, char **file_portion, char **params_portion)
1215 {
1216 char *e = NULL;
1217 char *space = strdup(file);
1218
1219 switch_assert(space);
1220 file = space;
1221
1222 *file_portion = NULL;
1223 *params_portion = NULL;
1224
1225 while (*file == '{') {
1226 e = switch_find_end_paren(file, '{', '}');
1227 file = e + 1;
1228 while(*file == ' ') file++;
1229 }
1230
1231
1232 if (e) {
1233 *file_portion = strdup((char *)file);
1234 *++e = '\0';
1235 *params_portion = (char *)space;
1236 } else {
1237 *file_portion = (char *)space;
1238 }
1239
1240 return;
1241 }
1242
switch_is_file_path(const char * file)1243 static inline switch_bool_t switch_is_file_path(const char *file)
1244 {
1245 const char *e;
1246 int r;
1247
1248 if (zstr(file)) {
1249 return SWITCH_FALSE;
1250 }
1251
1252 while(*file == '{') {
1253 if ((e = switch_find_end_paren(file, '{', '}'))) {
1254 file = e + 1;
1255 while(*file == ' ') file++;
1256 }
1257 }
1258
1259 #ifdef WIN32
1260 r = (*file == '\\' || *(file + 1) == ':' || *file == '/' || strstr(file, SWITCH_URL_SEPARATOR));
1261 #else
1262 r = ((*file == '/') || strstr(file, SWITCH_URL_SEPARATOR));
1263 #endif
1264
1265 return r ? SWITCH_TRUE : SWITCH_FALSE;
1266 }
1267
1268
switch_parse_audio_col(switch_audio_col_t col)1269 static inline const char *switch_parse_audio_col(switch_audio_col_t col)
1270 {
1271 const char *field = NULL;
1272
1273 switch (col) {
1274 case SWITCH_AUDIO_COL_STR_TITLE:
1275 field = "title";
1276 break;
1277 case SWITCH_AUDIO_COL_STR_COMMENT:
1278 field = "comment";
1279 break;
1280 case SWITCH_AUDIO_COL_STR_ARTIST:
1281 field = "artist";
1282 break;
1283 case SWITCH_AUDIO_COL_STR_DATE:
1284 field = "date";
1285 break;
1286 case SWITCH_AUDIO_COL_STR_SOFTWARE:
1287 field = "software";
1288 break;
1289 case SWITCH_AUDIO_COL_STR_COPYRIGHT:
1290 field = "copyright";
1291 break;
1292 default:
1293 break;
1294 }
1295
1296 return field;
1297 }
1298
1299 SWITCH_DECLARE(int) switch_parse_cidr(const char *string, ip_t *ip, ip_t *mask, uint32_t *bitp);
1300 SWITCH_DECLARE(switch_status_t) switch_network_list_create(switch_network_list_t **list, const char *name, switch_bool_t default_type,
1301 switch_memory_pool_t *pool);
1302 SWITCH_DECLARE(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);
1303 #define switch_network_list_add_cidr(_list, _cidr_str, _ok) switch_network_list_add_cidr_token(_list, _cidr_str, _ok, NULL)
1304
1305 SWITCH_DECLARE(char *) switch_network_ipv4_mapped_ipv6_addr(const char* ip_str);
1306 SWITCH_DECLARE(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);
1307
1308 SWITCH_DECLARE(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);
1309 SWITCH_DECLARE(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);
1310
1311 SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_port_token(switch_network_list_t *list, uint32_t ip, int port, const char **token);
1312 SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_port_token(switch_network_list_t *list, ip_t ip, int port, const char **token);
1313 SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_network_list_t *list, uint32_t ip, const char **token);
1314 SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_token(switch_network_list_t *list, ip_t ip, const char **token);
1315 #define switch_network_list_validate_ip(_list, _ip) switch_network_list_validate_ip_token(_list, _ip, NULL);
1316
1317 #define switch_test_subnet(_ip, _net, _mask) (_mask ? ((_net & _mask) == (_ip & _mask)) : _net ? _net == _ip : 1)
1318
1319 SWITCH_DECLARE(int) switch_inet_pton(int af, const char *src, void *dst);
1320
1321 SWITCH_DECLARE(const char *) switch_dow_int2str(int val);
1322 SWITCH_DECLARE(int) switch_dow_str2int(const char *exp);
1323 SWITCH_DECLARE(switch_bool_t) switch_dow_cmp(const char *exp, int val);
1324 SWITCH_DECLARE(int) switch_number_cmp(const char *exp, int val);
1325 SWITCH_DECLARE(int) switch_tod_cmp(const char *exp, int val);
1326
1327 SWITCH_DECLARE(int) switch_fulldate_cmp(const char *exp, switch_time_t *ts);
1328 SWITCH_DECLARE(void) switch_split_date(const char *exp, int *year, int *month, int *day);
1329 SWITCH_DECLARE(void) switch_split_time(const char *exp, int *hour, int *min, int *sec);
1330
1331 /*!
1332 \brief Split a user@domain string as user and domain
1333 \param in the input string
1334 \param user the string to put the user into
1335 \param domain the string to put the domain into
1336 \return 1 if successfull
1337 \note Extended formats protocol:user@domain:port (Example: sip:toto@example.org)
1338 */
1339 SWITCH_DECLARE(int) switch_split_user_domain(char *in, char **user, char **domain);
1340
1341 SWITCH_DECLARE(void *) switch_calloc(size_t nmemb, size_t size);
1342
1343 #ifdef __clang_analyzer__
1344 #define calloc switch_calloc
1345 #endif
1346
1347 /* malloc or DIE macros */
1348 #ifdef NDEBUG
1349 #define switch_malloc(ptr, len) (void)( (!!(ptr = malloc(len))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr )
1350 #define switch_zmalloc(ptr, len) (void)( (!!(ptr = calloc(1, (len)))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr)
1351 #if (_MSC_VER >= 1500) // VC9+
1352 #define switch_strdup(ptr, s) (void)( (!!(ptr = _strdup(s))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr)
1353 #else
1354 #define switch_strdup(ptr, s) (void)( (!!(ptr = strdup(s))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr)
1355 #endif
1356 #else
1357 #if (_MSC_VER >= 1500) // VC9+
1358 #define switch_malloc(ptr, len) (void)(assert(((ptr) = malloc((len)))),ptr);__analysis_assume( ptr )
1359 #define switch_zmalloc(ptr, len) (void)(assert((ptr = calloc(1, (len)))),ptr);__analysis_assume( ptr )
1360 #define switch_strdup(ptr, s) (void)(assert(((ptr) = _strdup(s))),ptr);__analysis_assume( ptr )
1361 #else
1362 #define switch_malloc(ptr, len) (void)(switch_assert(((ptr) = malloc((len)))),ptr)
1363 #define switch_zmalloc(ptr, len) (void)(switch_assert((ptr = calloc(1, (len)))),ptr)
1364 #define switch_strdup(ptr, s) (void)(switch_assert(((ptr) = strdup((s)))),ptr)
1365 #endif
1366 #endif
1367
1368 #define DUMP_EVENT(_e) {char *event_str;switch_event_serialize(_e, &event_str, SWITCH_FALSE);switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "DUMP\n%s\n", event_str);free(event_str);}
1369
1370 #ifndef _MSC_VER
1371 #define switch_inet_ntop inet_ntop
1372 #else
1373 SWITCH_DECLARE(const char *) switch_inet_ntop(int af, void const *src, char *dst, size_t size);
1374 #endif
1375
1376 SWITCH_DECLARE(char *) switch_uuid_str(char *buf, switch_size_t len);
1377 SWITCH_DECLARE(char *) switch_format_number(const char *num);
1378
1379 SWITCH_DECLARE(unsigned int) switch_atoui(const char *nptr);
1380 SWITCH_DECLARE(unsigned long) switch_atoul(const char *nptr);
1381
1382 /**
1383 * Portable version of strerror_r(), work around for the incompatible
1384 * return type of GNU and XSI variants.
1385 * \param[in] errnum Error number
1386 * \param[both] buf Buffer for error message
1387 * \param[in] buflen Size of message buffer
1388 * \return Pointer to message buffer, returning error message or "Unknown error xxx" if none found
1389 */
1390 SWITCH_DECLARE(char *) switch_strerror_r(int errnum, char *buf, switch_size_t buflen);
1391 SWITCH_DECLARE(int) switch_wait_sock(switch_os_socket_t sock, uint32_t ms, switch_poll_t flags);
1392 SWITCH_DECLARE(int) switch_wait_socklist(switch_waitlist_t *waitlist, uint32_t len, uint32_t ms);
1393
1394 typedef struct switch_http_request_s {
1395 const char *method; /* GET POST PUT DELETE OPTIONS PATCH HEAD */
1396 const char *uri;
1397 const char *qs; /* query string*/
1398 const char *host;
1399 switch_port_t port;
1400 const char *from;
1401 const char *user_agent;
1402 const char *referer;
1403 const char *user;
1404 switch_bool_t keepalive;
1405 const char *content_type;
1406 switch_size_t content_length;
1407 switch_size_t bytes_header;
1408 switch_size_t bytes_read;
1409 switch_size_t bytes_buffered;
1410 switch_event_t *headers;
1411 void *user_data; /* private user data */
1412
1413 /* private members used by the parser internally */
1414 char *_buffer;
1415 switch_bool_t _destroy_headers;
1416 } switch_http_request_t;
1417
1418 /**
1419 * parse http headers in a buffer
1420 * return status of success or not
1421 * \param[in] buffer the buffer start from the very begining of the http request, e.g. 'GET '
1422 * \param[in] datalen the buffer length
1423 * \param[out] the http request pointer or null, need destroy later if got non-NULL pointer
1424 * \return SWITCH_STATUS_SUCCESS | SWITCH_STATUS_FALSE
1425 */
1426 SWITCH_DECLARE(switch_status_t) switch_http_parse_header(char *buffer, uint32_t datalen, switch_http_request_t *request);
1427 SWITCH_DECLARE(void) switch_http_free_request(switch_http_request_t *request);
1428 SWITCH_DECLARE(void) switch_http_dump_request(switch_http_request_t *request);
1429 /**
1430 * parse http query string
1431 * \param[in] request the http request object
1432 * \param[in] qs the query string buffer
1433 *
1434 * qs buffer will be modified, so be sure to dup the qs before passing into this function if you want to keep the original string untouched
1435 * if qs is NULL, the it will parse request->qs, request->qs will be duplicated before parse to avoid being modified
1436 */
1437
1438 SWITCH_DECLARE(void) switch_http_parse_qs(switch_http_request_t *request, char *qs);
1439
1440 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_free(switch_frame_buffer_t *fb, switch_frame_t **frameP);
1441 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_dup(switch_frame_buffer_t *fb, switch_frame_t *orig, switch_frame_t **clone);
1442 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_destroy(switch_frame_buffer_t **fbP);
1443 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_create(switch_frame_buffer_t **fbP, switch_size_t qlen);
1444 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_push(switch_frame_buffer_t *fb, void *ptr);
1445 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_trypush(switch_frame_buffer_t *fb, void *ptr);
1446 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_pop(switch_frame_buffer_t *fb, void **ptr);
1447 SWITCH_DECLARE(switch_status_t) switch_frame_buffer_trypop(switch_frame_buffer_t *fb, void **ptr);
1448 SWITCH_DECLARE(int) switch_frame_buffer_size(switch_frame_buffer_t *fb);
1449
1450 typedef struct {
1451 int64_t userms;
1452 int64_t kernelms;
1453 } switch_cputime;
1454 /**
1455 / Return used CPU time in this process for user and kernel code
1456 **/
1457 SWITCH_DECLARE(void) switch_getcputime(switch_cputime *t);
1458
1459 SWITCH_DECLARE(char *)switch_html_strip(const char *str);
1460
1461 SWITCH_DECLARE(unsigned long) switch_getpid(void);
1462
1463 SWITCH_END_EXTERN_C
1464 #endif
1465 /* For Emacs:
1466 * Local Variables:
1467 * mode:c
1468 * indent-tabs-mode:t
1469 * tab-width:4
1470 * c-basic-offset:4
1471 * End:
1472 * For VIM:
1473 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
1474 */
1475