?? h323neg.cxx
字號:
/* * h323neg.cxx * * H.323 PDU definitions * * Open H323 Library * * Copyright (c) 1998-2000 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Open H323 Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Portions of this code were written with the assisance of funding from * Vovida Networks, Inc. http://www.vovida.com. * * Contributor(s): ______________________________________. * * $Log: h323neg.cxx,v $ * Revision 1.35 2000/07/14 09:00:48 robertj * Fixed race condition in closing connection and explicit close logical channel. * * Revision 1.34 2000/07/11 19:31:28 robertj * Fixed possible deadlock under unix when trying to restart running TCS. * * Revision 1.33 2000/07/10 16:04:01 robertj * Added TCS=0 support. * Fixed bug where negotiations hang if not fast start and tunnelled but remot does not tunnel. * * Revision 1.32 2000/07/09 14:57:54 robertj * Fixed bug where don't accept TCS if supplied sequence number is zero. * * Revision 1.31 2000/07/04 13:00:36 craigs * Fixed problem with selecting large and small video sizes * * Revision 1.30 2000/07/04 04:15:41 robertj * Fixed capability check of "combinations" for fast start cases. * * Revision 1.29 2000/07/03 00:38:40 robertj * Fixed deadlock caused by nested mutex waits in negotiated channel closing. * * Revision 1.28 2000/06/27 03:46:52 robertj * Fixed another possible race condition on logical channel closure. * * Revision 1.27 2000/06/03 03:16:39 robertj * Fixed using the wrong capability table (should be connections) for some operations. * * Revision 1.26 2000/05/23 11:32:37 robertj * Rewrite of capability table to combine 2 structures into one and move functionality into that class * allowing some normalisation of usage across several applications. * Changed H323Connection so gets a copy of capabilities instead of using endponts, allows adjustments * to be done depending on the remote client application. * * Revision 1.25 2000/05/22 07:32:51 craigs * Fixed problem with ohphone silence detection hanging * * Revision 1.24 2000/05/16 08:13:42 robertj * Added function to find channel by session ID, supporting H323Connection::FindChannel() with mutex. * * Revision 1.23 2000/05/11 04:19:45 robertj * Fixed typo * * Revision 1.22 2000/05/11 04:16:35 robertj * Fixed missing timeout (and typo!) in bidirectional open logical channel. * * Revision 1.21 2000/05/08 05:06:27 robertj * Fixed bug in H.245 close logical channel timeout, thanks XuPeili. * * Revision 1.20 2000/05/05 04:35:10 robertj * Changed where the system timer is sampled to minimise overhead in round trip delay calculation. * * Revision 1.19 2000/05/02 04:32:27 robertj * Fixed copyright notice comment. * * Revision 1.18 2000/04/24 23:47:01 robertj * Fixed bug in master/slave negotiator for if have "in sync" random number generators, thanks Shawn Sincoski. * * Revision 1.17 2000/04/10 17:50:28 robertj * Fixed yet another race condition needing mutex in logical channels management class. * * Revision 1.16 2000/04/05 03:17:31 robertj * Added more RTP statistics gathering and H.245 round trip delay calculation. * * Revision 1.15 2000/03/29 02:14:46 robertj * Changed TerminationReason to CallEndReason to use correct telephony nomenclature. * Added CallEndReason for capability exchange failure. * * Revision 1.14 2000/03/25 02:19:50 robertj * Fixed missing mutex call in some logical channels structure access. * * Revision 1.13 2000/02/17 12:07:43 robertj * Used ne wPWLib random number generator after finding major problem in MSVC rand(). * * Revision 1.12 1999/11/26 01:25:01 craigs * Removed deadlock when remote endpoint requests unsupported channel type * * Revision 1.11 1999/11/19 09:07:27 robertj * Fixed bug allocating incorrect channel number to fast start transmit channel. * * Revision 1.10 1999/11/06 11:00:18 robertj * Fixed race condition in explicit channel close and connection close. * * Revision 1.9 1999/11/06 05:37:45 robertj * Complete rewrite of termination of connection to avoid numerous race conditions. * * Revision 1.8 1999/10/30 12:34:47 robertj * Added information callback for closed logical channel on H323EndPoint. * * Revision 1.7 1999/10/24 04:45:14 robertj * Removed requirement that must be sending capability set to receive capability set. * * Revision 1.6 1999/09/21 14:10:41 robertj * Fixed incorrect PTRACING test and removed uneeded include of videoio.h * * Revision 1.5 1999/09/15 01:26:27 robertj * Changed capability set call backs to have more specific class as parameter. * * Revision 1.4 1999/09/14 14:26:17 robertj * Added more debug tracing. * * Revision 1.3 1999/09/08 04:05:49 robertj * Added support for video capabilities & codec, still needs the actual codec itself! * * Revision 1.2 1999/08/31 12:34:19 robertj * Added gatekeeper support. * * Revision 1.1 1999/08/25 05:08:14 robertj * File fission (critical mass reached). * */#include <ptlib.h>#include <ptclib/random.h>#include "h323neg.h"#define new PNEW///////////////////////////////////////////////////////////////////////////////H245Negotiator::H245Negotiator(H323EndPoint & end, H323Connection & conn) : endpoint(end), connection(conn){ replyTimer.SetNotifier(PCREATE_NOTIFIER(HandleTimeout));}void H245Negotiator::HandleTimeout(PTimer &, INT){}/////////////////////////////////////////////////////////////////////////////H245NegMasterSlaveDetermination::H245NegMasterSlaveDetermination(H323EndPoint & end, H323Connection & conn) : H245Negotiator(end, conn){ retryCount = 1; state = e_Idle; status = e_Indeterminate;}BOOL H245NegMasterSlaveDetermination::Start(){ PWaitAndSignal wait(mutex); retryCount = 1; return Restart();}BOOL H245NegMasterSlaveDetermination::Restart(){ PTRACE(3, "H245\tSending MasterSlaveDetermination"); // Begin the Master/Slave determination procedure determinationNumber = PRandom::Number()%16777216; replyTimer = endpoint.GetMasterSlaveDeterminationTimeout(); state = e_Outgoing; H323ControlPDU pdu; pdu.BuildMasterSlaveDetermination(endpoint.GetTerminalType(), determinationNumber); return connection.WriteControlPDU(pdu);}void H245NegMasterSlaveDetermination::Stop(){ PWaitAndSignal wait(mutex); PTRACE(3, "H245\tStopping MasterSlaveDetermination: state=" << state); if (state == e_Idle) return; replyTimer.Stop(); state = e_Idle;}BOOL H245NegMasterSlaveDetermination::HandleIncoming(const H245_MasterSlaveDetermination & pdu){ PWaitAndSignal wait(mutex); PTRACE(3, "H245\tReceived MasterSlaveDetermination: state=" << state); if (state == e_Incoming) { replyTimer.Stop(); state = e_Idle; return connection.OnControlProtocolError(H323Connection::e_MasterSlaveDetermination, "Duplicate MasterSlaveDetermination"); } replyTimer = endpoint.GetMasterSlaveDeterminationTimeout(); // Determine the master and slave MasterSlaveStatus newStatus; if (pdu.m_terminalType < (unsigned)endpoint.GetTerminalType()) newStatus = e_DeterminedMaster; else if (pdu.m_terminalType > (unsigned)endpoint.GetTerminalType()) newStatus = e_DeterminedSlave; else if (pdu.m_statusDeterminationNumber < determinationNumber) { if ((determinationNumber - pdu.m_statusDeterminationNumber) > 8388608) newStatus = e_DeterminedMaster; else newStatus = e_DeterminedSlave; } else if (pdu.m_statusDeterminationNumber > determinationNumber) { if ((pdu.m_statusDeterminationNumber - determinationNumber) > 8388608) newStatus = e_DeterminedSlave; else newStatus = e_DeterminedMaster; } else newStatus = e_Indeterminate; H323ControlPDU reply; if (newStatus != e_Indeterminate) { PTRACE(2, "H245\tMasterSlaveDetermination: local is " << (newStatus == e_DeterminedMaster ? "master" : "slave")); reply.BuildMasterSlaveDeterminationAck(newStatus == e_DeterminedMaster); state = e_Incoming; status = newStatus; } else if (state == e_Outgoing) { retryCount++; if (retryCount < endpoint.GetMasterSlaveDeterminationRetries()) return Restart(); // Try again replyTimer.Stop(); state = e_Idle; return connection.OnControlProtocolError(H323Connection::e_MasterSlaveDetermination, "Retries exceeded"); } else { reply.BuildMasterSlaveDeterminationReject(H245_MasterSlaveDeterminationReject_cause::e_identicalNumbers); } return connection.WriteControlPDU(reply);}BOOL H245NegMasterSlaveDetermination::HandleAck(const H245_MasterSlaveDeterminationAck & pdu){ PWaitAndSignal wait(mutex); PTRACE(3, "H245\tReceived MasterSlaveDeterminationAck: state=" << state); if (state == e_Idle) return TRUE; replyTimer = endpoint.GetMasterSlaveDeterminationTimeout(); MasterSlaveStatus newStatus; if (pdu.m_decision.GetTag() == H245_MasterSlaveDeterminationAck_decision::e_master) newStatus = e_DeterminedMaster; else newStatus = e_DeterminedSlave; H323ControlPDU reply; if (state == e_Outgoing) { status = newStatus; PTRACE(2, "H245\tMasterSlaveDetermination: remote is " << (newStatus == e_DeterminedSlave ? "master" : "slave")); reply.BuildMasterSlaveDeterminationAck(newStatus == e_DeterminedMaster); if (!connection.WriteControlPDU(reply)) return FALSE; } replyTimer.Stop(); state = e_Idle; if (status != newStatus) return connection.OnControlProtocolError(H323Connection::e_MasterSlaveDetermination, "Master/Slave mismatch"); return TRUE;}BOOL H245NegMasterSlaveDetermination::HandleReject(const H245_MasterSlaveDeterminationReject & pdu){ PWaitAndSignal wait(mutex); PTRACE(3, "H245\tReceived MasterSlaveDeterminationReject: state=" << state); switch (state) { case e_Idle : return TRUE; case e_Outgoing : if (pdu.m_cause.GetTag() == H245_MasterSlaveDeterminationReject_cause::e_identicalNumbers) { retryCount++; if (retryCount < endpoint.GetMasterSlaveDeterminationRetries()) return Restart(); } default : break; } replyTimer.Stop(); state = e_Idle; return connection.OnControlProtocolError(H323Connection::e_MasterSlaveDetermination, "Retries exceeded");}BOOL H245NegMasterSlaveDetermination::HandleRelease(const H245_MasterSlaveDeterminationRelease & /*pdu*/){ PWaitAndSignal wait(mutex); PTRACE(3, "H245\tReceived MasterSlaveDeterminationRelease: state=" << state); if (state == e_Idle) return TRUE; replyTimer.Stop(); state = e_Idle; return connection.OnControlProtocolError(H323Connection::e_MasterSlaveDetermination, "Aborted");}void H245NegMasterSlaveDetermination::HandleTimeout(PTimer &, INT){ PWaitAndSignal wait(mutex); PTRACE(3, "H245\tTimeout on MasterSlaveDetermination: state=" << state); if (state == e_Outgoing) { H323ControlPDU reply; reply.Build(H245_IndicationMessage::e_masterSlaveDeterminationRelease); connection.WriteControlPDU(reply); } state = e_Idle; connection.OnControlProtocolError(H323Connection::e_MasterSlaveDetermination, "Timeout");}#if PTRACINGconst char * const H245NegMasterSlaveDetermination::StateNames[] = { "Idle", "Outgoing", "Incoming"};const char * const H245NegMasterSlaveDetermination::StatusNames[] = { "Indeterminate", "DeterminedMaster", "DeterminedSlave"};#endif/////////////////////////////////////////////////////////////////////////////H245NegTerminalCapabilitySet::H245NegTerminalCapabilitySet(H323EndPoint & end, H323Connection & conn) : H245Negotiator(end, conn){ inSequenceNumber = UINT_MAX; outSequenceNumber = 0; state = e_Idle; receivedCapabilites = FALSE;}BOOL H245NegTerminalCapabilitySet::Start(){ if (state == e_InProgress) { PTRACE(3, "H245\tTerminalCapabilitySet already in progress: outSeq=" << outSequenceNumber); return TRUE; } PWaitAndSignal wait(mutex); // Begin the capability exchange procedure outSequenceNumber = (outSequenceNumber+1)%256; replyTimer = endpoint.GetCapabilityExchangeTimeout(); state = e_InProgress; PTRACE(3, "H245\tSending TerminalCapabilitySet: outSeq=" << outSequenceNumber); H323ControlPDU pdu; connection.OnSendCapabilitySet(pdu.BuildTerminalCapabilitySet(connection, outSequenceNumber)); return connection.WriteControlPDU(pdu);}void H245NegTerminalCapabilitySet::Stop(){ PWaitAndSignal wait(mutex); PTRACE(3, "H245\tStopping TerminalCapabilitySet: state=" << state); if (state == e_Idle) return; replyTimer.Stop(); state = e_Idle; receivedCapabilites = FALSE;}BOOL H245NegTerminalCapabilitySet::HandleIncoming(const H245_TerminalCapabilitySet & pdu){ PWaitAndSignal wait(mutex); PTRACE(3, "H245\tReceived TerminalCapabilitySet:" " state=" << state << " pduSeq=" << pdu.m_sequenceNumber << " inSeq=" << inSequenceNumber); if (pdu.m_sequenceNumber == inSequenceNumber) { PTRACE(3, "H245\tIgnoring TerminalCapabilitySet, already received sequence number"); return TRUE; // Already had this one } inSequenceNumber = pdu.m_sequenceNumber; receivedCapabilites = TRUE; H323Capabilities remoteCapabilities(connection, pdu); const H245_MultiplexCapability * muxCap = NULL;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -