#include "stdafx.h" #include "portmgmt.h" #include "timerval.h" #include "cbridge.h" #include "main.h" // destructor // virtual RTP_LOGICAL_CHANNEL::~RTP_LOGICAL_CHANNEL (void) { // close NAT mappings CloseNATMappings(); // release reference to any associated channel or allocated ports ReleaseAssociationAndPorts(); } /*++ Release ports only if there is no associated channel. If there is an associated channel the ports will be freed when it is deleted. Note that a logical channel could be closed and reopened again. --*/ inline void RTP_LOGICAL_CHANNEL::ReleaseAssociationAndPorts() { // if there is an associated logical channel if (NULL != m_pAssocLogicalChannel) { // release reference to it m_pAssocLogicalChannel->ResetAssociationRef(); m_pAssocLogicalChannel = NULL; } else { if (m_OwnSourceRecvRTPPort != 0) PortPoolFreeRTPPort(m_OwnSourceRecvRTPPort); if (m_OwnAssocLCRecvRTPPort != 0) PortPoolFreeRTPPort(m_OwnAssocLCRecvRTPPort); if (m_OwnDestSendRTPPort != 0) PortPoolFreeRTPPort(m_OwnDestSendRTPPort); if (m_OwnAssocLCSendRTPPort != 0) PortPoolFreeRTPPort(m_OwnAssocLCSendRTPPort); m_OwnSourceRecvRTPPort = m_OwnSourceRecvRTCPPort = 0; m_OwnAssocLCRecvRTPPort = m_OwnDestRecvRTCPPort = 0; m_OwnDestSendRTPPort = m_OwnDestSendRTCPPort = 0; m_OwnAssocLCSendRTPPort = m_OwnSourceSendRTCPPort = 0; } } /*++ This function is called after the OLC is received. --*/ HRESULT RTP_LOGICAL_CHANNEL::SetPorts (void) { HRESULT HResult = E_FAIL; // if there is an associated LC, copy all the ports from that LC. // else, allocate them now if (NULL != m_pAssocLogicalChannel) { // tell the associated logical channel that we are associated // with it m_pAssocLogicalChannel->SetAssociationRef(*this); // save the associated channel's own source/dest ports // assoc channel's source ports become our dest ports and vice versa m_OwnDestRecvRTCPPort = m_pAssocLogicalChannel->m_OwnSourceRecvRTCPPort; m_OwnSourceRecvRTCPPort = m_pAssocLogicalChannel->m_OwnDestRecvRTCPPort; m_OwnDestSendRTCPPort = m_pAssocLogicalChannel->m_OwnSourceSendRTCPPort; m_OwnSourceSendRTCPPort = m_pAssocLogicalChannel->m_OwnDestSendRTCPPort; // Copy the RTP ports m_OwnSourceRecvRTPPort = m_pAssocLogicalChannel->m_OwnAssocLCRecvRTPPort; m_OwnAssocLCRecvRTPPort = m_pAssocLogicalChannel->m_OwnSourceRecvRTPPort; m_OwnDestSendRTPPort = m_pAssocLogicalChannel->m_OwnAssocLCSendRTPPort; m_OwnAssocLCSendRTPPort = m_pAssocLogicalChannel->m_OwnDestSendRTPPort; } else { // allocate own ports - the portmgt apis return an even port only (RTP) // and the assumption is that the RTCP port = RTP port + 1 // however, we use the odd port for receiving RTCP and the even // port for sending RTP HResult = PortPoolAllocRTPPort (&m_OwnSourceRecvRTPPort); if (FAILED(HResult)) { DebugF( _T("RTP_LOGICAL_CHANNEL::SetPorts") _T("failed to allocate m_OwnSourceRecvRTPPort, returning 0x%x\n"), HResult); goto cleanup; } m_OwnSourceRecvRTCPPort = m_OwnSourceRecvRTPPort + 1; HResult = PortPoolAllocRTPPort (&m_OwnAssocLCRecvRTPPort); if (FAILED(HResult)) { DebugF( _T("RTP_LOGICAL_CHANNEL::SetPorts") _T("failed to allocate m_OwnAssocLCRecvRTPPort, returning 0x%x\n"), HResult); goto cleanup; } m_OwnDestRecvRTCPPort = m_OwnAssocLCRecvRTPPort + 1; HResult = PortPoolAllocRTPPort (&m_OwnDestSendRTPPort); if (FAILED(HResult)) { DebugF( _T("RTP_LOGICAL_CHANNEL::SetPorts") _T("failed to allocate m_OwnDestSendRTPPort, returning 0x%x\n"), HResult); goto cleanup; } m_OwnDestSendRTCPPort = m_OwnDestSendRTPPort + 1; HResult = PortPoolAllocRTPPort (&m_OwnAssocLCSendRTPPort); if (FAILED(HResult)) { DebugF( _T("RTP_LOGICAL_CHANNEL::SetPorts, ") _T("failed to allocate m_OwnAssocLCSendRTPPort, returning 0x%x\n"), HResult); goto cleanup; } m_OwnSourceSendRTCPPort = m_OwnAssocLCSendRTPPort + 1; } DebugF (_T("RTP : 0x%x using ports %04X, %04X, %04X, %04X.\n"), &GetCallBridge (), m_OwnSourceRecvRTPPort, m_OwnAssocLCRecvRTPPort, m_OwnDestSendRTPPort, m_OwnAssocLCSendRTPPort); DebugF (_T("RTCP: 0x%x using ports %04X, %04X, %04X, %04X.\n"), &GetCallBridge (), m_OwnSourceRecvRTCPPort, m_OwnDestRecvRTCPPort, m_OwnDestSendRTCPPort, m_OwnSourceSendRTCPPort); return S_OK; cleanup: if (m_OwnSourceRecvRTPPort != 0) PortPoolFreeRTPPort(m_OwnSourceRecvRTPPort); if (m_OwnAssocLCRecvRTPPort != 0) PortPoolFreeRTPPort(m_OwnAssocLCRecvRTPPort); if (m_OwnDestSendRTPPort != 0) PortPoolFreeRTPPort(m_OwnDestSendRTPPort); if (m_OwnAssocLCSendRTPPort != 0) PortPoolFreeRTPPort(m_OwnAssocLCSendRTPPort); m_OwnSourceRecvRTPPort = m_OwnSourceRecvRTCPPort = 0; m_OwnAssocLCRecvRTPPort = m_OwnDestRecvRTCPPort = 0; m_OwnDestSendRTPPort = m_OwnDestSendRTCPPort = 0; m_OwnAssocLCSendRTPPort = m_OwnSourceSendRTCPPort = 0; return HResult; } /////////////////////////////////////////////////////////////////////////////// // // // Routines for setting up and tearing down NAT Redirects // // // /////////////////////////////////////////////////////////////////////////////// // opens the forward RTP, forward RTCP and reverse RTCP streams // This function is called after the OLCAck is received. HRESULT RTP_LOGICAL_CHANNEL::OpenNATMappings( ) { // open NAT mapping for source -> dest RTP stream // this is the forward RTP stream and we must always open this NTSTATUS Status; ULONG RedirectFlags = NatRedirectFlagNoTimeout; if (m_OwnDestIPv4Address == m_DestIPv4Address || m_SourceIPv4Address == m_OwnSourceIPv4Address) { RedirectFlags |= NatRedirectFlagLoopback; } Status = NatCreateRedirectEx ( NatHandle, RedirectFlags, // flags IPPROTO_UDP, // UDP htonl(m_OwnSourceIPv4Address), // source packet dest address (local) htons(m_OwnSourceRecvRTPPort), // source packet dest port (local) htonl(0), // wildcard - source packet source address htons(0), // wildcard - source packet source port htonl(m_DestRTPIPv4Address), // NewDestinationAddress htons(m_DestRTPPort), // NewDestinationPort htonl(m_OwnDestIPv4Address), // NewSourceAddress htons(m_OwnDestSendRTPPort), // NewSourcePort NULL, // RestrictedAdapterIndex NULL, // CompletionRoutine NULL, // CompletionContext NULL); // NotifyEvent if (Status != NO_ERROR) { DebugF (_T("RTP : 0x%x failed to set up redirect for forward RTP stream: (*:* -> %08X:%04X) => (%08X:%04X -> %08X:%04X). Error - %d.\n"), &GetCallBridge (), m_OwnSourceIPv4Address, m_OwnSourceRecvRTPPort, m_OwnDestIPv4Address, m_OwnDestSendRTPPort, m_DestRTPIPv4Address, m_DestRTPPort, Status); return E_FAIL; } else { DebugF (_T("RTP : 0x%x set up redirect for forward RTP stream: (*:* -> %08X:%04X) => (%08X:%04X -> %08X:%04X).\n"), &GetCallBridge (), m_OwnSourceIPv4Address, m_OwnSourceRecvRTPPort, m_OwnDestIPv4Address, m_OwnDestSendRTPPort, m_DestRTPIPv4Address, m_DestRTPPort); } // check to see if we must open the RTCP streams in both directions // source <-> dest // if there is no associated logical channel or the assoc logical // channel is in neither LC_STATE_OPEN_ACK_RCVD nor // LC_STATE_OPENED_CLOSE_RCVD, we must open the RTCP streams if ((!m_pAssocLogicalChannel) || ((LC_STATE_OPEN_ACK_RCVD != m_pAssocLogicalChannel -> m_LogicalChannelState) && (LC_STATE_OPENED_CLOSE_RCVD != m_pAssocLogicalChannel -> m_LogicalChannelState))) { // open NAT mapping for forward RTCP stream Status = NatCreateRedirectEx ( NatHandle, RedirectFlags, // flags IPPROTO_UDP, // UDP htonl(m_OwnSourceIPv4Address), // source packet dest address (local) htons(m_OwnSourceRecvRTCPPort), // source packet dest port (local) htonl(0), // wildcard - source packet source address htons(0), // wildcard - source packet source port htonl(m_DestRTCPIPv4Address), // NewDestinationAddress htons(m_DestRTCPPort), // NewDestinationPort htonl(m_OwnDestIPv4Address), // NewSourceAddress htons(m_OwnDestSendRTCPPort), // NewSourcePort NULL, // RestrictedAdapterIndex NULL, // CompletionRoutine NULL, // CompletionContext NULL); // NotifyEvent if (Status != NO_ERROR) { // close the forward RTP stream // ignore error code DebugF (_T("RTCP: 0x%x failed to set up redirect for forward RCTP stream: (*:* -> %08X:%04X) => (%08X:%04X -> %08X:%04X). Error - %d.\n"), &GetCallBridge (), m_OwnSourceIPv4Address, m_OwnSourceRecvRTCPPort, m_OwnDestIPv4Address, m_OwnDestSendRTCPPort, m_DestRTCPIPv4Address, m_DestRTCPPort, Status); NatCancelRedirect ( NatHandle, IPPROTO_UDP, // UDP htonl(m_OwnSourceIPv4Address), // source packet dest address (local) htons(m_OwnSourceRecvRTPPort), // source packet dest port (local) htonl(0), // wildcard - source packet source address htons(0), // wildcard - source packet source port htonl(m_DestRTPIPv4Address), // NewDestinationAddress htons(m_DestRTPPort), // NewDestinationPort htonl(m_OwnDestIPv4Address), // NewSourceAddress htons(m_OwnDestSendRTPPort)); // NewSourcePort return E_FAIL; } else { DebugF (_T("RTCP: 0x%x set up redirect for forward RCTP stream: (*:* -> %08X:%04X) => (%08X:%04X -> %08X:%04X).\n"), &GetCallBridge (), m_OwnSourceIPv4Address, // source packet dest address (local) m_OwnSourceRecvRTCPPort, // source packet dest port (local) m_OwnDestIPv4Address, // NewSourceAddress m_OwnDestSendRTCPPort, // NewSourcePort m_DestRTCPIPv4Address, // NewDestinationAddress m_DestRTCPPort); // NewDestinationPort } // open NAT mapping for reverse RTCP stream Status = NatCreateRedirectEx ( NatHandle, RedirectFlags, // flags IPPROTO_UDP, // UDP htonl(m_OwnDestIPv4Address), // source packet dest address (local) htons(m_OwnDestRecvRTCPPort), // source packet dest port (local) htonl(0), // wildcard - source packet source address htons(0), // wildcard - source packet source port htonl(m_SourceRTCPIPv4Address), // NewDestinationAddress htons(m_SourceRTCPPort), // NewDestinationPort htonl(m_OwnSourceIPv4Address), // NewSourceAddress htons(m_OwnSourceSendRTCPPort), // NewSourcePort NULL, // RestrictedAdapterIndex NULL, // CompletionRoutine NULL, // CompletionContext NULL); // NotifyEvent if (Status != NO_ERROR) { DebugF (_T("RTCP: 0x%x failed to set up redirect for reverse RTCP stream: (*:* -> %08X:%04X) => (%08X:%04X -> %08X:%04X). Error - %d.\n"), &GetCallBridge (), m_OwnDestIPv4Address, m_OwnDestRecvRTCPPort, m_OwnSourceIPv4Address, m_OwnSourceSendRTCPPort, m_SourceRTCPIPv4Address, m_SourceRTCPPort, Status); // close the forward RTP stream // ignore error code NatCancelRedirect( NatHandle, IPPROTO_UDP, // UDP htonl(m_OwnSourceIPv4Address), // source packet dest address (local) htons(m_OwnSourceRecvRTPPort), // source packet dest port (local) htonl(0), // wildcard - source packet source address htons(0), // wildcard - source packet source port htonl(m_DestRTPIPv4Address), // NewDestinationAddress htons(m_DestRTPPort), // NewDestinationPort htonl(m_OwnDestIPv4Address), // NewSourceAddress htons(m_OwnDestSendRTPPort) // NewSourcePort ); // close the forward RTCP stream // ignore error code NatCancelRedirect( NatHandle, IPPROTO_UDP, // UDP htonl(m_OwnSourceIPv4Address), // source packet dest address (local) htons(m_OwnSourceRecvRTCPPort), // source packet dest port (local) htonl(0), // wildcard - source packet source address htons(0), // wildcard - source packet source port htonl(m_DestRTCPIPv4Address), // NewDestinationAddress htons(m_DestRTCPPort), // NewDestinationPort htonl(m_OwnDestIPv4Address), // NewSourceAddress htons(m_OwnDestSendRTCPPort) // NewSourcePort ); return E_FAIL; } else { DebugF (_T("RTCP: 0x%x set up redirect for reverse RTCP stream: (*:* -> %08X:%04X) => (%08X:%04X -> %08X:%04X).\n"), &GetCallBridge (), m_OwnDestIPv4Address, m_OwnDestRecvRTCPPort, m_OwnSourceIPv4Address, m_OwnSourceSendRTCPPort, m_SourceRTCPIPv4Address, m_SourceRTCPPort); } } return S_OK; } void RTP_LOGICAL_CHANNEL::CloseNATMappings( ) { // if our current state is LC_STATE_OPEN_ACK_RCVD or // LC_STATE_OPENED_CLOSE_RCVD, we have a forward RTP NAT mapping // we may also have to close the RTCP mappings if ( (LC_STATE_OPEN_ACK_RCVD == m_LogicalChannelState) || (LC_STATE_OPENED_CLOSE_RCVD == m_LogicalChannelState) ) { DebugF (_T ("RTP : 0x%x cancels forward RTP redirect (*:* -> %08X:%04X) => (%08X:%04X -> %08X:%04X).\n"), &GetCallBridge (), m_OwnSourceIPv4Address, // source packet dest address (local) m_OwnSourceRecvRTPPort, // source packet dest port (local) m_OwnDestIPv4Address, // NewSourceAddress m_OwnDestSendRTPPort, // NewSourcePort m_DestRTPIPv4Address, // NewDestinationAddress m_DestRTPPort // NewDestinationPort ); // cancel forward RTP NAT mapping // ignore error code ULONG Win32ErrorCode = NO_ERROR; Win32ErrorCode = NatCancelRedirect( NatHandle, IPPROTO_UDP, // UDP htonl(m_OwnSourceIPv4Address), // source packet dest address (local) htons(m_OwnSourceRecvRTPPort), // source packet dest port (local) htonl(0), // wildcard - source packet source address htons(0), // wildcard - source packet source port htonl(m_DestRTPIPv4Address), // NewDestinationAddress htons(m_DestRTPPort), // NewDestinationPort htonl(m_OwnDestIPv4Address), // NewSourceAddress htons(m_OwnDestSendRTPPort) // NewSourcePort ); // if we don't have an associated logical channel or its in neither // LC_STATE_OPEN_ACK_RCVD nor LC_STATE_OPENED_CLOSE_RCVD, we // must close the forward and reverse RTCP NAT mappings if ( (NULL == m_pAssocLogicalChannel) || ( (LC_STATE_OPEN_ACK_RCVD != m_pAssocLogicalChannel->m_LogicalChannelState) && (LC_STATE_OPENED_CLOSE_RCVD != m_pAssocLogicalChannel->m_LogicalChannelState) ) ) { DebugF (_T ("RTCP: 0x%x cancels forward RTCP redirect (*:* -> %08X:%04X) => (%08X:%04X -> %08X:%04X).\n"), &GetCallBridge (), m_OwnSourceIPv4Address, // source packet dest address (local) m_OwnSourceRecvRTCPPort, // source packet dest port (local) m_OwnDestIPv4Address, // NewSourceAddress m_OwnDestSendRTCPPort, // NewSourcePort m_DestRTCPIPv4Address, // NewDestinationAddress m_DestRTCPPort // NewDestinationPort ); // cancel forward RTCP NAT mapping // ignore error code Win32ErrorCode = NatCancelRedirect( NatHandle, IPPROTO_UDP, // UDP htonl(m_OwnSourceIPv4Address), // source packet dest address (local) htons(m_OwnSourceRecvRTCPPort), // source packet dest port (local) htonl(0), // wildcard - source packet source address htons(0), // wildcard - source packet source port htonl(m_DestRTCPIPv4Address), // NewDestinationAddress htons(m_DestRTCPPort), // NewDestinationPort htonl(m_OwnDestIPv4Address), // NewSourceAddress htons(m_OwnDestSendRTCPPort) // NewSourcePort ); DebugF (_T ("RTCP: 0x%x cancels reverse RTCP redirect (*:* -> %08X:%04X) => (%08X:%04X -> %08X:%04X).\n"), &GetCallBridge (), m_OwnDestIPv4Address, // source packet dest address (local) m_OwnDestRecvRTCPPort, // source packet dest port (local) m_OwnSourceIPv4Address, // NewSourceAddress m_OwnSourceSendRTCPPort, // NewSourcePort m_SourceRTCPIPv4Address, // NewDestinationAddress m_SourceRTCPPort // NewDestinationPort ); // close the reverse RTCP stream // ignore error code Win32ErrorCode = NatCancelRedirect( NatHandle, IPPROTO_UDP, // UDP htonl(m_OwnDestIPv4Address), // source packet dest address (local) htons(m_OwnDestRecvRTCPPort), // source packet dest port (local) htonl(0), // wildcard - source packet source address htons(0), // wildcard - source packet source port htonl(m_SourceRTCPIPv4Address), // NewDestinationAddress htons(m_SourceRTCPPort), // NewDestinationPort htonl(m_OwnSourceIPv4Address), // NewSourceAddress htons(m_OwnSourceSendRTCPPort) // NewSourcePort ); } } } /////////////////////////////////////////////////////////////////////////////// // // // Routines for processing H.245 PDUs // // // /////////////////////////////////////////////////////////////////////////////// HRESULT RTP_LOGICAL_CHANNEL::HandleOpenLogicalChannelPDU( IN H245_INFO &H245Info, IN MEDIA_TYPE MediaType, IN DWORD LocalIPv4Address, IN DWORD RemoteIPv4Address, IN DWORD OtherLocalIPv4Address, IN DWORD OtherRemoteIPv4Address, IN WORD LogicalChannelNumber, IN BYTE SessionId, IN RTP_LOGICAL_CHANNEL *pAssocLogicalChannel, IN DWORD SourceRTCPIPv4Address, IN WORD SourceRTCPPort, IN MultimediaSystemControlMessage *pH245pdu ) /*++ Routine Description: Arguments: Return Values: S_OK on success. E_INVALIDARG if the PDU is invalid. --*/ { // this should be the first call to this instance after its // created - hence, these fields must be as asserted _ASSERTE(LC_STATE_NOT_INIT == m_LogicalChannelState); _ASSERTE(NULL == m_pH245Info); _ASSERTE(NULL == m_pAssocLogicalChannel); HRESULT HResult = E_FAIL; m_pH245Info = &H245Info; // the destructor will try to release associations, so assign the // associated logical channel now m_pAssocLogicalChannel = pAssocLogicalChannel; // set the local/remote addresses for our and the other h245 instance m_OwnSourceIPv4Address = LocalIPv4Address; m_SourceIPv4Address = RemoteIPv4Address; m_OwnDestIPv4Address = OtherLocalIPv4Address; m_DestIPv4Address = OtherRemoteIPv4Address; m_LogicalChannelNumber = LogicalChannelNumber; m_SessionId = SessionId; m_MediaType = MediaType; // XXX m_SourceRTCPIPv4Address = SourceRTCPIPv4Address; m_SourceRTCPPort = SourceRTCPPort; // set the rtp and rtcp ports on the source and dest side // if there is a logical channel, then, just the rtcp ports will be shared HResult = SetPorts(); if (FAILED(HResult)) { DebugF( _T("RTP_LOGICAL_CHANNEL::HandleOpenLogicalChannelPDU, ") _T("failed to set its ports, returning 0x%x\n"), HResult); return HResult; } //_ASSERTE(S_FALSE != HResult); OpenLogicalChannel &OlcPDU = pH245pdu->u.request.u.openLogicalChannel; OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters & MultiplexParams = OlcPDU.forwardLogicalChannelParameters.multiplexParameters; H2250LogicalChannelParameters &H2250Params = MultiplexParams.u.h2250LogicalChannelParameters; // modify the OLC PDU by replacing the RTCP address/port // with the h245 address and RTCP port FillH245TransportAddress( m_OwnDestIPv4Address, m_OwnDestRecvRTCPPort, H2250Params.mediaControlChannel); // Should the part below be pushed into H245_INFO::HandleOpenLogicalChannelPDU ????? // let the other H245 instance process the PDU HResult = m_pH245Info->GetOtherH245Info().ProcessMessage( pH245pdu ); if (FAILED(HResult)) { DebugF(_T("RTP_LOGICAL_CHANNEL::HandleOpenLogicalChannelPDU: other H245 instance failed to process OLC PDU, returning 0x%x\n"), HResult); return HResult; } // start timer for a response // TO DO *** creating timers after queueing the send is sufficient. // change back earlier policy of creating these only after the send // callback (to be consistent). creating timers that way would be too // complex for logical channels HResult = CreateTimer(LC_POST_OPEN_TIMER_VALUE); if (FAILED(HResult)) { DebugF (_T("RTP : 0x%x failed to create timer for duration %d milliseconds ('Open Logical Channel'). Error - %x.\n"), &GetCallBridge (), LC_POST_OPEN_TIMER_VALUE, HResult); return HResult; } DebugF (_T("RTP : 0x%x created timer for duration %d milliseconds ('Open Logical Channel').\n"), &GetCallBridge (), LC_POST_OPEN_TIMER_VALUE); // transition state to LC_STATE_OPEN_RCVD m_LogicalChannelState = LC_STATE_OPEN_RCVD; return S_OK; } HRESULT RTP_LOGICAL_CHANNEL::CheckOpenLogicalChannelAckPDU( IN MultimediaSystemControlMessage &H245pdu, OUT BYTE &SessionId, OUT DWORD &DestRTPIPv4Address, OUT WORD &DestRTPPort, OUT DWORD &DestRTCPIPv4Address, OUT WORD &DestRTCPPort ) /*++ Routine Description: Arguments: Return Values: S_OK on success. E_INVALIDARG if the PDU is invalid. --*/ { // get the open logical channel ack PDU OpenLogicalChannelAck &OlcAckPDU = H245pdu.u.response.u.openLogicalChannelAck; // there shouldn't be reverse logical channel parameters if (OpenLogicalChannelAck_reverseLogicalChannelParameters_present & OlcAckPDU.bit_mask) { DebugF( _T("RTP_LOGICAL_CHANNEL::CheckOpenLogicalChannelAckPDU, has ") _T("reverse logical channel params, returning E_INVALIDARG\n")); return E_INVALIDARG; } // there shouldn't be a separate stack if (OpenLogicalChannelAck_separateStack_present & OlcAckPDU.bit_mask) { DebugF( _T("RTP_LOGICAL_CHANNEL::CheckOpenLogicalChannelAckPDU, ") _T("has a separate stack, returning E_INVALIDARG\n")); return E_INVALIDARG; } // we should have forward multiplex ack params - these contain the // H245 params if ( !(forwardMultiplexAckParameters_present & OlcAckPDU.bit_mask) ) { DebugF( _T("RTP_LOGICAL_CHANNEL::CheckOpenLogicalChannelAckPDU, ") _T("doesn't have forward multiplex ack params,") _T(" returning E_INVALIDARG\n")); return E_INVALIDARG; } // we should have the H245 params if (h2250LogicalChannelAckParameters_chosen != OlcAckPDU.forwardMultiplexAckParameters.choice) { DebugF( _T("RTP_LOGICAL_CHANNEL::CheckOpenLogicalChannelAckPDU, ") _T("doesn't have H2250 ack params, returning E_INVALIDARG\n")); return E_INVALIDARG; } H2250LogicalChannelAckParameters &H2250Params = OlcAckPDU.forwardMultiplexAckParameters.\ u.h2250LogicalChannelAckParameters; // it should have media channel info if ( !(H2250LogicalChannelAckParameters_mediaChannel_present & H2250Params.bit_mask) ) { DebugF( _T("RTP_LOGICAL_CHANNEL::CheckOpenLogicalChannelAckPDU, ") _T("doesn't have media channel info, returning E_INVALIDARG\n")); return E_INVALIDARG; } // it should have control channel info if ( !(H2250LogicalChannelAckParameters_mediaControlChannel_present & H2250Params.bit_mask) ) { DebugF(_T("RTP_LOGICAL_CHANNEL::CheckOpenLogicalChannelAckPDU, ") _T("doesn't have media control channel info,") _T(" returning E_INVALIDARG\n")); return E_INVALIDARG; } // save remote client RTP address/port HRESULT HResult = E_FAIL; HResult = GetH245TransportInfo( H2250Params.mediaChannel, DestRTPIPv4Address, DestRTPPort); if (FAILED(HResult)) { DebugF( _T("RTP_LOGICAL_CHANNEL::CheckOpenLogicalChannelAckPDU, ") _T("can't get media channel (RTP) address/port, returning 0x%x\n"), HResult); return HResult; } _ASSERTE(S_OK == HResult); // save remote client RTP address/port HResult = GetH245TransportInfo( H2250Params.mediaControlChannel, DestRTCPIPv4Address, DestRTCPPort); if (FAILED(HResult)) { DebugF( _T("RTP_LOGICAL_CHANNEL::CheckOpenLogicalChannelAckPDU, ") _T("can't get media control channel (RTCP) address/port, ") _T("returning 0x%x\n"), HResult); return HResult; } _ASSERTE(S_OK == HResult); // if there is a session id, save it if (sessionID_present & H2250Params.bit_mask) { // the PDU stores the session ID as an unsigned short // although the ITU spec requires it to be a BYTE value [0..255] // the cast to BYTE is intentional _ASSERTE(255 >= H2250Params.sessionID); SessionId = (BYTE)H2250Params.sessionID; // the session id must be non-zero if (0 == SessionId) { DebugF( _T("RTP_LOGICAL_CHANNEL::CheckOpenLogicalChannelAckPDU, ") _T("has a session id of 0, returning E_INVALIDARG\n")); return E_INVALIDARG; } } else { // if no session id is supplied, the source must have supplied // a non-zero session id in OpenLogicalChannel if (0 == SessionId) { DebugF( _T("RTP_LOGICAL_CHANNEL::CheckOpenLogicalChannelAckPDU, ") _T("the source supplied a session id of 0 and the dest hasn't") _T("supplied one, returning E_INVALIDARG\n")); return E_INVALIDARG; } } return HResult; } HRESULT RTP_LOGICAL_CHANNEL::ProcessOpenLogicalChannelAckPDU( IN MultimediaSystemControlMessage *pH245pdu ) /*++ Routine Description: Arguments: pH245pdu - Return Values: S_OK on success. E_INVALIDARG if the PDU is invalid. --*/ { HRESULT HResult = E_FAIL; switch(m_LogicalChannelState) { case LC_STATE_OPEN_RCVD: { HResult = CheckOpenLogicalChannelAckPDU( *pH245pdu, m_SessionId, m_DestRTPIPv4Address, m_DestRTPPort, m_DestRTCPIPv4Address, m_DestRTCPPort ); if (FAILED(HResult)) { DebugF( _T("RTP_LOGICAL_CHANNEL::ProcessOpenLogicalChannelAckPDU") _T("(&%x), can't process OpenLogicalChannelAck, returning 0x%x\n"), pH245pdu, HResult); return HResult; } _ASSERTE(S_OK == HResult); HResult = OpenNATMappings(); if (FAILED(HResult)) { DebugF( _T("RTP_LOGICAL_CHANNEL::ProcessOpenLogicalChannelAckPDU") _T("(&%x), can't process OpenLogicalChannelAck, returning 0x%x\n"), pH245pdu, HResult); return HResult; } _ASSERTE(S_OK == HResult); OpenLogicalChannelAck &OlcAckPDU = pH245pdu->u.response.u.openLogicalChannelAck; H2250LogicalChannelAckParameters &H2250Params = OlcAckPDU.forwardMultiplexAckParameters.u.h2250LogicalChannelAckParameters; // replace the RTP address/port // with the H.245 address and RTP port FillH245TransportAddress( m_OwnSourceIPv4Address, m_OwnSourceRecvRTPPort, H2250Params.mediaChannel ); // replace the RTCP address/port // with the h245 address and RTCP port FillH245TransportAddress( m_OwnSourceIPv4Address, m_OwnSourceRecvRTCPPort, H2250Params.mediaControlChannel); // reset timer, we must have one (ignore error code if any) _ASSERTE(NULL != m_TimerHandle); TimprocCancelTimer(); DebugF (_T("RTP : 0x%x cancelled timer.\n"), &GetCallBridge ()); // trasition to LC_STATE_OPEN_ACK_RCVD m_LogicalChannelState = LC_STATE_OPEN_ACK_RCVD; } break; case LC_STATE_CLOSE_RCVD: { // if we have received a close logical channel PDU, we must throw // OLC ACKs away and continue to wait DebugF( _T("RTP_LOGICAL_CHANNEL::ProcessOpenLogicalChannelAckPDU") _T("(&%x), in close state %d, returning E_INVALIDARG\n"), pH245pdu, m_LogicalChannelState); return E_INVALIDARG; } break; case LC_STATE_NOT_INIT: case LC_STATE_OPEN_ACK_RCVD: case LC_STATE_OPENED_CLOSE_RCVD: default: { DebugF( _T("RTP_LOGICAL_CHANNEL::ProcessOpenLogicalChannelAckPDU") _T("(&%x), in state %d, returning E_UNEXPECTED"), pH245pdu, m_LogicalChannelState); _ASSERTE(FALSE); return E_UNEXPECTED; } break; }; return HResult; }