869 lines
30 KiB
C++
869 lines
30 KiB
C++
#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;
|
|
}
|