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.

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