aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2009-10-14 17:48:57 +0000
committerjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2009-10-14 17:48:57 +0000
commitd02738f5920dfd4590d3b6ebf1ff75f55c31c057 (patch)
treee0ce47e0c57ba61e576f3d769e4f23a56af67d04
parent2f25cd5cc8f0ff4e82c5258e4f634e0ffbf0b6cb (diff)
Allow for adding message body to the SIP NOTIFY message
Ability has been added to both manager command SIPnotify as well as console command sip notify. Message body is stored in the "Content" variable. An example is present in sip_notify.conf. (closes issue #13926) Reported by: jthurman Patches: sip-notify-svn189463.diff uploaded by gareth (license 208) Tested by: gareth git-svn-id: http://svn.digium.com/svn/asterisk/trunk@224035 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--CHANGES2
-rw-r--r--channels/chan_sip.c125
-rw-r--r--configs/sip_notify.conf.sample23
3 files changed, 77 insertions, 73 deletions
diff --git a/CHANGES b/CHANGES
index 95221d68e..83e6e2611 100644
--- a/CHANGES
+++ b/CHANGES
@@ -46,6 +46,8 @@ SIP Changes
in a multi-channel setup resolved in an individual way.
* Added 'externtcpport' and 'externtlsport' options to allow custom port
configuration for the externip and externhost options when tcp or tls is used.
+ * Added support for message body (stored in content variable) to SIP NOTIFY message
+ accessible via AMI and CLI.
IAX2 Changes
-----------
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 7c619d414..27d658a81 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1640,6 +1640,11 @@ struct sip_refer {
enum referstatus status; /*!< REFER status */
};
+/*! \brief Struct to handle custom SIP notify requests. Dynamically allocated when needed */
+struct sip_notify {
+ struct ast_variable *headers;
+ struct ast_str *content;
+};
/*! \brief Structure that encapsulates all attributes related to running
* SIP Session-Timers feature on a per dialog basis.
@@ -1792,7 +1797,7 @@ struct sip_pvt {
enum transfermodes allowtransfer; /*!< REFER: restriction scheme */
struct ast_channel *owner; /*!< Who owns us (if we have an owner) */
struct sip_route *route; /*!< Head of linked list of routing steps (fm Record-Route) */
- struct ast_variable *notify_headers; /*!< Custom notify type */
+ struct sip_notify *notify; /*!< Custom notify type */
struct sip_auth *peerauth; /*!< Realm authentication */
int noncecount; /*!< Nonce-count */
unsigned int stalenonce:1; /*!< Marks the current nonce as responded too */
@@ -2415,7 +2420,6 @@ static int transmit_message_with_text(struct sip_pvt *p, const char *text);
static int transmit_refer(struct sip_pvt *p, const char *dest);
static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs, const char *vmexten);
static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *message, int terminate);
-static int transmit_notify_custom(struct sip_pvt *p, struct ast_variable *vars);
static int transmit_register(struct sip_registry *r, int sipmethod, const char *auth, const char *authheader);
static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);
static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, int seqno);
@@ -2502,6 +2506,7 @@ static void peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer
static struct ast_variable *copy_vars(struct ast_variable *src);
/* static int sip_addrcmp(char *name, struct sockaddr_in *sin); Support for peer matching */
static int sip_refer_allocate(struct sip_pvt *p);
+static int sip_notify_allocate(struct sip_pvt *p);
static void ast_quiet_chan(struct ast_channel *chan);
static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);
static int do_magic_pickup(struct ast_channel *channel, const char *extension, const char *context);
@@ -5610,9 +5615,10 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist)
if (p->options)
ast_free(p->options);
- if (p->notify_headers) {
- ast_variables_destroy(p->notify_headers);
- p->notify_headers = NULL;
+ if (p->notify) {
+ ast_variables_destroy(p->notify->headers);
+ ast_free(p->notify->content);
+ ast_free(p->notify);
}
if (p->rtp) {
ast_rtp_instance_destroy(p->rtp);
@@ -11004,13 +11010,6 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
add_header(&req, "Allow", ALLOWED_METHODS);
add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
- if(p->notify_headers) {
- char buf[512];
- for (var = p->notify_headers; var; var = var->next) {
- ast_copy_string(buf, var->value, sizeof(buf));
- add_header(&req, var->name, ast_unescape_semicolon(buf));
- }
- }
if (p->options && p->options->addsipheaders && p->owner) {
struct ast_channel *chan = p->owner; /* The owner channel */
struct varshead *headp;
@@ -11065,11 +11064,15 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
try_suggested_sip_codec(p);
add_sdp(&req, p, FALSE, TRUE, FALSE);
}
+ } else if (p->notify) {
+ for (var = p->notify->headers; var; var = var->next)
+ add_header(&req, var->name, var->value);
+ add_header_contentLength(&req, ast_str_strlen(p->notify->content));
+ if (ast_str_strlen(p->notify->content))
+ add_line(&req, ast_str_buffer(p->notify->content));
} else {
- if (!p->notify_headers) {
- add_header_contentLength(&req, 0);
- }
- }
+ add_header_contentLength(&req, 0);
+ }
if (!p->initreq.headers || init > 2)
initialize_initreq(p, &req);
@@ -11510,37 +11513,12 @@ static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *messa
return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
}
-/*! \brief Notify device with custom headers from sip_notify.conf */
-static int transmit_notify_custom(struct sip_pvt *p, struct ast_variable *vars) {
- struct sip_request req;
- struct ast_variable *var, *newvar;
-
- initreqprep(&req, p, SIP_NOTIFY);
-
- /* Copy notify vars and add headers */
- p->notify_headers = newvar = ast_variable_new("Subscription-State", "terminated", "");
- add_header(&req, newvar->name, newvar->value);
- for (var = vars; var; var = var->next) {
- char buf[512];
- ast_debug(2, " Adding pair %s=%s\n", var->name, var->value);
- ast_copy_string(buf, var->value, sizeof(buf));
- add_header(&req, var->name, ast_unescape_semicolon(buf));
- newvar->next = ast_variable_new(var->name, var->value, "");
- newvar = newvar->next;
- }
-
- if (!p->initreq.headers) { /* Initialize first request before sending */
- initialize_initreq(p, &req);
- }
-
- return send_request(p, &req, XMIT_UNRELIABLE, p->ocseq);
-}
-
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(m);
struct sip_pvt *p;
+ struct ast_variable *header, *var;
if (ast_strlen_zero(channame)) {
astman_send_error(s, m, "SIPNotify requires a channel name");
@@ -11567,21 +11545,26 @@ static int manager_sipnotify(struct mansession *s, const struct message *m)
/* Notify is outgoing call */
ast_set_flag(&p->flags[0], SIP_OUTGOING);
+ sip_notify_allocate(p);
+
+ p->notify->headers = header = ast_variable_new("Subscription-State", "terminated", "");
+
+ for (var = vars; var; var = var->next) {
+ if (!strcasecmp(var->name, "Content")) {
+ if (ast_str_strlen(p->notify->content))
+ ast_str_append(&p->notify->content, 0, "\r\n");
+ ast_str_append(&p->notify->content, 0, "%s", var->value);
+ } else {
+ header->next = ast_variable_new(var->name, var->value, "");
+ header = header->next;
+ }
+ }
- /* Recalculate our side, and recalculate Call ID */
- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
- build_via(p);
- ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name");
- build_callid_pvt(p);
- ao2_t_link(dialogs, p, "Linking in new name");
dialog_ref(p, "bump the count of p, which transmit_sip_request will decrement.");
sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
+ transmit_invite(p, SIP_NOTIFY, 0, 2);
- if (!transmit_notify_custom(p, vars)) {
- astman_send_ack(s, m, "Notify Sent");
- } else {
- astman_send_error(s, m, "Unable to send notify");
- }
+ astman_send_ack(s, m, "Notify Sent");
ast_variables_destroy(vars);
return 0;
}
@@ -12024,6 +12007,15 @@ static int sip_refer_allocate(struct sip_pvt *p)
return p->refer ? 1 : 0;
}
+/*! \brief Allocate SIP refer structure */
+static int sip_notify_allocate(struct sip_pvt *p)
+{
+ p->notify = ast_calloc(1, sizeof(struct sip_notify));
+ if (p->notify)
+ p->notify->content = ast_str_create(128);
+ return p->notify ? 1 : 0;
+}
+
/*! \brief Transmit SIP REFER message (initiated by the transfer() dialplan application
\note this is currently broken as we have no way of telling the dialplan
engine whether a transfer succeeds or fails.
@@ -17199,6 +17191,8 @@ static char *sip_cli_notify(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
for (i = 3; i < a->argc; i++) {
struct sip_pvt *p;
+ char buf[512];
+ struct ast_variable *header, *var;
if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL))) {
ast_log(LOG_WARNING, "Unable to build sip pvt data for notify (memory/socket error)\n");
@@ -17216,17 +17210,28 @@ static char *sip_cli_notify(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
/* Notify is outgoing call */
ast_set_flag(&p->flags[0], SIP_OUTGOING);
+ sip_notify_allocate(p);
+ p->notify->headers = header = ast_variable_new("Subscription-State", "terminated", "");
+
+ for (var = varlist; var; var = var->next) {
+ ast_copy_string(buf, var->value, sizeof(buf));
+ ast_unescape_semicolon(buf);
+
+ if (!strcasecmp(var->name, "Content")) {
+ if (ast_str_strlen(p->notify->content))
+ ast_str_append(&p->notify->content, 0, "\r\n");
+ ast_str_append(&p->notify->content, 0, "%s", buf);
+ } else {
+ header->next = ast_variable_new(var->name, buf, "");
+ header = header->next;
+ }
+ }
/* Recalculate our side, and recalculate Call ID */
- ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip, p);
- build_via(p);
- ao2_t_unlink(dialogs, p, "About to change the callid -- remove the old name");
- build_callid_pvt(p);
- ao2_t_link(dialogs, p, "Linking in new name");
ast_cli(a->fd, "Sending NOTIFY of type '%s' to '%s'\n", a->argv[2], a->argv[i]);
dialog_ref(p, "bump the count of p, which transmit_sip_request will decrement.");
sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
- transmit_notify_custom(p, varlist);
+ transmit_invite(p, SIP_NOTIFY, 0, 2);
}
return CLI_SUCCESS;
@@ -18397,7 +18402,7 @@ static void handle_response_notify(struct sip_pvt *p, int resp, const char *rest
break;
case 401: /* Not www-authorized on SIP method */
case 407: /* Proxy auth */
- if (!p->notify_headers) {
+ if (!p->notify) {
break; /* Only device notify can use NOTIFY auth */
}
ast_string_field_set(p, theirtag, NULL);
diff --git a/configs/sip_notify.conf.sample b/configs/sip_notify.conf.sample
index 74ee9554b..145bf7dbe 100644
--- a/configs/sip_notify.conf.sample
+++ b/configs/sip_notify.conf.sample
@@ -1,53 +1,50 @@
+; rfc3842
+
+[clear-mwi]
+Event=>message-summary
+Content-type=>application/simple-message-summary
+Content=>Messages-Waiting: no
+Content=>Message-Account: sip:asterisk@127.0.0.1
+Content=>Voice-Message: 0/0 (0/0)
+
; Aastra
[aastra-check-cfg]
Event=>check-sync
-Content-Length=>0
[aastra-xml]
Event=>aastra-xml
-Content-Length=>0
; Linksys
[linksys-cold-restart]
Event=>reboot_now
-Content-Length=>0
[linksys-warm-restart]
Event=>restart_now
-Content-Length=>0
; Polycom
[polycom-check-cfg]
Event=>check-sync
-Content-Length=>0
; Sipura
[sipura-check-cfg]
Event=>resync
-Content-Length=>0
[sipura-get-report]
Event=>report
-Content-Length=>0
; snom
[snom-check-cfg]
Event=>check-sync\;reboot=false
-Content-Length=>0
[snom-reboot]
Event=>reboot
-Content-Length=>0
-;;
-;; The following NOTIFY messages are not confirmed to work.
-;;
+; Cisco
[cisco-check-cfg]
Event=>check-sync
-Content-Length=>0