Compare commits

...

6 Commits

Author SHA1 Message Date
George Joseph
4b95a5eda3 xmldoc.c: Fix rendering of CLI output.
If you do a `core show application Dial`, you'll see it's kind of a mess.
Indents are wrong is some places, examples are printed in black which makes
them invisible on most terminals, and the lack of line breaks in some cases
makes it hard to follow.

* Fixed the rendering of examples so they are indented properly and changed
the color so they can be seen.
* There is now a line break before each option.
* Options are now printed on their own line with all option content indented
below them.

Example from Dial before fixes:
```
    Example: Dial 555-1212 on first available channel in group 1, searching
    from highest to lowest

    Example: Ringing FXS channel 4 with ring cadence 2

    Example: Dial 555-1212 on channel 3 and require answer confirmation

...

    O([mode]):
        mode - With <mode> either not specified or set to '1', the originator
        hanging up will cause the phone to ring back immediately.
 - With <mode> set to '2', when the operator flashes the trunk, it will ring
 their phone back.
Enables *operator services* mode.  This option only works when bridging a DAHDI
channel to another DAHDI channel only. If specified on non-DAHDI interfaces, it
will be ignored. When the destination answers (presumably an operator services
station), the originator no longer has control of their line. They may hang up,
but the switch will not release their line until the destination party (the
operator) hangs up.

    p: This option enables screening mode. This is basically Privacy mode
    without memory.
```

After:
```
    Example: Dial 555-1212 on first available channel in group 1, searching
    from highest to lowest

     same => n,Dial(DAHDI/g1/5551212)

    Example: Ringing FXS channel 4 with ring cadence 2

     same => n,Dial(DAHDI/4r2)

    Example: Dial 555-1212 on channel 3 and require answer confirmation

     same => n,Dial(DAHDI/3c/5551212)

...

    O([mode]):
        mode - With <mode> either not specified or set to '1', the originator
        hanging up will cause the phone to ring back immediately.
        With <mode> set to '2', when the operator flashes the trunk, it will
        ring their phone back.
        Enables *operator services* mode.  This option only works when bridging
        a DAHDI channel to another DAHDI channel only. If specified on
        non-DAHDI interfaces, it will be ignored. When the destination answers
        (presumably an operator services station), the originator no longer has
        control of their line. They may hang up, but the switch will not
        release their line until the destination party (the operator) hangs up.

    p:
        This option enables screening mode. This is basically Privacy mode
        without memory.
```

There are still things we can do to make this more readable but this is a
start.
2025-08-15 16:48:21 +00:00
Naveen Albert
b174816484 func_frame_drop: Add debug messages for dropped frames.
Add debug messages in scenarios where frames that are usually processed
are dropped or skipped.

Resolves: #1371
2025-08-15 16:47:56 +00:00
Naveen Albert
77df0ebcad test_res_prometheus: Fix compilation failure on Debian 13.
curl_easy_setopt expects long types, so be explicit.

Resolves: #1369
2025-08-15 16:10:55 +00:00
Naveen Albert
d08c3ad99f func_frame_drop: Handle allocation failure properly.
Handle allocation failure and simplify the allocation using asprintf.

Resolves: #1366
2025-08-15 16:09:27 +00:00
Alexey Khabulyak
5003d882e7 pbx_lua.c: segfault when pass null data to term_color function
This can be reproduced under certain curcomstences.
For example: call app.playback from lua with invalid data: app.playback({}).
pbx_lua.c will try to get data for this playback using lua_tostring function.
This function returs NULL for everything but strings and numbers.
Then, it calls term_color with NULL data.
term_color function can call(if we don't use vt100 compat term)
ast_copy_string with NULL inbuf which cause segfault. bt example:
ast_copy_string (size=8192, src=0x0, dst=0x7fe44b4be8b0)
at /usr/src/asterisk/asterisk-20.11.0/include/asterisk/strings.h:412

Resolves: https://github.com/asterisk/asterisk/issues/1363
2025-08-15 16:00:25 +00:00
Naveen Albert
d772f61231 bridge.c: Obey BRIDGE_NOANSWER variable to skip answering channel.
If the BRIDGE_NOANSWER variable is set on a channel, it is not supposed
to answer when another channel bridges to it using Bridge(), and this is
checked when ast_bridge_call* is called. However, another path exists
(bridge_exec -> ast_bridge_add_channel) where this variable was not
checked and channels would be answered. We now check the variable there.

Resolves: #401
Resolves: #1364
2025-08-15 15:59:31 +00:00
7 changed files with 46 additions and 21 deletions

View File

@@ -173,6 +173,7 @@ static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_fram
{
int i;
int drop_frame = 0;
char buf[64];
struct frame_drop_data *framedata = data;
if (!frame) {
return frame;
@@ -188,6 +189,7 @@ static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_fram
if (frame->subclass.integer == controlframetype2str[i].type) {
if (framedata->controlvalues[i]) {
drop_frame = 1;
ast_frame_subclass2str(frame, buf, sizeof(buf), NULL, 0);
}
break;
}
@@ -197,6 +199,7 @@ static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_fram
if (frame->frametype == frametype2str[i].type) {
if (framedata->values[i]) {
drop_frame = 1;
ast_frame_type2str(frame->frametype, buf, sizeof(buf));
}
break;
}
@@ -206,6 +209,7 @@ static struct ast_frame *hook_event_cb(struct ast_channel *chan, struct ast_fram
if (drop_frame) {
ast_frfree(frame);
frame = &ast_null_frame;
ast_debug(2, "Dropping %s frame\n", buf);
}
return frame;
}
@@ -234,8 +238,10 @@ static int frame_drop_helper(struct ast_channel *chan, const char *cmd, char *da
framedata->list_type = TX;
}
buffer = ast_malloc(sizeof(value) + 3); /* leading and trailing comma and null terminator */
snprintf(buffer, sizeof(value) + 2, ",%s,", value);
if (ast_asprintf(&buffer, ",%s,", value) < 0) {
ast_free(framedata);
return -1;
}
for (i = 0; i < ARRAY_LEN(frametype2str); i++) {
if (strcasestr(buffer, frametype2str[i].str)) {
framedata->values[i] = 1;

View File

@@ -2578,6 +2578,8 @@ int ast_bridge_add_channel(struct ast_bridge *bridge, struct ast_channel *chan,
ast_bridge_unlock(chan_bridge);
ast_bridge_unlock(bridge);
} else {
int noanswer;
const char *value;
/* Slightly less easy case. We need to yank channel A from
* where he currently is and impart him into our bridge.
*/
@@ -2587,9 +2589,17 @@ int ast_bridge_add_channel(struct ast_bridge *bridge, struct ast_channel *chan,
ast_bridge_features_destroy(features);
return -1;
}
if (ast_channel_state(yanked_chan) != AST_STATE_UP) {
ast_channel_lock(chan);
value = pbx_builtin_getvar_helper(chan, "BRIDGE_NOANSWER");
noanswer = !ast_strlen_zero(value) ? 1 : 0;
ast_channel_unlock(chan);
if (noanswer) {
ast_debug(3, "Skipping answer on bridge target channel %s\n", ast_channel_name(chan));
} else if (ast_channel_state(yanked_chan) != AST_STATE_UP) {
ast_answer(yanked_chan);
}
ast_channel_ref(yanked_chan);
if (ast_bridge_impart(bridge, yanked_chan, NULL, features,
AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {

View File

@@ -2647,8 +2647,9 @@ int ast_raw_answer_with_stream_topology(struct ast_channel *chan, struct ast_str
ast_channel_unlock(chan);
break;
case AST_STATE_UP:
break;
/* Fall through */
default:
ast_debug(2, "Skipping answer, since channel state on %s is %s\n", ast_channel_name(chan), ast_state2str(ast_channel_state(chan)));
break;
}

View File

@@ -172,6 +172,9 @@
<para>Additionally, to prevent a bridged channel (the target of the Bridge application)
from answering, the <literal>BRIDGE_NOANSWER</literal> variable can be set to inhibit
answering.</para>
<warning><para>Do not set the <literal>BRIDGE_NOANSWER</literal> variable globally,
as it will break normal bridging behavior in many cases. Only use this variable on
a per-channel basis when you really know what you are doing!</para></warning>
</option>
<option name="S(x)">
<para>Hang up the call after <replaceable>x</replaceable> seconds *after* the called party has answered the call.</para>

View File

@@ -94,7 +94,7 @@ static const struct strcolorized_tags {
{ "", "", COLOR_YELLOW, "<note>", "</note>" },
{ "", "", COLOR_RED, "<warning>", "</warning>" },
{ "", "", COLOR_WHITE, "<example>", "</example>" },
{ "", "", COLOR_GRAY, "<exampletext>", "</exampletext>"},
{ "", "", COLOR_WHITE, "<exampletext>", "</exampletext>"},
};
static const struct strspecial_tags {
@@ -1359,7 +1359,8 @@ static int xmldoc_parse_para(struct ast_xml_node *node, const char *tabs, const
* \retval 0 if no example node is parsed.
* \retval 1 if an example node is parsed.
*/
static int xmldoc_parse_example(struct ast_xml_node *fixnode, struct ast_str **buffer)
static int xmldoc_parse_example(struct ast_xml_node *fixnode, const char *tabs,
struct ast_str **buffer)
{
struct ast_xml_node *node = fixnode;
const char *tmptext;
@@ -1387,9 +1388,11 @@ static int xmldoc_parse_example(struct ast_xml_node *fixnode, struct ast_str **b
for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
tmptext = ast_xml_get_text(node);
if (tmptext) {
xmldoc_string_cleanup(tmptext, &stripped_text, 0, 1);
const char *skipped = ast_skip_blanks(tmptext);
xmldoc_string_cleanup(skipped, &stripped_text, 0, 1);
if (stripped_text) {
ast_str_append(buffer, 0, "<exampletext>%s</exampletext>\n", ast_str_buffer(stripped_text));
ast_str_append(buffer, 0, "\n %s<exampletext>%s</exampletext>\n",
tabs, ast_str_buffer(stripped_text));
ast_xml_free_text(tmptext);
ast_free(stripped_text);
}
@@ -1434,7 +1437,7 @@ static int xmldoc_parse_specialtags(struct ast_xml_node *fixnode, const char *ta
ast_str_append(buffer, 0, "%s%s", tabs, special_tags[i].init);
}
if (xmldoc_parse_example(node, buffer)) {
if (xmldoc_parse_example(node, tabs, buffer)) {
ret = 1;
break;
}
@@ -1495,7 +1498,9 @@ static int xmldoc_parse_argument(struct ast_xml_node *fixnode, int insideparamet
}
for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
if (xmldoc_parse_common_elements(node, (insideparameter ? paramtabs : (!count ? " - " : tabs)), "\n", buffer) == 2) {
int rc = 0;
rc = xmldoc_parse_common_elements(node, (insideparameter ? paramtabs : (!count ? " - " : tabs)), "\n", buffer);
if (rc >= 1) {
count++;
ret = 1;
}
@@ -1902,19 +1907,19 @@ static int xmldoc_parse_option(struct ast_xml_node *fixnode, const char *tabs, s
return ret;
}
for (node = ast_xml_node_get_children(fixnode); node; node = ast_xml_node_get_next(node)) {
/* if this is the first data appended to buffer, print a \n */
if (!ret && ast_xml_node_get_children(node)) {
/* print \n */
ast_str_append(buffer, 0, "\n");
}
if (!strcasecmp(ast_xml_node_get_name(node), "argument")) {
/* if this is the first data appended to buffer, print a \n*/
if (!ret && ast_xml_node_get_children(node)) {
/* print \n */
ast_str_append(buffer, 0, "\n");
}
if (xmldoc_parse_argument(node, 0, NULL, optiontabs, buffer)) {
ret = 1;
}
continue;
}
if (xmldoc_parse_common_elements(node, (ret ? tabs : ""), "\n", buffer)) {
if (xmldoc_parse_common_elements(node, optiontabs, "\n", buffer)) {
ret = 1;
}
@@ -2012,7 +2017,7 @@ static void xmldoc_parse_parameter(struct ast_xml_node *fixnode, const char *tab
}
if (!hasarguments && xmldoc_has_nodes(node)) {
ast_str_append(buffer, 0, "%s\n", paramname);
ast_str_append(buffer, 0, "\n%s\n", paramname);
ast_xml_free_attr(paramname);
printed = 1;
}

View File

@@ -222,7 +222,7 @@ static int lua_pbx_exec(lua_State *L)
exten, context, priority,
term_color(tmp, app_name, COLOR_BRCYAN, 0, sizeof(tmp)),
term_color(tmp2, ast_channel_name(chan), COLOR_BRMAGENTA, 0, sizeof(tmp2)),
term_color(tmp3, data, COLOR_BRMAGENTA, 0, sizeof(tmp3)));
term_color(tmp3, data ? data : "", COLOR_BRMAGENTA, 0, sizeof(tmp3)));
lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
autoservice = lua_toboolean(L, -1);

View File

@@ -83,10 +83,10 @@ static CURL *get_curl_instance(void)
return NULL;
}
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 180);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 180L);
curl_easy_setopt(curl, CURLOPT_USERAGENT, AST_CURL_USER_AGENT);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_URL, server_uri);
return curl;