Source code of Windows XP (NT5)
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.

1283 lines
42 KiB

  1. /****************************************************************************
  2. *
  3. * $Archive: S:/STURGEON/SRC/CALLCONT/VCS/q931man.c_v $
  4. *
  5. * INTEL Corporation Prorietary Information
  6. *
  7. * This listing is supplied under the terms of a license agreement
  8. * with INTEL Corporation and may not be copied nor disclosed except
  9. * in accordance with the terms of that agreement.
  10. *
  11. * Copyright (c) 1993-1994 Intel Corporation.
  12. *
  13. * $Revision: 1.138.1.1 $
  14. * $Date: 23 Jun 1997 15:58:12 $
  15. * $Author: MANDREWS $
  16. *
  17. * Deliverable:
  18. *
  19. * Abstract:
  20. *
  21. *
  22. * Notes:
  23. *
  24. ***************************************************************************/
  25. #pragma warning ( disable : 4100 4115 4201 4214 )
  26. #include <nt.h>
  27. #include <ntrtl.h>
  28. #include <nturtl.h>
  29. #include <windows.h>
  30. #pragma warning ( default : 4115 4201 4214 )
  31. #include "apierror.h"
  32. #include "incommon.h"
  33. #include "callcont.h"
  34. #include "q931.h"
  35. #include "ccmain.h"
  36. #include "listman.h"
  37. #include "q931man.h"
  38. #include "userman.h"
  39. #include "callman.h"
  40. #include "confman.h"
  41. #include "h245man.h"
  42. #include "linkapi.h"
  43. #include "ccutils.h"
  44. extern CALL_CONTROL_STATE CallControlState;
  45. extern THREADCOUNT ThreadCount;
  46. extern CC_CONFERENCEID InvalidConferenceID;
  47. HRESULT InitQ931Manager()
  48. {
  49. return CC_OK;
  50. }
  51. HRESULT DeInitQ931Manager()
  52. {
  53. return CC_OK;
  54. }
  55. DWORD _GenerateListenCallback( PLISTEN pListen,
  56. HQ931CALL hQ931Call,
  57. PCSS_CALL_INCOMING pCallIncomingData)
  58. {
  59. HRESULT status;
  60. CC_HLISTEN hListen;
  61. CC_LISTEN_CALLBACK_PARAMS ListenCallbackParams;
  62. PCALL pCall;
  63. CC_HCALL hCall;
  64. ASSERT(pListen != NULL);
  65. ASSERT(pCallIncomingData != NULL);
  66. hListen = pListen->hListen;
  67. status = AllocAndLockCall(
  68. &hCall, // pointer to call handle
  69. CC_INVALID_HANDLE, // conference handle
  70. hQ931Call, // Q931 call handle
  71. CC_INVALID_HANDLE, // Q931 call handle for third party invitor
  72. pCallIncomingData->pCalleeAliasList,
  73. pCallIncomingData->pCallerAliasList,
  74. NULL, // pPeerExtraAliasNames
  75. NULL, // pPeerExtension
  76. NULL, // local non-standard data
  77. pCallIncomingData->pNonStandardData, // remote non-standard data
  78. NULL, // local display value
  79. pCallIncomingData->pszDisplay, // remote display value
  80. pCallIncomingData->pSourceEndpointType->pVendorInfo,// remote vendor info
  81. pCallIncomingData->pLocalAddr, // local address
  82. pCallIncomingData->pCallerAddr, // connect address
  83. NULL, // destination address
  84. pCallIncomingData->pSourceAddr, // source call signal address
  85. CALLEE, // call direction
  86. pCallIncomingData->bCallerIsMC,
  87. 0, // user token; user will specify in AcceptRejectCall
  88. INCOMING, // initial call state
  89. 0, // bandwidth
  90. &pCallIncomingData->ConferenceID, // conference ID
  91. &pCall); // pointer to call object
  92. if (status != CC_OK) {
  93. UnlockListen(pListen);
  94. Q931RejectCall(hQ931Call, // Q931 call handle
  95. CC_REJECT_UNDEFINED_REASON, // reject reason
  96. &pCallIncomingData->ConferenceID,
  97. NULL, // alternate address
  98. NULL); // non-standard data
  99. return 1;
  100. }
  101. // Map from Q.931 goals to Call Control goals
  102. switch (pCallIncomingData->wGoal) {
  103. case CSG_JOIN:
  104. ListenCallbackParams.wGoal = CC_GOAL_JOIN;
  105. break;
  106. case CSG_CREATE:
  107. ListenCallbackParams.wGoal = CC_GOAL_CREATE;
  108. break;
  109. case CSG_INVITE:
  110. ListenCallbackParams.wGoal = CC_GOAL_INVITE;
  111. break;
  112. }
  113. ListenCallbackParams.hCall = hCall;
  114. ListenCallbackParams.pCallerAliasNames = pCallIncomingData->pCallerAliasList;
  115. ListenCallbackParams.pCalleeAliasNames = pCallIncomingData->pCalleeAliasList;
  116. ListenCallbackParams.pNonStandardData = pCallIncomingData->pNonStandardData;
  117. ListenCallbackParams.pszDisplay = pCallIncomingData->pszDisplay;
  118. ListenCallbackParams.pVendorInfo = NULL;
  119. ListenCallbackParams.ConferenceID = pCallIncomingData->ConferenceID;
  120. ListenCallbackParams.pCallerAddr = pCallIncomingData->pCallerAddr;
  121. ListenCallbackParams.pCalleeAddr = pCallIncomingData->pLocalAddr;
  122. ListenCallbackParams.dwListenToken = pListen->dwListenToken;
  123. UnlockCall(pCall);
  124. // Invoke the user callback -- the listen object is locked during the callback,
  125. // but the associated call object is unlocked (to prevent deadlock if
  126. // CC_AcceptCall() or CC_RejectCall() is called during the callback from a
  127. // different thread, and the callback thread blocks pending completion of
  128. // CC_AcceptCall() or CC_RejectCall())
  129. InvokeUserListenCallback(pListen,
  130. CC_OK,
  131. &ListenCallbackParams);
  132. // Need to validate the listen handle; the associated object may have been
  133. // deleted during the user callback by this thread
  134. if (ValidateListen(hListen) == CC_OK)
  135. UnlockListen(pListen);
  136. status = LockCall(hCall, &pCall);
  137. if ((status == CC_OK) && (pCall->CallState == INCOMING)) {
  138. UnlockCall(pCall);
  139. return 0; // cause a ringing condition to occur
  140. } else {
  141. // call object has been deleted, or exists in a non-incoming state
  142. if (status == CC_OK)
  143. // call object exists in a non-incoming state; AcceptRejectCall
  144. // may have been invoked from the user callback
  145. UnlockCall(pCall);
  146. // return 1; // don't cause a ringing condition to occur
  147. }
  148. // // We should never reach this point
  149. // ASSERT(0);
  150. return 1;
  151. }
  152. DWORD _Q931CallIncoming( HQ931CALL hQ931Call,
  153. CC_HLISTEN hListen,
  154. PCSS_CALL_INCOMING pCallIncomingData)
  155. {
  156. HRESULT status;
  157. PLISTEN pListen;
  158. PCONFERENCE pConference;
  159. PCALL pCall;
  160. CC_HCALL hCall;
  161. ASSERT(hListen != CC_INVALID_HANDLE);
  162. ASSERT(pCallIncomingData != NULL);
  163. ASSERT(!EqualConferenceIDs(&pCallIncomingData->ConferenceID, &InvalidConferenceID));
  164. if ((pCallIncomingData->wGoal != CSG_CREATE) &&
  165. (pCallIncomingData->wGoal != CSG_JOIN) &&
  166. (pCallIncomingData->wGoal != CSG_INVITE)) {
  167. Q931RejectCall(hQ931Call, // Q931 call handle
  168. CC_REJECT_UNDEFINED_REASON, // reject reason
  169. &pCallIncomingData->ConferenceID,
  170. NULL, // alternate address
  171. NULL); // non-standard data
  172. return 1;
  173. }
  174. status = LockListen(hListen, &pListen);
  175. if (status != CC_OK) {
  176. // the listen was presumably cancelled by the user,
  177. // but we haven't informed Call Setup yet
  178. Q931RejectCall(hQ931Call, // Q931 call handle
  179. CC_REJECT_UNDEFINED_REASON, // reject reason
  180. &pCallIncomingData->ConferenceID,
  181. NULL, // alternate address
  182. NULL); // non-standard data
  183. return 1;
  184. }
  185. // Look for wConferenceID in conference list
  186. status = LockConferenceID(&pCallIncomingData->ConferenceID, &pConference);
  187. if (status == CC_OK) {
  188. // We found a matching conference ID
  189. if ((pConference->bDeferredDelete) &&
  190. ((pConference->bAutoAccept == FALSE) ||
  191. ((pConference->tsMultipointController == TS_TRUE) &&
  192. (pCallIncomingData->bCallerIsMC == TRUE)))) {
  193. UnlockListen(pListen);
  194. UnlockConference(pConference);
  195. Q931RejectCall(hQ931Call, // Q931 call handle
  196. CC_REJECT_UNDEFINED_REASON, // reject reason
  197. &pCallIncomingData->ConferenceID,
  198. NULL, // alternate address
  199. NULL); // non-standard data
  200. return 1;
  201. } else {
  202. if (pConference->tsMultipointController == TS_TRUE) {
  203. if ((pCallIncomingData->pCalleeDestAddr == NULL) ||
  204. ((pCallIncomingData->pCalleeDestAddr != NULL) &&
  205. (EqualAddrs(pCallIncomingData->pLocalAddr,
  206. pCallIncomingData->pCalleeDestAddr)))) {
  207. switch (pCallIncomingData->wGoal) {
  208. case CSG_CREATE:
  209. UnlockListen(pListen);
  210. UnlockConference(pConference);
  211. Q931RejectCall(hQ931Call, // Q931 call handle
  212. CC_REJECT_UNDEFINED_REASON, // reject reason
  213. &pCallIncomingData->ConferenceID,
  214. NULL, // alternate address
  215. NULL); // non-standard data
  216. return 1;
  217. case CSG_JOIN:
  218. if ((pConference->bDeferredDelete) &&
  219. (pConference->bAutoAccept == TRUE)) {
  220. // Auto accept
  221. status = AllocAndLockCall(
  222. &hCall, // pointer to call handle
  223. pConference->hConference, // conference handle
  224. hQ931Call, // Q931 call handle
  225. CC_INVALID_HANDLE, // Q931 call handle for third party invitor
  226. pCallIncomingData->pCalleeAliasList,
  227. pCallIncomingData->pCallerAliasList,
  228. NULL, // pPeerExtraAliasNames
  229. NULL, // pPeerExtension
  230. NULL, // local non-standard data
  231. pCallIncomingData->pNonStandardData, // remote non-standard data
  232. NULL, // local display value
  233. pCallIncomingData->pszDisplay, // remote display value
  234. pCallIncomingData->pSourceEndpointType->pVendorInfo,// remote vendor info
  235. pCallIncomingData->pLocalAddr, // local address
  236. pCallIncomingData->pCallerAddr, // connect address
  237. NULL, // destination address
  238. pCallIncomingData->pSourceAddr, // source call signal address
  239. CALLEE, // call type
  240. pCallIncomingData->bCallerIsMC,
  241. 0, // user token; user will specify in AcceptRejectCall
  242. INCOMING, // initial call state
  243. 0, // bandwidth
  244. &pCallIncomingData->ConferenceID, // conference ID
  245. &pCall); // pointer to call object
  246. if (status != CC_OK) {
  247. UnlockListen(pListen);
  248. UnlockConference(pConference);
  249. Q931RejectCall(hQ931Call, // Q931 call handle
  250. CC_REJECT_UNDEFINED_REASON, // reject reason
  251. &pCallIncomingData->ConferenceID,
  252. NULL, // alternate address
  253. NULL); // non-standard data
  254. return 1;
  255. }
  256. AcceptCall(pCall, pConference);
  257. return 1; // Don't send back a RINGING indication
  258. } else {
  259. UnlockConference(pConference);
  260. return _GenerateListenCallback(pListen,
  261. hQ931Call,
  262. pCallIncomingData);
  263. }
  264. case CSG_INVITE:
  265. UnlockListen(pListen);
  266. UnlockConference(pConference);
  267. Q931RejectCall(hQ931Call, // Q931 call handle
  268. CC_REJECT_IN_CONF, // reject reason
  269. &pCallIncomingData->ConferenceID,
  270. NULL, // alternate address
  271. NULL); // non-standard data
  272. return 1;
  273. } // switch (wGoal)
  274. } else { // connect addr != destination addr
  275. switch (pCallIncomingData->wGoal) {
  276. case CSG_CREATE:
  277. case CSG_JOIN:
  278. UnlockListen(pListen);
  279. UnlockConference(pConference);
  280. Q931RejectCall(hQ931Call, // Q931 call handle
  281. CC_REJECT_UNDEFINED_REASON, // reject reason
  282. &pCallIncomingData->ConferenceID,
  283. NULL, // alternate address
  284. NULL); // non-standard data
  285. return 1;
  286. case CSG_INVITE:
  287. // 3rd party invite
  288. if (pCallIncomingData->bCallerIsMC == TRUE) {
  289. UnlockListen(pListen);
  290. UnlockConference(pConference);
  291. Q931RejectCall(hQ931Call, // Q931 call handle
  292. CC_REJECT_UNDEFINED_REASON, // reject reason
  293. &pCallIncomingData->ConferenceID,
  294. NULL, // alternate address
  295. NULL); // non-standard data
  296. return 1;
  297. }
  298. status = AllocAndLockCall(
  299. &hCall, // pointer to call handle
  300. pConference->hConference, // conference handle
  301. CC_INVALID_HANDLE, // Q931 call handle
  302. hQ931Call, // Q931 call handle for third party invitor
  303. pCallIncomingData->pCallerAliasList, // local alias names
  304. pCallIncomingData->pCalleeAliasList, // remote alias names
  305. NULL, // pPeerExtraAliasNames
  306. NULL, // pPeerExtension
  307. pCallIncomingData->pNonStandardData, // local non-standard data
  308. NULL, // remote non-standard data
  309. pCallIncomingData->pszDisplay, // local display value
  310. NULL, // remote display value
  311. NULL, // remote vendor info
  312. NULL, // local address
  313. pCallIncomingData->pCalleeDestAddr, // connect address
  314. pCallIncomingData->pCalleeDestAddr, // destination address
  315. pCallIncomingData->pSourceAddr, // source call signal address
  316. THIRD_PARTY_INTERMEDIARY, // call type
  317. TRUE, // caller (this endpoint) is MC
  318. 0, // user token; user will specify in AcceptRejectCall
  319. PLACED, // initial call state
  320. 0, // bandwidth
  321. &pCallIncomingData->ConferenceID, // conference ID
  322. &pCall); // pointer to call object
  323. if (status != CC_OK) {
  324. UnlockListen(pListen);
  325. UnlockConference(pConference);
  326. Q931RejectCall(hQ931Call, // Q931 call handle
  327. CC_REJECT_UNDEFINED_REASON, // reject reason
  328. &pCallIncomingData->ConferenceID,
  329. NULL, // alternate address
  330. NULL); // non-standard data
  331. return 1;
  332. }
  333. PlaceCall(pCall, pConference);
  334. UnlockCall(pCall);
  335. UnlockConference(pConference);
  336. return 1; // Don't send back a RINGING indication
  337. } // switch (wGoal)
  338. }
  339. } else { // pConference->tsMultipointController != TS_TRUE
  340. if ((pCallIncomingData->pCalleeDestAddr == NULL) ||
  341. ((pCallIncomingData->pCalleeDestAddr != NULL) &&
  342. (EqualAddrs(pCallIncomingData->pLocalAddr,
  343. pCallIncomingData->pCalleeDestAddr)))) {
  344. switch (pCallIncomingData->wGoal) {
  345. case CSG_CREATE:
  346. UnlockListen(pListen);
  347. UnlockConference(pConference);
  348. Q931RejectCall(hQ931Call, // Q931 call handle
  349. CC_REJECT_UNDEFINED_REASON, // reject reason
  350. &pCallIncomingData->ConferenceID,
  351. NULL, // alternate address
  352. NULL); // non-standard data
  353. return 1;
  354. case CSG_JOIN:
  355. case CSG_INVITE:
  356. UnlockConference(pConference);
  357. return _GenerateListenCallback(pListen,
  358. hQ931Call,
  359. pCallIncomingData);
  360. } // switch (wGoal)
  361. } else { // connect addr != destination addr
  362. UnlockListen(pListen);
  363. UnlockConference(pConference);
  364. Q931RejectCall(hQ931Call, // Q931 call handle
  365. CC_REJECT_UNDEFINED_REASON, // reject reason
  366. &pCallIncomingData->ConferenceID,
  367. NULL, // alternate address
  368. NULL); // non-standard data
  369. return 1;
  370. } // connect addr != destination addr
  371. } // pConference->tsMultipointController != TS_TRUE
  372. } // Matching conference ID
  373. } else if (status == CC_BAD_PARAM) {
  374. // This is OK; it simply means that we did not find a matching conference ID
  375. if (((pCallIncomingData->pCalleeDestAddr != NULL) &&
  376. (EqualAddrs(pCallIncomingData->pLocalAddr,
  377. pCallIncomingData->pCalleeDestAddr))) ||
  378. (pCallIncomingData->pCalleeDestAddr == NULL)) {
  379. return _GenerateListenCallback(pListen,
  380. hQ931Call,
  381. pCallIncomingData);
  382. } else { // connect addr != destination addr
  383. UnlockListen(pListen);
  384. Q931RejectCall(hQ931Call, // Q931 call handle
  385. CC_REJECT_UNDEFINED_REASON, // reject reason
  386. &pCallIncomingData->ConferenceID,
  387. NULL, // alternate address
  388. NULL); // non-standard data
  389. return 1;
  390. }
  391. } else { // fatal error in LockConference
  392. UnlockListen(pListen);
  393. Q931RejectCall(hQ931Call, // Q931 call handle
  394. CC_REJECT_UNDEFINED_REASON, // reject reason
  395. &pCallIncomingData->ConferenceID,
  396. NULL, // alternate address
  397. NULL); // non-standard data
  398. return 1;
  399. }
  400. // We should never reach this point
  401. ASSERT(0);
  402. return 1;
  403. }
  404. DWORD _Q931CallRemoteHangup( HQ931CALL hQ931Call,
  405. CC_HLISTEN hListen,
  406. CC_HCALL hCall)
  407. {
  408. CC_LISTEN_CALLBACK_PARAMS ListenCallbackParams;
  409. PCALL pCall;
  410. PLISTEN pListen;
  411. if (hCall == CC_INVALID_HANDLE) {
  412. // Either we've already informed the user of the hangup,
  413. // or the user has not yet accepted or rejected the incoming
  414. // call request
  415. ASSERT(hListen != CC_INVALID_HANDLE);
  416. if (LockQ931Call(hCall, hQ931Call, &pCall) != CC_OK)
  417. return 0;
  418. hCall = pCall->hCall;
  419. if (pCall->hConference != CC_INVALID_HANDLE) {
  420. UnlockCall(pCall);
  421. // XXX -- need bHangupReason
  422. ProcessRemoteHangup(hCall, hQ931Call, CC_REJECT_NORMAL_CALL_CLEARING);
  423. return 0;
  424. }
  425. if (LockListen(hListen, &pListen) != CC_OK) {
  426. FreeCall(pCall);
  427. return 0;
  428. }
  429. MarkCallForDeletion(pCall);
  430. ListenCallbackParams.hCall = pCall->hCall;
  431. ListenCallbackParams.pCallerAliasNames = pCall->pPeerAliasNames;
  432. ListenCallbackParams.pCalleeAliasNames = pCall->pLocalAliasNames;
  433. ListenCallbackParams.pNonStandardData = pCall->pPeerNonStandardData;
  434. ListenCallbackParams.pszDisplay = pCall->pszPeerDisplay;
  435. ListenCallbackParams.pVendorInfo = pCall->pPeerVendorInfo;
  436. ListenCallbackParams.wGoal = CC_GOAL_CREATE; // igonred in this callback
  437. ListenCallbackParams.ConferenceID = pCall->ConferenceID;
  438. ListenCallbackParams.pCallerAddr = pCall->pQ931PeerConnectAddr;
  439. ListenCallbackParams.pCalleeAddr = pCall->pQ931LocalConnectAddr;
  440. ListenCallbackParams.dwListenToken = pListen->dwListenToken;
  441. InvokeUserListenCallback(pListen,
  442. CC_PEER_CANCEL,
  443. &ListenCallbackParams);
  444. // Need to validate the listen and call handles; the associated objects may
  445. // have been deleted during the user callback by this thread
  446. if (ValidateListen(hListen) == CC_OK)
  447. UnlockListen(pListen);
  448. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  449. FreeCall(pCall);
  450. } else
  451. // XXX -- need bHangupReason
  452. ProcessRemoteHangup(hCall, hQ931Call, CC_REJECT_NORMAL_CALL_CLEARING);
  453. return 0;
  454. }
  455. DWORD _Q931CallRejected( HQ931CALL hQ931Call,
  456. CC_HCALL hCall,
  457. PCSS_CALL_REJECTED pCallRejectedData)
  458. {
  459. PCALL pCall;
  460. CC_HCONFERENCE hConference;
  461. PCONFERENCE pConference;
  462. HRESULT status;
  463. CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams;
  464. HQ931CALL hQ931CallInvitor;
  465. CC_ENDPOINTTYPE SourceEndpointType;
  466. CALLTYPE CallType;
  467. CC_CONFERENCEID ConferenceID;
  468. CC_ADDR SourceAddr;
  469. WORD wNumCalls;
  470. WORD wQ931Goal;
  471. WORD wQ931CallType;
  472. status = LockCall(hCall, &pCall);
  473. if (status != CC_OK)
  474. return 0;
  475. CallType = pCall->CallType;
  476. ConferenceID = pCall->ConferenceID;
  477. if ((pCall->hQ931Call != hQ931Call) ||
  478. ((pCall->CallState != PLACED) && (pCall->CallState != RINGING))) {
  479. // The peer must be in a bad state; we don't expect to receive this message now
  480. UnlockCall(pCall);
  481. return 0;
  482. }
  483. if (CallType == THIRD_PARTY_INTERMEDIARY) {
  484. hQ931CallInvitor = pCall->hQ931CallInvitor;
  485. FreeCall(pCall);
  486. if (hQ931CallInvitor != CC_INVALID_HANDLE)
  487. Q931RejectCall(hQ931CallInvitor,
  488. pCallRejectedData->bRejectReason,
  489. &ConferenceID,
  490. NULL, // alternate address
  491. NULL); // non-standard data
  492. return 0;
  493. }
  494. if (pCall->hConference == CC_INVALID_HANDLE) {
  495. // Call is not attached to a conference
  496. FreeCall(pCall);
  497. return 0;
  498. }
  499. UnlockCall(pCall);
  500. status = LockCallAndConference(hCall, &pCall, &pConference);
  501. if (status != CC_OK)
  502. return 0;
  503. ConnectCallbackParams.pNonStandardData = pCallRejectedData->pNonStandardData;
  504. ConnectCallbackParams.pszPeerDisplay = NULL;
  505. ConnectCallbackParams.bRejectReason = pCallRejectedData->bRejectReason;
  506. ConnectCallbackParams.pTermCapList = NULL;
  507. ConnectCallbackParams.pH2250MuxCapability = NULL;
  508. ConnectCallbackParams.pTermCapDescriptors = NULL;
  509. ConnectCallbackParams.pLocalAddr = pCall->pQ931LocalConnectAddr;
  510. if (pCall->pQ931DestinationAddr == NULL)
  511. ConnectCallbackParams.pPeerAddr = pCall->pQ931PeerConnectAddr;
  512. else
  513. ConnectCallbackParams.pPeerAddr = pCall->pQ931DestinationAddr;
  514. ConnectCallbackParams.pVendorInfo = pCall->pPeerVendorInfo;
  515. if (pCallRejectedData->bRejectReason == CC_REJECT_ROUTE_TO_MC)
  516. {
  517. ConnectCallbackParams.bMultipointConference = TRUE;
  518. wQ931Goal = CSG_JOIN;
  519. wQ931CallType = CC_CALLTYPE_N_N;
  520. }
  521. else
  522. {
  523. // Goal and CallType need to be changed for multipoint support.
  524. ConnectCallbackParams.bMultipointConference = FALSE;
  525. wQ931Goal = CSG_CREATE;
  526. wQ931CallType = CC_CALLTYPE_PT_PT;
  527. }
  528. ConnectCallbackParams.pConferenceID = &pCallRejectedData->ConferenceID;
  529. if (pCallRejectedData->bRejectReason == CC_REJECT_ROUTE_TO_MC)
  530. ConnectCallbackParams.pMCAddress = pCallRejectedData->pAlternateAddr;
  531. else
  532. ConnectCallbackParams.pMCAddress = NULL;
  533. ConnectCallbackParams.pAlternateAddress = pCallRejectedData->pAlternateAddr;
  534. ConnectCallbackParams.dwUserToken = pCall->dwUserToken;
  535. // save a copy of the conference handle; we'll need it to validate
  536. // the conference object after returning from the user callback
  537. hConference = pConference->hConference;
  538. if (((pCallRejectedData->bRejectReason == CC_REJECT_ROUTE_TO_MC) ||
  539. (pCallRejectedData->bRejectReason == CC_REJECT_CALL_FORWARDED) ||
  540. (pCallRejectedData->bRejectReason == CC_REJECT_ROUTE_TO_GATEKEEPER)) &&
  541. (EqualConferenceIDs(&pCallRejectedData->ConferenceID, &pCall->ConferenceID)) &&
  542. (pCallRejectedData->pAlternateAddr != NULL)) {
  543. // XXX - In order to be H.323 compliant here, we need to re-permission this call
  544. // through the gatekeeper because:
  545. // 1. The rerouted call may be going to another gatekeeper zone.
  546. // 2. The alternate address may be NULL, and we may have to resolve the
  547. // alternate alias name list through the gatekeeper
  548. SourceEndpointType.pVendorInfo = pConference->pVendorInfo;
  549. SourceEndpointType.bIsTerminal = TRUE;
  550. SourceEndpointType.bIsGateway = FALSE;
  551. // Cause our local Q.931 connect address to be placed in the
  552. // Q.931 setup-UUIE sourceAddress field
  553. SourceAddr.nAddrType = CC_IP_BINARY;
  554. SourceAddr.bMulticast = FALSE;
  555. SourceAddr.Addr.IP_Binary.dwAddr = 0;
  556. SourceAddr.Addr.IP_Binary.wPort = 0;
  557. status = Q931PlaceCall(&pCall->hQ931Call, // Q931 call handle
  558. pCall->pszLocalDisplay,
  559. pCall->pLocalAliasNames,
  560. pCall->pPeerAliasNames,
  561. pCall->pPeerExtraAliasNames, // pExtraAliasList
  562. pCall->pPeerExtension, // pExtensionAliasItem
  563. pCall->pLocalNonStandardData,// non-standard data
  564. &SourceEndpointType,
  565. NULL, // pszCalledPartyNumber
  566. pCallRejectedData->pAlternateAddr, // connect address
  567. pCall->pQ931DestinationAddr, // destination address
  568. NULL, // source address
  569. FALSE, // bIsMC
  570. &pCall->ConferenceID, // conference ID
  571. wQ931Goal, // goal
  572. wQ931CallType, // call type
  573. hCall, // user token
  574. (Q931_CALLBACK)Q931Callback, // callback
  575. pCall->dwBandwidth,
  576. #ifdef GATEKEEPER
  577. pCall->GkiCall.usCRV); // CRV
  578. #else
  579. 0); // CRV
  580. #endif GATEKEEPER
  581. if (status != CS_OK) {
  582. MarkCallForDeletion(pCall);
  583. InvokeUserConferenceCallback(pConference,
  584. CC_CONNECT_INDICATION,
  585. status,
  586. &ConnectCallbackParams);
  587. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  588. FreeCall(pCall);
  589. if (ValidateConference(hConference) != CC_OK)
  590. return 0;
  591. for ( ; ; ) {
  592. // Start up an enqueued call, if one exists
  593. status = RemoveEnqueuedCallFromConference(pConference, &hCall);
  594. if ((status != CC_OK) || (hCall == CC_INVALID_HANDLE))
  595. break;
  596. status = LockCall(hCall, &pCall);
  597. if (status == CC_OK) {
  598. pCall->CallState = PLACED;
  599. status = PlaceCall(pCall, pConference);
  600. UnlockCall(pCall);
  601. if (status == CC_OK)
  602. break;
  603. }
  604. }
  605. return 0;
  606. }
  607. UnlockCall(pCall);
  608. UnlockConference(pConference);
  609. return 0;
  610. }
  611. MarkCallForDeletion(pCall);
  612. if ((CallType == CALLER) || (CallType == THIRD_PARTY_INVITOR) ||
  613. ((CallType == CALLEE) && (pConference->LocalEndpointAttached == NEVER_ATTACHED))) {
  614. InvokeUserConferenceCallback(pConference,
  615. CC_CONNECT_INDICATION,
  616. CC_PEER_REJECT,
  617. &ConnectCallbackParams);
  618. }
  619. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  620. FreeCall(pCall);
  621. // Need to validate conference handle; the associated object may
  622. // have been deleted during the user callback in this thread
  623. if (ValidateConference(hConference) != CC_OK)
  624. return 0;
  625. for ( ; ; ) {
  626. // Start up an enqueued call, if one exists
  627. status = RemoveEnqueuedCallFromConference(pConference, &hCall);
  628. if ((status != CC_OK) || (hCall == CC_INVALID_HANDLE))
  629. break;
  630. status = LockCall(hCall, &pCall);
  631. if (status == CC_OK) {
  632. pCall->CallState = PLACED;
  633. status = PlaceCall(pCall, pConference);
  634. UnlockCall(pCall);
  635. if (status == CC_OK)
  636. break;
  637. }
  638. }
  639. EnumerateCallsInConference(&wNumCalls, NULL, pConference, REAL_CALLS);
  640. if (wNumCalls == 0) {
  641. if (pConference->bDeferredDelete) {
  642. ASSERT(pConference->LocalEndpointAttached == DETACHED);
  643. FreeConference(pConference);
  644. } else {
  645. if ((pConference->ConferenceMode != MULTIPOINT_MODE) ||
  646. (pConference->tsMultipointController != TS_TRUE))
  647. ReInitializeConference(pConference);
  648. UnlockConference(pConference);
  649. }
  650. } else {
  651. UnlockConference(pConference);
  652. }
  653. return 0;
  654. }
  655. DWORD _Q931CallAccepted( HQ931CALL hQ931Call,
  656. CC_HCALL hCall,
  657. PCSS_CALL_ACCEPTED pCallAcceptedData)
  658. {
  659. HRESULT status;
  660. PCALL pCall;
  661. CC_HCONFERENCE hConference;
  662. PCONFERENCE pConference;
  663. CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams;
  664. BYTE bTerminalType;
  665. BOOL bMultipointConference;
  666. CALLTYPE CallType;
  667. HQ931CALL hQ931CallInvitor;
  668. H245_INST_T H245Instance;
  669. DWORD dwLinkLayerPhysicalId;
  670. status = LockCallAndConference(hCall, &pCall, &pConference);
  671. if (status != CC_OK)
  672. return 0;
  673. CallType = pCall->CallType;
  674. hConference = pConference->hConference;
  675. hQ931Call = pCall->hQ931Call;
  676. hQ931CallInvitor = pCall->hQ931CallInvitor;
  677. ASSERT((pCall->hQ931Call == hQ931Call) || (pCall->hQ931CallInvitor == hQ931Call));
  678. if ((pConference->ConferenceMode == POINT_TO_POINT_MODE) ||
  679. (pConference->ConferenceMode == MULTIPOINT_MODE))
  680. bMultipointConference = TRUE;
  681. else
  682. bMultipointConference = FALSE;
  683. // Initialize ConnectCallbackParams
  684. ConnectCallbackParams.pNonStandardData = pCallAcceptedData->pNonStandardData;
  685. ConnectCallbackParams.pszPeerDisplay = pCallAcceptedData->pszDisplay;
  686. ConnectCallbackParams.bRejectReason = CC_REJECT_UNDEFINED_REASON; // field ignored
  687. ConnectCallbackParams.pTermCapList = NULL;
  688. ConnectCallbackParams.pH2250MuxCapability = NULL;
  689. ConnectCallbackParams.pTermCapDescriptors = NULL;
  690. ConnectCallbackParams.pLocalAddr = pCall->pQ931LocalConnectAddr;
  691. ConnectCallbackParams.pPeerAddr = pCallAcceptedData->pCalleeAddr;
  692. ConnectCallbackParams.pVendorInfo = pCall->pPeerVendorInfo;
  693. ConnectCallbackParams.bMultipointConference = bMultipointConference;
  694. ConnectCallbackParams.pConferenceID = &pConference->ConferenceID;
  695. ConnectCallbackParams.pMCAddress = pConference->pMultipointControllerAddr;
  696. ConnectCallbackParams.pAlternateAddress = NULL;
  697. ConnectCallbackParams.dwUserToken = pCall->dwUserToken;
  698. if (pCallAcceptedData->pCalleeAddr) {
  699. // Set pCall->pQ931DestinationAddr to the destination address that we got from Q931.
  700. // Note that we may not current have a destination address (if the client didn't
  701. // specify one), or we may currently have a destination address in domain name format
  702. // which we need to change to binary format
  703. if (pCall->pQ931DestinationAddr == NULL)
  704. pCall->pQ931DestinationAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  705. if (pCall->pQ931DestinationAddr != NULL)
  706. *pCall->pQ931DestinationAddr = *pCallAcceptedData->pCalleeAddr;
  707. }
  708. if ((!EqualConferenceIDs(&pConference->ConferenceID, &InvalidConferenceID)) &&
  709. (!EqualConferenceIDs(&pConference->ConferenceID, &pCallAcceptedData->ConferenceID))) {
  710. MarkCallForDeletion(pCall);
  711. if (CallType == THIRD_PARTY_INTERMEDIARY) {
  712. if (hQ931CallInvitor != CC_INVALID_HANDLE)
  713. Q931RejectCall(hQ931CallInvitor,
  714. CC_REJECT_UNDEFINED_REASON,
  715. &pCallAcceptedData->ConferenceID,
  716. NULL, // alternate address
  717. pCallAcceptedData->pNonStandardData);
  718. } else {
  719. if ((CallType == CALLER) || (CallType == THIRD_PARTY_INVITOR) ||
  720. ((CallType == CALLEE) && (pConference->LocalEndpointAttached == NEVER_ATTACHED)))
  721. InvokeUserConferenceCallback(pConference,
  722. CC_CONNECT_INDICATION,
  723. CC_INTERNAL_ERROR,
  724. &ConnectCallbackParams);
  725. }
  726. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  727. FreeCall(pCall);
  728. if (ValidateConference(hConference) == CC_OK)
  729. UnlockConference(pConference);
  730. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  731. return 0;
  732. }
  733. pConference->ConferenceID = pCallAcceptedData->ConferenceID;
  734. pCall->ConferenceID = pCallAcceptedData->ConferenceID;
  735. // Copy the newly-supplied peer address into the call object.
  736. // This is preferable if the original peer address was in IP dot
  737. // or domain name format
  738. if (CallType != THIRD_PARTY_INVITOR) {
  739. if (pCallAcceptedData->pCalleeAddr != NULL) {
  740. if (pCall->pQ931DestinationAddr == NULL)
  741. pCall->pQ931DestinationAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  742. if (pCall->pQ931DestinationAddr != NULL)
  743. *pCall->pQ931DestinationAddr = *pCallAcceptedData->pCalleeAddr;
  744. }
  745. if (pCallAcceptedData->pLocalAddr != NULL) {
  746. if (pCall->pQ931LocalConnectAddr == NULL)
  747. pCall->pQ931LocalConnectAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  748. if (pCall->pQ931LocalConnectAddr != NULL)
  749. *pCall->pQ931LocalConnectAddr = *pCallAcceptedData->pLocalAddr;
  750. }
  751. }
  752. ASSERT(pCall->pPeerNonStandardData == NULL);
  753. CopyNonStandardData(&pCall->pPeerNonStandardData,
  754. pCallAcceptedData->pNonStandardData);
  755. ASSERT(pCall->pszPeerDisplay == NULL);
  756. CopyDisplay(&pCall->pszPeerDisplay,
  757. pCallAcceptedData->pszDisplay);
  758. ASSERT(pCall->pPeerVendorInfo == NULL);
  759. CopyVendorInfo(&pCall->pPeerVendorInfo,
  760. pCallAcceptedData->pDestinationEndpointType->pVendorInfo);
  761. if (CallType == THIRD_PARTY_INVITOR) {
  762. pCall->CallState = CALL_COMPLETE;
  763. ConnectCallbackParams.pPeerAddr = pCall->pQ931DestinationAddr;
  764. MarkCallForDeletion(pCall);
  765. InvokeUserConferenceCallback(pConference,
  766. CC_CONNECT_INDICATION,
  767. CC_OK,
  768. &ConnectCallbackParams);
  769. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  770. FreeCall(pCall);
  771. if (ValidateConference(hConference) == CC_OK)
  772. UnlockConference(pConference);
  773. return 0;
  774. }
  775. pCall->CallState = TERMCAP;
  776. status = MakeH245PhysicalID(&pCall->dwH245PhysicalID);
  777. if (status != CC_OK) {
  778. MarkCallForDeletion(pCall);
  779. if (CallType == THIRD_PARTY_INTERMEDIARY) {
  780. if (hQ931CallInvitor != CC_INVALID_HANDLE)
  781. Q931RejectCall(hQ931CallInvitor,
  782. CC_REJECT_UNDEFINED_REASON,
  783. &pCallAcceptedData->ConferenceID,
  784. NULL, // alternate address
  785. pCallAcceptedData->pNonStandardData);
  786. } else {
  787. if ((CallType == CALLER) || (CallType == THIRD_PARTY_INVITOR) ||
  788. ((CallType == CALLEE) && (pConference->LocalEndpointAttached == NEVER_ATTACHED)))
  789. InvokeUserConferenceCallback(pConference,
  790. CC_CONNECT_INDICATION,
  791. status,
  792. &ConnectCallbackParams);
  793. }
  794. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  795. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  796. FreeCall(pCall);
  797. if (ValidateConference(hConference) == CC_OK)
  798. UnlockConference(pConference);
  799. return 0;
  800. }
  801. //MULTITHREAD
  802. //Use a tmp ID so we don't clobber the chosen H245Id.
  803. // H245Id=>
  804. // <= linkLayerId
  805. dwLinkLayerPhysicalId = INVALID_PHYS_ID;
  806. SetTerminalType(pConference->tsMultipointController, &bTerminalType);
  807. pCall->H245Instance = H245Init(H245_CONF_H323,
  808. pCall->dwH245PhysicalID,
  809. &dwLinkLayerPhysicalId,
  810. hCall,
  811. (H245_CONF_IND_CALLBACK_T)H245Callback,
  812. bTerminalType);
  813. if (pCall->H245Instance == H245_INVALID_ID) {
  814. MarkCallForDeletion(pCall);
  815. if (CallType == THIRD_PARTY_INTERMEDIARY) {
  816. if (hQ931CallInvitor != CC_INVALID_HANDLE)
  817. Q931RejectCall(hQ931CallInvitor,
  818. CC_REJECT_UNDEFINED_REASON,
  819. &pCallAcceptedData->ConferenceID,
  820. NULL, // alternate address
  821. pCallAcceptedData->pNonStandardData);
  822. } else {
  823. if ((CallType == CALLER) || (CallType == THIRD_PARTY_INVITOR) ||
  824. ((CallType == CALLEE) && (pConference->LocalEndpointAttached == NEVER_ATTACHED)))
  825. InvokeUserConferenceCallback(pConference,
  826. CC_CONNECT_INDICATION,
  827. CC_INTERNAL_ERROR,
  828. &ConnectCallbackParams);
  829. }
  830. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  831. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  832. FreeCall(pCall);
  833. if (ValidateConference(hConference) == CC_OK)
  834. UnlockConference(pConference);
  835. return 0;
  836. }
  837. H245Instance = pCall->H245Instance;
  838. // XXX -- need to define connect callback routine
  839. // Send in the Id we got back from H245Init.
  840. status = linkLayerConnect(dwLinkLayerPhysicalId,
  841. pCallAcceptedData->pH245Addr,
  842. NULL);
  843. if (status != NOERROR) {
  844. MarkCallForDeletion(pCall);
  845. if (CallType == THIRD_PARTY_INTERMEDIARY) {
  846. if (hQ931CallInvitor != CC_INVALID_HANDLE)
  847. Q931RejectCall(hQ931CallInvitor,
  848. CC_REJECT_UNDEFINED_REASON,
  849. &pCallAcceptedData->ConferenceID,
  850. NULL, // alternate address
  851. pCallAcceptedData->pNonStandardData);
  852. } else {
  853. if ((CallType == CALLER) || (CallType == THIRD_PARTY_INVITOR) ||
  854. ((CallType == CALLEE) && (pConference->LocalEndpointAttached == NEVER_ATTACHED)))
  855. InvokeUserConferenceCallback(pConference,
  856. CC_CONNECT_INDICATION,
  857. status,
  858. &ConnectCallbackParams);
  859. }
  860. H245ShutDown(H245Instance);
  861. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  862. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  863. FreeCall(pCall);
  864. if (ValidateConference(hConference) == CC_OK)
  865. UnlockConference(pConference);
  866. return 0;
  867. }
  868. pCall->bLinkEstablished = TRUE;
  869. status = SendTermCaps(pCall, pConference);
  870. if (status != CC_OK) {
  871. MarkCallForDeletion(pCall);
  872. if (CallType == THIRD_PARTY_INTERMEDIARY) {
  873. if (hQ931CallInvitor != CC_INVALID_HANDLE)
  874. Q931RejectCall(hQ931CallInvitor,
  875. CC_REJECT_UNDEFINED_REASON,
  876. &pCallAcceptedData->ConferenceID,
  877. NULL, // alternate address
  878. pCallAcceptedData->pNonStandardData);
  879. } else {
  880. if ((CallType == CALLER) || (CallType == THIRD_PARTY_INVITOR) ||
  881. ((CallType == CALLEE) && (pConference->LocalEndpointAttached == NEVER_ATTACHED)))
  882. InvokeUserConferenceCallback(pConference,
  883. CC_CONNECT_INDICATION,
  884. CC_NO_MEMORY,
  885. &ConnectCallbackParams);
  886. }
  887. H245ShutDown(H245Instance);
  888. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  889. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  890. FreeCall(pCall);
  891. if (ValidateConference(hConference) == CC_OK)
  892. UnlockConference(pConference);
  893. return 0;
  894. }
  895. pCall->OutgoingTermCapState = AWAITING_ACK;
  896. if (pCall->MasterSlaveState == MASTER_SLAVE_NOT_STARTED) {
  897. status = H245InitMasterSlave(pCall->H245Instance,
  898. pCall->H245Instance); // returned as dwTransId in the callback
  899. if (status != H245_ERROR_OK) {
  900. MarkCallForDeletion(pCall);
  901. if (CallType == THIRD_PARTY_INTERMEDIARY) {
  902. if (hQ931CallInvitor != CC_INVALID_HANDLE)
  903. Q931RejectCall(hQ931CallInvitor,
  904. CC_REJECT_UNDEFINED_REASON,
  905. &pCallAcceptedData->ConferenceID,
  906. NULL, // alternate address
  907. pCallAcceptedData->pNonStandardData);
  908. } else {
  909. if ((CallType == CALLER) || (CallType == THIRD_PARTY_INVITOR) ||
  910. ((CallType == CALLEE) && (pConference->LocalEndpointAttached == NEVER_ATTACHED)))
  911. InvokeUserConferenceCallback(pConference,
  912. CC_CONNECT_INDICATION,
  913. status,
  914. &ConnectCallbackParams);
  915. }
  916. H245ShutDown(H245Instance);
  917. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  918. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  919. FreeCall(pCall);
  920. if (ValidateConference(hConference) == CC_OK)
  921. UnlockConference(pConference);
  922. return 0;
  923. }
  924. pCall->MasterSlaveState = MASTER_SLAVE_IN_PROGRESS;
  925. }
  926. UnlockConference(pConference);
  927. UnlockCall(pCall);
  928. return 0;
  929. }
  930. DWORD _Q931CallRinging( HQ931CALL hQ931Call,
  931. CC_HCALL hCall)
  932. {
  933. PCALL pCall;
  934. CC_HCONFERENCE hConference;
  935. PCONFERENCE pConference;
  936. HRESULT status;
  937. CC_RINGING_CALLBACK_PARAMS RingingCallbackParams;
  938. CC_CONFERENCEID ConferenceID;
  939. status = LockCallAndConference(hCall, &pCall, &pConference);
  940. if (status != CC_OK) {
  941. Q931RejectCall(hQ931Call, // Q931 call handle
  942. CC_REJECT_UNDEFINED_REASON, // reject reason
  943. NULL, // conference ID
  944. NULL, // alternate address
  945. NULL); // non-standard data
  946. return 0;
  947. }
  948. ConferenceID = pCall->ConferenceID;
  949. if ((pCall->hQ931Call != hQ931Call) || (pCall->CallState != PLACED)) {
  950. // The peer must be in a bad state; we don't expect to receive this message now
  951. UnlockCall(pCall);
  952. return 0;
  953. }
  954. pCall->CallState = RINGING;
  955. if (pCall->CallType == THIRD_PARTY_INTERMEDIARY) {
  956. // Send "ringing" indication to pCall->hQ931CallInvitor
  957. Q931Ringing(pCall->hQ931CallInvitor,
  958. NULL); // pCRV
  959. UnlockConference(pConference);
  960. UnlockCall(pCall);
  961. return 0;
  962. }
  963. RingingCallbackParams.pNonStandardData = NULL;
  964. RingingCallbackParams.dwUserToken = pCall->dwUserToken;
  965. // save a copy of the conference handle; we'll need it to validate
  966. // the conference object after returning from the user callback
  967. hConference = pConference->hConference;
  968. InvokeUserConferenceCallback(pConference,
  969. CC_RINGING_INDICATION,
  970. CC_OK,
  971. &RingingCallbackParams);
  972. // Need to validate conference and call handles; the associated objects may
  973. // have been deleted during the user callback in this thread
  974. if (ValidateConference(hConference) == CC_OK)
  975. UnlockConference(pConference);
  976. if (ValidateCall(hCall) == CC_OK)
  977. UnlockCall(pCall);
  978. return 0;
  979. }
  980. DWORD _Q931CallFailed( HQ931CALL hQ931Call,
  981. CC_HCALL hCall,
  982. PCSS_CALL_FAILED pCallFailedData)
  983. {
  984. PCALL pCall;
  985. CC_HCONFERENCE hConference;
  986. PCONFERENCE pConference;
  987. HQ931CALL hQ931CallInvitor;
  988. HRESULT status;
  989. CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams;
  990. CALLTYPE CallType;
  991. CC_CONFERENCEID ConferenceID;
  992. WORD wNumCalls;
  993. status = LockCallAndConference(hCall, &pCall, &pConference);
  994. if (status != CC_OK)
  995. return 0;
  996. CallType = pCall->CallType;
  997. ConferenceID = pCall->ConferenceID;
  998. if (pCall->hQ931Call != hQ931Call) {
  999. UnlockConference(pConference);
  1000. UnlockCall(pCall);
  1001. return 0;
  1002. }
  1003. if (CallType == THIRD_PARTY_INTERMEDIARY) {
  1004. hQ931CallInvitor = pCall->hQ931CallInvitor;
  1005. FreeCall(pCall);
  1006. UnlockConference(pConference);
  1007. if (hQ931CallInvitor != CC_INVALID_HANDLE)
  1008. Q931RejectCall(hQ931CallInvitor,
  1009. CC_REJECT_UNREACHABLE_DESTINATION,
  1010. &ConferenceID,
  1011. NULL, // alternate address
  1012. NULL); // non-standard data
  1013. return 0;
  1014. }
  1015. ConnectCallbackParams.pNonStandardData = NULL;
  1016. ConnectCallbackParams.pszPeerDisplay = NULL;
  1017. ConnectCallbackParams.bRejectReason = CC_REJECT_UNREACHABLE_DESTINATION;
  1018. ConnectCallbackParams.pTermCapList = NULL;
  1019. ConnectCallbackParams.pH2250MuxCapability = NULL;
  1020. ConnectCallbackParams.pTermCapDescriptors = NULL;
  1021. ConnectCallbackParams.pLocalAddr = pCall->pQ931LocalConnectAddr;
  1022. if (pCall->pQ931DestinationAddr == NULL)
  1023. ConnectCallbackParams.pPeerAddr = pCall->pQ931PeerConnectAddr;
  1024. else
  1025. ConnectCallbackParams.pPeerAddr = pCall->pQ931DestinationAddr;
  1026. ConnectCallbackParams.pVendorInfo = pCall->pPeerVendorInfo;
  1027. ConnectCallbackParams.bMultipointConference = FALSE;
  1028. ConnectCallbackParams.pConferenceID = &pConference->ConferenceID;
  1029. ConnectCallbackParams.pMCAddress = NULL;
  1030. ConnectCallbackParams.pAlternateAddress = NULL;
  1031. ConnectCallbackParams.dwUserToken = pCall->dwUserToken;
  1032. // save a copy of the conference handle; we'll need it to validate
  1033. // the conference object after returning from the user callback
  1034. hConference = pConference->hConference;
  1035. MarkCallForDeletion(pCall);
  1036. if ((CallType == CALLER) || (CallType == THIRD_PARTY_INVITOR) ||
  1037. ((CallType == CALLEE) && (pConference->LocalEndpointAttached == NEVER_ATTACHED))) {
  1038. InvokeUserConferenceCallback(pConference,
  1039. CC_CONNECT_INDICATION,
  1040. pCallFailedData->error,
  1041. &ConnectCallbackParams);
  1042. }
  1043. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  1044. FreeCall(pCall);
  1045. // Need to validate conference handle; the associated object may
  1046. // have been deleted during the user callback in this thread
  1047. if (ValidateConference(hConference) != CC_OK)
  1048. return 0;
  1049. for ( ; ; ) {
  1050. // Start up an enqueued call, if one exists
  1051. status = RemoveEnqueuedCallFromConference(pConference, &hCall);
  1052. if ((status != CC_OK) || (hCall == CC_INVALID_HANDLE))
  1053. break;
  1054. status = LockCall(hCall, &pCall);
  1055. if (status == CC_OK) {
  1056. pCall->CallState = PLACED;
  1057. status = PlaceCall(pCall, pConference);
  1058. UnlockCall(pCall);
  1059. if (status == CC_OK)
  1060. break;
  1061. }
  1062. }
  1063. EnumerateCallsInConference(&wNumCalls, NULL, pConference, REAL_CALLS);
  1064. if (wNumCalls == 0) {
  1065. if (pConference->bDeferredDelete) {
  1066. ASSERT(pConference->LocalEndpointAttached == DETACHED);
  1067. FreeConference(pConference);
  1068. } else {
  1069. if ((pConference->ConferenceMode != MULTIPOINT_MODE) ||
  1070. (pConference->tsMultipointController != TS_TRUE))
  1071. ReInitializeConference(pConference);
  1072. UnlockConference(pConference);
  1073. }
  1074. } else {
  1075. UnlockConference(pConference);
  1076. }
  1077. return 0;
  1078. }
  1079. DWORD _Q931CallConnectionClosed( HQ931CALL hQ931Call,
  1080. CC_HCALL hCall)
  1081. {
  1082. return 0;
  1083. }
  1084. DWORD Q931Callback( BYTE bEvent,
  1085. HQ931CALL hQ931Call,
  1086. DWORD dwListenToken,
  1087. DWORD dwUserToken,
  1088. void * pEventData)
  1089. {
  1090. DWORD dwStatus;
  1091. EnterCallControl();
  1092. if (CallControlState != OPERATIONAL_STATE)
  1093. DWLeaveCallControl(0);
  1094. switch (bEvent) {
  1095. case Q931_CALL_INCOMING:
  1096. dwStatus = _Q931CallIncoming(hQ931Call, (CC_HLISTEN)dwListenToken,
  1097. (PCSS_CALL_INCOMING)pEventData);
  1098. break;
  1099. case Q931_CALL_REMOTE_HANGUP:
  1100. dwStatus = _Q931CallRemoteHangup(hQ931Call, (CC_HLISTEN)dwListenToken,
  1101. (CC_HCALL)dwUserToken);
  1102. break;
  1103. case Q931_CALL_REJECTED:
  1104. dwStatus = _Q931CallRejected(hQ931Call, (CC_HCALL)dwUserToken,
  1105. (PCSS_CALL_REJECTED)pEventData);
  1106. break;
  1107. case Q931_CALL_ACCEPTED:
  1108. dwStatus = _Q931CallAccepted(hQ931Call, (CC_HCALL)dwUserToken,
  1109. (PCSS_CALL_ACCEPTED)pEventData);
  1110. break;
  1111. case Q931_CALL_RINGING:
  1112. dwStatus = _Q931CallRinging(hQ931Call, (CC_HCALL)dwUserToken);
  1113. break;
  1114. case Q931_CALL_FAILED:
  1115. dwStatus = _Q931CallFailed(hQ931Call, (CC_HCALL)dwUserToken,
  1116. (PCSS_CALL_FAILED)pEventData);
  1117. break;
  1118. case Q931_CALL_CONNECTION_CLOSED:
  1119. dwStatus = _Q931CallConnectionClosed(hQ931Call, (CC_HCALL)dwUserToken);
  1120. break;
  1121. default:
  1122. ASSERT(0);
  1123. dwStatus = 0;
  1124. break;
  1125. }
  1126. DWLeaveCallControl(dwStatus);
  1127. }