[asterisk-commits] branch oej/subscribemwi-1.2 r11377 - in
/team/oej/subscribemwi-1.2: ./ channels/
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Tue Feb 28 09:34:16 MST 2006
Author: oej
Date: Tue Feb 28 10:34:14 2006
New Revision: 11377
URL: http://svn.digium.com/view/asterisk?rev=11377&view=rev
Log:
Fixes for backporting the subscribemwi branch to 1.2
Modified:
team/oej/subscribemwi-1.2/ (props changed)
team/oej/subscribemwi-1.2/channels/chan_sip.c
Propchange: team/oej/subscribemwi-1.2/
------------------------------------------------------------------------------
svnmerge-integrated = /branches/1.2:1-11374
Modified: team/oej/subscribemwi-1.2/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/subscribemwi-1.2/channels/chan_sip.c?rev=11377&r1=11376&r2=11377&view=diff
==============================================================================
--- team/oej/subscribemwi-1.2/channels/chan_sip.c (original)
+++ team/oej/subscribemwi-1.2/channels/chan_sip.c Tue Feb 28 10:34:14 2006
@@ -161,7 +161,8 @@
XPIDF_XML,
DIALOG_INFO_XML,
CPIM_PIDF_XML,
- PIDF_XML
+ PIDF_XML,
+ MWI_NOTIFICATION
};
static const struct cfsubscription_types {
@@ -175,7 +176,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 {
@@ -574,6 +576,7 @@
#define SIP_PAGE2_RTAUTOCLEAR (1 << 2)
#define SIP_PAGE2_IGNOREREGEXPIRE (1 << 3)
#define SIP_PAGE2_RT_FROMCONTACT (1 << 4)
+#define SIP_PAGE2_SUBSCRIBEMWIONLY (1 << 9)
/* SIP packet flags */
#define SIP_PKT_DEBUG (1 << 0) /*!< Debug this packet */
@@ -681,7 +684,7 @@
struct ast_dsp *vad; /*!< Voice Activation Detection dsp */
- struct sip_peer *peerpoke; /*!< If this calls is to poke a peer, which one */
+ struct sip_peer *relatedpeer; /*!< If this calls is to poke a peer, which one */
struct sip_registry *registry; /*!< If this is a REGISTER call, to which registry */
struct ast_rtp *rtp; /*!< RTP Session */
struct ast_rtp *vrtp; /*!< Video RTP session */
@@ -792,6 +795,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 */
int lastmsg;
};
@@ -891,6 +895,8 @@
static int transmit_refer(struct sip_pvt *p, const char *dest);
static int sip_sipredirect(struct sip_pvt *p, const char *dest);
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);
static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader, int sipmethod, int init);
static void free_old_route(struct sip_route *route);
static int build_reply_digest(struct sip_pvt *p, int method, char *digest, int digest_len);
@@ -1631,6 +1637,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;
@@ -2101,6 +2112,10 @@
if (sip_debug_test_pvt(p))
ast_verbose("Destroying call '%s'\n", p->callid);
+
+ /* 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);
@@ -5050,7 +5065,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");
@@ -5131,6 +5145,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 : global_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");
@@ -6404,7 +6424,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;
}
@@ -6929,7 +6950,7 @@
/*! \brief check_user_full: Check if matching user or peer is defined ---*/
/* Match user on From: user name and peer on IP/port */
/* This is used on first invite (not re-invites) and subscribe requests */
-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;
@@ -6992,7 +7013,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 */
@@ -7064,7 +7085,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);
}
@@ -7086,6 +7107,7 @@
if (peer) {
if (debug)
ast_verbose("Found peer '%s'\n", peer->name);
+
/* Take the peer */
ast_copy_flags(p, peer, SIP_FLAGS_TO_COPY);
@@ -7135,8 +7157,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_copy_string(p->username, peer->username, sizeof(p->username));
/* Use the default username for authentication on outbound calls */
@@ -7194,7 +7218,7 @@
/*! \brief check_user: Find user ---*/
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_msg_text: Get text out of a SIP MESSAGE packet ---*/
@@ -8257,7 +8281,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;
@@ -8269,8 +8293,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),
@@ -8287,7 +8311,7 @@
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));
+ subscription_type2str(cur->subscribed), "");
numchans++;
}
cur = cur->next;
@@ -9687,7 +9711,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)
@@ -9764,7 +9788,7 @@
if (ast_strlen_zero(p->theirtag) || (resp >= 200)) {
gettag(req, "To", p->theirtag, sizeof(p->theirtag));
}
- 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" */
@@ -10646,12 +10670,17 @@
}
return 1;
}
-/*! \brief handle_request_subscribe: Handle incoming SUBSCRIBE request ---*/
+
+
+/*! \brief handle_request_subscribe: Handle incoming SUBSCRIBE request */
static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, int debug, int ignore, struct sockaddr_in *sin, int seqno, char *e)
{
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 */
@@ -10662,15 +10691,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);
@@ -10678,105 +10710,88 @@
} else if (debug && ignore)
ast_verbose("Ignoring this SUBSCRIBE request\n");
- if (!p->lastinvite) {
- char mailboxbuf[256]="";
- int found = 0;
- 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_copy_string(p->context, p->subscribecontext, sizeof(p->context));
+ else if (ast_strlen_zero(p->context))
+ ast_copy_string(p->context, default_context, sizeof(p->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_copy_string(p->context, p->subscribecontext, sizeof(p->context));
- else if (ast_strlen_zero(p->context))
- strcpy(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)) {
- found++;
- }
-
- if (found){
- 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)
@@ -10784,61 +10799,75 @@
if (p && !ast_test_flag(p, SIP_NEEDDESTROY)) {
p->expiry = atoi(get_header(req, "Expires"));
- /* The next 4 lines can be removed if the SNOM Expires bug is fixed */
- if (p->subscribed == DIALOG_INFO_XML) {
- if (p->expiry > max_expiry)
- p->expiry = max_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);
+ /* check if the requested expiry-time is within the approved limits from sip.conf */
+ if (p->expiry > max_expiry)
+ p->expiry = max_expiry;
+
+ 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 */
- 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->expiry > 0)
+ sip_scheddestroy(p, (p->expiry + 10) * 1000); /* Set timer for destruction of call at expiration */
+
+ 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, 1); /* Send first notification */
- append_history(p, "Subscribestatus", 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, 1); /* Send first notification */
+ append_history(p, "Subscribestatus", 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;
}
-
/*! \brief handle_request_register: Handle incoming REGISTER request ---*/
static int handle_request_register(struct sip_pvt *p, struct sip_request *req, int debug, int ignore, struct sockaddr_in *sin, char *e)
{
@@ -11168,26 +11197,48 @@
return 0;
}
- p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
- if (!p) {
- ast_log(LOG_WARNING, "Unable to build sip pvt data for MWI\n");
- 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, p->via, sizeof(p->via));
- build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
+ if (peer->mwipvt) {
+ p = peer->mwipvt;
+ } else {
+ p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY);
+ if (!p) {
+ ast_log(LOG_WARNING, "Unable to build sip pvt data for MWI\n");
+ 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, p->via, sizeof(p->via));
+ build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
+ sip_scheddestroy(p, 15000);
+ }
+
/* 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 0;
+ }
+
+ time(&t);
+
+ if (!ast_strlen_zero(peer->mailbox) && ((t - peer->lastmsgcheck) > global_mwitime))
+ return 1;
+
return 0;
}
@@ -11300,7 +11351,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 = 1;
lastpeernum = curpeernum;
peer = ASTOBJ_REF(iterator);
@@ -11421,7 +11472,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));
@@ -12183,6 +12234,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