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.

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