DPClient.cpp
上传用户:weiliangfb
上传日期:2007-01-23
资源大小:142k
文件大小:13k
- // DPClient.cpp: implementation of the CDPClient class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "Cient.h"
- #include "DPClient.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CDPClient::CDPClient(MediaMessageRespEvent * pEvent)
- {
- InitializeCriticalSection(&m_csHostList);
- m_pHostList = NULL;
- m_pDPClient = NULL;
- m_pHostAddress = NULL;
- m_pDeviceAddress =NULL;
- m_MMEvent = pEvent;
- m_bConnected = FALSE;
- }
- CDPClient::~CDPClient()
- {
- CleanupDirectPlay();
- }
- void CDPClient::CleanupDirectPlay()
- {
- CSimpleAutoLock lock(&m_csHostList);
- PHOST_NODE pHostNode = m_pHostList;
- while( pHostNode != NULL )
- {
- if(pHostNode->pHostAddress)
- {
- pHostNode->pHostAddress->Release();
- pHostNode->pHostAddress = NULL;
- }
- if(pHostNode->pAppDesc)
- {
- delete pHostNode->pAppDesc;
- pHostNode->pAppDesc = NULL;
- }
- if(pHostNode->pwszSessionName)
- {
- SysFreeString(pHostNode->pwszSessionName);
- pHostNode->pwszSessionName = NULL;
- }
-
- PHOST_NODE pHostNodetmp = pHostNode;
- pHostNode = pHostNode->pNext;
- if(pHostNodetmp)
- {
- delete pHostNodetmp;
- pHostNodetmp = NULL;
- }
- }
- m_pHostList = NULL;
-
- if( m_pDPClient)
- {
- m_pDPClient->Release();
- m_pDPClient = NULL;
- }
- if(m_pDeviceAddress)
- {
- m_pDeviceAddress->Release();
- m_pDeviceAddress = NULL;
- }
- if(m_pHostAddress)
- {
- m_pHostAddress->Release();
- m_pHostAddress = NULL;
- }
- if(m_pDeviceAddress)
- {
- m_pDeviceAddress->Release();
- m_pDeviceAddress = NULL;
- }
- }
- HRESULT CDPClient::ConnectDirectly()
- {
- if(m_bConnected)
- return E_FAIL;
- EnterCriticalSection(&m_csHostList);
- PHOST_NODE pHostInfoList = m_pHostList;
- LeaveCriticalSection(&m_csHostList);
- if(pHostInfoList)
- {
- HRESULT hr = E_FAIL;
- DPN_APPLICATION_DESC dpnAppDesc;
- IDirectPlay8Address* pHostAddress = NULL;
-
- ZeroMemory(&dpnAppDesc, sizeof(DPN_APPLICATION_DESC));
- dpnAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
- dpnAppDesc.guidApplication = WPGirFriendInstance;
-
- // Simply connect to the first one in the list
- hr =pHostInfoList->pHostAddress->Duplicate(&pHostAddress );
- if(FAILED(hr))
- return hr;
-
- hr = m_pDPClient->Connect(&dpnAppDesc, // pdnAppDesc
- pHostAddress, // pHostAddr
- m_pDeviceAddress, // pDeviceInfo
- NULL, // pdnSecurity
- NULL, // pdnCredentials
- NULL, 0, // pvUserConnectData/Size
- NULL, // pvAsyncContext
- NULL, // pvAsyncHandle
- DPNCONNECT_SYNC); // dwFlags
-
- if(pHostAddress)
- pHostAddress->Release();
- if(FAILED(hr))
- return hr;
- m_bConnected = TRUE;
- return S_OK;
- }
- return E_FAIL;
- }
- HRESULT CDPClient::InitNetEnvironment()
- {
- HRESULT hr = InitDirectPlay();
- if(FAILED(hr))
- return hr;
- hr = CreateDeviceAddress();
- if(FAILED(hr))
- return hr;
- hr = CreateHostAddress();
- if(FAILED(hr))
- return hr;
- hr=EnumDirectPlayHosts();
- return hr;
- }
- HRESULT CDPClient::CreateDeviceAddress()
- {
- HRESULT hr = S_OK;
- // Create our IDirectPlay8Address Device Address
- hr = CoCreateInstance(CLSID_DirectPlay8Address, NULL,
- CLSCTX_INPROC_SERVER,
- IID_IDirectPlay8Address,
- (LPVOID*) &m_pDeviceAddress );
- if( FAILED( hr ) )
- {
- return hr;
- }
-
- // Set the SP for our Device Address
- hr = m_pDeviceAddress->SetSP(&CLSID_DP8SP_TCPIP ) ;
- return hr;
- }
- HRESULT CDPClient::CreateHostAddress()
- {
- HRESULT hr = S_OK;
- if(m_bstrHostName.length()==0)//如果不指定主机名则会枚举出所有的主机地址
- return S_OK;
- // Create our IDirectPlay8Address Host Address
- hr = CoCreateInstance(CLSID_DirectPlay8Address, NULL,
- CLSCTX_INPROC_SERVER,
- IID_IDirectPlay8Address,
- (LPVOID*) &m_pHostAddress );
- if( FAILED( hr ) )
- return hr;
- // Set the SP for our Host Address
- hr = m_pHostAddress->SetSP(&CLSID_DP8SP_TCPIP );
- if( FAILED( hr ) )
- {
- return hr;
- }
- // Set the hostname into the address
- hr = m_pHostAddress->AddComponent(DPNA_KEY_HOSTNAME, (BSTR)m_bstrHostName,
- sizeof(WCHAR)*( m_bstrHostName.length() + 1),
- DPNA_DATATYPE_STRING );
- if(FAILED(hr))
- return hr;
- DPN_PLAYER_INFO dpPlayerInfo;
- ZeroMemory( &dpPlayerInfo, sizeof(DPN_PLAYER_INFO) );
- dpPlayerInfo.dwSize = sizeof(DPN_PLAYER_INFO);
- dpPlayerInfo.dwInfoFlags = DPNINFO_NAME|DPNINFO_DATA;
- dpPlayerInfo.pwszName = L"ClientName";
- return m_pDPClient->SetClientInfo(&dpPlayerInfo,NULL,NULL,DPNSETCLIENTINFO_SYNC );
- }
- HRESULT CDPClient::EnumDirectPlayHosts()
- {
- HRESULT hr = S_OK;
- DPN_APPLICATION_DESC dpAppDesc;
- // Now set up the Application Description
- ZeroMemory(&dpAppDesc, sizeof(DPN_APPLICATION_DESC));
- dpAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
- dpAppDesc.guidApplication = WPGirFriendInstance;
- // We now have the host address so lets enum
- DPNHANDLE hCancelHandle;
- hr = m_pDPClient->EnumHosts(&dpAppDesc, // pApplicationDesc
- m_pHostAddress, // pdpaddrHost
- m_pDeviceAddress, // pdpaddrDeviceInfo
- NULL, 0, // pvUserEnumData, size
- INFINITE , // dwEnumCount
- 0, // dwRetryInterval
- INFINITE , // dwTimeOut
- NULL, // pvUserContext
- &hCancelHandle, // pAsyncHandle
- 0 ) ;// dwFlags
- return hr;
- }
- HRESULT CDPClient::InitDirectPlay()
- {
- HRESULT hr = S_OK;
- // Create the IDirectPlay8Client Object
- hr = CoCreateInstance(CLSID_DirectPlay8Client, NULL,
- CLSCTX_INPROC_SERVER,
- IID_IDirectPlay8Client,
- (LPVOID*) &m_pDPClient ) ;
- if( FAILED(hr) )
- return hr;
- // Init DirectPlay
- hr = m_pDPClient->Initialize(this, Shell_DirectPlayMessageHandler, 0 );
- if( FAILED( hr ) )
- {
- return hr;
- }
-
- // Ensure that TCP/IP is a valid Service Provider
- BOOL bVal = IsServiceProviderValid(m_pDPClient,&CLSID_DP8SP_TCPIP );
- if( FALSE == bVal)
- hr = E_FAIL;
-
- return hr;
- }
- BOOL CDPClient::IsServiceProviderValid(IDirectPlay8Client * lpDPClient,const GUID* pGuidSP)
- {
- HRESULT hr;
- DPN_SERVICE_PROVIDER_INFO* pdnSPInfo = NULL;
- DWORD dwItems = 0;
- DWORD dwSize = 0;
- hr = lpDPClient->EnumServiceProviders(pGuidSP, NULL, NULL, &dwSize, &dwItems, 0);
- if( hr != DPNERR_BUFFERTOOSMALL)
- {
- return hr;
- }
- pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
- hr = lpDPClient->EnumServiceProviders(pGuidSP, NULL, pdnSPInfo, &dwSize, &dwItems, 0 ) ;
- if( FAILED( hr) )
- {
- delete [](LPBYTE) pdnSPInfo;
- return hr;
- }
- // There are no items returned so the requested SP is not available
- if( dwItems == 0)
- {
- hr = E_FAIL;
- }
- delete [](LPBYTE)pdnSPInfo;
- if( SUCCEEDED(hr) )
- return TRUE;
- else
- return FALSE;
- }
- HRESULT CDPClient::Shell_DirectPlayMessageHandler(PVOID pvUserContext, DWORD dwMessageType, PVOID pMessage)
- {
- CDPClient * pThis = (CDPClient*)pvUserContext;
- if(pThis)
- return pThis->Inner_DirectPlayMessageHandler(dwMessageType,pMessage);
- return E_FAIL;
- }
- HRESULT CDPClient::Inner_DirectPlayMessageHandler(DWORD dwMessageType, PVOID pMessage)
- {
- switch(dwMessageType)
- {
- //DirectPlayClient必须处理的消息
- case DPN_MSGID_RECEIVE:
- {
- PDPNMSG_RECEIVE pReceivBuf = (PDPNMSG_RECEIVE)pMessage;
- PumpVBMessage(pReceivBuf);
- }
- return S_OK;
- case DPN_MSGID_TERMINATE_SESSION:
- m_bConnected = FALSE;
- break;
- case DPN_MSGID_RETURN_BUFFER:
- break;
- //DirectPlayClient可选消息
- case DPN_MSGID_ENUM_HOSTS_RESPONSE://枚举主机响应消息
- {
- DPNMSG_ENUM_HOSTS_RESPONSE * pEnumHostResp = (DPNMSG_ENUM_HOSTS_RESPONSE*)pMessage;
- EnumHostRespMessageHandler(pEnumHostResp);
- return S_OK;
- }
- break;
- case DPN_MSGID_ASYNC_OP_COMPLETE:
- break;
- case DPN_MSGID_CLIENT_INFO:
- break;
- case DPN_MSGID_CONNECT_COMPLETE:
- break;
- case DPN_MSGID_SEND_COMPLETE:
- break;
- case DPN_MSGID_SERVER_INFO:
- break;
- }
- return S_OK;//DPN_OK
- }
- PHOST_NODE CDPClient::FindInstanceGuid(const GUID &newInstanceGUID)
- {
- PHOST_NODE HostHeader = m_pHostList;
- while(HostHeader)
- {
- if(IsEqualGUID(HostHeader->pAppDesc->guidInstance ,newInstanceGUID))
- return HostHeader;
- HostHeader = HostHeader->pNext;
- }
- return NULL;
- }
- HRESULT CDPClient::EnumHostRespMessageHandler(DPNMSG_ENUM_HOSTS_RESPONSE *pEnumHostResp)
- {
- if(pEnumHostResp==NULL)
- return S_OK;
- //获得会话名与实例GUID
- CSimpleAutoLock lock(&m_csHostList);
- PHOST_NODE pHostInfoList = FindInstanceGuid(pEnumHostResp->pApplicationDescription->guidInstance);
- if(pHostInfoList)
- {
- return S_OK;
- }
-
- const DPN_APPLICATION_DESC* pAppDesc;
- HOST_NODE* pHostNode = NULL;
- WCHAR* pwszSession = NULL;
-
- pAppDesc = pEnumHostResp->pApplicationDescription;
-
- // Insert each host response if it isn't already present
-
-
- // This host session is not in the list then so insert it.
- pHostNode = new HOST_NODE;
- if( pHostNode == NULL)
- {
- return S_OK;
- }
-
- ZeroMemory(pHostNode, sizeof(HOST_NODE));
-
- // Copy the Host Address
- HRESULT hr = pEnumHostResp->pAddressSender->Duplicate(&pHostNode->pHostAddress ) ;
- if( FAILED(hr) )
- {
- delete pHostNode;
- return S_OK;
- }
-
- pHostNode->pAppDesc = new DPN_APPLICATION_DESC;
-
- if(pHostNode->pAppDesc==NULL)
- {
- pHostNode->pHostAddress->Release();
- delete pHostNode;
- return S_OK;
- }
- ZeroMemory(pHostNode->pAppDesc, sizeof(DPN_APPLICATION_DESC));
- memcpy(pHostNode->pAppDesc, pAppDesc, sizeof(DPN_APPLICATION_DESC));
-
- // Null out all the pointers we aren't copying
- pHostNode->pAppDesc->pwszSessionName = NULL;
- pHostNode->pAppDesc->pwszPassword = NULL;
- pHostNode->pAppDesc->pvReservedData = NULL;
- pHostNode->pAppDesc->dwReservedDataSize = 0;
- pHostNode->pAppDesc->pvApplicationReservedData = NULL;
- pHostNode->pAppDesc->dwApplicationReservedDataSize = 0;
-
- if( pAppDesc->pwszSessionName)
- pwszSession = SysAllocString(pAppDesc->pwszSessionName);
-
- pHostNode->pwszSessionName = pwszSession;
-
- // 将此结点插入到链表的前头
- pHostNode->pNext = m_pHostList;
- if(m_pHostList)
- pHostNode->HostIndex = m_pHostList->HostIndex +1;
- else
- pHostNode->HostIndex = 0;
-
- m_pHostList = pHostNode;
- return S_OK;
- }
- HRESULT CDPClient::PumpVBMessage(PDPNMSG_RECEIVE pReceiveMessage)
- {
- PMEDIAMSG pNetMessage = (PMEDIAMSG)pReceiveMessage->pReceiveData;
- if(pReceiveMessage->dwReceiveDataSize ==0)
- return DPN_OK;
- if(pNetMessage->mmsgType==mmsg_DataRespons)
- {
- PMEDIADATAPARAM param = (PMEDIADATAPARAM)pNetMessage->lpParamBuffer;
- m_MMEvent->OnDataArrive(param->llDataPos,param->dwDataSize,param->lpDataBuff);
- }
- else if(pNetMessage->mmsgType==mmsg_MediaInfoRespons)
- {
- LONGLONG llLength = *((LONGLONG*)pNetMessage->lpParamBuffer);
- m_MMEvent->OnLenghtArrive(llLength);
- }
- else
- {
- ASSERT(0);
- }
- return S_OK;
- }
- void CDPClient::SendBuffer(LPBYTE lpBuffer,DWORD dwSize)
- {
- DPN_BUFFER_DESC dpbuf;
- dpbuf.dwBufferSize =dwSize ;
- dpbuf.pBufferData = lpBuffer;
- DPNHANDLE hCancelHandle;
- m_pDPClient->Send(&dpbuf,1,
- 1000,
- NULL,&hCancelHandle,DPNSEND_NOCOMPLETE );
- }
- void CDPClient::SendMediaLenRequire()
- {
- MEDIAMSG mediaLenReq;
- mediaLenReq.mmsgType = mmsg_MediaInfoRequire;
- mediaLenReq.dwBufferLen = 0;
- SendBuffer((LPBYTE)&mediaLenReq,sizeof(MEDIAMSG));
- }
- void CDPClient::SendMediaDataRequire(LONGLONG llPos,DWORD dwSize)
- {
- BYTE bytReqBuf[sizeof(MEDIADATAPARAM)+sizeof(MEDIAMSG)];
- PMEDIAMSG preqParam = (PMEDIAMSG)bytReqBuf;
- preqParam->mmsgType = mmsg_DataRequire;
- preqParam->dwBufferLen = sizeof(MEDIADATAPARAM);
- PMEDIADATAPARAM param = (PMEDIADATAPARAM)preqParam->lpParamBuffer;
- param->llDataPos = llPos;
- param->dwDataSize = dwSize;
- SendBuffer(bytReqBuf,sizeof(MEDIADATAPARAM)+sizeof(MEDIAMSG));
- }