Party A channel state differs while dialing via Dial() vs Originate()

Hi everyone,

If I make a regular call via softphone from one local extension to another, while the party B phone is ringing, we have the following channel states: Channel_A: Ring, Channel_B: Ringing.

If I initiate a call via Originate (AMI, console, dialplan app, doesn’t matter), after the first softphone answers and starts to hear the progress tone and while the second phone is ringing, we have the following channel states: Channel_A: Up, Channel_B: Ringing.

I never use the Answer() app in the dialplan, but despite this in the second case the Channel_A state is already Up before two channels are bridged.
As a consequence, I have a CDR problem where the answer time and the billsec field values are set incorrectly (these fields are not null for the unanswered call and the billsec counts from the party A answer, not party B which in case of originate doesn’t make sense).

Is this behaviour intended or maybe this is a bug?
Is it possible to somehow change this originate app behaviour (some walkaround) not to put the first channel in the Up state before the second party answers?

While reading about the possible causes, I also tried to reproduce the example with originate and local channels described here Asterisk 12 CDR Specification, particularly the section captioned “Local channel between bridges”. This might be my case, I thought, but the actually generated CDR records differ from the described (my Asterisk generates the same answer time for both CDR records with no 10 sec difference as is in the example).

(I’m using Asterisk 18 with PJSIP).


You’d need to show a log including the complete Originate you are doing.

It’s expected behaviour.

Firstly both legs are outgoing, so the transient state is Ringing.

Secondly, the dialplan, or application, to call the B side isn’t started until the A side has answered. When A has answered, the call is up on that side.

Here is the log

pbx*CLI> channel originate PJSIP/9001 extension 89222333444@context_name

No.   Timestamp  (Dir) Address                  SIP Message
===== ========== ============================== ===================================

* CALLING PARTY A (9001@ *
00000 1642974186 * ==>        INVITE sip:9001@;transport=tls SIP/2.0
00001 1642974186 * <==        SIP/2.0 100 Trying
00002 1642974186 * <==        SIP/2.0 180 Ringing

00003 1642974188 * <==        SIP/2.0 200 OK
00004 1642974188 * ==>         ACK sip:9001@;transport=tls SIP/2.0

* CALLING PARTY B (89222333444@ *
00005 1642974188 * ==>         INVITE sip:89222333444@;user=phone SIP/2.0
00006 1642974188 * <==         SIP/2.0 100 Trying
00007 1642974193 * <==         SIP/2.0 180 Ringing
00008 1642974193 * ==>         PRACK sip:89222333444@;user=phone;transport=udp;Hpt=8e98_16;CxtId=3;TRC=ffffffff-ffffffff SIP/2.0

00009 1642974193 * <==         SIP/2.0 200 OK
00010 1642974194 * <==         SIP/2.0 200 OK
00011 1642974194 * ==>         ACK sip:89222333444@;user=phone;transport=udp;Hpt=8e98_16;CxtId=3;TRC=ffffffff-ffffffff SIP/2.0

00012 1642974197 * <==         BYE sip:asterisk@ SIP/2.0
00013 1642974197 * ==>         SIP/2.0 200 OK
00014 1642974197 * ==>         BYE sip:9001@;transport=tls SIP/2.0
00015 1642974197 * <==         SIP/2.0 200 OK

Is it possible then to initiate a call from the asterisk side (like originate does) where it would be CDRed like a regular Dial call? With just the actually bridged time billed.

You could probably reset the CDR within the dialplan that calls the B side.

Unfortunately ForkCDR and ResetCDR (or even CDR_PROP(“disable”) toggle) don’t do the thing. I already tried to put them just before the Dial that calls the B-party (or from the b-/B-handlers of the Dial or Originate calls), because the call is considered answered already, so the event of B-party answer doesn’t affect the resulting CDR in any way (so I cannot deduce its timing from the resulting CDR).

CDRs have changed a lot recently, but ResetCDR used to reset the CDR state completely and allow a new answer.

Just checked the sources:

int ast_cdr_reset(const char *channel_name, int keep_variables) {
    /* Reset to initial state */

static void cdr_object_check_party_a_answer(struct cdr_object *cdr)
	if (cdr->party_a.snapshot->state == AST_STATE_UP && ast_tvzero(cdr->answer)) {
		cdr->answer = cdr->lastevent;

As far as I can understand, if the party A channel state is Up when ResetCDR is called, the new CDR record’s “answer” field value is set instantly (before the actual party B’s answer). And that’s exactly what I get doing live tests.

It’s even mentioned in wiki:

If the channel is answered, the answer time is set to the current time.

So ResetCDR seems to be useless here.

Well, if the maintainers are ignoring the originate app CDR problem since the Asterisk 13 release (and I’ve found quite enough threads about it even here), it seems to write a patch by myself is the only solution I end up with.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.