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

  1. /*******************************************************************************
  2. Module: bridge.cpp
  3. Author: Qianbo Huai
  4. Abstract:
  5. implements the class CBridge
  6. *******************************************************************************/
  7. #include "stdafx.h"
  8. #include "work.h"
  9. extern LPSTR glpCmdLine;
  10. /*//////////////////////////////////////////////////////////////////////////////
  11. hard coded SDP
  12. ////*/
  13. const WCHAR * const MySDP = L"\
  14. v=0\n\
  15. o=qhuai 0 0 IN IP4 157.55.89.115\n\
  16. s=BridgeTestConf\n\
  17. c=IN IP4 239.9.20.26/15\n\
  18. t=0 0\n\
  19. m=video 20000 RTP/AVP 34 31\n\
  20. m=audio 20040 RTP/AVP 0 4\n\
  21. ";
  22. const WCHAR * const MySDP2 = L"\
  23. v=0\n\
  24. o=qhuai 0 0 IN IP4 157.55.89.115\n\
  25. s=BridgeTestConf2\n\
  26. c=IN IP4 239.9.20.26/15\n\
  27. t=0 0\n\
  28. m=video 20000 RTP/AVP 34 31\n\
  29. m=audio 20040 RTP/AVP 3\n\
  30. ";
  31. /*//////////////////////////////////////////////////////////////////////////////
  32. initiates tapi and listens at h323 address
  33. ////*/
  34. HRESULT
  35. CBridge::InitTapi ()
  36. {
  37. HRESULT hr;
  38. // init members
  39. m_pTapi = NULL;
  40. m_pH323Addr = NULL;
  41. m_pSDPAddr = NULL;
  42. m_pBridgeCall = new CBridgeCall (this);
  43. // create tapi
  44. hr = CoCreateInstance (
  45. CLSID_TAPI,
  46. NULL,
  47. CLSCTX_INPROC_SERVER,
  48. IID_ITTAPI,
  49. (LPVOID *)&m_pTapi
  50. );
  51. if (FAILED(hr))
  52. return hr;
  53. // tapi initiate
  54. hr = m_pTapi->Initialize ();
  55. if (FAILED(hr))
  56. return hr;
  57. // associate event with listener
  58. CTAPIEventNotification *pEventNotif = NULL;
  59. IConnectionPointContainer *pContainer = NULL;
  60. IConnectionPoint *pPoint = NULL;
  61. IH323LineEx *pIH323LineEx = NULL;
  62. ULONG ulTapiEventAdvise;
  63. long lCallNotif;
  64. BSTR bstrAddrName = NULL;
  65. // create event notification
  66. pEventNotif = new CTAPIEventNotification;
  67. if (!pEventNotif)
  68. {
  69. hr = E_OUTOFMEMORY;
  70. goto Error;
  71. }
  72. // get pointer container from tapi
  73. hr = m_pTapi->QueryInterface (
  74. IID_IConnectionPointContainer,
  75. (void **)&pContainer
  76. );
  77. if (FAILED(hr))
  78. goto Error;
  79. // get connection point from container
  80. hr = pContainer->FindConnectionPoint (
  81. IID_ITTAPIEventNotification,
  82. &pPoint
  83. );
  84. if (FAILED(hr))
  85. goto Error;
  86. // advise event notification on connection pointer
  87. hr = pPoint->Advise (
  88. pEventNotif,
  89. &ulTapiEventAdvise
  90. );
  91. if (FAILED(hr))
  92. goto Error;
  93. // put event filter on tapi
  94. hr = m_pTapi->put_EventFilter (
  95. TE_CALLNOTIFICATION |
  96. TE_CALLSTATE |
  97. TE_CALLMEDIA |
  98. TE_PRIVATE
  99. );
  100. if (FAILED(hr))
  101. goto Error;
  102. // find h323 address
  103. bstrAddrName = SysAllocString (L"H323 Line");
  104. hr = FindAddress (
  105. 0,
  106. bstrAddrName,
  107. TAPIMEDIATYPE_AUDIO,
  108. &m_pH323Addr
  109. );
  110. SysFreeString (bstrAddrName);
  111. if (FAILED(hr))
  112. goto Error;
  113. // check if it supports video
  114. BOOL fSupportsVideo;
  115. if (AddressSupportsMediaType (m_pH323Addr, TAPIMEDIATYPE_VIDEO))
  116. m_lH323MediaType = TAPIMEDIATYPE_AUDIO | TAPIMEDIATYPE_VIDEO;
  117. else
  118. m_lH323MediaType = TAPIMEDIATYPE_AUDIO;
  119. hr = m_pH323Addr->QueryInterface(&pIH323LineEx);
  120. if (SUCCEEDED(hr))
  121. {
  122. hr = pIH323LineEx->SetExternalT120Address(TRUE, INADDR_ANY, 1503);
  123. H245_CAPABILITY Capabilities[] =
  124. {HC_G711, HC_G723, HC_H263QCIF, HC_H261QCIF};
  125. DWORD Weights[] = {200, 100, 100, 0};
  126. hr = pIH323LineEx->SetDefaultCapabilityPreferrence(
  127. 4, Capabilities, Weights
  128. );
  129. }
  130. // register call notification
  131. hr = m_pTapi->RegisterCallNotifications (
  132. m_pH323Addr,
  133. VARIANT_TRUE,
  134. VARIANT_TRUE,
  135. m_lH323MediaType,
  136. ulTapiEventAdvise,
  137. &lCallNotif
  138. );
  139. if (FAILED(hr))
  140. goto Error;
  141. // find sdp address
  142. hr = FindAddress (
  143. LINEADDRESSTYPE_SDP,
  144. NULL,
  145. TAPIMEDIATYPE_AUDIO,
  146. &m_pSDPAddr
  147. );
  148. if (FAILED(hr))
  149. return hr;
  150. // check if it supports video
  151. if (AddressSupportsMediaType (m_pSDPAddr, TAPIMEDIATYPE_VIDEO))
  152. m_lSDPMediaType = TAPIMEDIATYPE_AUDIO | TAPIMEDIATYPE_VIDEO;
  153. else
  154. m_lSDPMediaType = TAPIMEDIATYPE_AUDIO;
  155. Cleanup:
  156. if (pEventNotif)
  157. pEventNotif->Release ();
  158. if (pPoint)
  159. pPoint->Release ();
  160. if (pContainer)
  161. pContainer->Release ();
  162. if (pIH323LineEx)
  163. pIH323LineEx->Release ();
  164. return hr;
  165. Error:
  166. if (m_pH323Addr)
  167. {
  168. m_pH323Addr->Release ();
  169. m_pH323Addr = NULL;
  170. }
  171. if (m_pSDPAddr)
  172. {
  173. m_pSDPAddr->Release ();
  174. m_pSDPAddr = NULL;
  175. }
  176. if (m_pTapi)
  177. {
  178. m_pTapi->Release ();
  179. m_pTapi = NULL;
  180. }
  181. goto Cleanup;
  182. }
  183. /*//////////////////////////////////////////////////////////////////////////////
  184. ////*/
  185. void
  186. CBridge::ShutdownTapi ()
  187. {
  188. if (m_pBridgeCall)
  189. {
  190. delete m_pBridgeCall;
  191. m_pBridgeCall = NULL;
  192. }
  193. if (m_pSDPAddr)
  194. {
  195. m_pSDPAddr->Release ();
  196. m_pSDPAddr = NULL;
  197. }
  198. if (m_pH323Addr)
  199. {
  200. m_pH323Addr->Release ();
  201. m_pH323Addr = NULL;
  202. }
  203. if (m_pTapi)
  204. {
  205. m_pTapi->Release ();
  206. m_pTapi = NULL;
  207. }
  208. }
  209. /*//////////////////////////////////////////////////////////////////////////////
  210. create h323 call from event
  211. ////*/
  212. HRESULT
  213. CBridge::CreateH323Call (IDispatch *pEvent)
  214. {
  215. HRESULT hr;
  216. ITCallNotificationEvent *pNotify = NULL;
  217. CALL_PRIVILEGE privilege;
  218. ITCallInfo *pCallInfo = NULL;
  219. ITBasicCallControl *pCall = NULL;
  220. // get call event interface
  221. hr = pEvent->QueryInterface (
  222. IID_ITCallNotificationEvent,
  223. (void **)&pNotify
  224. );
  225. if (FAILED(hr))
  226. return hr;
  227. // get call info
  228. hr = pNotify->get_Call (&pCallInfo);
  229. if (FAILED(hr))
  230. goto Error;
  231. // if we own the call
  232. hr = pCallInfo->get_Privilege (&privilege);
  233. if (FAILED(hr))
  234. goto Error;
  235. if (CP_OWNER!=privilege)
  236. {
  237. hr = E_UNEXPECTED;
  238. goto Cleanup;
  239. }
  240. // get basic call control
  241. hr = pCallInfo->QueryInterface (
  242. IID_ITBasicCallControl,
  243. (void **)&pCall
  244. );
  245. if (FAILED(hr))
  246. goto Error;
  247. m_pBridgeCall->SetH323Call (pCall);
  248. Cleanup:
  249. if (pCall)
  250. {
  251. pCall->Release ();
  252. pCall = NULL;
  253. }
  254. if (pCallInfo)
  255. {
  256. pCallInfo->Release ();
  257. pCallInfo = NULL;
  258. }
  259. if (pNotify)
  260. {
  261. pNotify->Release ();
  262. pNotify = NULL;
  263. }
  264. return hr;
  265. Error:
  266. goto Cleanup;
  267. }
  268. /*//////////////////////////////////////////////////////////////////////////////
  269. ////*/
  270. BOOL
  271. CBridge::HasH323Call ()
  272. {
  273. return m_pBridgeCall->HasH323Call ();
  274. }
  275. /*//////////////////////////////////////////////////////////////////////////////
  276. iterates through tapi, find an address and create a sdp call
  277. ////*/
  278. HRESULT
  279. CBridge::CreateSDPCall ()
  280. {
  281. HRESULT hr;
  282. // create call, ignore bstrDestAddr, hardcode it here
  283. ITBasicCallControl *pCall = NULL;
  284. BSTR bstrFixedDest;
  285. if (glpCmdLine[0] == '\0')
  286. bstrFixedDest = SysAllocString (MySDP);
  287. else
  288. bstrFixedDest = SysAllocString (MySDP2);
  289. hr = m_pSDPAddr->CreateCall (
  290. bstrFixedDest, // bstrDestAddr,
  291. LINEADDRESSTYPE_SDP,
  292. m_lSDPMediaType,
  293. &pCall
  294. );
  295. SysFreeString (bstrFixedDest);
  296. if (FAILED(hr))
  297. return hr;
  298. m_pBridgeCall->SetSDPCall (pCall);
  299. pCall->Release ();
  300. return hr;
  301. }
  302. /*//////////////////////////////////////////////////////////////////////////////
  303. bridges h323 and sdp calls
  304. ////*/
  305. HRESULT
  306. CBridge::BridgeCalls ()
  307. {
  308. HRESULT hr;
  309. return m_pBridgeCall->BridgeCalls ();
  310. }
  311. /*//////////////////////////////////////////////////////////////////////////////
  312. returns to same state as just initializing tapi
  313. ////*/
  314. void
  315. CBridge::Clear ()
  316. {
  317. m_pBridgeCall->Clear ();
  318. }
  319. /*//////////////////////////////////////////////////////////////////////////////
  320. if the address type is given, find an address based on
  321. address type and media type
  322. else if address name is given, find an address based on
  323. address name and media type
  324. else
  325. return E_FAIL
  326. ////*/
  327. HRESULT
  328. CBridge::FindAddress (
  329. long dwAddrType,
  330. BSTR bstrAddrName,
  331. long lMediaType,
  332. ITAddress **ppAddr
  333. )
  334. {
  335. HRESULT hr;
  336. IEnumAddress *pEnumAddr = NULL;
  337. ITAddress *pAddr = NULL;
  338. ITAddressCapabilities *pAddrCaps = NULL;
  339. BOOL fFound = false;
  340. long lTypeFound;
  341. BSTR bstrAddrNameFound = NULL;
  342. // clear output address
  343. if ((*ppAddr))
  344. {
  345. (*ppAddr)->Release ();
  346. (*ppAddr) = NULL;
  347. }
  348. // enumerate the address
  349. hr = m_pTapi->EnumerateAddresses (&pEnumAddr);
  350. if (FAILED(hr))
  351. {
  352. DoMessage (L"Failed to enumerate address");
  353. goto Error;
  354. }
  355. // loop to find the right address
  356. while (!fFound)
  357. {
  358. // next address
  359. if (pAddr)
  360. {
  361. pAddr->Release ();
  362. pAddr = NULL;
  363. }
  364. hr = pEnumAddr->Next (1, &pAddr, NULL);
  365. if (S_OK != hr)
  366. break;
  367. if (dwAddrType != 0)
  368. {
  369. // addr type is valid, ignore addr name
  370. if (pAddrCaps)
  371. {
  372. pAddrCaps->Release ();
  373. pAddrCaps = NULL;
  374. }
  375. hr = pAddr->QueryInterface (
  376. IID_ITAddressCapabilities,
  377. (void **)&pAddrCaps
  378. );
  379. if (FAILED(hr))
  380. {
  381. DoMessage (L"Failed to retrieve address capabilities");
  382. goto Error;
  383. }
  384. // find address type supported
  385. hr = pAddrCaps->get_AddressCapability (AC_ADDRESSTYPES, &lTypeFound);
  386. if (FAILED(hr))
  387. {
  388. DoMessage (L"Failed to get address type");
  389. goto Error;
  390. }
  391. // check if the type we wanted
  392. if (dwAddrType != lTypeFound)
  393. continue;
  394. }
  395. else if (bstrAddrName != NULL)
  396. {
  397. hr = pAddr->get_AddressName (&bstrAddrNameFound);
  398. if (FAILED(hr))
  399. {
  400. DoMessage (L"Failed to get address name");
  401. goto Error;
  402. }
  403. if (wcscmp(bstrAddrName, bstrAddrNameFound) != 0)
  404. continue;
  405. }
  406. else
  407. {
  408. DoMessage (L"Both address type and name are null. Internal error");
  409. hr = E_UNEXPECTED;
  410. goto Error;
  411. }
  412. // now check media type
  413. if (AddressSupportsMediaType (pAddr, lMediaType))
  414. fFound = true;
  415. } // end of while (!fFound)
  416. if (fFound)
  417. {
  418. (*ppAddr) = pAddr;
  419. (*ppAddr)->AddRef ();
  420. }
  421. Cleanup:
  422. if (pAddrCaps)
  423. pAddrCaps->Release ();
  424. if (pAddr)
  425. pAddr->Release ();
  426. if (pEnumAddr)
  427. pEnumAddr->Release ();
  428. return hr;
  429. Error:
  430. goto Cleanup;
  431. }
  432. /*//////////////////////////////////////////////////////////////////////////////
  433. checks if the address supports the media type
  434. ////*/
  435. BOOL
  436. CBridge::AddressSupportsMediaType (ITAddress *pAddr, long lMediaType)
  437. {
  438. VARIANT_BOOL vbSupport = VARIANT_FALSE;
  439. ITMediaSupport * pMediaSupport;
  440. if (SUCCEEDED(pAddr->QueryInterface (IID_ITMediaSupport, (void**)&pMediaSupport)))
  441. {
  442. pMediaSupport->QueryMediaType (lMediaType, &vbSupport);
  443. pMediaSupport->Release ();
  444. }
  445. return (vbSupport==VARIANT_TRUE);
  446. }
  447. /*//////////////////////////////////////////////////////////////////////////////
  448. ////*/
  449. HRESULT
  450. CBridge::GetSDPAddress (ITAddress **ppAddress)
  451. {
  452. HRESULT hr;
  453. if (*ppAddress)
  454. {
  455. (*ppAddress)->Release ();
  456. *ppAddress = NULL;
  457. }
  458. *ppAddress = m_pSDPAddr;
  459. m_pSDPAddr->AddRef ();
  460. return S_OK;
  461. }