[asterisk-commits] branch oej/test-this-branch r10689 - in
/team/oej/test-this-branch: ./ channels/
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Tue Feb 21 13:48:30 MST 2006
Author: oej
Date: Tue Feb 21 14:48:27 2006
New Revision: 10689
URL: http://svn.digium.com/view/asterisk?rev=10689&view=rev
Log:
Adding subscribemwi branch for testing
Modified:
team/oej/test-this-branch/README.test-this-branch
team/oej/test-this-branch/channels/chan_sip.c
Modified: team/oej/test-this-branch/README.test-this-branch
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/README.test-this-branch?rev=10689&r1=10688&r2=10689&view=diff
==============================================================================
--- team/oej/test-this-branch/README.test-this-branch (original)
+++ team/oej/test-this-branch/README.test-this-branch Tue Feb 21 14:48:27 2006
@@ -20,6 +20,7 @@
- rtcp: Improved support for RTCP (#2863)
- dialplan-ami-events: Report dialplan reload in manager (#5741)
- sipregister: A new registration architecture (#5834)
+- subscribemwi: Support for SIP subscription of MWI notification (#6390)
Coming here soon:
- iptos: New IPtos support, separate audio and signalling (#6355)
Modified: team/oej/test-this-branch/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/channels/chan_sip.c?rev=10689&r1=10688&r2=10689&view=diff
==============================================================================
--- team/oej/test-this-branch/channels/chan_sip.c (original)
+++ team/oej/test-this-branch/channels/chan_sip.c Tue Feb 21 14:48:27 2006
@@ -192,7 +192,8 @@
XPIDF_XML,
DIALOG_INFO_XML,
CPIM_PIDF_XML,
- PIDF_XML
+ PIDF_XML,
+ MWI_NOTIFICATION
};
static const struct cfsubscription_types {
@@ -206,7 +207,8 @@
{ DIALOG_INFO_XML, "dialog", "application/dialog-info+xml", "dialog-info+xml" },
{ CPIM_PIDF_XML, "presence", "application/cpim-pidf+xml", "cpim-pidf+xml" }, /* RFC 3863 */
{ PIDF_XML, "presence", "application/pidf+xml", "pidf+xml" }, /* RFC 3863 */
- { XPIDF_XML, "presence", "application/xpidf+xml", "xpidf+xml" } /* Pre-RFC 3863 with MS additions */
+ { XPIDF_XML, "presence", "application/xpidf+xml", "xpidf+xml" }, /* Pre-RFC 3863 with MS additions */
+ { MWI_NOTIFICATION, "message-summary", "application/simple-message-summary", "mwi" } /* Mailbox notification */
};
enum sipmethod {
@@ -614,8 +616,9 @@
#define SIP_PAGE2_DEBUG_CONSOLE (1 << 6)
#define SIP_PAGE2_DYNAMIC (1 << 7) /*!< Dynamic Peers register with Asterisk */
#define SIP_PAGE2_SELFDESTRUCT (1 << 8) /*!< Automatic peers need to destruct themselves */
-#define SIP_PAGE2_VIDEOSUPPORT (1 << 10)
-#define SIP_PAGE2_PEER_REGISTER (1 << 11)
+#define SIP_PAGE2_SUBSCRIBEMWIONLY (1 << 9) /*!< Only support subscription-related MWI notification */
+#define SIP_PAGE2_VIDEOSUPPORT (1 << 10) /*!< Support video for this peer */
+#define SIP_PAGE2_PEER_REGISTER (1 << 11) /*!< Register this peer with service */
#define SIP_PAGE2_FLAGS_TO_COPY \
(SIP_PAGE2_VIDEOSUPPORT)
@@ -734,7 +737,7 @@
struct ast_dsp *vad; /*!< Voice Activation Detection dsp */
- struct sip_peer *peerpoke; /*!< If this dialog is to poke a peer, which one */
+ struct sip_peer *relatedpeer; /*!< If this dialog is to related to a peer, which one */
struct sip_registry *registry; /*!< If this is a REGISTER dialog, to which registry
If this is an INVITE, to which registry */
struct ast_rtp *rtp; /*!< RTP Session */
@@ -851,6 +854,7 @@
struct sockaddr_in defaddr; /*!< Default IP address, used until registration */
struct ast_ha *ha; /*!< Access control list */
struct ast_variable *chanvars; /*!< Variables to set for channel created by user */
+ struct sip_pvt *mwipvt; /*!< Subscription for MWI */
struct sip_registry *registry; /*!< If this peer registers with outside service */
int lastmsg;
};
@@ -991,6 +995,8 @@
static int find_sip_method(char *msg);
static unsigned int parse_sip_options(struct sip_pvt *pvt, char *supported);
static void sip_destroy(struct sip_pvt *p);
+static void sip_destroy_peer(struct sip_peer *peer);
+static void sip_destroy_user(struct sip_user *user);
static void parse_request(struct sip_request *req);
static char *get_header(struct sip_request *req, const char *name);
static void copy_request(struct sip_request *dst,struct sip_request *src);
@@ -1002,6 +1008,8 @@
static char *generate_random_string(char *buf, size_t size);
static void set_peer_defaults(struct sip_peer *peer);
static struct sip_peer *temp_peer(const char *name);
+static int sip_send_mwi_to_peer(struct sip_peer *peer);
+static int sip_scheddestroy(struct sip_pvt *p, int ms);
/*----- RTP interface functions */
@@ -1719,6 +1727,11 @@
/* Delete it, it needs to disappear */
if (peer->call)
sip_destroy(peer->call);
+
+ if (peer->mwipvt) { /* We have an active subscription, delete it */
+ sip_destroy(peer->mwipvt);
+ }
+
if (peer->chanvars) {
ast_variables_destroy(peer->chanvars);
peer->chanvars = NULL;
@@ -2212,6 +2225,10 @@
if (sip_debug_test_pvt(p) || option_debug > 2)
ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text);
+
+ /* Remove link from peer to subscription of MWI */
+ if (p->relatedpeer && p->relatedpeer->mwipvt)
+ p->relatedpeer->mwipvt = (struct sip_pvt *) NULL;
if (dumphistory)
sip_dump_history(p);
@@ -5295,7 +5312,6 @@
case AST_EXTENSION_REMOVED:
add_header(&req, "Subscription-State", "terminated;reason=noresource");
break;
- break;
default:
if (p->expiry)
add_header(&req, "Subscription-State", "active");
@@ -5376,6 +5392,12 @@
ast_build_string(&t, &maxbytes, "Messages-Waiting: %s\r\n", newmsgs ? "yes" : "no");
ast_build_string(&t, &maxbytes, "Message-Account: sip:%s@%s\r\n", !ast_strlen_zero(vmexten) ? vmexten : default_vmexten, ast_strlen_zero(p->fromdomain) ? ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip) : p->fromdomain);
ast_build_string(&t, &maxbytes, "Voice-Message: %d/%d (0/0)\r\n", newmsgs, oldmsgs);
+ if (p->subscribed) {
+ if (p->expiry)
+ add_header(&req, "Subscription-State", "active");
+ else /* Expired */
+ add_header(&req, "Subscription-State", "terminated;reason=timeout");
+ }
if (t > tmp + sizeof(tmp))
ast_log(LOG_WARNING, "Buffer overflow detected!! (Please file a bug report)\n");
@@ -6618,7 +6640,8 @@
update_peer(peer, p->expiry);
/* Say OK and ask subsystem to retransmit msg counter */
transmit_response_with_date(p, "200 OK", req);
- peer->lastmsgssent = -1;
+ if (!ast_test_flag((&peer->flags_page2), SIP_PAGE2_SUBSCRIBEMWIONLY))
+ peer->lastmsgssent = -1;
res = 0;
break;
}
@@ -7245,7 +7268,7 @@
\return 0 on success, -1 on failure, and 1 on challenge sent
-2 on authentication error from chedck_auth()
*/
-static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, int reliable, struct sockaddr_in *sin, int ignore, char *mailbox, int mailboxlen)
+static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, int reliable, struct sockaddr_in *sin, int ignore, struct sip_peer **authpeer)
{
struct sip_user *user = NULL;
struct sip_peer *peer;
@@ -7314,7 +7337,7 @@
if (ast_strlen_zero(of))
return 0;
- if (!mailbox) /* If it's a mailbox SUBSCRIBE, don't check users */
+ if (!authpeer) /* If we are looking for a peer, don't check the user objects (or realtime) */
user = find_user(of, 1);
/* Find user based on user name in the from header */
@@ -7405,7 +7428,7 @@
ast_verbose("Found user '%s'\n", user->name);
} else {
if (user) {
- if (!mailbox && debug)
+ if (!authpeer && debug)
ast_verbose("Found user '%s', but fails host access\n", user->name);
ASTOBJ_UNREF(user,sip_destroy_user);
}
@@ -7482,8 +7505,10 @@
p->chanvars = tmpvar;
}
}
- if (mailbox)
- snprintf(mailbox, mailboxlen, ",%s,", peer->mailbox);
+ if (authpeer) {
+ (*authpeer) = peer; /* We might want to add a ref to the object here, to keep it in memory a bit longer if it is realtime */
+ ASTOBJ_REF(peer); /* Any function that uses authpeer needs to ASTOBJ_UNREF */
+ }
if (!ast_strlen_zero(peer->username)) {
ast_string_field_set(p, username, peer->username);
/* Use the default username for authentication on outbound calls */
@@ -7553,7 +7578,7 @@
*/
static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, int reliable, struct sockaddr_in *sin, int ignore)
{
- return check_user_full(p, req, sipmethod, uri, reliable, sin, ignore, NULL, 0);
+ return check_user_full(p, req, sipmethod, uri, reliable, sin, ignore, NULL);
}
/*! \brief Get text out of a SIP MESSAGE packet */
@@ -8624,7 +8649,7 @@
static int __sip_show_channels(int fd, int argc, char *argv[], int subscriptions)
{
-#define FORMAT3 "%-15.15s %-10.10s %-11.11s %-15.15s %-13.13s %-15.15s\n"
+#define FORMAT3 "%-15.15s %-10.10s %-11.11s %-15.15s %-13.13s %-15.15s %-10.10s\n"
#define FORMAT2 "%-15.15s %-10.10s %-11.11s %-11.11s %-4.4s %-7.7s %-15.15s\n"
#define FORMAT "%-15.15s %-10.10s %-11.11s %5.5d/%5.5d %-4.4s %-3.3s %-3.3s %-15.15s\n"
struct sip_pvt *cur;
@@ -8636,8 +8661,8 @@
cur = iflist;
if (!subscriptions)
ast_cli(fd, FORMAT2, "Peer", "User/ANR", "Call ID", "Seq (Tx/Rx)", "Format", "Hold", "Last Message");
- else
- ast_cli(fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type");
+ else
+ ast_cli(fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type", "Mailbox");
while (cur) {
if (cur->subscribed == NONE && !subscriptions) {
ast_cli(fd, FORMAT, ast_inet_ntoa(iabuf, sizeof(iabuf), cur->sa.sin_addr),
@@ -8653,8 +8678,12 @@
if (cur->subscribed != NONE && subscriptions) {
ast_cli(fd, FORMAT3, ast_inet_ntoa(iabuf, sizeof(iabuf), cur->sa.sin_addr),
ast_strlen_zero(cur->username) ? ( ast_strlen_zero(cur->cid_num) ? "(None)" : cur->cid_num ) : cur->username,
- cur->callid, cur->exten, ast_extension_state2str(cur->laststate),
- subscription_type2str(cur->subscribed));
+ cur->callid,
+ cur->subscribed == MWI_NOTIFICATION ? "--" : cur->exten,
+ cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate),
+ subscription_type2str(cur->subscribed),
+ cur->subscribed == MWI_NOTIFICATION ? (cur->relatedpeer ? cur->relatedpeer->mailbox : "<none>") : "<none>"
+);
numchans++;
}
cur = cur->next;
@@ -10019,7 +10048,7 @@
if (resp != 100) {
int statechanged = 0;
int newstate = 0;
- peer = p->peerpoke;
+ peer = p->relatedpeer;
gettimeofday(&tv, NULL);
pingtime = ast_tvdiff_ms(tv, peer->ps);
if (pingtime < 1)
@@ -10099,7 +10128,7 @@
gettag(req, "To", tag, sizeof(tag));
ast_string_field_set(p, theirtag, tag);
}
- if (p->peerpoke) {
+ if (p->relatedpeer && p->method == SIP_OPTIONS) {
/* We don't really care what the response is, just that it replied back.
Well, as long as it's not a 100 response... since we might
need to hang around for something more "definitive" */
@@ -10980,6 +11009,9 @@
int gotdest;
int res = 0;
int firststate = AST_EXTENSION_REMOVED;
+ struct sip_peer *authpeer = NULL;
+ char *event = get_header(req, "Event"); /* Get Event package name */
+ char *accept = get_header(req, "Accept");
if (p->initreq.headers) {
/* We already have a dialog */
@@ -10990,15 +11022,18 @@
/* Do not destroy session, since we will break the call if we do */
ast_log(LOG_DEBUG, "Got a subscription within the context of another call, can't handle that - %s (Method %s)\n", p->callid, sip_methods[p->initreq.method].text);
return 0;
- } else {
- if (debug)
+ } else if (debug) {
+ if (p->subscribed != NONE)
ast_log(LOG_DEBUG, "Got a re-subscribe on existing subscription %s\n", p->callid);
- }
- }
- if (!ignore && !p->initreq.headers) {
+ else
+ ast_log(LOG_DEBUG, "Got a new subscription %s (possibly with auth)\n", p->callid);
+ }
+ }
+ if (!ignore && !p->initreq.headers) { /* Set up dialog, new subscription */
/* Use this as the basis */
if (debug)
- ast_verbose("Using latest SUBSCRIBE request as basis request\n");
+ ast_verbose("Creating new subscription\n");
+
/* This call is no longer outgoing if it ever was */
ast_clear_flag(p, SIP_OUTGOING);
copy_request(&p->initreq, req);
@@ -11006,100 +11041,88 @@
} else if (debug && ignore)
ast_verbose("Ignoring this SUBSCRIBE request\n");
- if (!p->lastinvite) {
- char mailboxbuf[256]="";
- char *mailbox = NULL;
- int mailboxsize = 0;
-
- char *event = get_header(req, "Event"); /* Get Event package name */
- char *accept = get_header(req, "Accept");
-
- if (!strcmp(event, "message-summary") && !strcmp(accept, "application/simple-message-summary")) {
- mailbox = mailboxbuf;
- mailboxsize = sizeof(mailboxbuf);
- }
- /* Handle authentication if this is our first subscribe */
- res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, ignore, mailbox, mailboxsize);
- if (res) {
- if (res < 0) {
- ast_log(LOG_NOTICE, "Failed to authenticate user %s for SUBSCRIBE\n", get_header(req, "From"));
+
+
+ /* Handle authentication if this is our first subscribe */
+ res = check_user_full(p, req, SIP_SUBSCRIBE, e, 0, sin, ignore, &authpeer);
+ if (res) {
+ if (res < 0) {
+ ast_log(LOG_NOTICE, "Failed to authenticate user %s for SUBSCRIBE\n", get_header(req, "From"));
+ ast_set_flag(p, SIP_NEEDDESTROY);
+ }
+ return 0;
+ }
+
+ /* Initialize the context if it hasn't been already */
+ if (!ast_strlen_zero(p->subscribecontext))
+ ast_string_field_set(p, context, p->subscribecontext);
+ else if (ast_strlen_zero(p->context))
+ ast_string_field_set(p, context, default_context);
+
+ /* Get destination right away */
+ gotdest = get_destination(p, NULL);
+ build_contact(p);
+ if (gotdest) {
+ if (gotdest < 0)
+ transmit_response(p, "404 Not Found (gotdest)", req);
+ else
+ transmit_response(p, "484 Address Incomplete", req); /* Overlap dialing on SUBSCRIBE?? */
+ ast_set_flag(p, SIP_NEEDDESTROY);
+ return 0;
+ } else {
+
+ /* Initialize tag for new subscriptions */
+ if (ast_strlen_zero(p->tag))
+ make_our_tag(p->tag, sizeof(p->tag));
+
+ if (!strcmp(event, "presence") || !strcmp(event, "dialog")) { /* Presence, RFC 3842 */
+
+ /* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */
+ if (strstr(accept, "application/pidf+xml")) {
+ p->subscribed = PIDF_XML; /* RFC 3863 format */
+ } else if (strstr(accept, "application/dialog-info+xml")) {
+ p->subscribed = DIALOG_INFO_XML;
+ /* IETF draft: draft-ietf-sipping-dialog-package-05.txt */
+ } else if (strstr(accept, "application/cpim-pidf+xml")) {
+ p->subscribed = CPIM_PIDF_XML; /* RFC 3863 format */
+ } else if (strstr(accept, "application/xpidf+xml")) {
+ p->subscribed = XPIDF_XML; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */
+ } else if (strstr(p->useragent, "Polycom")) {
+ p->subscribed = XPIDF_XML; /* Polycoms subscribe for "event: dialog" but don't include an "accept:" header */
+ } else {
+ /* Can't find a format for events that we know about */
+ transmit_response(p, "489 Bad Event", req);
+ ast_set_flag(p, SIP_NEEDDESTROY);
+ return 0;
+ }
+ } else if (!strcmp(event, "message-summary") && !strcmp(accept, "application/simple-message-summary")) {
+ /* Looks like they actually want a mailbox status
+ This version of Asterisk supports mailbox subscriptions
+ The subscribed URI needs to exist in the dial plan
+ In most devices, this is configurable to the voicemailmain extension you use
+ */
+ if (!authpeer || ast_strlen_zero(authpeer->mailbox)) {
+ transmit_response(p, "404 Not found (no mailbox)", req);
ast_set_flag(p, SIP_NEEDDESTROY);
- }
- return 0;
- }
- /* Initialize the context if it hasn't been already */
- if (!ast_strlen_zero(p->subscribecontext))
- ast_string_field_set(p, context, p->subscribecontext);
- else if (ast_strlen_zero(p->context))
- ast_string_field_set(p, context, default_context);
- /* Get destination right away */
- gotdest = get_destination(p, NULL);
- build_contact(p);
- if (gotdest) {
- if (gotdest < 0)
- transmit_response(p, "404 Not Found", req);
- else
- transmit_response(p, "484 Address Incomplete", req); /* Overlap dialing on SUBSCRIBE?? */
- ast_set_flag(p, SIP_NEEDDESTROY);
- } else {
-
- /* Initialize tag for new subscriptions */
- if (ast_strlen_zero(p->tag))
- make_our_tag(p->tag, sizeof(p->tag));
-
- if (!strcmp(event, "presence") || !strcmp(event, "dialog")) { /* Presence, RFC 3842 */
-
- /* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */
- if (strstr(accept, "application/pidf+xml")) {
- p->subscribed = PIDF_XML; /* RFC 3863 format */
- } else if (strstr(accept, "application/dialog-info+xml")) {
- p->subscribed = DIALOG_INFO_XML;
- /* IETF draft: draft-ietf-sipping-dialog-package-05.txt */
- } else if (strstr(accept, "application/cpim-pidf+xml")) {
- p->subscribed = CPIM_PIDF_XML; /* RFC 3863 format */
- } else if (strstr(accept, "application/xpidf+xml")) {
- p->subscribed = XPIDF_XML; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */
- } else if (strstr(p->useragent, "Polycom")) {
- p->subscribed = XPIDF_XML; /* Polycoms subscribe for "event: dialog" but don't include an "accept:" header */
- } else {
- /* Can't find a format for events that we know about */
- transmit_response(p, "489 Bad Event", req);
- ast_set_flag(p, SIP_NEEDDESTROY);
- return 0;
- }
- } else if (!strcmp(event, "message-summary") && !strcmp(accept, "application/simple-message-summary")) {
- /* Looks like they actually want a mailbox status */
-
- /* At this point, we should check if they subscribe to a mailbox that
- has the same extension as the peer or the mailbox id. If we configure
- the context to be the same as a SIP domain, we could check mailbox
- context as well. To be able to securely accept subscribes on mailbox
- IDs, not extensions, we need to check the digest auth user to make
- sure that the user has access to the mailbox.
-
- Since we do not act on this subscribe anyway, we might as well
- accept any authenticated peer with a mailbox definition in their
- config section.
-
- */
- if (!ast_strlen_zero(mailbox)) {
- transmit_response(p, "200 OK", req);
- ast_set_flag(p, SIP_NEEDDESTROY);
- } else {
- transmit_response(p, "404 Not found", req);
- ast_set_flag(p, SIP_NEEDDESTROY);
- }
- return 0;
- } else { /* At this point, Asterisk does not understand the specified event */
- transmit_response(p, "489 Bad Event", req);
- if (option_debug > 1)
- ast_log(LOG_DEBUG, "Received SIP subscribe for unknown event package: %s\n", event);
- ast_set_flag(p, SIP_NEEDDESTROY);
+ ast_log(LOG_NOTICE, "Received SIP subscribe for peer without mailbox: %s\n", authpeer->name);
return 0;
}
- if (p->subscribed != NONE)
- p->stateid = ast_extension_state_add(p->context, p->exten, cb_extensionstate, p);
- }
+
+ p->subscribed = MWI_NOTIFICATION;
+ if (authpeer->mwipvt && authpeer->mwipvt != p) /* Destroy old PVT if this is a new one */
+ /* We only allow one subscription per peer */
+ sip_destroy(authpeer->mwipvt);
+ authpeer->mwipvt = p; /* Link from peer to pvt */
+ p->relatedpeer = authpeer; /* Link from pvt to peer */
+ } else { /* At this point, Asterisk does not understand the specified event */
+ transmit_response(p, "489 Bad Event", req);
+ if (option_debug > 1)
+ ast_log(LOG_DEBUG, "Received SIP subscribe for unknown event package: %s\n", event);
+ ast_set_flag(p, SIP_NEEDDESTROY);
+ return 0;
+ }
+ if (p->subscribed != MWI_NOTIFICATION)
+ p->stateid = ast_extension_state_add(p->context, p->exten, cb_extensionstate, p);
}
if (!ignore && p)
@@ -11113,54 +11136,69 @@
if (p->expiry < min_expiry && p->expiry > 0)
p->expiry = min_expiry;
- if (sipdebug || option_debug > 1)
- ast_log(LOG_DEBUG, "Adding subscription for extension %s context %s for peer %s\n", p->exten, p->context, p->username);
+ if (sipdebug || option_debug > 1) {
+ if (p->subscribed == MWI_NOTIFICATION && p->relatedpeer)
+ ast_log(LOG_DEBUG, "Adding subscription for mailbox notification - peer %s Mailbox %s\n", p->relatedpeer->name, p->relatedpeer->mailbox);
+ else
+ ast_log(LOG_DEBUG, "Adding subscription for extension %s context %s for peer %s\n", p->exten, p->context, p->username);
+ }
if (p->autokillid > -1)
sip_cancel_destroy(p); /* Remove subscription expiry for renewals */
if (p->expiry > 0)
sip_scheddestroy(p, (p->expiry + 10) * 1000); /* Set timer for destruction of call at expiration */
- if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) {
- ast_log(LOG_ERROR, "Got SUBSCRIBE for extensions without hint. Please add hint to %s in context %s\n", p->exten, p->context);
- transmit_response(p, "404 Not found", req);
- ast_set_flag(p, SIP_NEEDDESTROY);
- return 0;
+ if (p->subscribed == MWI_NOTIFICATION) {
+ transmit_response(p, "200 OK", req);
+ if (p->relatedpeer) { /* Send first notification */
+ ASTOBJ_WRLOCK(p->relatedpeer);
+ sip_send_mwi_to_peer(p->relatedpeer);
+ ASTOBJ_UNLOCK(p->relatedpeer);
+ }
} else {
- struct sip_pvt *p_old;
-
- transmit_response(p, "200 OK", req);
- transmit_state_notify(p, firststate, 1); /* Send first notification */
- append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate));
-
- /* remove any old subscription from this peer for the same exten/context,
- as the peer has obviously forgotten about it and it's wasteful to wait
- for it to expire and send NOTIFY messages to the peer only to have them
- ignored (or generate errors)
- */
- ast_mutex_lock(&iflock);
- for (p_old = iflist; p_old; p_old = p_old->next) {
- if (p_old == p)
- continue;
- if (p_old->initreq.method != SIP_SUBSCRIBE)
- continue;
- if (p_old->subscribed == NONE)
- continue;
- ast_mutex_lock(&p_old->lock);
- if (!strcmp(p_old->username, p->username)) {
- if (!strcmp(p_old->exten, p->exten) &&
- !strcmp(p_old->context, p->context)) {
- ast_set_flag(p_old, SIP_NEEDDESTROY);
- ast_mutex_unlock(&p_old->lock);
- break;
+ if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) {
+ ast_log(LOG_ERROR, "Got SUBSCRIBE for extensions without hint. Please add hint to %s in context %s\n", p->exten, p->context);
+ transmit_response(p, "404 Not found", req);
+ ast_set_flag(p, SIP_NEEDDESTROY);
+ return 0;
+ } else {
+ struct sip_pvt *p_old;
+
+ transmit_response(p, "200 OK", req);
+ transmit_state_notify(p, firststate, 1); /* Send first notification */
+ append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate));
+
+ /* remove any old subscription from this peer for the same exten/context,
+ as the peer has obviously forgotten about it and it's wasteful to wait
+ for it to expire and send NOTIFY messages to the peer only to have them
+ ignored (or generate errors)
+ */
+ ast_mutex_lock(&iflock);
+ for (p_old = iflist; p_old; p_old = p_old->next) {
+ if (p_old == p)
+ continue;
+ if (p_old->initreq.method != SIP_SUBSCRIBE)
+ continue;
+ if (p_old->subscribed == NONE)
+ continue;
+ ast_mutex_lock(&p_old->lock);
+ if (!strcmp(p_old->username, p->username)) {
+ if (!strcmp(p_old->exten, p->exten) &&
+ !strcmp(p_old->context, p->context)) {
+ ast_set_flag(p_old, SIP_NEEDDESTROY);
+ ast_mutex_unlock(&p_old->lock);
+ break;
+ }
}
+ ast_mutex_unlock(&p_old->lock);
}
- ast_mutex_unlock(&p_old->lock);
+ ast_mutex_unlock(&iflock);
}
- ast_mutex_unlock(&iflock);
}
if (!p->expiry)
ast_set_flag(p, SIP_NEEDDESTROY);
}
+ if (authpeer)
+ ASTOBJ_UNREF(authpeer, sip_destroy_peer);
return 1;
}
@@ -11492,26 +11530,52 @@
return 0;
}
- if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY)))
- return -1;
peer->lastmsgssent = ((newmsgs << 8) | (oldmsgs));
- if (create_addr_from_peer(p, peer)) {
- /* Maybe they're not registered, etc. */
- sip_destroy(p);
- return 0;
- }
- /* Recalculate our side, and recalculate Call ID */
- if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip))
- memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
- build_via(p);
- build_callid_pvt(p);
+
+ if (peer->mwipvt) {
+ /* Base message on subscription */
+ p = peer->mwipvt;
+ } else {
+ /* Build temporary dialog for this message */
+ if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY)))
+ return -1;
+ if (create_addr_from_peer(p, peer)) {
+ /* Maybe they're not registered, etc. */
+ sip_destroy(p);
+ return 0;
+ }
+ /* Recalculate our side, and recalculate Call ID */
+ if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
+ memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
+ build_via(p);
+ build_callid_pvt(p);
+ /* Destroy this session after 32 secs */
+ sip_scheddestroy(p, 32000);
+ }
/* Send MWI */
ast_set_flag(p, SIP_OUTGOING);
transmit_notify_with_mwi(p, newmsgs, oldmsgs, peer->vmexten);
- sip_scheddestroy(p, 15000);
return 0;
}
+
+/*! \brief Check whether peer needs a new MWI notification check */
+static int does_peer_need_mwi(struct sip_peer *peer) {
+ time_t t;
+
+ if(ast_test_flag((&peer->flags_page2), SIP_PAGE2_SUBSCRIBEMWIONLY) && !peer->mwipvt) { /* We don't have a subscription */
+ time(&peer->lastmsgcheck); /* Reset timer */
+ return FALSE;
+ }
+
+ time(&t);
+
+ if (!ast_strlen_zero(peer->mailbox) && ((t - peer->lastmsgcheck) > global_mwitime))
+ return TRUE;
+
+ return FALSE;
+}
+
/*! \brief The SIP monitoring thread
\note This thread monitors all the SIP sessions and peers that needs notification of mwi
@@ -11615,7 +11679,7 @@
curpeernum = 0;
peer = NULL;
ASTOBJ_CONTAINER_TRAVERSE(&peerl, !peer, do {
- if ((curpeernum > lastpeernum) && !ast_strlen_zero(iterator->mailbox) && ((t - iterator->lastmsgcheck) > global_mwitime)) {
+ if ((curpeernum > lastpeernum) && does_peer_need_mwi(iterator)) {
fastrestart = TRUE;
lastpeernum = curpeernum;
peer = ASTOBJ_REF(iterator);
@@ -11737,7 +11801,7 @@
if (peer->pokeexpire > -1)
ast_sched_del(sched, peer->pokeexpire);
- p->peerpoke = peer;
+ p->relatedpeer = peer;
ast_set_flag(p, SIP_OUTGOING);
#ifdef VOCAL_DATA_HACK
ast_copy_string(p->username, "__VOCAL_DATA_SHOULD_READ_THE_SIP_SPEC__", sizeof(p->username));
@@ -12493,6 +12557,9 @@
ast_copy_string(peer->musicclass, v->value, sizeof(peer->musicclass));
} else if (!strcasecmp(v->name, "mailbox")) {
ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
+ } else if (!strcasecmp(v->name, "subscribemwi")) {
+ if (ast_true(v->value))
+ ast_set_flag((&peer->flags_page2), SIP_PAGE2_SUBSCRIBEMWIONLY);
} else if (!strcasecmp(v->name, "vmexten")) {
ast_copy_string(peer->vmexten, v->value, sizeof(peer->vmexten));
} else if (!strcasecmp(v->name, "callgroup")) {
More information about the asterisk-commits
mailing list