[libpri-commits] trunk - r297 /trunk/

libpri-commits at lists.digium.com libpri-commits at lists.digium.com
Thu Jan 19 11:22:06 MST 2006


Author: mattf
Date: Thu Jan 19 12:22:06 2006
New Revision: 297

URL: http://svn.digium.com/view/libpri?rev=297&view=rev
Log:
Numerous updates for RLT (just remember, trunk can be a bumpy ride)

Modified:
    trunk/pri.c
    trunk/pri_facility.c
    trunk/pri_facility.h
    trunk/pri_internal.h
    trunk/q931.c

Modified: trunk/pri.c
URL: http://svn.digium.com/view/libpri/trunk/pri.c?rev=297&r1=296&r2=297&view=diff
==============================================================================
--- trunk/pri.c (original)
+++ trunk/pri.c Thu Jan 19 12:22:06 2006
@@ -543,10 +543,13 @@
 	if (call1->pri != call2->pri)
 		return -1;
 	
-	if (eect_initiate_transfer(call1->pri, call1, call2))
-		return -1;
-
-	return 0;
+	if (call1->pri->switchtype == PRI_SWITCH_LUCENT5E)
+		return eect_initiate_transfer(call1->pri, call1, call2);
+
+	if (call1->pri->switchtype == PRI_SWITCH_DMS100)
+		return rlt_initiate_transfer(call1->pri, call1, call2);
+
+	return -1;
 }
 
 int pri_hangup(struct pri *pri, q931_call *call, int cause)

Modified: trunk/pri_facility.c
URL: http://svn.digium.com/view/libpri/trunk/pri_facility.c?rev=297&r1=296&r2=297&view=diff
==============================================================================
--- trunk/pri_facility.c (original)
+++ trunk/pri_facility.c Thu Jan 19 12:22:06 2006
@@ -836,6 +836,84 @@
 		return -1;
 		
 	return 0;
+}
+
+/* Send the rltThirdParty: Invoke */
+extern int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
+{
+	int i = 0;
+	unsigned char buffer[256];
+	struct rose_component *comp = NULL, *compstk[10];
+	const unsigned char rlt_3rd_pty = RLT_THIRD_PARTY;
+	q931_call *callwithid = NULL, *apdubearer = NULL;
+	int compsp = 0;
+
+	if (c2->transferable) {
+		apdubearer = c1;
+		callwithid = c2;
+	} else if (c1->transferable) {
+		apdubearer = c2;
+		callwithid = c1;
+	} else
+		return -1;
+
+	buffer[i++] = (0x80 | Q932_PROTOCOL_ROSE);
+	buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */
+
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+
+	/* Invoke ID is set to the operation ID */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty);
+
+	/* Operation Tag */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty);
+
+	/* Additional RLT invoke info - Octet 12 */
+	ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+
+	ASN1_ADD_WORDCOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, callwithid->rlt_call_id & 0xFFFFFF); /* Length is 3 octets */
+	/* Reason for redirect - unused, set to 129 */
+	ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i, 0);
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	if (pri_call_apdu_queue(apdubearer, Q931_FACILITY, buffer, i, NULL, NULL))
+		return -1;
+
+	if (q931_facility(apdubearer->pri, apdubearer)) {
+		pri_message(pri, "Could not schedule facility message for call %d\n", apdubearer->cr);
+		return -1;
+	}
+	return 0;
+}
+
+static int add_dms100_transfer_ability_apdu(struct pri *pri, q931_call *c)
+{
+	int i = 0;
+	unsigned char buffer[256];
+	struct rose_component *comp = NULL, *compstk[10];
+	const unsigned char rlt_op_ind = RLT_OPERATION_IND;
+	int compsp = 0;
+
+	buffer[i++] = (0x80 | Q932_PROTOCOL_ROSE);
+	buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */
+
+	ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+	ASN1_PUSH(compstk, compsp, comp);
+
+	/* Invoke ID is set to the operation ID */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind);
+	
+	/* Operation Tag - basically the same as the invoke ID tag */
+	ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind);
+	ASN1_FIXUP(compstk, compsp, buffer, i);
+
+	if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL))
+		return -1;
+	else
+		return 0;
 }
 
 /* Sending callername information functions */
@@ -1270,6 +1348,200 @@
 }
 /* End AOC */
 
+extern int rose_reject_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
+{
+	int i = 0;
+	int problemtag = -1;
+	int problem = -1;
+	int invokeidvalue = -1;
+	unsigned char *vdata = data;
+	struct rose_component *comp = NULL;
+	char *problemtagstr, *problemstr;
+	
+	do {
+		/* Invoke ID stuff */
+		GET_COMPONENT(comp, i, vdata, len);
+		CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
+		ASN1_GET_INTEGER(comp, invokeidvalue);
+		NEXT_COMPONENT(comp, i);
+
+		GET_COMPONENT(comp, i, vdata, len);
+		problemtag = comp->type;
+		problem = comp->data[0];
+
+		if (pri->switchtype == PRI_SWITCH_DMS100) {
+			switch (problemtag) {
+			case 0x80:
+				problemtagstr = "General problem";
+				break;
+			case 0x81:
+				problemtagstr = "Invoke problem";
+				break;
+			case 0x82:
+				problemtagstr = "Return result problem";
+				break;
+			case 0x83:
+				problemtagstr = "Return error problem";
+				break;
+			default:
+				problemtagstr = "Unknown";
+			}
+
+			switch (problem) {
+			case 0x00:
+				problemstr = "Unrecognized component";
+				break;
+			case 0x01:
+				problemstr = "Mistyped component";
+				break;
+			case 0x02:
+				problemstr = "Badly structured component";
+				break;
+			default:
+				problemstr = "Unknown";
+			}
+
+			pri_error(pri, "ROSE REJECT:\n");
+			pri_error(pri, "\tINVOKE ID: 0x%X\n", invokeidvalue);
+			pri_error(pri, "\tPROBLEM TYPE: %s (0x%x)\n", problemtagstr, problemtag);
+			pri_error(pri, "\tPROBLEM: %s (0x%x)\n", problemstr, problem);
+
+			return 0;
+		} else {
+			pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
+			return -1;
+		}
+
+	} while(0);
+	
+	return -1;
+}
+extern int rose_return_error_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
+{
+	int i = 0;
+	int errorvalue = -1;
+	int invokeidvalue = -1;
+	unsigned char *vdata = data;
+	struct rose_component *comp = NULL;
+	char *invokeidstr, *errorstr;
+	
+	do {
+		/* Invoke ID stuff */
+		GET_COMPONENT(comp, i, vdata, len);
+		CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
+		ASN1_GET_INTEGER(comp, invokeidvalue);
+		NEXT_COMPONENT(comp, i);
+
+		GET_COMPONENT(comp, i, vdata, len);
+		CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second component in return error is 0x%x\n");
+		ASN1_GET_INTEGER(comp, errorvalue);
+
+		if (pri->switchtype == PRI_SWITCH_DMS100) {
+			switch (invokeidvalue) {
+			case RLT_OPERATION_IND:
+				invokeidstr = "RLT_OPERATION_IND";
+				break;
+			case RLT_THIRD_PARTY:
+				invokeidstr = "RLT_THIRD_PARTY";
+				break;
+			default:
+				invokeidstr = "Unknown";
+			}
+
+			switch (errorvalue) {
+			case 0x10:
+				errorstr = "RLT Bridge Fail";
+				break;
+			case 0x11:
+				errorstr = "RLT Call ID Not Found";
+				break;
+			case 0x12:
+				errorstr = "RLT Not Allowed";
+				break;
+			case 0x13:
+				errorstr = "RLT Switch Equip Congs";
+				break;
+			default:
+				errorstr = "Unknown";
+			}
+
+			pri_error(pri, "ROSE RETURN ERROR:\n");
+			pri_error(pri, "\tOPERATION: %s\n", invokeidstr);
+			pri_error(pri, "\tERROR: %s\n", errorstr);
+
+			return 0;
+		} else {
+			pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
+			return -1;
+		}
+
+	} while(0);
+	
+	return -1;
+}
+
+extern int rose_return_result_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
+{
+	int i = 0;
+	int operationidvalue = -1;
+	int invokeidvalue = -1;
+	unsigned char *vdata = data;
+	struct rose_component *comp = NULL;
+	
+	do {
+		/* Invoke ID stuff */
+		GET_COMPONENT(comp, i, vdata, len);
+		CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
+		ASN1_GET_INTEGER(comp, invokeidvalue);
+		NEXT_COMPONENT(comp, i);
+
+		if (pri->switchtype == PRI_SWITCH_DMS100) {
+			switch (invokeidvalue) {
+			case RLT_THIRD_PARTY:
+				if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Successfully completed RLT transfer!\n");
+				return 0;
+			case RLT_OPERATION_IND:
+				if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Received RLT_OPERATION_IND\n");
+				/* Have to take out the rlt_call_id */
+				GET_COMPONENT(comp, i, vdata, len);
+				CHECK_COMPONENT(comp, ASN1_SEQUENCE, "Protocol error detected in parsing RLT_OPERATION_IND return result!\n");
+
+				/* Traverse the contents of this sequence */
+				/* First is the Operation Value */
+				SUB_COMPONENT(comp, i);
+				GET_COMPONENT(comp, i, vdata, len);
+				CHECK_COMPONENT(comp, ASN1_INTEGER, "RLT_OPERATION_IND should be of type ASN1_INTEGER!\n");
+				ASN1_GET_INTEGER(comp, operationidvalue);
+
+				if (operationidvalue != RLT_OPERATION_IND) {
+					pri_message(pri, "Invalid Operation ID value (0x%x) in return result!\n", operationidvalue);
+					return -1;
+				}
+
+				/*  Next is the Call ID */
+				NEXT_COMPONENT(comp, i);
+				GET_COMPONENT(comp, i, vdata, len);
+				CHECK_COMPONENT(comp, (ASN1_CONTEXT_SPECIFIC|ASN1_TAG_0), "Error check failed on Call ID!\n");
+				ASN1_GET_INTEGER(comp, call->rlt_call_id);
+				/* We have enough data to transfer the call */
+				call->transferable = 1;
+
+				return 0;
+				
+			default:
+				pri_message(pri, "Could not parse invoke of type 0x%x!\n", invokeidvalue);
+				return -1;
+			}
+		} else {
+			pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
+			return -1;
+		}
+
+	} while(0);
+	
+	return -1;
+}
+
 extern int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
 {
 	int i = 0;
@@ -1474,6 +1746,12 @@
 		add_callername_facility_ies(pri, call, (pri->localtype == PRI_CPE));
 #endif
 
+	if ((pri->switchtype == PRI_SWITCH_DMS100) && (pri->localtype == PRI_CPE)) {
+		add_dms100_transfer_ability_apdu(pri, call);
+	}
+
+
+
 	return 0;
 }
 

Modified: trunk/pri_facility.h
URL: http://svn.digium.com/view/libpri/trunk/pri_facility.h?rev=297&r1=296&r2=297&view=diff
==============================================================================
--- trunk/pri_facility.h (original)
+++ trunk/pri_facility.h Thu Jan 19 12:22:06 2006
@@ -104,7 +104,7 @@
 #define ASN1_CLAN_MASK			0xc0
 #define ASN1_UNIVERSAL			0x00
 #define ASN1_APPLICATION		0x40
-#define ASN1_CONTEXT_SPECIFIC	0x80
+#define ASN1_CONTEXT_SPECIFIC		0x80
 #define ASN1_PRIVATE			0xc0
 
 /* ASN.1 Length masks */
@@ -134,6 +134,11 @@
 #define Q932_TON_NET_SPECIFIC			0x03
 #define Q932_TON_SUBSCRIBER				0x04
 #define Q932_TON_ABBREVIATED			0x06
+
+/* RLT related Operations */
+#define RLT_SERVICE_ID		0x3e
+#define RLT_OPERATION_IND	0x01
+#define RLT_THIRD_PARTY		0x02
 
 struct rose_component {
 	u_int8_t type;
@@ -230,8 +235,17 @@
 		(stack)[(stackpointer)]->len = (unsigned char *)&((data)[(idx)]) - (unsigned char *)(stack)[(stackpointer)] - 2; \
 	} while (0)
 
-/* Decoder for the invoke part of a ROSE request */
+/* Decoder for the invoke ROSE component */
 extern int rose_invoke_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
+
+/* Decoder for the return result ROSE component */
+extern int rose_return_result_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
+
+/* Decoder for the return error ROSE component */
+extern int rose_return_error_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
+
+/* Decoder for the reject ROSE component */
+extern int rose_reject_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
 
 extern int asn1_copy_string(char * buf, int buflen, struct rose_component *comp);
 
@@ -249,6 +263,8 @@
 
 /* starts a 2BCT */
 extern int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
+
+extern int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
 
 /* Use this function to queue a facility-IE born APDU onto a call
  * call is the call to use, messagetype is any one of the Q931 messages,

Modified: trunk/pri_internal.h
URL: http://svn.digium.com/view/libpri/trunk/pri_internal.h?rev=297&r1=296&r2=297&view=diff
==============================================================================
--- trunk/pri_internal.h (original)
+++ trunk/pri_internal.h Thu Jan 19 12:22:06 2006
@@ -130,6 +130,7 @@
 	int redirectingreason;
 	int justsignalling;
 	const char *useruserinfo;
+	int transferable;
 };
 
 /* Internal switch types */
@@ -239,6 +240,9 @@
 	long aoc_units;				/* Advice of Charge Units */
 
 	struct apdu_event *apdus;	/* APDU queue for call */
+
+	int transferable;
+	unsigned int rlt_call_id;	/* RLT call id */
 };
 
 extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);

Modified: trunk/q931.c
URL: http://svn.digium.com/view/libpri/trunk/q931.c?rev=297&r1=296&r2=297&view=diff
==============================================================================
--- trunk/q931.c (original)
+++ trunk/q931.c Thu Jan 19 12:22:06 2006
@@ -1216,9 +1216,9 @@
 			case Q932_PROTOCOL_ROSE:
 				switch (comp->type) {
 				Q932_HANDLE_PROC(COMP_TYPE_INVOKE, Q932_STATE_SERVICE, "ROSE Invoke", rose_invoke_decode);
-				Q932_HANDLE_NULL(COMP_TYPE_RETURN_RESULT, Q932_STATE_SERVICE, "ROSE return result", NULL);
-				Q932_HANDLE_NULL(COMP_TYPE_RETURN_ERROR, Q932_STATE_SERVICE, "ROSE return error", NULL);
-				Q932_HANDLE_NULL(COMP_TYPE_REJECT, Q932_STATE_SERVICE, "ROSE reject", NULL);
+				Q932_HANDLE_PROC(COMP_TYPE_RETURN_RESULT, Q932_STATE_SERVICE, "ROSE return result", rose_return_result_decode);
+				Q932_HANDLE_PROC(COMP_TYPE_RETURN_ERROR, Q932_STATE_SERVICE, "ROSE return error", rose_return_error_decode);
+				Q932_HANDLE_PROC(COMP_TYPE_REJECT, Q932_STATE_SERVICE, "ROSE reject", rose_reject_decode);
 				default:
 					if (pri->debug & PRI_DEBUG_APDU)
 						pri_message(pri, "Don't know how to handle ROSE component of type 0x%X\n", comp->type);



More information about the libpri-commits mailing list