📄 connectionmanagerservice.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "av_upnp.h"
using namespace av_upnp;
/////////////////////////////////////////////////////////////////////////////
// ConnectionManagerServiceImpl
ConnectionManagerServiceImpl::ConnectionManagerServiceImpl()
: m_pIConnectionManager(NULL), m_pAVTS(NULL), m_pRCS(NULL)
{
InitErrDescrips();
InitToolkitErrs();
InitDISPIDs();
}
ConnectionManagerServiceImpl::~ConnectionManagerServiceImpl()
{
if(m_pIConnectionManager)
const DWORD retUnadvise = m_pIConnectionManager->Unadvise(this);
// if Unadvise() fails, we can do nothing but ignore.
}
DWORD ConnectionManagerServiceImpl::Init(/* [in] */ IConnectionManager* pIConnectionManager,
/* [in] */ AVTransportServiceImpl* pAVTransportService,
/* [in] */ RenderingControlServiceImpl* pRenderingControlService)
{
if(m_pIConnectionManager || m_pAVTS || m_pRCS)
return ERROR_AV_ALREADY_INITED;
if(!pIConnectionManager)
return ERROR_AV_POINTER; // this class requires m_pIConnectionManager in all cases
m_pIConnectionManager = pIConnectionManager;
m_pAVTS = pAVTransportService;
m_pRCS = pRenderingControlService;
const DWORD retAdvise = m_pIConnectionManager->Advise(this);
if(SUCCESS_AV != retAdvise)
return retAdvise;
return SUCCESS_AV;
}
//
// IUPnPEventSource
//
STDMETHODIMP ConnectionManagerServiceImpl::Advise(/*[in]*/ IUPnPEventSink* punkSubscriber)
{
if(!punkSubscriber)
return E_POINTER;
return punkSubscriber->QueryInterface(IID_IUPnPEventSink, reinterpret_cast<void**>(&m_punkSubscriber));
}
STDMETHODIMP ConnectionManagerServiceImpl::Unadvise(/*[in]*/ IUPnPEventSink* punkSubscriber)
{
if(m_punkSubscriber)
m_punkSubscriber.Release();
return S_OK;
}
//
// IUPnPService_ConnectionManager1
//
STDMETHODIMP ConnectionManagerServiceImpl::get_SourceProtocolInfo(BSTR* pSourceProtocolInfo)
{
if(!pSourceProtocolInfo)
return E_POINTER;
const HRESULT hr = generic_get_ProtocolInfo(pSourceProtocolInfo, NULL);
if(FAILED(hr))
return hr; // generic_get_ProtocolInfo does error work, so we do not.
return S_OK;
}
STDMETHODIMP ConnectionManagerServiceImpl::get_SinkProtocolInfo(BSTR* pSinkProtocolInfo)
{
if(!pSinkProtocolInfo)
return E_POINTER;
const HRESULT hr = generic_get_ProtocolInfo(NULL, pSinkProtocolInfo);
if(FAILED(hr))
return hr; // generic_get_ProtocolInfo does error work, so we do not.
return S_OK;
}
STDMETHODIMP ConnectionManagerServiceImpl::get_CurrentConnectionIDs(BSTR* pCurrentConnectionIDs)
{
if(!pCurrentConnectionIDs)
return E_POINTER;
if(!m_pIConnectionManager)
return m_ErrReport.ReportError(ERROR_AV_UPNP_ACTION_FAILED);
wstring strConnectionIDs;
wstring strCurConnectionID;
const int nltowLimit = 33;
const int radixTen = 10;
long nCurConnectionID;
strCurConnectionID.reserve(nltowLimit);
if(SUCCESS_AV == m_pIConnectionManager->GetFirstConnectionID(&nCurConnectionID))
{
_ltow(nCurConnectionID, strCurConnectionID.get_buffer(), radixTen);
if(!strConnectionIDs.append(strCurConnectionID))
return m_ErrReport.ReportError(ERROR_AV_OOM);
while(SUCCESS_AV == m_pIConnectionManager->GetNextConnectionID(&nCurConnectionID))
{
_itow(nCurConnectionID, strCurConnectionID.get_buffer(), radixTen);
if(!strConnectionIDs.append(AVDCPListDelimiter))
return m_ErrReport.ReportError(ERROR_AV_OOM);
if(!strConnectionIDs.append(strCurConnectionID))
return m_ErrReport.ReportError(ERROR_AV_OOM);
}
}
else
{
// no connections, empty string
}
// Set out argument
*pCurrentConnectionIDs = SysAllocString(strConnectionIDs);
if(!*pCurrentConnectionIDs)
return m_ErrReport.ReportError(ERROR_AV_OOM);
return S_OK;
}
// get_A_ARG_TYPE_foo() methods are implemented only to satisfy upnp's devicehost, they are not used
STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_ConnectionStatus(BSTR* pA_ARG_TYPE_ConnectionStatus)
{
return S_OK;
}
STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_ConnectionManager(BSTR* pA_ARG_TYPE_ConnectionManager)
{
return S_OK;
}
STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_Direction(BSTR* pA_ARG_TYPE_Direction)
{
return S_OK;
}
STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_ProtocolInfo(BSTR* pA_ARG_TYPE_ProtocolInfo)
{
return S_OK;
}
STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_ConnectionID(long* pA_ARG_TYPE_ConnectionID)
{
return S_OK;
}
STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_AVTransportID(long* pA_ARG_TYPE_AVTransportID)
{
return S_OK;
}
STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_RcsID(long* pA_ARG_TYPE_RcsID)
{
return S_OK;
}
STDMETHODIMP ConnectionManagerServiceImpl::GetProtocolInfo(BSTR* pSource,
BSTR* pSink)
{
if(!pSource || !pSink)
return E_POINTER;
return generic_get_ProtocolInfo(pSource, pSink); // generic_get_ProtocolInfo does error work, so we do not.
}
void ReleaseVirtualService(IVirtualService* pService)
{
pService->Release();
}
STDMETHODIMP ConnectionManagerServiceImpl::PrepareForConnection(BSTR RemoteProtocolInfo,
BSTR PeerConnectionManager,
long PeerConnectionID,
BSTR Direction,
long* pConnectionID,
long* pAVTransportID,
long* pRcsID)
{
if(!pConnectionID || !pAVTransportID || !pRcsID)
return E_POINTER;
if(!m_pIConnectionManager)
return m_ErrReport.ReportError(ERROR_AV_UPNP_ACTION_FAILED);
// Setup arguments for call to IConnectionManager
DIRECTION direction;
wstring strDirection;
wstring strRemoteProtocolInfo, strPeerConnectionManager;
if(!strRemoteProtocolInfo.assign(RemoteProtocolInfo, SysStringLen(RemoteProtocolInfo)))
return m_ErrReport.ReportError(ERROR_AV_OOM);
if(!strPeerConnectionManager.assign(PeerConnectionManager, SysStringLen(PeerConnectionManager)))
return m_ErrReport.ReportError(ERROR_AV_OOM);
if(!strDirection.assign(Direction, SysStringLen(Direction)))
return m_ErrReport.ReportError(ERROR_AV_OOM);
if(details::Direction::Input == strDirection)
direction = INPUT;
else if(details::Direction::Output == strDirection)
direction = OUTPUT;
else
return m_ErrReport.ReportError(ERROR_AV_UPNP_CM_INCOMPATIBLE_DIRECTION);
// using smart pointers for virtual services to make sure they are release in case of any failure
typedef ce::auto_xxx<IAVTransport*, void (*)(IVirtualService*), ReleaseVirtualService, NULL> auto_av_transport_ptr;
typedef ce::auto_xxx<IRenderingControl*, void (*)(IVirtualService*), ReleaseVirtualService, NULL> auto_rendering_control_ptr;
auto_av_transport_ptr pIAVTransport;
auto_rendering_control_ptr pIRenderingControl;
// Make the call
const DWORD retPFC = m_pIConnectionManager->PrepareForConnection(strRemoteProtocolInfo,
strPeerConnectionManager,
PeerConnectionID,
direction,
pConnectionID,
&pIAVTransport,
&pIRenderingControl);
if(retPFC != SUCCESS_AV)
return m_ErrReport.ReportError(retPFC);
// add entry to the map of virtual instance ids
IDMap::iterator itIDs = m_mapIDs.insert(*pConnectionID, InstanceIDs());
if(m_mapIDs.end() != itIDs)
{
// set ids to -1 until the services are successfully registered
itIDs->second.AVTID = *pAVTransportID = -1;
itIDs->second.RCID = *pRcsID = -1;
}
else
{
// cleanup after the incomplete connection
ConnectionComplete(*pConnectionID);
return m_ErrReport.ReportError(ERROR_AV_OOM);
}
// register virtual instance of AVTransport
if(pIAVTransport)
{
if(!m_pAVTS)
{
DEBUGMSG(ZONE_AV_ERROR, (TEXT("IConnectionManager::PrepareForConnection or CreateConnection returned non-NULL pIAVTransport but")));
DEBUGMSG(ZONE_AV_ERROR, (TEXT("\tConnectionManagerServiceImpl::Init was called with NULL for pAVTransportService")));
}
else
{
const DWORD retRI = m_pAVTS->RegisterInstance(pIAVTransport, pAVTransportID);
if(SUCCESS_AV != retRI)
{
// cleanup after the incomplete connection
ConnectionComplete(*pConnectionID);
return m_ErrReport.ReportError(retRI);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -