[asterisk-commits] branch oej/ami_ssl r18026 - in
/team/oej/ami_ssl: ./ apps/ channels/
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Thu Apr 6 13:47:29 MST 2006
Author: oej
Date: Thu Apr 6 15:47:25 2006
New Revision: 18026
URL: http://svn.digium.com/view/asterisk?rev=18026&view=rev
Log:
Forced update
Modified:
team/oej/ami_ssl/ (props changed)
team/oej/ami_ssl/apps/app_amd.c
team/oej/ami_ssl/channels/chan_sip.c
Propchange: team/oej/ami_ssl/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Thu Apr 6 15:47:25 2006
@@ -1,1 +1,1 @@
-/trunk:1-18002
+/trunk:1-18025
Modified: team/oej/ami_ssl/apps/app_amd.c
URL: http://svn.digium.com/view/asterisk/team/oej/ami_ssl/apps/app_amd.c?rev=18026&r1=18025&r2=18026&view=diff
==============================================================================
--- team/oej/ami_ssl/apps/app_amd.c (original)
+++ team/oej/ami_ssl/apps/app_amd.c Thu Apr 6 15:47:25 2006
@@ -91,7 +91,7 @@
static void isAnsweringMachine(struct ast_channel *chan, void *data)
{
- int res = 0;
+ int res = 0, ret = 0;
struct ast_frame *f = NULL;
@@ -136,8 +136,8 @@
AST_APP_ARG(argMaximumNumberOfWords);
AST_APP_ARG(argSilenceThreshold);
);
-
- ast_verbose(VERBOSE_PREFIX_3 "AMD: %s %s %s (Fmt: %d)\n", chan->name ,chan->cid.cid_ani, chan->cid.cid_rdnis, chan->readformat);
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "AMD: %s %s %s (Fmt: %d)\n", chan->name ,chan->cid.cid_ani, chan->cid.cid_rdnis, chan->readformat);
/* Lets parse the arguments. */
if (ast_strlen_zero(data)) {
@@ -180,8 +180,9 @@
}
/* Now we're ready to roll! */
-
- ast_verbose(VERBOSE_PREFIX_3 "AMD: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
+
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "AMD: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
"totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] \n",
initialSilence, greeting, afterGreetingSilence, totalAnalysisTime,
minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold );
@@ -204,42 +205,45 @@
}
ast_dsp_set_threshold(silenceDetector, silenceThreshold );
- while (ast_waitfor(chan, -1) > -1)
+ while ((ret = ast_waitfor(chan, totalAnalysisTime)))
{
- f = ast_read(chan);
- if (!f ) {
- /* No Frame: Called Party Must Have Dropped */
- ast_verbose(VERBOSE_PREFIX_3 "AMD: HANGUP\n");
- ast_log(LOG_DEBUG, "Got hangup\n");
+ if (ret < 0 || !(f = ast_read(chan))) {
+ /* No Frame OR Error on ast_waitfor : Called Party Must Have Dropped */
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "AMD: HANGUP\n");
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Got hangup\n");
strcpy(amdStatus , "HANGUP" );
strcpy(amdCause , "" );
break;
}
- framelength = (ast_codec_get_samples(f) / 8);
- iTotalTime += framelength;
- if (iTotalTime >= totalAnalysisTime ) {
- ast_verbose(VERBOSE_PREFIX_3 "AMD: Channel [%s]. Too long...\n", chan->name );
- ast_frfree(f);
- strcpy(amdStatus , "NOTSURE" );
- sprintf(amdCause , "TOOLONG-%d", iTotalTime );
- break;
- }
if (f->frametype == AST_FRAME_VOICE ) {
+ framelength = (ast_codec_get_samples(f) / DEFAULT_SAMPLES_PER_MS);
+ iTotalTime += framelength;
+ if (iTotalTime >= totalAnalysisTime ) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "AMD: Channel [%s]. Too long...\n", chan->name );
+ ast_frfree(f);
+ strcpy(amdStatus , "NOTSURE" );
+ sprintf(amdCause , "TOOLONG-%d", iTotalTime );
+ break;
+ }
dspsilence = 0;
ast_dsp_silence(silenceDetector, f, &dspsilence);
if (dspsilence ) {
silenceDuration = dspsilence;
- /* ast_verbose(VERBOSE_PREFIX_3 "AMD: %d SILENCE: silenceDuration:%d afterGreetingSilence:%d inGreeting:%d\n", currentState, silenceDuration, afterGreetingSilence, inGreeting ); */
if (silenceDuration >= betweenWordsSilence ) {
if (currentState != STATE_IN_SILENCE ) {
previousState = currentState;
- ast_verbose(VERBOSE_PREFIX_3 "AMD: Changed state to STATE_IN_SILENCE\n");
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "AMD: Changed state to STATE_IN_SILENCE\n");
}
currentState = STATE_IN_SILENCE;
consecutiveVoiceDuration = 0;
}
if (inInitialSilence == 1 && silenceDuration >= initialSilence ) {
- ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: silenceDuration:%d initialSilence:%d\n",
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: silenceDuration:%d initialSilence:%d\n",
silenceDuration, initialSilence );
ast_frfree(f);
strcpy(amdStatus , "MACHINE" );
@@ -248,7 +252,8 @@
}
if (silenceDuration >= afterGreetingSilence && inGreeting == 1 ) {
- ast_verbose(VERBOSE_PREFIX_3 "AMD: HUMAN: silenceDuration:%d afterGreetingSilence:%d\n",
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "AMD: HUMAN: silenceDuration:%d afterGreetingSilence:%d\n",
silenceDuration, afterGreetingSilence );
ast_frfree(f);
strcpy(amdStatus , "HUMAN" );
@@ -258,21 +263,22 @@
} else {
consecutiveVoiceDuration += framelength;
voiceDuration += framelength;
- /* ast_verbose(VERBOSE_PREFIX_3 "AMD: %d VOICE: ConsecutiveVoice:%d voiceDuration:%d inGreeting:%d\n", currentState, consecutiveVoiceDuration, voiceDuration, inGreeting ); */
/* If I have enough consecutive voice to say that I am in a Word, I can only increment the
number of words if my previous state was Silence, which means that I moved into a word. */
if (consecutiveVoiceDuration >= minimumWordLength ) {
if (currentState == STATE_IN_SILENCE ) {
iWordsCount++;
- ast_verbose(VERBOSE_PREFIX_3 "AMD: Word detected. iWordsCount:%d\n", iWordsCount );
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "AMD: Word detected. iWordsCount:%d\n", iWordsCount );
previousState = currentState;
currentState = STATE_IN_WORD;
}
}
if (iWordsCount >= maximumNumberOfWords ) {
- ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: iWordsCount:%d\n", iWordsCount );
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: iWordsCount:%d\n", iWordsCount );
ast_frfree(f);
strcpy(amdStatus , "MACHINE" );
sprintf(amdCause , "MAXWORDS-%d-%d", iWordsCount, maximumNumberOfWords );
@@ -280,9 +286,9 @@
}
if (inGreeting == 1 && voiceDuration >= greeting ) {
- ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: voiceDuration:%d greeting:%d\n",
- voiceDuration, greeting );
- ast_frfree(f);
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: voiceDuration:%d greeting:%d\n", voiceDuration, greeting);
+ ast_frfree(f);
strcpy(amdStatus , "MACHINE" );
sprintf(amdCause , "LONGGREETING-%d-%d", voiceDuration, greeting );
break;
@@ -296,12 +302,19 @@
}
ast_frfree(f);
}
+ if (!ret) {
+ /* It took too long to get a frame back. Giving up. */
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "AMD: Channel [%s]. Too long...\n", chan->name );
+ strcpy(amdStatus , "NOTSURE" );
+ sprintf(amdCause , "TOOLONG-%d", iTotalTime );
+ }
pbx_builtin_setvar_helper(chan , "AMDSTATUS" , amdStatus );
pbx_builtin_setvar_helper(chan , "AMDCAUSE" , amdCause );
/* If We Started With A Valid Read Format, Return To It... */
- if (readFormat) {
+ if (readFormat && chan->_state == AST_STATE_UP) {
res = ast_set_read_format(chan, readFormat );
if (res)
ast_log(LOG_WARNING, "AMD: Unable to restore read format on '%s'\n", chan->name);
@@ -371,7 +384,8 @@
}
ast_config_destroy(cfg);
- ast_verbose(VERBOSE_PREFIX_3 "AMD defaults: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "AMD defaults: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
"totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] \n",
dfltInitialSilence, dfltGreeting, dfltAfterGreetingSilence, dfltTotalAnalysisTime,
dfltMinimumWordLength, dfltBetweenWordsSilence, dfltMaximumNumberOfWords, dfltSilenceThreshold );
Modified: team/oej/ami_ssl/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/ami_ssl/channels/chan_sip.c?rev=18026&r1=18025&r2=18026&view=diff
==============================================================================
--- team/oej/ami_ssl/channels/chan_sip.c (original)
+++ team/oej/ami_ssl/channels/chan_sip.c Thu Apr 6 15:47:25 2006
@@ -9812,6 +9812,58 @@
}
}
+/* \brief Handle SIP response in REFER transaction
+ We've sent a REFER, now handle responses to it
+ */
+static void handle_response_refer(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int ignore, int seqno)
+{
+ char *auth = "Proxy-Authenticate";
+ char *auth2 = "Proxy-Authorization";
+ char iabuf[INET_ADDRSTRLEN];
+
+ switch (resp) {
+ case 202: /* Transfer accepted */
+ /* We need to do something here */
+ /* The transferee is now sending INVITE to target */
+ /* Now wait for next message */
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "Got 202 accepted on transfer\n");
+ /* We should hang along, waiting for NOTIFY's here */
+ /* (done in a separate function) */
+ break;
+
+ case 401: /* Not www-authorized on SIP method */
+ case 407: /* Proxy auth */
+ if (ast_strlen_zero(p->authname)) {
+ ast_log(LOG_WARNING, "Asked to authenticate REFER to %s:%d but we have no matching peer or realm auth!\n",
+ ast_inet_ntoa(iabuf, sizeof(iabuf), p->recv.sin_addr), ntohs(p->recv.sin_port));
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ }
+ if (resp == 401) {
+ auth = "WWW-Authenticate";
+ auth2 = "Authorization";
+ }
+ if ((p->authtries > 1) || do_proxy_auth(p, req, auth, auth2, SIP_REFER, 0)) {
+ ast_log(LOG_NOTICE, "Failed to authenticate on REFER to '%s'\n", get_header(&p->initreq, "From"));
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ }
+ break;
+
+
+ case 500: /* Server error */
+ case 501: /* Method not implemented */
+ /* Return to the current call onhold */
+ /* Status flag needed to be reset */
+ ast_log(LOG_NOTICE, "SIP transfer failed, call miserably fails. \n");
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ break;
+ case 603: /* Transfer declined */
+ ast_log(LOG_NOTICE, "SIP transfer declined, call fails. \n" );
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+ break;
+ }
+}
+
/*! \brief Handle responses on REGISTER to services */
static int handle_response_register(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int ignore, int seqno)
{
@@ -10065,9 +10117,15 @@
res = handle_response_register(p, resp, rest, req, ignore, seqno);
}
break;
+ case 202: /* Transfer accepted */
+ if (sipmethod == SIP_REFER)
+ handle_response_refer(p, resp, rest, req, ignore, seqno);
+ break;
case 401: /* Not www-authorized on SIP method */
if (sipmethod == SIP_INVITE) {
handle_response_invite(p, resp, rest, req, ignore, seqno);
+ } else if (sipmethod == SIP_REFER) {
+ handle_response_refer(p, resp, rest, req, ignore, seqno);
} else if (p->registry && sipmethod == SIP_REGISTER) {
res = handle_response_register(p, resp, rest, req, ignore, seqno);
} else {
@@ -10095,7 +10153,9 @@
case 407: /* Proxy auth required */
if (sipmethod == SIP_INVITE) {
handle_response_invite(p, resp, rest, req, ignore, seqno);
- } else if (sipmethod == SIP_BYE || sipmethod == SIP_REFER) {
+ } else if (sipmethod == SIP_REFER) {
+ handle_response_refer(p, resp, rest, req, ignore, seqno);
+ } else if (sipmethod == SIP_BYE) {
if (ast_strlen_zero(p->authname))
ast_log(LOG_WARNING, "Asked to authenticate %s, to %s:%d but we have no matching peer!\n",
msg, ast_inet_ntoa(iabuf, sizeof(iabuf), p->recv.sin_addr), ntohs(p->recv.sin_port));
@@ -10117,9 +10177,17 @@
case 501: /* Not Implemented */
if (sipmethod == SIP_INVITE) {
handle_response_invite(p, resp, rest, req, ignore, seqno);
+ } else if (sipmethod == SIP_REFER) {
+ handle_response_refer(p, resp, rest, req, ignore, seqno);
} else
ast_log(LOG_WARNING, "Host '%s' does not implement '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), p->sa.sin_addr), msg);
break;
+ case 603: /* Declined transfer */
+ if (sipmethod == SIP_REFER) {
+ handle_response_refer(p, resp, rest, req, ignore, seqno);
+ break;
+ }
+ /* Fallthrough */
default:
if ((resp >= 300) && (resp < 700)) {
/* Fatal response */
@@ -10152,10 +10220,11 @@
/* channel now destroyed - dec the inUse counter */
update_call_counter(p, DEC_CALL_LIMIT);
break;
- case 482: /* SIP is incapable of performing a hairpin call, which
+ case 482: /*
+ \note SIP is incapable of performing a hairpin call, which
is yet another failure of not having a layer 2 (again, YAY
- IETF for thinking ahead). So we treat this as a call
- forward and hope we end up at the right place... */
+ IETF for thinking ahead). So we treat this as a call
+ forward and hope we end up at the right place... */
ast_log(LOG_DEBUG, "Hairpin detected, setting up call forward for what it's worth\n");
if (p->owner)
ast_string_field_build(p->owner, call_forward,
@@ -10167,6 +10236,12 @@
case 410: /* Gone */
case 400: /* Bad Request */
case 500: /* Server error */
+ if (sipmethod == SIP_REFER) {
+ handle_response_refer(p, resp, rest, req, ignore, seqno);
+ break;
+ }
+ /* Fall through */
+ handle_response_refer(p, resp, rest, req, ignore, seqno);
case 503: /* Service Unavailable */
if (owner)
ast_queue_control(p->owner, AST_CONTROL_CONGESTION);
@@ -10220,9 +10295,16 @@
/* We successfully transmitted a message */
ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
break;
+ case 202: /* Transfer accepted */
+ if (sipmethod == SIP_REFER) {
+ handle_response_refer(p, resp, rest, req, ignore, seqno);
+ }
+ break;
case 401: /* www-auth */
case 407:
- if (sipmethod == SIP_BYE || sipmethod == SIP_REFER) {
+ if (sipmethod == SIP_REFER) {
+ handle_response_refer(p, resp, rest, req, ignore, seqno);
+ } else if (sipmethod == SIP_BYE) {
char *auth, *auth2;
if (resp == 407) {
@@ -10246,6 +10328,19 @@
handle_response_invite(p, resp, rest, req, ignore, seqno);
}
break;
+ case 501: /* Not Implemented */
+ if (sipmethod == SIP_INVITE) {
+ handle_response_invite(p, resp, rest, req, ignore, seqno);
+ } else if (sipmethod == SIP_REFER) {
+ handle_response_refer(p, resp, rest, req, ignore, seqno);
+ }
+ break;
+ case 603: /* Declined transfer */
+ if (sipmethod == SIP_REFER) {
+ handle_response_refer(p, resp, rest, req, ignore, seqno);
+ break;
+ }
+ /* Fallthrough */
default: /* Errors without handlers */
if ((resp >= 100) && (resp < 200)) {
if (sipmethod == SIP_INVITE) { /* re-invite */
@@ -10456,6 +10551,145 @@
*sep = '\0';
}
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 */
@@ -11333,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