- Implement handle_request_notify to handle incoming NOTIFY requests

and respond properly to them.


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@18024 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Olle Johansson
2006-04-06 20:36:25 +00:00
parent d42357fae1
commit 5483288048

View 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 */