📄 iconnectionmanagerimpl.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;
/////////////////////////////////////////////////////////////////////////////
// Non-member internal functions
//
// These functions could be static const private member functions, but since they don't depend on data members of
// IConnectionManagerImpl they are made non-members to simplify this class's declaration.
namespace av_upnp {
namespace details {
typedef ce::hash_set<wstring> ProtocolInfoSet;
DWORD generic_AddProtocol( LPCWSTR pszProtocolInfo, ProtocolInfoSet* pProtocolInfoSet);
DWORD generic_RemoveProtocol(LPCWSTR pszProtocolInfo, ProtocolInfoSet* pProtocolInfoSet);
DWORD generic_get_ProtocolInfo(wstring* pstrProtocolInfo, const ProtocolInfoSet &protocolInfoSet);
}
}
/////////////////////////////////////////////////////////////////////////////
// IConnectionManagerImpl
IConnectionManagerImpl::IConnectionManagerImpl()
: m_nLastCreatedConnectionID(-1),
m_pSubscriber(NULL)
{
}
IConnectionManagerImpl::~IConnectionManagerImpl()
{
assert(m_pSubscriber == NULL);
}
//
// IEventSource
//
DWORD IConnectionManagerImpl::Advise(/*[in]*/ av::IEventSink *pSubscriber)
{
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
m_pSubscriber = pSubscriber;
return av::SUCCESS_AV;
}
DWORD IConnectionManagerImpl::Unadvise(/*[in]*/ av::IEventSink *pSubscriber)
{
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
m_pSubscriber = NULL;
return av::SUCCESS_AV;
}
DWORD IConnectionManagerImpl::AddSinkProtocol(LPCWSTR pszProtocolInfo)
{
if(!pszProtocolInfo)
return ERROR_AV_POINTER;
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
const DWORD retAdd = details::generic_AddProtocol(pszProtocolInfo, &m_setSinkProtocols);
if(SUCCESS_AV != retAdd)
return retAdd;
if(m_pSubscriber)
if(SUCCESS_AV != m_pSubscriber->OnStateChanged(ConnectionManagerState::SinkProtocolInfo, static_cast<LPCWSTR>(NULL)))
{
DEBUGMSG(ZONE_AV_ERROR, (AV_TEXT("OnStateChanged failed!")));
}
return SUCCESS_AV;
}
DWORD IConnectionManagerImpl::RemoveSinkProtocol(LPCWSTR pszProtocolInfo)
{
if(!pszProtocolInfo)
return ERROR_AV_POINTER;
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
const DWORD retRem = details::generic_RemoveProtocol(pszProtocolInfo, &m_setSinkProtocols);
if(SUCCESS_AV != retRem)
return retRem;
if(m_pSubscriber)
if(SUCCESS_AV != m_pSubscriber->OnStateChanged(ConnectionManagerState::SinkProtocolInfo, static_cast<LPCWSTR>(NULL)))
{
DEBUGMSG(ZONE_AV_ERROR, (AV_TEXT("OnStateChanged failed!")));
}
return SUCCESS_AV;
}
DWORD IConnectionManagerImpl::AddSourceProtocol(LPCWSTR pszProtocolInfo)
{
if(!pszProtocolInfo)
return ERROR_AV_POINTER;
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
const DWORD retAdd = details::generic_AddProtocol(pszProtocolInfo, &m_setSourceProtocols);
if(SUCCESS_AV != retAdd)
return retAdd;
if(m_pSubscriber)
if(SUCCESS_AV != m_pSubscriber->OnStateChanged(ConnectionManagerState::SourceProtocolInfo, static_cast<LPCWSTR>(NULL)))
{
DEBUGMSG(ZONE_AV_ERROR, (AV_TEXT("OnStateChanged failed!")));
}
return SUCCESS_AV;
}
DWORD IConnectionManagerImpl::RemoveSourceProtocol(LPCWSTR pszProtocolInfo)
{
if(!pszProtocolInfo)
return ERROR_AV_POINTER;
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
const DWORD retRem = details::generic_RemoveProtocol(pszProtocolInfo, &m_setSourceProtocols);
if(SUCCESS_AV != retRem)
return retRem;
if(m_pSubscriber)
if(SUCCESS_AV != m_pSubscriber->OnStateChanged(ConnectionManagerState::SourceProtocolInfo, static_cast<LPCWSTR>(NULL)))
{
DEBUGMSG(ZONE_AV_ERROR, (AV_TEXT("OnStateChanged failed!")));
}
return SUCCESS_AV;
}
//
// IConnectionManager
//
DWORD IConnectionManagerImpl::PrepareForConnection(
/* [in] */ LPCWSTR pszRemoteProtocolInfo,
/* [in] */ LPCWSTR pszPeerConnectionManager,
/* [in] */ long PeerConnectionID,
/* [in] */ DIRECTION Direction,
/* [in, out] */ long* pConnectionID,
/* [in, out] */ IAVTransport** ppAVTransport,
/* [in, out] */ IRenderingControl** ppRenderingControl)
{
if(!pszRemoteProtocolInfo || !pszPeerConnectionManager || !pConnectionID || !ppAVTransport || !ppRenderingControl)
return ERROR_AV_POINTER;
const DWORD retCUCID = CreateUniqueConnectionID(pConnectionID);
if(SUCCESS_AV != retCUCID)
return retCUCID;
*ppAVTransport = NULL;
*ppRenderingControl = NULL;
//
// Call customization point
//
const DWORD retCC = CreateConnection(pszRemoteProtocolInfo,
Direction,
*pConnectionID,
ppAVTransport,
ppRenderingControl);
if(SUCCESS_AV != retCC)
return retCC;
ConnectionInfo connection;
connection.pRenderingControl = *ppRenderingControl;
connection.pAVTransport = *ppAVTransport;
connection.Direction = Direction;
connection.nPeerConnectionID = PeerConnectionID;
connection.strPeerConnectionManager = pszPeerConnectionManager;
connection.strRemoteProtocolInfo = pszRemoteProtocolInfo;
connection.strStatus = L"Unknown";
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
if(m_mapConnections.end() == m_mapConnections.insert(*pConnectionID, connection))
return ERROR_AV_OOM;
if(m_pSubscriber)
if(SUCCESS_AV != m_pSubscriber->OnStateChanged(ConnectionManagerState::CurrentConnectionIDs, static_cast<LPCWSTR>(NULL)))
{
DEBUGMSG(ZONE_AV_ERROR, (AV_TEXT("OnStateChanged failed!")));
}
m_nLastCreatedConnectionID = *pConnectionID;
return SUCCESS_AV;
}
DWORD IConnectionManagerImpl::ConnectionComplete(
/* [in] */ long ConnectionID)
{
// Call customization point
const DWORD retEC = EndConnection(ConnectionID);
if(SUCCESS_AV != retEC)
return retEC;
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
m_mapConnections.erase(ConnectionID);
if(m_pSubscriber)
if(SUCCESS_AV != m_pSubscriber->OnStateChanged(ConnectionManagerState::CurrentConnectionIDs, static_cast<LPCWSTR>(NULL)))
{
DEBUGMSG(ZONE_AV_ERROR, (AV_TEXT("OnStateChanged failed!")));
}
return SUCCESS_AV;
}
DWORD IConnectionManagerImpl::GetFirstConnectionID(
/* [in, out] */ long* pConnectionID)
{
if(!pConnectionID)
return ERROR_AV_POINTER;
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
m_itLastAskedForConnection = m_mapConnections.begin();
if(m_itLastAskedForConnection == m_mapConnections.end())
return ERROR_AV_UPNP_CM_INVALID_CONNECTION_REFERENCE; // no connections
*pConnectionID = m_itLastAskedForConnection->first;
return SUCCESS_AV;
}
DWORD IConnectionManagerImpl::GetNextConnectionID(
/* [in, out] */ long* pConnectionID)
{
if(!pConnectionID)
return ERROR_AV_POINTER;
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
m_itLastAskedForConnection++;
if(m_itLastAskedForConnection == m_mapConnections.end())
return ERROR_AV_UPNP_CM_INVALID_CONNECTION_REFERENCE; // no remaining connections
*pConnectionID = m_itLastAskedForConnection->first;
return SUCCESS_AV;
}
DWORD IConnectionManagerImpl::GetProtocolInfo(
/* [in, out] */ wstring* pstrSourceProtocolInfo,
/* [in, out] */ wstring* pstrSinkProtocolInfo)
{
if(!pstrSourceProtocolInfo || !pstrSinkProtocolInfo)
return ERROR_AV_POINTER;
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
DWORD ret;
ret = details::generic_get_ProtocolInfo(pstrSourceProtocolInfo, m_setSourceProtocols);
if(SUCCESS_AV != ret)
return ret;
ret = details::generic_get_ProtocolInfo(pstrSinkProtocolInfo, m_setSinkProtocols);
if(SUCCESS_AV != ret)
return ret;
return SUCCESS_AV;
}
DWORD IConnectionManagerImpl::GetCurrentConnectionInfo(
/* [in] */ long ConnectionID,
/* [in, out] */ ConnectionInfo* pConnectionInfo)
{
if(!pConnectionInfo)
return ERROR_AV_POINTER;
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
const ConnInfoMap::const_iterator it = m_mapConnections.find(ConnectionID);
if(it == m_mapConnections.end())
return ERROR_AV_UPNP_CM_INVALID_CONNECTION_REFERENCE;
*pConnectionInfo = it->second;
return SUCCESS_AV;
}
// InvokeVendorAction
DWORD IConnectionManagerImpl::InvokeVendorAction(
/* [in] */ LPCWSTR pszActionName,
/* [in] */ DISPPARAMS* pdispparams,
/* [in, out] */ VARIANT* pvarResult)
{
return ERROR_AV_UPNP_INVALID_ACTION;
}
//
// Private
//
DWORD IConnectionManagerImpl::CreateUniqueConnectionID(long* pNewConnectionID)
{
if(!pNewConnectionID)
return ERROR_AV_POINTER;
ce::gate<ce::critical_section> csDataMembersLock(m_csDataMembers);
const long firstID = m_nLastCreatedConnectionID; // used to detect if we've stepped through all connection ids
*pNewConnectionID = firstID;
do {
if(*pNewConnectionID >= 0)
++(*pNewConnectionID);
else // ConnectionIDs can not be negative, skip over all negative numbers
*pNewConnectionID = 0;
} while (m_mapConnections.end() != m_mapConnections.find(*pNewConnectionID)
&& firstID != *pNewConnectionID);
if(firstID == *pNewConnectionID)
return ERROR_AV_UPNP_CM_LOCAL_RESTRICTIONS; // all connection ids in use
else
return SUCCESS_AV;
}
//
// Non-member internal functions
//
namespace av_upnp {
namespace details {
DWORD details::generic_AddProtocol(LPCWSTR pszProtocolInfo, ProtocolInfoSet* pProtocolInfoSet)
{
if(!pszProtocolInfo || !pProtocolInfoSet)
return ERROR_AV_POINTER;
wstring strProtocolInfo(pszProtocolInfo);
if(FAILED(EscapeAVDCPListDelimiters(&strProtocolInfo)))
return ERROR_AV_OOM;
if(pProtocolInfoSet->end() == pProtocolInfoSet->insert(strProtocolInfo))
return ERROR_AV_OOM;
return SUCCESS_AV;
}
DWORD details::generic_RemoveProtocol(LPCWSTR pszProtocolInfo, ProtocolInfoSet* pProtocolInfoSet)
{
if(!pszProtocolInfo || !pProtocolInfoSet)
return ERROR_AV_POINTER;
wstring strProtocolInfo(pszProtocolInfo);
if(FAILED(EscapeAVDCPListDelimiters(&strProtocolInfo)))
return ERROR_AV_OOM;
pProtocolInfoSet->erase(strProtocolInfo);
return SUCCESS_AV;
}
DWORD details::generic_get_ProtocolInfo(wstring* pstrProtocolInfo, const ProtocolInfoSet &protocolInfoSet)
{
if(!pstrProtocolInfo)
return ERROR_AV_POINTER;
// Build AV DCP list of protocols
bool firstItem = true;
const ProtocolInfoSet::const_iterator itEnd = protocolInfoSet.end();
for(ProtocolInfoSet::const_iterator it = protocolInfoSet.begin(); it != itEnd; ++it)
{
if(!firstItem)
{
if(!pstrProtocolInfo->append(AVDCPListDelimiter))
return ERROR_AV_OOM;
}
else
{
firstItem = false;
}
if(!pstrProtocolInfo->append(*it))
return ERROR_AV_OOM;
}
return SUCCESS_AV;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -