]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
- Implement handle_request_notify to handle incoming NOTIFY requests
authorOlle Johansson <oej@edvina.net>
Thu, 6 Apr 2006 20:36:25 +0000 (20:36 +0000)
committerOlle Johansson <oej@edvina.net>
Thu, 6 Apr 2006 20:36:25 +0000 (20:36 +0000)
  and respond properly to them.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@18024 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c

index 6d91fbec90d70c69a35d28b5c11af082f912dc74..58dcb4f6da7196ae1747c49dc742c4b632026840 100644 (file)
@@ -10553,6 +10553,145 @@ static char *gettag(struct sip_request *req, char *header, char *tagbuf, int tag
        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 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
                }
                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 */