[Asterisk-Dev] IAX2 Frame_Text to send Hangup Cause

Tilghman Lesher tilghman at mail.jeffandtilghman.com
Fri Dec 10 11:42:35 MST 2004


On Friday 10 December 2004 12:13, Tilghman Lesher wrote:
> On Friday 10 December 2004 11:22, reseaux wrote:
> > 	i know is not a solution but is a great Hack!! With my little Remove of
> > the two line in Chan_iax2.c i can give any problem? Can you give me some
> > idea how to replace this two line in Chan_iax2.c for example:
> > --------------------
> > /* Set hangup cause */
> > 	if AST_FRAME_TEXT != "hangupcause=" {
> >           if (ies.cause)
> > 		iaxs[fr.callno]->owner->hangupcause = atoi(ies.cause);
> > 	}
> > ---------------------
> > Is not C code line :-) but i use to explain how want fix it.
>
> Attached is a better way to do it, given some time to look at the code
> and find the right way to send messages.  What I've done is to create a
> Q.931 code to be sent along with a IAX_COMMAND_HANGUP frame and
> receive that code on the remote end, to be inserted into the channel
> hangupcause at the appropriate time.
>
> BTW, this is a patch against CVS, so I have no idea if it will cleanly
> apply against one of the releases.

Ooops, missed the most critical case...

-- 
Tilghman
-------------- next part --------------
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)


More information about the asterisk-dev mailing list