In Asterisk 15 and 17 early media handling treats the call as answered and AMI state messages also report an “up” (answered) state. This does not reflect the actual state of the call.
We have recently gone from using Asterisk 11 to Asterisk 15 and 17. Our usage of Asterisk involves programmatically placing a call on behalf of a user in a conference. We do this using the AMI originate command. We want the user to hear the provider’s call progress audio, so we originate the call with the early media flag set true.
Our applications also monitors the connection state of the call via AMI events. We note that when a progress indication (signifying early media) is received on the trunk (usually SIP 183 response) that the call is regarded ANSWERED in asterisk. This does not reflect the true state of the call. We feel that the discrepancy between the actual state of the call and presented state of the call is radical enough to be considered as a bug. This may be considered serious, as a call over a SIP trunk might incur charges if answered. The current functionality inhibits the ability to determine if the call is incurring a charge by the provider. Any reports generated from data relating to such calls may be grossly misrepresentative.
I note substantial changes between Asterisk 11 and 15 with respect to “dial” functionality
In appears that the current handling of calls receiving early media as being answered is explicitly deliberate in the code.
pbx.c
static void pbx_outgoing_state_callback(struct ast_dial *dial)
{
struct ast_channel *channel;
if (ast_dial_state(dial) != AST_DIAL_RESULT_PROGRESS) {
return;
}
if (!(channel = ast_dial_get_channel(dial, 0))) {
return;
}
ast_verb(4, "Treating progress as answer on '%s' due to early media option\n",
ast_channel_name(channel));
ast_queue_control(channel, AST_CONTROL_ANSWER);
}
static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap,
…
if (early_media) {
ast_dial_set_state_callback(outgoing->dial, pbx_outgoing_state_callback);
}
…
We hope the Asterisk developers recognise this issue and make this behaviour configurable.
We have found that normal behaviour is restored if the “dial->state = AST_DIAL_RESULT_ANSWERED” is delayed. locating this line as shown below will connect the voice path and complete any originate
without indicating the call state is up/answered. Should the call be answered at the remote end, the state “up” is then reported appropriately at that point.
dial.c
static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_channel chan)
…
/ Attempt to read in a frame */
if (!(fr = ast_read(who))) {
/* If this is the caller then we switch state to hangup and stop */
if (chan && IS_CALLER(chan, who)) {
set_state(dial, AST_DIAL_RESULT_HANGUP);
break;
}
ast_channel_publish_dial(chan, who, channel->device, ast_hangup_cause_to_dial_status(ast_channel_hangupcause(who)));
ast_hangup(who);
channel->owner = NULL;
continue;
}
/* Process the frame */
handle_frame(dial, channel, fr, chan);
/* Free the received frame and start all over */
ast_frfree(fr);
}
// ***************** add 2 lines ****************
if (dial->state == AST_DIAL_RESULT_PROGRESS && dial->state_callback )
dial->state = AST_DIAL_RESULT_ANSWERED;
/* Do post-processing from loop */
if (dial->state == AST_DIAL_RESULT_ANSWERED) {
/* Hangup everything except that which answered */
AST_LIST_LOCK(&dial->channels);
AST_LIST_TRAVERSE(&dial->channels, channel, list) {
if (!channel->owner || channel->owner == who)