windows-nt/Source/XPSP1/NT/enduser/netmeeting/av/h323/t120chan.cpp
2020-09-26 16:20:57 +08:00

307 lines
6.1 KiB
C++

/*
* File: t120chan.cpp
*
* T.120 implementation of ICommChannel, ICtrlCommChannel
*
* Revision History:
*
* 06/11/97 mikev created
*
*/
#include "precomp.h"
ImpT120Chan::ImpT120Chan()
:m_MediaID(MEDIA_TYPE_H323_T120),
m_pCtlChan(NULL),
m_pCapObject(NULL),
m_pH323ConfAdvise(NULL),
m_dwFlags(COMCH_ENABLED),
dwhChannel(0),
uRef(1)
{
ZeroMemory(&local_sin, sizeof(local_sin));
ZeroMemory(&remote_sin, sizeof(remote_sin));
}
ImpT120Chan::~ImpT120Chan ()
{
}
STDMETHODIMP ImpT120Chan::GetMediaType(LPGUID pGuid)
{
if(!pGuid)
return CHAN_E_INVALID_PARAM;
*pGuid = m_MediaID;
return hrSuccess;
}
STDMETHODIMP ImpT120Chan::QueryInterface( REFIID iid, void ** ppvObject)
{
// this breaks the rules for the official COM QueryInterface because
// the interfaces that are queried for are not necessarily real COM
// interfaces. The reflexive property of QueryInterface would be broken in
// that case.
HRESULT hr = E_NOINTERFACE;
if(!ppvObject)
return hr;
*ppvObject = 0;
if(iid == IID_IUnknown)
{
*ppvObject = this;
hr = hrSuccess;
AddRef();
}
else if((iid == IID_ICommChannel))
{
*ppvObject = (ICommChannel *)this;
hr = hrSuccess;
AddRef();
}
else if((iid == IID_ICtrlCommChannel))
{
*ppvObject = (ICtrlCommChan *)this;
hr = hrSuccess;
AddRef();
}
return (hr);
}
ULONG ImpT120Chan::AddRef()
{
uRef++;
return uRef;
}
ULONG ImpT120Chan::Release()
{
uRef--;
if(uRef == 0)
{
delete this;
return 0;
}
else
{
return uRef;
}
}
HRESULT ImpT120Chan::BeginControlSession(IControlChannel *pCtlChan, LPIH323PubCap pCapObject)
{
// this channel is now "in a call".
m_pCtlChan = pCtlChan;
m_pCapObject = pCapObject;
return hrSuccess;
}
HRESULT ImpT120Chan::EndControlSession()
{
// this channel is no longer "in a call".
m_pCtlChan = NULL;
m_pCapObject = NULL;
return hrSuccess;
}
HRESULT ImpT120Chan::OnChannelClose(DWORD dwStatus)
{
HRESULT hr = hrSuccess;
FX_ENTRY("ImpT120Chan::OnChannelClose");
BOOL fCloseAction = FALSE;
SHOW_OBJ_ETIME("ImpT120Chan::OnChannelClose");
m_dwFlags &= ~COMCH_OPEN_PENDING;
switch(dwStatus)
{
default:
ERRORMESSAGE(("%s: unexpected unidirectional notification\r\n", _fx_));
case CHANNEL_CLOSED:
DEBUGMSG(ZONE_COMMCHAN,("%s:closing\r\n",_fx_));
if(IsComchOpen())
{
fCloseAction = TRUE;
m_dwFlags &= ~COMCH_OPEN;
}
else
{
ERRORMESSAGE(("%s: notification when not open\r\n", _fx_));
}
break;
}
// clear general purpose channel handle
dwhChannel = 0;
if(m_pH323ConfAdvise && m_pCtlChan)
{
DEBUGMSG(ZONE_COMMCHAN,("%s:issuing notification 0x%08lX\r\n",_fx_, dwStatus));
m_pH323ConfAdvise->ChannelEvent(this, m_pCtlChan->GetIConnIF(), dwStatus);
}
return hr;
}
HRESULT ImpT120Chan::OnChannelOpening()
{
m_dwFlags |= COMCH_OPEN_PENDING;
return hrSuccess;
}
HRESULT ImpT120Chan::OnChannelOpen(DWORD dwStatus)
{
FX_ENTRY("ImpT120Chan::OnChannelOpen");
SHOW_OBJ_ETIME("ImpICommChan::OnChannelOpen");
// the open is no longer pending, regardless of success or failure
m_dwFlags &= ~COMCH_OPEN_PENDING;
if(IsComchOpen())
{
ERRORMESSAGE(("%s: %d notification when open\r\n", _fx_,
dwStatus));
}
switch(dwStatus)
{
case CHANNEL_OPEN:
m_dwFlags |= (COMCH_OPEN | COMCH_SUPPRESS_NOTIFICATION);
break;
default:
dwStatus = CHANNEL_OPEN_ERROR;
// fall through to notification
case CHANNEL_REJECTED:
case CHANNEL_NO_CAPABILITY:
goto NOTIFICATION;
break;
}
NOTIFICATION:
if(m_pH323ConfAdvise && m_pCtlChan)
{
DEBUGMSG(ZONE_COMMCHAN,("%s:issuing notification 0x%08lX\r\n",_fx_, dwStatus));
m_pH323ConfAdvise->ChannelEvent(this, m_pCtlChan->GetIConnIF(), dwStatus);
}
else
DEBUGMSG(ZONE_COMMCHAN,("%s: *** not issuing notification 0x%08lX m_pH323ConfAdvise: 0x%08lX, m_pCtlChan:0x%08lX \r\n"
,_fx_, dwStatus,m_pH323ConfAdvise,m_pCtlChan));
SHOW_OBJ_ETIME("ImpT120Chan::OnChannelOpen - done ");
return hrSuccess;
}
BOOL ImpT120Chan::SelectPorts(LPIControlChannel pCtlChannel)
{
PSOCKADDR_IN psin;
HRESULT hr;
hr = pCtlChannel->GetLocalAddress(&psin);
{
if(!HR_SUCCEEDED(hr))
return FALSE;
}
local_sin = *psin;
// HACK uses well known port
local_sin.sin_port = htons(1503);
return TRUE;
}
HRESULT ImpT120Chan::AcceptRemoteAddress (PSOCKADDR_IN pSin)
{
if(!pSin)
return CHAN_E_INVALID_PARAM;
remote_sin = *pSin;
return hrSuccess;
}
STDMETHODIMP ImpT120Chan::GetRemoteAddress(PSOCKADDR_IN pAddrOutput)
{
if (!pAddrOutput)
{
return CHAN_E_INVALID_PARAM;
}
*pAddrOutput = remote_sin;
return hrSuccess;
}
HRESULT ImpT120Chan::EnableOpen(BOOL bEnable)
{
if(bEnable)
{
m_dwFlags |= COMCH_ENABLED;
}
else
{
m_dwFlags &= ~COMCH_ENABLED;
}
return hrSuccess;
}
HRESULT ImpT120Chan::IsChannelOpen(BOOL *pbOpen)
{
if(!pbOpen)
return CHAN_E_INVALID_PARAM;
*pbOpen = (IsComchOpen()) ? TRUE:FALSE;
return hrSuccess;
}
HRESULT ImpT120Chan::Open(MEDIA_FORMAT_ID idLocalFormat, IH323Endpoint *pConnection)
{
HRESULT hr;
IConfAdvise * pConfAdvise = NULL;
if((m_dwFlags & COMCH_OPEN_PENDING) || IsComchOpen() || !pConnection)
return CHAN_E_INVALID_PARAM;
if(!m_pCtlChan) // this channel is not part of a call
{
hr = pConnection->QueryInterface(IID_IConfAdvise, (void **)&pConfAdvise);
if(!HR_SUCCEEDED(hr))
goto EXIT;
hr = pConfAdvise->AddCommChannel(this);
if(!HR_SUCCEEDED(hr))
goto EXIT;
ASSERT(m_pCtlChan && m_pCapObject);
}
// Start the control channel stuff needed to open the channel.
// The media format ID arguments are irrelevant for T.120 channels
hr = m_pCtlChan->OpenChannel((ICtrlCommChan*)this, m_pCapObject,
idLocalFormat, INVALID_MEDIA_FORMAT);
EXIT:
if(pConfAdvise)
pConfAdvise->Release();
return hr;
}
HRESULT ImpT120Chan::Close()
{
HRESULT hr = CHAN_E_INVALID_PARAM;
if(!IsComchOpen() || !m_pCtlChan)
goto EXIT;
hr = m_pCtlChan->CloseChannel((ICtrlCommChan*)this);
EXIT:
return hr;
}
HRESULT ImpT120Chan::SetAdviseInterface(IH323ConfAdvise *pH323ConfAdvise)
{
if (!pH323ConfAdvise)
{
return CHAN_E_INVALID_PARAM;
}
m_pH323ConfAdvise = pH323ConfAdvise;
return hrSuccess;
}