chan_sip: 3PCC patch for AMI "SIPnotify"
authorYasuhiko Kamata <yasuhiko.kamata@nxtg.co.jp>
Wed, 13 Dec 2017 04:42:35 +0000 (13:42 +0900)
committerYasuhiko Kamata <yasuhiko.kamata@nxtg.co.jp>
Wed, 13 Dec 2017 04:42:35 +0000 (13:42 +0900)
A patch for sending in-dialog SIP NOTIFY message
with "SIPnotify" AMI action.

ASTERISK-27461

Change-Id: I5797ded4752acd966db6b13971284db684cc5ab4

channels/chan_sip.c

index a829e20..689975f 100644 (file)
                                <para>At least one variable pair must be specified.
                                <replaceable>name</replaceable>=<replaceable>value</replaceable></para>
                        </parameter>
+                       <parameter name="Call-ID" required="false">
+                               <para>When specified, SIP notity will be sent as a part of an existing dialog.</para>
+                       </parameter>
                </syntax>
                <description>
                        <para>Sends a SIP Notify event.</para>
@@ -15591,11 +15594,13 @@ static int manager_sipnotify(struct mansession *s, const struct message *m)
 {
        const char *channame = astman_get_header(m, "Channel");
        struct ast_variable *vars = astman_get_variables_order(m, ORDER_NATURAL);
+       const char *callid = astman_get_header(m, "Call-ID");
        struct sip_pvt *p;
        struct ast_variable *header, *var;
 
        if (ast_strlen_zero(channame)) {
                astman_send_error(s, m, "SIPNotify requires a channel name");
+               ast_variables_destroy(vars);
                return 0;
        }
 
@@ -15603,23 +15608,46 @@ static int manager_sipnotify(struct mansession *s, const struct message *m)
                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 header is set */
+       if (!ast_strlen_zero(callid)) {
+               struct sip_pvt tmp_dialog = {
+                       .callid = callid,
+               };
 
-       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;
-       }
+               p = ao2_find(dialogs, &tmp_dialog, OBJ_SEARCH_OBJECT);
+               if (!p) {
+                       astman_send_error(s, m, "Call-ID not found");
+                       ast_variables_destroy(vars);
+                       return 0;
+               }
 
-       /* Notify is outgoing call */
-       ast_set_flag(&p->flags[0], SIP_OUTGOING);
-       sip_notify_alloc(p);
+               if (!(p->notify)) {
+                       sip_notify_alloc(p);
+               } else {
+                       ast_variables_destroy(p->notify->headers);
+               }
+       } else {
+               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)");
+                       ast_variables_destroy(vars);
+                       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");
+                       ast_variables_destroy(vars);
+                       return 0;
+               }
+
+               /* 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", "");
 
@@ -15636,14 +15664,19 @@ static int manager_sipnotify(struct mansession *s, const struct message *m)
                }
        }
 
-       /* 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);
+       if (ast_strlen_zero(callid)) {
+               /* 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);
+               sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
+               transmit_invite(p, SIP_NOTIFY, 0, 2, NULL);
+       } else {
+               sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
+               transmit_invite(p, SIP_NOTIFY, 0, 1, NULL);
+       }
        dialog_unref(p, "bump down the count of p since we're done with it.");
 
        astman_send_ack(s, m, "Notify Sent");