From 83728dbd79f1569d77cf6daf332470fa317d0396 Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Sun, 26 Dec 2004 22:33:25 +0000 Subject: [PATCH] Merge Tilghman's cause codes patch (bug #3032) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4558 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_iax2.c | 22 +++++++++++++++++++++- channels/iax2-parser.c | 8 ++++++++ channels/iax2-parser.h | 1 + channels/iax2.h | 1 + 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index bec162f222..9bb48a9b12 100755 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -1474,6 +1474,7 @@ static int attempt_transmit(void *data) fr.frametype = AST_FRAME_CONTROL; fr.subclass = AST_CONTROL_HANGUP; iax2_queue_frame(f->callno, &fr); + iaxs[f->callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; } else { if (iaxs[f->callno]->reg) { memset(&iaxs[f->callno]->reg->us, 0, sizeof(iaxs[f->callno]->reg->us)); @@ -2366,13 +2367,16 @@ static int iax2_hangup(struct ast_channel *c) { unsigned short callno = PTR_TO_CALLNO(c->pvt->pvt); int alreadygone; + struct iax_ie_data ied; + memset(&ied, 0, sizeof(ied)); ast_mutex_lock(&iaxsl[callno]); if (callno && iaxs[callno]) { ast_log(LOG_DEBUG, "We're hanging up %s now...\n", c->name); alreadygone = ast_test_flag(iaxs[callno], IAX_ALREADYGONE); /* Send the hangup unless we have had a transmission error or are already gone */ + iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, (unsigned char)c->hangupcause); if (!iaxs[callno]->error && !alreadygone) - send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, NULL, 0, -1); + send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); /* Explicitly predestroy it */ iax2_predestroy_nolock(callno); /* If we were already gone to begin with, destroy us now */ @@ -4653,8 +4657,10 @@ static int auth_reject(void *nothing) memset(&ied, 0, sizeof(ied)); if (iaxs[callno]->authfail == IAX_COMMAND_REGREJ) { iax_ie_append_str(&ied, IAX_IE_CAUSE, "Registration Refused"); + iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_REJECTED); } else if (iaxs[callno]->authfail == IAX_COMMAND_REJECT) { iax_ie_append_str(&ied, IAX_IE_CAUSE, "No authority found"); + iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); } send_command_final(iaxs[callno], AST_FRAME_IAX, iaxs[callno]->authfail, 0, ied.buf, ied.pos, -1); } @@ -4690,6 +4696,7 @@ static int auto_hangup(void *nothing) iaxs[callno]->autoid = -1; memset(&ied, 0, sizeof(ied)); iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout"); + iax_ie_append_byte(&ied, IAX_IE_CAUSECODE, AST_CAUSE_NO_USER_RESPONSE); send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_HANGUP, 0, ied.buf, ied.pos, -1); } ast_mutex_unlock(&iaxsl[callno]); @@ -5479,6 +5486,7 @@ retryowner: if (strcmp(iaxs[fr.callno]->exten, "TBD") && !exists) { memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); + iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (authdebug) ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context); @@ -5490,6 +5498,7 @@ retryowner: if (!format) { memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); + iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (authdebug) ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->peercapability, iaxs[fr.callno]->capability); @@ -5499,6 +5508,7 @@ retryowner: if (!format) { memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); + iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); ast_log(LOG_ERROR, "No best format in 0x%x???\n", iaxs[fr.callno]->peercapability & iaxs[fr.callno]->capability); send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (authdebug) @@ -5549,6 +5559,10 @@ retryowner: case IAX_COMMAND_HANGUP: ast_set_flag(iaxs[fr.callno], IAX_ALREADYGONE); ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr.callno); + /* Set hangup cause according to remote */ + ast_log(LOG_NOTICE, "Remote sent causecode %d\n", ies.causecode); + if (ies.causecode) + iaxs[fr.callno]->owner->hangupcause = ies.causecode; /* Send ack immediately, before we destroy */ send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno); iax2_destroy_nolock(fr.callno); @@ -5615,6 +5629,7 @@ retryowner: if (!(iaxs[fr.callno]->peerformat & iaxs[fr.callno]->capability)) { memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); + iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); if (authdebug) ast_log(LOG_NOTICE, "Rejected call to %s, format 0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->capability); @@ -5777,6 +5792,7 @@ retryowner2: ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context); memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); + iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); } else { /* Select an appropriate format */ @@ -5789,6 +5805,7 @@ retryowner2: ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->peercapability, iaxs[fr.callno]->capability); memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); + iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); } else { /* Pick one... */ @@ -5799,6 +5816,7 @@ retryowner2: ast_log(LOG_NOTICE, "Rejected connect attempt from %s, requested/capability 0x%x/0x%x incompatible with our capability 0x%x.\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->peerformat, iaxs[fr.callno]->peercapability, iaxs[fr.callno]->capability); memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); + iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); } } @@ -5834,6 +5852,7 @@ retryowner2: ast_log(LOG_NOTICE, "Rejected dial attempt from %s, request '%s@%s' does not exist\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context); memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No such context/extension"); + iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_NO_ROUTE_DESTINATION); send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); } else { iaxs[fr.callno]->state |= IAX_STATE_STARTED; @@ -5903,6 +5922,7 @@ retryowner2: if (registry_rerequest(&ies, fr.callno, &sin)) { memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "No authority found"); + iax_ie_append_byte(&ied0, IAX_IE_CAUSECODE, AST_CAUSE_FACILITY_NOT_SUBSCRIBED); send_command_final(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_REJECT, 0, ied0.buf, ied0.pos, -1); } break; diff --git a/channels/iax2-parser.c b/channels/iax2-parser.c index 90d4822556..5ce9191deb 100755 --- a/channels/iax2-parser.c +++ b/channels/iax2-parser.c @@ -648,6 +648,14 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen) case IAX_IE_CAUSE: ies->cause = data + 2; break; + case IAX_IE_CAUSECODE: + if (len != 1) { + snprintf(tmp, (int)sizeof(tmp), "Expecting causecode to be single byte but was %d\n", len); + errorf(tmp); + } else { + ies->causecode = data[2]; + } + break; case IAX_IE_IAX_UNKNOWN: if (len == 1) ies->iax_unknown = data[2]; diff --git a/channels/iax2-parser.h b/channels/iax2-parser.h index cb29a088e2..8f74d24869 100755 --- a/channels/iax2-parser.h +++ b/channels/iax2-parser.h @@ -41,6 +41,7 @@ struct iax_ies { unsigned short dpstatus; unsigned short callno; char *cause; + unsigned char causecode; unsigned char iax_unknown; int msgcount; int autoanswer; diff --git a/channels/iax2.h b/channels/iax2.h index 83817442dd..f145b45bda 100755 --- a/channels/iax2.h +++ b/channels/iax2.h @@ -116,6 +116,7 @@ #define IAX_IE_CALLINGTON 39 /* Calling type of number (u8) */ #define IAX_IE_CALLINGTNS 40 /* Calling transit network select (u16) */ #define IAX_IE_SAMPLINGRATE 41 /* Supported sampling rates (u16) */ +#define IAX_IE_CAUSECODE 42 /* Hangup cause (u8) */ #define IAX_AUTH_PLAINTEXT (1 << 0) #define IAX_AUTH_MD5 (1 << 1)