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.

4927 lines
172 KiB

  1. /****************************************************************************
  2. *
  3. * $Archive: S:/STURGEON/SRC/CALLCONT/VCS/h245man.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.225.1.1 $
  14. * $Date: 23 Jun 1997 15:58:08 $
  15. * $Author: MANDREWS $
  16. *
  17. * Deliverable:
  18. *
  19. * Abstract:
  20. *
  21. *
  22. * Notes:
  23. *
  24. ***************************************************************************/
  25. #pragma warning ( disable : 4057 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 "chanman.h"
  43. #include "hangman.h"
  44. #include "ccutils.h"
  45. #include "linkapi.h"
  46. extern CALL_CONTROL_STATE CallControlState;
  47. extern THREADCOUNT ThreadCount;
  48. static BOOL bH245ManagerInited = FALSE;
  49. static struct {
  50. DWORD dwPhysicalID;
  51. LOCK Lock;
  52. } PhysicalID;
  53. HRESULT InitH245Manager()
  54. {
  55. ASSERT(bH245ManagerInited == FALSE);
  56. // Note -- don't use a physical ID of 0; the physical ID gets mapped
  57. // to an H245 instance of the same value, and an H245 instance of
  58. // 0 is invalid
  59. PhysicalID.dwPhysicalID = 1;
  60. InitializeLock(&PhysicalID.Lock);
  61. bH245ManagerInited = TRUE;
  62. return CC_OK;
  63. }
  64. HRESULT DeInitH245Manager()
  65. {
  66. if (bH245ManagerInited == FALSE)
  67. return CC_OK;
  68. DeleteLock(&PhysicalID.Lock);
  69. bH245ManagerInited = FALSE;
  70. return CC_OK;
  71. }
  72. HRESULT MakeH245PhysicalID( DWORD *pdwH245PhysicalID)
  73. {
  74. AcquireLock(&PhysicalID.Lock);
  75. *pdwH245PhysicalID = PhysicalID.dwPhysicalID++;
  76. RelinquishLock(&PhysicalID.Lock);
  77. return CC_OK;
  78. }
  79. HRESULT _ConstructTermCapList( PCC_TERMCAPLIST *ppTermCapList,
  80. PCC_TERMCAP *ppH2250MuxCap,
  81. PCC_TERMCAPDESCRIPTORS *ppTermCapDescriptors,
  82. PCALL pCall)
  83. {
  84. #define MAX_TERM_CAPS 257
  85. #define MAX_TERM_CAP_DESC 255
  86. H245_TOTCAP_T * pTermCapArray[MAX_TERM_CAPS];
  87. H245_TOTCAPDESC_T * pTermCapDescriptorArray[MAX_TERM_CAP_DESC];
  88. unsigned long CapArrayLength;
  89. unsigned long CapDescriptorArrayLength;
  90. unsigned long i, j;
  91. HRESULT status;
  92. ASSERT(ppTermCapList != NULL);
  93. ASSERT(*ppTermCapList == NULL);
  94. ASSERT(ppH2250MuxCap != NULL);
  95. ASSERT(*ppH2250MuxCap == NULL);
  96. ASSERT(ppTermCapDescriptors != NULL);
  97. ASSERT(*ppTermCapDescriptors == NULL);
  98. ASSERT(pCall != NULL);
  99. CapArrayLength = MAX_TERM_CAPS;
  100. CapDescriptorArrayLength = MAX_TERM_CAP_DESC;
  101. status = H245GetCaps(pCall->H245Instance,
  102. H245_CAPDIR_RMTRXTX,
  103. H245_DATA_DONTCARE,
  104. H245_CLIENT_DONTCARE,
  105. pTermCapArray,
  106. &CapArrayLength,
  107. pTermCapDescriptorArray,
  108. &CapDescriptorArrayLength);
  109. if (status != H245_ERROR_OK) {
  110. *ppTermCapList = NULL;
  111. *ppH2250MuxCap = NULL;
  112. *ppTermCapDescriptors = NULL;
  113. return status;
  114. }
  115. // Check the term cap list to see if an H.225.0 mux capability is present;
  116. // this capability is treated as a special case
  117. *ppH2250MuxCap = NULL;
  118. for (i = 0; i < CapArrayLength; i++) {
  119. ASSERT(pTermCapArray[i] != NULL);
  120. if (pTermCapArray[i]->CapId == 0) {
  121. *ppH2250MuxCap = pTermCapArray[i];
  122. --CapArrayLength;
  123. for (j = i; j < CapArrayLength; j++)
  124. pTermCapArray[j] = pTermCapArray[j+1];
  125. break;
  126. }
  127. }
  128. if (CapArrayLength == 0)
  129. *ppTermCapList = NULL;
  130. else {
  131. *ppTermCapList = (PCC_TERMCAPLIST)Malloc(sizeof(CC_TERMCAPLIST));
  132. if (*ppTermCapList == NULL) {
  133. for (i = 0; i < CapArrayLength; i++)
  134. H245FreeCap(pTermCapArray[i]);
  135. if (*ppH2250MuxCap != NULL)
  136. H245FreeCap(*ppH2250MuxCap);
  137. for (i = 0; i < CapDescriptorArrayLength; i++)
  138. H245FreeCapDescriptor(pTermCapDescriptorArray[i]);
  139. return CC_NO_MEMORY;
  140. }
  141. (*ppTermCapList)->wLength = (WORD)CapArrayLength;
  142. (*ppTermCapList)->pTermCapArray =
  143. (H245_TOTCAP_T **)Malloc(sizeof(H245_TOTCAP_T *) * CapArrayLength);
  144. if ((*ppTermCapList)->pTermCapArray == NULL) {
  145. Free(*ppTermCapList);
  146. for (i = 0; i < CapArrayLength; i++)
  147. H245FreeCap(pTermCapArray[i]);
  148. if (*ppH2250MuxCap != NULL)
  149. H245FreeCap(*ppH2250MuxCap);
  150. for (i = 0; i < CapDescriptorArrayLength; i++)
  151. H245FreeCapDescriptor(pTermCapDescriptorArray[i]);
  152. *ppTermCapList = NULL;
  153. *ppH2250MuxCap = NULL;
  154. *ppTermCapDescriptors = NULL;
  155. return CC_NO_MEMORY;
  156. }
  157. for (i = 0; i < CapArrayLength; i++)
  158. (*ppTermCapList)->pTermCapArray[i] = pTermCapArray[i];
  159. }
  160. if (CapDescriptorArrayLength == 0)
  161. *ppTermCapDescriptors = NULL;
  162. else {
  163. *ppTermCapDescriptors = (PCC_TERMCAPDESCRIPTORS)Malloc(sizeof(CC_TERMCAPDESCRIPTORS));
  164. if (*ppTermCapDescriptors == NULL) {
  165. for (i = 0; i < CapArrayLength; i++)
  166. H245FreeCap(pTermCapArray[i]);
  167. if (*ppH2250MuxCap != NULL)
  168. H245FreeCap(*ppH2250MuxCap);
  169. for (i = 0; i < CapDescriptorArrayLength; i++)
  170. H245FreeCapDescriptor(pTermCapDescriptorArray[i]);
  171. if (*ppTermCapList != NULL) {
  172. Free((*ppTermCapList)->pTermCapArray);
  173. Free(*ppTermCapList);
  174. }
  175. *ppTermCapList = NULL;
  176. *ppH2250MuxCap = NULL;
  177. *ppTermCapDescriptors = NULL;
  178. return CC_NO_MEMORY;
  179. }
  180. (*ppTermCapDescriptors)->wLength = (WORD)CapDescriptorArrayLength;
  181. (*ppTermCapDescriptors)->pTermCapDescriptorArray =
  182. (H245_TOTCAPDESC_T **)Malloc(sizeof(H245_TOTCAPDESC_T *) * CapDescriptorArrayLength);
  183. if ((*ppTermCapDescriptors)->pTermCapDescriptorArray == NULL) {
  184. for (i = 0; i < CapArrayLength; i++)
  185. H245FreeCap(pTermCapArray[i]);
  186. if (*ppH2250MuxCap != NULL)
  187. H245FreeCap(*ppH2250MuxCap);
  188. for (i = 0; i < CapDescriptorArrayLength; i++)
  189. H245FreeCapDescriptor(pTermCapDescriptorArray[i]);
  190. if (*ppTermCapList != NULL) {
  191. Free((*ppTermCapList)->pTermCapArray);
  192. Free(*ppTermCapList);
  193. }
  194. Free(*ppTermCapDescriptors);
  195. *ppTermCapList = NULL;
  196. *ppH2250MuxCap = NULL;
  197. *ppTermCapDescriptors = NULL;
  198. return CC_NO_MEMORY;
  199. }
  200. for (i = 0; i < CapDescriptorArrayLength; i++)
  201. (*ppTermCapDescriptors)->pTermCapDescriptorArray[i] = pTermCapDescriptorArray[i];
  202. }
  203. return CC_OK;
  204. }
  205. HRESULT _ProcessConnectionComplete( PCONFERENCE pConference,
  206. PCALL pCall)
  207. {
  208. CC_HCONFERENCE hConference;
  209. CC_HCALL hCall;
  210. HQ931CALL hQ931Call;
  211. HQ931CALL hQ931CallInvitor;
  212. HRESULT status;
  213. CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams;
  214. CC_MULTIPOINT_CALLBACK_PARAMS MultipointCallbackParams;
  215. CC_PEER_CHANGE_CAP_CALLBACK_PARAMS PeerChangeCapCallbackParams;
  216. CC_PEER_ADD_CALLBACK_PARAMS PeerAddCallbackParams;
  217. WORD i;
  218. BOOL bMultipointConference;
  219. H245_TRANSPORT_ADDRESS_T Q931Address;
  220. PDU_T Pdu;
  221. CALLTYPE CallType;
  222. WORD wNumCalls;
  223. PCC_HCALL CallList;
  224. WORD wNumChannels;
  225. PCC_HCHANNEL ChannelList;
  226. PCHANNEL pChannel;
  227. PCALL pOldCall;
  228. CC_HCALL hOldCall;
  229. BYTE bNewTerminalNumber;
  230. BYTE bNewMCUNumber;
  231. CC_ENDPOINTTYPE DestinationEndpointType;
  232. H245_COMM_MODE_ENTRY_T *pH245CommunicationTable;
  233. BYTE bCommunicationTableCount;
  234. BOOL bSessionTableChanged;
  235. CONFMODE PreviousConferenceMode;
  236. CC_ADDR MCAddress;
  237. BOOL bConferenceTermCapsChanged;
  238. H245_INST_T H245Instance;
  239. PCC_TERMCAP pTxTermCap;
  240. PCC_TERMCAP pRxTermCap;
  241. H245_MUX_T *pTxMuxTable;
  242. H245_MUX_T *pRxMuxTable;
  243. ASSERT(pConference != NULL);
  244. ASSERT(pCall != NULL);
  245. ASSERT(pCall->hConference == pConference->hConference);
  246. hConference = pConference->hConference;
  247. hCall = pCall->hCall;
  248. hQ931Call = pCall->hQ931Call;
  249. hQ931CallInvitor = pCall->hQ931CallInvitor;
  250. H245Instance = pCall->H245Instance;
  251. CallType = pCall->CallType;
  252. // Note that pConference->ConferenceMode refers to the conference mode BEFORE
  253. // this connection attempt completes. If the current conference mode is
  254. // point-to-point, this connection (if successful) will result in a multipoint
  255. // conference. We want to reflect in the CONNECT callback the connection mode
  256. // that would exist if the connect attempt is successful.
  257. if ((pConference->ConferenceMode == POINT_TO_POINT_MODE) ||
  258. (pConference->ConferenceMode == MULTIPOINT_MODE) ||
  259. (pCall->bCallerIsMC))
  260. bMultipointConference = TRUE;
  261. else
  262. bMultipointConference = FALSE;
  263. // Initialize all fields of ConnectCallbackParams now
  264. ConnectCallbackParams.pNonStandardData = pCall->pPeerNonStandardData;
  265. ConnectCallbackParams.pszPeerDisplay = pCall->pszPeerDisplay;
  266. ConnectCallbackParams.bRejectReason = CC_REJECT_UNDEFINED_REASON;
  267. ConnectCallbackParams.pTermCapList = pCall->pPeerH245TermCapList;
  268. ConnectCallbackParams.pH2250MuxCapability = pCall->pPeerH245H2250MuxCapability;
  269. ConnectCallbackParams.pTermCapDescriptors = pCall->pPeerH245TermCapDescriptors;
  270. ConnectCallbackParams.pLocalAddr = pCall->pQ931LocalConnectAddr;
  271. if (pCall->pQ931DestinationAddr == NULL)
  272. ConnectCallbackParams.pPeerAddr = pCall->pQ931PeerConnectAddr;
  273. else
  274. ConnectCallbackParams.pPeerAddr = pCall->pQ931DestinationAddr;
  275. ConnectCallbackParams.pVendorInfo = pCall->pPeerVendorInfo;
  276. ConnectCallbackParams.bMultipointConference = bMultipointConference;
  277. ConnectCallbackParams.pConferenceID = &pConference->ConferenceID;
  278. ConnectCallbackParams.pMCAddress = pConference->pMultipointControllerAddr;
  279. ConnectCallbackParams.pAlternateAddress = NULL;
  280. ConnectCallbackParams.dwUserToken = pCall->dwUserToken;
  281. status = AddEstablishedCallToConference(pCall, pConference);
  282. if (status != CC_OK) {
  283. MarkCallForDeletion(pCall);
  284. if (CallType == THIRD_PARTY_INTERMEDIARY)
  285. Q931RejectCall(hQ931CallInvitor,
  286. CC_REJECT_UNDEFINED_REASON,
  287. &pCall->ConferenceID,
  288. NULL, // alternate address
  289. pCall->pPeerNonStandardData);
  290. if ((CallType == CALLER) || (CallType == THIRD_PARTY_INVITOR) ||
  291. ((CallType == CALLEE) && (pConference->LocalEndpointAttached == NEVER_ATTACHED)))
  292. InvokeUserConferenceCallback(pConference,
  293. CC_CONNECT_INDICATION,
  294. status,
  295. &ConnectCallbackParams);
  296. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  297. FreeCall(pCall);
  298. H245ShutDown(H245Instance);
  299. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  300. if (ValidateConference(hConference) == CC_OK)
  301. UnlockConference(pConference);
  302. return status;
  303. }
  304. if (((pConference->ConferenceMode == POINT_TO_POINT_MODE) ||
  305. (pConference->ConferenceMode == MULTIPOINT_MODE)) &&
  306. (pConference->tsMultipointController == TS_TRUE))
  307. status = CreateConferenceTermCaps(pConference, &bConferenceTermCapsChanged);
  308. else {
  309. status = CC_OK;
  310. bConferenceTermCapsChanged = FALSE;
  311. }
  312. if (status != CC_OK) {
  313. MarkCallForDeletion(pCall);
  314. if (CallType == THIRD_PARTY_INTERMEDIARY)
  315. Q931RejectCall(pCall->hQ931CallInvitor,
  316. CC_REJECT_UNDEFINED_REASON,
  317. &pCall->ConferenceID,
  318. NULL, // alternate address
  319. pCall->pPeerNonStandardData);
  320. if ((CallType == CALLER) || (CallType == THIRD_PARTY_INVITOR) ||
  321. ((CallType == CALLEE) && (pConference->LocalEndpointAttached == NEVER_ATTACHED)))
  322. InvokeUserConferenceCallback(pConference,
  323. CC_CONNECT_INDICATION,
  324. status,
  325. &ConnectCallbackParams);
  326. if (ValidateCallMarkedForDeletion(hCall) == CC_OK)
  327. FreeCall(pCall);
  328. H245ShutDown(H245Instance);
  329. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  330. if (ValidateConference(hConference) == CC_OK)
  331. UnlockConference(pConference);
  332. return status;
  333. }
  334. if (pConference->tsMultipointController == TS_TRUE) {
  335. // Send MCLocationIndication
  336. status = GetLastListenAddress(&MCAddress);
  337. if (status == CC_OK) {
  338. ASSERT(MCAddress.nAddrType == CC_IP_BINARY);
  339. Q931Address.type = H245_IP_UNICAST;
  340. Q931Address.u.ip.tsapIdentifier =
  341. MCAddress.Addr.IP_Binary.wPort;
  342. HostToH245IPNetwork(Q931Address.u.ip.network,
  343. MCAddress.Addr.IP_Binary.dwAddr);
  344. H245MCLocationIndication(pCall->H245Instance,
  345. &Q931Address);
  346. }
  347. }
  348. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  349. if (pConference->ConferenceMode == UNCONNECTED_MODE) {
  350. ASSERT(pConference->pSessionTable == NULL);
  351. ASSERT(wNumCalls == 1);
  352. pConference->ConferenceMode = POINT_TO_POINT_MODE;
  353. } else { // we're currently in point-to-point mode or multipoint mode
  354. if (pConference->tsMultipointController == TS_TRUE) {
  355. PreviousConferenceMode = pConference->ConferenceMode;
  356. pConference->ConferenceMode = MULTIPOINT_MODE;
  357. // In the future, we may want to construct a new session table
  358. // each time a new peer is added to the conference
  359. if (PreviousConferenceMode == POINT_TO_POINT_MODE) {
  360. // Assign a terminal label to ourselves
  361. // Note that we reserve a terminal number of 0 for ourselves
  362. // if we're the MC
  363. ASSERT(pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bTerminalNumber == 255);
  364. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bTerminalNumber = 0;
  365. // Create a new session table
  366. CreateConferenceSessionTable(
  367. pConference,
  368. &bSessionTableChanged);
  369. } else
  370. // For the current implementation, don't cause a new
  371. // CommunicationModeCommand to be issued when a new peer is added
  372. // unless we're switching from point-to-point to multipoint mode
  373. // (in which case bSessionTableChanged is ignored)
  374. bSessionTableChanged = FALSE;
  375. if (bSessionTableChanged)
  376. SessionTableToH245CommunicationTable(pConference->pSessionTable,
  377. &pH245CommunicationTable,
  378. &bCommunicationTableCount);
  379. else
  380. pH245CommunicationTable = NULL;
  381. // Send MultipointModeCommand to new call
  382. Pdu.choice = MSCMg_cmmnd_chosen;
  383. Pdu.u.MSCMg_cmmnd.choice = miscellaneousCommand_chosen;
  384. // logical channel number is irrelavent but needs to be filled in
  385. Pdu.u.MSCMg_cmmnd.u.miscellaneousCommand.logicalChannelNumber = 1;
  386. Pdu.u.MSCMg_cmmnd.u.miscellaneousCommand.type.choice = multipointModeCommand_chosen;
  387. H245SendPDU(pCall->H245Instance, &Pdu);
  388. status = AllocatePeerParticipantInfo(pConference, &pCall->pPeerParticipantInfo);
  389. if (status == CC_OK) {
  390. bNewMCUNumber = pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber;
  391. bNewTerminalNumber = pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber;
  392. // Send TerminalNumberAssign to new call
  393. H245ConferenceIndication(pCall->H245Instance,
  394. H245_IND_TERMINAL_NUMBER_ASSIGN,// Indication Type
  395. 0, // SBE number; ignored here
  396. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber, // MCU number
  397. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber); // terminal number
  398. // Send EnterH243TerminalID to new call
  399. H245ConferenceRequest(pCall->H245Instance,
  400. H245_REQ_ENTER_H243_TERMINAL_ID,
  401. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber,
  402. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber);
  403. pCall->pPeerParticipantInfo->TerminalIDState = TERMINAL_ID_REQUESTED;
  404. } else {
  405. // Unable to assign a terminal number to the new call
  406. bNewMCUNumber = 0;
  407. bNewTerminalNumber = 0;
  408. }
  409. if (pH245CommunicationTable != NULL) {
  410. // Send CommunicationModeCommand to new call
  411. status = H245CommunicationModeCommand(pCall->H245Instance,
  412. pH245CommunicationTable,
  413. bCommunicationTableCount);
  414. }
  415. if (PreviousConferenceMode == POINT_TO_POINT_MODE) {
  416. // Generate MULTIPOINT callback
  417. MultipointCallbackParams.pTerminalInfo = &pConference->LocalParticipantInfo.ParticipantInfo;
  418. MultipointCallbackParams.pSessionTable = pConference->pSessionTable;
  419. InvokeUserConferenceCallback(pConference,
  420. CC_MULTIPOINT_INDICATION,
  421. CC_OK,
  422. &MultipointCallbackParams);
  423. if (ValidateConference(hConference) != CC_OK) {
  424. if (ValidateCall(hCall) == CC_OK) {
  425. pCall->CallState = CALL_COMPLETE;
  426. UnlockCall(pCall);
  427. }
  428. Free(CallList);
  429. return CC_OK;
  430. }
  431. // Generate CC_PEER_CHANGE_CAP callback
  432. PeerChangeCapCallbackParams.pTermCapList =
  433. pConference->pConferenceTermCapList;
  434. PeerChangeCapCallbackParams.pH2250MuxCapability =
  435. pConference->pConferenceH245H2250MuxCapability;
  436. PeerChangeCapCallbackParams.pTermCapDescriptors =
  437. pConference->pConferenceTermCapDescriptors;
  438. InvokeUserConferenceCallback(pConference,
  439. CC_PEER_CHANGE_CAP_INDICATION,
  440. CC_OK,
  441. &PeerChangeCapCallbackParams);
  442. if (ValidateConference(hConference) != CC_OK) {
  443. if (ValidateCall(hCall) == CC_OK) {
  444. pCall->CallState = CALL_COMPLETE;
  445. UnlockCall(pCall);
  446. }
  447. Free(CallList);
  448. return CC_OK;
  449. }
  450. ASSERT(wNumCalls == 2); // one existing call and new call
  451. if (CallList[0] == hCall)
  452. hOldCall = CallList[1];
  453. else
  454. hOldCall = CallList[0];
  455. if (LockCall(hOldCall, &pOldCall) == CC_OK) {
  456. // Send MultipointModeCommand to old call
  457. Pdu.choice = MSCMg_cmmnd_chosen;
  458. Pdu.u.MSCMg_cmmnd.choice = miscellaneousCommand_chosen;
  459. // logical channel number is irrelavent but needs to be filled in
  460. Pdu.u.MSCMg_cmmnd.u.miscellaneousCommand.logicalChannelNumber = 1;
  461. Pdu.u.MSCMg_cmmnd.u.miscellaneousCommand.type.choice = multipointModeCommand_chosen;
  462. H245SendPDU(pOldCall->H245Instance, &Pdu);
  463. status = AllocatePeerParticipantInfo(pConference,
  464. &pOldCall->pPeerParticipantInfo);
  465. if (status == CC_OK) {
  466. // Send TerminalNumberAssign to old call
  467. H245ConferenceIndication(pOldCall->H245Instance,
  468. H245_IND_TERMINAL_NUMBER_ASSIGN,// Indication Type
  469. 0, // SBE number; ignored here
  470. pOldCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber, // MCU number
  471. pOldCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber); // terminal number
  472. // Send EnterH243TerminalID to old call
  473. H245ConferenceRequest(pOldCall->H245Instance,
  474. H245_REQ_ENTER_H243_TERMINAL_ID,
  475. pOldCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber,
  476. pOldCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber);
  477. pOldCall->pPeerParticipantInfo->TerminalIDState = TERMINAL_ID_REQUESTED;
  478. }
  479. if (pH245CommunicationTable != NULL) {
  480. // Send CommunicationModeCommand to old call
  481. status = H245CommunicationModeCommand(pOldCall->H245Instance,
  482. pH245CommunicationTable,
  483. bCommunicationTableCount);
  484. FreeH245CommunicationTable(pH245CommunicationTable,
  485. bCommunicationTableCount);
  486. }
  487. // Send TerminalJoinedConference (this call) to old call
  488. H245ConferenceIndication(pOldCall->H245Instance,
  489. H245_IND_TERMINAL_JOINED, // Indication Type
  490. 0, // SBE number; ignored here
  491. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bMCUNumber, // MCU number
  492. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bTerminalNumber); // terminal number // terminal number of MC
  493. if (bNewTerminalNumber != 0) {
  494. // Send TerminalJoinedConference (new call) to old call
  495. H245ConferenceIndication(pOldCall->H245Instance,
  496. H245_IND_TERMINAL_JOINED, // Indication Type
  497. 0, // SBE number; ignored here
  498. bNewMCUNumber, // MCU number
  499. bNewTerminalNumber); // terminal number
  500. // Generate PEER_ADD callback for old call
  501. PeerAddCallbackParams.hCall = pOldCall->hCall;
  502. PeerAddCallbackParams.TerminalLabel =
  503. pOldCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  504. PeerAddCallbackParams.pPeerTerminalID = NULL;
  505. InvokeUserConferenceCallback(pConference,
  506. CC_PEER_ADD_INDICATION,
  507. CC_OK,
  508. &PeerAddCallbackParams);
  509. if (ValidateConference(hConference) != CC_OK) {
  510. if (ValidateCall(hOldCall) == CC_OK)
  511. UnlockCall(pCall);
  512. if (ValidateCall(hCall) == CC_OK) {
  513. pCall->CallState = CALL_COMPLETE;
  514. UnlockCall(pCall);
  515. }
  516. Free(CallList);
  517. return CC_OK;
  518. }
  519. }
  520. // Send new term caps to old call
  521. SendTermCaps(pOldCall, pConference);
  522. UnlockCall(pOldCall);
  523. }
  524. } else { // we're currently in multipoint mode
  525. EnumerateChannelsInConference(&wNumChannels,
  526. &ChannelList,
  527. pConference,
  528. TX_CHANNEL | PROXY_CHANNEL | TXRX_CHANNEL);
  529. for (i = 0; i < wNumChannels; i++) {
  530. if (LockChannel(ChannelList[i], &pChannel) == CC_OK) {
  531. if (pChannel->bMultipointChannel) {
  532. if ((pChannel->bChannelType == TX_CHANNEL) ||
  533. ((pChannel->bChannelType == TXRX_CHANNEL) &&
  534. (pChannel->bLocallyOpened == TRUE))) {
  535. pTxTermCap = pChannel->pTxH245TermCap;
  536. pTxMuxTable = pChannel->pTxMuxTable;
  537. pRxTermCap = pChannel->pRxH245TermCap;
  538. pRxMuxTable = pChannel->pRxMuxTable;
  539. } else {
  540. // Note: since this is a proxy or remotely-opened
  541. // bi-directional channel, RxTermCap and RxMuxTable
  542. // contain the channel's term cap and mux table,
  543. // and must be sent to other endpoints as the
  544. // Tx term cap and mux table;
  545. // TxTermCap and TxMuxTable should be NULL
  546. pTxTermCap = pChannel->pRxH245TermCap;
  547. pTxMuxTable = pChannel->pRxMuxTable;
  548. pRxTermCap = pChannel->pTxH245TermCap;
  549. pRxMuxTable = pChannel->pTxMuxTable;
  550. }
  551. status = H245OpenChannel(
  552. pCall->H245Instance,
  553. pChannel->hChannel, // dwTransId
  554. pChannel->wLocalChannelNumber,
  555. pTxTermCap, // TxMode
  556. pTxMuxTable, // TxMux
  557. H245_INVALID_PORT_NUMBER, // TxPort
  558. pRxTermCap, // RxMode
  559. pRxMuxTable, // RxMux
  560. pChannel->pSeparateStack);
  561. if ((status == CC_OK) && (pChannel->wNumOutstandingRequests != 0))
  562. (pChannel->wNumOutstandingRequests)++;
  563. }
  564. UnlockChannel(pChannel);
  565. }
  566. }
  567. Free(ChannelList);
  568. for (i = 0; i < wNumCalls; i++) {
  569. // Don't send a message to the endpoint that just joined the conference!
  570. if (CallList[i] != hCall) {
  571. if (LockCall(CallList[i], &pOldCall) == CC_OK) {
  572. if (bNewTerminalNumber != 0)
  573. // Send TerminalJoinedConference (new call) to old call
  574. H245ConferenceIndication(pOldCall->H245Instance,
  575. H245_IND_TERMINAL_JOINED, // Indication Type
  576. 0, // SBE number; ignored here
  577. bNewMCUNumber, // MCU number
  578. bNewTerminalNumber); // terminal number
  579. // Send CommunicationModeCommand, if necessary
  580. if (pH245CommunicationTable != NULL)
  581. status = H245CommunicationModeCommand(pOldCall->H245Instance,
  582. pH245CommunicationTable,
  583. bCommunicationTableCount);
  584. if (bConferenceTermCapsChanged)
  585. // Send new term caps
  586. SendTermCaps(pOldCall, pConference);
  587. UnlockCall(pOldCall);
  588. }
  589. }
  590. }
  591. if (bConferenceTermCapsChanged) {
  592. // Generate CC_PEER_CHANGE_CAP callback
  593. PeerChangeCapCallbackParams.pTermCapList =
  594. pConference->pConferenceTermCapList;
  595. PeerChangeCapCallbackParams.pH2250MuxCapability =
  596. pConference->pConferenceH245H2250MuxCapability;
  597. PeerChangeCapCallbackParams.pTermCapDescriptors =
  598. pConference->pConferenceTermCapDescriptors;
  599. InvokeUserConferenceCallback(pConference,
  600. CC_PEER_CHANGE_CAP_INDICATION,
  601. CC_OK,
  602. &PeerChangeCapCallbackParams);
  603. if (ValidateConference(hConference) != CC_OK) {
  604. if (ValidateCall(hCall) == CC_OK) {
  605. pCall->CallState = CALL_COMPLETE;
  606. UnlockCall(pCall);
  607. }
  608. Free(CallList);
  609. return CC_OK;
  610. }
  611. }
  612. }
  613. // Generate PEER_ADD callback
  614. PeerAddCallbackParams.hCall = pCall->hCall;
  615. PeerAddCallbackParams.TerminalLabel =
  616. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  617. PeerAddCallbackParams.pPeerTerminalID = NULL;
  618. InvokeUserConferenceCallback(pConference,
  619. CC_PEER_ADD_INDICATION,
  620. CC_OK,
  621. &PeerAddCallbackParams);
  622. if (ValidateConference(hConference) != CC_OK) {
  623. if (ValidateCall(hCall) == CC_OK) {
  624. pCall->CallState = CALL_COMPLETE;
  625. UnlockCall(pCall);
  626. Free(CallList);
  627. return CC_OK;
  628. }
  629. }
  630. if (CallType == THIRD_PARTY_INTERMEDIARY) {
  631. DestinationEndpointType.pVendorInfo = pCall->pPeerVendorInfo;
  632. DestinationEndpointType.bIsTerminal = TRUE;
  633. DestinationEndpointType.bIsGateway = FALSE;
  634. status = Q931AcceptCall(pCall->hQ931CallInvitor,
  635. pCall->pszPeerDisplay,
  636. pCall->pPeerNonStandardData,
  637. &DestinationEndpointType,
  638. NULL,
  639. pCall->dwBandwidth,
  640. pCall->hCall);
  641. Q931Hangup(pCall->hQ931CallInvitor, CC_REJECT_NORMAL_CALL_CLEARING);
  642. }
  643. } // if (pConference->tsMultipointController == TS_TRUE)
  644. }
  645. Free(CallList);
  646. if (ValidateConference(hConference) == CC_OK)
  647. if ((CallType == CALLER) || (CallType == THIRD_PARTY_INVITOR) ||
  648. ((CallType == CALLEE) && (pConference->LocalEndpointAttached == NEVER_ATTACHED))) {
  649. // This CONNECT must apply to the local endpoint
  650. pConference->LocalEndpointAttached = ATTACHED;
  651. InvokeUserConferenceCallback(pConference,
  652. CC_CONNECT_INDICATION,
  653. CC_OK,
  654. &ConnectCallbackParams);
  655. }
  656. // Need to validate the conference and call handles; the associated
  657. // objects may have been deleted during user callback on this thread
  658. if (ValidateConference(hConference) == CC_OK)
  659. UnlockConference(pConference);
  660. if (ValidateCall(hCall) == CC_OK) {
  661. pCall->CallState = CALL_COMPLETE;
  662. UnlockCall(pCall);
  663. }
  664. return status;
  665. }
  666. HRESULT _IndUnimplemented( H245_CONF_IND_T *pH245ConfIndData)
  667. {
  668. return H245_ERROR_NOSUP;
  669. }
  670. HRESULT _IndFlowControl( H245_CONF_IND_T *pH245ConfIndData)
  671. {
  672. HRESULT status;
  673. CC_HCALL hCall;
  674. PCALL pCall;
  675. PCONFERENCE pConference;
  676. CC_HCONFERENCE hConference;
  677. CC_HCHANNEL hChannel;
  678. PCHANNEL pChannel;
  679. CC_FLOW_CONTROL_CALLBACK_PARAMS FlowControlCallbackParams;
  680. if (pH245ConfIndData->u.Indication.u.IndFlowControl.Scope != H245_SCOPE_CHANNEL_NUMBER)
  681. return H245_ERROR_NOSUP;
  682. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  683. status = LockCallAndConference(hCall, &pCall, &pConference);
  684. if (status != CC_OK) {
  685. // This may be OK, if the call was cancelled while
  686. // call setup was in progress.
  687. return H245_ERROR_OK;
  688. }
  689. hConference = pCall->hConference;
  690. UnlockCall(pCall);
  691. if (FindChannelInConference(pH245ConfIndData->u.Indication.u.IndFlowControl.Channel,
  692. TRUE, // local channel number
  693. TX_CHANNEL | PROXY_CHANNEL,
  694. CC_INVALID_HANDLE,
  695. &hChannel,
  696. pConference) != CC_OK) {
  697. UnlockConference(pConference);
  698. return H245_ERROR_OK;
  699. }
  700. if (LockChannel(hChannel, &pChannel) != CC_OK) {
  701. UnlockConference(pConference);
  702. return H245_ERROR_OK;
  703. }
  704. if (pChannel->bChannelType == TX_CHANNEL) {
  705. UnlockChannel(pChannel);
  706. FlowControlCallbackParams.hChannel = hChannel;
  707. FlowControlCallbackParams.dwRate =
  708. pH245ConfIndData->u.Indication.u.IndFlowControl.dwRestriction;
  709. // H.245 gives us the flow rate in units of 100 bps
  710. if (pH245ConfIndData->u.Indication.u.IndFlowControl.dwRestriction != H245_NO_RESTRICTION)
  711. FlowControlCallbackParams.dwRate *= 100;
  712. InvokeUserConferenceCallback(pConference,
  713. CC_FLOW_CONTROL_INDICATION,
  714. CC_OK,
  715. &FlowControlCallbackParams);
  716. if (ValidateConference(hConference) == CC_OK)
  717. UnlockConference(pConference);
  718. } else { // pChannel->bChannelType == PROXY_CHANNEL
  719. if (LockCall(pChannel->hCall, &pCall) == CC_OK) {
  720. H245FlowControl(pCall->H245Instance,
  721. pH245ConfIndData->u.Indication.u.IndFlowControl.Scope,
  722. pChannel->wRemoteChannelNumber,
  723. pH245ConfIndData->u.Indication.u.IndFlowControl.wResourceID,
  724. pH245ConfIndData->u.Indication.u.IndFlowControl.dwRestriction);
  725. UnlockCall(pCall);
  726. }
  727. UnlockChannel(pChannel);
  728. UnlockConference(pConference);
  729. }
  730. return H245_ERROR_OK;
  731. }
  732. HRESULT _IndEndSession( H245_CONF_IND_T *pH245ConfIndData)
  733. {
  734. CC_HCALL hCall;
  735. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  736. if (hCall != CC_INVALID_HANDLE)
  737. ProcessRemoteHangup(hCall, CC_INVALID_HANDLE, CC_REJECT_NORMAL_CALL_CLEARING);
  738. return H245_ERROR_OK;
  739. }
  740. HRESULT _IndCapability( H245_CONF_IND_T *pH245ConfIndData)
  741. {
  742. CC_HCALL hCall;
  743. PCALL pCall;
  744. HRESULT status;
  745. PCONFERENCE pConference;
  746. CC_HCONFERENCE hConference;
  747. CC_PEER_CHANGE_CAP_CALLBACK_PARAMS PeerChangeCapCallbackParams;
  748. BOOL bConferenceTermCapsChanged;
  749. WORD wNumCalls;
  750. PCC_HCALL CallList;
  751. PCALL pOldCall;
  752. WORD i;
  753. // We received a TerminalCapabilitySet message from a peer
  754. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  755. status = LockCallAndConference(hCall, &pCall, &pConference);
  756. if (status != CC_OK) {
  757. // This may be OK, if the call was cancelled while
  758. // call setup was in progress.
  759. return H245_ERROR_OK;
  760. }
  761. hConference = pCall->hConference;
  762. if ((pConference->ConferenceMode == MULTIPOINT_MODE) &&
  763. (pConference->tsMultipointController == TS_TRUE))
  764. CreateConferenceTermCaps(pConference, &bConferenceTermCapsChanged);
  765. else
  766. bConferenceTermCapsChanged = FALSE;
  767. pCall->bLinkEstablished = TRUE;
  768. pCall->IncomingTermCapState = TERMCAP_COMPLETE;
  769. if (pCall->CallState == TERMCAP) {
  770. ASSERT(pCall->pPeerH245TermCapList == NULL);
  771. ASSERT(pCall->pPeerH245H2250MuxCapability == NULL);
  772. ASSERT(pCall->pPeerH245TermCapDescriptors == NULL);
  773. } else {
  774. DestroyH245TermCapList(&pCall->pPeerH245TermCapList);
  775. DestroyH245TermCap(&pCall->pPeerH245H2250MuxCapability);
  776. DestroyH245TermCapDescriptors(&pCall->pPeerH245TermCapDescriptors);
  777. }
  778. _ConstructTermCapList(&(pCall->pPeerH245TermCapList),
  779. &(pCall->pPeerH245H2250MuxCapability),
  780. &(pCall->pPeerH245TermCapDescriptors),
  781. pCall);
  782. if ((pCall->OutgoingTermCapState == TERMCAP_COMPLETE) &&
  783. (pCall->IncomingTermCapState == TERMCAP_COMPLETE) &&
  784. (pCall->CallState == TERMCAP) &&
  785. (pCall->MasterSlaveState == MASTER_SLAVE_COMPLETE)) {
  786. // Note that _ProcessConnectionComplete() returns with pConference and pCall unlocked
  787. _ProcessConnectionComplete(pConference, pCall);
  788. return H245_ERROR_OK;
  789. }
  790. if (pCall->CallState == CALL_COMPLETE) {
  791. if ((pConference->ConferenceMode == MULTIPOINT_MODE) &&
  792. (pConference->tsMultipointController == TS_TRUE)) {
  793. CreateConferenceTermCaps(pConference, &bConferenceTermCapsChanged);
  794. if (bConferenceTermCapsChanged) {
  795. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  796. for (i = 0; i < wNumCalls; i++) {
  797. // Don't send a message to the endpoint that just joined the conference!
  798. if (CallList[i] != hCall) {
  799. if (LockCall(CallList[i], &pOldCall) == CC_OK) {
  800. // Send new term caps
  801. SendTermCaps(pOldCall, pConference);
  802. UnlockCall(pOldCall);
  803. }
  804. }
  805. }
  806. if (CallList != NULL)
  807. Free(CallList);
  808. // Generate CC_PEER_CHANGE_CAP callback
  809. PeerChangeCapCallbackParams.pTermCapList =
  810. pConference->pConferenceTermCapList;
  811. PeerChangeCapCallbackParams.pH2250MuxCapability =
  812. pConference->pConferenceH245H2250MuxCapability;
  813. PeerChangeCapCallbackParams.pTermCapDescriptors =
  814. pConference->pConferenceTermCapDescriptors;
  815. InvokeUserConferenceCallback(pConference,
  816. CC_PEER_CHANGE_CAP_INDICATION,
  817. CC_OK,
  818. &PeerChangeCapCallbackParams);
  819. }
  820. } else {
  821. PeerChangeCapCallbackParams.pTermCapList = pCall->pPeerH245TermCapList;
  822. PeerChangeCapCallbackParams.pH2250MuxCapability = pCall->pPeerH245H2250MuxCapability;
  823. PeerChangeCapCallbackParams.pTermCapDescriptors = pCall->pPeerH245TermCapDescriptors;
  824. InvokeUserConferenceCallback(pConference,
  825. CC_PEER_CHANGE_CAP_INDICATION,
  826. CC_OK,
  827. &PeerChangeCapCallbackParams);
  828. }
  829. if (ValidateConference(hConference) == CC_OK)
  830. UnlockConference(pConference);
  831. if (ValidateCall(hCall) == CC_OK)
  832. UnlockCall(pCall);
  833. return H245_ERROR_OK;
  834. }
  835. UnlockCall(pCall);
  836. UnlockConference(pConference);
  837. return H245_ERROR_OK;
  838. }
  839. HRESULT _IndOpenT120( H245_CONF_IND_T *pH245ConfIndData)
  840. {
  841. BOOL bFailed;
  842. CC_T120_CHANNEL_REQUEST_CALLBACK_PARAMS T120ChannelRequestCallbackParams;
  843. CC_HCALL hCall;
  844. PCALL pCall;
  845. CC_HCONFERENCE hConference;
  846. PCONFERENCE pConference;
  847. CC_HCHANNEL hChannel;
  848. PCHANNEL pChannel;
  849. CC_TERMCAP RxTermCap;
  850. CC_TERMCAP TxTermCap;
  851. H245_MUX_T RxH245MuxTable;
  852. H245_MUX_T TxH245MuxTable;
  853. CC_ADDR T120Addr;
  854. CC_OCTETSTRING ExternalReference;
  855. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  856. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK) {
  857. // Can't cancel with H245, because we don't have the H245 instance
  858. return H245_ERROR_OK;
  859. }
  860. hConference = pCall->hConference;
  861. if (pH245ConfIndData->u.Indication.u.IndOpen.RxDataType != H245_DATA_DATA ||
  862. pH245ConfIndData->u.Indication.u.IndOpen.RxClientType != H245_CLIENT_DAT_T120 ||
  863. pH245ConfIndData->u.Indication.u.IndOpen.pRxCap == NULL ||
  864. pH245ConfIndData->u.Indication.u.IndOpen.pRxCap->H245Dat_T120.application.choice != DACy_applctn_t120_chosen ||
  865. pH245ConfIndData->u.Indication.u.IndOpen.pRxCap->H245Dat_T120.application.u.DACy_applctn_t120.choice != separateLANStack_chosen ||
  866. pH245ConfIndData->u.Indication.u.IndOpen.TxDataType != H245_DATA_DATA ||
  867. pH245ConfIndData->u.Indication.u.IndOpen.TxClientType != H245_CLIENT_DAT_T120 ||
  868. pH245ConfIndData->u.Indication.u.IndOpen.pTxCap == NULL ||
  869. pH245ConfIndData->u.Indication.u.IndOpen.pTxCap->H245Dat_T120.application.choice != DACy_applctn_t120_chosen ||
  870. pH245ConfIndData->u.Indication.u.IndOpen.pTxCap->H245Dat_T120.application.u.DACy_applctn_t120.choice != separateLANStack_chosen) {
  871. bFailed = TRUE;
  872. } else {
  873. bFailed = FALSE;
  874. }
  875. if (pH245ConfIndData->u.Indication.u.IndOpen.pSeparateStack) {
  876. if ((pH245ConfIndData->u.Indication.u.IndOpen.pSeparateStack->networkAddress.choice == localAreaAddress_chosen) &&
  877. (pH245ConfIndData->u.Indication.u.IndOpen.pSeparateStack->networkAddress.u.localAreaAddress.choice == unicastAddress_chosen) &&
  878. (pH245ConfIndData->u.Indication.u.IndOpen.pSeparateStack->networkAddress.u.localAreaAddress.u.unicastAddress.choice == UnicastAddress_iPAddress_chosen)) {
  879. T120Addr.nAddrType = CC_IP_BINARY;
  880. T120Addr.bMulticast = FALSE;
  881. T120Addr.Addr.IP_Binary.wPort =
  882. pH245ConfIndData->u.Indication.u.IndOpen.pSeparateStack->networkAddress.u.localAreaAddress.u.unicastAddress.u.UnicastAddress_iPAddress.tsapIdentifier;
  883. H245IPNetworkToHost(&T120Addr.Addr.IP_Binary.dwAddr,
  884. pH245ConfIndData->u.Indication.u.IndOpen.pSeparateStack->networkAddress.u.localAreaAddress.u.unicastAddress.u.UnicastAddress_iPAddress.network.value);
  885. } else {
  886. bFailed = TRUE;
  887. }
  888. }
  889. if (bFailed) {
  890. H245OpenChannelReject(pCall->H245Instance, // H245 instance
  891. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel,
  892. H245_REJ); // rejection reason
  893. UnlockConference(pConference);
  894. UnlockCall(pCall);
  895. return H245_ERROR_OK;
  896. }
  897. RxTermCap.Dir = H245_CAPDIR_RMTTX;
  898. RxTermCap.DataType = pH245ConfIndData->u.Indication.u.IndOpen.RxDataType;
  899. RxTermCap.ClientType = pH245ConfIndData->u.Indication.u.IndOpen.RxClientType;
  900. RxTermCap.CapId = 0; // not used for channels
  901. RxTermCap.Cap = *pH245ConfIndData->u.Indication.u.IndOpen.pRxCap;
  902. TxTermCap.Dir = H245_CAPDIR_RMTTX;
  903. TxTermCap.DataType = pH245ConfIndData->u.Indication.u.IndOpen.TxDataType;
  904. TxTermCap.ClientType = pH245ConfIndData->u.Indication.u.IndOpen.TxClientType;
  905. TxTermCap.CapId = 0; // not used for channels
  906. TxTermCap.Cap = *pH245ConfIndData->u.Indication.u.IndOpen.pTxCap;
  907. RxH245MuxTable = *pH245ConfIndData->u.Indication.u.IndOpen.pRxMux;
  908. if ((pCall->pPeerParticipantInfo != NULL) &&
  909. (pCall->pPeerParticipantInfo->TerminalIDState == TERMINAL_ID_VALID)) {
  910. RxH245MuxTable.u.H2250.destinationPresent = TRUE;
  911. RxH245MuxTable.u.H2250.destination.mcuNumber = pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber;
  912. RxH245MuxTable.u.H2250.destination.terminalNumber = pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber;
  913. } else
  914. RxH245MuxTable.u.H2250.destinationPresent = FALSE;
  915. TxH245MuxTable = *pH245ConfIndData->u.Indication.u.IndOpen.pTxMux;
  916. TxH245MuxTable.u.H2250.destinationPresent = FALSE;
  917. if (AllocAndLockChannel(&hChannel,
  918. pConference,
  919. hCall,
  920. &TxTermCap, // Tx terminal capability
  921. &RxTermCap, // Rx terminal capability
  922. &TxH245MuxTable, // Tx H245 mux table
  923. &RxH245MuxTable, // Rx H245 mux table
  924. pH245ConfIndData->u.Indication.u.IndOpen.pSeparateStack, // separate stack
  925. 0, // user token
  926. TXRX_CHANNEL, // channel type
  927. 0, // session ID
  928. 0, // associated session ID
  929. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel, // remote bi-dir channel number
  930. NULL, // pLocalRTPAddr
  931. NULL, // pLocalRTCPAddr
  932. NULL, // pPeerRTPAddr
  933. NULL, // pPeerRTCPAddr
  934. FALSE, // locally opened
  935. 0, // bandwidth
  936. &pChannel) != CC_OK) {
  937. H245OpenChannelReject(pCall->H245Instance, // H245 instance
  938. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel,
  939. H245_REJ); // rejection reason
  940. UnlockConference(pConference);
  941. UnlockCall(pCall);
  942. return H245_ERROR_OK;
  943. }
  944. if (AddChannelToConference(pChannel, pConference) != CC_OK) {
  945. H245OpenChannelReject(pCall->H245Instance, // H245 instance
  946. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel,
  947. H245_REJ); // rejection reason
  948. UnlockConference(pConference);
  949. UnlockCall(pCall);
  950. FreeChannel(pChannel);
  951. return H245_ERROR_OK;
  952. }
  953. T120ChannelRequestCallbackParams.hChannel = hChannel;
  954. if (pH245ConfIndData->u.Indication.u.IndOpen.pSeparateStack == NULL) {
  955. T120ChannelRequestCallbackParams.bAssociateConference = FALSE;
  956. T120ChannelRequestCallbackParams.pExternalReference = NULL;
  957. T120ChannelRequestCallbackParams.pAddr = NULL;
  958. } else {
  959. T120ChannelRequestCallbackParams.bAssociateConference =
  960. pH245ConfIndData->u.Indication.u.IndOpen.pSeparateStack->associateConference;
  961. if (pH245ConfIndData->u.Indication.u.IndOpen.pSeparateStack->bit_mask & externalReference_present) {
  962. ExternalReference.wOctetStringLength = (WORD)
  963. pH245ConfIndData->u.Indication.u.IndOpen.pSeparateStack->externalReference.length;
  964. ExternalReference.pOctetString =
  965. pH245ConfIndData->u.Indication.u.IndOpen.pSeparateStack->externalReference.value;
  966. T120ChannelRequestCallbackParams.pExternalReference = &ExternalReference;
  967. } else
  968. T120ChannelRequestCallbackParams.pExternalReference = NULL;
  969. T120ChannelRequestCallbackParams.pAddr = &T120Addr;
  970. }
  971. if ((pConference->ConferenceMode == MULTIPOINT_MODE) &&
  972. (pConference->tsMultipointController == TS_TRUE))
  973. T120ChannelRequestCallbackParams.bMultipointController = TRUE;
  974. else
  975. T120ChannelRequestCallbackParams.bMultipointController = FALSE;
  976. if (pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.destinationPresent) {
  977. T120ChannelRequestCallbackParams.TerminalLabel.bMCUNumber =
  978. (BYTE)pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.destination.mcuNumber;
  979. T120ChannelRequestCallbackParams.TerminalLabel.bTerminalNumber =
  980. (BYTE)pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.destination.terminalNumber;
  981. } else {
  982. T120ChannelRequestCallbackParams.TerminalLabel.bMCUNumber = 255;
  983. T120ChannelRequestCallbackParams.TerminalLabel.bTerminalNumber = 255;
  984. }
  985. pChannel->wNumOutstandingRequests = 1;
  986. InvokeUserConferenceCallback(pConference,
  987. CC_T120_CHANNEL_REQUEST_INDICATION,
  988. CC_OK,
  989. &T120ChannelRequestCallbackParams);
  990. if (ValidateChannel(hChannel) == CC_OK)
  991. UnlockChannel(pChannel);
  992. if (ValidateCall(hCall) == CC_OK)
  993. UnlockCall(pCall);
  994. if (ValidateConference(hConference) == CC_OK)
  995. UnlockConference(pConference);
  996. return H245_ERROR_OK;
  997. }
  998. HRESULT _IndOpen( H245_CONF_IND_T *pH245ConfIndData)
  999. {
  1000. CC_HCALL hCall;
  1001. PCALL pCall;
  1002. PCALL pOldCall;
  1003. CC_HCONFERENCE hConference;
  1004. PCONFERENCE pConference;
  1005. WORD wNumCalls;
  1006. PCC_HCALL CallList;
  1007. CC_HCHANNEL hChannel;
  1008. PCHANNEL pChannel;
  1009. CC_TERMCAP TermCap;
  1010. CC_ADDR PeerRTPAddr;
  1011. CC_ADDR PeerRTCPAddr;
  1012. CC_RX_CHANNEL_REQUEST_CALLBACK_PARAMS RxChannelRequestCallbackParams;
  1013. BYTE bChannelType;
  1014. WORD i;
  1015. H245_MUX_T H245MuxTable;
  1016. PCC_ADDR pLocalRTPAddr;
  1017. PCC_ADDR pLocalRTCPAddr;
  1018. PCC_ADDR pPeerRTPAddr;
  1019. PCC_ADDR pPeerRTCPAddr;
  1020. BOOL bFoundSession;
  1021. HRESULT status;
  1022. // First check to see if this is a T.120 channel request,
  1023. // as T.120 channels are handled differently then other channels
  1024. if (pH245ConfIndData->u.Indication.u.IndOpen.RxClientType == H245_CLIENT_DAT_T120) {
  1025. status = _IndOpenT120(pH245ConfIndData);
  1026. return status;
  1027. }
  1028. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  1029. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK) {
  1030. // Can't cancel with H245, because we don't have the H245 instance
  1031. return H245_ERROR_OK;
  1032. }
  1033. // Make sure that this is not a bi-directional channel
  1034. if ((pH245ConfIndData->u.Indication.u.IndOpen.pTxMux != NULL) ||
  1035. (pH245ConfIndData->u.Indication.u.IndOpen.pRxCap == NULL)) {
  1036. H245OpenChannelReject(pCall->H245Instance, // H245 instance
  1037. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel,
  1038. H245_REJ); // rejection reason
  1039. UnlockConference(pConference);
  1040. UnlockCall(pCall);
  1041. return H245_ERROR_OK;
  1042. }
  1043. hConference = pCall->hConference;
  1044. TermCap.Dir = H245_CAPDIR_RMTTX;
  1045. TermCap.DataType = pH245ConfIndData->u.Indication.u.IndOpen.RxDataType;
  1046. TermCap.ClientType = pH245ConfIndData->u.Indication.u.IndOpen.RxClientType;
  1047. TermCap.CapId = 0; // not used for Rx channels
  1048. TermCap.Cap = *pH245ConfIndData->u.Indication.u.IndOpen.pRxCap;
  1049. RxChannelRequestCallbackParams.pChannelCapability = &TermCap;
  1050. if ((pH245ConfIndData->u.Indication.u.IndOpen.pRxMux != NULL) &&
  1051. (pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->Kind == H245_H2250)) {
  1052. RxChannelRequestCallbackParams.bSessionID =
  1053. pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.sessionID;
  1054. if (pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.associatedSessionIDPresent)
  1055. RxChannelRequestCallbackParams.bAssociatedSessionID =
  1056. pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.associatedSessionID;
  1057. else
  1058. RxChannelRequestCallbackParams.bAssociatedSessionID = 0;
  1059. if (pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.silenceSuppressionPresent)
  1060. RxChannelRequestCallbackParams.bSilenceSuppression =
  1061. pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.silenceSuppression;
  1062. else
  1063. RxChannelRequestCallbackParams.bSilenceSuppression = FALSE;
  1064. if ((pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.mediaChannelPresent) &&
  1065. ((pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.mediaChannel.type == H245_IP_MULTICAST) ||
  1066. (pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.mediaChannel.type == H245_IP_UNICAST))) {
  1067. RxChannelRequestCallbackParams.pPeerRTPAddr = &PeerRTPAddr;
  1068. PeerRTPAddr.nAddrType = CC_IP_BINARY;
  1069. if (pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.mediaChannel.type == H245_IP_MULTICAST)
  1070. PeerRTPAddr.bMulticast = TRUE;
  1071. else
  1072. PeerRTPAddr.bMulticast = FALSE;
  1073. PeerRTPAddr.Addr.IP_Binary.wPort =
  1074. pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.mediaChannel.u.ip.tsapIdentifier;
  1075. H245IPNetworkToHost(&PeerRTPAddr.Addr.IP_Binary.dwAddr,
  1076. pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.mediaChannel.u.ip.network);
  1077. } else
  1078. RxChannelRequestCallbackParams.pPeerRTPAddr = NULL;
  1079. if ((pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.mediaControlChannelPresent) &&
  1080. ((pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.mediaControlChannel.type == H245_IP_MULTICAST) ||
  1081. (pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.mediaControlChannel.type == H245_IP_UNICAST))) {
  1082. RxChannelRequestCallbackParams.pPeerRTCPAddr = &PeerRTCPAddr;
  1083. PeerRTCPAddr.nAddrType = CC_IP_BINARY;
  1084. if (pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.mediaControlChannel.type == H245_IP_MULTICAST)
  1085. PeerRTCPAddr.bMulticast = TRUE;
  1086. else
  1087. PeerRTCPAddr.bMulticast = FALSE;
  1088. PeerRTCPAddr.Addr.IP_Binary.wPort =
  1089. pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.mediaControlChannel.u.ip.tsapIdentifier;
  1090. H245IPNetworkToHost(&PeerRTCPAddr.Addr.IP_Binary.dwAddr,
  1091. pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.mediaControlChannel.u.ip.network);
  1092. } else
  1093. RxChannelRequestCallbackParams.pPeerRTCPAddr = NULL;
  1094. if (pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.destinationPresent) {
  1095. RxChannelRequestCallbackParams.TerminalLabel.bMCUNumber =
  1096. (BYTE)pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.destination.mcuNumber;
  1097. RxChannelRequestCallbackParams.TerminalLabel.bTerminalNumber =
  1098. (BYTE)pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.destination.terminalNumber;
  1099. } else {
  1100. RxChannelRequestCallbackParams.TerminalLabel.bMCUNumber = 255;
  1101. RxChannelRequestCallbackParams.TerminalLabel.bTerminalNumber = 255;
  1102. }
  1103. if (pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.dynamicRTPPayloadTypePresent)
  1104. RxChannelRequestCallbackParams.bRTPPayloadType =
  1105. pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.dynamicRTPPayloadType;
  1106. else
  1107. RxChannelRequestCallbackParams.bRTPPayloadType = 0;
  1108. } else {
  1109. H245OpenChannelReject(pCall->H245Instance, // H245 instance
  1110. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel,
  1111. H245_REJ); // rejection reason
  1112. UnlockConference(pConference);
  1113. UnlockCall(pCall);
  1114. return H245_ERROR_OK;
  1115. }
  1116. // XXX -- someday we should allow dynamic sessions to be created on the MC
  1117. if (pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.sessionID == 0) {
  1118. H245OpenChannelReject(pCall->H245Instance, // H245 instance
  1119. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel,
  1120. H245_REJ); // rejection reason
  1121. UnlockConference(pConference);
  1122. UnlockCall(pCall);
  1123. return H245_ERROR_OK;
  1124. }
  1125. if (pConference->ConferenceMode == MULTIPOINT_MODE) {
  1126. if ((pConference->tsMultipointController == TS_TRUE) &&
  1127. ((RxChannelRequestCallbackParams.pPeerRTPAddr != NULL) ||
  1128. (RxChannelRequestCallbackParams.pPeerRTCPAddr != NULL)) ||
  1129. ((pConference->tsMultipointController == TS_FALSE) &&
  1130. ((RxChannelRequestCallbackParams.pPeerRTPAddr == NULL) ||
  1131. (RxChannelRequestCallbackParams.pPeerRTCPAddr == NULL) ||
  1132. (RxChannelRequestCallbackParams.bSessionID == 0)))) {
  1133. H245OpenChannelReject(pCall->H245Instance, // H245 instance
  1134. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel,
  1135. H245_REJ); // rejection reason
  1136. UnlockConference(pConference);
  1137. UnlockCall(pCall);
  1138. return H245_ERROR_OK;
  1139. }
  1140. // Validate session ID
  1141. pLocalRTPAddr = NULL;
  1142. pLocalRTCPAddr = NULL;
  1143. bFoundSession = FALSE;
  1144. if (pConference->pSessionTable != NULL) {
  1145. for (i = 0; i < pConference->pSessionTable->wLength; i++) {
  1146. if (pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.sessionID ==
  1147. pConference->pSessionTable->SessionInfoArray[i].bSessionID) {
  1148. bFoundSession = TRUE;
  1149. pLocalRTPAddr = pConference->pSessionTable->SessionInfoArray[i].pRTPAddr;
  1150. pLocalRTCPAddr = pConference->pSessionTable->SessionInfoArray[i].pRTCPAddr;
  1151. break;
  1152. }
  1153. }
  1154. }
  1155. if (bFoundSession == FALSE) {
  1156. H245OpenChannelReject(pCall->H245Instance, // H245 instance
  1157. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel,
  1158. H245_REJ); // rejection reason
  1159. UnlockConference(pConference);
  1160. UnlockCall(pCall);
  1161. return H245_ERROR_OK;
  1162. }
  1163. ASSERT(pLocalRTPAddr != NULL);
  1164. ASSERT(pLocalRTCPAddr != NULL);
  1165. if (pConference->tsMultipointController == TS_TRUE) {
  1166. pPeerRTPAddr = pLocalRTPAddr;
  1167. pPeerRTCPAddr = pLocalRTCPAddr;
  1168. RxChannelRequestCallbackParams.pPeerRTPAddr = pLocalRTPAddr;
  1169. RxChannelRequestCallbackParams.pPeerRTCPAddr = pLocalRTCPAddr;
  1170. bChannelType = PROXY_CHANNEL;
  1171. } else { // multipoint mode, not MC
  1172. pLocalRTPAddr = RxChannelRequestCallbackParams.pPeerRTPAddr;
  1173. pLocalRTCPAddr = RxChannelRequestCallbackParams.pPeerRTCPAddr;
  1174. pPeerRTPAddr = RxChannelRequestCallbackParams.pPeerRTPAddr;
  1175. pPeerRTCPAddr = RxChannelRequestCallbackParams.pPeerRTCPAddr;
  1176. bChannelType = RX_CHANNEL;
  1177. }
  1178. } else { // not multipoint mode
  1179. pLocalRTPAddr = NULL;
  1180. pLocalRTCPAddr = NULL;
  1181. pPeerRTPAddr = RxChannelRequestCallbackParams.pPeerRTPAddr;
  1182. pPeerRTCPAddr = RxChannelRequestCallbackParams.pPeerRTCPAddr;
  1183. bChannelType = RX_CHANNEL;
  1184. }
  1185. H245MuxTable = *pH245ConfIndData->u.Indication.u.IndOpen.pRxMux;
  1186. if ((pCall->pPeerParticipantInfo != NULL) &&
  1187. (pCall->pPeerParticipantInfo->TerminalIDState == TERMINAL_ID_VALID)) {
  1188. H245MuxTable.u.H2250.destinationPresent = TRUE;
  1189. H245MuxTable.u.H2250.destination.mcuNumber = pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber;
  1190. H245MuxTable.u.H2250.destination.terminalNumber = pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber;
  1191. } else
  1192. H245MuxTable.u.H2250.destinationPresent = FALSE;
  1193. if (pLocalRTPAddr != NULL) {
  1194. if (pLocalRTPAddr->bMulticast)
  1195. H245MuxTable.u.H2250.mediaChannel.type = H245_IP_MULTICAST;
  1196. else
  1197. H245MuxTable.u.H2250.mediaChannel.type = H245_IP_UNICAST;
  1198. H245MuxTable.u.H2250.mediaChannel.u.ip.tsapIdentifier =
  1199. pLocalRTPAddr->Addr.IP_Binary.wPort;
  1200. HostToH245IPNetwork(H245MuxTable.u.H2250.mediaChannel.u.ip.network,
  1201. pLocalRTPAddr->Addr.IP_Binary.dwAddr);
  1202. H245MuxTable.u.H2250.mediaChannelPresent = TRUE;
  1203. } else
  1204. H245MuxTable.u.H2250.mediaChannelPresent = FALSE;
  1205. if (pLocalRTCPAddr != NULL) {
  1206. if (pLocalRTCPAddr->bMulticast)
  1207. H245MuxTable.u.H2250.mediaControlChannel.type = H245_IP_MULTICAST;
  1208. else
  1209. H245MuxTable.u.H2250.mediaControlChannel.type = H245_IP_UNICAST;
  1210. H245MuxTable.u.H2250.mediaControlChannel.u.ip.tsapIdentifier =
  1211. pLocalRTCPAddr->Addr.IP_Binary.wPort;
  1212. HostToH245IPNetwork(H245MuxTable.u.H2250.mediaControlChannel.u.ip.network,
  1213. pLocalRTCPAddr->Addr.IP_Binary.dwAddr);
  1214. H245MuxTable.u.H2250.mediaControlChannelPresent = TRUE;
  1215. } else
  1216. H245MuxTable.u.H2250.mediaControlChannelPresent = FALSE;
  1217. if (AllocAndLockChannel(&hChannel,
  1218. pConference,
  1219. hCall,
  1220. NULL, // Tx terminal capability
  1221. &TermCap, // Rx terminal capability
  1222. NULL, // Tx H245 mux table
  1223. &H245MuxTable, // Rx H245 mux table
  1224. NULL, // separate stack
  1225. 0, // user token
  1226. bChannelType,
  1227. pH245ConfIndData->u.Indication.u.IndOpen.pRxMux->u.H2250.sessionID,
  1228. RxChannelRequestCallbackParams.bAssociatedSessionID,
  1229. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel,
  1230. pLocalRTPAddr, // pLocalRTPAddr
  1231. pLocalRTCPAddr, // pLocalRTCPAddr
  1232. pPeerRTPAddr, // pPeerRTPAddr
  1233. pPeerRTCPAddr, // pPeerRTCPAddr
  1234. FALSE, // locally opened
  1235. 0, // bandwidth
  1236. &pChannel) != CC_OK) {
  1237. H245OpenChannelReject(pCall->H245Instance, // H245 instance
  1238. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel,
  1239. H245_REJ); // rejection reason
  1240. UnlockConference(pConference);
  1241. UnlockCall(pCall);
  1242. return H245_ERROR_OK;
  1243. }
  1244. if (AddChannelToConference(pChannel, pConference) != CC_OK) {
  1245. H245OpenChannelReject(pCall->H245Instance, // H245 instance
  1246. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel,
  1247. H245_REJ); // rejection reason
  1248. UnlockConference(pConference);
  1249. UnlockCall(pCall);
  1250. FreeChannel(pChannel);
  1251. return H245_ERROR_OK;
  1252. }
  1253. RxChannelRequestCallbackParams.hChannel = hChannel;
  1254. if ((pConference->ConferenceMode == MULTIPOINT_MODE) &&
  1255. (pConference->tsMultipointController == TS_TRUE)) {
  1256. // Open this channel to each peer in the conference (except the peer
  1257. // that requested this channel)
  1258. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  1259. for (i = 0; i < wNumCalls; i++) {
  1260. if (CallList[i] != hCall) {
  1261. if (LockCall(CallList[i], &pOldCall) == CC_OK) {
  1262. ASSERT(pChannel->bChannelType == PROXY_CHANNEL);
  1263. // Note: since this is a proxy channel, RxTermCap and RxMuxTable
  1264. // contain the channel's term cap and mux table, and must be sent
  1265. // to other endpoints as the Tx term cap and mux table;
  1266. // TxTermCap and TxMuxTable should be NULL
  1267. if (H245OpenChannel(pOldCall->H245Instance,
  1268. pChannel->hChannel, // dwTransId
  1269. pChannel->wLocalChannelNumber,
  1270. pChannel->pRxH245TermCap, // TxMode
  1271. pChannel->pRxMuxTable, // TxMux
  1272. H245_INVALID_PORT_NUMBER, // TxPort
  1273. pChannel->pTxH245TermCap, // RxMode
  1274. pChannel->pTxMuxTable, // RxMux
  1275. pChannel->pSeparateStack) == CC_OK)
  1276. (pChannel->wNumOutstandingRequests)++;
  1277. UnlockCall(pOldCall);
  1278. }
  1279. }
  1280. }
  1281. Free(CallList);
  1282. if (pConference->LocalEndpointAttached == ATTACHED)
  1283. (pChannel->wNumOutstandingRequests)++;
  1284. if (pChannel->wNumOutstandingRequests == 0) {
  1285. H245OpenChannelReject(pCall->H245Instance, // H245 instance
  1286. pH245ConfIndData->u.Indication.u.IndOpen.RxChannel,
  1287. H245_REJ); // rejection reason
  1288. UnlockConference(pConference);
  1289. UnlockCall(pCall);
  1290. FreeChannel(pChannel);
  1291. return H245_ERROR_OK;
  1292. }
  1293. } else
  1294. pChannel->wNumOutstandingRequests = 1;
  1295. InvokeUserConferenceCallback(pConference,
  1296. CC_RX_CHANNEL_REQUEST_INDICATION,
  1297. CC_OK,
  1298. &RxChannelRequestCallbackParams);
  1299. if (ValidateChannel(hChannel) == CC_OK)
  1300. UnlockChannel(pChannel);
  1301. if (ValidateCall(hCall) == CC_OK)
  1302. UnlockCall(pCall);
  1303. if (ValidateConference(hConference) == CC_OK)
  1304. UnlockConference(pConference);
  1305. return H245_ERROR_OK;
  1306. }
  1307. HRESULT _IndOpenConf( H245_CONF_IND_T *pH245ConfIndData)
  1308. {
  1309. CC_HCALL hCall;
  1310. PCALL pCall;
  1311. CC_HCONFERENCE hConference;
  1312. PCONFERENCE pConference;
  1313. CC_HCHANNEL hChannel;
  1314. CC_ACCEPT_CHANNEL_CALLBACK_PARAMS AcceptChannelCallbackParams;
  1315. // Bi-directional channel open initiated by remote peer is now complete.
  1316. // Local peer may now send data over this channel.
  1317. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  1318. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  1319. return H245_ERROR_OK;
  1320. hConference = pConference->hConference;
  1321. UnlockCall(pCall);
  1322. if (FindChannelInConference(pH245ConfIndData->u.Indication.u.IndOpenConf.TxChannel,
  1323. FALSE, // remote channel number
  1324. TXRX_CHANNEL,
  1325. hCall,
  1326. &hChannel,
  1327. pConference) != CC_OK) {
  1328. UnlockConference(pConference);
  1329. return H245_ERROR_OK;
  1330. }
  1331. AcceptChannelCallbackParams.hChannel = hChannel;
  1332. InvokeUserConferenceCallback(pConference,
  1333. CC_ACCEPT_CHANNEL_INDICATION,
  1334. CC_OK,
  1335. &AcceptChannelCallbackParams);
  1336. if (ValidateConference(hConference) == CC_OK)
  1337. UnlockConference(pConference);
  1338. return H245_ERROR_OK;
  1339. }
  1340. HRESULT _IndMstslv( H245_CONF_IND_T *pH245ConfIndData)
  1341. {
  1342. CC_HCALL hCall;
  1343. PCALL pCall;
  1344. PCONFERENCE pConference;
  1345. CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams;
  1346. CC_HCALL hEnqueuedCall;
  1347. PCALL pEnqueuedCall;
  1348. CC_HCONFERENCE hConference;
  1349. HRESULT status;
  1350. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  1351. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK) {
  1352. // Can't cancel with H245, because we don't have the H245 instance
  1353. return H245_ERROR_OK;
  1354. }
  1355. ASSERT(pCall->MasterSlaveState != MASTER_SLAVE_COMPLETE);
  1356. switch (pH245ConfIndData->u.Indication.u.IndMstSlv) {
  1357. case H245_MASTER:
  1358. pConference->tsMaster = TS_TRUE;
  1359. if (pConference->tsMultipointController == TS_UNKNOWN) {
  1360. ASSERT(pConference->bMultipointCapable == TRUE);
  1361. pConference->tsMultipointController = TS_TRUE;
  1362. // place all calls enqueued on this conference object
  1363. for ( ; ; ) {
  1364. // Start up all enqueued calls, if any exist
  1365. status = RemoveEnqueuedCallFromConference(pConference, &hEnqueuedCall);
  1366. if ((status != CC_OK) || (hEnqueuedCall == CC_INVALID_HANDLE))
  1367. break;
  1368. status = LockCall(hEnqueuedCall, &pEnqueuedCall);
  1369. if (status == CC_OK) {
  1370. pEnqueuedCall->CallState = PLACED;
  1371. status = PlaceCall(pEnqueuedCall, pConference);
  1372. UnlockCall(pEnqueuedCall);
  1373. }
  1374. }
  1375. }
  1376. break;
  1377. case H245_SLAVE:
  1378. ASSERT(pConference->tsMaster != TS_TRUE);
  1379. ASSERT(pConference->tsMultipointController != TS_TRUE);
  1380. pConference->tsMaster = TS_FALSE;
  1381. pConference->tsMultipointController = TS_FALSE;
  1382. // XXX -- we may eventually want to re-enqueue these requests
  1383. // and set an expiration timer
  1384. hConference = pConference->hConference;
  1385. for ( ; ; ) {
  1386. status = RemoveEnqueuedCallFromConference(pConference, &hEnqueuedCall);
  1387. if ((status != CC_OK) || (hEnqueuedCall == CC_INVALID_HANDLE))
  1388. break;
  1389. status = LockCall(hEnqueuedCall, &pEnqueuedCall);
  1390. if (status == CC_OK) {
  1391. MarkCallForDeletion(pEnqueuedCall);
  1392. ConnectCallbackParams.pNonStandardData = pEnqueuedCall->pPeerNonStandardData;
  1393. ConnectCallbackParams.pszPeerDisplay = pEnqueuedCall->pszPeerDisplay;
  1394. ConnectCallbackParams.bRejectReason = CC_REJECT_UNDEFINED_REASON;
  1395. ConnectCallbackParams.pTermCapList = pEnqueuedCall->pPeerH245TermCapList;
  1396. ConnectCallbackParams.pH2250MuxCapability = pEnqueuedCall->pPeerH245H2250MuxCapability;
  1397. ConnectCallbackParams.pTermCapDescriptors = pEnqueuedCall->pPeerH245TermCapDescriptors;
  1398. ConnectCallbackParams.pLocalAddr = pEnqueuedCall->pQ931LocalConnectAddr;
  1399. if (pEnqueuedCall->pQ931DestinationAddr == NULL)
  1400. ConnectCallbackParams.pPeerAddr = pEnqueuedCall->pQ931PeerConnectAddr;
  1401. else
  1402. ConnectCallbackParams.pPeerAddr = pEnqueuedCall->pQ931DestinationAddr;
  1403. ConnectCallbackParams.pVendorInfo = pEnqueuedCall->pPeerVendorInfo;
  1404. ConnectCallbackParams.bMultipointConference = TRUE;
  1405. ConnectCallbackParams.pConferenceID = &pConference->ConferenceID;
  1406. ConnectCallbackParams.pMCAddress = pConference->pMultipointControllerAddr;
  1407. ConnectCallbackParams.pAlternateAddress = NULL;
  1408. ConnectCallbackParams.dwUserToken = pEnqueuedCall->dwUserToken;
  1409. InvokeUserConferenceCallback(pConference,
  1410. CC_CONNECT_INDICATION,
  1411. CC_NOT_MULTIPOINT_CAPABLE,
  1412. &ConnectCallbackParams);
  1413. if (ValidateCallMarkedForDeletion(hEnqueuedCall) == CC_OK)
  1414. FreeCall(pEnqueuedCall);
  1415. if (ValidateConference(hConference) != CC_OK) {
  1416. if (ValidateCall(hCall) == CC_OK)
  1417. UnlockCall(pCall);
  1418. return H245_ERROR_OK;
  1419. }
  1420. }
  1421. }
  1422. break;
  1423. default: // H245_INDETERMINATE
  1424. UnlockConference(pConference);
  1425. if (++pCall->wMasterSlaveRetry < MASTER_SLAVE_RETRY_MAX) {
  1426. H245InitMasterSlave(pCall->H245Instance, pCall->H245Instance);
  1427. UnlockCall(pCall);
  1428. } else {
  1429. UnlockCall(pCall);
  1430. ProcessRemoteHangup(hCall, CC_INVALID_HANDLE, CC_REJECT_UNDEFINED_REASON);
  1431. }
  1432. return H245_ERROR_OK;
  1433. } // switch
  1434. pCall->MasterSlaveState = MASTER_SLAVE_COMPLETE;
  1435. if ((pCall->OutgoingTermCapState == TERMCAP_COMPLETE) &&
  1436. (pCall->IncomingTermCapState == TERMCAP_COMPLETE) &&
  1437. (pCall->CallState == TERMCAP) &&
  1438. (pCall->MasterSlaveState == MASTER_SLAVE_COMPLETE)) {
  1439. // Note that _ProcessConnectionComplete() returns with pConference and pCall unlocked
  1440. _ProcessConnectionComplete(pConference, pCall);
  1441. return H245_ERROR_OK;
  1442. }
  1443. UnlockCall(pCall);
  1444. UnlockConference(pConference);
  1445. return H245_ERROR_OK;
  1446. }
  1447. HRESULT _IndClose( H245_CONF_IND_T *pH245ConfIndData)
  1448. {
  1449. CC_HCALL hCall;
  1450. PCALL pCall;
  1451. CC_HCONFERENCE hConference;
  1452. PCONFERENCE pConference;
  1453. CC_HCHANNEL hChannel;
  1454. PCHANNEL pChannel;
  1455. WORD i;
  1456. WORD wNumCalls;
  1457. PCC_HCALL CallList;
  1458. CC_RX_CHANNEL_CLOSE_CALLBACK_PARAMS RxChannelCloseCallbackParams;
  1459. #ifdef GATEKEEPER
  1460. unsigned uBandwidth;
  1461. #endif // GATEKEEPER
  1462. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  1463. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  1464. return H245_ERROR_OK;
  1465. hConference = pCall->hConference;
  1466. UnlockCall(pCall);
  1467. if (FindChannelInConference(pH245ConfIndData->u.Indication.u.IndClose.Channel,
  1468. FALSE, // remote channel number
  1469. RX_CHANNEL | TXRX_CHANNEL | PROXY_CHANNEL,
  1470. hCall,
  1471. &hChannel,
  1472. pConference) != CC_OK) {
  1473. UnlockConference(pConference);
  1474. return H245_ERROR_OK;
  1475. }
  1476. if (LockChannel(hChannel, &pChannel) != CC_OK)
  1477. return H245_ERROR_OK;
  1478. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  1479. #ifdef GATEKEEPER
  1480. if (pChannel->bChannelType != TXRX_CHANNEL) {
  1481. uBandwidth = pChannel->dwBandwidth / 100;
  1482. for (i = 0; i < wNumCalls; i++) {
  1483. if (LockCall(CallList[i], &pCall) == CC_OK) {
  1484. if (uBandwidth && pCall->GkiCall.uBandwidthUsed >= uBandwidth) {
  1485. if (GkiCloseChannel(&pCall->GkiCall, pChannel->dwBandwidth, hChannel) == CC_OK) {
  1486. uBandwidth = 0;
  1487. UnlockCall(pCall);
  1488. break;
  1489. }
  1490. }
  1491. UnlockCall(pCall);
  1492. }
  1493. } // for
  1494. }
  1495. #endif // GATEKEEPER
  1496. if (pChannel->bChannelType == PROXY_CHANNEL) {
  1497. ASSERT(pConference->ConferenceMode == MULTIPOINT_MODE);
  1498. ASSERT(pConference->tsMultipointController == TS_TRUE);
  1499. ASSERT(pChannel->bMultipointChannel == TRUE);
  1500. for (i = 0; i < wNumCalls; i++) {
  1501. if (CallList[i] != hCall) {
  1502. if (LockCall(CallList[i], &pCall) == CC_OK) {
  1503. H245CloseChannel(pCall->H245Instance, // H245 instance
  1504. 0, // dwTransId
  1505. pChannel->wLocalChannelNumber);
  1506. UnlockCall(pCall);
  1507. }
  1508. }
  1509. }
  1510. }
  1511. if (CallList != NULL)
  1512. Free(CallList);
  1513. if (pChannel->tsAccepted == TS_TRUE) {
  1514. RxChannelCloseCallbackParams.hChannel = hChannel;
  1515. InvokeUserConferenceCallback(pConference,
  1516. CC_RX_CHANNEL_CLOSE_INDICATION,
  1517. CC_OK,
  1518. &RxChannelCloseCallbackParams);
  1519. }
  1520. if (ValidateChannel(hChannel) == CC_OK)
  1521. FreeChannel(pChannel);
  1522. if (ValidateConference(hConference) == CC_OK)
  1523. UnlockConference(pConference);
  1524. return H245_ERROR_OK;
  1525. }
  1526. HRESULT _IndRequestClose( H245_CONF_IND_T *pH245ConfIndData)
  1527. {
  1528. CC_HCALL hCall;
  1529. PCALL pCall;
  1530. CC_HCONFERENCE hConference;
  1531. PCONFERENCE pConference;
  1532. CC_HCHANNEL hChannel;
  1533. PCHANNEL pChannel;
  1534. CC_TX_CHANNEL_CLOSE_REQUEST_CALLBACK_PARAMS TxChannelCloseRequestCallbackParams;
  1535. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  1536. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  1537. return H245_ERROR_OK;
  1538. hConference = pCall->hConference;
  1539. UnlockCall(pCall);
  1540. if (FindChannelInConference(pH245ConfIndData->u.Indication.u.IndClose.Channel,
  1541. TRUE, // local channel number
  1542. TX_CHANNEL | TXRX_CHANNEL | PROXY_CHANNEL,
  1543. CC_INVALID_HANDLE,
  1544. &hChannel,
  1545. pConference) != CC_OK) {
  1546. UnlockConference(pConference);
  1547. return H245_ERROR_OK;
  1548. }
  1549. if (LockChannel(hChannel, &pChannel) != CC_OK) {
  1550. UnlockConference(pConference);
  1551. return H245_ERROR_OK;
  1552. }
  1553. if ((pChannel->bChannelType == TX_CHANNEL) ||
  1554. (pChannel->bChannelType == TXRX_CHANNEL)) {
  1555. EnqueueRequest(&pChannel->pCloseRequests, hCall);
  1556. UnlockChannel(pChannel);
  1557. TxChannelCloseRequestCallbackParams.hChannel = hChannel;
  1558. InvokeUserConferenceCallback(pConference,
  1559. CC_TX_CHANNEL_CLOSE_REQUEST_INDICATION,
  1560. CC_OK,
  1561. &TxChannelCloseRequestCallbackParams);
  1562. if (ValidateConference(hConference) == CC_OK)
  1563. UnlockConference(pConference);
  1564. } else { // pChannel->bChannelType == PROXY_CHANNEL
  1565. if (LockCall(pChannel->hCall, &pCall) == CC_OK) {
  1566. // Note that dwTransID is set to the call handle of the peer who
  1567. // initiated the close channel request. When the close channel response
  1568. // is received, the dwTransID gives us back the call handle to which
  1569. // the response must be forwarded
  1570. H245CloseChannelReq(pCall->H245Instance,
  1571. hCall, // dwTransID
  1572. pChannel->wRemoteChannelNumber);
  1573. UnlockCall(pCall);
  1574. }
  1575. UnlockChannel(pChannel);
  1576. UnlockConference(pConference);
  1577. }
  1578. return H245_ERROR_OK;
  1579. }
  1580. HRESULT _IndNonStandard( H245_CONF_IND_T *pH245ConfIndData)
  1581. {
  1582. CC_HCALL hCall;
  1583. PCALL pCall;
  1584. CC_HCONFERENCE hConference;
  1585. PCONFERENCE pConference;
  1586. CC_RX_NONSTANDARD_MESSAGE_CALLBACK_PARAMS RxNonStandardMessageCallbackParams;
  1587. // We only handle H221 non-standard messages; if pwObjectId is non-NULL,
  1588. // ignore the message
  1589. if (pH245ConfIndData->u.Indication.u.IndNonstandard.pwObjectId != NULL)
  1590. return H245_ERROR_OK;
  1591. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  1592. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  1593. return H245_ERROR_OK;
  1594. hConference = pCall->hConference;
  1595. switch (pH245ConfIndData->u.Indication.Indicator) {
  1596. case H245_IND_NONSTANDARD_REQUEST:
  1597. RxNonStandardMessageCallbackParams.bH245MessageType = CC_H245_MESSAGE_REQUEST;
  1598. break;
  1599. case H245_IND_NONSTANDARD_RESPONSE:
  1600. RxNonStandardMessageCallbackParams.bH245MessageType = CC_H245_MESSAGE_RESPONSE;
  1601. break;
  1602. case H245_IND_NONSTANDARD_COMMAND:
  1603. RxNonStandardMessageCallbackParams.bH245MessageType = CC_H245_MESSAGE_COMMAND;
  1604. break;
  1605. case H245_IND_NONSTANDARD:
  1606. RxNonStandardMessageCallbackParams.bH245MessageType = CC_H245_MESSAGE_INDICATION;
  1607. break;
  1608. default:
  1609. UnlockConference(pConference);
  1610. return H245_ERROR_NOSUP;
  1611. }
  1612. RxNonStandardMessageCallbackParams.NonStandardData.sData.pOctetString =
  1613. pH245ConfIndData->u.Indication.u.IndNonstandard.pData;
  1614. RxNonStandardMessageCallbackParams.NonStandardData.sData.wOctetStringLength =
  1615. (WORD)pH245ConfIndData->u.Indication.u.IndNonstandard.dwDataLength;
  1616. RxNonStandardMessageCallbackParams.NonStandardData.bCountryCode =
  1617. pH245ConfIndData->u.Indication.u.IndNonstandard.byCountryCode;
  1618. RxNonStandardMessageCallbackParams.NonStandardData.bExtension =
  1619. pH245ConfIndData->u.Indication.u.IndNonstandard.byExtension;
  1620. RxNonStandardMessageCallbackParams.NonStandardData.wManufacturerCode =
  1621. pH245ConfIndData->u.Indication.u.IndNonstandard.wManufacturerCode;
  1622. RxNonStandardMessageCallbackParams.hCall = pCall->hCall;
  1623. if (pCall->pPeerParticipantInfo != NULL)
  1624. RxNonStandardMessageCallbackParams.InitiatorTerminalLabel =
  1625. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  1626. else {
  1627. RxNonStandardMessageCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  1628. RxNonStandardMessageCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  1629. }
  1630. InvokeUserConferenceCallback(pConference,
  1631. CC_RX_NONSTANDARD_MESSAGE_INDICATION,
  1632. CC_OK,
  1633. &RxNonStandardMessageCallbackParams);
  1634. if (ValidateConference(hConference) == CC_OK)
  1635. UnlockConference(pConference);
  1636. if (ValidateCall(hCall) == CC_OK)
  1637. UnlockCall(pCall);
  1638. return H245_ERROR_OK;
  1639. }
  1640. HRESULT _IndMiscellaneous( H245_CONF_IND_T *pH245ConfIndData,
  1641. MiscellaneousIndication *pMiscellaneousIndication)
  1642. {
  1643. HRESULT status = CC_OK;
  1644. CC_HCALL hCall;
  1645. PCALL pCall;
  1646. PCALL pOldCall;
  1647. CC_HCONFERENCE hConference;
  1648. PCONFERENCE pConference;
  1649. CC_HCHANNEL hChannel;
  1650. PCHANNEL pChannel;
  1651. WORD i;
  1652. WORD wNumCalls;
  1653. PCC_HCALL CallList;
  1654. PDU_T Pdu;
  1655. CC_MUTE_CALLBACK_PARAMS MuteCallbackParams;
  1656. CC_UNMUTE_CALLBACK_PARAMS UnMuteCallbackParams;
  1657. CC_H245_MISCELLANEOUS_INDICATION_CALLBACK_PARAMS H245MiscellaneousIndicationCallbackParams;
  1658. if (pMiscellaneousIndication == NULL)
  1659. // Should never hit this case
  1660. return H245_ERROR_NOSUP;
  1661. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  1662. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  1663. return H245_ERROR_OK;
  1664. hConference = pCall->hConference;
  1665. switch (pMiscellaneousIndication->type.choice) {
  1666. case logicalChannelActive_chosen:
  1667. case logicalChannelInactive_chosen:
  1668. UnlockCall(pCall);
  1669. if (FindChannelInConference(pMiscellaneousIndication->logicalChannelNumber,
  1670. FALSE, // remote channel number
  1671. RX_CHANNEL | PROXY_CHANNEL,
  1672. hCall,
  1673. &hChannel,
  1674. pConference) != CC_OK) {
  1675. UnlockConference(pConference);
  1676. return H245_ERROR_OK;
  1677. }
  1678. if (LockChannel(hChannel, &pChannel) != CC_OK) {
  1679. UnlockConference(pConference);
  1680. return H245_ERROR_OK;
  1681. }
  1682. if (pChannel->bChannelType == PROXY_CHANNEL) {
  1683. ASSERT(pConference->ConferenceMode == MULTIPOINT_MODE);
  1684. ASSERT(pConference->tsMultipointController == TS_TRUE);
  1685. ASSERT(pChannel->bMultipointChannel == TRUE);
  1686. // Construct an H.245 PDU to hold a miscellaneous indication
  1687. // of "logical channel inactive" (mute) or "logical channel active" (unmute)
  1688. Pdu.choice = indication_chosen;
  1689. Pdu.u.indication.choice = miscellaneousIndication_chosen;
  1690. Pdu.u.indication.u.miscellaneousIndication.logicalChannelNumber =
  1691. pChannel->wLocalChannelNumber;
  1692. Pdu.u.indication.u.miscellaneousIndication.type.choice =
  1693. pMiscellaneousIndication->type.choice;
  1694. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  1695. for (i = 0; i < wNumCalls; i++) {
  1696. if (CallList[i] != hCall) {
  1697. if (LockCall(CallList[i], &pCall) == CC_OK) {
  1698. H245SendPDU(pCall->H245Instance, &Pdu);
  1699. UnlockCall(pCall);
  1700. }
  1701. }
  1702. }
  1703. Free(CallList);
  1704. }
  1705. if (pMiscellaneousIndication->type.choice == logicalChannelActive_chosen) {
  1706. if (pChannel->tsAccepted == TS_TRUE) {
  1707. UnMuteCallbackParams.hChannel = hChannel;
  1708. InvokeUserConferenceCallback(pConference,
  1709. CC_UNMUTE_INDICATION,
  1710. CC_OK,
  1711. &UnMuteCallbackParams);
  1712. }
  1713. } else {
  1714. if (pChannel->tsAccepted == TS_TRUE) {
  1715. MuteCallbackParams.hChannel = hChannel;
  1716. InvokeUserConferenceCallback(pConference,
  1717. CC_MUTE_INDICATION,
  1718. CC_OK,
  1719. &MuteCallbackParams);
  1720. }
  1721. }
  1722. if (ValidateChannel(hChannel) == CC_OK)
  1723. UnlockChannel(pChannel);
  1724. if (ValidateConference(hConference) == CC_OK)
  1725. UnlockConference(pConference);
  1726. status = H245_ERROR_OK;
  1727. break;
  1728. case multipointConference_chosen:
  1729. case cnclMltpntCnfrnc_chosen:
  1730. // We're required to support receipt of this indication, but I have no
  1731. // idea what we're supposed to do with it
  1732. UnlockCall(pCall);
  1733. UnlockConference(pConference);
  1734. status = H245_ERROR_OK;
  1735. break;
  1736. case vdIndctRdyTActvt_chosen:
  1737. case MIn_tp_vdTmprlSptlTrdOff_chosen:
  1738. if (FindChannelInConference(pMiscellaneousIndication->logicalChannelNumber,
  1739. FALSE, // remote channel number
  1740. RX_CHANNEL | PROXY_CHANNEL,
  1741. hCall,
  1742. &hChannel,
  1743. pConference) != CC_OK) {
  1744. UnlockCall(pCall);
  1745. UnlockConference(pConference);
  1746. return H245_ERROR_OK;
  1747. }
  1748. if (LockChannel(hChannel, &pChannel) != CC_OK) {
  1749. UnlockCall(pCall);
  1750. UnlockConference(pConference);
  1751. return H245_ERROR_OK;
  1752. }
  1753. if (pChannel->bChannelType == PROXY_CHANNEL) {
  1754. ASSERT(pConference->ConferenceMode == MULTIPOINT_MODE);
  1755. ASSERT(pConference->tsMultipointController == TS_TRUE);
  1756. ASSERT(pChannel->bMultipointChannel == TRUE);
  1757. // Construct an H.245 PDU to hold a miscellaneous indication
  1758. // of "video indicate ready to activate" or
  1759. // "video temporal spatial tradeoff"
  1760. Pdu.choice = indication_chosen;
  1761. Pdu.u.indication.choice = miscellaneousIndication_chosen;
  1762. Pdu.u.indication.u.miscellaneousIndication.logicalChannelNumber =
  1763. pChannel->wLocalChannelNumber;
  1764. Pdu.u.indication.u.miscellaneousIndication.type.choice =
  1765. pMiscellaneousIndication->type.choice;
  1766. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  1767. for (i = 0; i < wNumCalls; i++) {
  1768. if (CallList[i] != hCall) {
  1769. if (LockCall(CallList[i], &pOldCall) == CC_OK) {
  1770. H245SendPDU(pOldCall->H245Instance, &Pdu);
  1771. UnlockCall(pOldCall);
  1772. }
  1773. }
  1774. }
  1775. Free(CallList);
  1776. }
  1777. if (pChannel->tsAccepted == TS_TRUE) {
  1778. H245MiscellaneousIndicationCallbackParams.hCall = hCall;
  1779. if (pCall->pPeerParticipantInfo == NULL) {
  1780. H245MiscellaneousIndicationCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  1781. H245MiscellaneousIndicationCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  1782. } else
  1783. H245MiscellaneousIndicationCallbackParams.InitiatorTerminalLabel =
  1784. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  1785. H245MiscellaneousIndicationCallbackParams.hChannel = hChannel;
  1786. H245MiscellaneousIndicationCallbackParams.pMiscellaneousIndication =
  1787. pMiscellaneousIndication;
  1788. status = InvokeUserConferenceCallback(pConference,
  1789. CC_H245_MISCELLANEOUS_INDICATION_INDICATION,
  1790. CC_OK,
  1791. &H245MiscellaneousIndicationCallbackParams);
  1792. if (status != CC_OK)
  1793. status = H245_ERROR_NOSUP;
  1794. } else
  1795. status = H245_ERROR_OK;
  1796. if (ValidateChannel(hChannel) == CC_OK)
  1797. UnlockChannel(pChannel);
  1798. if (ValidateCall(hCall) == CC_OK)
  1799. UnlockCall(pCall);
  1800. if (ValidateConference(hConference) == CC_OK)
  1801. UnlockConference(pConference);
  1802. break;
  1803. case videoNotDecodedMBs_chosen:
  1804. if (FindChannelInConference(pMiscellaneousIndication->logicalChannelNumber,
  1805. TRUE, // local channel number
  1806. TX_CHANNEL | PROXY_CHANNEL,
  1807. CC_INVALID_HANDLE,
  1808. &hChannel,
  1809. pConference) != CC_OK) {
  1810. UnlockCall(pCall);
  1811. UnlockConference(pConference);
  1812. return H245_ERROR_OK;
  1813. }
  1814. if (LockChannel(hChannel, &pChannel) != CC_OK) {
  1815. UnlockCall(pCall);
  1816. UnlockConference(pConference);
  1817. return H245_ERROR_OK;
  1818. }
  1819. if (pChannel->bChannelType == TX_CHANNEL) {
  1820. H245MiscellaneousIndicationCallbackParams.hCall = hCall;
  1821. if (pCall->pPeerParticipantInfo == NULL) {
  1822. H245MiscellaneousIndicationCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  1823. H245MiscellaneousIndicationCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  1824. } else
  1825. H245MiscellaneousIndicationCallbackParams.InitiatorTerminalLabel =
  1826. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  1827. H245MiscellaneousIndicationCallbackParams.hChannel = hChannel;
  1828. H245MiscellaneousIndicationCallbackParams.pMiscellaneousIndication =
  1829. pMiscellaneousIndication;
  1830. status = InvokeUserConferenceCallback(pConference,
  1831. CC_H245_MISCELLANEOUS_INDICATION_INDICATION,
  1832. CC_OK,
  1833. &H245MiscellaneousIndicationCallbackParams);
  1834. if (status != CC_OK)
  1835. status = H245_ERROR_NOSUP;
  1836. if (ValidateChannel(hChannel) == CC_OK)
  1837. UnlockChannel(pChannel);
  1838. if (ValidateCall(hCall) == CC_OK)
  1839. UnlockCall(pCall);
  1840. if (ValidateConference(hConference) == CC_OK)
  1841. UnlockConference(pConference);
  1842. return status;
  1843. } else {
  1844. // Proxy channel; forward the request to the transmitter
  1845. ASSERT(pConference->ConferenceMode == MULTIPOINT_MODE);
  1846. ASSERT(pConference->tsMultipointController == TS_TRUE);
  1847. ASSERT(pChannel->bMultipointChannel == TRUE);
  1848. // Construct an H.245 PDU to hold a miscellaneous indication
  1849. // of "video not decoded MBs"
  1850. Pdu.choice = indication_chosen;
  1851. Pdu.u.indication.choice = miscellaneousIndication_chosen;
  1852. Pdu.u.indication.u.miscellaneousIndication.logicalChannelNumber =
  1853. pChannel->wRemoteChannelNumber;
  1854. Pdu.u.indication.u.miscellaneousIndication.type.choice =
  1855. pMiscellaneousIndication->type.choice;
  1856. if (LockCall(pChannel->hCall, &pOldCall) == CC_OK) {
  1857. H245SendPDU(pOldCall->H245Instance, &Pdu);
  1858. UnlockCall(pOldCall);
  1859. }
  1860. UnlockChannel(pChannel);
  1861. UnlockCall(pCall);
  1862. UnlockConference(pConference);
  1863. return H245_ERROR_OK;
  1864. }
  1865. // We should never reach here
  1866. ASSERT(0);
  1867. default:
  1868. // Miscellaneous indication not containing channel information
  1869. // Pass it up to the client
  1870. H245MiscellaneousIndicationCallbackParams.hCall = hCall;
  1871. if (pCall->pPeerParticipantInfo == NULL) {
  1872. H245MiscellaneousIndicationCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  1873. H245MiscellaneousIndicationCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  1874. } else
  1875. H245MiscellaneousIndicationCallbackParams.InitiatorTerminalLabel =
  1876. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  1877. H245MiscellaneousIndicationCallbackParams.hChannel = CC_INVALID_HANDLE;;
  1878. H245MiscellaneousIndicationCallbackParams.pMiscellaneousIndication =
  1879. pMiscellaneousIndication;
  1880. status = InvokeUserConferenceCallback(pConference,
  1881. CC_H245_MISCELLANEOUS_INDICATION_INDICATION,
  1882. CC_OK,
  1883. &H245MiscellaneousIndicationCallbackParams);
  1884. if (status != CC_OK)
  1885. status = H245_ERROR_NOSUP;
  1886. if (ValidateCall(hCall) == CC_OK)
  1887. UnlockCall(pCall);
  1888. if (ValidateConference(hConference) == CC_OK)
  1889. UnlockConference(pConference);
  1890. break;
  1891. }
  1892. return status;
  1893. // We should never reach this point
  1894. ASSERT(0);
  1895. }
  1896. HRESULT _IndMiscellaneousCommand( H245_CONF_IND_T *pH245ConfIndData,
  1897. MiscellaneousCommand *pMiscellaneousCommand)
  1898. {
  1899. CC_HCALL hCall;
  1900. PCALL pCall;
  1901. PCALL pOldCall;
  1902. CC_HCONFERENCE hConference;
  1903. PCONFERENCE pConference;
  1904. HRESULT status = CC_OK;
  1905. WORD wChoice;
  1906. CC_HCHANNEL hChannel;
  1907. PCHANNEL pChannel;
  1908. PDU_T Pdu;
  1909. CC_H245_MISCELLANEOUS_COMMAND_CALLBACK_PARAMS H245MiscellaneousCommandCallbackParams;
  1910. if (pMiscellaneousCommand == NULL)
  1911. // Should never hit this case
  1912. return H245_ERROR_NOSUP;
  1913. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  1914. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  1915. return H245_ERROR_OK;
  1916. hConference = pConference->hConference;
  1917. switch (pMiscellaneousCommand->type.choice) {
  1918. case multipointModeCommand_chosen:
  1919. if (pConference->bMultipointCapable == FALSE) {
  1920. // We can't support multipoint operation, so treat this as if
  1921. // we received a remote hangup indication
  1922. UnlockConference(pConference);
  1923. UnlockCall(pCall);
  1924. ProcessRemoteHangup(hCall, CC_INVALID_HANDLE, CC_REJECT_NORMAL_CALL_CLEARING);
  1925. return H245_ERROR_OK;
  1926. } else {
  1927. pConference->ConferenceMode = MULTIPOINT_MODE;
  1928. // Send TerminalListRequest
  1929. H245ConferenceRequest(pCall->H245Instance,
  1930. H245_REQ_TERMINAL_LIST,
  1931. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bMCUNumber,
  1932. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bTerminalNumber);
  1933. }
  1934. status = H245_ERROR_OK;
  1935. break;
  1936. case cnclMltpntMdCmmnd_chosen:
  1937. // We're required to support receipt of this command, but I have no
  1938. // idea what we're supposed to do with it
  1939. status = H245_ERROR_OK;
  1940. break;
  1941. case videoFreezePicture_chosen:
  1942. case videoFastUpdatePicture_chosen:
  1943. case videoFastUpdateGOB_chosen:
  1944. case MCd_tp_vdTmprlSptlTrdOff_chosen:
  1945. case videoSendSyncEveryGOB_chosen:
  1946. case videoFastUpdateMB_chosen:
  1947. case vdSndSyncEvryGOBCncl_chosen:
  1948. if (FindChannelInConference(pMiscellaneousCommand->logicalChannelNumber,
  1949. TRUE, // local channel number
  1950. TX_CHANNEL | PROXY_CHANNEL,
  1951. CC_INVALID_HANDLE,
  1952. &hChannel,
  1953. pConference) != CC_OK) {
  1954. UnlockCall(pCall);
  1955. UnlockConference(pConference);
  1956. return H245_ERROR_OK;
  1957. }
  1958. if (LockChannel(hChannel, &pChannel) != CC_OK) {
  1959. UnlockCall(pCall);
  1960. UnlockConference(pConference);
  1961. return H245_ERROR_OK;
  1962. }
  1963. if (pChannel->bChannelType == TX_CHANNEL) {
  1964. H245MiscellaneousCommandCallbackParams.hCall = hCall;
  1965. if (pCall->pPeerParticipantInfo == NULL) {
  1966. H245MiscellaneousCommandCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  1967. H245MiscellaneousCommandCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  1968. } else
  1969. H245MiscellaneousCommandCallbackParams.InitiatorTerminalLabel =
  1970. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  1971. H245MiscellaneousCommandCallbackParams.hChannel = hChannel;
  1972. wChoice = pMiscellaneousCommand->type.choice;
  1973. if ((wChoice == videoFreezePicture_chosen) ||
  1974. (wChoice == videoFastUpdatePicture_chosen) ||
  1975. (wChoice == videoFastUpdateGOB_chosen) ||
  1976. (wChoice == videoFastUpdateMB_chosen))
  1977. H245MiscellaneousCommandCallbackParams.bH323ActionRequired = TRUE;
  1978. else
  1979. H245MiscellaneousCommandCallbackParams.bH323ActionRequired = FALSE;
  1980. H245MiscellaneousCommandCallbackParams.pMiscellaneousCommand =
  1981. pMiscellaneousCommand;
  1982. status = InvokeUserConferenceCallback(pConference,
  1983. CC_H245_MISCELLANEOUS_COMMAND_INDICATION,
  1984. CC_OK,
  1985. &H245MiscellaneousCommandCallbackParams);
  1986. if (status != CC_OK)
  1987. status = H245_ERROR_NOSUP;
  1988. if (ValidateChannel(hChannel) == CC_OK)
  1989. UnlockChannel(pChannel);
  1990. if (ValidateCall(hCall) == CC_OK)
  1991. UnlockCall(pCall);
  1992. if (ValidateConference(hConference) == CC_OK)
  1993. UnlockConference(pConference);
  1994. return status;
  1995. } else {
  1996. // Proxy channel; forward the request to the transmitter
  1997. ASSERT(pConference->ConferenceMode == MULTIPOINT_MODE);
  1998. ASSERT(pConference->tsMultipointController == TS_TRUE);
  1999. ASSERT(pChannel->bMultipointChannel == TRUE);
  2000. Pdu.choice = MSCMg_cmmnd_chosen;
  2001. Pdu.u.MSCMg_cmmnd.choice = miscellaneousCommand_chosen;
  2002. Pdu.u.MSCMg_cmmnd.u.miscellaneousCommand.logicalChannelNumber =
  2003. pChannel->wRemoteChannelNumber;
  2004. Pdu.u.MSCMg_cmmnd.u.miscellaneousCommand = *pMiscellaneousCommand;
  2005. if (LockCall(pChannel->hCall, &pOldCall) == CC_OK) {
  2006. H245SendPDU(pOldCall->H245Instance, &Pdu);
  2007. UnlockCall(pOldCall);
  2008. }
  2009. UnlockChannel(pChannel);
  2010. UnlockCall(pCall);
  2011. UnlockConference(pConference);
  2012. return H245_ERROR_OK;
  2013. }
  2014. // We should never reach here
  2015. ASSERT(0);
  2016. default:
  2017. // Unrecognized miscellaneous command
  2018. // Pass it up to the client
  2019. H245MiscellaneousCommandCallbackParams.hCall = hCall;
  2020. if (pCall->pPeerParticipantInfo == NULL) {
  2021. H245MiscellaneousCommandCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  2022. H245MiscellaneousCommandCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  2023. } else
  2024. H245MiscellaneousCommandCallbackParams.InitiatorTerminalLabel =
  2025. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  2026. H245MiscellaneousCommandCallbackParams.hChannel = CC_INVALID_HANDLE;
  2027. H245MiscellaneousCommandCallbackParams.bH323ActionRequired = FALSE;
  2028. H245MiscellaneousCommandCallbackParams.pMiscellaneousCommand =
  2029. pMiscellaneousCommand;
  2030. status = InvokeUserConferenceCallback(pConference,
  2031. CC_H245_MISCELLANEOUS_COMMAND_INDICATION,
  2032. CC_OK,
  2033. &H245MiscellaneousCommandCallbackParams);
  2034. if (status != CC_OK)
  2035. status = H245_ERROR_NOSUP;
  2036. if (ValidateCall(hCall) == CC_OK)
  2037. UnlockCall(pCall);
  2038. if (ValidateConference(hConference) == CC_OK)
  2039. UnlockConference(pConference);
  2040. return status;
  2041. }
  2042. if (ValidateCall(hCall) == CC_OK)
  2043. UnlockCall(pCall);
  2044. if (ValidateConference(hConference) == CC_OK)
  2045. UnlockConference(pConference);
  2046. return status;
  2047. // We should never reach this point
  2048. ASSERT(0);
  2049. }
  2050. HRESULT _IndMCLocation( H245_CONF_IND_T *pH245ConfIndData)
  2051. {
  2052. CC_HCALL hCall;
  2053. PCALL pCall;
  2054. PCONFERENCE pConference;
  2055. CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams;
  2056. PCALL pEnqueuedCall;
  2057. CC_HCALL hEnqueuedCall;
  2058. HRESULT status;
  2059. CC_HCONFERENCE hConference;
  2060. if (pH245ConfIndData->u.Indication.u.IndMcLocation.type != H245_IP_UNICAST)
  2061. return H245_ERROR_OK;
  2062. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  2063. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  2064. return H245_ERROR_OK;
  2065. UnlockCall(pCall);
  2066. hConference = pConference->hConference;
  2067. if (pConference->tsMultipointController != TS_FALSE) {
  2068. // We don't expect to receive an MCLocationIndication until master/slave
  2069. // has completed, at which time tsMultipointController will change from
  2070. // TS_UNKNOWN to either TS_TRUE or TS_FALSE.
  2071. UnlockConference(pConference);
  2072. return H245_ERROR_NOSUP;
  2073. }
  2074. if (pConference->pMultipointControllerAddr == NULL) {
  2075. pConference->pMultipointControllerAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  2076. if (pConference->pMultipointControllerAddr == NULL) {
  2077. UnlockConference(pConference);
  2078. return H245_ERROR_OK;
  2079. }
  2080. }
  2081. pConference->pMultipointControllerAddr->nAddrType = CC_IP_BINARY;
  2082. pConference->pMultipointControllerAddr->bMulticast = FALSE;
  2083. pConference->pMultipointControllerAddr->Addr.IP_Binary.wPort =
  2084. pH245ConfIndData->u.Indication.u.IndMcLocation.u.ip.tsapIdentifier;
  2085. H245IPNetworkToHost(&pConference->pMultipointControllerAddr->Addr.IP_Binary.dwAddr,
  2086. pH245ConfIndData->u.Indication.u.IndMcLocation.u.ip.network);
  2087. // place all calls enqueued on this conference object
  2088. for ( ; ; ) {
  2089. // Start up all enqueued calls, if any exist
  2090. status = RemoveEnqueuedCallFromConference(pConference, &hEnqueuedCall);
  2091. if ((status != CC_OK) || (hEnqueuedCall == CC_INVALID_HANDLE))
  2092. break;
  2093. status = LockCall(hEnqueuedCall, &pEnqueuedCall);
  2094. if (status == CC_OK) {
  2095. // Place Call to MC
  2096. pEnqueuedCall->CallState = PLACED;
  2097. pEnqueuedCall->CallType = THIRD_PARTY_INVITOR;
  2098. if (pEnqueuedCall->pQ931DestinationAddr == NULL)
  2099. pEnqueuedCall->pQ931DestinationAddr = pEnqueuedCall->pQ931PeerConnectAddr;
  2100. if (pEnqueuedCall->pQ931PeerConnectAddr == NULL)
  2101. pEnqueuedCall->pQ931PeerConnectAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  2102. if (pEnqueuedCall->pQ931PeerConnectAddr == NULL) {
  2103. MarkCallForDeletion(pEnqueuedCall);
  2104. ConnectCallbackParams.pNonStandardData = pEnqueuedCall->pPeerNonStandardData;
  2105. ConnectCallbackParams.pszPeerDisplay = pEnqueuedCall->pszPeerDisplay;
  2106. ConnectCallbackParams.bRejectReason = CC_REJECT_UNDEFINED_REASON;
  2107. ConnectCallbackParams.pTermCapList = pEnqueuedCall->pPeerH245TermCapList;
  2108. ConnectCallbackParams.pH2250MuxCapability = pEnqueuedCall->pPeerH245H2250MuxCapability;
  2109. ConnectCallbackParams.pTermCapDescriptors = pEnqueuedCall->pPeerH245TermCapDescriptors;
  2110. ConnectCallbackParams.pLocalAddr = pEnqueuedCall->pQ931LocalConnectAddr;
  2111. if (pEnqueuedCall->pQ931DestinationAddr == NULL)
  2112. ConnectCallbackParams.pPeerAddr = pEnqueuedCall->pQ931PeerConnectAddr;
  2113. else
  2114. ConnectCallbackParams.pPeerAddr = pEnqueuedCall->pQ931DestinationAddr;
  2115. ConnectCallbackParams.pVendorInfo = pEnqueuedCall->pPeerVendorInfo;
  2116. ConnectCallbackParams.bMultipointConference = TRUE;
  2117. ConnectCallbackParams.pConferenceID = &pConference->ConferenceID;
  2118. ConnectCallbackParams.pMCAddress = pConference->pMultipointControllerAddr;
  2119. ConnectCallbackParams.pAlternateAddress = NULL;
  2120. ConnectCallbackParams.dwUserToken = pEnqueuedCall->dwUserToken;
  2121. InvokeUserConferenceCallback(pConference,
  2122. CC_CONNECT_INDICATION,
  2123. CC_NO_MEMORY,
  2124. &ConnectCallbackParams);
  2125. if (ValidateCallMarkedForDeletion(hEnqueuedCall) == CC_OK)
  2126. FreeCall(pEnqueuedCall);
  2127. if (ValidateConference(hConference) != CC_OK)
  2128. return H245_ERROR_OK;
  2129. }
  2130. pEnqueuedCall->pQ931PeerConnectAddr = pConference->pMultipointControllerAddr;
  2131. status = PlaceCall(pEnqueuedCall, pConference);
  2132. UnlockCall(pEnqueuedCall);
  2133. }
  2134. }
  2135. UnlockConference(pConference);
  2136. return H245_ERROR_OK;
  2137. }
  2138. HRESULT _IndConferenceRequest( H245_CONF_IND_T *pH245ConfIndData)
  2139. {
  2140. CC_HCALL hCall;
  2141. PCALL pCall;
  2142. PCALL pPeerCall;
  2143. CC_HCONFERENCE hConference;
  2144. PCONFERENCE pConference;
  2145. HRESULT status;
  2146. H245_TERMINAL_LABEL_T *H245TerminalLabelList;
  2147. H245_TERMINAL_LABEL_T H245TerminalLabel;
  2148. WORD wNumTerminalLabels;
  2149. CC_H245_CONFERENCE_REQUEST_CALLBACK_PARAMS H245ConferenceRequestCallbackParams;
  2150. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  2151. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  2152. return H245_ERROR_OK;
  2153. hConference = pConference->hConference;
  2154. switch (pH245ConfIndData->u.Indication.u.IndConferReq.RequestType) {
  2155. case H245_REQ_ENTER_H243_TERMINAL_ID:
  2156. switch (pConference->LocalParticipantInfo.TerminalIDState) {
  2157. case TERMINAL_ID_INVALID:
  2158. UnlockCall(pCall);
  2159. EnqueueRequest(&pConference->LocalParticipantInfo.pEnqueuedRequestsForTerminalID,
  2160. hCall);
  2161. pConference->LocalParticipantInfo.TerminalIDState = TERMINAL_ID_REQUESTED;
  2162. InvokeUserConferenceCallback(pConference,
  2163. CC_TERMINAL_ID_REQUEST_INDICATION,
  2164. CC_OK,
  2165. NULL);
  2166. if (ValidateConference(hConference) == CC_OK)
  2167. UnlockConference(pConference);
  2168. return H245_ERROR_OK;
  2169. case TERMINAL_ID_REQUESTED:
  2170. UnlockCall(pCall);
  2171. EnqueueRequest(&pConference->LocalParticipantInfo.pEnqueuedRequestsForTerminalID,
  2172. hCall);
  2173. UnlockConference(pConference);
  2174. return H245_ERROR_OK;
  2175. case TERMINAL_ID_VALID:
  2176. H245ConferenceResponse(pCall->H245Instance,
  2177. H245_RSP_TERMINAL_ID,
  2178. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bMCUNumber,
  2179. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bTerminalNumber,
  2180. pConference->LocalParticipantInfo.ParticipantInfo.TerminalID.pOctetString,
  2181. (BYTE)pConference->LocalParticipantInfo.ParticipantInfo.TerminalID.wOctetStringLength,
  2182. NULL, // terminal list
  2183. 0); // terminal list count
  2184. UnlockCall(pCall);
  2185. UnlockConference(pConference);
  2186. return H245_ERROR_OK;
  2187. default:
  2188. ASSERT(0);
  2189. }
  2190. case H245_REQ_TERMINAL_LIST:
  2191. if ((pConference->ConferenceMode == MULTIPOINT_MODE) &&
  2192. (pConference->tsMultipointController == TS_TRUE)) {
  2193. status = EnumerateTerminalLabelsInConference(&wNumTerminalLabels,
  2194. &H245TerminalLabelList,
  2195. pConference);
  2196. if (status == CC_OK)
  2197. H245ConferenceResponse(pCall->H245Instance,
  2198. H245_RSP_TERMINAL_LIST,
  2199. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bMCUNumber,
  2200. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bTerminalNumber,
  2201. pConference->LocalParticipantInfo.ParticipantInfo.TerminalID.pOctetString,
  2202. (BYTE)pConference->LocalParticipantInfo.ParticipantInfo.TerminalID.wOctetStringLength,
  2203. H245TerminalLabelList, // terminal list
  2204. wNumTerminalLabels); // terminal list count
  2205. if (H245TerminalLabelList != NULL)
  2206. Free(H245TerminalLabelList);
  2207. status = H245_ERROR_OK;
  2208. } else
  2209. status = H245_ERROR_NOSUP;
  2210. break;
  2211. case H245_REQ_TERMINAL_ID:
  2212. if (pConference->tsMultipointController != TS_TRUE) {
  2213. status = H245_ERROR_NOSUP;
  2214. break;
  2215. }
  2216. if (pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bMCUNumber !=
  2217. pH245ConfIndData->u.Indication.u.IndConferReq.byMcuNumber) {
  2218. // This terminal ID wasn't allocated by this MC, so return without a response
  2219. status = H245_ERROR_OK;
  2220. break;
  2221. }
  2222. // First check to see whether the requested terminal ID is ours
  2223. if (pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bTerminalNumber ==
  2224. pH245ConfIndData->u.Indication.u.IndConferReq.byTerminalNumber) {
  2225. if (pConference->LocalEndpointAttached != ATTACHED) {
  2226. status = H245_ERROR_OK;
  2227. break;
  2228. }
  2229. switch (pConference->LocalParticipantInfo.TerminalIDState) {
  2230. case TERMINAL_ID_INVALID:
  2231. UnlockCall(pCall);
  2232. EnqueueRequest(&pConference->LocalParticipantInfo.pEnqueuedRequestsForTerminalID,
  2233. hCall);
  2234. pConference->LocalParticipantInfo.TerminalIDState = TERMINAL_ID_REQUESTED;
  2235. InvokeUserConferenceCallback(pConference,
  2236. CC_TERMINAL_ID_REQUEST_INDICATION,
  2237. CC_OK,
  2238. NULL);
  2239. if (ValidateConference(hConference) == CC_OK)
  2240. UnlockConference(pConference);
  2241. return H245_ERROR_OK;
  2242. case TERMINAL_ID_REQUESTED:
  2243. UnlockCall(pCall);
  2244. EnqueueRequest(&pConference->LocalParticipantInfo.pEnqueuedRequestsForTerminalID,
  2245. hCall);
  2246. UnlockConference(pConference);
  2247. return H245_ERROR_OK;
  2248. case TERMINAL_ID_VALID:
  2249. H245ConferenceResponse(pCall->H245Instance,
  2250. H245_RSP_MC_TERMINAL_ID,
  2251. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bMCUNumber,
  2252. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bTerminalNumber,
  2253. pConference->LocalParticipantInfo.ParticipantInfo.TerminalID.pOctetString,
  2254. (BYTE)pConference->LocalParticipantInfo.ParticipantInfo.TerminalID.wOctetStringLength,
  2255. NULL, // terminal list
  2256. 0); // terminal list count
  2257. UnlockCall(pCall);
  2258. UnlockConference(pConference);
  2259. return H245_ERROR_OK;
  2260. default:
  2261. ASSERT(0);
  2262. }
  2263. }
  2264. H245TerminalLabel.mcuNumber = pH245ConfIndData->u.Indication.u.IndConferReq.byMcuNumber;
  2265. H245TerminalLabel.terminalNumber = pH245ConfIndData->u.Indication.u.IndConferReq.byTerminalNumber;
  2266. FindPeerParticipantInfo(H245TerminalLabel,
  2267. pConference,
  2268. ESTABLISHED_CALL,
  2269. &pPeerCall);
  2270. if (pPeerCall == NULL) {
  2271. // We don't know about the existance of this terminal ID, so return without a response
  2272. status = H245_ERROR_OK;
  2273. break;
  2274. }
  2275. if (pPeerCall->pPeerParticipantInfo == NULL) {
  2276. UnlockCall(pPeerCall);
  2277. status = H245_ERROR_OK;
  2278. break;
  2279. }
  2280. switch (pPeerCall->pPeerParticipantInfo->TerminalIDState) {
  2281. case TERMINAL_ID_INVALID:
  2282. EnqueueRequest(&pPeerCall->pPeerParticipantInfo->pEnqueuedRequestsForTerminalID,
  2283. hCall);
  2284. pPeerCall->pPeerParticipantInfo->TerminalIDState = TERMINAL_ID_REQUESTED;
  2285. H245ConferenceRequest(pPeerCall->H245Instance,
  2286. H245_REQ_ENTER_H243_TERMINAL_ID,
  2287. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber,
  2288. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber);
  2289. break;
  2290. case TERMINAL_ID_REQUESTED:
  2291. EnqueueRequest(&pPeerCall->pPeerParticipantInfo->pEnqueuedRequestsForTerminalID,
  2292. hCall);
  2293. break;
  2294. case TERMINAL_ID_VALID:
  2295. H245ConferenceResponse(pCall->H245Instance,
  2296. H245_RSP_MC_TERMINAL_ID,
  2297. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber,
  2298. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber,
  2299. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID.pOctetString,
  2300. (BYTE)pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID.wOctetStringLength,
  2301. NULL, // terminal list
  2302. 0); // terminal list count
  2303. break;
  2304. default:
  2305. ASSERT(0);
  2306. break;
  2307. }
  2308. UnlockCall(pPeerCall);
  2309. status = H245_ERROR_OK;
  2310. break;
  2311. default:
  2312. H245ConferenceRequestCallbackParams.hCall = hCall;
  2313. if (pCall->pPeerParticipantInfo == NULL) {
  2314. H245ConferenceRequestCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  2315. H245ConferenceRequestCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  2316. } else
  2317. H245ConferenceRequestCallbackParams.InitiatorTerminalLabel =
  2318. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  2319. H245ConferenceRequestCallbackParams.RequestType =
  2320. pH245ConfIndData->u.Indication.u.IndConferReq.RequestType;
  2321. H245ConferenceRequestCallbackParams.TerminalLabel.bMCUNumber =
  2322. pH245ConfIndData->u.Indication.u.IndConferReq.byMcuNumber;
  2323. H245ConferenceRequestCallbackParams.TerminalLabel.bTerminalNumber =
  2324. pH245ConfIndData->u.Indication.u.IndConferReq.byTerminalNumber;
  2325. status = InvokeUserConferenceCallback(pConference,
  2326. CC_H245_CONFERENCE_REQUEST_INDICATION,
  2327. CC_OK,
  2328. &H245ConferenceRequestCallbackParams);
  2329. if (status != CC_OK)
  2330. status = H245_ERROR_NOSUP;
  2331. break;
  2332. }
  2333. if (ValidateCall(hCall) == CC_OK)
  2334. UnlockCall(pCall);
  2335. if (ValidateConference(hConference) == CC_OK)
  2336. UnlockConference(pConference);
  2337. return status;
  2338. }
  2339. HRESULT _IndConferenceResponse( H245_CONF_IND_T *pH245ConfIndData)
  2340. {
  2341. CC_HCALL hCall;
  2342. PCALL pCall;
  2343. PCALL pPeerCall;
  2344. CC_HCALL hEnqueuedCall;
  2345. PCALL pEnqueuedCall;
  2346. CC_HCALL hVirtualCall;
  2347. CC_HCALL hPeerCall;
  2348. PCALL pVirtualCall;
  2349. PCONFERENCE pConference;
  2350. CC_HCONFERENCE hConference;
  2351. HRESULT status;
  2352. WORD i;
  2353. PPARTICIPANTINFO pPeerParticipantInfo;
  2354. H245_TERMINAL_LABEL_T TerminalLabel;
  2355. CC_PEER_ADD_CALLBACK_PARAMS PeerAddCallbackParams;
  2356. CC_PEER_UPDATE_CALLBACK_PARAMS PeerUpdateCallbackParams;
  2357. CC_H245_CONFERENCE_RESPONSE_CALLBACK_PARAMS H245ConferenceResponseCallbackParams;
  2358. CC_OCTETSTRING OctetString;
  2359. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  2360. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  2361. return H245_ERROR_OK;
  2362. hConference = pConference->hConference;
  2363. switch (pH245ConfIndData->u.Indication.u.IndConferRsp.ResponseType) {
  2364. case H245_RSP_TERMINAL_LIST:
  2365. if (pConference->tsMultipointController == TS_FALSE) {
  2366. for (i = 0; i < pH245ConfIndData->u.Indication.u.IndConferRsp.wTerminalListCount; i++) {
  2367. if ((pH245ConfIndData->u.Indication.u.IndConferRsp.pTerminalList[i].mcuNumber ==
  2368. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bMCUNumber) &&
  2369. (pH245ConfIndData->u.Indication.u.IndConferRsp.pTerminalList[i].terminalNumber ==
  2370. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bTerminalNumber))
  2371. // This terminal number refers to us
  2372. continue;
  2373. FindPeerParticipantInfo(pH245ConfIndData->u.Indication.u.IndConferRsp.pTerminalList[i],
  2374. pConference,
  2375. VIRTUAL_CALL,
  2376. &pPeerCall);
  2377. if (pPeerCall != NULL) {
  2378. // We already know this peer's terminal label, and we
  2379. // eithet know its terminal ID or we have a pending request
  2380. // to obtain it
  2381. UnlockCall(pPeerCall);
  2382. continue;
  2383. }
  2384. // We don't know about this peer.
  2385. // Create a virtual call object for it, and issue a request
  2386. // for its terminal ID
  2387. status = AllocAndLockCall(&hVirtualCall,
  2388. pConference->hConference,
  2389. CC_INVALID_HANDLE, // hQ931Call
  2390. CC_INVALID_HANDLE, // hQ931CallInvitor
  2391. NULL, // pLocalAliasNames
  2392. NULL, // pPeerAliasNames
  2393. NULL, // pPeerExtraAliasNames
  2394. NULL, // pPeerExtension
  2395. NULL, // pLocalNonStandardData
  2396. NULL, // pPeerNonStandardData
  2397. NULL, // pszLocalDisplay
  2398. NULL, // pszPeerDisplay
  2399. NULL, // pPeerVendorInfo
  2400. NULL, // pQ931LocalConnectAddr
  2401. NULL, // pQ931PeerConnectAddr
  2402. NULL, // pQ931DestinationAddr
  2403. NULL, // pSourceCallSignalAddr
  2404. VIRTUAL, // CallType
  2405. FALSE, // bCallerIsMC
  2406. 0, // dwUserToken
  2407. CALL_COMPLETE, // InitialCallState
  2408. 0, // bandwidth
  2409. &pConference->ConferenceID,
  2410. &pVirtualCall);
  2411. if (status == CC_OK) {
  2412. status = AllocatePeerParticipantInfo(NULL,
  2413. &pPeerParticipantInfo);
  2414. if (status == CC_OK) {
  2415. pVirtualCall->pPeerParticipantInfo =
  2416. pPeerParticipantInfo;
  2417. pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber =
  2418. (BYTE)pH245ConfIndData->u.Indication.u.IndConferRsp.pTerminalList[i].mcuNumber;
  2419. pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber =
  2420. (BYTE)pH245ConfIndData->u.Indication.u.IndConferRsp.pTerminalList[i].terminalNumber;
  2421. AddVirtualCallToConference(pVirtualCall,
  2422. pConference);
  2423. // Send RequestTerminalID
  2424. H245ConferenceRequest(pCall->H245Instance,
  2425. H245_REQ_TERMINAL_ID,
  2426. (BYTE)pH245ConfIndData->u.Indication.u.IndConferRsp.pTerminalList[i].mcuNumber,
  2427. (BYTE)pH245ConfIndData->u.Indication.u.IndConferRsp.pTerminalList[i].terminalNumber);
  2428. pPeerParticipantInfo->TerminalIDState = TERMINAL_ID_REQUESTED;
  2429. // Generate PEER_ADD callback
  2430. PeerAddCallbackParams.hCall = hVirtualCall;
  2431. PeerAddCallbackParams.TerminalLabel =
  2432. pVirtualCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  2433. PeerAddCallbackParams.pPeerTerminalID = NULL;
  2434. InvokeUserConferenceCallback(pConference,
  2435. CC_PEER_ADD_INDICATION,
  2436. CC_OK,
  2437. &PeerAddCallbackParams);
  2438. if (ValidateCall(hVirtualCall) == CC_OK)
  2439. UnlockCall(pVirtualCall);
  2440. } else
  2441. FreeCall(pVirtualCall);
  2442. }
  2443. }
  2444. }
  2445. status = H245_ERROR_OK;
  2446. break;
  2447. case H245_RSP_MC_TERMINAL_ID:
  2448. if (pConference->tsMultipointController == TS_FALSE) {
  2449. TerminalLabel.mcuNumber = pH245ConfIndData->u.Indication.u.IndConferRsp.byMcuNumber;
  2450. TerminalLabel.terminalNumber = pH245ConfIndData->u.Indication.u.IndConferRsp.byTerminalNumber;
  2451. FindPeerParticipantInfo(TerminalLabel,
  2452. pConference,
  2453. VIRTUAL_CALL,
  2454. &pPeerCall);
  2455. if (pPeerCall != NULL) {
  2456. hPeerCall = pPeerCall->hCall;
  2457. if (pPeerCall->pPeerParticipantInfo->TerminalIDState != TERMINAL_ID_VALID) {
  2458. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID.pOctetString =
  2459. (BYTE *)Malloc(pH245ConfIndData->u.Indication.u.IndConferRsp.byOctetStringLength);
  2460. if (pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID.pOctetString == NULL) {
  2461. UnlockCall(pPeerCall);
  2462. status = H245_ERROR_OK;
  2463. break;
  2464. }
  2465. memcpy(pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID.pOctetString,
  2466. pH245ConfIndData->u.Indication.u.IndConferRsp.pOctetString,
  2467. pH245ConfIndData->u.Indication.u.IndConferRsp.byOctetStringLength);
  2468. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID.wOctetStringLength =
  2469. pH245ConfIndData->u.Indication.u.IndConferRsp.byOctetStringLength;
  2470. pPeerCall->pPeerParticipantInfo->TerminalIDState = TERMINAL_ID_VALID;
  2471. PeerUpdateCallbackParams.hCall = hPeerCall;
  2472. PeerUpdateCallbackParams.TerminalLabel =
  2473. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  2474. PeerUpdateCallbackParams.pPeerTerminalID = &pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID;
  2475. InvokeUserConferenceCallback(pConference,
  2476. CC_PEER_UPDATE_INDICATION,
  2477. CC_OK,
  2478. &PeerUpdateCallbackParams);
  2479. }
  2480. if (ValidateCall(hPeerCall) == CC_OK)
  2481. UnlockCall(pPeerCall);
  2482. }
  2483. }
  2484. status = H245_ERROR_OK;
  2485. break;
  2486. case H245_RSP_TERMINAL_ID:
  2487. if ((pConference->ConferenceMode == MULTIPOINT_MODE) &&
  2488. (pConference->tsMultipointController == TS_TRUE)) {
  2489. TerminalLabel.mcuNumber = pH245ConfIndData->u.Indication.u.IndConferRsp.byMcuNumber;
  2490. TerminalLabel.terminalNumber = pH245ConfIndData->u.Indication.u.IndConferRsp.byTerminalNumber;
  2491. FindPeerParticipantInfo(TerminalLabel,
  2492. pConference,
  2493. ESTABLISHED_CALL,
  2494. &pPeerCall);
  2495. if (pPeerCall != NULL) {
  2496. hPeerCall = pPeerCall->hCall;
  2497. if (pPeerCall->pPeerParticipantInfo->TerminalIDState != TERMINAL_ID_VALID) {
  2498. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID.pOctetString =
  2499. (BYTE *)Malloc(pH245ConfIndData->u.Indication.u.IndConferRsp.byOctetStringLength);
  2500. if (pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID.pOctetString == NULL) {
  2501. UnlockCall(pPeerCall);
  2502. status = H245_ERROR_OK;
  2503. break;
  2504. }
  2505. memcpy(pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID.pOctetString,
  2506. pH245ConfIndData->u.Indication.u.IndConferRsp.pOctetString,
  2507. pH245ConfIndData->u.Indication.u.IndConferRsp.byOctetStringLength);
  2508. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID.wOctetStringLength =
  2509. pH245ConfIndData->u.Indication.u.IndConferRsp.byOctetStringLength;
  2510. pPeerCall->pPeerParticipantInfo->TerminalIDState = TERMINAL_ID_VALID;
  2511. // Dequeue and respond to each enqueued request for this terminal ID
  2512. while (DequeueRequest(&pPeerCall->pPeerParticipantInfo->pEnqueuedRequestsForTerminalID,
  2513. &hEnqueuedCall) == CC_OK) {
  2514. if (LockCall(hEnqueuedCall, &pEnqueuedCall) == CC_OK) {
  2515. H245ConferenceResponse(pEnqueuedCall->H245Instance,
  2516. H245_RSP_MC_TERMINAL_ID,
  2517. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber,
  2518. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber,
  2519. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID.pOctetString,
  2520. (BYTE)pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID.wOctetStringLength,
  2521. NULL, // terminal list
  2522. 0); // terminal list count
  2523. UnlockCall(pEnqueuedCall);
  2524. }
  2525. }
  2526. // Generate a CC_PEER_UPDATE_INDICATION callback
  2527. PeerUpdateCallbackParams.hCall = hPeerCall;
  2528. PeerUpdateCallbackParams.TerminalLabel =
  2529. pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  2530. PeerUpdateCallbackParams.pPeerTerminalID = &pPeerCall->pPeerParticipantInfo->ParticipantInfo.TerminalID;
  2531. InvokeUserConferenceCallback(pConference,
  2532. CC_PEER_UPDATE_INDICATION,
  2533. CC_OK,
  2534. &PeerUpdateCallbackParams);
  2535. }
  2536. if (ValidateCall(hPeerCall) == CC_OK)
  2537. UnlockCall(pPeerCall);
  2538. }
  2539. }
  2540. status = H245_ERROR_OK;
  2541. break;
  2542. default:
  2543. H245ConferenceResponseCallbackParams.hCall = hCall;
  2544. if (pCall->pPeerParticipantInfo == NULL) {
  2545. H245ConferenceResponseCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  2546. H245ConferenceResponseCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  2547. } else
  2548. H245ConferenceResponseCallbackParams.InitiatorTerminalLabel =
  2549. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  2550. H245ConferenceResponseCallbackParams.ResponseType =
  2551. pH245ConfIndData->u.Indication.u.IndConferRsp.ResponseType;
  2552. H245ConferenceResponseCallbackParams.TerminalLabel.bMCUNumber =
  2553. pH245ConfIndData->u.Indication.u.IndConferRsp.byMcuNumber;
  2554. H245ConferenceResponseCallbackParams.TerminalLabel.bTerminalNumber =
  2555. pH245ConfIndData->u.Indication.u.IndConferRsp.byTerminalNumber;
  2556. if ((pH245ConfIndData->u.Indication.u.IndConferRsp.pOctetString == NULL) ||
  2557. (pH245ConfIndData->u.Indication.u.IndConferRsp.byOctetStringLength == 0)) {
  2558. H245ConferenceResponseCallbackParams.pOctetString = NULL;
  2559. } else {
  2560. OctetString.pOctetString =
  2561. pH245ConfIndData->u.Indication.u.IndConferRsp.pOctetString;
  2562. OctetString.wOctetStringLength =
  2563. pH245ConfIndData->u.Indication.u.IndConferRsp.byOctetStringLength;
  2564. H245ConferenceResponseCallbackParams.pOctetString = &OctetString;
  2565. }
  2566. if (pH245ConfIndData->u.Indication.u.IndConferRsp.wTerminalListCount == 0) {
  2567. H245ConferenceResponseCallbackParams.pTerminalList = NULL;
  2568. H245ConferenceResponseCallbackParams.wTerminalListCount = 0;
  2569. status = CC_OK;
  2570. } else {
  2571. H245ConferenceResponseCallbackParams.pTerminalList =
  2572. (CC_TERMINAL_LABEL *)Malloc(sizeof(CC_TERMINAL_LABEL) *
  2573. pH245ConfIndData->u.Indication.u.IndConferRsp.wTerminalListCount);
  2574. if (H245ConferenceResponseCallbackParams.pTerminalList == NULL) {
  2575. H245ConferenceResponseCallbackParams.wTerminalListCount = 0;
  2576. status = CC_NO_MEMORY;
  2577. } else {
  2578. for (i = 0; i < pH245ConfIndData->u.Indication.u.IndConferRsp.wTerminalListCount; i++) {
  2579. H245ConferenceResponseCallbackParams.pTerminalList[i].bMCUNumber =
  2580. (BYTE)pH245ConfIndData->u.Indication.u.IndConferRsp.pTerminalList[i].mcuNumber;
  2581. H245ConferenceResponseCallbackParams.pTerminalList[i].bMCUNumber =
  2582. (BYTE)pH245ConfIndData->u.Indication.u.IndConferRsp.pTerminalList[i].terminalNumber;
  2583. }
  2584. H245ConferenceResponseCallbackParams.wTerminalListCount =
  2585. pH245ConfIndData->u.Indication.u.IndConferRsp.wTerminalListCount;
  2586. status = CC_OK;
  2587. }
  2588. }
  2589. status = InvokeUserConferenceCallback(pConference,
  2590. CC_H245_CONFERENCE_RESPONSE_INDICATION,
  2591. status,
  2592. &H245ConferenceResponseCallbackParams);
  2593. if (status != CC_OK)
  2594. status = H245_ERROR_NOSUP;
  2595. if (H245ConferenceResponseCallbackParams.pTerminalList != NULL)
  2596. Free(H245ConferenceResponseCallbackParams.pTerminalList);
  2597. break;
  2598. }
  2599. if (ValidateCall(hCall) == CC_OK)
  2600. UnlockCall(pCall);
  2601. if (ValidateConference(hConference) == CC_OK)
  2602. UnlockConference(pConference);
  2603. return status;
  2604. }
  2605. HRESULT _IndConferenceCommand( H245_CONF_IND_T *pH245ConfIndData)
  2606. {
  2607. CC_HCALL hCall;
  2608. PCALL pCall;
  2609. PCALL pOldCall;
  2610. PCONFERENCE pConference;
  2611. CC_HCONFERENCE hConference;
  2612. WORD i;
  2613. WORD wNumCalls;
  2614. PCC_HCALL CallList;
  2615. WORD wNumChannels;
  2616. PCC_HCHANNEL ChannelList;
  2617. PCHANNEL pChannel;
  2618. CC_HCHANNEL hChannel;
  2619. CALLSTATE CallState;
  2620. HQ931CALL hQ931Call;
  2621. H245_INST_T H245Instance;
  2622. HRESULT status = CC_OK;
  2623. CC_H245_CONFERENCE_COMMAND_CALLBACK_PARAMS H245ConferenceCommandCallbackParams;
  2624. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  2625. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  2626. return H245_ERROR_OK;
  2627. hConference = pConference->hConference;
  2628. switch (pH245ConfIndData->u.Indication.u.IndConferCmd.CommandType) {
  2629. case H245_CMD_DROP_CONFERENCE:
  2630. if ((pConference->ConferenceMode == MULTIPOINT_MODE) &&
  2631. (pConference->tsMultipointController == TS_TRUE)) {
  2632. UnlockCall(pCall);
  2633. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ALL_CALLS);
  2634. for (i = 0; i < wNumCalls; i++) {
  2635. if (LockCall(CallList[i], &pCall) == CC_OK) {
  2636. hQ931Call = pCall->hQ931Call;
  2637. H245Instance = pCall->H245Instance;
  2638. CallState = pCall->CallState;
  2639. FreeCall(pCall);
  2640. switch (CallState) {
  2641. case ENQUEUED:
  2642. break;
  2643. case PLACED:
  2644. case RINGING:
  2645. Q931Hangup(hQ931Call, CC_REJECT_NORMAL_CALL_CLEARING);
  2646. break;
  2647. default:
  2648. H245ShutDown(H245Instance);
  2649. Q931Hangup(hQ931Call, CC_REJECT_NORMAL_CALL_CLEARING);
  2650. break;
  2651. }
  2652. }
  2653. }
  2654. if (CallList != NULL)
  2655. Free(CallList);
  2656. EnumerateChannelsInConference(&wNumChannels,
  2657. &ChannelList,
  2658. pConference,
  2659. ALL_CHANNELS);
  2660. for (i = 0; i < wNumChannels; i++) {
  2661. if (LockChannel(ChannelList[i], &pChannel) == CC_OK)
  2662. FreeChannel(pChannel);
  2663. }
  2664. if (ChannelList != NULL)
  2665. Free(ChannelList);
  2666. InvokeUserConferenceCallback(
  2667. pConference,
  2668. CC_CONFERENCE_TERMINATION_INDICATION,
  2669. CC_OK,
  2670. NULL);
  2671. if (ValidateConference(hConference) == CC_OK) {
  2672. if (pConference->bDeferredDelete)
  2673. FreeConference(pConference);
  2674. else {
  2675. ReInitializeConference(pConference);
  2676. UnlockConference(pConference);
  2677. }
  2678. }
  2679. return H245_ERROR_OK;
  2680. }
  2681. status = H245_ERROR_OK;
  2682. break;
  2683. case brdcstMyLgclChnnl_chosen:
  2684. case cnclBrdcstMyLgclChnnl_chosen:
  2685. if (FindChannelInConference(pH245ConfIndData->u.Indication.u.IndConferCmd.Channel,
  2686. FALSE, // remote channel number
  2687. RX_CHANNEL | PROXY_CHANNEL,
  2688. hCall,
  2689. &hChannel,
  2690. pConference) != CC_OK) {
  2691. UnlockCall(pCall);
  2692. UnlockConference(pConference);
  2693. return H245_ERROR_OK;
  2694. }
  2695. if (LockChannel(hChannel, &pChannel) != CC_OK) {
  2696. UnlockCall(pCall);
  2697. UnlockConference(pConference);
  2698. return H245_ERROR_OK;
  2699. }
  2700. if (pChannel->bChannelType == PROXY_CHANNEL) {
  2701. ASSERT(pConference->ConferenceMode == MULTIPOINT_MODE);
  2702. ASSERT(pConference->tsMultipointController == TS_TRUE);
  2703. ASSERT(pChannel->bMultipointChannel == TRUE);
  2704. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  2705. for (i = 0; i < wNumCalls; i++) {
  2706. if (CallList[i] != hCall) {
  2707. if (LockCall(CallList[i], &pOldCall) == CC_OK) {
  2708. H245ConferenceCommand(pOldCall->H245Instance,
  2709. pH245ConfIndData->u.Indication.u.IndConferCmd.CommandType,
  2710. pChannel->wLocalChannelNumber,
  2711. pH245ConfIndData->u.Indication.u.IndConferCmd.byMcuNumber,
  2712. pH245ConfIndData->u.Indication.u.IndConferCmd.byTerminalNumber);
  2713. UnlockCall(pOldCall);
  2714. }
  2715. }
  2716. }
  2717. Free(CallList);
  2718. }
  2719. if (pChannel->tsAccepted == TS_TRUE) {
  2720. H245ConferenceCommandCallbackParams.hCall = hCall;
  2721. H245ConferenceCommandCallbackParams.hChannel = hChannel;
  2722. if (pCall->pPeerParticipantInfo == NULL) {
  2723. H245ConferenceCommandCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  2724. H245ConferenceCommandCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  2725. } else
  2726. H245ConferenceCommandCallbackParams.InitiatorTerminalLabel =
  2727. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  2728. H245ConferenceCommandCallbackParams.CommandType =
  2729. pH245ConfIndData->u.Indication.u.IndConferCmd.CommandType;
  2730. H245ConferenceCommandCallbackParams.TerminalLabel.bMCUNumber =
  2731. pH245ConfIndData->u.Indication.u.IndConferCmd.byMcuNumber;
  2732. H245ConferenceCommandCallbackParams.TerminalLabel.bTerminalNumber =
  2733. pH245ConfIndData->u.Indication.u.IndConferCmd.byTerminalNumber;
  2734. status = InvokeUserConferenceCallback(pConference,
  2735. CC_H245_CONFERENCE_COMMAND_INDICATION,
  2736. CC_OK,
  2737. &H245ConferenceCommandCallbackParams);
  2738. if (status != CC_OK)
  2739. status = H245_ERROR_NOSUP;
  2740. } else
  2741. status = H245_ERROR_OK;
  2742. if (ValidateChannel(hChannel) == CC_OK)
  2743. UnlockChannel(pChannel);
  2744. if (ValidateCall(hCall) == CC_OK)
  2745. UnlockCall(pCall);
  2746. if (ValidateConference(hConference) == CC_OK)
  2747. UnlockConference(pConference);
  2748. return status;
  2749. default:
  2750. // Unrecognized conference command
  2751. // Pass it up to the client
  2752. H245ConferenceCommandCallbackParams.hCall = hCall;
  2753. if (pCall->pPeerParticipantInfo == NULL) {
  2754. H245ConferenceCommandCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  2755. H245ConferenceCommandCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  2756. } else
  2757. H245ConferenceCommandCallbackParams.InitiatorTerminalLabel =
  2758. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  2759. H245ConferenceCommandCallbackParams.CommandType =
  2760. pH245ConfIndData->u.Indication.u.IndConferCmd.CommandType;
  2761. H245ConferenceCommandCallbackParams.TerminalLabel.bMCUNumber =
  2762. pH245ConfIndData->u.Indication.u.IndConferCmd.byMcuNumber;
  2763. H245ConferenceCommandCallbackParams.TerminalLabel.bTerminalNumber =
  2764. pH245ConfIndData->u.Indication.u.IndConferCmd.byTerminalNumber;
  2765. H245ConferenceCommandCallbackParams.hChannel = CC_INVALID_HANDLE;
  2766. status = InvokeUserConferenceCallback(pConference,
  2767. CC_H245_CONFERENCE_COMMAND_INDICATION,
  2768. CC_OK,
  2769. &H245ConferenceCommandCallbackParams);
  2770. if (status != CC_OK)
  2771. status = H245_ERROR_NOSUP;
  2772. if (ValidateCall(hCall) == CC_OK)
  2773. UnlockCall(pCall);
  2774. if (ValidateConference(hConference) == CC_OK)
  2775. UnlockConference(pConference);
  2776. return status;
  2777. }
  2778. if (ValidateCall(hCall) == CC_OK)
  2779. UnlockCall(pCall);
  2780. if (ValidateConference(hConference) == CC_OK)
  2781. UnlockConference(pConference);
  2782. return status;
  2783. }
  2784. HRESULT _IndConference( H245_CONF_IND_T *pH245ConfIndData)
  2785. {
  2786. CC_HCALL hCall;
  2787. PCALL pCall;
  2788. PCALL pPeerCall;
  2789. PCONFERENCE pConference;
  2790. CC_HCONFERENCE hConference;
  2791. H245_TERMINAL_LABEL_T H245TerminalLabel;
  2792. PPARTICIPANTINFO pPeerParticipantInfo;
  2793. HRESULT status;
  2794. CC_HCALL hVirtualCall;
  2795. PCALL pVirtualCall;
  2796. CC_PEER_ADD_CALLBACK_PARAMS PeerAddCallbackParams;
  2797. CC_PEER_DROP_CALLBACK_PARAMS PeerDropCallbackParams;
  2798. CC_H245_CONFERENCE_INDICATION_CALLBACK_PARAMS H245ConferenceIndicationCallbackParams;
  2799. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  2800. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  2801. return H245_ERROR_OK;
  2802. hConference = pConference->hConference;
  2803. switch (pH245ConfIndData->u.Indication.u.IndConfer.IndicationType) {
  2804. case H245_IND_TERMINAL_NUMBER_ASSIGN:
  2805. if (pConference->tsMultipointController == TS_FALSE) {
  2806. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bMCUNumber =
  2807. pH245ConfIndData->u.Indication.u.IndConfer.byMcuNumber;
  2808. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bTerminalNumber =
  2809. pH245ConfIndData->u.Indication.u.IndConfer.byTerminalNumber;
  2810. }
  2811. status = H245_ERROR_OK;
  2812. break;
  2813. case H245_IND_TERMINAL_JOINED:
  2814. if (pConference->tsMultipointController == TS_FALSE) {
  2815. if ((pH245ConfIndData->u.Indication.u.IndConfer.byMcuNumber ==
  2816. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bMCUNumber) &&
  2817. (pH245ConfIndData->u.Indication.u.IndConfer.byTerminalNumber ==
  2818. pConference->LocalParticipantInfo.ParticipantInfo.TerminalLabel.bTerminalNumber)) {
  2819. // This message refers to us
  2820. status = H245_ERROR_OK;
  2821. break;
  2822. }
  2823. H245TerminalLabel.mcuNumber = pH245ConfIndData->u.Indication.u.IndConfer.byMcuNumber;
  2824. H245TerminalLabel.terminalNumber = pH245ConfIndData->u.Indication.u.IndConfer.byTerminalNumber;
  2825. FindPeerParticipantInfo(H245TerminalLabel,
  2826. pConference,
  2827. VIRTUAL_CALL,
  2828. &pPeerCall);
  2829. if (pPeerCall != NULL) {
  2830. // We already know this peer's terminal label, and we
  2831. // eithet know its terminal ID or we have a pending request
  2832. // to obtain it
  2833. UnlockCall(pPeerCall);
  2834. status = H245_ERROR_OK;
  2835. break;
  2836. }
  2837. // We don't know about this peer.
  2838. // Create a virtual call object for it, and issue a request
  2839. // for its terminal ID
  2840. status = AllocAndLockCall(&hVirtualCall,
  2841. pConference->hConference,
  2842. CC_INVALID_HANDLE, // hQ931Call
  2843. CC_INVALID_HANDLE, // hQ931CallInvitor
  2844. NULL, // pLocalAliasNames
  2845. NULL, // pPeerAliasNames
  2846. NULL, // pPeerExtraAliasNames
  2847. NULL, // pPeerExtension
  2848. NULL, // pLocalNonStandardData
  2849. NULL, // pPeerNonStandardData
  2850. NULL, // pszLocalDisplay
  2851. NULL, // pszPeerDisplay
  2852. NULL, // pPeerVendorInfo
  2853. NULL, // pQ931LocalConnectAddr
  2854. NULL, // pQ931PeerConnectAddr
  2855. NULL, // pQ931DestinationAddr
  2856. NULL, // pSourceCallSignalAddr
  2857. VIRTUAL, // CallType
  2858. FALSE, // bCallerIsMC
  2859. 0, // dwUserToken
  2860. CALL_COMPLETE, // InitialCallState
  2861. 0, // bandwidth
  2862. &pConference->ConferenceID,
  2863. &pVirtualCall);
  2864. if (status == CC_OK) {
  2865. status = AllocatePeerParticipantInfo(NULL,
  2866. &pPeerParticipantInfo);
  2867. if (status == CC_OK) {
  2868. pVirtualCall->pPeerParticipantInfo =
  2869. pPeerParticipantInfo;
  2870. pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber =
  2871. (BYTE)H245TerminalLabel.mcuNumber;
  2872. pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber =
  2873. (BYTE)H245TerminalLabel.terminalNumber;
  2874. AddVirtualCallToConference(pVirtualCall,
  2875. pConference);
  2876. // Send RequestTerminalID
  2877. H245ConferenceRequest(pCall->H245Instance,
  2878. H245_REQ_TERMINAL_ID,
  2879. (BYTE)H245TerminalLabel.mcuNumber,
  2880. (BYTE)H245TerminalLabel.terminalNumber);
  2881. pPeerParticipantInfo->TerminalIDState = TERMINAL_ID_REQUESTED;
  2882. // Generate PEER_ADD callback
  2883. PeerAddCallbackParams.hCall = hVirtualCall;
  2884. PeerAddCallbackParams.TerminalLabel =
  2885. pVirtualCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  2886. PeerAddCallbackParams.pPeerTerminalID = NULL;
  2887. InvokeUserConferenceCallback(pConference,
  2888. CC_PEER_ADD_INDICATION,
  2889. CC_OK,
  2890. &PeerAddCallbackParams);
  2891. if (ValidateCall(hVirtualCall) == CC_OK)
  2892. UnlockCall(pVirtualCall);
  2893. if (ValidateConference(hConference) == CC_OK)
  2894. UnlockConference(pConference);
  2895. UnlockCall(pCall);
  2896. return H245_ERROR_OK;
  2897. } else
  2898. FreeCall(pVirtualCall);
  2899. }
  2900. }
  2901. status = H245_ERROR_OK;
  2902. break;
  2903. case H245_IND_TERMINAL_LEFT:
  2904. if (pConference->tsMultipointController == TS_FALSE) {
  2905. H245TerminalLabel.mcuNumber = pH245ConfIndData->u.Indication.u.IndConfer.byMcuNumber;
  2906. H245TerminalLabel.terminalNumber = pH245ConfIndData->u.Indication.u.IndConfer.byTerminalNumber;
  2907. status = FindPeerParticipantInfo(H245TerminalLabel,
  2908. pConference,
  2909. VIRTUAL_CALL,
  2910. &pVirtualCall);
  2911. if (status == CC_OK) {
  2912. ASSERT(pVirtualCall != NULL);
  2913. ASSERT(pVirtualCall->pPeerParticipantInfo != NULL);
  2914. // Save the virtual call handle; we'll need to validate the virtual
  2915. // call object after returning from the conference callback
  2916. hVirtualCall = pVirtualCall->hCall;
  2917. PeerDropCallbackParams.hCall = hVirtualCall;
  2918. PeerDropCallbackParams.TerminalLabel = pVirtualCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  2919. if (pVirtualCall->pPeerParticipantInfo->TerminalIDState == TERMINAL_ID_VALID)
  2920. PeerDropCallbackParams.pPeerTerminalID = &pVirtualCall->pPeerParticipantInfo->ParticipantInfo.TerminalID;
  2921. else
  2922. PeerDropCallbackParams.pPeerTerminalID = NULL;
  2923. } else {
  2924. // Set pVirtualCall to NULL to indicate that we don't have
  2925. // a virtual call object that needs to be free'd up later
  2926. pVirtualCall = NULL;
  2927. PeerDropCallbackParams.hCall = CC_INVALID_HANDLE;
  2928. PeerDropCallbackParams.TerminalLabel.bMCUNumber = pH245ConfIndData->u.Indication.u.IndConfer.byMcuNumber;
  2929. PeerDropCallbackParams.TerminalLabel.bTerminalNumber = pH245ConfIndData->u.Indication.u.IndConfer.byTerminalNumber;
  2930. PeerDropCallbackParams.pPeerTerminalID = NULL;
  2931. }
  2932. hConference = pConference->hConference;
  2933. // Generate a CC_PEER_DROP_INDICATION callback
  2934. InvokeUserConferenceCallback(pConference,
  2935. CC_PEER_DROP_INDICATION,
  2936. CC_OK,
  2937. &PeerDropCallbackParams);
  2938. if (ValidateConference(hConference) == CC_OK)
  2939. UnlockConference(pConference);
  2940. // Check to see if we have a virtual call object that needs to be free'd up
  2941. if (pVirtualCall != NULL)
  2942. if (ValidateCall(hVirtualCall) == CC_OK)
  2943. FreeCall(pVirtualCall);
  2944. UnlockCall(pCall);
  2945. return H245_ERROR_OK;
  2946. }
  2947. status = H245_ERROR_OK;
  2948. break;
  2949. default:
  2950. H245ConferenceIndicationCallbackParams.hCall = hCall;
  2951. if (pCall->pPeerParticipantInfo == NULL) {
  2952. H245ConferenceIndicationCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  2953. H245ConferenceIndicationCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  2954. } else
  2955. H245ConferenceIndicationCallbackParams.InitiatorTerminalLabel =
  2956. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  2957. H245ConferenceIndicationCallbackParams.IndicationType =
  2958. pH245ConfIndData->u.Indication.u.IndConfer.IndicationType;
  2959. H245ConferenceIndicationCallbackParams.bSBENumber =
  2960. pH245ConfIndData->u.Indication.u.IndConfer.bySbeNumber;
  2961. H245ConferenceIndicationCallbackParams.TerminalLabel.bMCUNumber =
  2962. pH245ConfIndData->u.Indication.u.IndConfer.byMcuNumber;
  2963. H245ConferenceIndicationCallbackParams.TerminalLabel.bTerminalNumber =
  2964. pH245ConfIndData->u.Indication.u.IndConfer.byTerminalNumber;
  2965. status = InvokeUserConferenceCallback(pConference,
  2966. CC_H245_CONFERENCE_INDICATION_INDICATION,
  2967. CC_OK,
  2968. &H245ConferenceIndicationCallbackParams);
  2969. if (status != CC_OK)
  2970. status = H245_ERROR_NOSUP;
  2971. break;
  2972. }
  2973. if (ValidateCall(hCall) == CC_OK)
  2974. UnlockCall(pCall);
  2975. if (ValidateConference(hConference) == CC_OK)
  2976. UnlockConference(pConference);
  2977. return status;
  2978. }
  2979. HRESULT _IndCommunicationModeCommand(
  2980. H245_CONF_IND_T *pH245ConfIndData)
  2981. {
  2982. CC_HCALL hCall;
  2983. PCALL pCall;
  2984. CC_HCONFERENCE hConference;
  2985. PCONFERENCE pConference;
  2986. CC_MULTIPOINT_CALLBACK_PARAMS MultipointCallbackParams;
  2987. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  2988. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  2989. return H245_ERROR_OK;
  2990. if (pConference->tsMultipointController == TS_TRUE) {
  2991. UnlockCall(pCall);
  2992. UnlockConference(pConference);
  2993. return H245_ERROR_OK;
  2994. }
  2995. hConference = pConference->hConference;
  2996. // Destroy the old session table
  2997. FreeConferenceSessionTable(pConference);
  2998. H245CommunicationTableToSessionTable(
  2999. pH245ConfIndData->u.Indication.u.IndCommRsp.pTable,
  3000. pH245ConfIndData->u.Indication.u.IndCommRsp.byTableCount,
  3001. &pConference->pSessionTable);
  3002. pConference->bSessionTableInternallyConstructed = TRUE;
  3003. // Generate MULTIPOINT callback
  3004. MultipointCallbackParams.pTerminalInfo = &pConference->LocalParticipantInfo.ParticipantInfo;
  3005. MultipointCallbackParams.pSessionTable = pConference->pSessionTable;
  3006. InvokeUserConferenceCallback(pConference,
  3007. CC_MULTIPOINT_INDICATION,
  3008. CC_OK,
  3009. &MultipointCallbackParams);
  3010. if (ValidateCall(hCall) == CC_OK)
  3011. UnlockCall(pCall);
  3012. if (ValidateConference(hConference) == CC_OK)
  3013. UnlockConference(pConference);
  3014. return H245_ERROR_OK;
  3015. }
  3016. HRESULT _IndVendorIdentification( H245_CONF_IND_T *pH245ConfIndData,
  3017. VendorIdentification *pVendorIdentification)
  3018. {
  3019. CC_HCALL hCall;
  3020. PCALL pCall;
  3021. CC_HCONFERENCE hConference;
  3022. PCONFERENCE pConference;
  3023. CC_NONSTANDARDDATA NonStandardData;
  3024. CC_OCTETSTRING ProductNumber;
  3025. CC_OCTETSTRING VersionNumber;
  3026. CC_VENDOR_ID_CALLBACK_PARAMS VendorIDCallbackParams;
  3027. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  3028. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  3029. return H245_ERROR_OK;
  3030. hConference = pConference->hConference;
  3031. VendorIDCallbackParams.hCall = hCall;
  3032. if (pCall->pPeerParticipantInfo == NULL) {
  3033. VendorIDCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  3034. VendorIDCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  3035. } else
  3036. VendorIDCallbackParams.InitiatorTerminalLabel =
  3037. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  3038. if (pVendorIdentification->vendor.choice == h221NonStandard_chosen) {
  3039. NonStandardData.sData.pOctetString = NULL;
  3040. NonStandardData.sData.wOctetStringLength = 0;
  3041. NonStandardData.bCountryCode = (BYTE)pVendorIdentification->vendor.u.h221NonStandard.t35CountryCode;
  3042. NonStandardData.bExtension = (BYTE)pVendorIdentification->vendor.u.h221NonStandard.t35Extension;
  3043. NonStandardData.wManufacturerCode = pVendorIdentification->vendor.u.h221NonStandard.manufacturerCode;
  3044. VendorIDCallbackParams.pNonStandardData = &NonStandardData;
  3045. } else
  3046. VendorIDCallbackParams.pNonStandardData = NULL;
  3047. if (pVendorIdentification->bit_mask & productNumber_present) {
  3048. ProductNumber.pOctetString =
  3049. pVendorIdentification->productNumber.value;
  3050. ProductNumber.wOctetStringLength = (WORD)
  3051. pVendorIdentification->productNumber.length;
  3052. VendorIDCallbackParams.pProductNumber = &ProductNumber;
  3053. } else
  3054. VendorIDCallbackParams.pProductNumber = NULL;
  3055. if (pVendorIdentification->bit_mask & versionNumber_present) {
  3056. VersionNumber.pOctetString =
  3057. pVendorIdentification->versionNumber.value;
  3058. VersionNumber.wOctetStringLength = (WORD)
  3059. pVendorIdentification->versionNumber.length;
  3060. VendorIDCallbackParams.pVersionNumber = &VersionNumber;
  3061. } else
  3062. VendorIDCallbackParams.pVersionNumber = NULL;
  3063. InvokeUserConferenceCallback(pConference,
  3064. CC_VENDOR_ID_INDICATION,
  3065. CC_OK,
  3066. &VendorIDCallbackParams);
  3067. if (ValidateCall(hCall) == CC_OK)
  3068. UnlockCall(pCall);
  3069. if (ValidateConference(hConference) == CC_OK)
  3070. UnlockConference(pConference);
  3071. return H245_ERROR_OK;
  3072. }
  3073. HRESULT _IndH2250MaximumSkew( H245_CONF_IND_T *pH245ConfIndData)
  3074. {
  3075. HRESULT status;
  3076. CC_HCONFERENCE hConference;
  3077. PCONFERENCE pConference;
  3078. CC_HCALL hCall;
  3079. PCC_HCALL CallList;
  3080. WORD wNumCalls;
  3081. WORD i;
  3082. PCALL pCall;
  3083. PCALL pOldCall;
  3084. CC_HCHANNEL hChannel1;
  3085. PCHANNEL pChannel1;
  3086. CC_HCHANNEL hChannel2;
  3087. PCHANNEL pChannel2;
  3088. CC_MAXIMUM_AUDIO_VIDEO_SKEW_CALLBACK_PARAMS MaximumAudioVideoSkewCallbackParams;
  3089. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  3090. status = LockCallAndConference(hCall, &pCall, &pConference);
  3091. if (status != CC_OK) {
  3092. // This may be OK, if the call was cancelled while
  3093. // call setup was in progress.
  3094. return H245_ERROR_OK;
  3095. }
  3096. hConference = pCall->hConference;
  3097. UnlockCall(pCall);
  3098. if (FindChannelInConference(pH245ConfIndData->u.Indication.u.IndH2250MaxSkew.LogicalChannelNumber1,
  3099. FALSE, // remote channel number
  3100. RX_CHANNEL | PROXY_CHANNEL,
  3101. hCall,
  3102. &hChannel1,
  3103. pConference) != CC_OK) {
  3104. UnlockConference(pConference);
  3105. return H245_ERROR_OK;
  3106. }
  3107. if (LockChannel(hChannel1, &pChannel1) != CC_OK) {
  3108. UnlockConference(pConference);
  3109. return H245_ERROR_OK;
  3110. }
  3111. if (pChannel1->bChannelType == RX_CHANNEL) {
  3112. UnlockChannel(pChannel1);
  3113. if (FindChannelInConference(pH245ConfIndData->u.Indication.u.IndH2250MaxSkew.LogicalChannelNumber2,
  3114. FALSE, // remote channel number
  3115. RX_CHANNEL,
  3116. hCall,
  3117. &hChannel2,
  3118. pConference) != CC_OK) {
  3119. UnlockConference(pConference);
  3120. return H245_ERROR_OK;
  3121. }
  3122. if (LockChannel(hChannel2, &pChannel2) != CC_OK) {
  3123. UnlockConference(pConference);
  3124. return H245_ERROR_OK;
  3125. }
  3126. if (pChannel2->bChannelType != RX_CHANNEL) {
  3127. UnlockChannel(pChannel2);
  3128. UnlockConference(pConference);
  3129. return H245_ERROR_OK;
  3130. }
  3131. UnlockChannel(pChannel2);
  3132. MaximumAudioVideoSkewCallbackParams.hChannel1 = hChannel1;
  3133. MaximumAudioVideoSkewCallbackParams.hChannel2 = hChannel2;
  3134. MaximumAudioVideoSkewCallbackParams.wMaximumSkew =
  3135. pH245ConfIndData->u.Indication.u.IndH2250MaxSkew.wSkew;
  3136. InvokeUserConferenceCallback(pConference,
  3137. CC_MAXIMUM_AUDIO_VIDEO_SKEW_INDICATION,
  3138. CC_OK,
  3139. &MaximumAudioVideoSkewCallbackParams);
  3140. if (ValidateConference(hConference) == CC_OK)
  3141. UnlockConference(pConference);
  3142. } else { // pChannel1->bChannelType == PROXY_CHANNEL
  3143. if (FindChannelInConference(pH245ConfIndData->u.Indication.u.IndH2250MaxSkew.LogicalChannelNumber2,
  3144. FALSE, // remote channel number
  3145. PROXY_CHANNEL,
  3146. hCall,
  3147. &hChannel2,
  3148. pConference) != CC_OK) {
  3149. UnlockChannel(pChannel1);
  3150. UnlockConference(pConference);
  3151. return H245_ERROR_OK;
  3152. }
  3153. if (LockChannel(hChannel2, &pChannel2) != CC_OK) {
  3154. UnlockChannel(pChannel1);
  3155. UnlockConference(pConference);
  3156. return H245_ERROR_OK;
  3157. }
  3158. if (pChannel1->hCall != pChannel2->hCall) {
  3159. UnlockChannel(pChannel1);
  3160. UnlockChannel(pChannel2);
  3161. UnlockConference(pConference);
  3162. return H245_ERROR_OK;
  3163. }
  3164. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  3165. for (i = 0; i < wNumCalls; i++) {
  3166. if (CallList[i] != hCall) {
  3167. if (LockCall(CallList[i], &pOldCall) == CC_OK) {
  3168. H245H2250MaximumSkewIndication(pOldCall->H245Instance,
  3169. pChannel1->wLocalChannelNumber,
  3170. pChannel2->wLocalChannelNumber,
  3171. pH245ConfIndData->u.Indication.u.IndH2250MaxSkew.wSkew);
  3172. UnlockCall(pCall);
  3173. }
  3174. }
  3175. }
  3176. if (CallList != NULL)
  3177. Free(CallList);
  3178. if ((pChannel1->tsAccepted == TS_TRUE) && (pChannel2->tsAccepted == TS_TRUE)) {
  3179. MaximumAudioVideoSkewCallbackParams.hChannel1 = hChannel1;
  3180. MaximumAudioVideoSkewCallbackParams.hChannel2 = hChannel2;
  3181. MaximumAudioVideoSkewCallbackParams.wMaximumSkew =
  3182. pH245ConfIndData->u.Indication.u.IndH2250MaxSkew.wSkew;
  3183. InvokeUserConferenceCallback(pConference,
  3184. CC_MAXIMUM_AUDIO_VIDEO_SKEW_INDICATION,
  3185. CC_OK,
  3186. &MaximumAudioVideoSkewCallbackParams);
  3187. }
  3188. if (ValidateChannel(hChannel1) == CC_OK)
  3189. UnlockChannel(pChannel1);
  3190. if (ValidateChannel(hChannel2) == CC_OK)
  3191. UnlockChannel(pChannel2);
  3192. if (ValidateConference(hConference) == CC_OK)
  3193. UnlockConference(pConference);
  3194. }
  3195. return H245_ERROR_OK;
  3196. }
  3197. HRESULT _IndUserInput( H245_CONF_IND_T *pH245ConfIndData)
  3198. {
  3199. HRESULT status;
  3200. CC_HCALL hCall;
  3201. PCALL pCall;
  3202. CC_HCONFERENCE hConference;
  3203. PCONFERENCE pConference;
  3204. CC_USER_INPUT_CALLBACK_PARAMS UserInputCallbackParams;
  3205. // only support user input kind string
  3206. if (pH245ConfIndData->u.Indication.u.IndUserInput.Kind != H245_USERINPUT_STRING) {
  3207. return H245_ERROR_OK;
  3208. }
  3209. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  3210. status = LockCallAndConference(hCall, &pCall, &pConference);
  3211. if (status != CC_OK) {
  3212. // This may be OK, if the call was cancelled while
  3213. // call setup was in progress.
  3214. return H245_ERROR_OK;
  3215. }
  3216. hConference = pConference->hConference;
  3217. UserInputCallbackParams.hCall = hCall;
  3218. UserInputCallbackParams.pUserInput =
  3219. pH245ConfIndData->u.Indication.u.IndUserInput.u.pGenString;
  3220. InvokeUserConferenceCallback(pConference,
  3221. CC_USER_INPUT_INDICATION,
  3222. CC_OK,
  3223. &UserInputCallbackParams);
  3224. if (ValidateCall(hCall) == CC_OK)
  3225. UnlockCall(pCall);
  3226. if (ValidateConference(hConference) == CC_OK)
  3227. UnlockConference(pConference);
  3228. return H245_ERROR_OK;
  3229. }
  3230. HRESULT _IndSendTerminalCapabilitySet(
  3231. H245_CONF_IND_T *pH245ConfIndData)
  3232. {
  3233. HRESULT status;
  3234. CC_HCALL hCall;
  3235. PCALL pCall;
  3236. PCONFERENCE pConference;
  3237. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  3238. status = LockCallAndConference(hCall, &pCall, &pConference);
  3239. if (status != CC_OK) {
  3240. // This may be OK, if the call was cancelled while
  3241. // call setup was in progress.
  3242. return H245_ERROR_OK;
  3243. }
  3244. SendTermCaps(pCall, pConference);
  3245. UnlockCall(pCall);
  3246. UnlockConference(pConference);
  3247. return H245_ERROR_OK;
  3248. }
  3249. HRESULT _IndModeRequest( H245_CONF_IND_T *pH245ConfIndData)
  3250. {
  3251. HRESULT status;
  3252. CC_HCALL hCall;
  3253. PCALL pCall;
  3254. CC_HCONFERENCE hConference;
  3255. PCONFERENCE pConference;
  3256. CC_REQUEST_MODE_CALLBACK_PARAMS RequestModeCallbackParams;
  3257. hCall = pH245ConfIndData->u.Indication.dwPreserved;
  3258. status = LockCallAndConference(hCall, &pCall, &pConference);
  3259. if (status != CC_OK) {
  3260. // This may be OK, if the call was cancelled while
  3261. // call setup was in progress.
  3262. return H245_ERROR_OK;
  3263. }
  3264. hConference = pConference->hConference;
  3265. EnqueueRequest(&pConference->pEnqueuedRequestModeCalls, hCall);
  3266. RequestModeCallbackParams.hCall = hCall;
  3267. if (pCall->pPeerParticipantInfo == NULL) {
  3268. RequestModeCallbackParams.InitiatorTerminalLabel.bMCUNumber = 255;
  3269. RequestModeCallbackParams.InitiatorTerminalLabel.bTerminalNumber = 255;
  3270. } else
  3271. RequestModeCallbackParams.InitiatorTerminalLabel =
  3272. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  3273. RequestModeCallbackParams.pRequestedModes =
  3274. pH245ConfIndData->u.Indication.u.IndMrse.pRequestedModes;
  3275. InvokeUserConferenceCallback(pConference,
  3276. CC_REQUEST_MODE_INDICATION,
  3277. CC_OK,
  3278. &RequestModeCallbackParams);
  3279. if (ValidateCall(hCall) == CC_OK)
  3280. UnlockCall(pCall);
  3281. if (ValidateConference(hConference) == CC_OK)
  3282. UnlockConference(pConference);
  3283. return H245_ERROR_OK;
  3284. }
  3285. HRESULT _ConfUnimplemented( H245_CONF_IND_T *pH245ConfIndData)
  3286. {
  3287. return H245_ERROR_NOSUP;
  3288. }
  3289. HRESULT _ConfBiDirectionalOpen( H245_CONF_IND_T *pH245ConfIndData)
  3290. {
  3291. CC_HCALL hCall;
  3292. CC_HCHANNEL hChannel;
  3293. CC_HCONFERENCE hConference;
  3294. PCHANNEL pChannel;
  3295. PCONFERENCE pConference;
  3296. BOOL bAccept;
  3297. HRESULT status;
  3298. CC_ADDR T120Addr;
  3299. CC_OCTETSTRING ExternalReference;
  3300. CC_T120_CHANNEL_OPEN_CALLBACK_PARAMS T120ChannelOpenCallbackParams;
  3301. hCall = pH245ConfIndData->u.Confirm.dwPreserved;
  3302. if (hCall == CC_INVALID_HANDLE)
  3303. return H245_ERROR_OK;
  3304. hChannel = pH245ConfIndData->u.Confirm.dwTransId;
  3305. if (hChannel == CC_INVALID_HANDLE)
  3306. return H245_ERROR_OK;
  3307. if (LockChannelAndConference(hChannel, &pChannel, &pConference) != CC_OK)
  3308. return H245_ERROR_OK;
  3309. hConference = pConference->hConference;
  3310. if (pChannel->bChannelType != TXRX_CHANNEL) {
  3311. UnlockChannel(pChannel);
  3312. UnlockConference(pConference);
  3313. return H245_ERROR_OK;
  3314. }
  3315. if ((pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.AccRej == H245_ACC) &&
  3316. (pH245ConfIndData->u.Confirm.Error == H245_ERROR_OK)) {
  3317. pChannel->wNumOutstandingRequests = 0;
  3318. bAccept = TRUE;
  3319. } else {
  3320. (pChannel->wNumOutstandingRequests)--;
  3321. bAccept = FALSE;
  3322. }
  3323. T120ChannelOpenCallbackParams.hChannel = hChannel;
  3324. T120ChannelOpenCallbackParams.hCall = hCall;
  3325. T120ChannelOpenCallbackParams.dwUserToken = pChannel->dwUserToken;
  3326. T120ChannelOpenCallbackParams.dwRejectReason = 0;
  3327. if (bAccept) {
  3328. status = CC_OK;
  3329. if (pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.pSeparateStack) {
  3330. if ((pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.pSeparateStack->networkAddress.choice == localAreaAddress_chosen) &&
  3331. (pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.pSeparateStack->networkAddress.u.localAreaAddress.choice == unicastAddress_chosen) &&
  3332. (pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.pSeparateStack->networkAddress.u.localAreaAddress.u.unicastAddress.choice == UnicastAddress_iPAddress_chosen)) {
  3333. T120Addr.nAddrType = CC_IP_BINARY;
  3334. T120Addr.bMulticast = FALSE;
  3335. T120Addr.Addr.IP_Binary.wPort =
  3336. pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.pSeparateStack->networkAddress.u.localAreaAddress.u.unicastAddress.u.UnicastAddress_iPAddress.tsapIdentifier;
  3337. H245IPNetworkToHost(&T120Addr.Addr.IP_Binary.dwAddr,
  3338. pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.pSeparateStack->networkAddress.u.localAreaAddress.u.unicastAddress.u.UnicastAddress_iPAddress.network.value);
  3339. T120ChannelOpenCallbackParams.pAddr = &T120Addr;
  3340. } else {
  3341. T120ChannelOpenCallbackParams.pAddr = NULL;
  3342. }
  3343. T120ChannelOpenCallbackParams.bAssociateConference =
  3344. pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.pSeparateStack->associateConference;
  3345. if (pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.pSeparateStack->bit_mask & externalReference_present) {
  3346. ExternalReference.wOctetStringLength = (WORD)
  3347. pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.pSeparateStack->externalReference.length;
  3348. ExternalReference.pOctetString =
  3349. pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.pSeparateStack->externalReference.value;
  3350. T120ChannelOpenCallbackParams.pExternalReference = &ExternalReference;
  3351. } else
  3352. T120ChannelOpenCallbackParams.pExternalReference = NULL;
  3353. } else {
  3354. T120ChannelOpenCallbackParams.pAddr = NULL;
  3355. T120ChannelOpenCallbackParams.bAssociateConference = FALSE;
  3356. T120ChannelOpenCallbackParams.pExternalReference = NULL;
  3357. }
  3358. } else { // bAccept == FALSE
  3359. if (pH245ConfIndData->u.Confirm.Error == H245_ERROR_OK)
  3360. status = CC_PEER_REJECT;
  3361. else
  3362. status = pH245ConfIndData->u.Confirm.Error;
  3363. T120ChannelOpenCallbackParams.pAddr = NULL;
  3364. T120ChannelOpenCallbackParams.bAssociateConference = FALSE;
  3365. T120ChannelOpenCallbackParams.pExternalReference = NULL;
  3366. T120ChannelOpenCallbackParams.dwRejectReason =
  3367. pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.AccRej;
  3368. }
  3369. InvokeUserConferenceCallback(pConference,
  3370. CC_T120_CHANNEL_OPEN_INDICATION,
  3371. status,
  3372. &T120ChannelOpenCallbackParams);
  3373. if (ValidateChannel(hChannel) == CC_OK)
  3374. if (bAccept)
  3375. UnlockChannel(pChannel);
  3376. else
  3377. FreeChannel(pChannel);
  3378. if (ValidateConference(hConference) == CC_OK)
  3379. UnlockConference(pConference);
  3380. return H245_ERROR_OK;
  3381. }
  3382. HRESULT _ConfOpenT120( H245_CONF_IND_T *pH245ConfIndData)
  3383. {
  3384. CC_HCALL hCall;
  3385. CC_HCHANNEL hChannel;
  3386. CC_HCONFERENCE hConference;
  3387. PCHANNEL pChannel;
  3388. PCONFERENCE pConference;
  3389. HRESULT status;
  3390. CC_T120_CHANNEL_OPEN_CALLBACK_PARAMS T120ChannelOpenCallbackParams;
  3391. hCall = pH245ConfIndData->u.Confirm.dwPreserved;
  3392. if (hCall == CC_INVALID_HANDLE)
  3393. return H245_ERROR_OK;
  3394. hChannel = pH245ConfIndData->u.Confirm.dwTransId;
  3395. if (hChannel == CC_INVALID_HANDLE)
  3396. return H245_ERROR_OK;
  3397. if (LockChannelAndConference(hChannel, &pChannel, &pConference) != CC_OK)
  3398. return H245_ERROR_OK;
  3399. hConference = pConference->hConference;
  3400. if (pChannel->bChannelType != TXRX_CHANNEL) {
  3401. UnlockChannel(pChannel);
  3402. UnlockConference(pConference);
  3403. return H245_ERROR_OK;
  3404. }
  3405. if ((pH245ConfIndData->u.Confirm.u.ConfOpen.AccRej == H245_ACC) &&
  3406. (pH245ConfIndData->u.Confirm.Error == H245_ERROR_OK)) {
  3407. // We expect to get a ConfOpenNeedRsp callback for this case;
  3408. // Since we're not sure how we got here, just bail out
  3409. UnlockChannel(pChannel);
  3410. UnlockConference(pConference);
  3411. return H245_ERROR_OK;
  3412. }
  3413. T120ChannelOpenCallbackParams.hChannel = hChannel;
  3414. T120ChannelOpenCallbackParams.hCall = hCall;
  3415. T120ChannelOpenCallbackParams.dwUserToken = pChannel->dwUserToken;
  3416. if (pH245ConfIndData->u.Confirm.Error == H245_ERROR_OK)
  3417. status = CC_PEER_REJECT;
  3418. else
  3419. status = pH245ConfIndData->u.Confirm.Error;
  3420. T120ChannelOpenCallbackParams.pAddr = NULL;
  3421. T120ChannelOpenCallbackParams.bAssociateConference = FALSE;
  3422. T120ChannelOpenCallbackParams.pExternalReference = NULL;
  3423. T120ChannelOpenCallbackParams.dwRejectReason =
  3424. pH245ConfIndData->u.Confirm.u.ConfOpenNeedRsp.AccRej;
  3425. InvokeUserConferenceCallback(pConference,
  3426. CC_T120_CHANNEL_OPEN_INDICATION,
  3427. status,
  3428. &T120ChannelOpenCallbackParams);
  3429. if (ValidateChannel(hChannel) == CC_OK)
  3430. FreeChannel(pChannel);
  3431. if (ValidateConference(hConference) == CC_OK)
  3432. UnlockConference(pConference);
  3433. return H245_ERROR_OK;
  3434. }
  3435. HRESULT _ConfOpen( H245_CONF_IND_T *pH245ConfIndData)
  3436. {
  3437. HRESULT status;
  3438. CC_ADDR PeerRTPAddr;
  3439. PCC_ADDR pPeerRTPAddr;
  3440. CC_ADDR PeerRTCPAddr;
  3441. PCC_ADDR pPeerRTCPAddr;
  3442. CC_HCHANNEL hChannel;
  3443. PCHANNEL pChannel;
  3444. CC_HCONFERENCE hConference;
  3445. PCONFERENCE pConference;
  3446. CC_TX_CHANNEL_OPEN_CALLBACK_PARAMS TxChannelOpenCallbackParams;
  3447. PCALL pCall;
  3448. BOOL bAccept;
  3449. H245_MUX_T H245MuxTable;
  3450. WORD i;
  3451. #ifdef GATEKEEPER
  3452. unsigned uBandwidth;
  3453. WORD wNumCalls;
  3454. PCC_HCALL CallList;
  3455. #endif // GATEKEEPER
  3456. // a channel was opened
  3457. hChannel = pH245ConfIndData->u.Confirm.dwTransId;
  3458. if (hChannel == CC_INVALID_HANDLE)
  3459. return H245_ERROR_OK;
  3460. if (LockChannelAndConference(hChannel, &pChannel, &pConference) != CC_OK)
  3461. return H245_ERROR_OK;
  3462. if (pChannel->bChannelType == TXRX_CHANNEL) {
  3463. UnlockChannel(pChannel);
  3464. UnlockConference(pConference);
  3465. return _ConfOpenT120(pH245ConfIndData);
  3466. }
  3467. hConference = pConference->hConference;
  3468. if (pChannel->wNumOutstandingRequests == 0) {
  3469. UnlockChannel(pChannel);
  3470. UnlockConference(pConference);
  3471. return H245_ERROR_OK;
  3472. }
  3473. if ((pH245ConfIndData->u.Confirm.u.ConfOpen.AccRej == H245_ACC) &&
  3474. (pH245ConfIndData->u.Confirm.Error == H245_ERROR_OK)) {
  3475. pChannel->wNumOutstandingRequests = 0;
  3476. bAccept = TRUE;
  3477. } else {
  3478. (pChannel->wNumOutstandingRequests)--;
  3479. bAccept = FALSE;
  3480. #ifdef GATEKEEPER
  3481. uBandwidth = pChannel->dwBandwidth / 100;
  3482. if (uBandwidth != 0 && pChannel->bChannelType != TXRX_CHANNEL) {
  3483. EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
  3484. for (i = 0; i < wNumCalls; ++i) {
  3485. if (LockCall(CallList[i], &pCall) == CC_OK) {
  3486. if (pCall->GkiCall.uBandwidthUsed >= uBandwidth) {
  3487. if (GkiCloseChannel(&pCall->GkiCall, pChannel->dwBandwidth, hChannel) == CC_OK) {
  3488. UnlockCall(pCall);
  3489. break;
  3490. }
  3491. }
  3492. UnlockCall(pCall);
  3493. }
  3494. } // for
  3495. if (CallList != NULL)
  3496. Free(CallList);
  3497. }
  3498. #endif // GATEKEEPER
  3499. }
  3500. if (pChannel->wNumOutstandingRequests == 0) {
  3501. if (pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux == NULL) {
  3502. pPeerRTPAddr = NULL;
  3503. pPeerRTCPAddr = NULL;
  3504. } else {
  3505. ASSERT(pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->Kind == H245_H2250ACK);
  3506. if ((pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->u.H2250ACK.mediaChannelPresent) &&
  3507. ((pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->u.H2250ACK.mediaChannel.type == H245_IP_MULTICAST) ||
  3508. (pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->u.H2250ACK.mediaChannel.type == H245_IP_UNICAST))) {
  3509. pPeerRTPAddr = &PeerRTPAddr;
  3510. PeerRTPAddr.nAddrType = CC_IP_BINARY;
  3511. if (pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->u.H2250ACK.mediaChannel.type == H245_IP_MULTICAST)
  3512. PeerRTPAddr.bMulticast = TRUE;
  3513. else
  3514. PeerRTPAddr.bMulticast = FALSE;
  3515. H245IPNetworkToHost(&PeerRTPAddr.Addr.IP_Binary.dwAddr,
  3516. pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->u.H2250ACK.mediaChannel.u.ip.network);
  3517. PeerRTPAddr.Addr.IP_Binary.wPort =
  3518. pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->u.H2250ACK.mediaChannel.u.ip.tsapIdentifier;
  3519. } else
  3520. pPeerRTPAddr = NULL;
  3521. if ((pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->u.H2250ACK.mediaControlChannelPresent) &&
  3522. ((pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->u.H2250ACK.mediaControlChannel.type == H245_IP_MULTICAST) ||
  3523. (pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->u.H2250ACK.mediaControlChannel.type == H245_IP_UNICAST))) {
  3524. pPeerRTCPAddr = &PeerRTCPAddr;
  3525. PeerRTCPAddr.nAddrType = CC_IP_BINARY;
  3526. if (pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->u.H2250ACK.mediaControlChannel.type == H245_IP_MULTICAST)
  3527. PeerRTCPAddr.bMulticast = TRUE;
  3528. else
  3529. PeerRTCPAddr.bMulticast = FALSE;
  3530. H245IPNetworkToHost(&PeerRTCPAddr.Addr.IP_Binary.dwAddr,
  3531. pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->u.H2250ACK.mediaControlChannel.u.ip.network);
  3532. PeerRTCPAddr.Addr.IP_Binary.wPort =
  3533. pH245ConfIndData->u.Confirm.u.ConfOpen.pTxMux->u.H2250ACK.mediaControlChannel.u.ip.tsapIdentifier;
  3534. } else
  3535. pPeerRTCPAddr = NULL;
  3536. }
  3537. if ((pPeerRTPAddr == NULL) || (pPeerRTCPAddr == NULL)) {
  3538. if (pConference->pSessionTable != NULL) {
  3539. for (i = 0; i < pConference->pSessionTable->wLength; i++) {
  3540. if (pConference->pSessionTable->SessionInfoArray[i].bSessionID ==
  3541. pChannel->bSessionID) {
  3542. if (pPeerRTPAddr == NULL)
  3543. pPeerRTPAddr = pConference->pSessionTable->SessionInfoArray[i].pRTPAddr;
  3544. if (pPeerRTCPAddr == NULL)
  3545. pPeerRTCPAddr = pConference->pSessionTable->SessionInfoArray[i].pRTCPAddr;
  3546. break;
  3547. }
  3548. }
  3549. }
  3550. }
  3551. if ((pChannel->pPeerRTPAddr == NULL) && (pPeerRTPAddr != NULL))
  3552. CopyAddr(&pChannel->pPeerRTPAddr, pPeerRTPAddr);
  3553. if ((pChannel->pPeerRTCPAddr == NULL) && (pPeerRTCPAddr != NULL))
  3554. CopyAddr(&pChannel->pPeerRTCPAddr, pPeerRTCPAddr);
  3555. if (pChannel->bChannelType == PROXY_CHANNEL) {
  3556. if (LockCall(pChannel->hCall, &pCall) == CC_OK) {
  3557. if (bAccept) {
  3558. H245MuxTable.Kind = H245_H2250ACK;
  3559. H245MuxTable.u.H2250ACK.nonStandardList = NULL;
  3560. if (pPeerRTPAddr != NULL) {
  3561. if (pPeerRTPAddr->bMulticast)
  3562. H245MuxTable.u.H2250ACK.mediaChannel.type = H245_IP_MULTICAST;
  3563. else
  3564. H245MuxTable.u.H2250ACK.mediaChannel.type = H245_IP_UNICAST;
  3565. H245MuxTable.u.H2250ACK.mediaChannel.u.ip.tsapIdentifier =
  3566. pPeerRTPAddr->Addr.IP_Binary.wPort;
  3567. HostToH245IPNetwork(H245MuxTable.u.H2250ACK.mediaChannel.u.ip.network,
  3568. pPeerRTPAddr->Addr.IP_Binary.dwAddr);
  3569. H245MuxTable.u.H2250ACK.mediaChannelPresent = TRUE;
  3570. } else
  3571. H245MuxTable.u.H2250ACK.mediaChannelPresent = FALSE;
  3572. if (pPeerRTCPAddr != NULL) {
  3573. if (pPeerRTCPAddr->bMulticast)
  3574. H245MuxTable.u.H2250ACK.mediaControlChannel.type = H245_IP_MULTICAST;
  3575. else
  3576. H245MuxTable.u.H2250ACK.mediaControlChannel.type = H245_IP_UNICAST;
  3577. H245MuxTable.u.H2250ACK.mediaControlChannel.u.ip.tsapIdentifier =
  3578. pPeerRTCPAddr->Addr.IP_Binary.wPort;
  3579. HostToH245IPNetwork(H245MuxTable.u.H2250ACK.mediaControlChannel.u.ip.network,
  3580. pPeerRTCPAddr->Addr.IP_Binary.dwAddr);
  3581. H245MuxTable.u.H2250ACK.mediaControlChannelPresent = TRUE;
  3582. } else
  3583. H245MuxTable.u.H2250ACK.mediaControlChannelPresent = FALSE;
  3584. H245MuxTable.u.H2250ACK.dynamicRTPPayloadTypePresent = FALSE;
  3585. H245MuxTable.u.H2250ACK.sessionIDPresent = TRUE;
  3586. H245MuxTable.u.H2250ACK.sessionID = pChannel->bSessionID;
  3587. status = H245OpenChannelAccept(pCall->H245Instance,
  3588. 0, // dwTransId
  3589. pChannel->wRemoteChannelNumber, // Rx channel
  3590. &H245MuxTable,
  3591. 0, // Tx channel
  3592. NULL, // Tx mux
  3593. H245_INVALID_PORT_NUMBER,// Port
  3594. NULL);
  3595. } else { // bAccept == FALSE
  3596. status = H245OpenChannelReject(pCall->H245Instance,
  3597. pChannel->wRemoteChannelNumber, // Rx channel
  3598. (unsigned short)pH245ConfIndData->u.Confirm.u.ConfOpen.AccRej); // rejection reason
  3599. }
  3600. UnlockCall(pCall);
  3601. }
  3602. }
  3603. TxChannelOpenCallbackParams.hChannel = hChannel;
  3604. TxChannelOpenCallbackParams.pPeerRTPAddr = pPeerRTPAddr;
  3605. TxChannelOpenCallbackParams.pPeerRTCPAddr = pPeerRTCPAddr;
  3606. TxChannelOpenCallbackParams.dwUserToken = pChannel->dwUserToken;
  3607. if (bAccept) {
  3608. status = CC_OK;
  3609. TxChannelOpenCallbackParams.dwRejectReason = H245_ACC;
  3610. } else { // bAccept = FALSE
  3611. if (pH245ConfIndData->u.Confirm.Error == H245_ERROR_OK)
  3612. status = CC_PEER_REJECT;
  3613. else
  3614. status = pH245ConfIndData->u.Confirm.Error;
  3615. TxChannelOpenCallbackParams.dwRejectReason =
  3616. pH245ConfIndData->u.Confirm.u.ConfOpen.AccRej;
  3617. }
  3618. if ((pChannel->bCallbackInvoked == FALSE) &&
  3619. ((pChannel->bChannelType == TX_CHANNEL) ||
  3620. ((pChannel->bChannelType == TXRX_CHANNEL) &&
  3621. (pChannel->bLocallyOpened == TRUE)))) {
  3622. pChannel->bCallbackInvoked = TRUE;
  3623. InvokeUserConferenceCallback(pConference,
  3624. CC_TX_CHANNEL_OPEN_INDICATION,
  3625. status,
  3626. &TxChannelOpenCallbackParams);
  3627. }
  3628. if (ValidateChannel(hChannel) == CC_OK)
  3629. if (bAccept)
  3630. UnlockChannel(pChannel);
  3631. else
  3632. FreeChannel(pChannel);
  3633. } else
  3634. UnlockChannel(pChannel);
  3635. if (ValidateConference(hConference) == CC_OK)
  3636. UnlockConference(pConference);
  3637. return H245_ERROR_OK;
  3638. }
  3639. HRESULT _ConfClose( H245_CONF_IND_T *pH245ConfIndData)
  3640. {
  3641. if (pH245ConfIndData->u.Confirm.Error != H245_ERROR_OK) {
  3642. // TBD - Report error to Call Control client
  3643. }
  3644. return H245_ERROR_OK;
  3645. }
  3646. HRESULT _ConfRequestClose( H245_CONF_IND_T *pH245ConfIndData)
  3647. {
  3648. CC_HCALL hCall;
  3649. CC_HCHANNEL hChannel;
  3650. PCHANNEL pChannel;
  3651. CC_HCONFERENCE hConference;
  3652. PCONFERENCE pConference;
  3653. PCALL pCall;
  3654. H245_ACC_REJ_T AccRej;
  3655. hCall = pH245ConfIndData->u.Confirm.dwPreserved;
  3656. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  3657. return H245_ERROR_OK;
  3658. hConference = pCall->hConference;
  3659. UnlockCall(pCall);
  3660. if (pH245ConfIndData->u.Confirm.Error == H245_ERROR_OK)
  3661. AccRej = pH245ConfIndData->u.Confirm.u.ConfReqClose.AccRej;
  3662. else
  3663. AccRej = H245_REJ;
  3664. // Note: the only time we need to take any real action is when the channel
  3665. // is a proxy channel, and the local endpoint is not the one which requested
  3666. // the channel closure; in this case, we simply forward the closure response
  3667. // on to the endpoint which initiated the request.
  3668. // If the channel is an RX or TXRX channel, the channel object was deleted
  3669. // when our client requested the channel closure, so there's no real work to
  3670. // be done.
  3671. // If the channel is a proxy channel which our client requested be closed,
  3672. // the channel object will remain around until closed by the TX side, but we
  3673. // don't need (nor do we have a mechanism) to inform our client of receipt
  3674. // of this channel closure response.
  3675. if (FindChannelInConference(pH245ConfIndData->u.Confirm.u.ConfReqClose.Channel,
  3676. FALSE, // remote channel number
  3677. PROXY_CHANNEL,
  3678. hCall,
  3679. &hChannel,
  3680. pConference) != CC_OK) {
  3681. UnlockConference(pConference);
  3682. return H245_ERROR_OK;
  3683. }
  3684. // Set hCall to the peer which initiated the close channel request
  3685. hCall = pH245ConfIndData->u.Confirm.dwTransId;
  3686. if (hCall == CC_INVALID_HANDLE) {
  3687. // The local endpoint was the one who requested the channel closure,
  3688. // so there's no one to forwards this response onto. We don't provide
  3689. // a callback for informing our client of receipt of this response,
  3690. // so we can simply clean up and return
  3691. UnlockConference(pConference);
  3692. return H245_ERROR_OK;
  3693. }
  3694. if (LockChannel(hChannel, &pChannel) != CC_OK) {
  3695. UnlockConference(pConference);
  3696. return H245_ERROR_OK;
  3697. }
  3698. // Forward this response onto the endpoint which requested the channel closure
  3699. if (LockCall(hCall, &pCall) == CC_OK) {
  3700. H245CloseChannelReqResp(pCall->H245Instance,
  3701. AccRej,
  3702. pChannel->wLocalChannelNumber);
  3703. UnlockCall(pCall);
  3704. }
  3705. UnlockChannel(pChannel);
  3706. UnlockConference(pConference);
  3707. return H245_ERROR_OK;
  3708. }
  3709. #if 0
  3710. HRESULT _ConfShutdown( H245_CONF_IND_T *pH245ConfIndData)
  3711. {
  3712. CC_HCALL hCall;
  3713. PCALL pCall;
  3714. CC_HCONFERENCE hConference;
  3715. PCONFERENCE pConference;
  3716. HRESULT status;
  3717. HQ931CALL hQ931Call;
  3718. H245_INST_T H245Instance;
  3719. #if 1
  3720. // Sync 2 - specific code
  3721. hCall = pH245ConfIndData->u.Confirm.dwPreserved;
  3722. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  3723. return H245_ERROR_OK;
  3724. hConference = pCall->hConference;
  3725. if (pConference->tsMultipointController == TS_TRUE) {
  3726. // XXX -- invoke user callback with "peer drop indication"
  3727. } else {
  3728. H245Instance = pCall->H245Instance;
  3729. hQ931Call = pCall->hQ931Call;
  3730. FreeCall(pCall);
  3731. if (H245Instance != H245_INVALID_ID)
  3732. status = H245ShutDown(H245Instance);
  3733. else
  3734. status = H245_ERROR_OK;
  3735. if (status == H245_ERROR_OK) {
  3736. status = Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  3737. // Q931Hangup may legitimately return CS_BAD_PARAM, because the Q.931 call object
  3738. // may have been deleted at this point
  3739. if (status == CS_BAD_PARAM)
  3740. status = CC_OK;
  3741. } else
  3742. Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
  3743. InvokeUserConferenceCallback(pConference,
  3744. CC_CONFERENCE_TERMINATION_INDICATION,
  3745. status,
  3746. NULL);
  3747. if (ValidateConference(hConference) == CC_OK)
  3748. UnlockConference(pConference);
  3749. return H245_ERROR_OK;
  3750. }
  3751. #else
  3752. // Probably sync 3 code
  3753. HHANGUP hHangup;
  3754. PHANGUP pHangup;
  3755. CC_HANGUP_CALLBACK_PARAMS HangupCallbackParams;
  3756. hHangup = pH245ConfIndData->u.Confirm.dwTransId;
  3757. if (hHangup == CC_INVALID_HANDLE)
  3758. return H245_ERROR_OK;
  3759. if (LockHangup(hHangup, &pHangup) != CC_OK)
  3760. return H245_ERROR_OK;
  3761. pHangup->wNumCalls--;
  3762. if (pHangup->wNumCalls == 0) {
  3763. hConference = pHangup->hConference;
  3764. if (LockConference(hConference, &pConference) != CC_OK) {
  3765. UnlockHangup(pHangup);
  3766. return H245_ERROR_OK;
  3767. }
  3768. HangupCallbackParams.dwUserToken = pHangup->dwUserToken;
  3769. InvokeUserConferenceCallback(pConference->ConferenceCallback,
  3770. CC_HANGUP_INDICATION,
  3771. CC_OK,
  3772. hConference,
  3773. pConference->dwConferenceToken,
  3774. &HangupCallbackParams);
  3775. if (ValidateConference(hConference) == CC_OK)
  3776. UnlockConference(pConference);
  3777. if (ValidateHangup(hHangup) == CC_OK)
  3778. FreeHangup(pHangup);
  3779. return H245_ERROR_OK;
  3780. } else
  3781. UnlockHangup(pHangup);
  3782. return H245_ERROR_OK;
  3783. #endif // Sync 3 code
  3784. }
  3785. #endif
  3786. HRESULT _ConfInitMstslv( H245_CONF_IND_T *pH245ConfIndData)
  3787. {
  3788. CC_HCALL hCall;
  3789. PCALL pCall;
  3790. PCONFERENCE pConference;
  3791. CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams;
  3792. CC_HCALL hEnqueuedCall;
  3793. PCALL pEnqueuedCall;
  3794. CC_HCONFERENCE hConference;
  3795. HRESULT status;
  3796. hCall = pH245ConfIndData->u.Confirm.dwPreserved;
  3797. if (LockCallAndConference(hCall, &pCall, &pConference) != CC_OK)
  3798. return H245_ERROR_OK;
  3799. ASSERT(pCall->MasterSlaveState != MASTER_SLAVE_COMPLETE);
  3800. switch (pH245ConfIndData->u.Confirm.u.ConfMstSlv) {
  3801. case H245_MASTER:
  3802. pConference->tsMaster = TS_TRUE;
  3803. if (pConference->tsMultipointController == TS_UNKNOWN) {
  3804. ASSERT(pConference->bMultipointCapable == TRUE);
  3805. pConference->tsMultipointController = TS_TRUE;
  3806. // place all calls enqueued on this conference object
  3807. for ( ; ; ) {
  3808. // Start up all enqueued calls, if any exist
  3809. status = RemoveEnqueuedCallFromConference(pConference, &hEnqueuedCall);
  3810. if ((status != CC_OK) || (hEnqueuedCall == CC_INVALID_HANDLE))
  3811. break;
  3812. status = LockCall(hEnqueuedCall, &pEnqueuedCall);
  3813. if (status == CC_OK) {
  3814. pEnqueuedCall->CallState = PLACED;
  3815. status = PlaceCall(pEnqueuedCall, pConference);
  3816. UnlockCall(pEnqueuedCall);
  3817. }
  3818. }
  3819. }
  3820. break;
  3821. case H245_SLAVE:
  3822. ASSERT(pConference->tsMaster != TS_TRUE);
  3823. ASSERT(pConference->tsMultipointController != TS_TRUE);
  3824. pConference->tsMaster = TS_FALSE;
  3825. pConference->tsMultipointController = TS_FALSE;
  3826. // XXX -- we may eventually want to re-enqueue these requests
  3827. // and set an expiration timer
  3828. hConference = pConference->hConference;
  3829. for ( ; ; ) {
  3830. status = RemoveEnqueuedCallFromConference(pConference, &hEnqueuedCall);
  3831. if ((status != CC_OK) || (hEnqueuedCall == CC_INVALID_HANDLE))
  3832. break;
  3833. status = LockCall(hEnqueuedCall, &pEnqueuedCall);
  3834. if (status == CC_OK) {
  3835. MarkCallForDeletion(pEnqueuedCall);
  3836. ConnectCallbackParams.pNonStandardData = pEnqueuedCall->pPeerNonStandardData;
  3837. ConnectCallbackParams.pszPeerDisplay = pEnqueuedCall->pszPeerDisplay;
  3838. ConnectCallbackParams.bRejectReason = CC_REJECT_UNDEFINED_REASON;
  3839. ConnectCallbackParams.pTermCapList = pEnqueuedCall->pPeerH245TermCapList;
  3840. ConnectCallbackParams.pH2250MuxCapability = pEnqueuedCall->pPeerH245H2250MuxCapability;
  3841. ConnectCallbackParams.pTermCapDescriptors = pEnqueuedCall->pPeerH245TermCapDescriptors;
  3842. ConnectCallbackParams.pLocalAddr = pEnqueuedCall->pQ931LocalConnectAddr;
  3843. if (pEnqueuedCall->pQ931DestinationAddr == NULL)
  3844. ConnectCallbackParams.pPeerAddr = pEnqueuedCall->pQ931PeerConnectAddr;
  3845. else
  3846. ConnectCallbackParams.pPeerAddr = pEnqueuedCall->pQ931DestinationAddr;
  3847. ConnectCallbackParams.pVendorInfo = pEnqueuedCall->pPeerVendorInfo;
  3848. ConnectCallbackParams.bMultipointConference = TRUE;
  3849. ConnectCallbackParams.pConferenceID = &pConference->ConferenceID;
  3850. ConnectCallbackParams.pMCAddress = pConference->pMultipointControllerAddr;
  3851. ConnectCallbackParams.pAlternateAddress = NULL;
  3852. ConnectCallbackParams.dwUserToken = pEnqueuedCall->dwUserToken;
  3853. InvokeUserConferenceCallback(pConference,
  3854. CC_CONNECT_INDICATION,
  3855. CC_NOT_MULTIPOINT_CAPABLE,
  3856. &ConnectCallbackParams);
  3857. if (ValidateCallMarkedForDeletion(hEnqueuedCall) == CC_OK)
  3858. FreeCall(pEnqueuedCall);
  3859. if (ValidateConference(hConference) != CC_OK) {
  3860. if (ValidateCall(hCall) == CC_OK)
  3861. UnlockCall(pCall);
  3862. return H245_ERROR_OK;
  3863. }
  3864. }
  3865. }
  3866. break;
  3867. default: // H245_INDETERMINATE
  3868. UnlockConference(pConference);
  3869. if (++pCall->wMasterSlaveRetry < MASTER_SLAVE_RETRY_MAX) {
  3870. H245InitMasterSlave(pCall->H245Instance, pCall->H245Instance);
  3871. UnlockCall(pCall);
  3872. } else {
  3873. UnlockCall(pCall);
  3874. ProcessRemoteHangup(hCall, CC_INVALID_HANDLE, CC_REJECT_UNDEFINED_REASON);
  3875. }
  3876. return H245_ERROR_OK;
  3877. } // switch
  3878. pCall->MasterSlaveState = MASTER_SLAVE_COMPLETE;
  3879. if ((pCall->OutgoingTermCapState == TERMCAP_COMPLETE) &&
  3880. (pCall->IncomingTermCapState == TERMCAP_COMPLETE) &&
  3881. (pCall->CallState == TERMCAP) &&
  3882. (pCall->MasterSlaveState == MASTER_SLAVE_COMPLETE)) {
  3883. // Note that _ProcessConnectionComplete() returns with pConference and pCall unlocked
  3884. _ProcessConnectionComplete(pConference, pCall);
  3885. return H245_ERROR_OK;
  3886. }
  3887. UnlockCall(pCall);
  3888. UnlockConference(pConference);
  3889. return H245_ERROR_OK;
  3890. }
  3891. HRESULT _ConfSendTermCap( H245_CONF_IND_T *pH245ConfIndData)
  3892. {
  3893. CC_HCALL hCall;
  3894. PCALL pCall;
  3895. HRESULT status;
  3896. PCONFERENCE pConference;
  3897. // A TerminalCapabilitySet message was successfully sent from this endpoint
  3898. hCall = pH245ConfIndData->u.Confirm.dwPreserved;
  3899. status = LockCallAndConference(hCall, &pCall, &pConference);
  3900. if (status != CC_OK) {
  3901. // This may be OK, if the call was cancelled while
  3902. // call setup was in progress.
  3903. return H245_ERROR_OK;
  3904. }
  3905. if (pH245ConfIndData->u.Confirm.Error == H245_ERROR_OK &&
  3906. pH245ConfIndData->u.Confirm.u.ConfSndTcap.AccRej == H245_ACC) {
  3907. pCall->OutgoingTermCapState = TERMCAP_COMPLETE;
  3908. if ((pCall->IncomingTermCapState == TERMCAP_COMPLETE) &&
  3909. (pCall->CallState == TERMCAP) &&
  3910. (pCall->MasterSlaveState == MASTER_SLAVE_COMPLETE)) {
  3911. // Note that _ProcessConnectionComplete() returns with pConference and pCall unlocked
  3912. _ProcessConnectionComplete(pConference, pCall);
  3913. return H245_ERROR_OK;
  3914. }
  3915. } else if (pCall->CallState == TERMCAP) {
  3916. // Report error to Call Control client
  3917. UnlockConference(pConference);
  3918. UnlockCall(pCall);
  3919. ProcessRemoteHangup(hCall, CC_INVALID_HANDLE, CC_REJECT_UNDEFINED_REASON);
  3920. return H245_ERROR_OK;
  3921. }
  3922. UnlockConference(pConference);
  3923. UnlockCall(pCall);
  3924. return H245_ERROR_OK;
  3925. }
  3926. HRESULT _ConfRequestMode( H245_CONF_IND_T *pH245ConfIndData)
  3927. {
  3928. HRESULT status;
  3929. CC_HCALL hCall;
  3930. PCALL pCall;
  3931. CC_HCONFERENCE hConference;
  3932. PCONFERENCE pConference;
  3933. CC_REQUEST_MODE_RESPONSE_CALLBACK_PARAMS RequestModeResponseCallbackParams;
  3934. hCall = pH245ConfIndData->u.Confirm.dwPreserved;
  3935. status = LockCallAndConference(hCall, &pCall, &pConference);
  3936. if (status != CC_OK) {
  3937. // This may be OK, if the call was cancelled while
  3938. // call setup was in progress.
  3939. return H245_ERROR_OK;
  3940. }
  3941. hConference = pConference->hConference;
  3942. RequestModeResponseCallbackParams.hCall = hCall;
  3943. if (pCall->pPeerParticipantInfo == NULL) {
  3944. RequestModeResponseCallbackParams.TerminalLabel.bMCUNumber = 255;
  3945. RequestModeResponseCallbackParams.TerminalLabel.bTerminalNumber = 255;
  3946. } else
  3947. RequestModeResponseCallbackParams.TerminalLabel =
  3948. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  3949. switch (pH245ConfIndData->u.Confirm.u.ConfMrse) {
  3950. case wllTrnsmtMstPrfrrdMd_chosen:
  3951. RequestModeResponseCallbackParams.RequestModeResponse = CC_WILL_TRANSMIT_PREFERRED_MODE;
  3952. break;
  3953. case wllTrnsmtLssPrfrrdMd_chosen:
  3954. RequestModeResponseCallbackParams.RequestModeResponse = CC_WILL_TRANSMIT_LESS_PREFERRED_MODE;
  3955. break;
  3956. default:
  3957. RequestModeResponseCallbackParams.RequestModeResponse = CC_REQUEST_DENIED;
  3958. break;
  3959. }
  3960. InvokeUserConferenceCallback(pConference,
  3961. CC_REQUEST_MODE_RESPONSE_INDICATION,
  3962. pH245ConfIndData->u.Confirm.Error,
  3963. &RequestModeResponseCallbackParams);
  3964. if (ValidateCall(hCall) == CC_OK)
  3965. UnlockCall(pCall);
  3966. if (ValidateConference(hConference) == CC_OK)
  3967. UnlockConference(pConference);
  3968. return H245_ERROR_OK;
  3969. }
  3970. HRESULT _ConfRequestModeReject( H245_CONF_IND_T *pH245ConfIndData)
  3971. {
  3972. HRESULT status;
  3973. CC_HCALL hCall;
  3974. PCALL pCall;
  3975. CC_HCONFERENCE hConference;
  3976. PCONFERENCE pConference;
  3977. CC_REQUEST_MODE_RESPONSE_CALLBACK_PARAMS RequestModeResponseCallbackParams;
  3978. hCall = pH245ConfIndData->u.Confirm.dwPreserved;
  3979. status = LockCallAndConference(hCall, &pCall, &pConference);
  3980. if (status != CC_OK) {
  3981. // This may be OK, if the call was cancelled while
  3982. // call setup was in progress.
  3983. return H245_ERROR_OK;
  3984. }
  3985. hConference = pConference->hConference;
  3986. RequestModeResponseCallbackParams.hCall = hCall;
  3987. if (pCall->pPeerParticipantInfo == NULL) {
  3988. RequestModeResponseCallbackParams.TerminalLabel.bMCUNumber = 255;
  3989. RequestModeResponseCallbackParams.TerminalLabel.bTerminalNumber = 255;
  3990. } else
  3991. RequestModeResponseCallbackParams.TerminalLabel =
  3992. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  3993. switch (pH245ConfIndData->u.Confirm.u.ConfMrseReject) {
  3994. case H245_REJ_UNAVAILABLE:
  3995. RequestModeResponseCallbackParams.RequestModeResponse = CC_MODE_UNAVAILABLE;
  3996. break;
  3997. case H245_REJ_MULTIPOINT:
  3998. RequestModeResponseCallbackParams.RequestModeResponse = CC_MULTIPOINT_CONSTRAINT;
  3999. break;
  4000. case H245_REJ_DENIED:
  4001. RequestModeResponseCallbackParams.RequestModeResponse = CC_REQUEST_DENIED;
  4002. break;
  4003. default:
  4004. RequestModeResponseCallbackParams.RequestModeResponse = CC_REQUEST_DENIED;
  4005. break;
  4006. }
  4007. InvokeUserConferenceCallback(pConference,
  4008. CC_REQUEST_MODE_RESPONSE_INDICATION,
  4009. pH245ConfIndData->u.Confirm.Error,
  4010. &RequestModeResponseCallbackParams);
  4011. if (ValidateCall(hCall) == CC_OK)
  4012. UnlockCall(pCall);
  4013. if (ValidateConference(hConference) == CC_OK)
  4014. UnlockConference(pConference);
  4015. return H245_ERROR_OK;
  4016. }
  4017. HRESULT _ConfRequestModeExpired( H245_CONF_IND_T *pH245ConfIndData)
  4018. {
  4019. HRESULT status;
  4020. CC_HCALL hCall;
  4021. PCALL pCall;
  4022. CC_HCONFERENCE hConference;
  4023. PCONFERENCE pConference;
  4024. CC_REQUEST_MODE_RESPONSE_CALLBACK_PARAMS RequestModeResponseCallbackParams;
  4025. hCall = pH245ConfIndData->u.Confirm.dwPreserved;
  4026. status = LockCallAndConference(hCall, &pCall, &pConference);
  4027. if (status != CC_OK) {
  4028. // This may be OK, if the call was cancelled while
  4029. // call setup was in progress.
  4030. return H245_ERROR_OK;
  4031. }
  4032. hConference = pConference->hConference;
  4033. RequestModeResponseCallbackParams.hCall = hCall;
  4034. if (pCall->pPeerParticipantInfo == NULL) {
  4035. RequestModeResponseCallbackParams.TerminalLabel.bMCUNumber = 255;
  4036. RequestModeResponseCallbackParams.TerminalLabel.bTerminalNumber = 255;
  4037. } else
  4038. RequestModeResponseCallbackParams.TerminalLabel =
  4039. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  4040. RequestModeResponseCallbackParams.RequestModeResponse = CC_REQUEST_DENIED;
  4041. InvokeUserConferenceCallback(pConference,
  4042. CC_REQUEST_MODE_RESPONSE_INDICATION,
  4043. pH245ConfIndData->u.Confirm.Error,
  4044. &RequestModeResponseCallbackParams);
  4045. if (ValidateCall(hCall) == CC_OK)
  4046. UnlockCall(pCall);
  4047. if (ValidateConference(hConference) == CC_OK)
  4048. UnlockConference(pConference);
  4049. return H245_ERROR_OK;
  4050. }
  4051. HRESULT _ConfRoundTrip( H245_CONF_IND_T *pH245ConfIndData)
  4052. {
  4053. CC_HCALL hCall;
  4054. PCALL pCall;
  4055. CC_HCONFERENCE hConference;
  4056. PCONFERENCE pConference;
  4057. HRESULT status;
  4058. CC_PING_RESPONSE_CALLBACK_PARAMS PingCallbackParams;
  4059. hCall = pH245ConfIndData->u.Confirm.dwPreserved;
  4060. status = LockCallAndConference(hCall, &pCall, &pConference);
  4061. if (status != CC_OK) {
  4062. // This may be OK, if the call was cancelled while
  4063. // call setup was in progress.
  4064. return H245_ERROR_OK;
  4065. }
  4066. hConference = pConference->hConference;
  4067. PingCallbackParams.hCall = hCall;
  4068. if (pCall->pPeerParticipantInfo == NULL) {
  4069. PingCallbackParams.TerminalLabel.bMCUNumber = 255;
  4070. PingCallbackParams.TerminalLabel.bTerminalNumber = 255;
  4071. } else
  4072. PingCallbackParams.TerminalLabel =
  4073. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  4074. PingCallbackParams.bResponse = TRUE;
  4075. InvokeUserConferenceCallback(pConference,
  4076. CC_PING_RESPONSE_INDICATION,
  4077. pH245ConfIndData->u.Confirm.Error,
  4078. &PingCallbackParams);
  4079. if (ValidateCall(hCall) == CC_OK)
  4080. UnlockCall(pCall);
  4081. if (ValidateConference(hConference) == CC_OK)
  4082. UnlockConference(pConference);
  4083. return H245_ERROR_OK;
  4084. }
  4085. HRESULT _ConfRoundTripExpired( H245_CONF_IND_T *pH245ConfIndData)
  4086. {
  4087. CC_HCALL hCall;
  4088. PCALL pCall;
  4089. CC_HCONFERENCE hConference;
  4090. PCONFERENCE pConference;
  4091. HRESULT status;
  4092. CC_PING_RESPONSE_CALLBACK_PARAMS PingCallbackParams;
  4093. hCall = pH245ConfIndData->u.Confirm.dwPreserved;
  4094. status = LockCallAndConference(hCall, &pCall, &pConference);
  4095. if (status != CC_OK) {
  4096. // This may be OK, if the call was cancelled while
  4097. // call setup was in progress.
  4098. return H245_ERROR_OK;
  4099. }
  4100. hConference = pConference->hConference;
  4101. PingCallbackParams.hCall = hCall;
  4102. if (pCall->pPeerParticipantInfo == NULL) {
  4103. PingCallbackParams.TerminalLabel.bMCUNumber = 255;
  4104. PingCallbackParams.TerminalLabel.bTerminalNumber = 255;
  4105. } else
  4106. PingCallbackParams.TerminalLabel =
  4107. pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel;
  4108. PingCallbackParams.bResponse = FALSE;
  4109. InvokeUserConferenceCallback(pConference,
  4110. CC_PING_RESPONSE_INDICATION,
  4111. pH245ConfIndData->u.Confirm.Error,
  4112. &PingCallbackParams);
  4113. if (ValidateCall(hCall) == CC_OK)
  4114. UnlockCall(pCall);
  4115. if (ValidateConference(hConference) == CC_OK)
  4116. UnlockConference(pConference);
  4117. return H245_ERROR_OK;
  4118. }
  4119. HRESULT H245Callback( H245_CONF_IND_T *pH245ConfIndData,
  4120. void *pMisc)
  4121. {
  4122. HRESULT status = H245_ERROR_OK;
  4123. EnterCallControl();
  4124. if (CallControlState != OPERATIONAL_STATE)
  4125. HResultLeaveCallControl(H245_ERROR_OK);
  4126. if (pH245ConfIndData == NULL)
  4127. HResultLeaveCallControl(H245_ERROR_OK);
  4128. if (pH245ConfIndData->Kind == H245_CONF) {
  4129. switch (pH245ConfIndData->u.Confirm.Confirm) {
  4130. case H245_CONF_INIT_MSTSLV:
  4131. status = _ConfInitMstslv(pH245ConfIndData);
  4132. break;
  4133. case H245_CONF_SEND_TERMCAP:
  4134. status = _ConfSendTermCap(pH245ConfIndData);
  4135. break;
  4136. case H245_CONF_OPEN:
  4137. status = _ConfOpen(pH245ConfIndData);
  4138. break;
  4139. case H245_CONF_NEEDRSP_OPEN:
  4140. status = _ConfBiDirectionalOpen(pH245ConfIndData);
  4141. break;
  4142. case H245_CONF_CLOSE:
  4143. status = _ConfClose(pH245ConfIndData);
  4144. break;
  4145. case H245_CONF_REQ_CLOSE:
  4146. status = _ConfRequestClose(pH245ConfIndData);
  4147. break;
  4148. // case H245_CONF_MUXTBL_SND: not valid for H.323 MuliplexEntrySend
  4149. // case H245_CONF_RMESE: not valid for H.323 RequestMultiplexEntry
  4150. // case H245_CONF_RMESE_REJECT: not valid for H.323 RequestMultiplexEntryReject
  4151. // case H245_CONF_RMESE_EXPIRED: not valid for H.323
  4152. case H245_CONF_MRSE:
  4153. status = _ConfRequestMode(pH245ConfIndData);
  4154. break;
  4155. case H245_CONF_MRSE_REJECT:
  4156. status = _ConfRequestModeReject(pH245ConfIndData);
  4157. break;
  4158. case H245_CONF_MRSE_EXPIRED:
  4159. status = _ConfRequestModeExpired(pH245ConfIndData);
  4160. break;
  4161. case H245_CONF_RTDSE:
  4162. status = _ConfRoundTrip(pH245ConfIndData);
  4163. break;
  4164. case H245_CONF_RTDSE_EXPIRED:
  4165. status = _ConfRoundTripExpired(pH245ConfIndData);
  4166. break;
  4167. default:
  4168. status = _ConfUnimplemented(pH245ConfIndData);
  4169. break;
  4170. }
  4171. } else if (pH245ConfIndData->Kind == H245_IND) {
  4172. switch (pH245ConfIndData->u.Indication.Indicator) {
  4173. case H245_IND_MSTSLV:
  4174. status = _IndMstslv(pH245ConfIndData);
  4175. break;
  4176. case H245_IND_CAP:
  4177. status = _IndCapability(pH245ConfIndData);
  4178. break;
  4179. case H245_IND_CESE_RELEASE:
  4180. // Remote has abandoned TerminalCapabilitySet
  4181. // No longer need to send TerminalCapabilitySetAck
  4182. // We can probably get away with ignoring this,
  4183. // but we should NOT return FunctionNotSupported!
  4184. break;
  4185. case H245_IND_OPEN:
  4186. status = _IndOpen(pH245ConfIndData);
  4187. break;
  4188. case H245_IND_OPEN_CONF:
  4189. // Bi-directionl channel open complete
  4190. status = _IndOpenConf(pH245ConfIndData);
  4191. break;
  4192. case H245_IND_CLOSE:
  4193. status = _IndClose(pH245ConfIndData);
  4194. break;
  4195. case H245_IND_REQ_CLOSE:
  4196. status = _IndRequestClose(pH245ConfIndData);
  4197. break;
  4198. case H245_IND_CLCSE_RELEASE:
  4199. // Remote has abandoned RequestChannelClose
  4200. // No longer need to send RequestChannelCloseAck and CloseLogicalChannel
  4201. // We can probably get away with ignoring this,
  4202. // but we should NOT return FunctionNotSupported!
  4203. break;
  4204. // case H245_IND_MUX_TBL: not valid in H.323 MuliplexEntrySend
  4205. // case H245_IND_MTSE_RELEASE not valid in H.323 MuliplexEntrySendRelease
  4206. // case H245_IND_RMESE not valid in H.323 RequestMuliplexEntry
  4207. // case H245_IND_RMESE_RELEASE not valid in H.323 RequestMuliplexEntryRelease
  4208. case H245_IND_MRSE:
  4209. status = _IndModeRequest(pH245ConfIndData);
  4210. break;
  4211. case H245_IND_MRSE_RELEASE:
  4212. // Remote has abandoned RequestMode
  4213. // No longer need to send RequestModeAck or RequestModeReject
  4214. // We can probably get away with ignoring this,
  4215. // but we should NOT return FunctionNotSupported!
  4216. break;
  4217. // case H245_IND_MLSE: We don't support looping back data
  4218. case H245_IND_MLSE_RELEASE:
  4219. // Required to accept this message
  4220. break;
  4221. case H245_IND_NONSTANDARD_REQUEST:
  4222. case H245_IND_NONSTANDARD_RESPONSE:
  4223. case H245_IND_NONSTANDARD_COMMAND:
  4224. case H245_IND_NONSTANDARD:
  4225. status = _IndNonStandard(pH245ConfIndData);
  4226. break;
  4227. case H245_IND_MISC_COMMAND:
  4228. status = _IndMiscellaneousCommand(pH245ConfIndData, pMisc);
  4229. break;
  4230. case H245_IND_MISC:
  4231. status = _IndMiscellaneous(pH245ConfIndData, pMisc);
  4232. break;
  4233. case H245_IND_COMM_MODE_REQUEST:
  4234. status = _IndUnimplemented(pH245ConfIndData); // TBD
  4235. break;
  4236. // case H245_IND_COMM_MODE_RESPONSE: We never send request!
  4237. case H245_IND_COMM_MODE_COMMAND:
  4238. status = _IndCommunicationModeCommand(pH245ConfIndData);
  4239. break;
  4240. case H245_IND_CONFERENCE_REQUEST:
  4241. status = _IndConferenceRequest(pH245ConfIndData);
  4242. break;
  4243. case H245_IND_CONFERENCE_RESPONSE:
  4244. status = _IndConferenceResponse(pH245ConfIndData);
  4245. break;
  4246. case H245_IND_CONFERENCE_COMMAND:
  4247. status = _IndConferenceCommand(pH245ConfIndData);
  4248. break;
  4249. case H245_IND_CONFERENCE:
  4250. status = _IndConference(pH245ConfIndData);
  4251. break;
  4252. case H245_IND_SEND_TERMCAP:
  4253. status = _IndSendTerminalCapabilitySet(pH245ConfIndData);
  4254. break;
  4255. // case H245_IND_ENCRYPTION: Not valid in H.323
  4256. case H245_IND_FLOW_CONTROL:
  4257. status = _IndFlowControl(pH245ConfIndData);
  4258. break;
  4259. case H245_IND_ENDSESSION:
  4260. status = _IndEndSession(pH245ConfIndData);
  4261. break;
  4262. case H245_IND_FUNCTION_NOT_UNDERSTOOD:
  4263. // We don't do anything with this but we still want to
  4264. // return H245_ERROR_OK so H.245 does not sent
  4265. // FunctionNotSupported back to remote peer!
  4266. break;
  4267. case H245_IND_JITTER:
  4268. // It is ok to ignore this; no response is expected
  4269. break;
  4270. // case H245_IND_H223_SKEW: Not valid in H.323
  4271. // case H245_IND_NEW_ATM_VC: Not valid in H.323
  4272. case H245_IND_USERINPUT:
  4273. status = _IndUserInput(pH245ConfIndData);
  4274. break;
  4275. case H245_IND_H2250_MAX_SKEW:
  4276. status = _IndH2250MaximumSkew(pH245ConfIndData);
  4277. break;
  4278. case H245_IND_MC_LOCATION:
  4279. status = _IndMCLocation(pH245ConfIndData);
  4280. break;
  4281. case H245_IND_VENDOR_ID:
  4282. status = _IndVendorIdentification(pH245ConfIndData, pMisc);
  4283. break;
  4284. case H245_IND_FUNCTION_NOT_SUPPORTED:
  4285. // We don't do anything with this but we still want to
  4286. // return H245_ERROR_OK so H.245 does not sent
  4287. // FunctionNotSupported back to remote peer!
  4288. break;
  4289. // case H245_IND_H223_RECONFIG: Not valid in H.323
  4290. // case H245_IND_H223_RECONFIG_ACK: Not valid in H.323
  4291. // case H245_IND_H223_RECONFIG_REJECT: Not valid in H.323
  4292. default:
  4293. status = _IndUnimplemented(pH245ConfIndData);
  4294. break;
  4295. }
  4296. }
  4297. HResultLeaveCallControl(status);
  4298. }