📄 h323.cxx
字号:
* Fixed H245 connect on receiving call. * * Revision 1.10 1999/06/09 06:18:00 robertj * GCC compatibiltiy. * * Revision 1.9 1999/06/09 05:26:19 robertj * Major restructuring of classes. * * Revision 1.8 1999/06/07 00:37:05 robertj * Allowed for reuseaddr on listen when in debug version * * Revision 1.7 1999/06/06 06:06:36 robertj * Changes for new ASN compiler and v2 protocol ASN files. * * Revision 1.6 1999/04/26 06:20:22 robertj * Fixed bugs in protocol * * Revision 1.5 1999/04/26 06:14:46 craigs * Initial implementation for RTP decoding and lots of stuff * As a whole, these changes are called "First Noise" * * Revision 1.4 1999/02/23 11:04:28 robertj * Added capability to make outgoing call. * * Revision 1.3 1999/01/16 01:31:33 robertj * Major implementation. * * Revision 1.2 1999/01/02 04:00:56 robertj * Added higher level protocol negotiations. * * Revision 1.1 1998/12/14 09:13:09 robertj * Initial revision * */#include <ptlib.h>#include "h323.h"#include "h323neg.h"#include "channels.h"#include "h323rtp.h"#define new PNEW#if !PTRACING // Stuff to remove unised parameters warning#define PTRACE_pdu#endif/////////////////////////////////////////////////////////////////////////////#if PTRACINGconst char * const H323Connection::CallEndReasonNames[NumCallEndReasons] = { "EndedByLocalUser", /// Local endpoint application cleared call "EndedByNoAccept", /// Local endpoint did not accept call OnIncomingCall()=FALSE "EndedByAnswerDenied", /// Local endpoint declined to answer call "EndedByRemoteUser", /// Remote endpoint application cleared call "EndedByRefusal", /// Remote endpoint refused call "EndedByNoAnswer", /// Remote endpoint did not answer in required time "EndedByCallerAbort", /// Remote endpoint stopped calling "EndedByTransportFail", /// Transport error cleared call "EndedByConnectFail", /// Transport connection failed to establish call "EndedByGatekeeper", /// Gatekeeper has cleared call "EndedByNoUser", /// Call failed as could not find user (in GK) "EndedByNoBandwidth", /// Call failed as could not get enough bandwidth "EndedByCallForwarded", /// Call was forwarded using FACILITY message "EndedByCapabilityExchange" /// Could not find common capabilities};const char * const H323Connection::ConnectionStatesNames[NumConnectionStates] = { "NoConnectionActive", "AwaitingGatekeeperAdmission", "AwaitingTransportConnect", "AwaitingSignalConnect", "HasExecutedSignalConnect", "EstablishedConnection", "ShuttingDownConnection"};const char * const H323Connection::FastStartStateNames[NumFastStartStates] = { "FastStartDisabled", "FastStartInitiate", "FastStartResponse"};const char * const H323Connection::AnswerCallResponseNames[NumAnswerCallResponses] = { "AnswerCallNow", "AnswerCallDenied", "AnswerCallPending", "AnswerCallDeferred"};#endifH323Connection::H323Connection(H323EndPoint & ep, unsigned ref) : endpoint(ep), localPartyName(ep.GetLocalUserName()), localCapabilities(ep.GetCapabilities()){ callAnswered = FALSE; distinctiveRing = 0; callReference = ref; signallingChannel = NULL; controlChannel = NULL; h245Tunneling = TRUE; h245TunnelPDU = NULL; connectionState = NoConnectionActive; callEndReason = NumCallEndReasons; answerResponse = NumAnswerCallResponses; bandwidthAvailable = endpoint.GetInitialBandwidth(); fastStartState = FastStartDisabled; remoteMaxAudioDelayJitter = 0; masterSlaveDeterminationProcedure = new H245NegMasterSlaveDetermination(endpoint, *this); capabilityExchangeProcedure = new H245NegTerminalCapabilitySet(endpoint, *this); logicalChannels = new H245NegLogicalChannels(endpoint, *this); requestModeProcedure = new H245NegRequestMode(endpoint, *this); roundTripDelayProcedure = new H245NegRoundTripDelay(endpoint, *this);}H323Connection::~H323Connection(){ delete masterSlaveDeterminationProcedure; delete capabilityExchangeProcedure; delete logicalChannels; delete requestModeProcedure; delete roundTripDelayProcedure; delete signallingChannel; delete controlChannel; PTRACE(3, "H323\tConnection " << callToken << " deleted.");}void H323Connection::SetCallEndReason(CallEndReason reason){ // Only set reason if not already set to something if (callEndReason == NumCallEndReasons) callEndReason = reason;}BOOL H323Connection::ClearCall(H323Connection::CallEndReason reason){ return endpoint.ClearCall(callToken, reason);}void H323Connection::CleanUpOnCallEnd(){ PTRACE(3, "H323\tConnection " << callToken << " closing: connectionState=" << connectionState); // Special case of aborting while waiting for a transport connect (in // particular a TCP socket connect) which must be aborted before the Lock() if (connectionState == AwaitingTransportConnect) signallingChannel->CleanUpOnTermination(); // Make sure no one is stll using this object before we go to town on it Lock(); connectionState = ShuttingDownConnection; // Clean up any fast start "pending" channels we may have running. PINDEX i; for (i = 0; i < fastStartChannels.GetSize(); i++) fastStartChannels[i].CleanUpOnTermination(); fastStartChannels.RemoveAll(); // Dispose of all the logical channels for (i = 0; i < logicalChannels->GetSize(); i++) { H323Channel * channel = logicalChannels->GetChannelAt(i); if (channel != NULL) channel->CleanUpOnTermination(); } logicalChannels->RemoveAll(); if (callEndReason == EndedByLocalUser) { // Send an H.245 end session to the remote endpoint. H323ControlPDU pdu; pdu.BuildEndSessionCommand(H245_EndSessionCommand::e_disconnect); WriteControlPDU(pdu); } /* If we have a signalling channel, then we should send a release complete. This may actually be redundent if we a terminating via the remote end sending release complete or if there is a transport failure, but it does not hurt to try and send it anyway. */ if (signallingChannel != NULL) { if (signallingChannel->IsOpen()) { PTRACE(2, "H225\tSending release complete PDU: callRef=" << callReference); H323SignalPDU replyPDU; replyPDU.BuildReleaseComplete(*this); replyPDU.Write(*signallingChannel); } signallingChannel->CleanUpOnTermination(); } // Wait for control channel to be cleaned up (thread ended). if (controlChannel != NULL) controlChannel->CleanUpOnTermination(); // Check for gatekeeper and do disengage if have one if (callEndReason != EndedByGatekeeper) { H323Gatekeeper * gatekeeper = endpoint.GetGatekeeper(); if (gatekeeper != NULL) gatekeeper->DisengageRequest(*this, H225_DisengageReason::e_normalDrop); } PTRACE(1, "H323\tConnection " << callToken << " terminated.");}void H323Connection::AttachSignalChannel(H323Transport * channel){ if (signallingChannel != NULL && signallingChannel->IsOpen()) { PAssertAlways(PLogicError); return; } delete signallingChannel; signallingChannel = channel;}BOOL H323Connection::WriteSignalPDU(H323SignalPDU & pdu){ PAssert(signallingChannel != NULL, PLogicError); if (signallingChannel == NULL) return FALSE; if (!signallingChannel->IsOpen()) return FALSE; pdu.m_h323_uu_pdu.m_h245Tunneling = h245Tunneling; return pdu.Write(*signallingChannel);}void H323Connection::HandleSignallingChannel(){ PAssert(signallingChannel != NULL, PLogicError); PTRACE(2, "H225\tReading PDUs: callRef=" << callReference); H323SignalPDU pdu; while (signallingChannel->IsOpen()) { if (pdu.Read(*signallingChannel)) { if (!HandleSignalPDU(pdu)) { ClearCall(EndedByTransportFail); break; } } else if (connectionState != EstablishedConnection || signallingChannel->GetErrorCode() != PChannel::Timeout) { if (controlChannel == NULL || !controlChannel->IsOpen()) ClearCall(signallingChannel->GetErrorCode() != PChannel::Timeout ? EndedByTransportFail : EndedByNoAnswer); signallingChannel->Close(); break; } if (controlChannel == NULL) StartRoundTripDelay(); } PTRACE(2, "H225\tSignal channel closed.");}BOOL H323Connection::HandleSignalPDU(H323SignalPDU & pdu){ const Q931 & q931 = pdu.GetQ931(); PTRACE(3, "H225\tHandling PDU: " << q931.GetMessageTypeName() << " callRef=" << q931.GetCallReference()); // If remote does not do tunneling, so we don't either. Note that if it // gets turned off once, it stays off for good. if (h245Tunneling && !pdu.m_h323_uu_pdu.m_h245Tunneling) { masterSlaveDeterminationProcedure->Stop(); capabilityExchangeProcedure->Stop(); h245Tunneling = FALSE; } switch (q931.GetMessageType()) { case Q931::SetupMsg : if (!OnReceivedSignalSetup(pdu)) return FALSE; break; case Q931::CallProceedingMsg : if (!OnReceivedCallProceeding(pdu)) return FALSE; break; case Q931::AlertingMsg : if (!OnReceivedAlerting(pdu)) return FALSE; break; case Q931::ConnectMsg : if (!OnReceivedSignalConnect(pdu)) return FALSE; break; case Q931::FacilityMsg : if (!OnReceivedFacility(pdu)) return FALSE; break; case Q931::StatusEnquiryMsg : if (!OnReceivedStatusEnquiry(pdu)) return FALSE; break; case Q931::ReleaseCompleteMsg : if (connectionState == EstablishedConnection) ClearCall(EndedByRemoteUser); else if (answerResponse == AnswerCallDeferred) ClearCall(EndedByCallerAbort); else ClearCall(EndedByRefusal); return FALSE; default : if (!OnUnknownSignalPDU(pdu)) return FALSE; } // Process tunnelled H245 PDU, if present. HandleTunnelPDU(pdu, NULL); return TRUE;}void H323Connection::HandleTunnelPDU(const H323SignalPDU & pdu, H323SignalPDU * reply){ if (!h245Tunneling) return; h245TunnelPDU = reply; for (PINDEX i = 0; i < pdu.m_h323_uu_pdu.m_h245Control.GetSize(); i++) { PPER_Stream strm = pdu.m_h323_uu_pdu.m_h245Control[i].GetValue(); HandleControlData(strm); } h245TunnelPDU = NULL; // Make sure does not get repeated, break const and clear tunnelled H.245 PDU's ((H323SignalPDU &)pdu).m_h323_uu_pdu.m_h245Control.SetSize(0);}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); PPER_Stream strm; open.Encode(strm);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -