diff --git a/include/h235/h235caps.h b/include/h235/h235caps.h index f1f5de7..99afaf6 100644 --- a/include/h235/h235caps.h +++ b/include/h235/h235caps.h @@ -530,6 +530,265 @@ class H323SecureCapability : public H323SecureRealTimeCapability }; +//////////////////////////////////////////////////////////////////////////////////////// +/**This class describes the interface to a secure extended codec used to transfer data + via the logical channels opened and managed by the H323 control channel. + + An application may create a descendent off this class and override + functions as required for descibing a codec. + */ + +class H323SecureExtendedCapability : public H323ExtendedVideoCapability +{ +public: + + PCLASSINFO(H323SecureExtendedCapability, H323ExtendedVideoCapability); + + /**@name Constructor/Deconstructor */ + //@{ + /**Constructor + */ + H323SecureExtendedCapability( + H323Capability * childCapability, ///< Child Capability + enum H235ChType Ch = H235ChNew, ///< ChannelType + H323Capabilities * capabilities = NULL, ///< Capabilities reference + unsigned secNo = 0, ///< Security Capability No + PBoolean active = false ///< Whether encryption Activated + ); + + H323SecureExtendedCapability( + RTP_QOS * _rtpqos, + H323Capability * childCapability + ); + + /**Deconstructor + */ + ~H323SecureExtendedCapability(); + //@} + + /**@name Operations */ + //@{ + /**Create the channel instance, allocating resources as required. + */ + virtual H323Channel * CreateChannel( + H323Connection & connection, /// Owner connection for channel + H323Channel::Directions dir, /// Direction of channel + unsigned sessionID, /// Session ID for RTP channel + const H245_H2250LogicalChannelParameters * param + /// Parameters for channel + ) const; + + /// Get unique capability number. + virtual unsigned GetCapabilityNumber() const; + + /// Set unique capability number. + virtual void SetCapabilityNumber(unsigned num); + + /// Attach QoS + void AttachQoS(RTP_QOS * _rtpqos); + + /// Set the Associated Capability + virtual void SetAssociatedCapability(unsigned _secNo); + + /// Set the Capability List + virtual void SetCapabilityList(H323Capabilities * capabilities); + + /// Set the encryption active + virtual void SetEncryptionActive(PBoolean active); + + /// Is encryption active + virtual PBoolean IsEncryptionActive() const; + + /// Set Algorithm + virtual void SetEncryptionAlgorithm(const PString & alg); + + /// Get Algorithm + virtual const PString & GetEncryptionAlgorithm() const; + + /// Get the MediaFormat for this capability. + virtual const OpalMediaFormat & GetMediaFormat() const; + + virtual OpalMediaFormat & GetWritableMediaFormat(); + //@} + + /**@name Overrides from class PObject */ + //@{ + /**Create a copy of the object. + */ + virtual PObject * Clone() const; + + /**Compare + */ + PObject::Comparison Compare(const PObject & obj) const; + //@} + + /**@name Identification functions */ + //@{ + /**Get the main type of the capability. + Always returns e_Audio. + */ + virtual MainTypes GetMainType() const; + + /**Get the sub-type of the capability. This is a code dependent on the + main type of the capability. + + This returns one of the four possible combinations of mode and speed + using the enum values of the protocol ASN H245_AudioCapability class. + */ + virtual unsigned GetSubType() const; + + /**Get Generic Identifier + Default returns PString::Empty + */ + virtual PString GetIdentifier() const; + + /**Get the name of the media data format this class represents. + */ + virtual PString GetFormatName() const; + + /**Create the Codec */ + H323Codec * CreateCodec(H323Codec::Direction direction) const; + //@} + + /**@name Operations */ + //@{ + /**Get the default RTP session. + This function gets the default RTP session ID for the capability + type. For example audio capabilities return the value + RTP_Session::DefaultAudioSessionID etc. + + The default behaviour returns zero, indicating it is not an RTP + based capability. + */ + virtual unsigned GetDefaultSessionID() const; + //@} + + /**@name Protocol manipulation */ + //@{ + /**This function is called whenever and outgoing TerminalCapabilitySet + PDU is being constructed for the control channel. It allows the + capability to set the PDU fields from information in members specific + to the class. + + The default behaviour calls the OnSendingPDU() function with a more + specific PDU type. + */ + virtual PBoolean OnSendingPDU( + H245_Capability & pdu /// PDU to set information on + ) const; + + /**This function is called whenever and outgoing OpenLogicalChannel + PDU is being constructed for the control channel. It allows the + capability to set the PDU fields from information in members specific + to the class. + + The default behaviour calls the OnSendingPDU() function with a more + specific PDU type. + */ + virtual PBoolean OnSendingPDU( + H245_DataType & pdu /// PDU to set information on + ) const; + + /**This function is called whenever and outgoing RequestMode + PDU is being constructed for the control channel. It allows the + capability to set the PDU fields from information in members specific + to the class. + + The default behaviour calls the OnSendingPDU() function with a more + specific PDU type. + */ + virtual PBoolean OnSendingPDU( + H245_ModeElement & pdu /// PDU to set information on + ) const; + + /**This function is called whenever and incoming TerminalCapabilitySet + PDU is received on the control channel, and a new H323Capability + descendent was created. This completes reading fields from the PDU + into the classes members. + + If the function returns FALSE then the received PDU codec description + is not supported, so will be ignored. + + The default behaviour calls the OnReceivedPDU() that takes a + H245_AudioCapability and clamps the txFramesInPacket. + */ + + virtual PBoolean OnReceivedPDU( + const H245_Capability & pdu /// PDU to get information from + ); + + /**This function is called whenever and incoming OpenLogicalChannel + PDU has been used to construct the control channel. It allows the + capability to set from the PDU fields, information in members specific + to the class. + + The default behaviour calls the OnReceivedPDU() that takes a + H245_AudioCapability and clamps the txFramesInPacket or + rxFramesInPacket. + */ + virtual PBoolean OnReceivedPDU( + const H245_DataType & pdu, /// PDU to get information from + PBoolean receiver /// is receiver OLC + ); + + /**Compare the sub capability. + */ + virtual PBoolean IsMatch( + const PASN_Choice & subTypePDU ///< sub-type PDU of H323Capability + ) const; + + /**Compare the security part of the capability, if applicable. + */ + virtual PBoolean IsSubMatch( + const PASN_Choice & subTypePDU ///< sub-type PDU of H323Capability + ) const; + + /**Get Child Capability + */ + H323Capability * GetChildCapability() const { return ChildCapability; } + + /**Validate that the capability is usable given the connection. + This checks agains the negotiated protocol version number and remote + application to determine if this capability should be used in TCS or + OLC pdus. + + The default behaviour returns TRUE. + */ + virtual PBoolean IsUsable( + const H323Connection & connection + ) const { return ChildCapability->IsUsable(connection); } + + /**Get the capabilities + */ + virtual const H323Capabilities & GetCapabilities() const; + //@} + + /**Get the direction for this capability. + */ + CapabilityDirection GetCapabilityDirection() const + { return ChildCapability->GetCapabilityDirection(); } + + /**Set the direction for this capability. + */ + void SetCapabilityDirection( + CapabilityDirection dir /// New direction code + ) { ChildCapability->SetCapabilityDirection(dir); } + + /// Get the payload type for the capaibility + RTP_DataFrame::PayloadTypes GetPayloadType() const + { return ChildCapability->GetPayloadType(); } + + //@} + +protected: + H323Capability * ChildCapability; /// Child Capability + H235ChType chtype; /// Channel Type + PBoolean m_active; /// Whether encryption is active + H323Capabilities * m_capabilities; /// Capabilities list + unsigned m_secNo; /// Security Capability + RTP_QOS * nrtpqos; /// RTP QOS + PString m_algorithm; /// Algorithm for encryption +}; //////////////////////////////////////////////////////////////////////////////////////// /**This class describes the secure interface to a data codec that has channels based on diff --git a/include/h323caps.h b/include/h323caps.h index 0772975..8f115b9 100644 --- a/include/h323caps.h +++ b/include/h323caps.h @@ -2590,6 +2590,10 @@ class H323ExtendedVideoCapability : public H323Capability, virtual PBoolean IsMatch( const PASN_Choice & subTypePDU ///< sub-type PDU of H323Capability ) const; + + /**Get the capabilities + */ + virtual const H323Capabilities & GetCapabilities() const; //@} /**@name Operations */ @@ -2610,9 +2614,6 @@ class H323ExtendedVideoCapability : public H323Capability, PINDEX simultaneous ///< The member of the SimultaneousCapabilitySet to add ); - /**Get the capabilities - */ - const H323Capabilities & GetCapabilities() const; //@} protected: @@ -2671,6 +2672,13 @@ class H323ControlExtendedVideoCapability : public H323ExtendedVideoCapability virtual PString GetFormatName() const { return "H.239 Control"; } + /**Get the default RTP session. + This function gets the default RTP session ID for the capability + type. + returns H323Capability::NonRTPSessionID . + */ + virtual unsigned GetDefaultSessionID() const; + virtual PObject * Clone() const { return new H323ControlExtendedVideoCapability(*this); diff --git a/src/h235/h235caps.cxx b/src/h235/h235caps.cxx index 9ea35be..9c15552 100644 --- a/src/h235/h235caps.cxx +++ b/src/h235/h235caps.cxx @@ -663,6 +663,390 @@ H323Codec * H323SecureCapability::CreateCodec(H323Codec::Direction direction) co return ChildCapability->CreateCodec(direction); } + +///////////////////////////////////////////////////////////////////////////// +// For extended + +H323SecureExtendedCapability::H323SecureExtendedCapability(H323Capability * childCapability, enum H235ChType Ch, H323Capabilities * capabilities, unsigned secNo, PBoolean active) + : H323ExtendedVideoCapability(""), + ChildCapability(childCapability), chtype(Ch), m_active(active), + m_capabilities(capabilities), m_secNo(secNo), nrtpqos(NULL) +{ + assignedCapabilityNumber = ChildCapability->GetCapabilityNumber(); +} + + +H323SecureExtendedCapability::H323SecureExtendedCapability(RTP_QOS * _rtpqos,H323Capability * childCapability) + : H323ExtendedVideoCapability(""), + ChildCapability(childCapability), chtype(H235ChNew), m_active(false), + m_capabilities(NULL), m_secNo(0), nrtpqos(_rtpqos) +{ +} + +H323SecureExtendedCapability::~H323SecureExtendedCapability() +{ + delete ChildCapability; +} + + +void H323SecureExtendedCapability::AttachQoS(RTP_QOS * _rtpqos) +{ +#ifdef P_QOS + delete nrtpqos; + nrtpqos = _rtpqos; +#endif +} + +void H323SecureExtendedCapability::SetAssociatedCapability(unsigned _secNo) +{ + m_secNo = _secNo; +} + +H323Channel * H323SecureExtendedCapability::CreateChannel(H323Connection & connection, + H323Channel::Directions dir, + unsigned sessionID, + const H245_H2250LogicalChannelParameters * param) const +{ + + // create a standard RTP channel if we don't have a DH token + H235Capabilities * caps = dynamic_cast(connection.GetLocalCapabilitiesRef()); + if (!caps || !caps->GetDiffieHellMan()) + return connection.CreateRealTimeLogicalChannel(*ChildCapability, dir, sessionID, param, nrtpqos); + + // Support for encrypted external RTP Channel + H323Channel * extRTPChannel = connection.CreateRealTimeLogicalChannel(*this, dir, sessionID, param, nrtpqos); + if (extRTPChannel) + return extRTPChannel; + + RTP_Session * session = NULL; // Session + if ( +#ifdef H323_H46026 + connection.H46026IsMediaTunneled() || +#endif + !param || !param->HasOptionalField(H245_H2250LogicalChannelParameters::e_mediaControlChannel)) { + // Make a fake transport address from the connection so gets initialised with + // the transport type (IP, IPX, multicast etc). + H245_TransportAddress addr; + connection.GetControlChannel().SetUpTransportPDU(addr, H323Transport::UseLocalTSAP); + session = connection.UseSession(sessionID, addr, dir, nrtpqos); + } else { + session = connection.UseSession(param->m_sessionID, param->m_mediaControlChannel, dir, nrtpqos); + } + + if (!session) + return NULL; + + return new H323SecureRTPChannel(connection, *this, dir, *session); +} + +unsigned H323SecureExtendedCapability::GetCapabilityNumber() const +{ + return ChildCapability->GetCapabilityNumber(); +}; + +void H323SecureExtendedCapability::SetCapabilityNumber(unsigned num) +{ + assignedCapabilityNumber = num; + ChildCapability->SetCapabilityNumber(num); +} + +void H323SecureExtendedCapability::SetCapabilityList(H323Capabilities * capabilities) +{ + m_capabilities = capabilities; +} + +void H323SecureExtendedCapability::SetEncryptionActive(PBoolean active) +{ + m_active = active; +} + +PBoolean H323SecureExtendedCapability::IsEncryptionActive() const +{ + return m_active; +} + +void H323SecureExtendedCapability::SetEncryptionAlgorithm(const PString & alg) +{ + m_algorithm = alg; +} + +const PString & H323SecureExtendedCapability::GetEncryptionAlgorithm() const +{ + return m_algorithm; +} + +const OpalMediaFormat & H323SecureExtendedCapability::GetMediaFormat() const +{ + return ChildCapability->GetMediaFormat(); +} + +OpalMediaFormat & H323SecureExtendedCapability::GetWritableMediaFormat() +{ + return ChildCapability->GetWritableMediaFormat(); +} + +H323Capability::MainTypes H323SecureExtendedCapability::GetMainType() const +{ + return ChildCapability->GetMainType(); +} + +PObject * H323SecureExtendedCapability::Clone() const +{ + PTRACE(3, "H235ExtRTP\tCloning Capability: " << GetFormatName()); + + H235ChType ch = H235ChNew; + + switch (chtype) { + case H235ChNew: + ch = H235ChClone; + break; + case H235ChClone: + ch = H235Channel; + break; + case H235Channel: + ch = H235Channel; + break; + } + + return new H323SecureExtendedCapability((H323Capability *)ChildCapability->Clone(), ch, m_capabilities, m_secNo, m_active); +} + +PBoolean H323SecureExtendedCapability::IsMatch(const PASN_Choice & subTypePDU) const +{ + + if (PIsDescendant(&subTypePDU, H245_AudioCapability) && + ChildCapability->GetMainType() == H323Capability::e_Audio) { + const H245_AudioCapability & audio = (const H245_AudioCapability &)subTypePDU; + return ChildCapability->IsMatch(audio); + } + + if (PIsDescendant(&subTypePDU, H245_VideoCapability) && + ChildCapability->GetMainType() == H323Capability::e_Video) { + const H245_VideoCapability & video = (const H245_VideoCapability &)subTypePDU; + return ChildCapability->IsMatch(video); + } + + if (PIsDescendant(&subTypePDU, H245_DataApplicationCapability_application) && + ChildCapability->GetMainType() == H323Capability::e_Data) { + const H245_DataApplicationCapability_application & data = + (const H245_DataApplicationCapability_application &)subTypePDU; + return ChildCapability->IsMatch(data); + } + + if (PIsDescendant(&subTypePDU, H245_H235Media_mediaType)) { + const H245_H235Media_mediaType & data = + (const H245_H235Media_mediaType &)subTypePDU; + return IsSubMatch(data); + } + return false; +} + + +PBoolean H323SecureExtendedCapability::IsSubMatch(const PASN_Choice & subTypePDU) const +{ + const H245_H235Media_mediaType & dataType = (const H245_H235Media_mediaType &)subTypePDU; + if (dataType.GetTag() == H245_H235Media_mediaType::e_audioData && + ChildCapability->GetMainType() == H323Capability::e_Audio) { + const H245_AudioCapability & audio = dataType; + return ChildCapability->IsMatch(audio); + } + + if (dataType.GetTag() == H245_H235Media_mediaType::e_videoData && + ChildCapability->GetMainType() == H323Capability::e_Video) { + const H245_VideoCapability & video = dataType; + return ChildCapability->IsMatch(video); + } + + return false; +} + +PObject::Comparison H323SecureExtendedCapability::Compare(const PObject & obj) const +{ + if (!PIsDescendant(&obj, H323SecureExtendedCapability)) + return LessThan; + + Comparison result = H323Capability::Compare(obj); + if (result != EqualTo) + return result; + + const H323SecureExtendedCapability & other = (const H323SecureExtendedCapability &)obj; + + return ChildCapability->Compare(*(other.GetChildCapability())); +} + +unsigned H323SecureExtendedCapability::GetDefaultSessionID() const +{ + return ChildCapability->GetDefaultSessionID(); +} + +//////////////////////////////////////////////////////////////////////// +// PDU Sending + +PBoolean H323SecureExtendedCapability::OnSendingPDU(H245_ModeElement & mode) const +{ + switch (ChildCapability->GetMainType()) { + case H323Capability::e_Video: +#ifdef H323_VIDEO + return ((H323VideoCapability *)ChildCapability)->OnSendingPDU(mode); +#endif // H323_VIDEO + case H323Capability::e_Audio: + case H323Capability::e_Data: + default: + return false; + } +} + +PBoolean H323SecureExtendedCapability::OnSendingPDU(H245_DataType & dataType) const +{ + // find the matching H235SecurityCapability to get the agreed algorithms + // if not found or no matching algorithm then assume no encryption. + H235SecurityCapability * secCap = NULL; + if (m_capabilities) { + secCap = (H235SecurityCapability *)m_capabilities->FindCapability(m_secNo); + if (secCap && secCap->GetAlgorithmCount() > 0) { + (PRemoveConst(H323SecureExtendedCapability,this))->SetEncryptionActive(true); + (PRemoveConst(H323SecureExtendedCapability,this))->SetEncryptionAlgorithm(secCap->GetAlgorithm()); + } + } + + if (!IsEncryptionActive()) { + switch (ChildCapability->GetMainType()) { + case H323Capability::e_Video: +#ifdef H323_VIDEO + dataType.SetTag(H245_DataType::e_videoData); + return ((H323VideoCapability *)ChildCapability)->OnSendingPDU((H245_VideoCapability &)dataType, e_OLC); +#endif // H323_VIDEO + case H323Capability::e_Audio: + case H323Capability::e_Data: + default: + break; + } + return false; + } + + dataType.SetTag(H245_DataType::e_h235Media); + H245_H235Media & h235Media = dataType; + // Load the algorithm + if (secCap) + secCap->OnSendingPDU(h235Media.m_encryptionAuthenticationAndIntegrity, e_OLC); + + H245_H235Media_mediaType & cType = h235Media.m_mediaType; + switch (ChildCapability->GetMainType()) { + case H323Capability::e_Video: +#ifdef H323_VIDEO + cType.SetTag(H245_H235Media_mediaType::e_videoData); + return ((H323VideoCapability *)ChildCapability)->OnSendingPDU((H245_VideoCapability &)cType, e_OLC); +#endif // H323_VIDEO + case H323Capability::e_Audio: + case H323Capability::e_Data: + default: + break; + } + return false; +} + +PBoolean H323SecureExtendedCapability::OnReceivedPDU(const H245_DataType & dataType,PBoolean receiver) +{ + if (dataType.GetTag() != H245_DataType::e_h235Media) + return ChildCapability->OnReceivedPDU(dataType, receiver); + + const H245_H235Media & h235Media = dataType; + + if (m_capabilities) { + H235SecurityCapability * secCap = (H235SecurityCapability *)m_capabilities->FindCapability(m_secNo); + if (!secCap || !secCap->OnReceivedPDU(h235Media.m_encryptionAuthenticationAndIntegrity, e_OLC)) { + PTRACE(4,"H235\tFailed to locate security capability " << m_secNo); + return false; + } + if (secCap && secCap->GetAlgorithmCount() > 0) { + SetEncryptionAlgorithm(secCap->GetAlgorithm()); + SetEncryptionActive(true); + } + } + + const H245_H235Media_mediaType & mediaType = h235Media.m_mediaType; + + switch (ChildCapability->GetMainType()) { + case H323Capability::e_Video: +#ifdef H323_VIDEO + if (mediaType.GetTag() == H245_H235Media_mediaType::e_videoData) + return ((H323CodecExtendedVideoCapability *)ChildCapability)->OnReceivedPDU((const H245_VideoCapability &)mediaType); + break; +#endif // H323_VIDEO + + case H323Capability::e_Audio: + case H323Capability::e_Data: + default: + break; + } + return false; +} + +////////////////////////////////////////////////////////////////////////////// +// Child Capability Intercept + +PBoolean H323SecureExtendedCapability::OnSendingPDU(H245_Capability & pdu) const +{ + switch (ChildCapability->GetMainType()) { + case H323Capability::e_Video: +#ifdef H323_VIDEO + return ((H323VideoCapability *)ChildCapability)->OnSendingPDU(pdu); +#endif // H323_VIDEO + case H323Capability::e_Audio: + case H323Capability::e_Data: + case H323Capability::e_UserInput: + case H323Capability::e_ExtendVideo: + default: + return false; + } +} + +PBoolean H323SecureExtendedCapability::OnReceivedPDU(const H245_Capability & pdu) +{ + switch (ChildCapability->GetMainType()) { + case H323Capability::e_Video: +#ifdef H323_VIDEO + return ((H323VideoCapability *)ChildCapability)->OnReceivedPDU(pdu); +#endif // H323_VIDEO + case H323Capability::e_Audio: + case H323Capability::e_Data: + case H323Capability::e_UserInput: + case H323Capability::e_ExtendVideo: + default: + return false; + } +} + + +PString H323SecureExtendedCapability::GetFormatName() const +{ + return PString("H323SecureExtendedCapability - ") + ChildCapability->GetFormatName() + (m_active ? " #" : ""); +} + +unsigned H323SecureExtendedCapability::GetSubType() const +{ + return ChildCapability->GetSubType(); +} + +PString H323SecureExtendedCapability::GetIdentifier() const +{ + return ChildCapability->GetIdentifier(); +} + +H323Codec * H323SecureExtendedCapability::CreateCodec(H323Codec::Direction direction) const +{ + return ChildCapability->CreateCodec(direction); +} + +const H323Capabilities & H323SecureExtendedCapability::GetCapabilities() const +{ + H323ExtendedVideoCapability* extCap = dynamic_cast(ChildCapability); + if (extCap) + return extCap->GetCapabilities(); + else + return extCapabilities; +} + ///////////////////////////////////////////////////////////////////////////// @@ -961,6 +1345,7 @@ void H235Capabilities::AddSecure(PINDEX descriptorNum, PINDEX simultaneous, H323 return; if (!PIsDescendant(capability,H323SecureCapability) && + !PIsDescendant(capability,H323SecureExtendedCapability) && !PIsDescendant(capability,H323SecureDataCapability) && !PIsDescendant(capability,H235SecurityCapability)) return; @@ -990,6 +1375,7 @@ void H235Capabilities::AddSecure(PINDEX descriptorNum, PINDEX simultaneous, H323 H323Capability * H235Capabilities::CopySecure(PINDEX descriptorNum, PINDEX simultaneous, const H323Capability & capability) { if (!PIsDescendant(&capability,H323SecureCapability) && + !PIsDescendant(&capability,H323SecureExtendedCapability) && !PIsDescendant(&capability,H323SecureDataCapability) && !PIsDescendant(&capability,H235SecurityCapability)) return NULL; @@ -1012,8 +1398,8 @@ H323Capability * H235Capabilities::CopySecure(PINDEX descriptorNum, PINDEX simul void H235Capabilities::WrapCapability(PINDEX descriptorNum, PINDEX simultaneous, H323Capability & capability) { - if (PIsDescendant(&capability,H323SecureCapability) || + PIsDescendant(&capability,H323SecureExtendedCapability) || PIsDescendant(&capability,H323SecureDataCapability) || PIsDescendant(&capability,H235SecurityCapability)) { CopySecure(descriptorNum, simultaneous, capability); @@ -1030,12 +1416,15 @@ void H235Capabilities::WrapCapability(PINDEX descriptorNum, PINDEX simultaneous, case OpalMediaFormat::DefaultVideoSessionID: AddSecure(descriptorNum, simultaneous, new H323SecureCapability(capability, H235ChNew,this)); break; + case OpalMediaFormat::DefaultExtVideoSessionID: + AddSecure(descriptorNum, simultaneous, new H323SecureExtendedCapability((H323Capability * )capability.Clone(), H235ChNew,this)); + break; case OpalMediaFormat::DefaultDataSessionID: AddSecure(descriptorNum, simultaneous, new H323SecureDataCapability(capability, H235ChNew,this)); break; case OpalMediaFormat::NonRTPSessionID: //case OpalMediaFormat::DefaultDataSessionID: - case OpalMediaFormat::DefaultExtVideoSessionID: + //case OpalMediaFormat::DefaultExtVideoSessionID: case OpalMediaFormat::DefaultFileSessionID: default: SetCapability(descriptorNum, simultaneous, (H323Capability *)capability.Clone()); @@ -1097,6 +1486,11 @@ PINDEX H235Capabilities::AddAllCapabilities(PINDEX descriptorNum, new H235SecurityCapability(this, newCapability->GetCapabilityNumber())); break; case OpalMediaFormat::DefaultExtVideoSessionID: + newCapability = new H323SecureExtendedCapability(capability, H235ChNew, this); + num = SetCapability(descriptorNum, simultaneous, newCapability); + num = SetCapability(descriptorNum, simultaneous, + new H235SecurityCapability(this, newCapability->GetCapabilityNumber())); + break; case OpalMediaFormat::DefaultFileSessionID: default: num = SetCapability(descriptorNum, simultaneous, capability); diff --git a/src/h323caps.cxx b/src/h323caps.cxx index d4fb355..d95acb0 100644 --- a/src/h323caps.cxx +++ b/src/h323caps.cxx @@ -1930,6 +1930,11 @@ H323ControlExtendedVideoCapability::H323ControlExtendedVideoCapability() { } +unsigned H323ControlExtendedVideoCapability::GetDefaultSessionID() const +{ + return OpalMediaFormat::NonRTPSessionID; +} + PBoolean H323ControlExtendedVideoCapability::CloseChannel(H323Connection * connection, H323Capability::CapabilityDirection dir) { SendGenericMessage(H239Control::e_h245command, connection, dir == H323Capability::e_Transmit);