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.

1100 lines
25 KiB

  1. // File: icallin.cpp
  2. #include "precomp.h"
  3. #include <regentry.h>
  4. #include "cncodes.h" // needed for CN_
  5. #include "icall_in.h"
  6. #include "imanager.h"
  7. #include "util.h"
  8. extern HRESULT OnNotifyCallError(IUnknown *pCallNotify, PVOID pv, REFIID riid);
  9. static HRESULT OnNotifyCallAccepted(IUnknown *pCallNotify, PVOID pv, REFIID riid);
  10. // Internal code to indicate that there was no security data available in an incoming call.
  11. const int CALL_NO_SECURITY_DATA = -1;
  12. static const IID * g_apiidCP_Call[] =
  13. {
  14. {&IID_INmCallNotify},
  15. {&IID_INmCallNotify2}
  16. };
  17. CIncomingCall::CIncomingCall(
  18. COprahNCUI * pOprahNCUI,
  19. BOOL fInvite,
  20. CONF_HANDLE hConf,
  21. PCWSTR pcwszNodeName,
  22. PUSERDATAINFO pUserDataInfoEntries,
  23. UINT cUserDataEntries) :
  24. CConnectionPointContainer(g_apiidCP_Call, ARRAY_ELEMENTS(g_apiidCP_Call)),
  25. m_pOprahNCUI(pOprahNCUI),
  26. m_pConnection(NULL),
  27. m_fInvite(fInvite),
  28. m_hConf(hConf),
  29. m_bstrCaller(SysAllocString(pcwszNodeName)),
  30. m_State(NM_CALL_INIT),
  31. m_dwFlags(0)
  32. {
  33. DebugEntry(CIncomingCall::CIncomingCall[T120]);
  34. ProcessT120UserData(pUserDataInfoEntries, cUserDataEntries);
  35. DebugExitVOID(CIncomingCall::CIncomingCall);
  36. }
  37. CIncomingCall::CIncomingCall(COprahNCUI *pOprahNCUI,
  38. IH323Endpoint* pConnection, P_APP_CALL_SETUP_DATA lpvMNMData,
  39. DWORD dwFlags) :
  40. CConnectionPointContainer(g_apiidCP_Call, ARRAY_ELEMENTS(g_apiidCP_Call)),
  41. m_pOprahNCUI(pOprahNCUI),
  42. m_pConnection(pConnection),
  43. m_fInvite(FALSE),
  44. m_hConf(NULL),
  45. m_bstrCaller(NULL),
  46. m_State(NM_CALL_INIT),
  47. m_guidNode(GUID_NULL),
  48. m_dwFlags(dwFlags),
  49. m_fMemberAdded(FALSE)
  50. {
  51. DebugEntry(CIncomingCall::CIncomingCall[H323]);
  52. HRESULT hr;
  53. ASSERT(m_pConnection);
  54. m_pConnection->AddRef();
  55. WCHAR wszCaller[MAX_CALLER_NAME];
  56. if (SUCCEEDED(m_pConnection->GetRemoteUserName(wszCaller, MAX_CALLER_NAME)))
  57. {
  58. m_bstrCaller = SysAllocString(wszCaller);
  59. }
  60. if ((NULL != lpvMNMData) && (lpvMNMData->dwDataSize > sizeof(DWORD)))
  61. {
  62. BYTE *pbData = ((BYTE*)lpvMNMData->lpData) + sizeof(DWORD);
  63. DWORD cbRemaining = lpvMNMData->dwDataSize - sizeof(DWORD);
  64. while ((sizeof(GUID) + sizeof(DWORD)) < cbRemaining)
  65. {
  66. DWORD cbData = *(DWORD*)(pbData + sizeof(GUID));
  67. DWORD cbRecord = cbData + sizeof(GUID) + sizeof(DWORD);
  68. if (cbRemaining < cbRecord)
  69. {
  70. break;
  71. }
  72. if (*(GUID *)pbData == g_csguidNodeIdTag)
  73. {
  74. m_guidNode = *(GUID *)(pbData + sizeof(GUID) + sizeof(DWORD));
  75. }
  76. m_UserData.AddUserData((GUID *)pbData,
  77. (unsigned short)cbData,
  78. pbData + sizeof(GUID) + sizeof(DWORD));
  79. cbRemaining -= cbRecord;
  80. pbData += cbRecord;
  81. }
  82. }
  83. DebugExitVOID(CIncomingCall::CIncomingCall);
  84. }
  85. CIncomingCall::~CIncomingCall()
  86. {
  87. DebugEntry(CIncomingCall::~CIncomingCall);
  88. if(m_pConnection)
  89. {
  90. m_pConnection->Release();
  91. m_pConnection = NULL;
  92. }
  93. SysFreeString(m_bstrCaller);
  94. DebugExitVOID(CIncomingCall::CIncomingCall);
  95. }
  96. VOID CIncomingCall::ProcessT120UserData(
  97. PUSERDATAINFO pUserDataInfoEntries,
  98. UINT cUserDataEntries)
  99. {
  100. if (cUserDataEntries > 0)
  101. {
  102. ASSERT(pUserDataInfoEntries);
  103. for (UINT u = 0; u < cUserDataEntries; u++)
  104. {
  105. m_UserData.AddUserData(pUserDataInfoEntries[u].pGUID,
  106. (unsigned short)pUserDataInfoEntries[u].cbData,
  107. pUserDataInfoEntries[u].pData);
  108. }
  109. }
  110. }
  111. BOOL CIncomingCall::MatchAcceptedCaller(PCWSTR pcwszNodeName)
  112. {
  113. // check to see if this caller matches someone whom we already accepted
  114. if ((NULL != m_pConnection) &&
  115. (NM_CALL_ACCEPTED == m_State) &&
  116. (GUID_NULL == m_guidNode) &&
  117. (NULL != m_bstrCaller) &&
  118. (0 == UnicodeCompare(m_bstrCaller, pcwszNodeName)) )
  119. {
  120. return TRUE;
  121. }
  122. return FALSE;
  123. }
  124. BOOL CIncomingCall::MatchAcceptedCaller(GUID* pguidNodeId)
  125. {
  126. // check to see if this caller matches someone whom we already accepted
  127. if ((NULL != m_pConnection) &&
  128. ((NM_CALL_INIT == m_State) ||
  129. (NM_CALL_ACCEPTED == m_State)) &&
  130. (GUID_NULL != m_guidNode) &&
  131. (*pguidNodeId == m_guidNode))
  132. {
  133. return TRUE;
  134. }
  135. return FALSE;
  136. }
  137. BOOL CIncomingCall::MatchActiveCaller(GUID* pguidNodeId)
  138. {
  139. // check to see if this caller matches someone whom we already accepted
  140. // or is in the process of calling us
  141. if ((NULL != m_pConnection) &&
  142. ((NM_CALL_INIT == m_State) ||
  143. (NM_CALL_RING == m_State) ||
  144. (NM_CALL_ACCEPTED == m_State)) &&
  145. (GUID_NULL != m_guidNode) &&
  146. (*pguidNodeId == m_guidNode))
  147. {
  148. return TRUE;
  149. }
  150. return FALSE;
  151. }
  152. void CIncomingCall::Ring()
  153. {
  154. m_State = NM_CALL_RING;
  155. NotifySink((PVOID) m_State, OnNotifyCallStateChanged);
  156. }
  157. HRESULT CIncomingCall::OnH323Connected()
  158. {
  159. CConfObject *pco = ::GetConfObject();
  160. if (NULL != pco)
  161. {
  162. BOOL fAddMember = DidUserAccept();
  163. pco->OnH323Connected(m_pConnection, m_dwFlags, fAddMember, m_guidNode);
  164. m_fMemberAdded = fAddMember;
  165. }
  166. return S_OK;
  167. }
  168. HRESULT CIncomingCall::OnH323Disconnected()
  169. {
  170. if (NM_CALL_RING == m_State)
  171. {
  172. if (m_hConf)
  173. {
  174. CONF_HANDLE hConf = m_hConf;
  175. m_hConf = NULL;
  176. // if there is an invite or join pending, kill it
  177. if ( m_fInvite )
  178. hConf->InviteResponse(FALSE);
  179. else
  180. hConf->JoinResponse(FALSE);
  181. }
  182. }
  183. if(m_pConnection)
  184. {
  185. m_pConnection->Release();
  186. m_pConnection = NULL;
  187. }
  188. if ((NM_CALL_RING == m_State) ||
  189. (NM_CALL_INIT == m_State))
  190. {
  191. m_State = NM_CALL_CANCELED;
  192. NotifySink((PVOID) m_State, OnNotifyCallStateChanged);
  193. }
  194. return m_hConf ? S_FALSE : S_OK;
  195. }
  196. VOID CIncomingCall::OnIncomingT120Call(
  197. BOOL fInvite,
  198. PUSERDATAINFO pUserDataInfoEntries,
  199. UINT cUserDataEntries)
  200. {
  201. m_fInvite = fInvite;
  202. ProcessT120UserData(pUserDataInfoEntries, cUserDataEntries);
  203. }
  204. HRESULT CIncomingCall::OnT120ConferenceEnded()
  205. {
  206. m_hConf = NULL;
  207. if(!m_fMemberAdded && m_pConnection)
  208. {
  209. // we didn't hand off this connection to the member
  210. IH323Endpoint* pConnection = m_pConnection;
  211. m_pConnection = NULL;
  212. pConnection->Disconnect();
  213. pConnection->Release();
  214. }
  215. if (NM_CALL_RING == m_State)
  216. {
  217. m_State = NM_CALL_CANCELED;
  218. NotifySink((PVOID) m_State, OnNotifyCallStateChanged);
  219. }
  220. return m_pConnection ? S_FALSE : S_OK;
  221. }
  222. HRESULT CIncomingCall::Terminate(BOOL fReject)
  223. {
  224. HRESULT hr = E_FAIL;
  225. // need to make sure that we are still ringing
  226. if ((NM_CALL_ACCEPTED != m_State) &&
  227. (NM_CALL_REJECTED != m_State) &&
  228. (NM_CALL_CANCELED != m_State))
  229. {
  230. m_State = fReject ? NM_CALL_REJECTED : NM_CALL_CANCELED;
  231. TRACE_OUT(("CIncomingCall: Call not accepted - responding"));
  232. if (NULL != m_hConf)
  233. {
  234. CONF_HANDLE hConf = m_hConf;
  235. m_hConf = NULL;
  236. if (m_fInvite)
  237. {
  238. hConf->InviteResponse(FALSE);
  239. }
  240. else
  241. {
  242. CConfObject *pco = ::GetConfObject();
  243. if ((NULL != pco) && (pco->GetConfHandle() == hConf))
  244. {
  245. hConf->JoinResponse(FALSE);
  246. }
  247. }
  248. }
  249. if (NULL != m_pConnection)
  250. {
  251. ConnectStateType state;
  252. hr = m_pConnection->GetState(&state);
  253. ASSERT(SUCCEEDED(hr));
  254. if(CLS_Alerting == state)
  255. {
  256. IH323Endpoint* pConn = m_pConnection;
  257. m_pConnection = NULL;
  258. pConn->AcceptRejectConnection(CRR_REJECT);
  259. pConn->Release();
  260. m_pOprahNCUI->ReleaseAV(pConn);
  261. }
  262. }
  263. NotifySink((PVOID) m_State, OnNotifyCallStateChanged);
  264. hr = S_OK;
  265. }
  266. return hr;
  267. }
  268. STDMETHODIMP_(ULONG) CIncomingCall::AddRef(void)
  269. {
  270. return RefCount::AddRef();
  271. }
  272. STDMETHODIMP_(ULONG) CIncomingCall::Release(void)
  273. {
  274. return RefCount::Release();
  275. }
  276. HRESULT STDMETHODCALLTYPE CIncomingCall::QueryInterface(REFIID riid, PVOID *ppv)
  277. {
  278. HRESULT hr = S_OK;
  279. if ((riid == IID_INmCall) || (riid == IID_IUnknown))
  280. {
  281. *ppv = (INmCall *)this;
  282. ApiDebugMsg(("CIncomingCall::QueryInterface()"));
  283. }
  284. else if (riid == IID_IConnectionPointContainer)
  285. {
  286. *ppv = (IConnectionPointContainer *) this;
  287. ApiDebugMsg(("CIncomingCall::QueryInterface(): Returning IConnectionPointContainer."));
  288. }
  289. else
  290. {
  291. hr = E_NOINTERFACE;
  292. *ppv = NULL;
  293. ApiDebugMsg(("CIncomingCall::QueryInterface(): Called on unknown interface."));
  294. }
  295. if (S_OK == hr)
  296. {
  297. AddRef();
  298. }
  299. return hr;
  300. }
  301. HRESULT CIncomingCall::IsIncoming(void)
  302. {
  303. return S_OK;
  304. }
  305. HRESULT CIncomingCall::GetState(NM_CALL_STATE *pState)
  306. {
  307. HRESULT hr = E_POINTER;
  308. if (NULL != pState)
  309. {
  310. *pState = m_State;
  311. hr = S_OK;
  312. }
  313. return hr;
  314. }
  315. HRESULT CIncomingCall::GetName(BSTR * pbstrName)
  316. {
  317. if (NULL == pbstrName)
  318. return E_POINTER;
  319. *pbstrName = SysAllocString(m_bstrCaller);
  320. return (*pbstrName ? S_OK : E_FAIL);
  321. }
  322. HRESULT CIncomingCall::GetAddr(BSTR * pbstrAddr, NM_ADDR_TYPE *puType)
  323. {
  324. // for now we just do the same thing as NM2.11
  325. if ((NULL == pbstrAddr) || (NULL == puType))
  326. return E_POINTER;
  327. *puType = NM_ADDR_UNKNOWN;
  328. *pbstrAddr = SysAllocString(L"");
  329. return (*pbstrAddr ? S_OK : E_FAIL);
  330. }
  331. HRESULT CIncomingCall::GetUserData(REFGUID rguid, BYTE **ppb, ULONG *pcb)
  332. {
  333. return m_UserData.GetUserData(rguid,ppb,pcb);
  334. }
  335. HRESULT CIncomingCall::GetConference(INmConference **ppConference)
  336. {
  337. #ifdef NOTYET
  338. *ppConference = NULL;
  339. CConfObject *pco = ::GetConfObject();
  340. if (NULL != pco)
  341. {
  342. if (pco->GetConfHandle() == m_hConf)
  343. {
  344. *ppConference = pco;
  345. return S_OK;
  346. }
  347. return E_UNEXPECTED;
  348. }
  349. #endif
  350. return S_FALSE;
  351. }
  352. HRESULT CIncomingCall::Accept(void)
  353. {
  354. HRESULT hr = E_FAIL;
  355. // need to make sure that we are still ringing
  356. if (NM_CALL_RING == m_State)
  357. {
  358. m_pOprahNCUI->OnIncomingCallAccepted();
  359. CConfObject *pco = ::GetConfObject();
  360. ASSERT(pco);
  361. if ((NULL != m_hConf) && ( NULL != pco ) && (pco->GetConfHandle() == m_hConf))
  362. {
  363. if (m_fInvite)
  364. {
  365. hr = m_hConf->InviteResponse(TRUE);
  366. }
  367. else
  368. if (pco->GetConfHandle() == m_hConf)
  369. {
  370. hr = m_hConf->JoinResponse(TRUE);
  371. }
  372. }
  373. else if (NULL != m_pConnection)
  374. {
  375. ConnectStateType state;
  376. HRESULT hrTemp = m_pConnection->GetState(&state);
  377. ASSERT(SUCCEEDED(hrTemp));
  378. if(CLS_Alerting == state)
  379. {
  380. hr = m_pConnection->AcceptRejectConnection(CRR_ACCEPT);
  381. }
  382. }
  383. if (S_OK == hr)
  384. {
  385. // notify all call observers that the call was accepted
  386. m_State = NM_CALL_ACCEPTED;
  387. NotifySink((INmConference *) pco, OnNotifyCallAccepted);
  388. }
  389. else
  390. {
  391. // call went away before it was accepted
  392. m_State = NM_CALL_CANCELED;
  393. NotifySink((PVOID)CN_RC_CONFERENCE_ENDED_BEFORE_ACCEPTED, OnNotifyCallError);
  394. if(m_pOprahNCUI)
  395. {
  396. m_pOprahNCUI->OnH323Disconnected(m_pConnection);
  397. }
  398. }
  399. // notify all call observers of the state change
  400. NotifySink((PVOID) m_State, OnNotifyCallStateChanged);
  401. }
  402. else
  403. {
  404. hr = ((NM_CALL_ACCEPTED == m_State) ? S_OK : E_FAIL);
  405. }
  406. return hr;
  407. }
  408. HRESULT CIncomingCall::Reject(void)
  409. {
  410. return Terminate(TRUE);
  411. }
  412. HRESULT CIncomingCall::Cancel(void)
  413. {
  414. return Terminate(FALSE);
  415. }
  416. /* O N N O T I F Y C A L L A C C E P T E D */
  417. /*-------------------------------------------------------------------------
  418. %%Function: OnNotifyCallAccepted
  419. -------------------------------------------------------------------------*/
  420. HRESULT OnNotifyCallAccepted(IUnknown *pCallNotify, PVOID pv, REFIID riid)
  421. {
  422. ASSERT(NULL != pCallNotify);
  423. ((INmCallNotify*)pCallNotify)->Accepted((INmConference *) pv);
  424. return S_OK;
  425. }
  426. CIncomingCallManager::CIncomingCallManager()
  427. {
  428. }
  429. CIncomingCallManager::~CIncomingCallManager()
  430. {
  431. // Empty the call list:
  432. while (!m_CallList.IsEmpty())
  433. {
  434. CIncomingCall* pCall = (CIncomingCall*) m_CallList.RemoveHead();
  435. // Shouldn't have any NULL entries:
  436. ASSERT(pCall);
  437. pCall->Release();
  438. }
  439. }
  440. CREQ_RESPONSETYPE CIncomingCallManager::OnIncomingH323Call(
  441. COprahNCUI *pManager,
  442. IH323Endpoint* pConnection,
  443. P_APP_CALL_SETUP_DATA lpvMNMData)
  444. {
  445. CREQ_RESPONSETYPE resp;
  446. ///////////////////////////////////////////////////
  447. // first we determine the capabilities the caller
  448. ///////////////////////////////////////////////////
  449. BOOL fRequestAutoAccept = FALSE;
  450. // don't assume anything about security
  451. BOOL fT120SecureCall = FALSE;
  452. BOOL fT120NonSecureCall = FALSE;
  453. // assume that the caller can do an invite or a join
  454. BOOL fT120Invite = TRUE;
  455. BOOL fT120Join = TRUE;
  456. // assume that the caller wants a/v
  457. BOOL fRequestAV = TRUE;
  458. // assume that the caller is not NM2.X
  459. BOOL fCallerNM2x = FALSE;
  460. PCC_VENDORINFO pLocalVendorInfo;
  461. PCC_VENDORINFO pRemoteVendorInfo;
  462. if (S_OK == pConnection->GetVersionInfo(&pLocalVendorInfo, &pRemoteVendorInfo))
  463. {
  464. H323VERSION version = GetH323Version(pRemoteVendorInfo);
  465. switch (version)
  466. {
  467. case H323_NetMeeting20:
  468. case H323_NetMeeting21:
  469. case H323_NetMeeting211:
  470. fCallerNM2x = TRUE;
  471. break;
  472. default:
  473. break;
  474. }
  475. }
  476. if ((NULL != lpvMNMData) &&
  477. (lpvMNMData->dwDataSize >= sizeof(DWORD)))
  478. {
  479. DWORD dwUserData = *((LPDWORD)lpvMNMData->lpData);
  480. if (fCallerNM2x)
  481. {
  482. fRequestAutoAccept = (H323UDF_ALREADY_IN_T120_CALL == dwUserData);
  483. fT120SecureCall = FALSE;
  484. fT120NonSecureCall = TRUE;
  485. fT120Invite = TRUE;
  486. fT120Join = TRUE;
  487. fRequestAV = TRUE;
  488. }
  489. else if (0 != dwUserData)
  490. {
  491. fT120SecureCall = (H323UDF_SECURE & dwUserData);
  492. fT120NonSecureCall = !fT120SecureCall;
  493. fT120Invite = (H323UDF_INVITE & dwUserData);
  494. fT120Join = (H323UDF_JOIN & dwUserData);
  495. fRequestAV = ((H323UDF_AUDIO | H323UDF_VIDEO) & dwUserData);
  496. }
  497. }
  498. ////////////////////////////////////////////////
  499. // next we determine the state of us the callee
  500. ////////////////////////////////////////////////
  501. DWORD dwFlags = CRPCF_DATA;
  502. BOOL fAcceptSecure = TRUE;
  503. BOOL fAcceptNonSecure = TRUE;
  504. CConfObject *pco = ::GetConfObject();
  505. if( NULL == pco )
  506. {
  507. ERROR_OUT(( "CConfObject not found" ));
  508. resp = CRR_REJECT;
  509. goto REJECT_CALL;
  510. }
  511. BOOL fInActiveConference = pco->IsConferenceActive();
  512. if (fInActiveConference)
  513. {
  514. //
  515. // If we've reached our limit of attendees, reject it. Also reject
  516. // it if incoming calls are prevented by settings.
  517. //
  518. if (pco->GetNumMembers() >= pco->GetConfMaxParticipants())
  519. {
  520. ASSERT(pco->GetNumMembers() == pco->GetConfMaxParticipants());
  521. WARNING_OUT(("Rejecting incoming H.323 call, reached limit setting of %d",
  522. pco->GetConfMaxParticipants()));
  523. resp = CRR_REJECT;
  524. goto REJECT_CALL;
  525. }
  526. if ((pco->IsHosting() != S_OK) &&
  527. !(pco->GetConfAttendeePermissions() & NM_PERMIT_INCOMINGCALLS))
  528. {
  529. WARNING_OUT(("Rejecting incoming H.323 call, not permitted by meeting setting"));
  530. resp = CRR_REJECT;
  531. goto REJECT_CALL;
  532. }
  533. //
  534. // We're in a conference, the security settings are whatever those
  535. // of the conference are. The user prefs are just for establishing
  536. // the first call.
  537. //
  538. if (pco->IsConfObjSecure())
  539. {
  540. fAcceptNonSecure = FALSE;
  541. }
  542. else
  543. {
  544. fAcceptSecure = FALSE;
  545. }
  546. }
  547. else
  548. {
  549. // we are not in a conference so use the prefered settings
  550. RegEntry reConf(POLICIES_KEY, HKEY_CURRENT_USER);
  551. switch (reConf.GetNumber(REGVAL_POL_SECURITY, DEFAULT_POL_SECURITY))
  552. {
  553. case DISABLED_POL_SECURITY:
  554. fAcceptSecure = FALSE;
  555. break;
  556. case REQUIRED_POL_SECURITY:
  557. fAcceptNonSecure = FALSE;
  558. break;
  559. default:
  560. {
  561. RegEntry rePref(CONFERENCING_KEY, HKEY_CURRENT_USER);
  562. // Is incoming required to be secure by preference?
  563. if (rePref.GetNumber(REGVAL_SECURITY_INCOMING_REQUIRED,
  564. DEFAULT_SECURITY_INCOMING_REQUIRED))
  565. {
  566. fAcceptNonSecure = FALSE;
  567. }
  568. break;
  569. }
  570. }
  571. }
  572. //////////////////////////////////////////
  573. // now we weed out non acceptable callers
  574. //////////////////////////////////////////
  575. if (fCallerNM2x && !fAcceptNonSecure)
  576. {
  577. // NetMeeting 2.X cannot speak security
  578. return CRR_REJECT;
  579. }
  580. if (fT120SecureCall || !fAcceptNonSecure)
  581. {
  582. //
  583. // If we insist on security, or the call is secure and we can
  584. // handle it, the result is secure.
  585. //
  586. dwFlags |= CRPCF_SECURE;
  587. }
  588. else if (fRequestAV && pManager->AcquireAV(pConnection))
  589. {
  590. dwFlags |= CRPCF_VIDEO | CRPCF_AUDIO;
  591. }
  592. if (fCallerNM2x && (0 == ((CRPCF_VIDEO | CRPCF_AUDIO) & dwFlags)))
  593. {
  594. // a/v is not available
  595. // if leading with H323, caller will try again with T120
  596. // else their done
  597. resp = CRR_BUSY;
  598. }
  599. else if (fRequestAutoAccept)
  600. {
  601. // Auto accept this call if it came from NetMeeting 2.X and the caller is telling
  602. // us that we are already in a T.120 call with them. This allows audio after data
  603. // calls to be accepted and also means that you aren't prompted when someone
  604. // switches a/v using the UI's "Send audio and video to..."
  605. if (fInActiveConference)
  606. {
  607. // we most likely have a matching call already but may not be able to find it
  608. CIncomingCall *pCall = new CIncomingCall(pManager, pConnection, lpvMNMData, dwFlags);
  609. // This transfers the implicit reference of pConnection to the
  610. // new CIncomingCall. It will Release().
  611. if (NULL != pCall)
  612. {
  613. // add call to the list of incoming calls
  614. m_CallList.AddTail(pCall);
  615. resp = CRR_ACCEPT;
  616. }
  617. else
  618. {
  619. resp = CRR_REJECT;
  620. }
  621. }
  622. else
  623. {
  624. // we're not really in a T120 call like the caller said. reject this call!
  625. resp = CRR_REJECT;
  626. }
  627. }
  628. else if (!fT120Join && fInActiveConference)
  629. {
  630. // need to change this to CRR_IN_CONFERENCE
  631. resp = CRR_BUSY;
  632. TRACE_OUT(("Can only accept joins; in a conference"));
  633. }
  634. else if (fT120Join && !fT120Invite && !fInActiveConference)
  635. {
  636. resp = CRR_REJECT;
  637. TRACE_OUT(("Cannot accept H323 Join Request; not in a conference"));
  638. }
  639. else if (!fRequestAV && !fT120Join && !fT120Invite && !fInActiveConference)
  640. {
  641. resp = CRR_REJECT;
  642. TRACE_OUT(("No av/ or data; reject"));
  643. }
  644. else if (fT120SecureCall && !fAcceptSecure)
  645. {
  646. resp = CRR_SECURITY_DENIED;
  647. TRACE_OUT(("Can not accept secure H323 Call"));
  648. }
  649. else if (fT120NonSecureCall && !fAcceptNonSecure)
  650. {
  651. resp = CRR_SECURITY_DENIED;
  652. TRACE_OUT(("Can not accept non secure H323 Call"));
  653. }
  654. else
  655. {
  656. CIncomingCall *pCall = new CIncomingCall(pManager, pConnection, lpvMNMData, dwFlags);
  657. // This transfers the implicit reference of pConnection to the
  658. // new CIncomingCall. It will Release().
  659. if (NULL != pCall)
  660. {
  661. if (g_guidLocalNodeId != *pCall->GetNodeGuid())
  662. {
  663. // Check for multiple calls from the same caller
  664. if (!MatchActiveCaller(pCall->GetNodeGuid()))
  665. {
  666. // add call to the list of incoming calls
  667. m_CallList.AddTail(pCall);
  668. pManager->OnIncomingCallCreated(pCall);
  669. // Don't ring on data only calls.
  670. // Wait for T120 call to come in.
  671. if (pCall->IsDataOnly())
  672. {
  673. resp = CRR_ACCEPT;
  674. }
  675. else
  676. {
  677. pCall->Ring();
  678. resp = CRR_ASYNC;
  679. }
  680. }
  681. else
  682. {
  683. // we're already in call with this person
  684. delete pCall;
  685. resp = CRR_REJECT;
  686. }
  687. }
  688. else
  689. {
  690. // we somehow called ourself
  691. delete pCall;
  692. resp = CRR_REJECT;
  693. }
  694. }
  695. else
  696. {
  697. resp = CRR_REJECT;
  698. }
  699. }
  700. REJECT_CALL:
  701. if ((resp != CRR_ACCEPT) && (resp != CRR_ASYNC))
  702. {
  703. // make sure we are not holding on to AV
  704. pManager->ReleaseAV(pConnection);
  705. }
  706. return resp;
  707. }
  708. VOID CIncomingCallManager::OnH323Connected(IH323Endpoint* lpConnection)
  709. {
  710. POSITION pos = m_CallList.GetHeadPosition();
  711. POSITION posItem;
  712. while (posItem = pos)
  713. {
  714. CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos);
  715. if ((NULL != pCall) &&
  716. (lpConnection == pCall->GetH323Connection()))
  717. {
  718. pCall->OnH323Connected();
  719. break;
  720. }
  721. }
  722. }
  723. VOID CIncomingCallManager::OnH323Disconnected(IH323Endpoint * lpConnection)
  724. {
  725. POSITION pos = m_CallList.GetHeadPosition();
  726. POSITION posItem;
  727. while (posItem = pos)
  728. {
  729. CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos);
  730. if ((NULL != pCall) &&
  731. (lpConnection == pCall->GetH323Connection()))
  732. {
  733. if (S_OK == pCall->OnH323Disconnected())
  734. {
  735. m_CallList.RemoveAt(posItem);
  736. pCall->Release();
  737. }
  738. break;
  739. }
  740. }
  741. }
  742. VOID CIncomingCallManager::OnT120ConferenceEnded(CONF_HANDLE hConference)
  743. {
  744. POSITION pos = m_CallList.GetHeadPosition();
  745. POSITION posItem;
  746. while (posItem = pos)
  747. {
  748. CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos);
  749. if ((NULL != pCall) &&
  750. (hConference == pCall->GetConfHandle()))
  751. {
  752. if (S_OK == pCall->OnT120ConferenceEnded())
  753. {
  754. m_CallList.RemoveAt(posItem);
  755. pCall->Release();
  756. }
  757. }
  758. }
  759. }
  760. HRESULT CIncomingCallManager::OnIncomingT120Call(
  761. COprahNCUI *pManager,
  762. BOOL fInvite,
  763. CONF_HANDLE hConf,
  764. PCWSTR pcwszNodeName,
  765. PUSERDATAINFO pUserDataInfoEntries,
  766. UINT cUserDataEntries,
  767. BOOL fSecure)
  768. {
  769. HRESULT hr = S_OK;
  770. // need to scan through all accepted calls passing the T120 params
  771. // if someone returns S_OK, we accept the call
  772. CIncomingCall *pMatchedCall = NULL;
  773. GUID* pguidNodeID = GetGuidFromT120UserData(pUserDataInfoEntries, cUserDataEntries);
  774. if (pguidNodeID)
  775. {
  776. pMatchedCall = MatchAcceptedCaller(pguidNodeID);
  777. }
  778. else
  779. {
  780. pMatchedCall = MatchAcceptedCaller(pcwszNodeName);
  781. }
  782. if (pMatchedCall)
  783. {
  784. pMatchedCall->SetConfHandle(hConf);
  785. // we should always ring the client when the call is secure
  786. // or when we haven't rang already
  787. if (!pMatchedCall->DidUserAccept())
  788. {
  789. pMatchedCall->OnIncomingT120Call(fInvite,
  790. pUserDataInfoEntries,
  791. cUserDataEntries);
  792. pMatchedCall->Ring();
  793. }
  794. else
  795. {
  796. if (fInvite)
  797. {
  798. hr = hConf->InviteResponse(TRUE);
  799. }
  800. else
  801. {
  802. hr = hConf->JoinResponse(TRUE);
  803. }
  804. }
  805. pMatchedCall->Release();
  806. }
  807. else
  808. {
  809. CIncomingCall *pCall = new CIncomingCall(pManager,
  810. fInvite,
  811. hConf,
  812. pcwszNodeName,
  813. pUserDataInfoEntries,
  814. cUserDataEntries);
  815. if (NULL != pCall)
  816. {
  817. // currently we don't add T120 calls to the call list
  818. pManager->OnIncomingCallCreated(pCall);
  819. pCall->Ring();
  820. // we're not holding on to the call so release it
  821. pCall->Release();
  822. }
  823. else
  824. {
  825. // unable to accept call
  826. if (fInvite)
  827. {
  828. hr = hConf->InviteResponse(FALSE);
  829. }
  830. else
  831. {
  832. hConf->JoinResponse(FALSE);
  833. }
  834. hr = E_OUTOFMEMORY;
  835. }
  836. }
  837. return hr;
  838. }
  839. CIncomingCall* CIncomingCallManager::MatchAcceptedCaller(PCWSTR pcwszNodeName)
  840. {
  841. // we won't auto accept anyone who is already in the roster
  842. CNmMember* pMember = PDataMemberFromName(pcwszNodeName);
  843. if (NULL != pMember)
  844. {
  845. return FALSE;
  846. }
  847. POSITION pos = m_CallList.GetHeadPosition();
  848. while (pos)
  849. {
  850. CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos);
  851. if ((NULL != pCall) &&
  852. pCall->MatchAcceptedCaller(pcwszNodeName))
  853. {
  854. TRACE_OUT(("Matched accepted caller"));
  855. pCall->AddRef();
  856. return pCall;
  857. }
  858. }
  859. return NULL;
  860. }
  861. CIncomingCall* CIncomingCallManager::MatchAcceptedCaller(GUID* pguidNodeId)
  862. {
  863. if (GUID_NULL == *pguidNodeId)
  864. {
  865. return FALSE;
  866. }
  867. // we wont auto accept anyone who is already in the roster
  868. CNmMember* pMember = PMemberFromNodeGuid(*pguidNodeId);
  869. if ((NULL != pMember) && pMember->FHasData())
  870. {
  871. return FALSE;
  872. }
  873. POSITION pos = m_CallList.GetHeadPosition();
  874. while (pos)
  875. {
  876. CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos);
  877. if ((NULL != pCall) &&
  878. pCall->MatchAcceptedCaller(pguidNodeId))
  879. {
  880. TRACE_OUT(("Matched accepted caller"));
  881. pCall->AddRef();
  882. return pCall;
  883. }
  884. }
  885. return NULL;
  886. }
  887. CIncomingCall* CIncomingCallManager::MatchActiveCaller(GUID* pguidNodeId)
  888. {
  889. if (GUID_NULL == *pguidNodeId)
  890. {
  891. return FALSE;
  892. }
  893. POSITION pos = m_CallList.GetHeadPosition();
  894. while (pos)
  895. {
  896. CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos);
  897. if ((NULL != pCall) &&
  898. pCall->MatchActiveCaller(pguidNodeId))
  899. {
  900. TRACE_OUT(("Matched active caller"));
  901. pCall->AddRef();
  902. return pCall;
  903. }
  904. }
  905. return NULL;
  906. }
  907. GUID* CIncomingCallManager::GetGuidFromT120UserData(
  908. PUSERDATAINFO pUserDataInfoEntries,
  909. UINT cUserDataEntries)
  910. {
  911. if (cUserDataEntries > 0)
  912. {
  913. ASSERT(pUserDataInfoEntries);
  914. for (UINT u = 0; u < cUserDataEntries; u++)
  915. {
  916. if ((*pUserDataInfoEntries[u].pGUID == g_csguidNodeIdTag) &&
  917. (pUserDataInfoEntries[u].cbData == sizeof(GUID)))
  918. {
  919. return (GUID*)pUserDataInfoEntries[u].pData;
  920. }
  921. }
  922. }
  923. return NULL;
  924. }
  925. VOID CIncomingCallManager::CancelCalls()
  926. {
  927. DebugEntry(CIncomingCallManager::CancelCalls);
  928. POSITION pos = m_CallList.GetHeadPosition();
  929. POSITION posItem;
  930. while (posItem = pos)
  931. {
  932. CIncomingCall* pCall = (CIncomingCall*) m_CallList.GetNext(pos);
  933. if (NULL != pCall)
  934. {
  935. if (SUCCEEDED(pCall->Terminate(FALSE)))
  936. {
  937. m_CallList.RemoveAt(posItem);
  938. pCall->Release();
  939. }
  940. }
  941. }
  942. DebugExitVOID(CIncomingCallManager::CancelCalls);
  943. }