37#if defined(HAVE_SYSINFO)
38#include <sys/sysinfo.h>
41#include <sys/loadavg.h>
214#define EXT_DATA_SIZE 256
216#define EXT_DATA_SIZE 8192
219#define SWITCH_DATA_LENGTH 256
222#define VAR_SOFTTRAN 2
223#define VAR_HARDTRAN 3
358#define HINTDEVICE_DATA_LENGTH 16
363#define HASH_EXTENHINT_SIZE 17
365#define HASH_EXTENHINT_SIZE 563
413 key =
ext->hintdevice;
432 const char *right_key = arg;
440 cmp = strcasecmp(left->
hintdevice, right_key);
447 cmp = strncmp(left->
hintdevice, right_key, strlen(right_key));
485 const char *right_key = arg;
493 cmp = strcasecmp(left->
context, right_key);
500 cmp = strncmp(left->
context, right_key, strlen(right_key));
517 if (!strcasecmp(candidate->
hintdevice, device)
518 && candidate->
hint == hint) {
565 if (!
hint || !devicelist) {
576 while ((cur =
strsep(&parse,
"&,"))) {
579 devicelength = strlen(cur);
590 "allocating a hintdevice structure");
604 ao2_t_ref(device, -1,
"hintdevice is linked so we can unref");
635static int matchcid(
const char *cidpattern,
const char *callerid);
640 struct match_char *tree,
int length,
int spec,
const char *callerid,
660 const char *application,
void *
data,
void (*
datad)(
void *),
666static unsigned int ext_strncpy(
char *dst,
const char *src,
size_t dst_size,
int nofluff);
681 const unsigned char *ac =
a;
682 const unsigned char *
bc =
b;
695 return strcmp(ac->
name,
bc->name);
702 int x = strcmp(ac->
exten,
bc->exten);
824void check_contexts_trouble(
void);
826void check_contexts_trouble(
void)
832int check_contexts(
char *,
int);
834int check_contexts(
char *
file,
int line )
860 check_contexts_trouble();
868 check_contexts_trouble();
883 char dummy_name[1024];
884 ex.exten = dummy_name;
892 "the exten %s (CID match: %s) but it is not in its root_table\n",
896 "the exten %s but it is not in its root_table\n",
899 check_contexts_trouble();
920 check_contexts_trouble();
932 for(e1 = c2->
root; e1; e1 = e1->
next) {
934 for(e2=e1;e2;e2=e2->
peer) {
938 check_contexts_trouble();
943 check_contexts_trouble();
948 check_contexts_trouble();
953 check_contexts_trouble();
960 check_contexts_trouble();
972 for(e3=e1;e3;e3=e3->
peer) {
980 check_contexts_trouble();
1080#ifdef NEED_DEBUG_HERE
1094 snprintf(extenstr,
sizeof(extenstr),
"(%p)",
node->exten);
1096 if (strlen(
node->x) > 1) {
1098 node->deleted?
'D':
'-',
node->specificity,
node->exten?
"EXTEN:":
"",
1099 node->exten ?
node->exten->exten :
"", extenstr);
1102 node->deleted?
'D':
'-',
node->specificity,
node->exten?
"EXTEN:":
"",
1103 node->exten ?
node->exten->exten :
"", extenstr);
1108 if (
node->next_char)
1124 snprintf(extenstr,
sizeof(extenstr),
"(%p)",
node->exten);
1127 if (strlen(
node->x) > 1) {
1129 node->deleted ?
'D' :
'-',
node->specificity,
node->exten?
"EXTEN:" :
"",
1130 node->exten ?
node->exten->name :
"", extenstr);
1133 node->deleted ?
'D' :
'-',
node->specificity,
node->exten?
"EXTEN:" :
"",
1134 node->exten ?
node->exten->name :
"", extenstr);
1139 if (
node->next_char)
1153#ifdef NEED_DEBUG_HERE
1156 return node2->
exten;
1159#ifdef NEED_DEBUG_HERE
1183 m3 =
node->next_char;
1193 for (m4 = m3; m4; m4 = m4->
alt_char) {
1227 while (*
str ==
'-') {
1233#define MORE(s) (*candidate_exten_advance(s))
1234#define ADVANCE(s) candidate_exten_advance(s)
1242 ast_log(
LOG_NOTICE,
"new_find_extension called with %s on (sub)tree %s action=%s\n",
str, tree->
x, action2str(action));
1244 ast_log(
LOG_NOTICE,
"new_find_extension called with %s on (sub)tree NULL action=%s\n",
str, action2str(action));
1246 for (p = tree; p; p = p->
alt_char) {
1248 if (p->
x[0] ==
'N') {
1249 if (p->
x[1] == 0 && *
str >=
'2' && *
str <=
'9' ) {
1250#define NEW_MATCHER_CHK_MATCH \
1251 if (p->exten && !MORE(str)) { \
1252 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { \
1253 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \
1254 if (!p->deleted) { \
1255 if (action == E_FINDLABEL) { \
1256 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \
1257 ast_debug(4, "Found label in preferred extension\n"); \
1261 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->name); \
1268#define NEW_MATCHER_RECURSE \
1269 if (p->next_char && (MORE(str) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \
1270 || p->next_char->x[0] == '!')) { \
1271 if (MORE(str) || p->next_char->x[0] == '!') { \
1272 new_find_extension(ADVANCE(str), score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
1273 if (score->exten) { \
1274 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->name); \
1278 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
1279 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \
1280 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->name : \
1285 } else if ((p->next_char || action == E_CANMATCH) && !MORE(str)) { \
1286 score->canmatch = 1; \
1287 score->canmatch_exten = get_canmatch_exten(p); \
1288 if (action == E_CANMATCH || action == E_MATCHMORE) { \
1289 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \
1297 }
else if (p->
x[0] ==
'Z') {
1298 if (p->
x[1] == 0 && *
str >=
'1' && *
str <=
'9' ) {
1302 }
else if (p->
x[0] ==
'X') {
1303 if (p->
x[1] == 0 && *
str >=
'0' && *
str <=
'9' ) {
1307 }
else if (p->
x[0] ==
'.' && p->
x[1] == 0) {
1310 const char *str2 =
str;
1311 while (*str2 && *str2 !=
'/') {
1315 if (p->
exten && *str2 !=
'/') {
1318 ast_debug(4,
"return because scoreboard has a match with '/'--- %s\n",
1326 ast_debug(4,
"return because scoreboard has exact match OR "
1327 "CANMATCH/MATCHMORE & canmatch set--- %s\n",
1332 }
else if (p->
x[0] ==
'!' && p->
x[1] == 0) {
1335 const char *str2 =
str;
1336 while (*str2 && *str2 !=
'/') {
1340 if (p->
exten && *str2 !=
'/') {
1343 ast_debug(4,
"return because scoreboard has a '!' match--- %s\n",
1351 ast_debug(4,
"return because scoreboard has exact match OR "
1352 "CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n",
1357 }
else if (p->
x[0] ==
'/' && p->
x[1] == 0) {
1359 if (p->
next_char && callerid && *callerid) {
1362 ast_debug(4,
"return because scoreboard has exact match OR "
1363 "CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n",
1368 }
else if (strchr(p->
x, *
str)) {
1369 ast_debug(4,
"Nothing strange about this match\n");
1373 }
else if (strchr(p->
x, *
str)) {
1374 ast_debug(4,
"Nothing strange about this match\n");
1379 ast_debug(4,
"return at end of func\n");
1429 if (!(*parent_ptr)) {
1434 if ((*parent_ptr)->specificity >
node->specificity) {
1436 node->alt_char = (*parent_ptr);
1441 lcurr = *parent_ptr;
1444 node->alt_char = curr;
1468 if (!(m =
ast_calloc(1,
sizeof(*m) + strlen(pattern->
buf)))) {
1475 strcpy(m->
x, pattern->
buf);
1520#define INC_DST_OVERFLOW_CHECK \
1522 if (dst - node->buf < sizeof(node->buf) - 1) { \
1530 node->buf[0] =
'\0';
1532 if (*src ==
'[' && pattern) {
1533 char *dst =
node->buf;
1534 const char *src_next;
1544 if (*src ==
'[' || *src ==
'\\' || *src ==
'-' || *src ==
']') {
1548 }
else if (*src ==
'-') {
1549 unsigned char first;
1553 first = *(src_next - 1);
1577 }
else if (*src ==
'\0') {
1579 "A matching ']' was not found for '[' in exten pattern '%s'\n",
1582 }
else if (*src ==
']') {
1595 "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n",
1597 node->buf[0] =
'\0';
1602 length = strlen(
node->buf);
1606 node->buf[0] =
'\0';
1613 src_next =
node->buf;
1614 while (*src_next++) {
1615 if (*dst != *src_next) {
1620 length = strlen(
node->buf);
1622 node->specif = length | (
unsigned char)
node->buf[0];
1624 }
else if (*src ==
'-') {
1634 node->buf[0] = *++src;
1635 if (!
node->buf[0]) {
1639 node->buf[0] = *src;
1642 if (
node->buf[0] ==
'n') {
1644 }
else if (
node->buf[0] ==
'x') {
1646 }
else if (
node->buf[0] ==
'z') {
1651 node->buf[1] =
'\0';
1659#undef INC_DST_OVERFLOW_CHECK
1662#define MAX_EXTENBUF_SIZE 512
1674 volatile size_t required_space = strlen(e1->
exten) + 1;
1678 required_space += (strlen(e1->
cidmatch) + 2 );
1681 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
1689 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
1697 ast_debug(1,
"Adding exten %s to tree\n", extenbuf);
1710 for (; pat_node[idx_cur].
buf[0]; idx_cur = idx_next) {
1711 idx_next = (idx_cur + 1) %
ARRAY_LEN(pat_node);
1718 if (!pat_node[idx_next].
buf[0]) {
1752 if (!pat_node[idx_next].
buf[0]) {
1753 if (m2 && m2->
exten) {
1775 int biggest_bucket, resizes, numobjs, numbucks;
1777 ast_debug(1,
"Creating Extension Trie for context %s(%p)\n", con->
name, con);
1779 ast_debug(1,
"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
1780 numobjs, numbucks, biggest_bucket, resizes);
1787 ast_log(
LOG_ERROR,
"Attempt to create extension with no extension name.\n");
1805 pattern_tree->
exten = 0;
1824 while (*
str ==
'-') {
1853 while (*left ==
'-') {
1856 while (*right ==
'-') {
1869 cmp = *left - *right;
1896 while (*left ==
'-') {
1899 while (*right ==
'-') {
1903 cmp = *left - *right;
2003 return 0x0800 |
'2';
2010 return 0x0A00 |
'0';
2017 return 0x0900 |
'1';
2037 end = strchr(*p,
']');
2046 for (; *p <
end; ++*p) {
2051 if (*p + 2 <
end && (*p)[1] ==
'-') {
2060 for (; c1 <= c2; ++c1) {
2069 if (!(bitwise[c1 /
BITS_PER] & mask)) {
2078 return count | cmin;
2099 unsigned char left_bitwise[32] = { 0, };
2100 unsigned char right_bitwise[32] = { 0, };
2104 cmp = left_pos - right_pos;
2113 cmp = memcmp(right_bitwise, left_bitwise,
ARRAY_LEN(left_bitwise));
2140static int ext_cmp(
const char *left,
const char *right)
2143 if (left[0] !=
'_') {
2144 if (right[0] ==
'_') {
2150 if (right[0] !=
'_') {
2166 if (*
exten !=
'_') {
2169 if (*
exten ==
'-') {
2180 if (*
exten ==
'-') {
2182 }
else if (*
exten ==
'[') {
2227#ifdef NEED_DEBUG_HERE
2231 if (pattern[0] !=
'_') {
2236#ifdef NEED_DEBUG_HERE
2243#ifdef NEED_DEBUG_HERE
2249#ifdef NEED_DEBUG_HERE
2250 ast_log(
LOG_NOTICE,
"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
2254#ifdef NEED_DEBUG_HERE
2270#ifdef NEED_DEBUG_HERE
2274#ifdef NEED_DEBUG_HERE
2290 while (*
data ==
'-') {
2293 while (*pattern ==
'-') {
2296 if (!*
data || !*pattern || *pattern ==
'/') {
2303 end = strchr(pattern,
']');
2308 if (pattern ==
end) {
2313 for (; pattern <
end; ++pattern) {
2314 if (pattern+2 <
end && pattern[1] ==
'-') {
2315 if (*
data >= pattern[0] && *
data <= pattern[2])
2321 }
else if (*
data == pattern[0])
2324 if (pattern >=
end) {
2325#ifdef NEED_DEBUG_HERE
2334 if (*data < '2' || *data >
'9') {
2335#ifdef NEED_DEBUG_HERE
2343 if (*data < '0' || *data >
'9') {
2344#ifdef NEED_DEBUG_HERE
2352 if (*data < '1' || *data >
'9') {
2353#ifdef NEED_DEBUG_HERE
2360#ifdef NEED_DEBUG_HERE
2365#ifdef NEED_DEBUG_HERE
2370 if (*
data != *pattern) {
2371#ifdef NEED_DEBUG_HERE
2382#ifdef NEED_DEBUG_HERE
2392 if (*pattern ==
'\0' || *pattern ==
'/') {
2393#ifdef NEED_DEBUG_HERE
2397 }
else if (*pattern ==
'!') {
2398#ifdef NEED_DEBUG_HERE
2403#ifdef NEED_DEBUG_HERE
2406 return (mode ==
E_MATCH) ? 0 : 1;
2417 static int prof_id = -2;
2418 if (prof_id == -2) {
2455 if (!strcasecmp(
name,
tmp->name)) {
2464#define STATUS_NO_CONTEXT 1
2465#define STATUS_NO_EXTENSION 2
2466#define STATUS_NO_PRIORITY 3
2467#define STATUS_NO_LABEL 4
2468#define STATUS_SUCCESS 5
2470static int matchcid(
const char *cidpattern,
const char *callerid)
2495 pattern.
label = label;
2497#ifdef NEED_DEBUG_HERE
2513 for (x = 0; x < q->
stacklen; x++) {
2536 if (!
tmp->pattern_tree &&
tmp->root_table) {
2540 log_match_char_tree(
tmp->pattern_tree,
" ");
2545 log_match_char_tree(
tmp->pattern_tree,
":: ");
2564 if (osw && strchr(osw,
'$')) {
2609 eroot = score.
exten;
2615#ifdef NEED_DEBUG_HERE
2623#ifdef NEED_DEBUG_HERE
2633#ifdef NEED_DEBUG_HERE
2638#ifdef NEED_DEBUG_HERE
2643#ifdef NEED_DEBUG_HERE
2650#ifdef NEED_DEBUG_HERE
2671#ifdef NEED_DEBUG_HERE
2685 if (!
match || (eroot->matchcid && !
matchcid(eroot->cidmatch, callerid)))
2771#ifdef NEED_DEBUG_HERE
2791 .
type =
"EXCEPTION",
2819 ds->
data = exception;
2822 exception = ds->
data;
2836 if (!ds || !ds->
data)
2838 exception = ds->
data;
2839 if (!strcasecmp(data,
"REASON"))
2841 else if (!strcasecmp(data,
"CONTEXT"))
2843 else if (!strncasecmp(data,
"EXTEN", 5))
2845 else if (!strcasecmp(data,
"PRIORITY"))
2853 .
name =
"EXCEPTION",
2877 const char *label,
const char *callerid,
enum ext_match_t action,
int *found,
int combined_find_spawn)
2881 char *substitute =
NULL;
2899 if (matching_action) {
2917 if ((!(
tmp = strchr(e->
data,
'$'))) || (!strstr(
tmp,
"${") && !strstr(
tmp,
"$["))) {
2953 if (matching_action) {
2967 if (!matching_action && !combined_find_spawn)
2971 if (!matching_action && !combined_find_spawn)
2975 if (!matching_action && !combined_find_spawn)
2979 if (
context && !combined_find_spawn)
2986 return (matching_action) ? 0 : -1;
3042 if ((
tmp = strrchr(
copy,
','))) {
3061 if ((
tmp = strrchr(
copy,
','))) {
3091 while ((cur =
strsep(&rest,
"&"))) {
3095 if (device_state_info) {
3117 if (!e || !hint_app) {
3150 if (e->
exten[0] ==
'_') {
3182 if (device_state_info) {
3192 if (device_state_info) {
3203 char *presence_provider;
3206 if (!e || !hint_app) {
3234 if (e->
exten[0] ==
'_') {
3272 info.presence_subtype =
"";
3277 info.presence_message =
"";
3310 struct timeval chantime = {0, };
3312 switch (
info->device_state) {
3349 info->causing_channel = chan;
3353 if (!
info->causing_channel) {
3356 info->causing_channel = chan;
3361 info->causing_channel = chan;
3377 int first_extended_cb_call = 1;
3444 if (state_cb->
extended && first_extended_cb_call) {
3446 first_extended_cb_call = 0;
3449 if (state_cb->
extended || !same_state) {
3558 char *presence_subtype =
NULL;
3559 char *presence_message =
NULL;
3563 hint->
exten, &presence_subtype, &presence_message);
3567 .subtype = presence_subtype,
3568 .message = presence_message
3593 char *virtual_device;
3630 if (dev_state->
eid) {
3655 "find devices in container");
3674 virtual_device = strchr(
type,
':');
3675 device_name = strchr(
type,
'/');
3676 if (virtual_device && (!device_name || (virtual_device < device_name))) {
3677 device_name = virtual_device;
3685 *device_name++ =
'\0';
3773 if (e->
exten[0] ==
'_') {
3780 if (!e || e->
exten[0] ==
'_') {
3802 }
while (
id == -1 ||
id == 0);
3924 if (!hint_remove_message_type()) {
3983 char *subtype =
NULL;
4007 hint_new->
exten = e;
4008 if (strstr(e->
app,
"${") && e->
exten[0] ==
'_') {
4030 ast_debug(2,
"HINTS: Not re-adding existing hint %s: %s\n",
4036 ast_debug(2,
"HINTS: Adding hint %s: %s\n",
4046 if (!(strstr(e->
app,
"${") && e->
exten[0] ==
'_')) {
4074 if (!hint_change_message_type()) {
4245 if (found && spawn_error) {
4247 ast_debug(1,
"Spawn extension (%s,%s,%d) exited non-zero on '%s'\n",
4250 ast_verb(2,
"Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
4296 if (pos < buflen - 1) {
4366 char dst_exten[256];
4373 dst_exten[pos] =
'\0';
4411 ast_debug(1,
"Extension %s, priority %d returned normally even though call was hung up\n",
4418 if (strchr(
"0123456789ABCDEF*#", res)) {
4419 ast_debug(1,
"Oooh, got something to jump out with ('%c')!\n", res);
4421 dst_exten[pos++] =
digit = res;
4422 dst_exten[pos] =
'\0';
4434 pos = strlen(dst_exten);
4498 ast_verb(3,
"Channel '%s' sent to invalid extension: context,exten,priority=%s,%s,%d\n",
4506 ast_log(
LOG_WARNING,
"Channel '%s' sent to invalid extension but no invalid handler: context,exten,priority=%s,%s,%d\n",