diff -Naru asterisk-14.5.0_orig/channels/chan_sip.c asterisk-14.5.0/channels/chan_sip.c --- asterisk-14.5.0_orig/channels/chan_sip.c 2017-05-31 02:50:46.000000000 +0900 +++ asterisk-14.5.0/channels/chan_sip.c 2017-06-16 17:20:51.662231445 +0900 @@ -15546,8 +15546,9 @@ { const char *channame = astman_get_header(m, "Channel"); struct ast_variable *vars = astman_get_variables_order(m, ORDER_NATURAL); - struct sip_pvt *p; + struct sip_pvt *p = NULL; struct ast_variable *header, *var; + char indialog = 0; if (ast_strlen_zero(channame)) { astman_send_error(s, m, "SIPNotify requires a channel name"); @@ -15558,25 +15559,61 @@ channame += 4; } - if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL, 0))) { - astman_send_error(s, m, "Unable to build sip pvt data for notify (memory/socket error)"); - return 0; - } + // check if Call-ID variable is set + for (var = vars; var; var = var->next) { + if (!strcasecmp(var->name, "Call-ID")) { + struct sip_pvt tmp_dialog = { + .callid = var->value, + }; + + p = ao2_find(dialogs, &tmp_dialog, OBJ_POINTER); + if (!p) { + astman_send_error(s, m, "Call-ID not found"); + return 0; + } + indialog = 1; + } + } + + if (!indialog) { + if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL, 0))) { + astman_send_error(s, m, "Unable to build sip pvt data for notify (memory/socket error)"); + return 0; + } - if (create_addr(p, channame, NULL, 0)) { - /* Maybe they're not registered, etc. */ - dialog_unlink_all(p); - dialog_unref(p, "unref dialog inside for loop" ); - /* sip_destroy(p); */ - astman_send_error(s, m, "Could not create address"); - return 0; - } + if (create_addr(p, channame, NULL, 0)) { + /* Maybe they're not registered, etc. */ + dialog_unlink_all(p); + dialog_unref(p, "unref dialog inside for loop" ); + /* sip_destroy(p); */ + astman_send_error(s, m, "Could not create address"); + return 0; + } - /* Notify is outgoing call */ - ast_set_flag(&p->flags[0], SIP_OUTGOING); - sip_notify_alloc(p); + /* Notify is outgoing call */ + ast_set_flag(&p->flags[0], SIP_OUTGOING); + sip_notify_alloc(p); + + p->notify->headers = header = ast_variable_new("Subscription-State", "terminated", ""); + } else { + if (!(p->notify)) { + sip_notify_alloc(p); + } else { + ast_variables_destroy(p->notify->headers); + } + + p->notify->headers = header = ast_variable_new("Subscription-State", "terminated", ""); + } - p->notify->headers = header = ast_variable_new("Subscription-State", "terminated", ""); + /* if (pref) { + ast_string_field_set(p, callid, pref->callid); + ast_string_field_set(p, fromuser, pref->fromuser); + ast_string_field_set(p, fromname, pref->fromname); + ast_string_field_set(p, tag, pref->tag); + ast_string_field_set(p, theirtag, pref->theirtag); + p->ocseq = pref->ocseq; + (pref->ocseq)++; + } */ for (var = vars; var; var = var->next) { if (!strcasecmp(var->name, "Content")) { @@ -15585,21 +15622,27 @@ ast_str_append(&p->notify->content, 0, "%s", var->value); } else if (!strcasecmp(var->name, "Content-Length")) { ast_log(LOG_WARNING, "it is not necessary to specify Content-Length, ignoring\n"); + } else if (!strcasecmp(var->name, "Call-ID")) { + // do nothing here } else { header->next = ast_variable_new(var->name, var->value, ""); header = header->next; } } + if (!indialog) { /* Now that we have the peer's address, set our ip and change callid */ ast_sip_ouraddrfor(&p->sa, &p->ourip, p); build_via(p); - change_callid_pvt(p, NULL); + change_callid_pvt(p, NULL); sip_scheddestroy(p, SIP_TRANS_TIMEOUT); transmit_invite(p, SIP_NOTIFY, 0, 2, NULL); dialog_unref(p, "bump down the count of p since we're done with it."); + } else { + transmit_invite(p, SIP_NOTIFY, 0, 1, NULL); + } astman_send_ack(s, m, "Notify Sent"); ast_variables_destroy(vars);