[asterisk-commits] trunk r18024 - /trunk/channels/chan_sip.c
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Thu Apr 6 13:36:28 MST 2006
Author: oej
Date: Thu Apr 6 15:36:25 2006
New Revision: 18024
URL: http://svn.digium.com/view/asterisk?rev=18024&view=rev
Log:
- Implement handle_request_notify to handle incoming NOTIFY requests
and respond properly to them.
Modified:
trunk/channels/chan_sip.c
Modified: trunk/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_sip.c?rev=18024&r1=18023&r2=18024&view=diff
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Thu Apr 6 15:36:25 2006
@@ -10553,6 +10553,145 @@
return thetag;
}
+/*! \brief Handle incoming notifications */
+static int handle_request_notify(struct sip_pvt *p, struct sip_request *req, int debug, int ignore, struct sockaddr_in *sin, int seqno, char *e)
+{
+ /* This is mostly a skeleton for future improvements */
+ /* Mostly created to return proper answers on notifications on outbound REFER's */
+ int res = 0;
+ char *event = get_header(req, "Event");
+ char *eventid = NULL;
+ char *sep;
+
+ if( (sep = strchr(event, ';')) ) {
+ *sep = '\0';
+ eventid = ++sep;
+ }
+
+ if (option_debug > 1 && sipdebug)
+ ast_log(LOG_DEBUG, "Got NOTIFY Event: %s\n", event);
+
+ if (strcmp(event, "refer")) {
+ /* We don't understand this event. */
+ /* Here's room to implement incoming voicemail notifications :-) */
+ transmit_response(p, "489 Bad event", req);
+ if (!p->lastinvite)
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ return -1;
+ } else {
+ /* Handle REFER notifications */
+
+ char buf[1024];
+ char *cmd, *code;
+ int respcode;
+ int success = TRUE;
+
+ /* EventID for each transfer... EventID is basically the REFER cseq
+
+ We are getting notifications on a call that we transfered
+ We should hangup when we are getting a 200 OK in a sipfrag
+ Check if we have an owner of this event */
+
+ /* Check the content type */
+ if (strncasecmp(get_header(req, "Content-Type"), "message/sipfrag", strlen("message/sipfrag"))) {
+ /* We need a sipfrag */
+ transmit_response(p, "400 Bad request", req);
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ return -1;
+ }
+
+ /* Get the text of the attachment */
+ if (get_msg_text(buf, sizeof(buf), req)) {
+ ast_log(LOG_WARNING, "Unable to retrieve attachment from NOTIFY %s\n", p->callid);
+ transmit_response(p, "400 Bad request", req);
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ return -1;
+ }
+
+ /*
+ From the RFC...
+ A minimal, but complete, implementation can respond with a single
+ NOTIFY containing either the body:
+ SIP/2.0 100 Trying
+
+ if the subscription is pending, the body:
+ SIP/2.0 200 OK
+ if the reference was successful, the body:
+ SIP/2.0 503 Service Unavailable
+ if the reference failed, or the body:
+ SIP/2.0 603 Declined
+
+ if the REFER request was accepted before approval to follow the
+ reference could be obtained and that approval was subsequently denied
+ (see Section 2.4.7).
+
+ If there are several REFERs in the same dialog, we need to
+ match the ID of the event header...
+ */
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "* SIP Transfer NOTIFY Attachment: \n---%s\n---\n", buf);
+ cmd = buf;
+ while(*cmd && (*cmd < 33)) { /* Skip white space */
+ cmd++;
+ }
+ code = cmd;
+ /* We are at SIP/2.0 */
+ while(*code && (*code > 32)) { /* Search white space */
+ code++;
+ }
+ *code = '\0';
+ code++;
+ while(*code && (*code < 33)) { /* Skip white space */
+ code++;
+ }
+ sep = code;
+ sep++;
+ while(*sep && (*sep > 32)) { /* Search white space */
+ sep++;
+ }
+ *sep = '\0';
+ sep++; /* Response string */
+ respcode = atoi(code);
+ switch (respcode) {
+ case 100: /* Trying: */
+ /* Don't do anything yet */
+ break;
+ case 183: /* Ringing: */
+ /* Don't do anything yet */
+ break;
+ case 200: /* OK: The new call is up, hangup this call */
+ /* Hangup the call that we are replacing */
+ break;
+ case 301: /* Moved permenantly */
+ case 302: /* Moved temporarily */
+ /* Do we get the header in the packet in this case? */
+ success = FALSE;
+ break;
+ case 503: /* Service Unavailable: The new call failed */
+ /* Cancel transfer, continue the call */
+ success = FALSE;
+ break;
+ case 603: /* Declined: Not accepted */
+ /* Cancel transfer, continue the current call */
+ success = FALSE;
+ break;
+ }
+ if (!success) {
+ ast_log(LOG_NOTICE, "Transfer failed. Sorry. Nothing further to do with this call\n");
+ }
+
+ /* Confirm that we received this packet */
+ transmit_response(p, "200 OK", req);
+ return res;
+ };
+
+ /* THis could be voicemail notification */
+ transmit_response(p, "200 OK", req);
+ if (!p->lastinvite)
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ return res;
+}
+
/*! \brief Handle incoming OPTIONS request */
static int handle_request_options(struct sip_pvt *p, struct sip_request *req, int debug)
{
@@ -11428,11 +11567,7 @@
}
break;
case SIP_NOTIFY:
- /* XXX we get NOTIFY's from some servers. WHY?? Maybe we should
- look into this someday XXX */
- transmit_response(p, "200 OK", req);
- if (!p->lastinvite)
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ res = handle_request_notify(p, req, debug, ignore, sin, seqno, e);
break;
case SIP_ACK:
/* Make sure we don't ignore this */
More information about the asterisk-commits
mailing list