summaryrefslogtreecommitdiff
path: root/channels/chan_sip.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/chan_sip.c')
-rw-r--r--channels/chan_sip.c92
1 files changed, 67 insertions, 25 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index a829e2039..2d20442d0 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -593,6 +593,9 @@
<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");
@@ -30286,6 +30319,7 @@ static int sip_send_keepalive(const void *data)
struct sip_peer *peer = (struct sip_peer*) data;
int res = 0;
const char keepalive[] = "\r\n";
+ size_t count = sizeof(keepalive) - 1;
peer->keepalivesend = -1;
@@ -30296,12 +30330,12 @@ static int sip_send_keepalive(const void *data)
/* Send the packet out using the proper method for this peer */
if ((peer->socket.fd != -1) && (peer->socket.type == AST_TRANSPORT_UDP)) {
- res = ast_sendto(peer->socket.fd, keepalive, sizeof(keepalive), 0, &peer->addr);
+ res = ast_sendto(peer->socket.fd, keepalive, count, 0, &peer->addr);
} else if ((peer->socket.type & (AST_TRANSPORT_TCP | AST_TRANSPORT_TLS)) &&
peer->socket.tcptls_session) {
- res = sip_tcptls_write(peer->socket.tcptls_session, keepalive, sizeof(keepalive));
+ res = sip_tcptls_write(peer->socket.tcptls_session, keepalive, count);
} else if (peer->socket.type == AST_TRANSPORT_UDP) {
- res = ast_sendto(sipsock, keepalive, sizeof(keepalive), 0, &peer->addr);
+ res = ast_sendto(sipsock, keepalive, count, 0, &peer->addr);
}
if (res == -1) {
@@ -30315,7 +30349,7 @@ static int sip_send_keepalive(const void *data)
}
}
- if (res != sizeof(keepalive)) {
+ if (res != count) {
ast_log(LOG_WARNING, "sip_send_keepalive to %s returned %d: %s\n", ast_sockaddr_stringify(&peer->addr), res, strerror(errno));
}
@@ -30715,6 +30749,14 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_
}
}
+ /* If stripping the DNID left us with nothing, bail out */
+ if (ast_strlen_zero(tmp)) {
+ dialog_unlink_all(p);
+ dialog_unref(p, "unref dialog p from bad destination");
+ *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
+ return NULL;
+ }
+
/* Divvy up the items separated by slashes */
AST_NONSTANDARD_APP_ARGS(args, tmp, '/');