Merged revisions 44022 via svnmerge from
authorPaul Cadach <paul@odt.east.telecom.kz>
Fri, 29 Sep 2006 19:13:26 +0000 (19:13 +0000)
committerPaul Cadach <paul@odt.east.telecom.kz>
Fri, 29 Sep 2006 19:13:26 +0000 (19:13 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r44022 | pcadach | 2006-09-30 01:06:55 +0600 (Сбт, 30 Сен 2006) | 3 lines

Properly pass TON/PRESENTATION information - original
H323Connection::SendSignalSetup() destroys Q.931 fields.

........

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@44024 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/h323/ast_h323.cxx
channels/h323/ast_h323.h

index 3c1a56c..37684dd 100644 (file)
@@ -923,7 +923,7 @@ static BOOL EmbedCiscoTunneledInfo(H323SignalPDU &pdu)
        } codes[] = {
                { Q931::RedirectingNumberIE, },
                { Q931::FacilityIE, },
        } codes[] = {
                { Q931::RedirectingNumberIE, },
                { Q931::FacilityIE, },
-               { Q931::CallingPartyNumberIE, TRUE },
+//             { Q931::CallingPartyNumberIE, TRUE },
        };
 
        BOOL res = FALSE;
        };
 
        BOOL res = FALSE;
@@ -1231,6 +1231,7 @@ BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
           by embedding routines */
        setupPDU.GetQ931().SetCallingPartyNumber(GetLocalPartyName(), (cid_ton >> 4) & 0x07,
                        cid_ton & 0x0f, (cid_presentation >> 5) & 0x03, cid_presentation & 0x1f);
           by embedding routines */
        setupPDU.GetQ931().SetCallingPartyNumber(GetLocalPartyName(), (cid_ton >> 4) & 0x07,
                        cid_ton & 0x0f, (cid_presentation >> 5) & 0x03, cid_presentation & 0x1f);
+       setupPDU.GetQ931().SetDisplayName(GetDisplayName());
 
 #ifdef TUNNELLING
        EmbedTunneledInfo(setupPDU);
 
 #ifdef TUNNELLING
        EmbedTunneledInfo(setupPDU);
@@ -1239,6 +1240,311 @@ BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
        return H323Connection::OnSendSignalSetup(setupPDU);
 }
 
        return H323Connection::OnSendSignalSetup(setupPDU);
 }
 
+static BOOL BuildFastStartList(const H323Channel & channel,
+               H225_ArrayOf_PASN_OctetString & array,
+               H323Channel::Directions reverseDirection)
+{
+       H245_OpenLogicalChannel open;
+       const H323Capability & capability = channel.GetCapability();
+
+       if (channel.GetDirection() != reverseDirection) {
+               if (!capability.OnSendingPDU(open.m_forwardLogicalChannelParameters.m_dataType))
+                       return FALSE;
+       }
+       else {
+               if (!capability.OnSendingPDU(open.m_reverseLogicalChannelParameters.m_dataType))
+                       return FALSE;
+
+               open.m_forwardLogicalChannelParameters.m_multiplexParameters.SetTag(
+                               H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters::e_none);
+               open.m_forwardLogicalChannelParameters.m_dataType.SetTag(H245_DataType::e_nullData);
+               open.IncludeOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters);
+       }
+
+       if (!channel.OnSendingPDU(open))
+               return FALSE;
+
+       PTRACE(4, "H225\tBuild fastStart:\n     " << setprecision(2) << open);
+       PINDEX last = array.GetSize();
+       array.SetSize(last+1);
+       array[last].EncodeSubType(open);
+
+       PTRACE(3, "H225\tBuilt fastStart for " << capability);
+       return TRUE;
+}
+
+H323Connection::CallEndReason MyH323Connection::SendSignalSetup(const PString & alias,
+               const H323TransportAddress & address)
+{
+       // Start the call, first state is asking gatekeeper
+       connectionState = AwaitingGatekeeperAdmission;
+
+       // Indicate the direction of call.
+       if (alias.IsEmpty())
+               remotePartyName = remotePartyAddress = address;
+       else {
+               remotePartyName = alias;
+               remotePartyAddress = alias + '@' + address;
+       }
+
+       // Start building the setup PDU to get various ID's
+       H323SignalPDU setupPDU;
+       H225_Setup_UUIE & setup = setupPDU.BuildSetup(*this, address);
+
+#ifdef H323_H450
+       h450dispatcher->AttachToSetup(setupPDU);
+#endif
+
+       // Save the identifiers generated by BuildSetup
+       setupPDU.GetQ931().GetCalledPartyNumber(remotePartyNumber);
+
+       H323TransportAddress gatekeeperRoute = address;
+
+       // Check for gatekeeper and do admission check if have one
+       H323Gatekeeper * gatekeeper = endpoint.GetGatekeeper();
+       H225_ArrayOf_AliasAddress newAliasAddresses;
+       if (gatekeeper != NULL) {
+               H323Gatekeeper::AdmissionResponse response;
+               response.transportAddress = &gatekeeperRoute;
+               response.aliasAddresses = &newAliasAddresses;
+               if (!gkAccessTokenOID)
+                       response.accessTokenData = &gkAccessTokenData;
+               while (!gatekeeper->AdmissionRequest(*this, response, alias.IsEmpty())) {
+                       PTRACE(1, "H225\tGatekeeper refused admission: "
+                                       << (response.rejectReason == UINT_MAX
+                                       ? PString("Transport error")
+                                       : H225_AdmissionRejectReason(response.rejectReason).GetTagName()));
+#ifdef H323_H450
+                       h4502handler->onReceivedAdmissionReject(H4501_GeneralErrorList::e_notAvailable);
+#endif
+
+                       switch (response.rejectReason) {
+                       case H225_AdmissionRejectReason::e_calledPartyNotRegistered:
+                               return EndedByNoUser;
+                       case H225_AdmissionRejectReason::e_requestDenied:
+                               return EndedByNoBandwidth;
+                       case H225_AdmissionRejectReason::e_invalidPermission:
+                       case H225_AdmissionRejectReason::e_securityDenial:
+                               return EndedBySecurityDenial;
+                       case H225_AdmissionRejectReason::e_resourceUnavailable:
+                               return EndedByRemoteBusy;
+                       case H225_AdmissionRejectReason::e_incompleteAddress:
+                               if (OnInsufficientDigits())
+                                       break;
+                               // Then default case
+                       default:
+                               return EndedByGatekeeper;
+                       }
+
+                       PString lastRemotePartyName = remotePartyName;
+                       while (lastRemotePartyName == remotePartyName) {
+                               Unlock(); // Release the mutex as can deadlock trying to clear call during connect.
+                               digitsWaitFlag.Wait();
+                               if (!Lock()) // Lock while checking for shutting down.
+                                       return EndedByCallerAbort;
+                       }
+               }
+               mustSendDRQ = TRUE;
+               if (response.gatekeeperRouted) {
+                       setup.IncludeOptionalField(H225_Setup_UUIE::e_endpointIdentifier);
+                       setup.m_endpointIdentifier = gatekeeper->GetEndpointIdentifier();
+                       gatekeeperRouted = TRUE;
+               }
+       }
+
+#ifdef H323_TRANSNEXUS_OSP
+       // check for OSP server (if not using GK)
+       if (gatekeeper == NULL) {
+               OpalOSP::Provider * ospProvider = endpoint.GetOSPProvider();
+               if (ospProvider != NULL) {
+                       OpalOSP::Transaction * transaction = new OpalOSP::Transaction();
+                       if (transaction->Open(*ospProvider) != 0) {
+                               PTRACE(1, "H225\tCannot create OSP transaction");
+                               return EndedByOSPRefusal;
+                       }
+
+                       OpalOSP::Transaction::DestinationInfo destInfo;
+                       if (!AuthoriseOSPTransaction(*transaction, destInfo)) {
+                               delete transaction;
+                               return EndedByOSPRefusal;
+                       }
+
+                       // save the transaction for use by the call
+                       ospTransaction = transaction;
+
+                       // retreive the call information
+                       gatekeeperRoute = destInfo.destinationAddress;
+                       newAliasAddresses.Append(new H225_AliasAddress(destInfo.calledNumber));
+
+                       // insert the token
+                       setup.IncludeOptionalField(H225_Setup_UUIE::e_tokens);
+                       destInfo.InsertToken(setup.m_tokens);
+               }
+       }
+#endif
+
+       // Update the field e_destinationAddress in the SETUP PDU to reflect the new 
+       // alias received in the ACF (m_destinationInfo).
+       if (newAliasAddresses.GetSize() > 0) {
+               setup.IncludeOptionalField(H225_Setup_UUIE::e_destinationAddress);
+               setup.m_destinationAddress = newAliasAddresses;
+
+               // Update the Q.931 Information Element (if is an E.164 address)
+               PString e164 = H323GetAliasAddressE164(newAliasAddresses);
+               if (!e164)
+                       remotePartyNumber = e164;
+       }
+
+       if (addAccessTokenToSetup && !gkAccessTokenOID && !gkAccessTokenData.IsEmpty()) {
+               PString oid1, oid2;
+               PINDEX comma = gkAccessTokenOID.Find(',');
+               if (comma == P_MAX_INDEX)
+                       oid1 = oid2 = gkAccessTokenOID;
+               else {
+                       oid1 = gkAccessTokenOID.Left(comma);
+                       oid2 = gkAccessTokenOID.Mid(comma+1);
+               }
+               setup.IncludeOptionalField(H225_Setup_UUIE::e_tokens);
+               PINDEX last = setup.m_tokens.GetSize();
+               setup.m_tokens.SetSize(last+1);
+               setup.m_tokens[last].m_tokenOID = oid1;
+               setup.m_tokens[last].IncludeOptionalField(H235_ClearToken::e_nonStandard);
+               setup.m_tokens[last].m_nonStandard.m_nonStandardIdentifier = oid2;
+               setup.m_tokens[last].m_nonStandard.m_data = gkAccessTokenData;
+       }
+
+       if (!signallingChannel->SetRemoteAddress(gatekeeperRoute)) {
+               PTRACE(1, "H225\tInvalid "
+                                        << (gatekeeperRoute != address ? "gatekeeper" : "user")
+                                        << " supplied address: \"" << gatekeeperRoute << '"');
+               connectionState = AwaitingTransportConnect;
+               return EndedByConnectFail;
+       }
+
+       // Do the transport connect
+       connectionState = AwaitingTransportConnect;
+
+       // Release the mutex as can deadlock trying to clear call during connect.
+       Unlock();
+
+       signallingChannel->SetWriteTimeout(100);
+
+       BOOL connectFailed = !signallingChannel->Connect();
+
+       // Lock while checking for shutting down.
+       if (!Lock())
+               return EndedByCallerAbort;
+
+       // See if transport connect failed, abort if so.
+       if (connectFailed) {
+               connectionState = NoConnectionActive;
+               switch (signallingChannel->GetErrorNumber()) {
+                       case ENETUNREACH :
+                               return EndedByUnreachable;
+                       case ECONNREFUSED :
+                               return EndedByNoEndPoint;
+                       case ETIMEDOUT :
+                               return EndedByHostOffline;
+               }
+               return EndedByConnectFail;
+       }
+
+       PTRACE(3, "H225\tSending Setup PDU");
+       connectionState = AwaitingSignalConnect;
+
+       // Put in all the signalling addresses for link
+       setup.IncludeOptionalField(H225_Setup_UUIE::e_sourceCallSignalAddress);
+       signallingChannel->SetUpTransportPDU(setup.m_sourceCallSignalAddress, TRUE);
+       if (!setup.HasOptionalField(H225_Setup_UUIE::e_destCallSignalAddress)) {
+               setup.IncludeOptionalField(H225_Setup_UUIE::e_destCallSignalAddress);
+               signallingChannel->SetUpTransportPDU(setup.m_destCallSignalAddress, FALSE);
+       }
+
+       // If a standard call do Fast Start (if required)
+       if (setup.m_conferenceGoal.GetTag() == H225_Setup_UUIE_conferenceGoal::e_create) {
+
+               // Get the local capabilities before fast start is handled
+               OnSetLocalCapabilities();
+
+               // Ask the application what channels to open
+               PTRACE(3, "H225\tCheck for Fast start by local endpoint");
+               fastStartChannels.RemoveAll();
+               OnSelectLogicalChannels();
+
+               // If application called OpenLogicalChannel, put in the fastStart field
+               if (!fastStartChannels.IsEmpty()) {
+                       PTRACE(3, "H225\tFast start begun by local endpoint");
+                       for (PINDEX i = 0; i < fastStartChannels.GetSize(); i++)
+                               BuildFastStartList(fastStartChannels[i], setup.m_fastStart, H323Channel::IsReceiver);
+                       if (setup.m_fastStart.GetSize() > 0)
+                               setup.IncludeOptionalField(H225_Setup_UUIE::e_fastStart);
+               }
+
+               // Search the capability set and see if we have video capability
+               for (PINDEX i = 0; i < localCapabilities.GetSize(); i++) {
+                       switch (localCapabilities[i].GetMainType()) {
+                       case H323Capability::e_Audio:
+                       case H323Capability::e_UserInput:
+                               break;
+
+                       default:        // Is video or other data (eg T.120)
+                               setupPDU.GetQ931().SetBearerCapabilities(Q931::TransferUnrestrictedDigital, 6);
+                               i = localCapabilities.GetSize(); // Break out of the for loop
+                               break;
+                       }
+               }
+       }
+
+       if (!OnSendSignalSetup(setupPDU))
+               return EndedByNoAccept;
+
+       // Do this again (was done when PDU was constructed) in case
+       // OnSendSignalSetup() changed something.
+//     setupPDU.SetQ931Fields(*this, TRUE);
+       setupPDU.GetQ931().GetCalledPartyNumber(remotePartyNumber);
+
+       fastStartState = FastStartDisabled;
+       BOOL set_lastPDUWasH245inSETUP = FALSE;
+
+       if (h245Tunneling && doH245inSETUP) {
+               h245TunnelTxPDU = &setupPDU;
+
+               // Try and start the master/slave and capability exchange through the tunnel
+               // Note: this used to be disallowed but is now allowed as of H323v4
+               BOOL ok = StartControlNegotiations();
+
+               h245TunnelTxPDU = NULL;
+
+               if (!ok)
+                       return EndedByTransportFail;
+
+               if (setup.m_fastStart.GetSize() > 0) {
+                       // Now if fast start as well need to put this in setup specific field
+                       // and not the generic H.245 tunneling field
+                       setup.IncludeOptionalField(H225_Setup_UUIE::e_parallelH245Control);
+                       setup.m_parallelH245Control = setupPDU.m_h323_uu_pdu.m_h245Control;
+                       setupPDU.m_h323_uu_pdu.RemoveOptionalField(H225_H323_UU_PDU::e_h245Control);
+                       set_lastPDUWasH245inSETUP = TRUE;
+               }
+       }
+
+       // Send the initial PDU
+       setupTime = PTime();
+       if (!WriteSignalPDU(setupPDU))
+               return EndedByTransportFail;
+
+       // WriteSignalPDU always resets lastPDUWasH245inSETUP.
+       // So set it here if required
+       if (set_lastPDUWasH245inSETUP)
+               lastPDUWasH245inSETUP = TRUE;
+
+       // Set timeout for remote party to answer the call
+       signallingChannel->SetReadTimeout(endpoint.GetSignallingChannelCallTimeout());
+
+       return NumCallEndReasons;
+}
+
+
 BOOL MyH323Connection::OnSendReleaseComplete(H323SignalPDU & releaseCompletePDU)
 {
        if (h323debug) {
 BOOL MyH323Connection::OnSendReleaseComplete(H323SignalPDU & releaseCompletePDU)
 {
        if (h323debug) {
index 74e13e7..3393295 100644 (file)
@@ -90,6 +90,7 @@ public:
        virtual BOOL StartControlChannel(const H225_TransportAddress & h245Address);
        void SetCallOptions(void *opts, BOOL isIncoming);
        void SetCallDetails(void *callDetails, const H323SignalPDU &setupPDU, BOOL isIncoming);
        virtual BOOL StartControlChannel(const H225_TransportAddress & h245Address);
        void SetCallOptions(void *opts, BOOL isIncoming);
        void SetCallDetails(void *callDetails, const H323SignalPDU &setupPDU, BOOL isIncoming);
+       virtual H323Connection::CallEndReason SendSignalSetup(const PString&, const H323TransportAddress&);
 #ifdef TUNNELLING
        virtual BOOL HandleSignalPDU(H323SignalPDU &pdu);
        BOOL EmbedTunneledInfo(H323SignalPDU &pdu);
 #ifdef TUNNELLING
        virtual BOOL HandleSignalPDU(H323SignalPDU &pdu);
        BOOL EmbedTunneledInfo(H323SignalPDU &pdu);