Index: channel.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channel.c,v
retrieving revision 1.184
diff -u -B -r1.184 channel.c
--- channel.c 31 Mar 2005 19:07:27 -0000 1.184
+++ channel.c 1 Apr 2005 00:43:40 -0000
@@ -2052,8 +2052,13 @@
cut = strchr(name,'-');
if (cut)
*cut = 0;
- if (!strcmp(name, device))
- return AST_DEVICE_INUSE;
+ if (!strcmp(name, device)) {
+ if (chan->_state == AST_STATE_RINGING) {
+ return AST_DEVICE_RINGING;
+ } else {
+ return AST_DEVICE_INUSE;
+ }
+ }
chan = ast_channel_walk_locked(chan);
}
return AST_DEVICE_UNKNOWN;
Index: pbx.c
===================================================================
RCS file: /usr/cvsroot/asterisk/pbx.c,v
retrieving revision 1.217
diff -u -B -r1.217 pbx.c
--- pbx.c 29 Mar 2005 06:18:58 -0000 1.217
+++ pbx.c 1 Apr 2005 00:43:50 -0000
@@ -1691,6 +1691,8 @@
int res = -1;
int allunavailable = 1, allbusy = 1, allfree = 1;
int busy = 0;
+ int inuse = 0;
+ int ring = 0;
if (!e)
return -1;
@@ -1712,7 +1714,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;
@@ -1731,7 +1741,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.700
diff -u -B -r1.700 chan_sip.c
--- channels/chan_sip.c 30 Mar 2005 16:28:28 -0000 1.700
+++ channels/chan_sip.c 1 Apr 2005 00:44:10 -0000
@@ -160,9 +160,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;
@@ -172,6 +173,8 @@
#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 */
@@ -404,6 +407,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[AST_MAX_EXTENSION]; /* 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 */
@@ -451,7 +455,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 */
@@ -487,7 +492,7 @@
ASTOBJ_COMPONENTS(struct sip_user);
char secret[80]; /* Password */
char md5secret[80]; /* Password in md5 */
- char context[80]; /* Default context for incoming calls */
+ char context[AST_MAX_EXTENSION]; /* Default context for incoming calls */
char cid_num[80]; /* Caller ID num */
char cid_name[80]; /* Caller ID name */
char accountcode[20]; /* Account code */
@@ -517,6 +522,7 @@
char md5secret[80]; /* Password in MD5 */
struct sip_auth *auth; /* Realm authentication list */
char context[80]; /* Default context for incoming calls */
+ char subscribecontext[AST_MAX_EXTENSION]; /* Context for subscriptions */
char username[80]; /* Temporary username until registration */
char accountcode[20]; /* Account code */
int amaflags; /* AMA Flags (for billing) */
@@ -644,6 +650,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);
@@ -3289,7 +3296,8 @@
if (maddr) {
maddr += 6;
hn = strspn(maddr, "0123456789.");
- if (hn > (sizeof(hostname) - 1)) hn = sizeof(hostname) - 1;
+ if (hn > (sizeof(hostname) - 1))
+ hn = sizeof(hostname) - 1;
strncpy(hostname, maddr, hn); hostname[hn] = '\0'; /* safe */
}
@@ -3407,7 +3415,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;
}
@@ -3420,7 +3428,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
@@ -3450,7 +3458,6 @@
}
init_req(req, sipmethod, c);
- snprintf(tmp, sizeof(tmp), "%d %s", seqno, sip_methods[sipmethod].text);
add_header(req, "Via", p->via);
if (p->route) {
@@ -3482,8 +3489,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);
@@ -4162,10 +4177,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));
@@ -4183,30 +4223,38 @@
reqprep(&req, p, SIP_NOTIFY, 0, 1);
- if (p->subscribed == 1) {
- strncpy(to, get_header(&p->initreq, "To"), sizeof(to)-1);
+ /* 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 */
+ }
+
+ strncpy(to, get_header(&p->initreq, "To"), sizeof(to)-1);
+ 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 */
+ ast_log(LOG_WARNING, "))))) 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");
@@ -4227,14 +4275,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");
@@ -4243,16 +4325,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");
@@ -4701,7 +4789,7 @@
manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", p->name);
register_peer_exten(p, 0);
p->expire = -1;
- ast_device_state_changed("SIP/%s", p->name);
+ ast_device_state_changed("SIP/%s", p->name); /* Activate notification */
if (ast_test_flag(p, SIP_SELFDESTRUCT) || ast_test_flag((&p->flags_page2), SIP_PAGE2_RTAUTOCLEAR)) {
ASTOBJ_MARK(p);
prune_peers();
@@ -5132,7 +5220,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. */
@@ -5258,21 +5346,25 @@
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;
- if (state == -1) {
- sip_scheddestroy(p, 15000);
- p->stateid = -1;
- return 0;
- }
-
- transmit_state_notify(p, state, 1);
+ struct sip_pvt *p = data; /* Pointer to the subscription "call" */
+
+ if (state == -1) {
+ sip_scheddestroy(p, 15000);
+ p->stateid = -1;
+ return 0;
+ }
+
+ transmit_state_notify(p, state, 1);
+ p->laststate = state;
- if (option_debug)
- ast_verbose(VERBOSE_PREFIX_1 "Extension Changed %s new state %d for Notify User %s\n", exten, state, p->username);
- return 0;
+ if (option_debug)
+ ast_verbose(VERBOSE_PREFIX_1 "Extension Changed %s new state %d for Notify User %s\n", exten, state, p->username);
+ return 0;
}
/*--- register_verify: Verify registration of user */
@@ -5353,7 +5447,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);
@@ -5396,7 +5490,7 @@
char tmp[256] = "", *c, *a;
char tmpf[256]= "", *fr;
struct sip_request *req;
-
+
req = oreq;
if (!req)
req = &p->initreq;
@@ -6005,6 +6099,8 @@
strncpy(p->fullcontact, peer->fullcontact, sizeof(p->fullcontact) - 1);
if (!ast_strlen_zero(peer->context))
strncpy(p->context, peer->context, sizeof(p->context) - 1);
+ if (!ast_strlen_zero(peer->subscribecontext))
+ strncpy(p->subscribecontext, peer->subscribecontext, sizeof(p->subscribecontext) - 1);
strncpy(p->peersecret, peer->secret, sizeof(p->peersecret) - 1);
strncpy(p->peermd5secret, peer->md5secret, sizeof(p->peermd5secret) - 1);
strncpy(p->language, peer->language, sizeof(p->language) -1);
@@ -6073,14 +6169,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) {
@@ -6093,7 +6201,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
@@ -6825,7 +6941,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;
@@ -6838,7 +6955,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),
@@ -6853,7 +6970,8 @@
if (cur->subscribed && 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->uri);
+ cur->callid, cur->exten, cur->laststate, cur->subscribed);
+ numchans++;
}
cur = cur->next;
@@ -7784,7 +7902,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 {
@@ -8660,17 +8778,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 ---*/
@@ -8705,7 +8819,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))
+ strncpy(p->context, p->subscribecontext, sizeof(p->context) - 1);
+ else if (ast_strlen_zero(p->context))
strncpy(p->context, default_context, sizeof(p->context) - 1);
/* Get destination right away */
gotdest = get_destination(p, NULL);
@@ -8717,12 +8833,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
@@ -8748,8 +8885,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);
}
@@ -8765,7 +8908,7 @@
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;
}
@@ -8778,8 +8921,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;
@@ -9293,7 +9440,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;
@@ -9388,13 +9535,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;
@@ -9858,6 +10027,7 @@
peer->chanvars = NULL;
}
strncpy(peer->context, default_context, sizeof(peer->context)-1);
+ strncpy(peer->subscribecontext, default_subscribecontext, sizeof(peer->subscribecontext)-1);
strncpy(peer->language, default_language, sizeof(peer->language)-1);
strncpy(peer->musicclass, global_musicclass, sizeof(peer->musicclass)-1);
ast_copy_flags(peer, &global_flags, SIP_USEREQPHONE);
@@ -9902,9 +10072,11 @@
peer->auth = add_realm_authentication(peer->auth, v->value, v->lineno);
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")) {
strncpy(peer->context, v->value, sizeof(peer->context)-1);
- else if (!strcasecmp(v->name, "fromdomain"))
+ } else if (!strcasecmp(v->name, "subscribecontext")) {
+ strncpy(peer->subscribecontext, v->value, sizeof(peer->subscribecontext)-1);
+ } else if (!strcasecmp(v->name, "fromdomain"))
strncpy(peer->fromdomain, v->value, sizeof(peer->fromdomain)-1);
else if (!strcasecmp(v->name, "usereqphone"))
ast_set2_flag(peer, ast_true(v->value), SIP_USEREQPHONE);
@@ -10100,6 +10272,7 @@
/* Initialize some reasonable defaults at SIP reload */
strncpy(default_context, DEFAULT_CONTEXT, sizeof(default_context) - 1);
+ default_subscribecontext[0] = '\0';
default_language[0] = '\0';
default_fromdomain[0] = '\0';
default_qualify = 0;
@@ -10108,6 +10281,7 @@
externrefresh = 10;
strncpy(default_useragent, DEFAULT_USERAGENT, sizeof(default_useragent) - 1);
strncpy(default_notifymime, DEFAULT_NOTIFYMIME, sizeof(default_notifymime) - 1);
+ global_notifyringing = 1;
strncpy(global_realm, DEFAULT_REALM, sizeof(global_realm) - 1);
strncpy(global_musicclass, "default", sizeof(global_musicclass) - 1);
strncpy(default_callerid, DEFAULT_CALLERID, sizeof(default_callerid) - 1);
@@ -10195,6 +10369,8 @@
compactheaders = ast_true(v->value);
} else if (!strcasecmp(v->name, "notifymimetype")) {
strncpy(default_notifymime, v->value, sizeof(default_notifymime) - 1);
+ } else if (!strcasecmp(v->name, "notifyringing")) {
+ global_notifyringing = ast_true(v->value);
} else if (!strcasecmp(v->name, "musicclass") || !strcasecmp(v->name, "musiconhold")) {
strncpy(global_musicclass, v->value, sizeof(global_musicclass) - 1);
} else if (!strcasecmp(v->name, "language")) {
Index: configs/sip.conf.sample
===================================================================
RCS file: /usr/cvsroot/asterisk/configs/sip.conf.sample,v
retrieving revision 1.61
diff -u -B -r1.61 sip.conf.sample
--- configs/sip.conf.sample 24 Mar 2005 23:06:21 -0000 1.61
+++ configs/sip.conf.sample 1 Apr 2005 00:44:11 -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
Index: include/asterisk/channel.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/channel.h,v
retrieving revision 1.80
diff -u -B -r1.80 channel.h
--- include/asterisk/channel.h 28 Mar 2005 20:48:24 -0000 1.80
+++ include/asterisk/channel.h 1 Apr 2005 00:44:13 -0000
@@ -447,6 +447,8 @@
#define AST_DEVICE_INVALID 4
/*! Device is unavailable */
#define AST_DEVICE_UNAVAILABLE 5
+/*! Device is ringing */
+#define AST_DEVICE_RINGING 6
/*! Create a channel structure */
/*! Returns NULL on failure to allocate */
Index: include/asterisk/pbx.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/pbx.h,v
retrieving revision 1.43
diff -u -B -r1.43 pbx.h
--- include/asterisk/pbx.h 29 Mar 2005 06:16:49 -0000 1.43
+++ include/asterisk/pbx.h 1 Apr 2005 00:44:14 -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;