Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

868 lines
30 KiB

#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;
}