DPClient.cpp
上传用户:weiliangfb
上传日期:2007-01-23
资源大小:142k
文件大小:13k
源码类别:

多媒体

开发平台:

Visual C++

  1. // DPClient.cpp: implementation of the CDPClient class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "Cient.h"
  6. #include "DPClient.h"
  7. #ifdef _DEBUG
  8. #undef THIS_FILE
  9. static char THIS_FILE[]=__FILE__;
  10. #define new DEBUG_NEW
  11. #endif
  12. //////////////////////////////////////////////////////////////////////
  13. // Construction/Destruction
  14. //////////////////////////////////////////////////////////////////////
  15. CDPClient::CDPClient(MediaMessageRespEvent * pEvent)
  16. {
  17. InitializeCriticalSection(&m_csHostList);
  18. m_pHostList = NULL;
  19. m_pDPClient = NULL;
  20. m_pHostAddress = NULL;
  21. m_pDeviceAddress =NULL;
  22. m_MMEvent = pEvent;
  23. m_bConnected = FALSE;
  24. }
  25. CDPClient::~CDPClient()
  26. {
  27. CleanupDirectPlay();
  28. }
  29. void CDPClient::CleanupDirectPlay()
  30. {
  31. CSimpleAutoLock lock(&m_csHostList);
  32. PHOST_NODE pHostNode = m_pHostList;
  33. while( pHostNode != NULL )
  34. {       
  35. if(pHostNode->pHostAddress)
  36. {
  37. pHostNode->pHostAddress->Release();
  38. pHostNode->pHostAddress = NULL;
  39. }
  40. if(pHostNode->pAppDesc)
  41. {
  42. delete pHostNode->pAppDesc;
  43. pHostNode->pAppDesc = NULL;
  44. }
  45. if(pHostNode->pwszSessionName)
  46. {
  47. SysFreeString(pHostNode->pwszSessionName);
  48. pHostNode->pwszSessionName = NULL;
  49. }
  50. PHOST_NODE pHostNodetmp = pHostNode;
  51. pHostNode    = pHostNode->pNext;
  52. if(pHostNodetmp)
  53. {
  54. delete pHostNodetmp;
  55. pHostNodetmp = NULL;
  56. }
  57. }
  58. m_pHostList = NULL;
  59. if( m_pDPClient)
  60. {
  61. m_pDPClient->Release();
  62. m_pDPClient = NULL;
  63. }
  64. if(m_pDeviceAddress)
  65. {
  66. m_pDeviceAddress->Release();
  67. m_pDeviceAddress = NULL;
  68. }
  69. if(m_pHostAddress)
  70. {
  71. m_pHostAddress->Release();
  72. m_pHostAddress = NULL;
  73. }
  74. if(m_pDeviceAddress)
  75. {
  76. m_pDeviceAddress->Release();
  77. m_pDeviceAddress = NULL;
  78. }
  79. }
  80. HRESULT CDPClient::ConnectDirectly()
  81. {
  82. if(m_bConnected)
  83. return E_FAIL;
  84. EnterCriticalSection(&m_csHostList);
  85. PHOST_NODE pHostInfoList = m_pHostList;
  86. LeaveCriticalSection(&m_csHostList);
  87. if(pHostInfoList)
  88. {
  89. HRESULT                     hr = E_FAIL;
  90. DPN_APPLICATION_DESC        dpnAppDesc;
  91. IDirectPlay8Address*        pHostAddress = NULL;
  92. ZeroMemory(&dpnAppDesc, sizeof(DPN_APPLICATION_DESC));
  93. dpnAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  94. dpnAppDesc.guidApplication = WPGirFriendInstance;
  95. // Simply connect to the first one in the list
  96. hr =pHostInfoList->pHostAddress->Duplicate(&pHostAddress );
  97. if(FAILED(hr))
  98. return hr;
  99. hr = m_pDPClient->Connect(&dpnAppDesc,  // pdnAppDesc
  100. pHostAddress,       // pHostAddr
  101. m_pDeviceAddress,   // pDeviceInfo
  102. NULL,               // pdnSecurity
  103. NULL,               // pdnCredentials
  104. NULL, 0,            // pvUserConnectData/Size
  105. NULL,               // pvAsyncContext
  106. NULL,               // pvAsyncHandle
  107. DPNCONNECT_SYNC);   // dwFlags
  108. if(pHostAddress)
  109. pHostAddress->Release();
  110. if(FAILED(hr))
  111. return hr;
  112. m_bConnected = TRUE;
  113. return S_OK;
  114. }
  115. return E_FAIL;
  116. }
  117. HRESULT CDPClient::InitNetEnvironment()
  118. {
  119. HRESULT hr = InitDirectPlay();
  120. if(FAILED(hr))
  121. return hr;
  122. hr = CreateDeviceAddress();
  123. if(FAILED(hr))
  124. return hr;
  125. hr = CreateHostAddress();
  126. if(FAILED(hr))
  127. return hr;
  128. hr=EnumDirectPlayHosts();
  129. return hr;
  130. }
  131. HRESULT CDPClient::CreateDeviceAddress()
  132. {
  133.     HRESULT         hr = S_OK;
  134.     // Create our IDirectPlay8Address Device Address
  135. hr = CoCreateInstance(CLSID_DirectPlay8Address, NULL,
  136.                                     CLSCTX_INPROC_SERVER,
  137.                                     IID_IDirectPlay8Address,
  138.                                     (LPVOID*) &m_pDeviceAddress );
  139.     if( FAILED( hr ) )
  140.     {
  141. return hr;
  142.     }
  143.     
  144.     // Set the SP for our Device Address
  145. hr = m_pDeviceAddress->SetSP(&CLSID_DP8SP_TCPIP ) ;
  146.     return hr;
  147. }
  148. HRESULT CDPClient::CreateHostAddress()
  149. {
  150.     HRESULT         hr = S_OK;
  151. if(m_bstrHostName.length()==0)//如果不指定主机名则会枚举出所有的主机地址
  152. return S_OK;
  153.     // Create our IDirectPlay8Address Host Address
  154. hr = CoCreateInstance(CLSID_DirectPlay8Address, NULL,
  155.                                     CLSCTX_INPROC_SERVER,
  156.                                     IID_IDirectPlay8Address,
  157.                                     (LPVOID*) &m_pHostAddress );
  158.     if( FAILED( hr  ) )
  159. return hr;
  160.     // Set the SP for our Host Address
  161. hr = m_pHostAddress->SetSP(&CLSID_DP8SP_TCPIP );
  162.     if( FAILED( hr ) )
  163.     {
  164. return hr;
  165.     }
  166.     // Set the hostname into the address
  167. hr  = m_pHostAddress->AddComponent(DPNA_KEY_HOSTNAME, (BSTR)m_bstrHostName,
  168.                                                     sizeof(WCHAR)*( m_bstrHostName.length() + 1), 
  169.                                                     DPNA_DATATYPE_STRING );
  170. if(FAILED(hr))
  171. return hr;
  172. DPN_PLAYER_INFO dpPlayerInfo;
  173. ZeroMemory( &dpPlayerInfo, sizeof(DPN_PLAYER_INFO) );
  174. dpPlayerInfo.dwSize = sizeof(DPN_PLAYER_INFO);
  175. dpPlayerInfo.dwInfoFlags = DPNINFO_NAME|DPNINFO_DATA;
  176. dpPlayerInfo.pwszName = L"ClientName";
  177. return m_pDPClient->SetClientInfo(&dpPlayerInfo,NULL,NULL,DPNSETCLIENTINFO_SYNC );
  178. }
  179. HRESULT CDPClient::EnumDirectPlayHosts()
  180. {
  181.     HRESULT                 hr = S_OK;
  182.     DPN_APPLICATION_DESC    dpAppDesc;
  183.     // Now set up the Application Description
  184.     ZeroMemory(&dpAppDesc, sizeof(DPN_APPLICATION_DESC));
  185.     dpAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  186.     dpAppDesc.guidApplication = WPGirFriendInstance;
  187.     // We now have the host address so lets enum
  188. DPNHANDLE  hCancelHandle;
  189. hr = m_pDPClient->EnumHosts(&dpAppDesc,          // pApplicationDesc
  190.                                         m_pHostAddress,     // pdpaddrHost
  191.                                         m_pDeviceAddress,   // pdpaddrDeviceInfo
  192.                                         NULL, 0,            // pvUserEnumData, size
  193.                                         INFINITE ,           // dwEnumCount
  194.                                         0,                  // dwRetryInterval
  195.                                         INFINITE ,                  // dwTimeOut
  196.                                         NULL,               // pvUserContext
  197.                                         &hCancelHandle, // pAsyncHandle
  198.                                         0 ) ;// dwFlags
  199. return hr;
  200. }
  201. HRESULT CDPClient::InitDirectPlay()
  202. {
  203.     HRESULT     hr = S_OK;
  204.     // Create the IDirectPlay8Client Object
  205. hr = CoCreateInstance(CLSID_DirectPlay8Client, NULL, 
  206.                                     CLSCTX_INPROC_SERVER,
  207.                                     IID_IDirectPlay8Client, 
  208.                                     (LPVOID*) &m_pDPClient ) ;
  209.     if( FAILED(hr) )
  210.         return hr;
  211.     // Init DirectPlay
  212. hr = m_pDPClient->Initialize(this, Shell_DirectPlayMessageHandler, 0 );
  213.     if( FAILED( hr ) )
  214.     {
  215. return hr;
  216.     }
  217.     
  218.     // Ensure that TCP/IP is a valid Service Provider
  219. BOOL bVal = IsServiceProviderValid(m_pDPClient,&CLSID_DP8SP_TCPIP );
  220.     if( FALSE == bVal)
  221.         hr = E_FAIL;
  222. return hr;
  223. }
  224. BOOL CDPClient::IsServiceProviderValid(IDirectPlay8Client * lpDPClient,const GUID* pGuidSP)
  225. {
  226.     HRESULT                     hr;
  227.     DPN_SERVICE_PROVIDER_INFO*  pdnSPInfo = NULL;
  228.     DWORD                       dwItems = 0;
  229.     DWORD                       dwSize = 0;
  230.     hr = lpDPClient->EnumServiceProviders(pGuidSP, NULL, NULL, &dwSize, &dwItems, 0);
  231.     if( hr != DPNERR_BUFFERTOOSMALL)
  232.     {
  233. return hr;
  234.     }
  235.     pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
  236. hr = lpDPClient->EnumServiceProviders(pGuidSP, NULL, pdnSPInfo, &dwSize, &dwItems, 0 ) ;
  237.     if( FAILED( hr) )
  238.     {
  239. delete [](LPBYTE) pdnSPInfo;
  240. return hr;
  241.     }
  242.     // There are no items returned so the requested SP is not available
  243.     if( dwItems == 0)
  244.     {
  245.         hr = E_FAIL;
  246.     }
  247.     delete [](LPBYTE)pdnSPInfo;
  248.     if( SUCCEEDED(hr) )
  249.         return TRUE;
  250.     else
  251.         return FALSE;
  252. }
  253. HRESULT CDPClient::Shell_DirectPlayMessageHandler(PVOID pvUserContext, DWORD dwMessageType, PVOID pMessage)
  254. {
  255. CDPClient * pThis = (CDPClient*)pvUserContext;
  256. if(pThis)
  257. return pThis->Inner_DirectPlayMessageHandler(dwMessageType,pMessage);
  258. return E_FAIL;
  259. }
  260. HRESULT CDPClient::Inner_DirectPlayMessageHandler(DWORD dwMessageType, PVOID pMessage)
  261. {
  262. switch(dwMessageType)
  263. {
  264. //DirectPlayClient必须处理的消息 
  265. case DPN_MSGID_RECEIVE:
  266. {
  267. PDPNMSG_RECEIVE pReceivBuf = (PDPNMSG_RECEIVE)pMessage;
  268. PumpVBMessage(pReceivBuf);
  269. }
  270. return S_OK;
  271. case DPN_MSGID_TERMINATE_SESSION:
  272. m_bConnected = FALSE;
  273. break;
  274. case DPN_MSGID_RETURN_BUFFER:
  275. break;
  276. //DirectPlayClient可选消息
  277. case DPN_MSGID_ENUM_HOSTS_RESPONSE://枚举主机响应消息
  278. {
  279. DPNMSG_ENUM_HOSTS_RESPONSE * pEnumHostResp = (DPNMSG_ENUM_HOSTS_RESPONSE*)pMessage;
  280. EnumHostRespMessageHandler(pEnumHostResp);
  281. return S_OK;
  282. }
  283. break;
  284. case DPN_MSGID_ASYNC_OP_COMPLETE:
  285. break;
  286. case DPN_MSGID_CLIENT_INFO:
  287. break;
  288. case DPN_MSGID_CONNECT_COMPLETE:
  289. break;
  290. case DPN_MSGID_SEND_COMPLETE:
  291. break;
  292. case DPN_MSGID_SERVER_INFO:
  293. break;
  294. }
  295. return S_OK;//DPN_OK
  296. }
  297. PHOST_NODE CDPClient::FindInstanceGuid(const GUID &newInstanceGUID)
  298. {
  299. PHOST_NODE HostHeader = m_pHostList;
  300. while(HostHeader)
  301. {
  302. if(IsEqualGUID(HostHeader->pAppDesc->guidInstance ,newInstanceGUID))
  303. return HostHeader;
  304. HostHeader = HostHeader->pNext;
  305. }
  306. return NULL;
  307. }
  308. HRESULT CDPClient::EnumHostRespMessageHandler(DPNMSG_ENUM_HOSTS_RESPONSE *pEnumHostResp)
  309. {
  310. if(pEnumHostResp==NULL)
  311. return S_OK;
  312. //获得会话名与实例GUID
  313. CSimpleAutoLock lock(&m_csHostList);
  314. PHOST_NODE pHostInfoList = FindInstanceGuid(pEnumHostResp->pApplicationDescription->guidInstance);
  315. if(pHostInfoList)
  316. {
  317. return S_OK;
  318. }
  319. const DPN_APPLICATION_DESC*     pAppDesc;
  320. HOST_NODE*                      pHostNode = NULL;
  321. WCHAR*                          pwszSession = NULL;
  322. pAppDesc = pEnumHostResp->pApplicationDescription;
  323. // Insert each host response if it isn't already present
  324. // This host session is not in the list then so insert it.
  325. pHostNode = new HOST_NODE;
  326. if( pHostNode == NULL)
  327. {
  328. return S_OK;
  329. }
  330. ZeroMemory(pHostNode, sizeof(HOST_NODE));
  331. // Copy the Host Address
  332. HRESULT hr = pEnumHostResp->pAddressSender->Duplicate(&pHostNode->pHostAddress ) ;
  333. if( FAILED(hr) )
  334. {
  335. delete pHostNode;
  336. return S_OK;
  337. }
  338. pHostNode->pAppDesc = new DPN_APPLICATION_DESC;
  339. if(pHostNode->pAppDesc==NULL)
  340. {
  341. pHostNode->pHostAddress->Release();
  342. delete pHostNode;
  343. return S_OK;
  344. }
  345. ZeroMemory(pHostNode->pAppDesc, sizeof(DPN_APPLICATION_DESC));
  346. memcpy(pHostNode->pAppDesc, pAppDesc, sizeof(DPN_APPLICATION_DESC));
  347. // Null out all the pointers we aren't copying
  348. pHostNode->pAppDesc->pwszSessionName = NULL;
  349. pHostNode->pAppDesc->pwszPassword = NULL;
  350. pHostNode->pAppDesc->pvReservedData = NULL;
  351. pHostNode->pAppDesc->dwReservedDataSize = 0;
  352. pHostNode->pAppDesc->pvApplicationReservedData = NULL;
  353. pHostNode->pAppDesc->dwApplicationReservedDataSize = 0;
  354. if( pAppDesc->pwszSessionName)
  355. pwszSession = SysAllocString(pAppDesc->pwszSessionName);
  356. pHostNode->pwszSessionName = pwszSession;
  357. // 将此结点插入到链表的前头
  358. pHostNode->pNext = m_pHostList;
  359. if(m_pHostList)
  360. pHostNode->HostIndex = m_pHostList->HostIndex +1;
  361. else
  362. pHostNode->HostIndex = 0;
  363. m_pHostList = pHostNode;
  364. return S_OK;
  365. }
  366. HRESULT CDPClient::PumpVBMessage(PDPNMSG_RECEIVE pReceiveMessage)
  367. {
  368. PMEDIAMSG pNetMessage = (PMEDIAMSG)pReceiveMessage->pReceiveData;
  369. if(pReceiveMessage->dwReceiveDataSize ==0)
  370. return DPN_OK;
  371. if(pNetMessage->mmsgType==mmsg_DataRespons)
  372. {
  373. PMEDIADATAPARAM param = (PMEDIADATAPARAM)pNetMessage->lpParamBuffer;
  374. m_MMEvent->OnDataArrive(param->llDataPos,param->dwDataSize,param->lpDataBuff);
  375. }
  376. else if(pNetMessage->mmsgType==mmsg_MediaInfoRespons)
  377. {
  378. LONGLONG llLength = *((LONGLONG*)pNetMessage->lpParamBuffer);
  379. m_MMEvent->OnLenghtArrive(llLength);
  380. }
  381. else
  382. {
  383. ASSERT(0);
  384. }
  385. return S_OK;
  386. }
  387. void CDPClient::SendBuffer(LPBYTE lpBuffer,DWORD dwSize)
  388. {
  389. DPN_BUFFER_DESC dpbuf;
  390. dpbuf.dwBufferSize =dwSize ;
  391. dpbuf.pBufferData  = lpBuffer;
  392. DPNHANDLE hCancelHandle;
  393. m_pDPClient->Send(&dpbuf,1,
  394. 1000,
  395. NULL,&hCancelHandle,DPNSEND_NOCOMPLETE );
  396. }
  397. void CDPClient::SendMediaLenRequire()
  398. {
  399. MEDIAMSG mediaLenReq;
  400. mediaLenReq.mmsgType = mmsg_MediaInfoRequire;
  401. mediaLenReq.dwBufferLen = 0;
  402. SendBuffer((LPBYTE)&mediaLenReq,sizeof(MEDIAMSG));
  403. }
  404. void CDPClient::SendMediaDataRequire(LONGLONG llPos,DWORD dwSize)
  405. {
  406. BYTE bytReqBuf[sizeof(MEDIADATAPARAM)+sizeof(MEDIAMSG)];
  407. PMEDIAMSG preqParam = (PMEDIAMSG)bytReqBuf;
  408. preqParam->mmsgType = mmsg_DataRequire;
  409. preqParam->dwBufferLen = sizeof(MEDIADATAPARAM);
  410. PMEDIADATAPARAM param = (PMEDIADATAPARAM)preqParam->lpParamBuffer;
  411. param->llDataPos = llPos;
  412. param->dwDataSize = dwSize;
  413. SendBuffer(bytReqBuf,sizeof(MEDIADATAPARAM)+sizeof(MEDIAMSG));
  414. }