Leaked source code of windows server 2003
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.
 
 
 
 
 
 

531 lines
12 KiB

/*******************************************************************************
Module: bridge.cpp
Author: Qianbo Huai
Abstract:
implements the class CBridge
*******************************************************************************/
#include "stdafx.h"
#include "work.h"
extern LPSTR glpCmdLine;
/*//////////////////////////////////////////////////////////////////////////////
hard coded SDP
////*/
const WCHAR * const MySDP = L"\
v=0\n\
o=qhuai 0 0 IN IP4 157.55.89.115\n\
s=BridgeTestConf\n\
c=IN IP4 239.9.20.26/15\n\
t=0 0\n\
m=video 20000 RTP/AVP 34 31\n\
m=audio 20040 RTP/AVP 0 4\n\
";
const WCHAR * const MySDP2 = L"\
v=0\n\
o=qhuai 0 0 IN IP4 157.55.89.115\n\
s=BridgeTestConf2\n\
c=IN IP4 239.9.20.26/15\n\
t=0 0\n\
m=video 20000 RTP/AVP 34 31\n\
m=audio 20040 RTP/AVP 3\n\
";
/*//////////////////////////////////////////////////////////////////////////////
initiates tapi and listens at h323 address
////*/
HRESULT
CBridge::InitTapi ()
{
HRESULT hr;
// init members
m_pTapi = NULL;
m_pH323Addr = NULL;
m_pSDPAddr = NULL;
m_pBridgeCall = new CBridgeCall (this);
// create tapi
hr = CoCreateInstance (
CLSID_TAPI,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITTAPI,
(LPVOID *)&m_pTapi
);
if (FAILED(hr))
return hr;
// tapi initiate
hr = m_pTapi->Initialize ();
if (FAILED(hr))
return hr;
// associate event with listener
CTAPIEventNotification *pEventNotif = NULL;
IConnectionPointContainer *pContainer = NULL;
IConnectionPoint *pPoint = NULL;
IH323LineEx *pIH323LineEx = NULL;
ULONG ulTapiEventAdvise;
long lCallNotif;
BSTR bstrAddrName = NULL;
// create event notification
pEventNotif = new CTAPIEventNotification;
if (!pEventNotif)
{
hr = E_OUTOFMEMORY;
goto Error;
}
// get pointer container from tapi
hr = m_pTapi->QueryInterface (
IID_IConnectionPointContainer,
(void **)&pContainer
);
if (FAILED(hr))
goto Error;
// get connection point from container
hr = pContainer->FindConnectionPoint (
IID_ITTAPIEventNotification,
&pPoint
);
if (FAILED(hr))
goto Error;
// advise event notification on connection pointer
hr = pPoint->Advise (
pEventNotif,
&ulTapiEventAdvise
);
if (FAILED(hr))
goto Error;
// put event filter on tapi
hr = m_pTapi->put_EventFilter (
TE_CALLNOTIFICATION |
TE_CALLSTATE |
TE_CALLMEDIA |
TE_PRIVATE
);
if (FAILED(hr))
goto Error;
// find h323 address
bstrAddrName = SysAllocString (L"H323 Line");
hr = FindAddress (
0,
bstrAddrName,
TAPIMEDIATYPE_AUDIO,
&m_pH323Addr
);
SysFreeString (bstrAddrName);
if (FAILED(hr))
goto Error;
// check if it supports video
BOOL fSupportsVideo;
if (AddressSupportsMediaType (m_pH323Addr, TAPIMEDIATYPE_VIDEO))
m_lH323MediaType = TAPIMEDIATYPE_AUDIO | TAPIMEDIATYPE_VIDEO;
else
m_lH323MediaType = TAPIMEDIATYPE_AUDIO;
hr = m_pH323Addr->QueryInterface(&pIH323LineEx);
if (SUCCEEDED(hr))
{
hr = pIH323LineEx->SetExternalT120Address(TRUE, INADDR_ANY, 1503);
H245_CAPABILITY Capabilities[] =
{HC_G711, HC_G723, HC_H263QCIF, HC_H261QCIF};
DWORD Weights[] = {200, 100, 100, 0};
hr = pIH323LineEx->SetDefaultCapabilityPreferrence(
4, Capabilities, Weights
);
}
// register call notification
hr = m_pTapi->RegisterCallNotifications (
m_pH323Addr,
VARIANT_TRUE,
VARIANT_TRUE,
m_lH323MediaType,
ulTapiEventAdvise,
&lCallNotif
);
if (FAILED(hr))
goto Error;
// find sdp address
hr = FindAddress (
LINEADDRESSTYPE_SDP,
NULL,
TAPIMEDIATYPE_AUDIO,
&m_pSDPAddr
);
if (FAILED(hr))
return hr;
// check if it supports video
if (AddressSupportsMediaType (m_pSDPAddr, TAPIMEDIATYPE_VIDEO))
m_lSDPMediaType = TAPIMEDIATYPE_AUDIO | TAPIMEDIATYPE_VIDEO;
else
m_lSDPMediaType = TAPIMEDIATYPE_AUDIO;
Cleanup:
if (pEventNotif)
pEventNotif->Release ();
if (pPoint)
pPoint->Release ();
if (pContainer)
pContainer->Release ();
if (pIH323LineEx)
pIH323LineEx->Release ();
return hr;
Error:
if (m_pH323Addr)
{
m_pH323Addr->Release ();
m_pH323Addr = NULL;
}
if (m_pSDPAddr)
{
m_pSDPAddr->Release ();
m_pSDPAddr = NULL;
}
if (m_pTapi)
{
m_pTapi->Release ();
m_pTapi = NULL;
}
goto Cleanup;
}
/*//////////////////////////////////////////////////////////////////////////////
////*/
void
CBridge::ShutdownTapi ()
{
if (m_pBridgeCall)
{
delete m_pBridgeCall;
m_pBridgeCall = NULL;
}
if (m_pSDPAddr)
{
m_pSDPAddr->Release ();
m_pSDPAddr = NULL;
}
if (m_pH323Addr)
{
m_pH323Addr->Release ();
m_pH323Addr = NULL;
}
if (m_pTapi)
{
m_pTapi->Release ();
m_pTapi = NULL;
}
}
/*//////////////////////////////////////////////////////////////////////////////
create h323 call from event
////*/
HRESULT
CBridge::CreateH323Call (IDispatch *pEvent)
{
HRESULT hr;
ITCallNotificationEvent *pNotify = NULL;
CALL_PRIVILEGE privilege;
ITCallInfo *pCallInfo = NULL;
ITBasicCallControl *pCall = NULL;
// get call event interface
hr = pEvent->QueryInterface (
IID_ITCallNotificationEvent,
(void **)&pNotify
);
if (FAILED(hr))
return hr;
// get call info
hr = pNotify->get_Call (&pCallInfo);
if (FAILED(hr))
goto Error;
// if we own the call
hr = pCallInfo->get_Privilege (&privilege);
if (FAILED(hr))
goto Error;
if (CP_OWNER!=privilege)
{
hr = E_UNEXPECTED;
goto Cleanup;
}
// get basic call control
hr = pCallInfo->QueryInterface (
IID_ITBasicCallControl,
(void **)&pCall
);
if (FAILED(hr))
goto Error;
m_pBridgeCall->SetH323Call (pCall);
Cleanup:
if (pCall)
{
pCall->Release ();
pCall = NULL;
}
if (pCallInfo)
{
pCallInfo->Release ();
pCallInfo = NULL;
}
if (pNotify)
{
pNotify->Release ();
pNotify = NULL;
}
return hr;
Error:
goto Cleanup;
}
/*//////////////////////////////////////////////////////////////////////////////
////*/
BOOL
CBridge::HasH323Call ()
{
return m_pBridgeCall->HasH323Call ();
}
/*//////////////////////////////////////////////////////////////////////////////
iterates through tapi, find an address and create a sdp call
////*/
HRESULT
CBridge::CreateSDPCall ()
{
HRESULT hr;
// create call, ignore bstrDestAddr, hardcode it here
ITBasicCallControl *pCall = NULL;
BSTR bstrFixedDest;
if (glpCmdLine[0] == '\0')
bstrFixedDest = SysAllocString (MySDP);
else
bstrFixedDest = SysAllocString (MySDP2);
hr = m_pSDPAddr->CreateCall (
bstrFixedDest, // bstrDestAddr,
LINEADDRESSTYPE_SDP,
m_lSDPMediaType,
&pCall
);
SysFreeString (bstrFixedDest);
if (FAILED(hr))
return hr;
m_pBridgeCall->SetSDPCall (pCall);
pCall->Release ();
return hr;
}
/*//////////////////////////////////////////////////////////////////////////////
bridges h323 and sdp calls
////*/
HRESULT
CBridge::BridgeCalls ()
{
HRESULT hr;
return m_pBridgeCall->BridgeCalls ();
}
/*//////////////////////////////////////////////////////////////////////////////
returns to same state as just initializing tapi
////*/
void
CBridge::Clear ()
{
m_pBridgeCall->Clear ();
}
/*//////////////////////////////////////////////////////////////////////////////
if the address type is given, find an address based on
address type and media type
else if address name is given, find an address based on
address name and media type
else
return E_FAIL
////*/
HRESULT
CBridge::FindAddress (
long dwAddrType,
BSTR bstrAddrName,
long lMediaType,
ITAddress **ppAddr
)
{
HRESULT hr;
IEnumAddress *pEnumAddr = NULL;
ITAddress *pAddr = NULL;
ITAddressCapabilities *pAddrCaps = NULL;
BOOL fFound = false;
long lTypeFound;
BSTR bstrAddrNameFound = NULL;
// clear output address
if ((*ppAddr))
{
(*ppAddr)->Release ();
(*ppAddr) = NULL;
}
// enumerate the address
hr = m_pTapi->EnumerateAddresses (&pEnumAddr);
if (FAILED(hr))
{
DoMessage (L"Failed to enumerate address");
goto Error;
}
// loop to find the right address
while (!fFound)
{
// next address
if (pAddr)
{
pAddr->Release ();
pAddr = NULL;
}
hr = pEnumAddr->Next (1, &pAddr, NULL);
if (S_OK != hr)
break;
if (dwAddrType != 0)
{
// addr type is valid, ignore addr name
if (pAddrCaps)
{
pAddrCaps->Release ();
pAddrCaps = NULL;
}
hr = pAddr->QueryInterface (
IID_ITAddressCapabilities,
(void **)&pAddrCaps
);
if (FAILED(hr))
{
DoMessage (L"Failed to retrieve address capabilities");
goto Error;
}
// find address type supported
hr = pAddrCaps->get_AddressCapability (AC_ADDRESSTYPES, &lTypeFound);
if (FAILED(hr))
{
DoMessage (L"Failed to get address type");
goto Error;
}
// check if the type we wanted
if (dwAddrType != lTypeFound)
continue;
}
else if (bstrAddrName != NULL)
{
hr = pAddr->get_AddressName (&bstrAddrNameFound);
if (FAILED(hr))
{
DoMessage (L"Failed to get address name");
goto Error;
}
if (wcscmp(bstrAddrName, bstrAddrNameFound) != 0)
continue;
}
else
{
DoMessage (L"Both address type and name are null. Internal error");
hr = E_UNEXPECTED;
goto Error;
}
// now check media type
if (AddressSupportsMediaType (pAddr, lMediaType))
fFound = true;
} // end of while (!fFound)
if (fFound)
{
(*ppAddr) = pAddr;
(*ppAddr)->AddRef ();
}
Cleanup:
if (pAddrCaps)
pAddrCaps->Release ();
if (pAddr)
pAddr->Release ();
if (pEnumAddr)
pEnumAddr->Release ();
return hr;
Error:
goto Cleanup;
}
/*//////////////////////////////////////////////////////////////////////////////
checks if the address supports the media type
////*/
BOOL
CBridge::AddressSupportsMediaType (ITAddress *pAddr, long lMediaType)
{
VARIANT_BOOL vbSupport = VARIANT_FALSE;
ITMediaSupport * pMediaSupport;
if (SUCCEEDED(pAddr->QueryInterface (IID_ITMediaSupport, (void**)&pMediaSupport)))
{
pMediaSupport->QueryMediaType (lMediaType, &vbSupport);
pMediaSupport->Release ();
}
return (vbSupport==VARIANT_TRUE);
}
/*//////////////////////////////////////////////////////////////////////////////
////*/
HRESULT
CBridge::GetSDPAddress (ITAddress **ppAddress)
{
HRESULT hr;
if (*ppAddress)
{
(*ppAddress)->Release ();
*ppAddress = NULL;
}
*ppAddress = m_pSDPAddr;
m_pSDPAddr->AddRef ();
return S_OK;
}