Asterisk 16.3: DialEnd DialStatus always "NOANSWER"

Okay I agree it makes sense that NOANSWER is a good reponse for 480, it’s also clear from the Hangup events why the call was rejected.

But the way the C flag works makes it completely impossible to distingush between if a user just wasn’t registered, if they rejected a call or of they’re DND.

I’ll just list a few cases here, all where the C flag is set

User is not registered (SIP 404 response)
When the C flag is set, all HangupEvents associated with the call has Cause 26. Answered Elsewhere.

This is not true. This call was not ended because it was answered elsewhere, since no SIP CANCEL was ever sent out. On the initial invite asterisk gets a 404 back from the registrar, so the correct cause code should be 1. AST_CAUSE_UNALLOCATED

Here are the relevant events:

404 (with c)
{
  "Event": "DialEnd",
  "Channel": "PJSIP/registrar-000000dc",
  "ChannelState": 4,
  "ChannelStateDesc": "Ring",
  "CallerIDNum": "jonas1",
  "CallerIDName": "jonas1",
  "ConnectedLineNum": "jonas2",
  "ConnectedLineName": "<unknown>",
  "AccountCode": "",
  "Context": "dial",
  "Exten": "jonas2",
  "Priority": "2",
  "DestChannel": "PJSIP/registrar-000000dd",
  "DestChannelState": 0,
  "DestChannelStateDesc": "Down",
  "DestCallerIDNum": "jonas2",
  "DestCallerIDName": "<unknown>",
  "DestConnectedLineNum": "jonas1",
  "DestConnectedLineName": "jonas1",
  "DestAccountCode": "",
  "DestContext": "dial",
  "DestExten": "jonas2",
  "DestPriority": "1",
  "DestUniqueid": "ast007-1558613595.415",
  "DialStatus": "NOANSWER",
  "Forward": null,
  "Linkedid": "ast007-1558613595.414",
  "DestLinkedid": "ast007-1558613595.414",
  "Uniqueid": "ast007-1558613595.414",
  "UtcDate": "2019-05-23T12:13:15Z",
  "DateReceived": "23-05-2019 12:13:15",
  "Language": "en",
  "Privilege": "call,all",
  "SystemName": "ast007",
  "KafkaPartitionId": 0,
  "KafkaOffset": 0,
  "_sequence": 1838,
  "AdditionalAttributes": {
    "DestLanguage": "en",
    "ApproxTimeStamp": "2019-05-23T12:13:16.628+00:00"
  }
}
{
  "Event": "Hangup",
  "Channel": "PJSIP/registrar-000000dd",
  "ChannelState": 0,
  "ChannelStateDesc": "Down",
  "CallerIDNum": "jonas2",
  "CallerIDName": "<unknown>",
  "ConnectedLineNum": "jonas1",
  "ConnectedLineName": "jonas1",
  "AccountCode": "",
  "Context": "dial",
  "Exten": "jonas2",
  "Priority": "1",
  "Cause": 26,
  "Causetxt": "Answered elsewhere",
  "Linkedid": "ast007-1558613595.414",
  "Uniqueid": "ast007-1558613595.415",
  "UtcDate": "2019-05-23T12:13:15Z",
  "DateReceived": "23-05-2019 12:13:15",
  "Language": "en",
  "Privilege": "call,all",
  "SystemName": "ast007",
  "KafkaPartitionId": 0,
  "KafkaOffset": 0,
  "_sequence": 1839,
  "AdditionalAttributes": {
    "Cause-txt": "Answered elsewhere",
    "ApproxTimeStamp": "2019-05-23T12:13:16.628+00:00"
  }
}
{
  "Event": "Hangup",
  "Channel": "PJSIP/registrar-000000dc",
  "ChannelState": 4,
  "ChannelStateDesc": "Ring",
  "CallerIDNum": "jonas1",
  "CallerIDName": "jonas1",
  "ConnectedLineNum": "jonas2",
  "ConnectedLineName": "<unknown>",
  "AccountCode": "",
  "Context": "dial",
  "Exten": "h",
  "Priority": "2",
  "Cause": 26,
  "Causetxt": "Answered elsewhere",
  "Linkedid": "ast007-1558613595.414",
  "Uniqueid": "ast007-1558613595.414",
  "UtcDate": "2019-05-23T12:13:15Z",
  "DateReceived": "23-05-2019 12:13:15",
  "Language": "en",
  "Privilege": "call,all",
  "SystemName": "ast007",
  "KafkaPartitionId": 0,
  "KafkaOffset": 0,
  "_sequence": 1840,
  "AdditionalAttributes": {
    "Cause-txt": "Answered elsewhere",
    "ApproxTimeStamp": "2019-05-23T12:13:16.628+00:00"
  }
}

If the c-flag isn’t set, then I get the expected hangup code (1. Unallocated number). This makes it impossible for me to know that the user isn’t registered from any of the AMI events, or if the call was simply cancelled or timed out.

I don’t believe the C flag is supposed to alter the Hangup Cause like this, unless the call was actually cancelled.

User is DND (SIP 480 response)
Again, here the HangupEvents are being altered by the C flag, exactly like in the first case.

480 (with c)
{
  "Event": "DialEnd",
  "Channel": "PJSIP/registrar-000000e2",
  "ChannelState": 4,
  "ChannelStateDesc": "Ring",
  "CallerIDNum": "jonas1",
  "CallerIDName": "jonas1",
  "ConnectedLineNum": "jonas2",
  "ConnectedLineName": "<unknown>",
  "AccountCode": "",
  "Context": "dial",
  "Exten": "jonas2",
  "Priority": "2",
  "DestChannel": "PJSIP/registrar-000000e3",
  "DestChannelState": 0,
  "DestChannelStateDesc": "Down",
  "DestCallerIDNum": "jonas2",
  "DestCallerIDName": "<unknown>",
  "DestConnectedLineNum": "jonas1",
  "DestConnectedLineName": "jonas1",
  "DestAccountCode": "",
  "DestContext": "dial",
  "DestExten": "jonas2",
  "DestPriority": "1",
  "DestUniqueid": "ast007-1558613775.421",
  "DialStatus": "NOANSWER",
  "Forward": null,
  "Linkedid": "ast007-1558613775.420",
  "DestLinkedid": "ast007-1558613775.420",
  "Uniqueid": "ast007-1558613775.420",
  "UtcDate": "2019-05-23T12:16:15Z",
  "DateReceived": "23-05-2019 12:16:15",
  "Language": "en",
  "Privilege": "call,all",
  "SystemName": "ast007",
  "KafkaPartitionId": 0,
  "KafkaOffset": 0,
  "_sequence": 1862,
  "AdditionalAttributes": {
    "DestLanguage": "en",
    "ApproxTimeStamp": "2019-05-23T12:16:16.625+00:00"
  }
}
{
  "Event": "Hangup",
  "Channel": "PJSIP/registrar-000000e3",
  "ChannelState": 0,
  "ChannelStateDesc": "Down",
  "CallerIDNum": "jonas2",
  "CallerIDName": "<unknown>",
  "ConnectedLineNum": "jonas1",
  "ConnectedLineName": "jonas1",
  "AccountCode": "",
  "Context": "dial",
  "Exten": "jonas2",
  "Priority": "1",
  "Cause": 26,
  "Causetxt": "Answered elsewhere",
  "Linkedid": "ast007-1558613775.420",
  "Uniqueid": "ast007-1558613775.421",
  "UtcDate": "2019-05-23T12:16:15Z",
  "DateReceived": "23-05-2019 12:16:15",
  "Language": "en",
  "Privilege": "call,all",
  "SystemName": "ast007",
  "KafkaPartitionId": 0,
  "KafkaOffset": 0,
  "_sequence": 1863,
  "AdditionalAttributes": {
    "Cause-txt": "Answered elsewhere",
    "ApproxTimeStamp": "2019-05-23T12:16:16.625+00:00"
  }
}
{
  "Event": "Hangup",
  "Channel": "PJSIP/registrar-000000e2",
  "ChannelState": 4,
  "ChannelStateDesc": "Ring",
  "CallerIDNum": "jonas1",
  "CallerIDName": "jonas1",
  "ConnectedLineNum": "jonas2",
  "ConnectedLineName": "<unknown>",
  "AccountCode": "",
  "Context": "dial",
  "Exten": "h",
  "Priority": "2",
  "Cause": 26,
  "Causetxt": "Answered elsewhere",
  "Linkedid": "ast007-1558613775.420",
  "Uniqueid": "ast007-1558613775.420",
  "UtcDate": "2019-05-23T12:16:15Z",
  "DateReceived": "23-05-2019 12:16:15",
  "Language": "en",
  "Privilege": "call,all",
  "SystemName": "ast007",
  "KafkaPartitionId": 0,
  "KafkaOffset": 0,
  "_sequence": 1864,
  "AdditionalAttributes": {
    "Cause-txt": "Answered elsewhere",
    "ApproxTimeStamp": "2019-05-23T12:16:16.625+00:00"
  }
}

User Rejects (SIP 180 Ringing -> SIP 486 Busy Here)
Again, here the HangupEvents are being altered by the C flag, exactly like in the first case.

486 (with c)
{
  "Event": "DialEnd",
  "Channel": "PJSIP/registrar-000000e8",
  "ChannelState": 4,
  "ChannelStateDesc": "Ring",
  "CallerIDNum": "jonas1",
  "CallerIDName": "jonas1",
  "ConnectedLineNum": "jonas2",
  "ConnectedLineName": "<unknown>",
  "AccountCode": "",
  "Context": "dial",
  "Exten": "jonas2",
  "Priority": "2",
  "DestChannel": "PJSIP/registrar-000000e9",
  "DestChannelState": 5,
  "DestChannelStateDesc": "Ringing",
  "DestCallerIDNum": "jonas2",
  "DestCallerIDName": "<unknown>",
  "DestConnectedLineNum": "jonas1",
  "DestConnectedLineName": "jonas1",
  "DestAccountCode": "",
  "DestContext": "dial",
  "DestExten": "jonas2",
  "DestPriority": "1",
  "DestUniqueid": "ast007-1558613944.427",
  "DialStatus": "NOANSWER",
  "Forward": null,
  "Linkedid": "ast007-1558613944.426",
  "DestLinkedid": "ast007-1558613944.426",
  "Uniqueid": "ast007-1558613944.426",
  "UtcDate": "2019-05-23T12:19:06Z",
  "DateReceived": "23-05-2019 12:19:06",
  "Language": "en",
  "Privilege": "call,all",
  "SystemName": "ast007",
  "KafkaPartitionId": 0,
  "KafkaOffset": 0,
  "_sequence": 1889,
  "AdditionalAttributes": {
    "DestLanguage": "en",
    "ApproxTimeStamp": "2019-05-23T12:19:07.609+00:00"
  }
}
{
  "Event": "Hangup",
  "Channel": "PJSIP/registrar-000000e9",
  "ChannelState": 5,
  "ChannelStateDesc": "Ringing",
  "CallerIDNum": "jonas2",
  "CallerIDName": "<unknown>",
  "ConnectedLineNum": "jonas1",
  "ConnectedLineName": "jonas1",
  "AccountCode": "",
  "Context": "dial",
  "Exten": "jonas2",
  "Priority": "1",
  "Cause": 26,
  "Causetxt": "Answered elsewhere",
  "Linkedid": "ast007-1558613944.426",
  "Uniqueid": "ast007-1558613944.427",
  "UtcDate": "2019-05-23T12:19:06Z",
  "DateReceived": "23-05-2019 12:19:06",
  "Language": "en",
  "Privilege": "call,all",
  "SystemName": "ast007",
  "KafkaPartitionId": 0,
  "KafkaOffset": 0,
  "_sequence": 1890,
  "AdditionalAttributes": {
    "Cause-txt": "Answered elsewhere",
    "ApproxTimeStamp": "2019-05-23T12:19:07.609+00:00"
  }
}
{
  "Event": "Hangup",
  "Channel": "PJSIP/registrar-000000e8",
  "ChannelState": 4,
  "ChannelStateDesc": "Ring",
  "CallerIDNum": "jonas1",
  "CallerIDName": "jonas1",
  "ConnectedLineNum": "jonas2",
  "ConnectedLineName": "<unknown>",
  "AccountCode": "",
  "Context": "dial",
  "Exten": "h",
  "Priority": "2",
  "Cause": 26,
  "Causetxt": "Answered elsewhere",
  "Linkedid": "ast007-1558613944.426",
  "Uniqueid": "ast007-1558613944.426",
  "UtcDate": "2019-05-23T12:19:06Z",
  "DateReceived": "23-05-2019 12:19:06",
  "Language": "en",
  "Privilege": "call,all",
  "SystemName": "ast007",
  "KafkaPartitionId": 0,
  "KafkaOffset": 0,
  "_sequence": 1891,
  "AdditionalAttributes": {
    "Cause-txt": "Answered elsewhere",
    "ApproxTimeStamp": "2019-05-23T12:19:07.609+00:00"
  }
}

As you can see, the DialEnd and Hangup events are completely identical for all three cases, making it completely impossible to tell these three very different outcomes of a call apart.

Reading the documentation for the c argument on the Dial application (https://wiki.asterisk.org/wiki/display/AST/Asterisk+16+Application_Dial):

  • c - If the Dial() application cancels this call, always set HANGUPCAUSE to ‘answered elsewhere’

It should only apply this change to hangup cause IF it cancels the call. In all of the above cases, none of the calls were cancelled.