From 19ef919be0621f9712375cd7aba7df70fb640b7e Mon Sep 17 00:00:00 2001 From: pcadach Date: Fri, 29 Sep 2006 19:13:26 +0000 Subject: Merged revisions 44022 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ........ 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: http://svn.digium.com/svn/asterisk/trunk@44024 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/h323/ast_h323.cxx | 308 ++++++++++++++++++++++++++++++++++++++++++++- channels/h323/ast_h323.h | 1 + 2 files changed, 308 insertions(+), 1 deletion(-) (limited to 'channels/h323') diff --git a/channels/h323/ast_h323.cxx b/channels/h323/ast_h323.cxx index 3c1a56c4b..37684dd59 100644 --- a/channels/h323/ast_h323.cxx +++ b/channels/h323/ast_h323.cxx @@ -923,7 +923,7 @@ static BOOL EmbedCiscoTunneledInfo(H323SignalPDU &pdu) } codes[] = { { Q931::RedirectingNumberIE, }, { Q931::FacilityIE, }, - { Q931::CallingPartyNumberIE, TRUE }, +// { Q931::CallingPartyNumberIE, TRUE }, }; 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); + setupPDU.GetQ931().SetDisplayName(GetDisplayName()); #ifdef TUNNELLING EmbedTunneledInfo(setupPDU); @@ -1239,6 +1240,311 @@ BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & 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) { diff --git a/channels/h323/ast_h323.h b/channels/h323/ast_h323.h index 74e13e7ca..339329560 100644 --- a/channels/h323/ast_h323.h +++ b/channels/h323/ast_h323.h @@ -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 H323Connection::CallEndReason SendSignalSetup(const PString&, const H323TransportAddress&); #ifdef TUNNELLING virtual BOOL HandleSignalPDU(H323SignalPDU &pdu); BOOL EmbedTunneledInfo(H323SignalPDU &pdu); -- cgit v1.2.3