From 72958ce90f2e50735334e3db08d194ab90db95bc Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Wed, 15 Feb 2017 08:50:17 -0500 Subject: [PATCH] Asterisk 13 implementation of ASTERISK-17362 Change-Id: I8d49b54d5cc741ef45d30970b57e1975df9715c7 --- channels/chan_sip.c | 165 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 143 insertions(+), 22 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 77ea5f2..31a15ec 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -25217,6 +25217,147 @@ static int handle_cc_notify(struct sip_pvt *pvt, struct sip_request *req) return 0; } +static int extract_voice_message_count(struct sip_request *req, int *old_messages, int *new_messages) +{ + char *old_count, *new_count; + char *c = ast_strdupa(get_content_line(req, "Voice-Message", ':')); + + if (ast_strlen_zero(c)) { + return 1; + } + + old_count = strsep(&c, " "); + new_count = strsep(&old_count, "/"); + *old_messages = atoi(old_count); + *new_messages = atoi(new_count); + + return 0; +} + +static int handle_notify_message_summary(struct sip_pvt *p, struct sip_request *req) +{ + const char *default_context = "SIP_Remote"; + char *context = NULL; + const char *mailbox = NULL; + struct sip_peer *peer = NULL; + int old_messages, new_messages; + + if (extract_voice_message_count(req, &old_messages, &new_messages)) { + /* We couldn't get the counts, so bail out */ + return -1; + } + + if (p->mwi) { + if (ast_strlen_zero(p->mwi->mailbox)) { + return -1; + } + ast_publish_mwi_state( + p->mwi->mailbox, + default_context, + new_messages, + old_messages); + return 0; + } + + ast_debug(4, "Unsolicited MWI received from: %s\n", + ast_sockaddr_stringify(&p->recv)); + /* + * Note: If you intend to light unsolicited MWI lights on your + * phones, they must be in the same context as the + * unsolicited_mailbox parameter in the format of: + * default_box@context + */ + + peer = sip_find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type); + if (peer) { + char *unsolicited_context, *specified_extension; + + if (ast_strlen_zero(peer->unsolicited_mailbox)) { + ast_debug(2, "unsolicited_mailbox is not set for peer %s," + " unsolicited MWI will not be delivered.\n", + ast_sockaddr_stringify(&p->recv)); + sip_unref_peer(peer, "removing unsolicited mwi ref short circuit"); + return -1; + } + + /* + * If the unsolicited_mailbox parameter has an @ symbol, use + * that for the context, otherwise leave it at the default of + * SIP_Remote. + */ + unsolicited_context = strchr(peer->unsolicited_mailbox, '@'); + if (unsolicited_context) { + unsolicited_context++; + if (!ast_strlen_zero(unsolicited_context)) { + context = ast_strdupa(unsolicited_context); + /* Was a mailbox also provided? */ + if (peer->unsolicited_mailbox[0] != '@') { + char *target_mailbox = + ast_strdupa(peer->unsolicited_mailbox); + mailbox = strsep(&target_mailbox, "@"); + } + } + } + + if (!context) { + /* We didn't find a context, so just fallback to the + old behavior */ + mailbox = ast_strdupa(peer->unsolicited_mailbox); + } else if (!mailbox) { + /* + * We found a context, but no mailbox was specified, so + * we look for it in the request. + * + * RFC3842 (For the Message-Account header) states: + * + * If the Request-URI or To header in a message-summary + * subscription corresponds to a group or collection of + * individual messaging accounts, the notifier MUST specify + * to which account the message-summary body corresponds. + * + * Therefore, use Message-Account from the body first, and then + * failback to the To header. + */ + specified_extension = ast_strdupa(get_content_line(req, "Message-Account", ':')); + if (ast_strlen_zero(specified_extension)) { + specified_extension = ast_strdupa(sip_get_header(req, "To")); + } + if (!ast_strlen_zero(specified_extension)) { + /* Get the mailbox from the format: */ + char *specified_mailbox = strchr(specified_extension, '@'); + if (specified_mailbox) { + *specified_mailbox = '\0'; + } + specified_mailbox = strchr(specified_extension, ':'); + if (specified_mailbox) { + specified_mailbox++; + if (!ast_strlen_zero(specified_mailbox)) { + mailbox = specified_mailbox; + } + } + } + } + + sip_unref_peer(peer, "removing unsolicited mwi ref"); + } + + if (!ast_strlen_zero(mailbox)) { + const char *delivery_context = context ?: default_context; + + ast_debug(4, "Unsolicited MWI being delivered to: %s@%s\n", + mailbox, delivery_context); + + ast_publish_mwi_state( + mailbox, + delivery_context, + new_messages, + old_messages); + return 0; + } + + return -1; +} + /*! \brief Handle incoming notifications */ static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, uint32_t seqno, const char *e) { @@ -25340,30 +25481,10 @@ static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, str /* Confirm that we received this packet */ transmit_response(p, "200 OK", req); } else if (!strcmp(event, "message-summary")) { - const char *mailbox = NULL; - char *c = ast_strdupa(get_content_line(req, "Voice-Message", ':')); - - if (!p->mwi) { - struct sip_peer *peer = sip_find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type); - - if (peer) { - mailbox = ast_strdupa(peer->unsolicited_mailbox); - sip_unref_peer(peer, "removing unsolicited mwi ref"); - } + if ((res = handle_notify_message_summary(p, req))) { + transmit_response(p, "489 Bad event", req); } else { - mailbox = p->mwi->mailbox; - } - - if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(c)) { - char *old = strsep(&c, " "); - char *new = strsep(&old, "/"); - - ast_publish_mwi_state(mailbox, "SIP_Remote", atoi(new), atoi(old)); - transmit_response(p, "200 OK", req); - } else { - transmit_response(p, "489 Bad event", req); - res = -1; } } else if (!strcmp(event, "keep-alive")) { /* Used by Sipura/Linksys for NAT pinhole, -- 2.7.4