Index: pbx.c
===================================================================
RCS file: /usr/cvsroot/asterisk/pbx.c,v
retrieving revision 1.246
diff -u -r1.246 pbx.c
--- pbx.c 26 May 2005 15:50:50 -0000 1.246
+++ pbx.c 31 May 2005 12:06:00 -0000
@@ -1737,6 +1737,8 @@
int res = -1;
int allunavailable = 1, allbusy = 1, allfree = 1;
int busy = 0;
+ int inuse = 0;
+ int ring = 0;
if (!e)
return -1;
@@ -1758,7 +1760,15 @@
allbusy = 0;
break;
case AST_DEVICE_INUSE:
- return AST_EXTENSION_INUSE;
+ inuse = 1;
+ allunavailable = 0;
+ allfree = 0;
+ break;
+ case AST_DEVICE_RINGING:
+ ring = 1;
+ allunavailable = 0;
+ allfree = 0;
+ break;
case AST_DEVICE_BUSY:
allunavailable = 0;
allfree = 0;
@@ -1777,7 +1787,13 @@
cur = rest;
} while (cur);
- if (allfree)
+ if (!inuse && ring) {
+ return AST_EXTENSION_RINGING;}
+ if (inuse && ring) {
+ return AST_EXTENSION_RINGING_AND_INUSE;}
+ if (inuse)
+ return AST_EXTENSION_INUSE;
+ if (allfree)
return AST_EXTENSION_NOT_INUSE;
if (allbusy)
return AST_EXTENSION_BUSY;
Index: channels/chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.747
diff -u -r1.747 chan_sip.c
--- channels/chan_sip.c 30 May 2005 13:51:04 -0000 1.747
+++ channels/chan_sip.c 31 May 2005 12:06:02 -0000
@@ -185,9 +185,10 @@
static char default_useragent[AST_MAX_EXTENSION] = DEFAULT_USERAGENT;
#define DEFAULT_CONTEXT "default"
-static char default_context[AST_MAX_EXTENSION] = DEFAULT_CONTEXT;
+static char default_context[AST_MAX_EXTENSION]; /* Default context for calls */
+static char default_subscribecontext[AST_MAX_EXTENSION]; /* Default context for subscriptions */
-static char default_language[MAX_LANGUAGE] = "";
+static char default_language[MAX_LANGUAGE] = ""; /* Default language */
#define DEFAULT_CALLERID "asterisk"
static char default_callerid[AST_MAX_EXTENSION] = DEFAULT_CALLERID;
@@ -197,6 +198,7 @@
#define DEFAULT_NOTIFYMIME "application/simple-message-summary"
static char default_notifymime[AST_MAX_EXTENSION] = DEFAULT_NOTIFYMIME;
+static int global_notifyringing = 1;
static int default_qualify = 0; /* Default Qualify= setting */
@@ -427,6 +429,7 @@
char from[256]; /* The From: header */
char useragent[256]; /* User agent in SIP request */
char context[AST_MAX_EXTENSION]; /* Context for this call */
+ char subscribecontext[AST_MAX_EXTENSION]; /* SubscribeContext for this call */
char fromdomain[MAXHOSTNAMELEN]; /* Domain to show in the from field */
char fromuser[AST_MAX_EXTENSION]; /* User to show in the user field */
char fromname[AST_MAX_EXTENSION]; /* Name to show in the user field */
@@ -474,7 +477,8 @@
int rtpkeepalive; /* Send RTP packets for keepalive */
int subscribed; /* Is this call a subscription? */
- int stateid;
+ int stateid; /* State ID */
+ int laststate; /* Last Known State */
int dialogver;
struct ast_dsp *vad; /* Voice Activation Detection dsp */
@@ -541,6 +545,7 @@
char md5secret[80]; /* Password in MD5 */
struct sip_auth *auth; /* Realm authentication list */
char context[AST_MAX_EXTENSION]; /* Default context for incoming calls */
+ char subscribecontext[AST_MAX_EXTENSION]; /* Context for subscriptions */
char username[80]; /* Temporary username until registration */
char accountcode[AST_MAX_ACCOUNT_CODE]; /* Account code */
int amaflags; /* AMA Flags (for billing) */
@@ -557,6 +562,7 @@
int outUse; /* disabled */
int outgoinglimit; /* disabled */
char mailbox[AST_MAX_EXTENSION]; /* Mailbox setting for MWI checks */
+ char mailbox_exten[AST_MAX_EXTENSION]; /* Message-Account for MWI notifies */
char language[MAX_LANGUAGE]; /* Default language for prompts */
char musicclass[MAX_LANGUAGE]; /* Music on Hold class */
char useragent[256]; /* User agent in SIP request (saved from registration) */
@@ -669,6 +675,7 @@
static struct sip_auth *authl; /* Authentication list */
+static void append_date(struct sip_request *req);
static struct ast_frame *sip_read(struct ast_channel *ast);
static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req);
static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
@@ -1444,8 +1451,6 @@
tmp = tmp->next;
}
-
-
user = build_user(username, var, !ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS));
if (!user) { /* No user found */
@@ -1456,8 +1461,8 @@
if (ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS)) {
ast_set_flag((&user->flags_page2), SIP_PAGE2_RTCACHEFRIENDS);
suserobjs++;
- ASTOBJ_CONTAINER_LINK(&userl,user);
- } else {
+ ASTOBJ_CONTAINER_LINK(&userl,user);
+ } else {
/* Move counter from s to r... */
suserobjs--;
ruserobjs++;
@@ -3571,7 +3576,7 @@
snprintf(p->lastmsg, sizeof(p->lastmsg), "Tx: %s", sip_methods[sipmethod].text);
- if (!seqno) {
+ if (!seqno) { /* Raise our CSEQ */
p->ocseq++;
seqno = p->ocseq;
}
@@ -3584,7 +3589,7 @@
c = p->initreq.rlPart2; /* Use original URI */
} else if (sipmethod == SIP_ACK) {
/* Use URI from Contact: in 200 OK (if INVITE)
- (we only have the contacturi on INVITEs) */
+ (we only have the contacturi on INVITEs) */
if (!ast_strlen_zero(p->okcontacturi))
c = p->okcontacturi;
else
@@ -3646,8 +3651,16 @@
add_header(req, "From", ot);
add_header(req, "To", of);
}
- add_header(req, "Contact", p->our_contact);
+ if (sipmethod == SIP_MESSAGE) {
+ /* Add date header to MESSAGE */
+ append_date(req);
+ } else {
+ /* Do not add Contact on MESSAGE */
+ add_header(req, "Contact", p->our_contact);
+ }
copy_header(req, orig, "Call-ID");
+
+ snprintf(tmp, sizeof(tmp), "%d %s", seqno, sip_methods[sipmethod].text);
add_header(req, "CSeq", tmp);
add_header(req, "User-Agent", default_useragent);
@@ -4326,10 +4339,35 @@
int maxbytes = 0;
int bytes = 0;
char from[256], to[256];
- char *t, *c, *a;
+ char *t = NULL, *c, *a;
char *mfrom, *mto;
struct sip_request req;
char clen[20];
+ char hint[AST_MAX_EXTENSION];
+ int hintstate = 1;
+ char *statestring;
+ int local_state;
+
+ switch(state) {
+ case AST_EXTENSION_RINGING_AND_INUSE:
+ if (global_notifyringing) {
+ statestring = "early";
+ } else {
+ statestring = "confirmed";
+ }
+ break;
+ case AST_EXTENSION_RINGING:
+ statestring = "early";
+ break;
+ case AST_EXTENSION_INUSE:
+ case AST_EXTENSION_BUSY:
+ case AST_EXTENSION_UNAVAILABLE:
+ statestring = "confirmed";
+ break;
+ case AST_EXTENSION_NOT_INUSE:
+ default:
+ statestring = "terminated";
+ }
memset(from, 0, sizeof(from));
memset(to, 0, sizeof(to));
@@ -4347,30 +4385,39 @@
reqprep(&req, p, SIP_NOTIFY, 0, 1);
- if (p->subscribed == 1) {
- ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to));
+ /* Check which device/devices we are watching and if they are registred */
+ /* If they are not registred, we will override notification and show no availability */
+ if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten)) {
+ if(ast_device_state(hint) == AST_DEVICE_UNAVAILABLE)
+ hintstate = 0; /* Not registred */
+ }
+
+ ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to));
+ c = ditch_braces(to);
+ if (strncmp(c, "sip:", 4)) {
+ ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c);
+ return -1;
+ }
+ if ((a = strchr(c, ';'))) {
+ *a = '\0';
+ }
+ mto = c;
- c = ditch_braces(to);
- if (strncmp(c, "sip:", 4)) {
- ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c);
- return -1;
- }
- if ((a = strchr(c, ';'))) {
- *a = '\0';
- }
- mto = c;
+ if ((state==AST_EXTENSION_UNAVAILABLE) || (state==AST_EXTENSION_BUSY) || !hintstate)
+ local_state = 2; /* Closed */
+ else if (state==AST_EXTENSION_INUSE || state==AST_EXTENSION_RINGING || state==AST_EXTENSION_RINGING_AND_INUSE)
+ local_state = 1; /* In use */
+ else
+ local_state = 0; /* Open */
+
+ if (sipdebug)
+ ast_log(LOG_NOTICE, "Extension %s@%s Status %d\n", p->exten, p->context, state);
+ if (p->subscribed == 1 || p->subscribed == 3) {
add_header(&req, "Event", "presence");
add_header(&req, "Subscription-State", "active");
add_header(&req, "Content-Type", "application/xpidf+xml");
- if ((state==AST_EXTENSION_UNAVAILABLE) || (state==AST_EXTENSION_BUSY))
- state = 2;
- else if (state==AST_EXTENSION_INUSE)
- state = 1;
- else
- state = 0;
-
t = tmp;
maxbytes = sizeof(tmp);
bytes = snprintf(t, maxbytes, "\n");
@@ -4391,14 +4438,48 @@
bytes = snprintf(t, maxbytes, "
\n", mto);
t += bytes;
maxbytes -= bytes;
- bytes = snprintf(t, maxbytes, "\n", !state ? "open" : (state==1) ? "inuse" : "closed");
+ bytes = snprintf(t, maxbytes, "\n", !local_state ? "open" : (local_state==1) ? "inuse" : "closed");
t += bytes;
maxbytes -= bytes;
- bytes = snprintf(t, maxbytes, "\n", !state ? "online" : (state==1) ? "onthephone" : "offline");
+ bytes = snprintf(t, maxbytes, "\n", !local_state ? "online" : (local_state==1) ? "onthephone" : "offline");
t += bytes;
maxbytes -= bytes;
bytes = snprintf(t, maxbytes, "\n\n\n");
- } else {
+ } else if (p->subscribed == 4) { /* pidf+xml */
+ add_header(&req, "Event", "presence");
+ add_header(&req, "Subscription-State", "active");
+ add_header(&req, "Content-Type", "application/pidf+xml");
+ t = tmp;
+ maxbytes = sizeof(tmp);
+ bytes = snprintf(t, maxbytes, "\n");
+ t += bytes;
+ maxbytes -= bytes;
+ bytes = snprintf(t, maxbytes, "\n", mfrom);
+ t += bytes;
+ maxbytes -= bytes;
+ bytes = snprintf(t, maxbytes, "\n", p->exten);
+ t += bytes;
+ maxbytes -= bytes;
+ bytes = snprintf(t, maxbytes, "%s\n", mto);
+ t += bytes;
+ maxbytes -= bytes;
+
+ bytes = snprintf(t, maxbytes, "%s\n", !local_state ? "open" : "closed");
+ t += bytes;
+ maxbytes -= bytes;
+
+ bytes = snprintf(t, maxbytes, "%s", local_state != 0?"on-the-phone\n":"");
+ t += bytes;
+ maxbytes -= bytes;
+
+ bytes = snprintf(t, maxbytes, "%s", local_state == 1?"On the phone\n":"");
+ t += bytes;
+ maxbytes -= bytes;
+
+ bytes = snprintf(t, maxbytes, "\n\n");
+ t += bytes;
+ maxbytes -= bytes;
+ } else if (p->subscribed == 2) {
add_header(&req, "Event", "dialog");
add_header(&req, "Content-Type", "application/dialog-info+xml");
@@ -4407,16 +4488,22 @@
bytes = snprintf(t, maxbytes, "\n");
t += bytes;
maxbytes -= bytes;
- bytes = snprintf(t, maxbytes, "\n", p->dialogver++, full ? "full":"partial", mfrom);
+ bytes = snprintf(t, maxbytes, "\n", p->dialogver++, full ? "full":"partial", mto);
t += bytes;
maxbytes -= bytes;
- bytes = snprintf(t, maxbytes, "\n");
+ t += bytes;
+ maxbytes -= bytes;
}
if (t > tmp + sizeof(tmp))
ast_log(LOG_WARNING, "Buffer overflow detected!! (Please file a bug report)\n");
@@ -4434,22 +4521,25 @@
* We use the SIP Event package message-summary
* MIME type defaults to "application/simple-message-summary";
*/
-static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs)
+static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs, char *mailbox_exten)
{
struct sip_request req;
char tmp[256];
char tmp2[256];
+ char tmp3[256];
char clen[20];
initreqprep(&req, p, SIP_NOTIFY, NULL);
add_header(&req, "Event", "message-summary");
add_header(&req, "Content-Type", default_notifymime);
- snprintf(tmp, sizeof(tmp), "Messages-Waiting: %s\r\n", newmsgs ? "yes" : "no");
- snprintf(tmp2, sizeof(tmp2), "Voice-Message: %d/%d\r\n", newmsgs, oldmsgs);
- snprintf(clen, sizeof(clen), "%d", (int)(strlen(tmp) + strlen(tmp2)));
+ snprintf(tmp, sizeof(tmp), "Message-Account: sip:%s@%s\r\n", (mailbox_exten && !ast_strlen_zero(mailbox_exten)) ? mailbox_exten : default_callerid, p->fromdomain);
+ snprintf(tmp2, sizeof(tmp2), "Messages-Waiting: %s\r\n", newmsgs ? "yes" : "no");
+ snprintf(tmp3, sizeof(tmp3), "Voice-Message: %d/%d\r\n", newmsgs, oldmsgs);
+ snprintf(clen, sizeof(clen), "%d", (int)(strlen(tmp) + strlen(tmp2) + strlen(tmp3)));
add_header(&req, "Content-Length", clen);
add_line(&req, tmp);
add_line(&req, tmp2);
+ add_line(&req, tmp3);
if (!p->initreq.headers) {
/* Use this as the basis */
@@ -4867,7 +4957,7 @@
manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
register_peer_exten(peer, 0);
peer->expire = -1;
- ast_device_state_changed("SIP/%s", peer->name);
+ ast_device_state_changed("SIP/%s", peer->name); /* Activate notification */
if (ast_test_flag(peer, SIP_SELFDESTRUCT) || ast_test_flag((&peer->flags_page2), SIP_PAGE2_RTAUTOCLEAR)) {
peer = ASTOBJ_CONTAINER_UNLINK(&peerl, peer);
ASTOBJ_UNREF(peer, sip_destroy_peer);
@@ -5301,7 +5391,7 @@
#endif
)
return 0;
- if (sipmethod == SIP_REGISTER) {
+ if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) {
/* On a REGISTER, we have to use 401 and its family of headers instead of 407 and its family
of headers -- GO SIP! Whoo hoo! Two things that do the same thing but are used in
different circumstances! What a surprise. */
@@ -5427,10 +5517,12 @@
return res;
}
-/*--- cb_extensionstate: Part of thte SUBSCRIBE support subsystem ---*/
+/*--- cb_extensionstate: Callback for the SUBSCRIBE (devicestate notification) support subsystem ---*/
+/* If you add an "hint" priority to the dial plan, you will get notifications
+ */
static int cb_extensionstate(char *context, char* exten, int state, void *data)
{
- struct sip_pvt *p = data;
+ struct sip_pvt *p = data; /* Pointer to the subscription "call" */
if (state == -1) {
sip_scheddestroy(p, 15000);
p->stateid = -1;
@@ -5438,6 +5530,7 @@
}
transmit_state_notify(p, state, 1);
+ p->laststate = state;
if (option_debug > 1)
ast_verbose(VERBOSE_PREFIX_1 "Extension Changed %s new state %d for Notify User %s\n", exten, state, p->username);
@@ -5522,7 +5615,7 @@
}
}
if (!res) {
- ast_device_state_changed("SIP/%s", peer->name);
+ ast_device_state_changed("SIP/%s", peer->name); /* Activate notification */
}
if (res < 0)
transmit_response(p, "403 Forbidden", &p->initreq);
@@ -6179,6 +6272,8 @@
ast_copy_string(p->fullcontact, peer->fullcontact, sizeof(p->fullcontact));
if (!ast_strlen_zero(peer->context))
ast_copy_string(p->context, peer->context, sizeof(p->context));
+ if (!ast_strlen_zero(peer->subscribecontext))
+ ast_copy_string(p->subscribecontext, peer->subscribecontext, sizeof(p->subscribecontext));
ast_copy_string(p->peersecret, peer->secret, sizeof(p->peersecret));
ast_copy_string(p->peermd5secret, peer->md5secret, sizeof(p->peermd5secret));
ast_copy_string(p->language, peer->language, sizeof(p->language) -1);
@@ -6247,14 +6342,26 @@
/*--- receive_message: Receive SIP MESSAGE method messages ---*/
-/* we handle messages within current calls currently */
+/* We only handle messages within current calls currently */
+/* Reference: RFC 3428 */
static void receive_message(struct sip_pvt *p, struct sip_request *req)
{
char buf[1024];
struct ast_frame f;
+ char *content_type;
+ content_type = get_header(req, "Content-Type");
+
+ if (strcmp(content_type, "text/plain")) {
+ /* No text/plain attachment */
+ transmit_response(p, "415 unsupported media type", req); /* Good enough or? */
+ ast_set_flag(p, SIP_NEEDDESTROY);
+ return;
+ }
if (get_msg_text(buf, sizeof(buf), req)) {
ast_log(LOG_WARNING, "Unable to retrieve text from %s\n", p->callid);
+ transmit_response(p, "202 Accepted", req);
+ ast_set_flag(p, SIP_NEEDDESTROY);
return;
}
if (p->owner) {
@@ -6267,7 +6374,15 @@
f.data = buf;
f.datalen = strlen(buf);
ast_queue_frame(p->owner, &f);
+ /* Should we respond somehow? */
+ transmit_response(p, "202 Accepted", req);
+ /* We should respond 202 accepted, since we relay the message */
+ } else {
+ ast_log(LOG_WARNING,"Received message to %s from %s, dropped it...\n Content-Type:%s\n Message: %s\n", get_header(req,"To"), get_header(req,"From"), content_type, buf);
+ transmit_response(p, "405 Method not allowed", req); /* Good enough or? */
}
+ ast_set_flag(p, SIP_NEEDDESTROY);
+ return;
}
/*--- sip_show_inuse: CLI Command to show calls within limits set by
@@ -7126,7 +7241,8 @@
static int __sip_show_channels(int fd, int argc, char *argv[], int subscriptions)
{
-#define FORMAT3 "%-15.15s %-10.10s %-21.21s %-15.15s\n"
+#define FORMAT4 "%-15.15s %-10.10s %-21.21s %-15.15s %10s\n"
+#define FORMAT3 "%-15.15s %-10.10s %-21.21s %-15.15s %2d (%d)\n"
#define FORMAT2 "%-15.15s %-10.10s %-11.11s %-11.11s %s %s\n"
#define FORMAT "%-15.15s %-10.10s %-11.11s %5.5d/%5.5d %-6.6s%s %s\n"
struct sip_pvt *cur;
@@ -7139,7 +7255,7 @@
if (!subscriptions)
ast_cli(fd, FORMAT2, "Peer", "User/ANR", "Call ID", "Seq (Tx/Rx)", "Format", "Last Msg");
else
- ast_cli(fd, FORMAT3, "Peer", "User", "Call ID", "URI");
+ ast_cli(fd, FORMAT4, "Peer", "User", "Call ID", "Extension", "Last State");
while (cur) {
if (!cur->subscribed && !subscriptions) {
ast_cli(fd, FORMAT, ast_inet_ntoa(iabuf, sizeof(iabuf), cur->sa.sin_addr),
@@ -7152,11 +7268,11 @@
numchans++;
}
if (cur->subscribed && subscriptions) {
- ast_cli(fd, FORMAT3, ast_inet_ntoa(iabuf, sizeof(iabuf), cur->sa.sin_addr),
+ 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->uri);
-
- }
+ cur->callid, cur->exten, cur->laststate, cur->subscribed);
+ numchans++;
+ }
cur = cur->next;
}
ast_mutex_unlock(&iflock);
@@ -7168,6 +7284,7 @@
#undef FORMAT
#undef FORMAT2
#undef FORMAT3
+#undef FORMAT4
}
/*--- complete_sipch: Support routine for 'sip show channel' CLI ---*/
@@ -8113,7 +8230,7 @@
peer->lastms = pingtime;
peer->call = NULL;
if (statechanged) {
- ast_device_state_changed("SIP/%s", peer->name);
+ ast_device_state_changed("SIP/%s", peer->name); /* Activate notification */
if (newstate == 2) {
manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, pingtime);
} else {
@@ -8996,17 +9113,13 @@
/*--- handle_request_message: Handle incoming MESSAGE request ---*/
static int handle_request_message(struct sip_pvt *p, struct sip_request *req, int debug, int ignore)
{
- if (p->lastinvite) {
- if (!ignore) {
- if (debug)
- ast_verbose("Receiving message!\n");
- receive_message(p, req);
- }
- transmit_response(p, "200 OK", req);
+ if (!ignore) {
+ if (debug)
+ ast_verbose("Receiving message!\n");
+ receive_message(p, req);
} else {
- transmit_response(p, "405 Method Not Allowed", req);
- ast_set_flag(p, SIP_NEEDDESTROY);
- }
+ transmit_response(p, "202 ACCEPTED", req);
+ }
return 1;
}
/*--- handle_request_subscribe: Handle incoming SUBSCRIBE request ---*/
@@ -9041,7 +9154,9 @@
return 0;
}
/* Initialize the context if it hasn't been already */
- if (ast_strlen_zero(p->context))
+ if (p->subscribecontext && !ast_strlen_zero(p->subscribecontext))
+ strcpy(p->context, p->subscribecontext);
+ else if (ast_strlen_zero(p->context))
strcpy(p->context, default_context);
/* Get destination right away */
gotdest = get_destination(p, NULL);
@@ -9053,12 +9168,33 @@
transmit_response(p, "484 Address Incomplete", req);
ast_set_flag(p, SIP_NEEDDESTROY);
} else {
+ char *event = get_header(req, "Event"); /* Get Event package name */
+ char *accept = get_header(req, "Accept");
+
/* Initialize tag */
p->tag = rand();
- if (!strcmp(get_header(req, "Accept"), "application/dialog-info+xml"))
- p->subscribed = 2;
- else if (!strcmp(get_header(req, "Accept"), "application/simple-message-summary")) {
- /* Looks like they actually want a mailbox */
+ 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/dialog-info+xml"))
+ p->subscribed = 2;
+ /* IETF draft: draft-ietf-sipping-dialog-package-05.txt */
+ /* Should not be used for SUBSCRIBE, but anyway */
+ else if (!p->subscribed && strstr(accept, "application/cpim-pidf+xml"))
+ p->subscribed = 3; /* RFC 3863 format */
+ else if (!p->subscribed && strstr(accept, "application/pidf+xml"))
+ p->subscribed = 4; /* RFC 3863 format */
+ else if (!p->subscribed && strstr(accept, "application/xpidf+xml"))
+ p->subscribed = 1; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */
+ 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
@@ -9084,8 +9220,14 @@
ast_set_flag(p, SIP_NEEDDESTROY);
}
return 0;
- } else
- p->subscribed = 1;
+ } 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)
p->stateid = ast_extension_state_add(p->context, p->exten, cb_extensionstate, p);
}
@@ -9101,10 +9243,10 @@
return 0;
}
/* The next line can be removed if the SNOM200 Expires bug is fixed */
- if (p->subscribed == 1) {
+ /* if (p->subscribed != 0) {
if (p->expiry>max_expiry)
p->expiry = max_expiry;
- }
+ } */
/* Go ahead and free RTP port */
if (p->rtp) {
ast_rtp_destroy(p->rtp);
@@ -9114,8 +9256,12 @@
ast_rtp_destroy(p->vrtp);
p->vrtp = NULL;
}
+ 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);
transmit_response(p, "200 OK", req);
+ /* Set timer for destruction of call at expiration */
sip_scheddestroy(p, (p->expiry+10)*1000);
+ /* Send first notification */
transmit_state_notify(p, ast_extension_state(NULL, p->context, p->exten),1);
}
return 1;
@@ -9449,7 +9595,7 @@
build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
/* Send MWI */
ast_set_flag(p, SIP_OUTGOING);
- transmit_notify_with_mwi(p, newmsgs, oldmsgs);
+ transmit_notify_with_mwi(p, newmsgs, oldmsgs, peer->mailbox_exten);
sip_scheddestroy(p, 15000);
return 0;
}
@@ -9629,7 +9775,7 @@
sip_destroy(peer->call);
peer->call = NULL;
peer->lastms = -1;
- ast_device_state_changed("SIP/%s", peer->name);
+ ast_device_state_changed("SIP/%s", peer->name); /* Activate notification */
/* Try again quickly */
peer->pokeexpire = ast_sched_add(sched, DEFAULT_FREQ_NOTOK, sip_poke_peer_s, peer);
return 0;
@@ -9724,13 +9870,35 @@
if (p) {
found++;
res = AST_DEVICE_UNAVAILABLE;
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "Checking device state for peer %s\n", dest);
if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
(!p->maxms || ((p->lastms > -1) && (p->lastms <= p->maxms)))) {
- /* peer found and valid */
- res = AST_DEVICE_UNKNOWN;
+ /* Peer is registred, or have default IP address
+ and a valid registration */
+
+
+ /* Now check if we know anything about the state. The only way is by implementing
+ call control with incominglimit=X in sip.conf where X > 0
+ Check if the device has incominglimit, and if qualify=on, if the device
+ is reachable
+ */
+ if (p->incominglimit && (p->lastms == 0 || p->lastms <= p->maxms)) {
+ /* Free for a call */
+ res = AST_DEVICE_NOT_INUSE;
+
+ if (p->inUse) { /* On a call */
+ res = AST_DEVICE_BUSY;
+ }
+ } else {
+ /* peer found and valid, state unknown */
+ res = AST_DEVICE_UNKNOWN;
+ }
}
}
if (!p && !found) {
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "Checking device state for DNS host %s\n", dest);
hp = ast_gethostbyname(host, &ahp);
if (hp)
res = AST_DEVICE_UNKNOWN;
@@ -10218,6 +10386,7 @@
peer->chanvars = NULL;
}
strcpy(peer->context, default_context);
+ strcpy(peer->subscribecontext, default_subscribecontext);
strcpy(peer->language, default_language);
strcpy(peer->musicclass, global_musicclass);
ast_copy_flags(peer, &global_flags, SIP_USEREQPHONE);
@@ -10253,9 +10422,9 @@
if (realtime && !strcasecmp(v->name, "regseconds")) {
if (sscanf(v->value, "%li", ®seconds) != 1)
regseconds = 0;
- } else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) ) {
+ } else if (realtime && !strcasecmp(v->name, "ipaddr") && !ast_strlen_zero(v->value) )
inet_aton(v->value, &(peer->addr.sin_addr));
- } else if (realtime && !strcasecmp(v->name, "name"))
+ else if (realtime && !strcasecmp(v->name, "name"))
ast_copy_string(peer->name, v->value, sizeof(peer->name));
else if (!strcasecmp(v->name, "secret"))
ast_copy_string(peer->secret, v->value, sizeof(peer->secret));
@@ -10263,10 +10432,12 @@
ast_copy_string(peer->md5secret, v->value, sizeof(peer->md5secret));
else if (!strcasecmp(v->name, "auth"))
peer->auth = add_realm_authentication(peer->auth, v->value, v->lineno);
- else if (!strcasecmp(v->name, "callerid")) {
+ else if (!strcasecmp(v->name, "callerid"))
ast_callerid_split(v->value, peer->cid_name, sizeof(peer->cid_name), peer->cid_num, sizeof(peer->cid_num));
- } else if (!strcasecmp(v->name, "context"))
+ else if (!strcasecmp(v->name, "context"))
ast_copy_string(peer->context, v->value, sizeof(peer->context));
+ else if (!strcasecmp(v->name, "subscribecontext"))
+ ast_copy_string(peer->subscribecontext, v->value, sizeof(peer->subscribecontext));
else if (!strcasecmp(v->name, "fromdomain"))
ast_copy_string(peer->fromdomain, v->value, sizeof(peer->fromdomain));
else if (!strcasecmp(v->name, "usereqphone"))
@@ -10356,6 +10527,8 @@
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, "mailboxexten")) {
+ ast_copy_string(peer->mailbox_exten, v->value, sizeof(peer->mailbox_exten));
} else if (!strcasecmp(v->name, "callgroup")) {
peer->callgroup = ast_get_group(v->value);
} else if (!strcasecmp(v->name, "pickupgroup")) {
@@ -10460,6 +10633,7 @@
/* Initialize some reasonable defaults at SIP reload */
ast_copy_string(default_context, DEFAULT_CONTEXT, sizeof(default_context));
+ default_subscribecontext[0] = '\0';
default_language[0] = '\0';
default_fromdomain[0] = '\0';
default_qualify = 0;
@@ -10468,6 +10642,7 @@
externrefresh = 10;
ast_copy_string(default_useragent, DEFAULT_USERAGENT, sizeof(default_useragent));
ast_copy_string(default_notifymime, DEFAULT_NOTIFYMIME, sizeof(default_notifymime));
+ global_notifyringing = 1;
ast_copy_string(global_realm, DEFAULT_REALM, sizeof(global_realm));
ast_copy_string(global_musicclass, "default", sizeof(global_musicclass));
ast_copy_string(default_callerid, DEFAULT_CALLERID, sizeof(default_callerid));
@@ -10554,6 +10729,8 @@
compactheaders = ast_true(v->value);
} else if (!strcasecmp(v->name, "notifymimetype")) {
ast_copy_string(default_notifymime, v->value, sizeof(default_notifymime));
+ } else if (!strcasecmp(v->name, "notifyringing")) {
+ global_notifyringing = ast_true(v->value);
} else if (!strcasecmp(v->name, "musicclass") || !strcasecmp(v->name, "musiconhold")) {
ast_copy_string(global_musicclass, v->value, sizeof(global_musicclass));
} else if (!strcasecmp(v->name, "language")) {
Index: configs/sip.conf.sample
===================================================================
RCS file: /usr/cvsroot/asterisk/configs/sip.conf.sample,v
retrieving revision 1.62
diff -u -r1.62 sip.conf.sample
--- configs/sip.conf.sample 27 Apr 2005 17:04:17 -0000 1.62
+++ configs/sip.conf.sample 31 May 2005 12:06:08 -0000
@@ -48,6 +48,9 @@
;maxexpirey=3600 ; Max length of incoming registration we allow
;defaultexpirey=120 ; Default length of incoming/outoing registration
;notifymimetype=text/plain ; Allow overriding of mime type in MWI NOTIFY
+;notifyringing=no ; Sent ringing (yes) or inuse (no) as state in
+ ; NOTIFY messages when observed extension is
+ ; in state RINGING_AND_INUSE (defaults to "yes")
;checkmwi=10 ; Default time between mailbox checks for peers
;videosupport=yes ; Turn on support for SIP video
;recordhistory=yes ; Record SIP history by default
@@ -309,6 +312,9 @@
;defaultip=192.168.0.59 ; IP used until peer registers
;username=snom ; Username to use in INVITE until peer registers
;mailbox=1234@context,2345 ; Mailbox(-es) for message waiting indicator
+;mailboxexten=voicemail ; dialplan extension to reach mailbox
+ ; sets the Message-Account in the MWI notify message
+ ; defaults to callerid which defaults to "asterisk"
;restrictcid=yes ; To have the callerid restriced -> sent as ANI
;disallow=all
;allow=ulaw ; dtmfmode=inband only works with ulaw or alaw!
Index: include/asterisk/pbx.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/pbx.h,v
retrieving revision 1.47
diff -u -r1.47 pbx.h
--- include/asterisk/pbx.h 18 May 2005 01:49:13 -0000 1.47
+++ include/asterisk/pbx.h 31 May 2005 12:06:15 -0000
@@ -42,6 +42,10 @@
#define AST_EXTENSION_BUSY 2
/*! All devices UNAVAILABLE/UNREGISTERED */
#define AST_EXTENSION_UNAVAILABLE 3
+/*! One or more devices are RINGING and none are INUSE */
+#define AST_EXTENSION_RINGING 4
+/*! One or more devices are RINGING and one or more are INUSE */
+#define AST_EXTENSION_RINGING_AND_INUSE 5
struct ast_context;
struct ast_exten;