[asterisk-commits] pcadach: branch pcadach/chan_h323-live r43035 - in /team/pcadach/chan_h323-li...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Sat Sep 16 12:45:44 MST 2006


Author: pcadach
Date: Sat Sep 16 14:45:43 2006
New Revision: 43035

URL: http://svn.digium.com/view/asterisk?rev=43035&view=rev
Log:
Provide support for redirection information and signalling messages tunnelling (for Cisco CallManager interoperability)

Added:
    team/pcadach/chan_h323-live/channels/h323/cisco-h225.asn   (with props)
    team/pcadach/chan_h323-live/channels/h323/cisco-h225.cpp   (with props)
    team/pcadach/chan_h323-live/channels/h323/cisco-h225.h   (with props)
Modified:
    team/pcadach/chan_h323-live/channels/chan_h323.c
    team/pcadach/chan_h323-live/channels/h323/Makefile
    team/pcadach/chan_h323-live/channels/h323/Makefile.in
    team/pcadach/chan_h323-live/channels/h323/ast_h323.cpp
    team/pcadach/chan_h323-live/channels/h323/ast_h323.h
    team/pcadach/chan_h323-live/channels/h323/chan_h323.h

Modified: team/pcadach/chan_h323-live/channels/chan_h323.c
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323-live/channels/chan_h323.c?rev=43035&r1=43034&r2=43035&view=diff
==============================================================================
--- team/pcadach/chan_h323-live/channels/chan_h323.c (original)
+++ team/pcadach/chan_h323-live/channels/chan_h323.c Sat Sep 16 14:45:43 2006
@@ -262,6 +262,22 @@
 #endif
 };
 
+static const char* redirectingreason2str(int redirectingreason)
+{
+	switch (redirectingreason) {
+	case 0:
+		return "UNKNOWN";
+	case 1:
+		return "BUSY";
+	case 2:
+		return "NO_REPLY";
+	case 0xF:
+		return "UNCONDITIONAL";
+	default:
+		return "NOREDIRECT";
+	}
+}
+
 static void oh323_destroy_alias(struct oh323_alias *alias)
 {
 	if (h323debug)
@@ -422,11 +438,20 @@
 		free(cd->sourceIp);
 		cd->sourceIp = NULL;
 	}
+	if (cd->redirect_number) {
+		free(cd->redirect_number);
+		cd->redirect_number = NULL;
+	}
 }
 
 static void __oh323_destroy(struct oh323_pvt *pvt)
 {
 	struct oh323_pvt *cur, *prev = NULL;
+
+	if (pvt->DTMFsched >= 0) {
+		ast_sched_del(sched, pvt->DTMFsched);
+		pvt->DTMFsched = -1;
+	}
 	
 	if (pvt->rtp) {
 		ast_rtp_destroy(pvt->rtp);
@@ -594,6 +619,26 @@
 
 	if (c->cid.cid_name)
 		strncpy(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name));
+
+	if (c->cid.cid_rdnis) {
+		strncpy(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis));
+		ast_log(LOG_NOTICE, "Settint RDNIS to %s\n", c->cid.cid_rdnis);
+	}
+	
+	if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) {
+		ast_log(LOG_NOTICE, "PRI redirect reason is %s\n", addr);
+		if (!strcasecmp(addr, "UNKNOWN"))
+			pvt->options.redirect_reason = 0;
+		else if (!strcasecmp(addr, "BUSY"))
+			pvt->options.redirect_reason = 1;
+		else if (!strcasecmp(addr, "NO_REPLY"))
+			pvt->options.redirect_reason = 2;
+		else if (!strcasecmp(addr, "UNCONDITIONAL"))
+			pvt->options.redirect_reason = 15;
+		else
+			pvt->options.redirect_reason = -1;
+	} else
+		pvt->options.redirect_reason = -1;
 
 	/* indicate that this is an outgoing call */
 	pvt->outgoing = 1;
@@ -1023,7 +1068,10 @@
 			ch->cid.cid_name = ast_strdup(pvt->options.cid_name);
 		else
 			ch->cid.cid_name = ast_strdup(pvt->cd.call_source_name);
-		ch->cid.cid_rdnis = ast_strdup(pvt->rdnis);
+		if (pvt->cd.redirect_reason >= 0) {
+			ch->cid.cid_rdnis = ast_strdup(pvt->cd.redirect_number);
+			pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason));
+		}
 		
 		if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) {
 			ch->cid.cid_dnid = strdup(pvt->exten);
@@ -1056,6 +1104,7 @@
 		return NULL;
 	}
 	memset(pvt, 0, sizeof(struct oh323_pvt));
+	pvt->cd.redirect_reason = -1;
 #if 0
 	pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0,bindaddr.sin_addr);
 	if (!pvt->rtp) {
@@ -2024,12 +2073,14 @@
 
 	if (h323debug) {
 		ast_verbose(VERBOSE_PREFIX_3 "Setting up Call\n");
-		ast_verbose(VERBOSE_PREFIX_3 "\tCall token:  [%s]\n", pvt->cd.call_token);
-		ast_verbose(VERBOSE_PREFIX_3 "\tCalling party name:  [%s]\n", pvt->cd.call_source_name);
-		ast_verbose(VERBOSE_PREFIX_3 "\tCalling party number:  [%s]\n", pvt->cd.call_source_e164);
-		ast_verbose(VERBOSE_PREFIX_3 "\tCalled party name:  [%s]\n", pvt->cd.call_dest_alias);
-		ast_verbose(VERBOSE_PREFIX_3 "\tCalled party number:  [%s]\n", pvt->cd.call_dest_e164);
-		ast_verbose(VERBOSE_PREFIX_3 "\tCalling party IP:  [%s]\n", pvt->cd.sourceIp);
+		ast_verbose(VERBOSE_PREFIX_3 " \tCall token:  [%s]\n", pvt->cd.call_token);
+		ast_verbose(VERBOSE_PREFIX_3 " \tCalling party name:  [%s]\n", pvt->cd.call_source_name);
+		ast_verbose(VERBOSE_PREFIX_3 " \tCalling party number:  [%s]\n", pvt->cd.call_source_e164);
+		ast_verbose(VERBOSE_PREFIX_3 " \tCalled party name:  [%s]\n", pvt->cd.call_dest_alias);
+		ast_verbose(VERBOSE_PREFIX_3 " \tCalled party number:  [%s]\n", pvt->cd.call_dest_e164);
+		if (pvt->cd.redirect_reason >= 0)
+			ast_verbose(VERBOSE_PREFIX_3 " \tRedirecting party number:  [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);
+		ast_verbose(VERBOSE_PREFIX_3 " \tCalling party IP:  [%s]\n", pvt->cd.sourceIp);
 	}
 
 	/* Decide if we are allowing Gatekeeper routed calls*/

Modified: team/pcadach/chan_h323-live/channels/h323/Makefile
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323-live/channels/h323/Makefile?rev=43035&r1=43034&r2=43035&view=diff
==============================================================================
--- team/pcadach/chan_h323-live/channels/h323/Makefile (original)
+++ team/pcadach/chan_h323-live/channels/h323/Makefile Sat Sep 16 14:45:43 2006
@@ -16,7 +16,7 @@
 CFLAGS		= -pipe
 TARGET		= libchanh323.a
 TARGET		+= Makefile.ast
-SOURCES		= ast_h323.cxx compat_h323.cxx
+SOURCES		= ast_h323.cxx compat_h323.cxx cisco-h225.cxx
 OBJDIR		= .
 OBJS		=
 
@@ -44,6 +44,10 @@
 libchanh323.a:	$(OBJS)
 	ar crv $@ $(OBJS)
 
+cisco-h225.cpp::	cisco-h225.asn
+	asnparser -m CISCO_H225 -c $<
+	mv -f cisco-h225.cxx cisco-h225.cpp
+
 Makefile.ast:
 	@echo H323CFLAGS  = $(STDCCFLAGS) $(OPTCCFLAGS) $(CFLAGS) >$@.tmp
 	@echo H323LDFLAGS = $(CFLAGS) $(LDFLAGS) >>$@.tmp

Modified: team/pcadach/chan_h323-live/channels/h323/Makefile.in
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323-live/channels/h323/Makefile.in?rev=43035&r1=43034&r2=43035&view=diff
==============================================================================
--- team/pcadach/chan_h323-live/channels/h323/Makefile.in (original)
+++ team/pcadach/chan_h323-live/channels/h323/Makefile.in Sat Sep 16 14:45:43 2006
@@ -16,7 +16,7 @@
 CFLAGS		= -pipe
 TARGET		= libchanh323.a
 TARGET		+= Makefile.ast
-SOURCES		= ast_h323.cxx compat_h323.cxx
+SOURCES		= ast_h323.cxx compat_h323.cxx cisco-h225.cxx
 OBJDIR		= .
 OBJS		=
 
@@ -44,6 +44,10 @@
 libchanh323.a:	$(OBJS)
 	ar crv $@ $(OBJS)
 
+cisco-h225.cpp::	cisco-h225.asn
+	asnparser -m CISCO_H225 -c $<
+	mv -f cisco-h225.cxx cisco-h225.cpp
+
 Makefile.ast:
 	@echo H323CFLAGS  = $(STDCCFLAGS) $(OPTCCFLAGS) $(CFLAGS) >$@.tmp
 	@echo H323LDFLAGS = $(CFLAGS) $(LDFLAGS) >>$@.tmp

Modified: team/pcadach/chan_h323-live/channels/h323/ast_h323.cpp
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323-live/channels/h323/ast_h323.cpp?rev=43035&r1=43034&r2=43035&view=diff
==============================================================================
--- team/pcadach/chan_h323-live/channels/h323/ast_h323.cpp (original)
+++ team/pcadach/chan_h323-live/channels/h323/ast_h323.cpp Sat Sep 16 14:45:43 2006
@@ -52,6 +52,7 @@
 
 #include "chan_h323.h"
 #include "ast_h323.h"
+#include "cisco-h225.h"
 
 /* PWlib Required Components  */
 #define MAJOR_VERSION 1
@@ -451,7 +452,7 @@
 		}
 		return 1;
 	}
-	*callReference = connection->GetCallReference();	
+	*callReference = connection->GetCallReference();
 
 	if (h323debug) {
 		cout << "\t-- " << GetLocalUserName() << " is calling host " << fullAddress << endl;
@@ -695,8 +696,13 @@
 	}
 #endif
 	conn = new MyH323Connection(*this, callReference, options);
-	if (conn && opts) {
-		conn->SetCallOptions(opts, (setupPDU ? TRUE : FALSE));
+	if (conn) {
+#ifdef TUNNELLING
+		conn->tunnelQSIG = FALSE;
+		conn->remoteTunnelQSIG = FALSE;
+#endif
+		if (opts)
+			conn->SetCallOptions(opts, (setupPDU ? TRUE : FALSE));
 	}
 	return conn;
 }
@@ -707,6 +713,12 @@
 	: H323Connection(ep, callReference, options)
 {
 	cause = -1;
+	sessionId = 0;
+	bridging = FALSE;
+	progressSetup = progressAlert = 0;
+	dtmfMode = 0;
+	dtmfCodec = (RTP_DataFrame::PayloadTypes)0;
+	redirect_reason = -1;
 	if (h323debug) {
 		cout << "	== New H.323 Connection created." << endl;
 	}
@@ -751,7 +763,7 @@
 
 H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller,
 								const H323SignalPDU & setupPDU,
-								H323SignalPDU & /*connectPDU*/)
+								H323SignalPDU & connectPDU)
 {
 	unsigned pi;
 
@@ -773,12 +785,18 @@
 	} else if (pi == Q931::ProgressOriginNotISDN) {
 		pi = Q931::ProgressInbandInformationAvailable;
 	}
-	if (pi) {
+	if (pi && alertingPDU) {
 		alertingPDU->GetQ931().SetProgressIndicator(pi);
 	}
 	if (h323debug) {
 		cout << "\t\t- Inserting PI of " << pi << " into ALERTING message" << endl;
 	}
+
+#ifdef TUNNELLING
+	if (alertingPDU)
+		EmbedTunneledInfo(*alertingPDU);
+	EmbedTunneledInfo(connectPDU);
+#endif
 
 	if (!on_answer_call(GetCallReference(), (const char *)GetCallToken())) {
 		return H323Connection::AnswerCallDenied;
@@ -831,26 +849,15 @@
 	dtmfMode = opts->dtmfmode;
 
 	if (isIncoming) {
-		if (opts->fastStart)
-			fastStartState = FastStartInitiate;
-		else
-			fastStartState = FastStartDisabled;
-
-		if (opts->h245Tunneling)
-			h245Tunneling = TRUE;
-		else
-			h245Tunneling = FALSE;
-	}
-
-	if (opts->cid_num) {
-		ast_cid_num = PString(opts->cid_num);
-		if (!isIncoming)
-			SetLocalPartyName(ast_cid_num);
-	}
-	if (opts->cid_name) {
-		ast_cid_name = PString(opts->cid_name);
-		if (!isIncoming)
-			SetDisplayName(ast_cid_name);
+		fastStartState = (opts->fastStart ? FastStartInitiate : FastStartDisabled);
+		h245Tunneling = (opts->h245Tunneling ? TRUE : FALSE);
+	} else {
+		SetLocalPartyName(PString(opts->cid_num));
+		SetDisplayName(PString(opts->cid_name));
+		if (opts->redirect_reason >= 0) {
+			rdnis = PString(opts->cid_rdnis);
+			redirect_reason = opts->redirect_reason;
+		}
 	}
 }
 
@@ -880,12 +887,21 @@
 		PString sourceName;
 		PIPSocket::Address Ip;
 		WORD sourcePort;
+		PString redirect_number;
+		unsigned redirect_reason;
 
 		sourceName = setupPDU.GetQ931().GetDisplayName();
 		cd->call_source_name = strdup((const char *)sourceName);
 
 		GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
 	 	cd->sourceIp = strdup((const char *)Ip.AsString());
+
+		if(setupPDU.GetQ931().GetRedirectingNumber(redirect_number, NULL, NULL, NULL, NULL, &redirect_reason, 0, 0, 0)) {
+			cd->redirect_number = strdup((const char *)redirect_number);
+			cd->redirect_reason = redirect_reason;
+		}
+		else
+			cd->redirect_reason = -1;
 	}
 
 	/* Convert complex strings */
@@ -907,6 +923,344 @@
 	cd->call_dest_alias = s1;
 }
 
+#ifdef TUNNELLING
+static BOOL FetchInformationElements(Q931 &q931, const PBYTEArray &data)
+{
+	PINDEX offset = 0;
+
+	while (offset < data.GetSize()) {
+		// Get field discriminator
+		int discriminator = data[offset++];
+
+#if 0
+		/* Do not overwrite existing IEs */
+		if (q931.HasIE((Q931::InformationElementCodes)discriminator)) {
+			if ((discriminatir & 0x80) == 0)
+				offset += data[offset++];
+			if (offset > data.GetSize())
+				return FALSE;
+			continue;
+		}
+#endif
+
+		PBYTEArray * item = new PBYTEArray;
+
+		// For discriminator with high bit set there is no data
+		if ((discriminator & 0x80) == 0) {
+			int len = data[offset++];
+
+#if 0		// That is not H.225 but regular Q.931 (ISDN) IEs
+			if (discriminator == UserUserIE) {
+				// Special case of User-user field. See 7.2.2.31/H.225.0v4.
+				len <<= 8;
+				len |= data[offset++];
+
+				// we also have a protocol discriminator, which we ignore
+				offset++;
+
+				// before decrementing the length, make sure it is not zero
+				if (len == 0)
+					return FALSE;
+
+				// adjust for protocol discriminator
+				len--;
+			}
+#endif
+
+			if (offset + len > data.GetSize()) {
+				delete item;
+				return FALSE;
+			}
+
+			memcpy(item->GetPointer(len), (const BYTE *)data+offset, len);
+			offset += len;
+		}
+
+		q931.SetIE((Q931::InformationElementCodes)discriminator, *item);
+		delete item;
+	}
+	return TRUE;
+}
+
+static BOOL FetchCiscoTunneledInfo(Q931 &q931, const H323SignalPDU &pdu)
+{
+	const H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
+	if(uuPDU.HasOptionalField(H225_H323_UU_PDU::e_nonStandardControl)) {
+		for(int i = 0; i < uuPDU.m_nonStandardControl.GetSize(); ++i) {
+			const H225_NonStandardParameter &np = uuPDU.m_nonStandardControl[i];
+			const H225_NonStandardIdentifier &id = np.m_nonStandardIdentifier;
+			if (id.GetTag() == H225_NonStandardIdentifier::e_h221NonStandard) {
+				const H225_H221NonStandard &ni = id;
+				/* Check for Cisco */
+				if ((ni.m_t35CountryCode == 181) && (ni.m_t35Extension == 0) && (ni.m_manufacturerCode == 18)) {
+					const PBYTEArray &data = np.m_data;
+					if (h323debug)
+						cout << setprecision(0) << "Received non-standard Cisco extension data " << np.m_data << endl;
+					CISCO_H225_H323_UU_NonStdInfo c;
+					PPER_Stream strm(data);
+					if (c.Decode(strm)) {
+						BOOL haveIEs = FALSE;
+						if (h323debug)
+							cout << setprecision(0) << "H323_UU_NonStdInfo = " << c << endl;
+						if (c.HasOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_protoParam)) {
+							FetchInformationElements(q931, c.m_protoParam.m_qsigNonStdInfo.m_rawMesg);
+							haveIEs = TRUE;
+						}
+						if (c.HasOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_commonParam)) {
+							FetchInformationElements(q931, c.m_commonParam.m_redirectIEinfo.m_redirectIE);
+							haveIEs = TRUE;
+						}
+						if (haveIEs && h323debug)
+							cout << setprecision(0) << "Information elements collected:" << q931 << endl;
+					} else {
+						cout << "ERROR while decoding non-standard Cisco extension" << endl;
+						return FALSE;
+					}
+				}
+			}
+		}
+	}
+	return TRUE;
+}
+
+static BOOL EmbedCiscoTunneledInfo(H323SignalPDU &pdu)
+{
+	const static Q931::InformationElementCodes codes[] =
+	{ Q931::RedirectingNumberIE, Q931::FacilityIE };
+
+	BOOL res = FALSE;
+	BOOL notRedirOnly = FALSE;
+	Q931 tmpQ931;
+	Q931 &q931 = pdu.GetQ931();
+
+	for(unsigned i = 0; i < (sizeof(codes) / sizeof(codes[0])); ++i) {
+		if (q931.HasIE(codes[i])) {
+			tmpQ931.SetIE(codes[i], q931.GetIE(codes[i]));
+			q931.RemoveIE(codes[i]);
+			if (codes[i] != Q931::RedirectingNumberIE)
+				notRedirOnly = TRUE;
+			res = TRUE;
+		}
+	}
+	/* Have something to embed */
+	if (res) {
+		PBYTEArray msg;
+		if (!tmpQ931.Encode(msg))
+			return FALSE;
+		PBYTEArray ies(msg.GetPointer() + 5, msg.GetSize() - 5);
+
+		H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
+		if(!uuPDU.HasOptionalField(H225_H323_UU_PDU::e_nonStandardControl)) {
+			uuPDU.IncludeOptionalField(H225_H323_UU_PDU::e_nonStandardControl);
+			uuPDU.m_nonStandardControl.SetSize(0);
+		}
+		H225_NonStandardParameter *np = new H225_NonStandardParameter;
+		uuPDU.m_nonStandardControl.Append(np);
+		H225_NonStandardIdentifier &nsi = (*np).m_nonStandardIdentifier;
+		nsi.SetTag(H225_NonStandardIdentifier::e_h221NonStandard);
+		H225_H221NonStandard &ns = nsi;
+		ns.m_t35CountryCode = 181;
+		ns.m_t35Extension = 0;
+		ns.m_manufacturerCode = 18;
+		
+		CISCO_H225_H323_UU_NonStdInfo c;
+		c.IncludeOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_version);
+		c.m_version = 0;
+		
+		if (notRedirOnly) {
+			c.IncludeOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_protoParam);
+			CISCO_H225_QsigNonStdInfo &qsigInfo = c.m_protoParam.m_qsigNonStdInfo;
+			qsigInfo.m_iei = ies[0];
+			qsigInfo.m_rawMesg = ies;
+		} else {
+			c.IncludeOptionalField(CISCO_H225_H323_UU_NonStdInfo::e_commonParam);
+			c.m_commonParam.m_redirectIEinfo.m_redirectIE = ies;
+		}
+		PPER_Stream stream;
+		c.Encode(stream);
+		stream.CompleteEncoding();
+		(*np).m_data = stream;
+	}
+	return res;
+}
+
+static const char OID_QSIG[] = "1.3.12.9";
+
+static BOOL FetchQSIGTunneledInfo(Q931 &q931, const H323SignalPDU &pdu)
+{
+	BOOL res = FALSE;
+	const H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
+	if (uuPDU.HasOptionalField(H225_H323_UU_PDU::e_tunnelledSignallingMessage)) {
+		const H225_H323_UU_PDU_tunnelledSignallingMessage &sig = uuPDU.m_tunnelledSignallingMessage;
+		const H225_TunnelledProtocol_id &proto = sig.m_tunnelledProtocolID.m_id;
+		if ((proto.GetTag() == H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) &&
+				(((const PASN_ObjectId &)proto).AsString() == OID_QSIG)) {
+			const H225_ArrayOf_PASN_OctetString &sigs = sig.m_messageContent;
+			for(int i = 0; i < sigs.GetSize(); ++i) {
+				const PASN_OctetString &msg = sigs[i];
+				if (h323debug)
+					cout << setprecision(0) << "Q.931 message data is " << msg << endl;
+				if(!q931.Decode((const PBYTEArray &)msg)) {
+					cout << "Error while decoding Q.931 message" << endl;
+					return FALSE;
+				}
+				res = TRUE;
+				if (h323debug)
+					cout << setprecision(0) << "Received QSIG message " << q931 << endl;
+			}
+		}
+	}
+	return res;
+}
+
+static H225_EndpointType *GetEndpointType(H323SignalPDU &pdu)
+{
+	if (!pdu.GetQ931().HasIE(Q931::UserUserIE))
+		return NULL;
+
+	H225_H323_UU_PDU_h323_message_body &body = pdu.m_h323_uu_pdu.m_h323_message_body;
+	switch (body.GetTag()) {
+	case H225_H323_UU_PDU_h323_message_body::e_setup:
+		return &((H225_Setup_UUIE &)body).m_sourceInfo;
+	case H225_H323_UU_PDU_h323_message_body::e_callProceeding:
+		return &((H225_CallProceeding_UUIE &)body).m_destinationInfo;
+	case H225_H323_UU_PDU_h323_message_body::e_connect:
+		return &((H225_Connect_UUIE &)body).m_destinationInfo;
+	case H225_H323_UU_PDU_h323_message_body::e_alerting:
+		return &((H225_Alerting_UUIE &)body).m_destinationInfo;
+	case H225_H323_UU_PDU_h323_message_body::e_facility:
+		return &((H225_Facility_UUIE &)body).m_destinationInfo;
+	case H225_H323_UU_PDU_h323_message_body::e_progress:
+		return &((H225_Progress_UUIE &)body).m_destinationInfo;
+	}
+	return NULL;
+}
+
+static BOOL QSIGTunnelRequested(H323SignalPDU &pdu)
+{
+	H225_EndpointType *epType = GetEndpointType(pdu);
+	if (epType) {
+		if (!(*epType).HasOptionalField(H225_EndpointType::e_supportedTunnelledProtocols)) {
+			return FALSE;
+		}
+		H225_ArrayOf_TunnelledProtocol &protos = (*epType).m_supportedTunnelledProtocols;
+		for (int i = 0; i < protos.GetSize(); ++i)
+		{
+			if ((protos[i].GetTag() == H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) &&
+					(((const PASN_ObjectId &)protos[i]).AsString() == OID_QSIG)) {
+				return TRUE;
+			}
+		}
+	}
+	return FALSE;
+}
+
+static BOOL EmbedQSIGTunneledInfo(H323SignalPDU &pdu)
+{
+	const static Q931::InformationElementCodes codes[] =
+	{ Q931::RedirectingNumberIE, Q931::FacilityIE };
+
+	Q931 &q931 = pdu.GetQ931();
+	PBYTEArray message;
+	
+	q931.Encode(message);
+	
+	/* Remove non-standard IEs */
+	for(unsigned i = 0; i < (sizeof(codes) / sizeof(codes[0])); ++i) {
+		if (q931.HasIE(codes[i])) {
+			q931.RemoveIE(codes[i]);
+		}
+	}
+
+	H225_H323_UU_PDU &uuPDU = pdu.m_h323_uu_pdu;
+	H225_EndpointType *epType = GetEndpointType(pdu);
+	if (epType) {
+		if (!(*epType).HasOptionalField(H225_EndpointType::e_supportedTunnelledProtocols)) {
+			(*epType).IncludeOptionalField(H225_EndpointType::e_supportedTunnelledProtocols);
+			(*epType).m_supportedTunnelledProtocols.SetSize(0);
+		}
+		H225_ArrayOf_TunnelledProtocol &protos = (*epType).m_supportedTunnelledProtocols;
+		BOOL addQSIG = TRUE;
+		for (int i = 0; i < protos.GetSize(); ++i)
+		{
+			if ((protos[i].GetTag() == H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) &&
+					(((const PASN_ObjectId &)protos[i]).AsString() == OID_QSIG)) {
+				addQSIG = FALSE;
+				break;
+			}
+		}
+		if (addQSIG) {
+			H225_TunnelledProtocol *proto = new H225_TunnelledProtocol;
+			(*proto).m_id.SetTag(H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID);
+			(PASN_ObjectId &)(proto->m_id) = OID_QSIG;
+			protos.Append(proto);
+		}
+	}
+	if (!uuPDU.HasOptionalField(H225_H323_UU_PDU::e_tunnelledSignallingMessage))
+		uuPDU.IncludeOptionalField(H225_H323_UU_PDU::e_tunnelledSignallingMessage);
+	H225_H323_UU_PDU_tunnelledSignallingMessage &sig = uuPDU.m_tunnelledSignallingMessage;
+	H225_TunnelledProtocol_id &proto = sig.m_tunnelledProtocolID.m_id;
+	if ((proto.GetTag() != H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID) ||
+			(((const PASN_ObjectId &)proto).AsString() != OID_QSIG)) {
+		proto.SetTag(H225_TunnelledProtocol_id::e_tunnelledProtocolObjectID);
+		(PASN_ObjectId &)proto = OID_QSIG;
+		sig.m_messageContent.SetSize(0);
+	}
+	PASN_OctetString *msg = new PASN_OctetString;
+	sig.m_messageContent.Append(msg);
+	*msg = message;
+	return TRUE;
+}
+
+BOOL MyH323Connection::EmbedTunneledInfo(H323SignalPDU &pdu)
+{
+	if (tunnelQSIG || remoteTunnelQSIG) {
+		cout << "Embedding Q.SIG message, tunnelQSIG=" << tunnelQSIG << ", remoteTunnelQSIG=" << remoteTunnelQSIG << endl;
+		EmbedQSIGTunneledInfo(pdu);
+	}
+	EmbedCiscoTunneledInfo(pdu);
+
+	return TRUE;
+}
+
+/* Handle tunneled messages */
+BOOL MyH323Connection::HandleSignalPDU(H323SignalPDU &pdu)
+{
+	if (pdu.GetQ931().HasIE(Q931::UserUserIE)) {
+		Q931 tunneledInfo;
+		const Q931 *q931Info;
+
+		q931Info = NULL;
+		if (FetchCiscoTunneledInfo(tunneledInfo, pdu))
+			q931Info = &tunneledInfo;
+		if (FetchQSIGTunneledInfo(tunneledInfo, pdu)) {
+			q931Info = &tunneledInfo;
+			if (!remoteTunnelQSIG) {
+				cout << "Got Q.SIG tunnelled message, enabling tunnelling" << endl;
+				remoteTunnelQSIG = TRUE;
+			}
+		}
+		if (!remoteTunnelQSIG && QSIGTunnelRequested(pdu)) {
+			cout << "Q.SIG tunnelling requested by remote, enable tunnelling" << endl;
+			remoteTunnelQSIG = TRUE;
+		}
+		if (q931Info) {
+			if (q931Info->HasIE(Q931::RedirectingNumberIE)) {
+				pdu.GetQ931().SetIE(Q931::RedirectingNumberIE, q931Info->GetIE(Q931::RedirectingNumberIE));
+				if (h323debug) {
+					PString number;
+					unsigned reason;
+					if(q931Info->GetRedirectingNumber(number, NULL, NULL, NULL, NULL, &reason, 0, 0, 0))
+						cout << "Got redirection from " << number << ", reason " << reason << endl;
+				}
+			}
+		}
+	}
+
+	return H323Connection::HandleSignalPDU(pdu);
+}
+#endif
+
 BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
 {
 	call_details_t cd;
@@ -948,6 +1302,9 @@
 
 	if (progressSetup)
 		setupPDU.GetQ931().SetProgressIndicator(progressSetup);
+	
+	if (redirect_reason >= 0)
+		setupPDU.GetQ931().SetRedirectingNumber(rdnis, 0, 0, 0, 0, redirect_reason);
 	
 	SetCallDetails(&cd, setupPDU, FALSE);
 
@@ -959,6 +1316,10 @@
 		return FALSE;
 	}
 
+#ifdef TUNNELLING
+	EmbedTunneledInfo(setupPDU);
+#endif
+
 	return H323Connection::OnSendSignalSetup(setupPDU);
 }
 
@@ -969,6 +1330,11 @@
 	}
 	if (cause > 0)
 		releaseCompletePDU.GetQ931().SetCause((Q931::CauseValues)cause);
+
+#ifdef TUNNELLING
+	EmbedTunneledInfo(releaseCompletePDU);
+#endif
+
 	return H323Connection::OnSendReleaseComplete(releaseCompletePDU);
 }
 

Modified: team/pcadach/chan_h323-live/channels/h323/ast_h323.h
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323-live/channels/h323/ast_h323.h?rev=43035&r1=43034&r2=43035&view=diff
==============================================================================
--- team/pcadach/chan_h323-live/channels/h323/ast_h323.h (original)
+++ team/pcadach/chan_h323-live/channels/h323/ast_h323.h Sat Sep 16 14:45:43 2006
@@ -219,14 +219,24 @@
 	virtual BOOL StartControlChannel(const H225_TransportAddress & h245Address);
 	void SetCallOptions(void *opts, BOOL isIncoming);
 	void SetCallDetails(void *callDetails, const H323SignalPDU &setupPDU, BOOL isIncoming);
+#ifdef TUNNELLING
+	virtual BOOL HandleSignalPDU(H323SignalPDU &pdu);
+	BOOL EmbedTunneledInfo(H323SignalPDU &pdu);
+#endif
 
 	PString sourceAliases;
 	PString destAliases;
 	PString sourceE164;
 	PString destE164;
+	PString rdnis;
+	int redirect_reason;
 
 	WORD sessionId;
-	BOOL bridging;			
+	BOOL bridging;
+#ifdef TUNNELLING
+	BOOL remoteTunnelQSIG;
+	BOOL tunnelQSIG;
+#endif
 
 	unsigned progressSetup;
 	unsigned progressAlert;
@@ -234,9 +244,6 @@
 
 	RTP_DataFrame::PayloadTypes dtmfCodec;
 	int dtmfMode;
-
-	PString ast_cid_num;
-	PString ast_cid_name;
 };
 
 class MyH323_ExternalRTPChannel : public H323_ExternalRTPChannel

Modified: team/pcadach/chan_h323-live/channels/h323/chan_h323.h
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323-live/channels/h323/chan_h323.h?rev=43035&r1=43034&r2=43035&view=diff
==============================================================================
--- team/pcadach/chan_h323-live/channels/h323/chan_h323.h (original)
+++ team/pcadach/chan_h323-live/channels/h323/chan_h323.h Sat Sep 16 14:45:43 2006
@@ -28,11 +28,21 @@
 
 #include <arpa/inet.h>
 
+/*
+ * Enable support for sending/reception of tunnelled Q.SIG messages and
+ * some sort of IEs (especially RedirectingNumber) which Cisco CallManager
+ * isn't like to pass in standard Q.931 message.
+ *
+ */
+#define TUNNELLING
+
 /** call_option struct holds various bits
  *         of information for each call */
 typedef struct call_options {
 	char			cid_num[80];
 	char			cid_name[80];
+	char			cid_rdnis[80];
+	int				redirect_reason;
 	int				fastStart;
 	int				h245Tunneling;
 	int				silenceSuppression;
@@ -96,6 +106,8 @@
 	char *call_source_name;
 	char *call_source_e164;
 	char *call_dest_e164;
+	char *redirect_number;
+	int redirect_reason;
 	int presentation;
 	int screening;
 	char *sourceIp;

Added: team/pcadach/chan_h323-live/channels/h323/cisco-h225.asn
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323-live/channels/h323/cisco-h225.asn?rev=43035&view=auto
==============================================================================
--- team/pcadach/chan_h323-live/channels/h323/cisco-h225.asn (added)
+++ team/pcadach/chan_h323-live/channels/h323/cisco-h225.asn Sat Sep 16 14:45:43 2006
@@ -1,0 +1,74 @@
+CISCO-H225-MESSAGES DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+
+H323_UU_NonStdInfo ::= SEQUENCE
+{
+	version INTEGER OPTIONAL,
+	protoParam ProtoParam OPTIONAL,
+	commonParam CommonParam OPTIONAL,
+	...,
+	progIndParam ProgIndParam OPTIONAL,
+	dummy1 OCTET STRING OPTIONAL,
+	callMgrParam CallMgrParam OPTIONAL,
+	callSignallingParam CallSignallingParam OPTIONAL,
+	dummy2 OCTET STRING OPTIONAL,
+	callPreserveParam CallPreserveParam OPTIONAL
+}
+
+CommonParam ::= SEQUENCE
+{
+	redirectIEinfo RedirectIEinfo,
+	...
+}
+
+RedirectIEinfo ::= SEQUENCE
+{
+	redirectIE OCTET STRING,
+	...
+}
+
+ProgIndParam ::= SEQUENCE
+{
+	progIndIEinfo ProgIndIEinfo,
+	...
+}
+
+ProgIndIEinfo ::= SEQUENCE
+{
+	progIndIE OCTET STRING,
+	...
+}
+
+ProtoParam ::= SEQUENCE
+{
+	qsigNonStdInfo QsigNonStdInfo,
+	...
+}
+
+QsigNonStdInfo ::= SEQUENCE
+{
+	iei	INTEGER,
+	rawMesg OCTET STRING,
+	...
+}
+
+CallMgrParam ::= SEQUENCE
+{
+	interclusterVersion INTEGER,
+	enterpriseID OCTET STRING,
+	...
+}
+
+CallPreserveParam ::= SEQUENCE
+{
+	callPreserveIE BOOLEAN,
+	...
+}
+
+CallSignallingParam ::= SEQUENCE
+{
+	connectedNumber OCTET STRING (1..127) OPTIONAL,
+	...
+}
+
+END

Propchange: team/pcadach/chan_h323-live/channels/h323/cisco-h225.asn
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/pcadach/chan_h323-live/channels/h323/cisco-h225.asn
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Propchange: team/pcadach/chan_h323-live/channels/h323/cisco-h225.asn
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/pcadach/chan_h323-live/channels/h323/cisco-h225.cpp
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323-live/channels/h323/cisco-h225.cpp?rev=43035&view=auto
==============================================================================
--- team/pcadach/chan_h323-live/channels/h323/cisco-h225.cpp (added)
+++ team/pcadach/chan_h323-live/channels/h323/cisco-h225.cpp Sat Sep 16 14:45:43 2006
@@ -1,0 +1,853 @@
+//
+// cisco-h225.cxx
+//
+// Code automatically generated by asnparse.
+//
+
+#ifdef P_USE_PRAGMA
+#pragma implementation "cisco-h225.h"
+#endif
+
+#include <ptlib.h>
+#include "cisco-h225.h"
+
+#define new PNEW
+
+
+#if ! H323_DISABLE_CISCO_H225
+
+//
+// RedirectIEinfo
+//
+
+CISCO_H225_RedirectIEinfo::CISCO_H225_RedirectIEinfo(unsigned tag, PASN_Object::TagClass tagClass)
+  : PASN_Sequence(tag, tagClass, 0, TRUE, 0)
+{
+}
+
+
+#ifndef PASN_NOPRINTON
+void CISCO_H225_RedirectIEinfo::PrintOn(ostream & strm) const
+{
+  int indent = strm.precision() + 2;
+  strm << "{\n";
+  strm << setw(indent+13) << "redirectIE = " << setprecision(indent) << m_redirectIE << '\n';
+  strm << setw(indent-1) << setprecision(indent-2) << "}";
+}
+#endif
+
+
+PObject::Comparison CISCO_H225_RedirectIEinfo::Compare(const PObject & obj) const
+{
+#ifndef PASN_LEANANDMEAN
+  PAssert(PIsDescendant(&obj, CISCO_H225_RedirectIEinfo), PInvalidCast);
+#endif
+  const CISCO_H225_RedirectIEinfo & other = (const CISCO_H225_RedirectIEinfo &)obj;
+
+  Comparison result;
+
+  if ((result = m_redirectIE.Compare(other.m_redirectIE)) != EqualTo)
+    return result;
+
+  return PASN_Sequence::Compare(other);
+}
+
+
+PINDEX CISCO_H225_RedirectIEinfo::GetDataLength() const
+{
+  PINDEX length = 0;
+  length += m_redirectIE.GetObjectLength();
+  return length;
+}
+
+
+BOOL CISCO_H225_RedirectIEinfo::Decode(PASN_Stream & strm)
+{
+  if (!PreambleDecode(strm))
+    return FALSE;
+
+  if (!m_redirectIE.Decode(strm))
+    return FALSE;
+
+  return UnknownExtensionsDecode(strm);
+}
+
+
+void CISCO_H225_RedirectIEinfo::Encode(PASN_Stream & strm) const
+{
+  PreambleEncode(strm);
+
+  m_redirectIE.Encode(strm);
+
+  UnknownExtensionsEncode(strm);
+}
+
+
+PObject * CISCO_H225_RedirectIEinfo::Clone() const
+{
+#ifndef PASN_LEANANDMEAN
+  PAssert(IsClass(CISCO_H225_RedirectIEinfo::Class()), PInvalidCast);
+#endif
+  return new CISCO_H225_RedirectIEinfo(*this);
+}
+
+
+//
+// ProgIndIEinfo
+//
+
+CISCO_H225_ProgIndIEinfo::CISCO_H225_ProgIndIEinfo(unsigned tag, PASN_Object::TagClass tagClass)
+  : PASN_Sequence(tag, tagClass, 0, TRUE, 0)
+{
+}
+
+
+#ifndef PASN_NOPRINTON
+void CISCO_H225_ProgIndIEinfo::PrintOn(ostream & strm) const
+{
+  int indent = strm.precision() + 2;
+  strm << "{\n";
+  strm << setw(indent+12) << "progIndIE = " << setprecision(indent) << m_progIndIE << '\n';
+  strm << setw(indent-1) << setprecision(indent-2) << "}";
+}
+#endif
+
+
+PObject::Comparison CISCO_H225_ProgIndIEinfo::Compare(const PObject & obj) const
+{
+#ifndef PASN_LEANANDMEAN
+  PAssert(PIsDescendant(&obj, CISCO_H225_ProgIndIEinfo), PInvalidCast);
+#endif
+  const CISCO_H225_ProgIndIEinfo & other = (const CISCO_H225_ProgIndIEinfo &)obj;
+
+  Comparison result;
+
+  if ((result = m_progIndIE.Compare(other.m_progIndIE)) != EqualTo)
+    return result;
+
+  return PASN_Sequence::Compare(other);
+}
+
+
+PINDEX CISCO_H225_ProgIndIEinfo::GetDataLength() const
+{
+  PINDEX length = 0;
+  length += m_progIndIE.GetObjectLength();
+  return length;
+}
+
+
+BOOL CISCO_H225_ProgIndIEinfo::Decode(PASN_Stream & strm)
+{
+  if (!PreambleDecode(strm))
+    return FALSE;
+
+  if (!m_progIndIE.Decode(strm))
+    return FALSE;
+
+  return UnknownExtensionsDecode(strm);
+}
+
+
+void CISCO_H225_ProgIndIEinfo::Encode(PASN_Stream & strm) const
+{
+  PreambleEncode(strm);
+
+  m_progIndIE.Encode(strm);
+
+  UnknownExtensionsEncode(strm);
+}
+
+
+PObject * CISCO_H225_ProgIndIEinfo::Clone() const
+{
+#ifndef PASN_LEANANDMEAN
+  PAssert(IsClass(CISCO_H225_ProgIndIEinfo::Class()), PInvalidCast);
+#endif
+  return new CISCO_H225_ProgIndIEinfo(*this);
+}
+
+
+//
+// QsigNonStdInfo
+//
+
+CISCO_H225_QsigNonStdInfo::CISCO_H225_QsigNonStdInfo(unsigned tag, PASN_Object::TagClass tagClass)
+  : PASN_Sequence(tag, tagClass, 0, TRUE, 0)
+{
+}
+
+
+#ifndef PASN_NOPRINTON
+void CISCO_H225_QsigNonStdInfo::PrintOn(ostream & strm) const
+{
+  int indent = strm.precision() + 2;
+  strm << "{\n";
+  strm << setw(indent+6) << "iei = " << setprecision(indent) << m_iei << '\n';
+  strm << setw(indent+10) << "rawMesg = " << setprecision(indent) << m_rawMesg << '\n';
+  strm << setw(indent-1) << setprecision(indent-2) << "}";
+}
+#endif
+
+
+PObject::Comparison CISCO_H225_QsigNonStdInfo::Compare(const PObject & obj) const
+{
+#ifndef PASN_LEANANDMEAN
+  PAssert(PIsDescendant(&obj, CISCO_H225_QsigNonStdInfo), PInvalidCast);
+#endif
+  const CISCO_H225_QsigNonStdInfo & other = (const CISCO_H225_QsigNonStdInfo &)obj;
+
+  Comparison result;
+
+  if ((result = m_iei.Compare(other.m_iei)) != EqualTo)
+    return result;
+  if ((result = m_rawMesg.Compare(other.m_rawMesg)) != EqualTo)
+    return result;
+
+  return PASN_Sequence::Compare(other);
+}
+
+
+PINDEX CISCO_H225_QsigNonStdInfo::GetDataLength() const
+{
+  PINDEX length = 0;
+  length += m_iei.GetObjectLength();
+  length += m_rawMesg.GetObjectLength();
+  return length;
+}
+
+
+BOOL CISCO_H225_QsigNonStdInfo::Decode(PASN_Stream & strm)
+{
+  if (!PreambleDecode(strm))
+    return FALSE;
+
+  if (!m_iei.Decode(strm))
+    return FALSE;
+  if (!m_rawMesg.Decode(strm))
+    return FALSE;
+
+  return UnknownExtensionsDecode(strm);
+}
+
+
+void CISCO_H225_QsigNonStdInfo::Encode(PASN_Stream & strm) const
+{
+  PreambleEncode(strm);
+
+  m_iei.Encode(strm);
+  m_rawMesg.Encode(strm);
+
+  UnknownExtensionsEncode(strm);
+}
+
+
+PObject * CISCO_H225_QsigNonStdInfo::Clone() const
+{
+#ifndef PASN_LEANANDMEAN
+  PAssert(IsClass(CISCO_H225_QsigNonStdInfo::Class()), PInvalidCast);
+#endif
+  return new CISCO_H225_QsigNonStdInfo(*this);
+}
+
+
+//
+// CallMgrParam
+//
+
+CISCO_H225_CallMgrParam::CISCO_H225_CallMgrParam(unsigned tag, PASN_Object::TagClass tagClass)
+  : PASN_Sequence(tag, tagClass, 0, TRUE, 0)
+{
+}
+
+
+#ifndef PASN_NOPRINTON
+void CISCO_H225_CallMgrParam::PrintOn(ostream & strm) const
+{
+  int indent = strm.precision() + 2;
+  strm << "{\n";
+  strm << setw(indent+22) << "interclusterVersion = " << setprecision(indent) << m_interclusterVersion << '\n';
+  strm << setw(indent+15) << "enterpriseID = " << setprecision(indent) << m_enterpriseID << '\n';
+  strm << setw(indent-1) << setprecision(indent-2) << "}";
+}
+#endif
+
+
+PObject::Comparison CISCO_H225_CallMgrParam::Compare(const PObject & obj) const
+{
+#ifndef PASN_LEANANDMEAN
+  PAssert(PIsDescendant(&obj, CISCO_H225_CallMgrParam), PInvalidCast);
+#endif
+  const CISCO_H225_CallMgrParam & other = (const CISCO_H225_CallMgrParam &)obj;
+
+  Comparison result;
+
+  if ((result = m_interclusterVersion.Compare(other.m_interclusterVersion)) != EqualTo)
+    return result;
+  if ((result = m_enterpriseID.Compare(other.m_enterpriseID)) != EqualTo)
+    return result;
+
+  return PASN_Sequence::Compare(other);
+}
+
+
+PINDEX CISCO_H225_CallMgrParam::GetDataLength() const
+{
+  PINDEX length = 0;
+  length += m_interclusterVersion.GetObjectLength();
+  length += m_enterpriseID.GetObjectLength();
+  return length;
+}
+
+
+BOOL CISCO_H225_CallMgrParam::Decode(PASN_Stream & strm)
+{
+  if (!PreambleDecode(strm))
+    return FALSE;
+
+  if (!m_interclusterVersion.Decode(strm))
+    return FALSE;
+  if (!m_enterpriseID.Decode(strm))
+    return FALSE;
+
+  return UnknownExtensionsDecode(strm);
+}
+
+
+void CISCO_H225_CallMgrParam::Encode(PASN_Stream & strm) const
+{
+  PreambleEncode(strm);
+
+  m_interclusterVersion.Encode(strm);
+  m_enterpriseID.Encode(strm);
+
+  UnknownExtensionsEncode(strm);
+}
+
+
+PObject * CISCO_H225_CallMgrParam::Clone() const
+{
+#ifndef PASN_LEANANDMEAN
+  PAssert(IsClass(CISCO_H225_CallMgrParam::Class()), PInvalidCast);
+#endif
+  return new CISCO_H225_CallMgrParam(*this);
+}
+
+
+//
+// CallPreserveParam
+//
+
+CISCO_H225_CallPreserveParam::CISCO_H225_CallPreserveParam(unsigned tag, PASN_Object::TagClass tagClass)
+  : PASN_Sequence(tag, tagClass, 0, TRUE, 0)
+{
+}
+
+
+#ifndef PASN_NOPRINTON
+void CISCO_H225_CallPreserveParam::PrintOn(ostream & strm) const
+{
+  int indent = strm.precision() + 2;
+  strm << "{\n";
+  strm << setw(indent+17) << "callPreserveIE = " << setprecision(indent) << m_callPreserveIE << '\n';
+  strm << setw(indent-1) << setprecision(indent-2) << "}";
+}
+#endif
+
+
+PObject::Comparison CISCO_H225_CallPreserveParam::Compare(const PObject & obj) const
+{
+#ifndef PASN_LEANANDMEAN
+  PAssert(PIsDescendant(&obj, CISCO_H225_CallPreserveParam), PInvalidCast);
+#endif
+  const CISCO_H225_CallPreserveParam & other = (const CISCO_H225_CallPreserveParam &)obj;
+
+  Comparison result;
+
+  if ((result = m_callPreserveIE.Compare(other.m_callPreserveIE)) != EqualTo)
+    return result;
+
+  return PASN_Sequence::Compare(other);
+}
+
+
+PINDEX CISCO_H225_CallPreserveParam::GetDataLength() const
+{
+  PINDEX length = 0;
+  length += m_callPreserveIE.GetObjectLength();
+  return length;
+}
+
+
+BOOL CISCO_H225_CallPreserveParam::Decode(PASN_Stream & strm)
+{
+  if (!PreambleDecode(strm))
+    return FALSE;
+
+  if (!m_callPreserveIE.Decode(strm))
+    return FALSE;
+
+  return UnknownExtensionsDecode(strm);
+}
+
+
+void CISCO_H225_CallPreserveParam::Encode(PASN_Stream & strm) const
+{
+  PreambleEncode(strm);
+
+  m_callPreserveIE.Encode(strm);
+
+  UnknownExtensionsEncode(strm);
+}
+
+
+PObject * CISCO_H225_CallPreserveParam::Clone() const
+{
+#ifndef PASN_LEANANDMEAN
+  PAssert(IsClass(CISCO_H225_CallPreserveParam::Class()), PInvalidCast);
+#endif
+  return new CISCO_H225_CallPreserveParam(*this);
+}
+
+
+//
+// CallSignallingParam
+//
+
+CISCO_H225_CallSignallingParam::CISCO_H225_CallSignallingParam(unsigned tag, PASN_Object::TagClass tagClass)
+  : PASN_Sequence(tag, tagClass, 1, TRUE, 0)
+{
+  m_connectedNumber.SetConstraints(PASN_Object::FixedConstraint, 1, 127);
+}
+
+
+#ifndef PASN_NOPRINTON
+void CISCO_H225_CallSignallingParam::PrintOn(ostream & strm) const
+{
+  int indent = strm.precision() + 2;
+  strm << "{\n";
+  if (HasOptionalField(e_connectedNumber))
+    strm << setw(indent+18) << "connectedNumber = " << setprecision(indent) << m_connectedNumber << '\n';
+  strm << setw(indent-1) << setprecision(indent-2) << "}";
+}
+#endif
+
+
+PObject::Comparison CISCO_H225_CallSignallingParam::Compare(const PObject & obj) const
+{
+#ifndef PASN_LEANANDMEAN
+  PAssert(PIsDescendant(&obj, CISCO_H225_CallSignallingParam), PInvalidCast);
+#endif
+  const CISCO_H225_CallSignallingParam & other = (const CISCO_H225_CallSignallingParam &)obj;
+
+  Comparison result;
+
+  if ((result = m_connectedNumber.Compare(other.m_connectedNumber)) != EqualTo)
+    return result;
+
+  return PASN_Sequence::Compare(other);
+}
+
+
+PINDEX CISCO_H225_CallSignallingParam::GetDataLength() const
+{
+  PINDEX length = 0;
+  if (HasOptionalField(e_connectedNumber))
+    length += m_connectedNumber.GetObjectLength();
+  return length;
+}
+
+
+BOOL CISCO_H225_CallSignallingParam::Decode(PASN_Stream & strm)
+{
+  if (!PreambleDecode(strm))
+    return FALSE;
+
+  if (HasOptionalField(e_connectedNumber) && !m_connectedNumber.Decode(strm))
+    return FALSE;
+
+  return UnknownExtensionsDecode(strm);
+}
+
+
+void CISCO_H225_CallSignallingParam::Encode(PASN_Stream & strm) const
+{
+  PreambleEncode(strm);
+
+  if (HasOptionalField(e_connectedNumber))
+    m_connectedNumber.Encode(strm);
+
+  UnknownExtensionsEncode(strm);
+}
+
+
+PObject * CISCO_H225_CallSignallingParam::Clone() const
+{
+#ifndef PASN_LEANANDMEAN
+  PAssert(IsClass(CISCO_H225_CallSignallingParam::Class()), PInvalidCast);
+#endif
+  return new CISCO_H225_CallSignallingParam(*this);
+}
+
+
+//
+// CommonParam
+//
+
+CISCO_H225_CommonParam::CISCO_H225_CommonParam(unsigned tag, PASN_Object::TagClass tagClass)
+  : PASN_Sequence(tag, tagClass, 0, TRUE, 0)
+{
+}
+
+
+#ifndef PASN_NOPRINTON
+void CISCO_H225_CommonParam::PrintOn(ostream & strm) const
+{
+  int indent = strm.precision() + 2;
+  strm << "{\n";

[... 677 lines stripped ...]


More information about the asterisk-commits mailing list