Index: channels/chan_iax2.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_iax2.c,v retrieving revision 1.221 diff -u -r1.221 chan_iax2.c --- channels/chan_iax2.c 29 Nov 2004 03:24:35 -0000 1.221 +++ channels/chan_iax2.c 10 Dec 2004 18:38:51 -0000 @@ -1489,6 +1489,7 @@ 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)); @@ -2381,13 +2382,16 @@ { 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 = iaxs[callno]->alreadygone; /* Send the hangup unless we have had a transmission error or are already gone */ + iax_ie_append_int(&ied, IAX_IE_CAUSECODE, 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 */ @@ -4634,8 +4638,10 @@ 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_int(&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_int(&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); } @@ -4671,6 +4677,7 @@ iaxs[callno]->autoid = -1; memset(&ied, 0, sizeof(ied)); iax_ie_append_str(&ied, IAX_IE_CAUSE, "Timeout"); + iax_ie_append_int(&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]); @@ -5460,6 +5467,7 @@ 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_int(&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); @@ -5471,6 +5479,7 @@ if (!format) { memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); + iax_ie_append_int(&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); @@ -5480,6 +5489,7 @@ if (!format) { memset(&ied0, 0, sizeof(ied0)); iax_ie_append_str(&ied0, IAX_IE_CAUSE, "Unable to negotiate codec"); + iax_ie_append_int(&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) @@ -5530,6 +5540,9 @@ case IAX_COMMAND_HANGUP: iaxs[fr.callno]->alreadygone = 1; ast_log(LOG_DEBUG, "Immediately destroying %d, having received hangup\n", fr.callno); + /* Set hangup cause according to remote */ + 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); @@ -5596,6 +5609,7 @@ 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_int(&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); @@ -5758,6 +5772,7 @@ 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_int(&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 */ @@ -5770,6 +5785,7 @@ 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_int(&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... */ @@ -5780,6 +5796,7 @@ 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_int(&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); } } @@ -5815,6 +5832,7 @@ 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_int(&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; @@ -5884,6 +5902,7 @@ 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_int(&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; Index: channels/iax2-parser.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/iax2-parser.c,v retrieving revision 1.30 diff -u -r1.30 iax2-parser.c --- channels/iax2-parser.c 19 Nov 2004 21:52:25 -0000 1.30 +++ channels/iax2-parser.c 10 Dec 2004 18:38:51 -0000 @@ -632,6 +632,13 @@ case IAX_IE_CAUSE: ies->cause = data + 2; break; + case IAX_IE_CAUSECODE: + if (len != (int)sizeof(unsigned int)) { + snprintf(tmp, (int)sizeof(tmp), "Expecting format to be %d bytes long but was %d\n", (int)sizeof(unsigned int), len); + errorf(tmp); + } else + ies->causecode = ntohl(*((unsigned int *)(data + 2))); + break; case IAX_IE_IAX_UNKNOWN: if (len == 1) ies->iax_unknown = data[2]; Index: channels/iax2-parser.h =================================================================== RCS file: /usr/cvsroot/asterisk/channels/iax2-parser.h,v retrieving revision 1.11 diff -u -r1.11 iax2-parser.h --- channels/iax2-parser.h 19 Nov 2004 21:52:25 -0000 1.11 +++ channels/iax2-parser.h 10 Dec 2004 18:38:51 -0000 @@ -41,6 +41,7 @@ unsigned short dpstatus; unsigned short callno; char *cause; + unsigned int causecode; unsigned char iax_unknown; int msgcount; int autoanswer; Index: channels/iax2.h =================================================================== RCS file: /usr/cvsroot/asterisk/channels/iax2.h,v retrieving revision 1.17 diff -u -r1.17 iax2.h --- channels/iax2.h 19 Nov 2004 21:52:25 -0000 1.17 +++ channels/iax2.h 10 Dec 2004 18:38:51 -0000 @@ -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 - int */ #define IAX_AUTH_PLAINTEXT (1 << 0) #define IAX_AUTH_MD5 (1 << 1)