aboutsummaryrefslogtreecommitdiffstats
path: root/channels/h323
diff options
context:
space:
mode:
Diffstat (limited to 'channels/h323')
-rw-r--r--channels/h323/ast_h323.cxx308
-rw-r--r--channels/h323/ast_h323.h1
2 files changed, 308 insertions, 1 deletions
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);