Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3748 lines
135 KiB

  1. /******************************************************************************
  2. *
  3. * INTEL Corporation Proprietary Information
  4. * Copyright (c) 1994, 1995, 1996 Intel Corporation.
  5. *
  6. * This listing is supplied under the terms of a license agreement
  7. * with INTEL Corporation and may not be used, copied, nor disclosed
  8. * except in accordance with the terms of that agreement.
  9. *
  10. *****************************************************************************/
  11. /******************************************************************************
  12. *
  13. * $Workfile: api_up.c $
  14. * $Revision: 1.33 $
  15. * $Modtime: 06 Feb 1997 14:37:24 $
  16. * $Log: S:\sturgeon\src\h245\src\vcs\api_up.c_v $
  17. *
  18. * Rev 1.33 06 Feb 1997 18:14:22 SBELL1
  19. * took out ossDecoding of returnFunction in FunctionNotSupported PDU.
  20. *
  21. * Rev 1.32 05 Feb 1997 16:46:42 EHOWARDX
  22. * Was allocating nLength bytes, not WCHARS, for UserInputIndication
  23. * ASCII to Unicode conversion. Changed to allocate nLength WCHARs.
  24. *
  25. * Rev 1.31 06 Jan 1997 20:38:18 EHOWARDX
  26. *
  27. * Changed H245_CONF_CLOSE and H245_CONF_REQ_CLOSE to fill in
  28. * AccRej with H245_REJ for any errors.
  29. *
  30. * Rev 1.30 19 Dec 1996 21:00:56 EHOWARDX
  31. * Oops! H245_IND_OPEN_CONF can occur from T103 timeout (it's unique among
  32. * indications; it's the only one that can happen in response to a timeout!)
  33. *
  34. * Rev 1.29 19 Dec 1996 17:18:22 EHOWARDX
  35. * Changed to use h245asn1.h definitions instead of _setof3 and _setof8.
  36. *
  37. * Rev 1.28 18 Dec 1996 16:33:18 EHOWARDX
  38. *
  39. * Fixed bug in Master Slave Determination Kludge.
  40. *
  41. * Rev 1.27 17 Dec 1996 17:13:20 EHOWARDX
  42. * Added pSeparateStack to IND_OPEN_T.
  43. *
  44. * Rev 1.26 12 Dec 1996 15:57:12 EHOWARDX
  45. * Master Slave Determination kludge.
  46. *
  47. * Rev 1.25 21 Oct 1996 16:07:38 EHOWARDX
  48. * Modified to make sure H245_INDETERMINATE is returned and Master/Slave
  49. * status if determination fails.
  50. *
  51. * Rev 1.24 17 Oct 1996 18:17:14 EHOWARDX
  52. * Changed general string to always be Unicode.
  53. *
  54. * Rev 1.23 14 Oct 1996 14:01:12 EHOWARDX
  55. * Unicode changes.
  56. *
  57. * Rev 1.22 27 Aug 1996 10:54:16 unknown
  58. * Deleted redundant lines.
  59. *
  60. * Rev 1.22 27 Aug 1996 10:52:28 unknown
  61. * Deleted redundant lines.
  62. *
  63. * Rev 1.22 27 Aug 1996 09:54:12 unknown
  64. * Deleted redundant lines.
  65. *
  66. * Rev 1.21 26 Aug 1996 14:19:18 EHOWARDX
  67. * Added code to send FunctionNotUnderstood indication to remote peer
  68. * if receive callback returns H245_ERROR_NOSUP.
  69. *
  70. * Rev 1.20 20 Aug 1996 14:44:40 EHOWARDX
  71. * Changed H245_IND_COMM_MODE_RESPONSE and H245_IND_COMM_MODE_COMMAND
  72. * callbacks to fill in DataType field in Cap as per Mike Andrews' request.
  73. *
  74. * Rev 1.19 15 Aug 1996 15:20:24 EHOWARDX
  75. * First pass at new H245_COMM_MODE_ENTRY_T requested by Mike Andrews.
  76. * Use at your own risk!
  77. *
  78. * Rev 1.18 15 Aug 1996 09:34:20 EHOWARDX
  79. * Made TOTCAP and MUX structure in process_open_ind static since we are
  80. * accessing pointers to them after return from the function.
  81. *
  82. * Rev 1.17 29 Jul 1996 19:33:00 EHOWARDX
  83. *
  84. * Fixed bug in flow control - missing break in restriction switch statement.
  85. *
  86. * Rev 1.16 19 Jul 1996 14:11:26 EHOWARDX
  87. *
  88. * Added indication callback structure for CommunicationModeResponse
  89. * and CommunicationModeCommand.
  90. *
  91. * Rev 1.15 19 Jul 1996 12:48:00 EHOWARDX
  92. *
  93. * Multipoint clean-up.
  94. *
  95. * Rev 1.14 09 Jul 1996 17:09:28 EHOWARDX
  96. * Fixed pointer offset bug in processing DataType from received
  97. * OpenLogicalChannel.
  98. *
  99. * Rev 1.13 01 Jul 1996 22:13:04 EHOWARDX
  100. *
  101. * Added Conference and CommunicationMode structures and functions.
  102. *
  103. * Rev 1.12 18 Jun 1996 14:50:28 EHOWARDX
  104. *
  105. * Changed MLSE confirm handling.
  106. *
  107. * Rev 1.11 14 Jun 1996 18:57:52 EHOWARDX
  108. * Geneva update.
  109. *
  110. * Rev 1.10 10 Jun 1996 16:55:34 EHOWARDX
  111. * Removed #include "h245init.x"
  112. *
  113. * Rev 1.9 06 Jun 1996 18:45:52 EHOWARDX
  114. * Added check for null dwTransId to Tracker routines; changed to use
  115. * tracker routines instead of PLOCK macros.
  116. *
  117. * Rev 1.8 04 Jun 1996 13:56:46 EHOWARDX
  118. * Fixed Release build warnings.
  119. *
  120. * Rev 1.7 30 May 1996 23:39:00 EHOWARDX
  121. * Cleanup.
  122. *
  123. * Rev 1.6 29 May 1996 15:20:06 EHOWARDX
  124. * Change to use HRESULT.
  125. *
  126. * Rev 1.5 28 May 1996 14:22:58 EHOWARDX
  127. * Tel Aviv update.
  128. *
  129. * Rev 1.4 20 May 1996 22:17:58 EHOWARDX
  130. * Completed NonStandard Message and H.225.0 Maximum Skew indication
  131. * implementation. Added ASN.1 validation to H245SetLocalCap and
  132. * H245SetCapDescriptor. Check-in from Microsoft drop on 17-May-96.
  133. *
  134. * Rev 1.3 16 May 1996 19:40:46 EHOWARDX
  135. * Fixed multiplex capability bug.
  136. *
  137. * Rev 1.2 16 May 1996 15:59:24 EHOWARDX
  138. * Fine-tuning H245SetLocalCap/H245DelLocalCap/H245SetCapDescriptor/
  139. * H245DelCapDescriptor behaviour.
  140. *
  141. * Rev 1.1 13 May 1996 23:16:26 EHOWARDX
  142. * Fixed remote terminal capability handling.
  143. *
  144. * Rev 1.0 09 May 1996 21:06:08 EHOWARDX
  145. * Initial revision.
  146. *
  147. * Rev 1.23.1.11 09 May 1996 19:31:30 EHOWARDX
  148. * Redesigned thread locking logic.
  149. * Added new API functions.
  150. *
  151. * Rev 1.23.1.10 01 May 1996 19:30:32 EHOWARDX
  152. * Added H245CopyCap(), H245FreeCap(), H245CopyMux(), H245FreeMux().
  153. * Changed H2250_xxx definitions for H.225.0 address types to H245_xxx.
  154. *
  155. * Rev 1.23.1.9 29 Apr 1996 16:02:58 EHOWARDX
  156. * Changed callback to give second parameters as pointer to specific message
  157. * instead of pointer to general PDU structure.
  158. *
  159. * Rev 1.23.1.8 27 Apr 1996 21:09:40 EHOWARDX
  160. * Changed Channel Numbers to words, added H.225.0 support.
  161. *
  162. * Rev 1.23.1.7 26 Apr 1996 15:54:34 EHOWARDX
  163. * Added H.225.0 Capability support; Changed Capability indication
  164. * to only callback once with PDU.
  165. *
  166. * Rev 1.23.1.6 24 Apr 1996 20:53:56 EHOWARDX
  167. * Added new OpenLogicalChannelAck/OpenLogicalChannelReject support.
  168. *
  169. * Rev 1.23.1.5 23 Apr 1996 14:45:28 EHOWARDX
  170. * Disabled Curt's "Conflict Resolution".
  171. *
  172. * Rev 1.23.1.4 19 Apr 1996 12:55:10 EHOWARDX
  173. * Updated to 1.29
  174. *
  175. * Rev 1.23.1.3 17 Apr 1996 14:37:38 unknown
  176. * Added load_H222_param(), load_VGMUX_param(), and load_H2250_param() and
  177. * modified process_open_ind() to use them.
  178. *
  179. * Rev 1.23.1.2 15 Apr 1996 15:10:32 EHOWARDX
  180. * Updated to match Curt's current version.
  181. *
  182. * Rev 1.23.1.1 03 Apr 1996 17:15:00 EHOWARDX
  183. * No change.
  184. *
  185. * Rev 1.23.1.0 03 Apr 1996 15:54:04 cjutzi
  186. * Branched for H.323.
  187. *
  188. * Rev 1.23 01 Apr 1996 16:46:20 cjutzi
  189. *
  190. * - changed tracker structure
  191. * - Completed ENdConnection, and made asynch.. rather
  192. * than sync.. as before
  193. * Changed H245ShutDown to be sync rather than async..
  194. *
  195. * Rev 1.22 29 Mar 1996 14:54:28 cjutzi
  196. * - added UserInput,
  197. *
  198. * Rev 1.21 28 Mar 1996 15:57:46 cjutzi
  199. * - removed ASSERT line 1290.. close can occur on any channel at any time
  200. *
  201. * Rev 1.20 27 Mar 1996 08:36:40 cjutzi
  202. * - removed PDU from stack.. made them dynamically allocated
  203. *
  204. * Rev 1.19 26 Mar 1996 13:48:30 cjutzi
  205. *
  206. * - dwPreserved in the callback routine was uninitialized..
  207. *
  208. * Rev 1.18 18 Mar 1996 15:23:30 cjutzi
  209. *
  210. *
  211. *
  212. * Rev 1.17 13 Mar 1996 14:14:02 cjutzi
  213. *
  214. * - clean up and added ASSERTs ..
  215. *
  216. * Rev 1.16 13 Mar 1996 12:06:12 cjutzi
  217. *
  218. * - fixed .. CONFIRM open.. for hani.. It released the tracker..
  219. * was supposed to simply update the state to IDLE..
  220. *
  221. * Rev 1.15 13 Mar 1996 09:22:12 cjutzi
  222. *
  223. * - removed CRITICAL SECTIONS
  224. *
  225. * Rev 1.14 12 Mar 1996 15:52:32 cjutzi
  226. *
  227. * - fixed master slave (forgot a break)
  228. * - fixed callback bug w/ cleanup on termcaps.
  229. * - implemented End Session
  230. * - fixed shutdown
  231. * - Implemented Locking (big changes here.. )
  232. *
  233. * Rev 1.13 08 Mar 1996 14:04:18 cjutzi
  234. *
  235. * - implemented the upcall for mux table entries..
  236. * - implemented capabillity descriptor callback
  237. *
  238. * Rev 1.12 05 Mar 1996 17:36:28 cjutzi
  239. *
  240. * - added MasterSlave indication message
  241. * - remove bzero/bcopy and changed free call
  242. * - implemented Mux Table down.. (not up)
  243. *
  244. * Rev 1.11 01 Mar 1996 14:16:08 cjutzi
  245. *
  246. * - added hani's error messages.. MasterSlave_FAILED.. oppss.. Forgot..
  247. *
  248. * Rev 1.10 01 Mar 1996 13:47:58 cjutzi
  249. *
  250. * - added hani's new fsm id's
  251. *
  252. * Rev 1.9 29 Feb 1996 17:26:16 cjutzi
  253. * - bi-directional channel open working
  254. *
  255. * Rev 1.8 27 Feb 1996 14:56:30 cjutzi
  256. *
  257. * - fixed termcap_ack.. pdu was not being zero'd out..
  258. * - cleaned up the code alittle..
  259. *
  260. * Rev 1.7 26 Feb 1996 17:22:40 cjutzi
  261. *
  262. * - Misc Command Indication added
  263. *
  264. * Rev 1.6 26 Feb 1996 11:05:48 cjutzi
  265. *
  266. * - lot's o-changes.. (sorry)
  267. *
  268. * Rev 1.5 16 Feb 1996 13:01:54 cjutzi
  269. *
  270. * - got open / close / request close working in both directions.
  271. *
  272. * Rev 1.4 15 Feb 1996 14:11:46 cjutzi
  273. *
  274. * - added muxt table to incoming open..
  275. *
  276. * Rev 1.3 15 Feb 1996 10:51:56 cjutzi
  277. *
  278. * - termcaps working
  279. * - changed API interface for MUX_T
  280. * - changed callback for IND_OPEN
  281. * - changed constants IND_OPEN/IND_OPEN_NEEDSRSP
  282. * - cleaned up the open.
  283. * - modified H223 stuff
  284. *
  285. * Rev 1.2 09 Feb 1996 16:58:28 cjutzi
  286. *
  287. * - cleanup.. and some fixes..
  288. * - added and or changed headers to reflect the log of changes
  289. *
  290. *****************************************************************************/
  291. /****************************************************************************/
  292. /****************************************************************************/
  293. /****************************************************************************/
  294. /**** *****/
  295. /**** NOTES TO THE READER *****/
  296. /**** *****/
  297. /**** This program has been put together using a a screen which is *****/
  298. /**** wider than 80 characters.. It is best if a similar screen size is *****/
  299. /**** used.. Of course emacs is my preference but 80 col screens will *****/
  300. /**** cause you much frustration.. *****/
  301. /**** *****/
  302. /**** Tabs are set to 8 *****/
  303. /**** *****/
  304. /****************************************************************************/
  305. /****************************************************************************/
  306. /****************************************************************************/
  307. #ifndef STRICT
  308. #define STRICT
  309. #endif
  310. #include "precomp.h"
  311. /***********************/
  312. /* H245 INCLUDES */
  313. /***********************/
  314. #include "h245api.h"
  315. #include "h245com.h"
  316. #include "h245sys.x"
  317. #include "h245asn1.h"
  318. #include "fsmexpor.h"
  319. #include "api_util.x"
  320. #include "pdu.x"
  321. HRESULT
  322. LoadUnicastAddress (H245_TRANSPORT_ADDRESS_T *pOut,
  323. UnicastAddress *pIn)
  324. {
  325. switch (pIn->choice)
  326. {
  327. case UnicastAddress_iPAddress_chosen:
  328. pOut->type = H245_IP_UNICAST;
  329. memcpy(pOut->u.ip.network,
  330. pIn->u.UnicastAddress_iPAddress.network.value,
  331. 4);
  332. pOut->u.ip.tsapIdentifier = pIn->u.UnicastAddress_iPAddress.tsapIdentifier;
  333. break;
  334. case iPXAddress_chosen:
  335. pOut->type = H245_IPX_UNICAST;
  336. memcpy(pOut->u.ipx.node,
  337. pIn->u.iPXAddress.node.value,
  338. 6);
  339. memcpy(pOut->u.ipx.netnum,
  340. pIn->u.iPXAddress.netnum.value,
  341. 4);
  342. memcpy(pOut->u.ipx.tsapIdentifier,
  343. pIn->u.iPXAddress.tsapIdentifier.value,
  344. 2);
  345. break;
  346. case UncstAddrss_iP6Address_chosen:
  347. pOut->type = H245_IP6_UNICAST;
  348. memcpy(pOut->u.ip6.network,
  349. pIn->u.UncstAddrss_iP6Address.network.value,
  350. 16);
  351. pOut->u.ip6.tsapIdentifier = pIn->u.UncstAddrss_iP6Address.tsapIdentifier;
  352. break;
  353. case netBios_chosen:
  354. pOut->type = H245_NETBIOS_UNICAST;
  355. memcpy(pOut->u.netBios, pIn->u.netBios.value, 16);
  356. break;
  357. case iPSourceRouteAddress_chosen:
  358. switch (pIn->u.iPSourceRouteAddress.routing.choice)
  359. {
  360. case strict_chosen:
  361. pOut->type = H245_IPSSR_UNICAST;
  362. break;
  363. case loose_chosen:
  364. pOut->type = H245_IPLSR_UNICAST;
  365. break;
  366. default:
  367. return H245_ERROR_INVALID_DATA_FORMAT;
  368. } // switch
  369. memcpy(pOut->u.ipSourceRoute.network,
  370. pIn->u.iPSourceRouteAddress.network.value,
  371. 4);
  372. pOut->u.ipSourceRoute.tsapIdentifier = pIn->u.iPSourceRouteAddress.tsapIdentifier;
  373. // TBD - handle route
  374. break;
  375. default:
  376. return H245_ERROR_INVALID_DATA_FORMAT;
  377. } // switch
  378. return H245_ERROR_OK;
  379. } // LoadUnicastAddress()
  380. HRESULT
  381. LoadMulticastAddress(H245_TRANSPORT_ADDRESS_T *pOut,
  382. MulticastAddress *pIn)
  383. {
  384. switch (pIn->choice)
  385. {
  386. case MltcstAddrss_iPAddress_chosen:
  387. pOut->type = H245_IP_MULTICAST;
  388. memcpy(pOut->u.ip.network,
  389. pIn->u.MltcstAddrss_iPAddress.network.value,
  390. 4);
  391. pOut->u.ip.tsapIdentifier = pIn->u.MltcstAddrss_iPAddress.tsapIdentifier;
  392. break;
  393. case MltcstAddrss_iP6Address_chosen:
  394. pOut->type = H245_IP6_MULTICAST;
  395. memcpy(pOut->u.ip6.network,
  396. pIn->u.MltcstAddrss_iP6Address.network.value,
  397. 16);
  398. pOut->u.ip6.tsapIdentifier = pIn->u.MltcstAddrss_iP6Address.tsapIdentifier;
  399. break;
  400. default:
  401. return H245_ERROR_INVALID_DATA_FORMAT;
  402. } // switch
  403. return H245_ERROR_OK;
  404. } // LoadMulticastAddress()
  405. HRESULT
  406. LoadTransportAddress(H245_TRANSPORT_ADDRESS_T *pOut,
  407. H245TransportAddress *pIn)
  408. {
  409. switch (pIn->choice)
  410. {
  411. case unicastAddress_chosen:
  412. return LoadUnicastAddress (pOut, &pIn->u.unicastAddress);
  413. case multicastAddress_chosen:
  414. return LoadMulticastAddress(pOut, &pIn->u.multicastAddress);
  415. default:
  416. return H245_ERROR_INVALID_DATA_FORMAT;
  417. } // switch
  418. } // LoadTransportAddress()
  419. HRESULT
  420. LoadCommModeEntry(H245_COMM_MODE_ENTRY_T *pOut,
  421. CommunicationModeTableEntry *pIn)
  422. {
  423. HRESULT lResult;
  424. memset(pOut, 0, sizeof(*pOut));
  425. if (pIn->bit_mask & CMTEy_nnStndrd_present)
  426. {
  427. pOut->pNonStandard = pIn->CMTEy_nnStndrd;
  428. }
  429. pOut->sessionID = (unsigned char)pIn->sessionID;
  430. if (pIn->bit_mask & CMTEy_assctdSssnID_present)
  431. {
  432. pOut->associatedSessionID = (unsigned char)pIn->CMTEy_assctdSssnID;
  433. pOut->associatedSessionIDPresent = TRUE;
  434. }
  435. if (pIn->bit_mask & CommunicationModeTableEntry_terminalLabel_present)
  436. {
  437. pOut->terminalLabel = pIn->terminalLabel;
  438. pOut->terminalLabelPresent = TRUE;
  439. }
  440. pOut->pSessionDescription = pIn->sessionDescription.value;
  441. pOut->wSessionDescriptionLength = (WORD) pIn->sessionDescription.length;
  442. switch (pIn->dataType.choice)
  443. {
  444. case dataType_videoData_chosen:
  445. pOut->dataType.DataType = H245_DATA_VIDEO;
  446. break;
  447. case dataType_audioData_chosen:
  448. pOut->dataType.DataType = H245_DATA_AUDIO;
  449. break;
  450. case dataType_data_chosen:
  451. pOut->dataType.DataType = H245_DATA_DATA;
  452. break;
  453. default:
  454. return H245_ERROR_INVALID_DATA_FORMAT;
  455. } // switch
  456. lResult = build_totcap_cap_n_client_from_capability ((struct Capability *)&pIn->dataType,
  457. pOut->dataType.DataType,
  458. pIn->dataType.u.dataType_videoData.choice,
  459. &pOut->dataType);
  460. if (lResult != H245_ERROR_OK)
  461. return lResult;
  462. if (pIn->bit_mask & CMTEy_mdChnnl_present)
  463. {
  464. lResult = LoadTransportAddress(&pOut->mediaChannel, &pIn->CMTEy_mdChnnl);
  465. if (lResult != H245_ERROR_OK)
  466. return lResult;
  467. pOut->mediaChannelPresent = TRUE;
  468. }
  469. if (pIn->bit_mask & CMTEy_mdGrntdDlvry_present)
  470. {
  471. pOut->mediaGuaranteed = pIn->CMTEy_mdGrntdDlvry;
  472. pOut->mediaGuaranteedPresent = TRUE;
  473. }
  474. if (pIn->bit_mask & CMTEy_mdCntrlChnnl_present)
  475. {
  476. lResult = LoadTransportAddress(&pOut->mediaControlChannel, &pIn->CMTEy_mdCntrlChnnl);
  477. if (lResult != H245_ERROR_OK)
  478. return lResult;
  479. pOut->mediaControlChannelPresent = TRUE;
  480. }
  481. if (pIn->bit_mask & CMTEy_mdCntrlGrntdDlvry_present)
  482. {
  483. pOut->mediaControlGuaranteed = pIn->CMTEy_mdCntrlGrntdDlvry;
  484. pOut->mediaControlGuaranteedPresent = TRUE;
  485. }
  486. return H245_ERROR_OK;
  487. } // LoadCommModeEntry()
  488. /*****************************************************************************
  489. *
  490. * TYPE: Local
  491. *
  492. * PROCEDURE: load_H222_param
  493. * load_H223_param
  494. * load_VGMUX_param
  495. * load_H2250_param
  496. * load_H2250ACK_param
  497. *
  498. * DESCRIPTION
  499. *
  500. * This routine builds local API-style Logical Parameters out of ASN.1
  501. * structure passed to it
  502. *
  503. *
  504. * RETURN:
  505. *
  506. *****************************************************************************/
  507. static HRESULT
  508. load_H222_param (H245_H222_LOGICAL_PARAM_T * pOut, /* output */
  509. H222LogicalChannelParameters * pIn) /* input */
  510. {
  511. /* See setup_H220_mux() for inverse function */
  512. memset(pOut, 0, sizeof(*pOut));
  513. pOut->resourceID = pIn->resourceID;
  514. pOut->subChannelID = pIn->subChannelID;
  515. if (pIn->bit_mask & pcr_pid_present)
  516. {
  517. pOut->pcr_pidPresent = TRUE;
  518. pOut->pcr_pid = pIn->pcr_pid;
  519. }
  520. if (pIn->bit_mask & programDescriptors_present)
  521. {
  522. pOut->programDescriptors.length = pIn->programDescriptors.length;
  523. pOut->programDescriptors.value = pIn->programDescriptors.value;
  524. }
  525. if (pIn->bit_mask & streamDescriptors_present)
  526. {
  527. pOut->streamDescriptors.length = pIn->streamDescriptors.length;
  528. pOut->streamDescriptors.value = pIn->streamDescriptors.value;
  529. }
  530. return H245_ERROR_OK;
  531. } // load_H222_param()
  532. static HRESULT
  533. load_H223_param (H245_H223_LOGICAL_PARAM_T * pOut, /* output */
  534. H223LogicalChannelParameters * pIn) /* input */
  535. {
  536. HRESULT lError = H245_ERROR_OK;
  537. /* See setup_H223_mux() for inverse function */
  538. memset(pOut, 0, sizeof(*pOut));
  539. pOut->SegmentFlag = pIn->segmentableFlag;
  540. switch (pIn->adaptationLayerType.choice)
  541. {
  542. case H223LCPs_aLTp_nnStndrd_chosen:
  543. lError = CopyNonStandardParameter(&pOut->H223_NONSTD,
  544. &pIn->adaptationLayerType.u.H223LCPs_aLTp_nnStndrd);
  545. pOut->AlType = H245_H223_AL_NONSTD;
  546. break;
  547. case H223LCPs_aLTp_al1Frmd_chosen:
  548. pOut->AlType = H245_H223_AL_AL1FRAMED;
  549. break;
  550. case H223LCPs_aLTp_al1NtFrmd_chosen:
  551. pOut->AlType = H245_H223_AL_AL1NOTFRAMED;
  552. break;
  553. case H223LCPs_aLTp_a2WSNs_1_chosen:
  554. pOut->AlType = H245_H223_AL_AL2NOSEQ;
  555. break;
  556. case H223LCPs_aLTp_a2WSNs_2_chosen:
  557. pOut->AlType = H245_H223_AL_AL2SEQ;
  558. break;
  559. case H223LCPs_aLTp_al3_chosen:
  560. pOut->AlType = H245_H223_AL_AL3;
  561. pOut->CtlFldOctet = (unsigned char)pIn->adaptationLayerType.u.H223LCPs_aLTp_al3.controlFieldOctets;
  562. pOut->SndBufSize = pIn->adaptationLayerType.u.H223LCPs_aLTp_al3.sendBufferSize;
  563. break;
  564. } /* switch */
  565. return lError;
  566. } // load_H223_param()
  567. static HRESULT
  568. load_VGMUX_param(H245_VGMUX_LOGICAL_PARAM_T *pOut, /* output */
  569. V76LogicalChannelParameters *pIn) /* input */
  570. {
  571. /* See setup_VGMUX_mux() for inverse function */
  572. memset(pOut, 0, sizeof(*pOut));
  573. pOut->crcLength = pIn->hdlcParameters.crcLength.choice;
  574. pOut->n401 = pIn->hdlcParameters.n401;
  575. pOut->loopbackTestProcedure = pIn->hdlcParameters.loopbackTestProcedure;
  576. pOut->suspendResume = pIn->suspendResume.choice;
  577. pOut->uIH = pIn->uIH;
  578. pOut->mode = pIn->mode.choice;
  579. switch (pIn->mode.choice)
  580. {
  581. case eRM_chosen:
  582. pOut->windowSize = pIn->mode.u.eRM.windowSize;
  583. pOut->recovery = pIn->mode.u.eRM.recovery.choice;
  584. break;
  585. } // switch
  586. pOut->audioHeaderPresent = pIn->v75Parameters.audioHeaderPresent;
  587. return H245_ERROR_OK;
  588. } // load_VGMUX_param()
  589. static HRESULT
  590. load_H2250_param(H245_H2250_LOGICAL_PARAM_T * pOut, /* output */
  591. H2250LogicalChannelParameters *pIn) /* input */
  592. {
  593. HRESULT lError = H245_ERROR_OK;
  594. /* See setup_H2250_mux() for inverse function */
  595. memset(pOut, 0, sizeof(*pOut));
  596. if (pIn->bit_mask & H2250LCPs_nnStndrd_present)
  597. {
  598. pOut->nonStandardList = pIn->H2250LCPs_nnStndrd;
  599. }
  600. pOut->sessionID = (unsigned char) pIn->sessionID;
  601. if (pIn->bit_mask & H2250LCPs_assctdSssnID_present)
  602. {
  603. pOut->associatedSessionID = (unsigned char)pIn->H2250LCPs_assctdSssnID;
  604. pOut->associatedSessionIDPresent = TRUE;
  605. }
  606. if (pIn->bit_mask & H2250LCPs_mdChnnl_present)
  607. {
  608. if (lError == H245_ERROR_OK)
  609. {
  610. lError = LoadTransportAddress(&pOut->mediaChannel,
  611. &pIn->H2250LCPs_mdChnnl);
  612. if (lError == H245_ERROR_OK)
  613. {
  614. pOut->mediaChannelPresent = TRUE;
  615. }
  616. }
  617. }
  618. if (pIn->bit_mask & H2250LCPs_mdGrntdDlvry_present)
  619. {
  620. pOut->mediaGuaranteed = pIn->H2250LCPs_mdGrntdDlvry;
  621. pOut->mediaGuaranteedPresent = TRUE;
  622. }
  623. if (pIn->bit_mask & H2250LCPs_mdCntrlChnnl_present)
  624. {
  625. if (lError == H245_ERROR_OK)
  626. {
  627. lError = LoadTransportAddress(&pOut->mediaControlChannel,
  628. &pIn->H2250LCPs_mdCntrlChnnl);
  629. if (lError == H245_ERROR_OK)
  630. {
  631. pOut->mediaControlChannelPresent = TRUE;
  632. }
  633. }
  634. }
  635. if (pIn->bit_mask & H2250LCPs_mCGDy_present)
  636. {
  637. pOut->mediaControlGuaranteed = pIn->H2250LCPs_mCGDy;
  638. pOut->mediaControlGuaranteedPresent = TRUE;
  639. }
  640. if (pIn->bit_mask & silenceSuppression_present)
  641. {
  642. pOut->silenceSuppression = pIn->silenceSuppression;
  643. pOut->silenceSuppressionPresent = TRUE;
  644. }
  645. if (pIn->bit_mask & H2250LogicalChannelParameters_destination_present)
  646. {
  647. pOut->destination = pIn->destination;
  648. pOut->destinationPresent = TRUE;
  649. }
  650. if (pIn->bit_mask & H2250LCPs_dRTPPTp_present)
  651. {
  652. pOut->dynamicRTPPayloadType = (unsigned char)pIn->H2250LCPs_dRTPPTp;
  653. pOut->dynamicRTPPayloadTypePresent = TRUE;
  654. }
  655. if (pIn->bit_mask & mediaPacketization_present)
  656. {
  657. switch (pIn->mediaPacketization.choice)
  658. {
  659. case h261aVideoPacketization_chosen:
  660. pOut->h261aVideoPacketization = TRUE;
  661. break;
  662. default:
  663. return H245_ERROR_INVALID_DATA_FORMAT;
  664. } // switch
  665. }
  666. return lError;
  667. } // load_H2250_param()
  668. static HRESULT
  669. load_H2250ACK_param(H245_H2250ACK_LOGICAL_PARAM_T * pOut,
  670. H2250LgclChnnlAckPrmtrs * pIn)
  671. {
  672. HRESULT lError = H245_ERROR_OK;
  673. /* See setup_H2250ACK_mux() for inverse function */
  674. memset(pOut, 0, sizeof(*pOut));
  675. if (pIn->bit_mask & H2250LCAPs_nnStndrd_present)
  676. {
  677. pOut->nonStandardList = pIn->H2250LCAPs_nnStndrd;
  678. }
  679. if (pIn->bit_mask & sessionID_present)
  680. {
  681. pOut->sessionID = (unsigned char) pIn->sessionID;
  682. pOut->sessionIDPresent = TRUE;
  683. }
  684. if (pIn->bit_mask & H2250LCAPs_mdChnnl_present)
  685. {
  686. if (lError == H245_ERROR_OK)
  687. {
  688. lError = LoadTransportAddress(&pOut->mediaChannel,
  689. &pIn->H2250LCAPs_mdChnnl);
  690. if (lError == H245_ERROR_OK)
  691. {
  692. pOut->mediaChannelPresent = TRUE;
  693. }
  694. }
  695. }
  696. if (pIn->bit_mask & H2250LCAPs_mdCntrlChnnl_present)
  697. {
  698. if (lError == H245_ERROR_OK)
  699. {
  700. lError = LoadTransportAddress(&pOut->mediaControlChannel,
  701. &pIn->H2250LCAPs_mdCntrlChnnl);
  702. if (lError == H245_ERROR_OK)
  703. {
  704. pOut->mediaControlChannelPresent = TRUE;
  705. }
  706. }
  707. }
  708. if (pIn->bit_mask & H2250LCAPs_dRTPPTp_present)
  709. {
  710. pOut->dynamicRTPPayloadType = (unsigned char)pIn->H2250LCAPs_dRTPPTp;
  711. pOut->dynamicRTPPayloadTypePresent = TRUE;
  712. }
  713. return lError;
  714. } // load_H2250ACK_param()
  715. /*****************************************************************************
  716. *
  717. * TYPE: Local
  718. *
  719. * PROCEDURE: build_element_list_from_mux -
  720. *
  721. * DESCRIPTION
  722. * recursively build H245_MUX_ENTRY_ELEMENT_T list from
  723. * ASN1 mux table descriptor entrys.
  724. *
  725. * RETURN:
  726. *
  727. *****************************************************************************/
  728. static H245_MUX_ENTRY_ELEMENT_T *
  729. build_element_list_from_mux (MultiplexElement *p_ASN_mux_el,
  730. H245_ACC_REJ_T *p_acc_rej)
  731. {
  732. DWORD ii;
  733. H245_MUX_ENTRY_ELEMENT_T *p_mux_el;
  734. H245_MUX_ENTRY_ELEMENT_T *p_mux_el_tmp = NULL;
  735. H245_MUX_ENTRY_ELEMENT_T *p_mux_el_lst = NULL;
  736. if (!(p_mux_el = (H245_MUX_ENTRY_ELEMENT_T *)MemAlloc(sizeof(H245_MUX_ENTRY_ELEMENT_T))))
  737. {
  738. /* too complicated.. ran out of memory */
  739. H245TRACE(0,1,"build_element_list_from_mux : H245_ERROR_NOMEM");
  740. *p_acc_rej = H245_REJ_MUX_COMPLICATED;
  741. return NULL;
  742. }
  743. /* zero it out */
  744. memset (p_mux_el, 0, sizeof(H245_MUX_ENTRY_ELEMENT_T));
  745. switch (p_ASN_mux_el->type.choice)
  746. {
  747. case typ_logicalChannelNumber_chosen:
  748. /* assign as a logical channel */
  749. p_mux_el->Kind = H245_MUX_LOGICAL_CHANNEL;
  750. p_mux_el->u.Channel = p_ASN_mux_el->type.u.typ_logicalChannelNumber;
  751. break;
  752. case subElementList_chosen:
  753. {
  754. /* if the sub element list doesn't exist .. no go */
  755. /* if the sub element list has less than 2 entries.. no go. */
  756. if ((!p_ASN_mux_el->type.u.subElementList) ||
  757. (p_ASN_mux_el->type.u.subElementList->count < 2))
  758. {
  759. /* invalid Element list.. */
  760. H245TRACE(0,1,"build_element_list_from_mux : << ERROR >> Element Count < 2");
  761. *p_acc_rej = H245_REJ;
  762. free_mux_el_list (p_mux_el);
  763. return NULL;
  764. }
  765. /* assign as entry element */
  766. p_mux_el->Kind = H245_MUX_ENTRY_ELEMENT;
  767. /* ok.. for every sub element in the list */
  768. for (ii=0;ii<p_ASN_mux_el->type.u.subElementList->count;ii++)
  769. {
  770. if (!(p_mux_el_tmp = build_element_list_from_mux (&p_ASN_mux_el->type.u.subElementList->value[ii], p_acc_rej)))
  771. {
  772. /* *p_acc_rej is set from below */
  773. free_mux_el_list (p_mux_el);
  774. return NULL;
  775. }
  776. /* if first on the down sub element list.. assign to sub */
  777. /* element portion of mux_el */
  778. if (!p_mux_el_lst)
  779. p_mux_el->u.pMuxTblEntryElem = p_mux_el_tmp;
  780. /* otherwise.. just a list.. add it on.. */
  781. else
  782. p_mux_el_lst->pNext = p_mux_el_tmp;
  783. p_mux_el_lst = p_mux_el_tmp;
  784. }
  785. }
  786. break;
  787. default:
  788. /* Un supported structure */
  789. H245TRACE(0,1,"build_element_list_from_mux : INVALID MUX TABLE ENTRY PDU 'type.choice' unknown");
  790. *p_acc_rej = H245_REJ;
  791. free_mux_el_list (p_mux_el);
  792. return NULL;
  793. }
  794. switch (p_ASN_mux_el->repeatCount.choice)
  795. {
  796. case repeatCount_finite_chosen:
  797. p_mux_el->RepeatCount = p_ASN_mux_el->repeatCount.u.repeatCount_finite;
  798. break;
  799. case untilClosingFlag_chosen:
  800. p_mux_el->RepeatCount = 0;
  801. break;
  802. default:
  803. /* Un supported structure */
  804. H245TRACE(0,1,"build_element_list_from_mux : INVALID MUX TABLE ENTRY PDU 'repeatCount.choice' unknown");
  805. *p_acc_rej = H245_REJ;
  806. free_mux_el_list (p_mux_el);
  807. return NULL;
  808. break;
  809. }
  810. return p_mux_el;
  811. }
  812. /*****************************************************************************
  813. *
  814. * TYPE: Local
  815. *
  816. * PROCEDURE: process_mux_table_ind
  817. *
  818. * DESCRIPTION
  819. *
  820. *
  821. * RETURN:
  822. *
  823. *****************************************************************************/
  824. static H245_MUX_TABLE_T *
  825. process_mux_table_ind (MltmdSystmCntrlMssg *p_pdu_ind,
  826. unsigned short *p_seq,
  827. H245_ACC_REJ_MUX_T rej_mux,
  828. DWORD *p_rej_cnt,
  829. DWORD *p_acc_cnt)
  830. {
  831. UINT ii; /* generic counter */
  832. MultiplexEntrySend *p_ASN_mux; /* ans1 mux entry */
  833. MultiplexEntryDescriptorLink p_ASN_med_desc_lnk; /* asn1 mux entry descriptor */
  834. int mux_entry; /* current mux entry descc */
  835. H245_MUX_TABLE_T *p_mux_table_list = NULL;
  836. ASSERT(p_pdu_ind->choice == MltmdSystmCntrlMssg_rqst_chosen);
  837. ASSERT(p_pdu_ind->u.MltmdSystmCntrlMssg_rqst.choice == multiplexEntrySend_chosen);
  838. /* initialize rej_mux */
  839. for (ii=0;ii<15;ii++)
  840. {
  841. rej_mux[ii].AccRej = H245_ACC;
  842. rej_mux[ii].MuxEntryId = 0;
  843. }
  844. *p_rej_cnt = 0;
  845. *p_acc_cnt = 0;
  846. p_ASN_mux = &(p_pdu_ind->u.MltmdSystmCntrlMssg_rqst.u.multiplexEntrySend);
  847. /* get sequence number */
  848. *p_seq = p_ASN_mux->sequenceNumber;
  849. /* this should never happen.. */
  850. if (!(p_ASN_mux->multiplexEntryDescriptors))
  851. return NULL;
  852. /* for each descriptor.. ie mux table entry */
  853. for (p_ASN_med_desc_lnk = p_ASN_mux->multiplexEntryDescriptors, mux_entry=0;
  854. p_ASN_med_desc_lnk;
  855. p_ASN_med_desc_lnk = p_ASN_med_desc_lnk->next, mux_entry++)
  856. {
  857. /* remove descriptor from table */
  858. H245_MUX_TABLE_T *p_mux_table;
  859. H245_MUX_TABLE_T *p_mux_table_lst = NULL;
  860. if (!(p_mux_table = (H245_MUX_TABLE_T *)MemAlloc(sizeof(H245_MUX_TABLE_T))))
  861. {
  862. /* houston.. we have a problem !!!!!!!! */
  863. /* rejet this one.. */
  864. /* and move on.. */
  865. rej_mux[mux_entry].MuxEntryId = p_ASN_med_desc_lnk->value.multiplexTableEntryNumber;
  866. rej_mux[mux_entry].AccRej = H245_REJ;
  867. (*p_rej_cnt)++;
  868. continue;
  869. }
  870. /* zero it out */
  871. memset (p_mux_table, 0, sizeof(H245_MUX_TABLE_T));
  872. /* assign mux table entry */
  873. rej_mux[mux_entry].MuxEntryId = (DWORD)
  874. p_mux_table->MuxEntryId =
  875. p_ASN_med_desc_lnk->value.multiplexTableEntryNumber;
  876. /* if element is not present */
  877. if (p_ASN_med_desc_lnk->value.bit_mask != elementList_present)
  878. {
  879. p_mux_table->pMuxTblEntryElem = NULL;
  880. rej_mux[mux_entry].AccRej = H245_ACC;
  881. (*p_acc_cnt)++;
  882. }
  883. /* if element list present */
  884. else
  885. {
  886. H245_MUX_ENTRY_ELEMENT_T *p_mux_el_lst = NULL;
  887. H245_MUX_ENTRY_ELEMENT_T *p_mux_el_tmp = NULL;
  888. /* start if off.. w/ ok */
  889. rej_mux[mux_entry].AccRej = H245_ACC;
  890. /* for each element in the element list.. */
  891. /* build the subelements.. if error .. free */
  892. /* what youve done so far.. and break out */
  893. for (ii=0;
  894. ii < p_ASN_med_desc_lnk->value.elementList.count;
  895. ii++)
  896. {
  897. /* if any of the elements fail.. flag the entry w/ reject reason */
  898. /* (this is done inside the build_element_list..) */
  899. /* and break out.. continue on with the next descriptor */
  900. if (!(p_mux_el_tmp = build_element_list_from_mux (&(p_ASN_med_desc_lnk->value.elementList.value[ii]),&(rej_mux[mux_entry].AccRej))))
  901. {
  902. /* free the list.. */
  903. free_mux_el_list (p_mux_table->pMuxTblEntryElem);
  904. break;
  905. }
  906. /* ***************************** */
  907. /* LINK IN THE MUX ENTRY ELEMENT */
  908. /* ***************************** */
  909. /* if first time through */
  910. if (!p_mux_el_lst)
  911. p_mux_table->pMuxTblEntryElem = p_mux_el_tmp;
  912. /* otherwize .. just tag on the end */
  913. else
  914. p_mux_el_lst->pNext = p_mux_el_tmp;
  915. p_mux_el_lst = p_mux_el_tmp;
  916. } /* for each element in descriptor list */
  917. } /* if element list present */
  918. /* if you've accepted the mux table entry descriptor */
  919. if (rej_mux[mux_entry].AccRej == H245_ACC)
  920. {
  921. /* indicate an accept */
  922. (*p_acc_cnt)++;
  923. /* ******************************** */
  924. /* LINK IN THE MUX TABLE DESCRIPTOR */
  925. /* ******************************** */
  926. /* first table entry on the list.. (first time through) */
  927. if (!p_mux_table_list)
  928. p_mux_table_list = p_mux_table;
  929. else
  930. p_mux_table_lst->pNext = p_mux_table;
  931. p_mux_table_lst = p_mux_table;
  932. }
  933. else
  934. {
  935. /* indicate a reject */
  936. (*p_rej_cnt)++;
  937. /* otherwise.. free it and move on to something better */
  938. MemFree(p_mux_table);
  939. }
  940. } /* for each desriptor in the list */
  941. return p_mux_table_list;
  942. } /* procedure */
  943. /*****************************************************************************
  944. *
  945. * TYPE: Local
  946. *
  947. * PROCEDURE: process_term_cap_set_ind__cap_table
  948. *
  949. * DESCRIPTION allocates a new cap link and copies the capabiliites.
  950. * links into the tiven capabilityTableLink, and if
  951. * Parameters are NONSTANDARD does some gymnastics to copy
  952. * data so it can be used..
  953. *
  954. * NOTE: Copied data must be freed when capability is deleted.
  955. * see where the capability is deleted for exceptions
  956. * for "NONSTD" parameter sets .. (this is not pretty)
  957. *
  958. * RETURN:
  959. *
  960. *****************************************************************************/
  961. static HRESULT
  962. process_term_cap_set_ind__cap_table ( struct InstanceStruct *pInstance,
  963. struct TerminalCapabilitySet *pTermCapSet,
  964. CapabilityTableLink pCapLink,
  965. MltmdSystmCntrlMssg *p_pdu_rsp)
  966. {
  967. H245_TOTCAP_T totcap;
  968. CapabilityTableLink pNewLink;
  969. HRESULT lError;
  970. while (pCapLink)
  971. {
  972. if (build_totcap_from_captbl (&totcap,
  973. pCapLink,
  974. H245_REMOTE) == H245_ERROR_OK)
  975. {
  976. /* ok.. assume the CapId is set.. find it in the remote table */
  977. /* if it exists, delete it so we can add new one in it's place */
  978. pNewLink = find_capid_by_entrynumber( pTermCapSet, totcap.CapId);
  979. if (pNewLink)
  980. {
  981. del_cap_link ( pTermCapSet, pNewLink );
  982. }
  983. /* ok.. if you've deleted the cap.. now see if there is a new one to take it's place */
  984. if (pCapLink->value.bit_mask & capability_present)
  985. {
  986. /* load and link into remote table entry */
  987. pNewLink = alloc_link_cap_entry (pTermCapSet);
  988. if (!pNewLink)
  989. {
  990. return H245_ERROR_NORESOURCE;
  991. }
  992. /* copy the cap over to the remote entry */
  993. pNewLink->value = pCapLink->value;
  994. // If it's nonstandard, the above didn't work, so fix it up...
  995. lError = H245_ERROR_OK;
  996. switch (pCapLink->value.capability.choice)
  997. {
  998. case Capability_nonStandard_chosen:
  999. lError = CopyNonStandardParameter(&pNewLink->value.capability.u.Capability_nonStandard,
  1000. &pCapLink->value.capability.u.Capability_nonStandard);
  1001. break;
  1002. case receiveVideoCapability_chosen:
  1003. case transmitVideoCapability_chosen:
  1004. case rcvAndTrnsmtVdCpblty_chosen:
  1005. if (pCapLink->value.capability.u.receiveVideoCapability.choice == VdCpblty_nonStandard_chosen)
  1006. {
  1007. lError = CopyNonStandardParameter(&pNewLink->value.capability.u.receiveVideoCapability.u.VdCpblty_nonStandard,
  1008. &pCapLink->value.capability.u.receiveVideoCapability.u.VdCpblty_nonStandard);
  1009. }
  1010. break;
  1011. case receiveAudioCapability_chosen:
  1012. case transmitAudioCapability_chosen:
  1013. case rcvAndTrnsmtAdCpblty_chosen:
  1014. if (pCapLink->value.capability.u.receiveAudioCapability.choice == AdCpblty_nonStandard_chosen)
  1015. {
  1016. lError = CopyNonStandardParameter(&pNewLink->value.capability.u.receiveAudioCapability.u.AdCpblty_nonStandard,
  1017. &pCapLink->value.capability.u.receiveAudioCapability.u.AdCpblty_nonStandard);
  1018. }
  1019. break;
  1020. case rcvDtApplctnCpblty_chosen:
  1021. case trnsmtDtApplctnCpblty_chosen:
  1022. case rATDACy_chosen :
  1023. if (pCapLink->value.capability.u.rcvDtApplctnCpblty.application.choice == DACy_applctn_nnStndrd_chosen)
  1024. {
  1025. lError = CopyNonStandardParameter(&pNewLink->value.capability.u.rcvDtApplctnCpblty.application.u.DACy_applctn_nnStndrd,
  1026. &pCapLink->value.capability.u.rcvDtApplctnCpblty.application.u.DACy_applctn_nnStndrd);
  1027. }
  1028. break;
  1029. } // switch
  1030. if (lError != H245_ERROR_OK)
  1031. return lError;
  1032. } /* if capability_present */
  1033. } /* if build_totcap_from_captbl succeeded */
  1034. pCapLink = pCapLink->next;
  1035. } /* for all entries in link */
  1036. return H245_ERROR_OK;
  1037. }
  1038. /*****************************************************************************
  1039. *
  1040. * TYPE: Local
  1041. *
  1042. * PROCEDURE: process_term_cap_set_ind__cap_desc
  1043. *
  1044. * DESCRIPTION
  1045. *
  1046. *
  1047. * RETURN:
  1048. *
  1049. *****************************************************************************/
  1050. static HRESULT
  1051. process_term_cap_set_ind__cap_desc (struct InstanceStruct *pInstance,
  1052. struct TerminalCapabilitySet *pTermCapSet,
  1053. CapabilityDescriptor *pReqCapDesc,
  1054. MltmdSystmCntrlMssg *p_pdu_rsp)
  1055. {
  1056. unsigned int uCapDescNumber;
  1057. CapabilityDescriptor *pCapDesc;
  1058. unsigned int uCapDesc;
  1059. SmltnsCpbltsLink pSimCap;
  1060. SmltnsCpbltsLink pReqSimCap;
  1061. CapabilityDescriptor TempCapDesc;
  1062. unsigned int uSimCount;
  1063. unsigned int uReqAltCount;
  1064. unsigned int uReqAltCap;
  1065. unsigned int uAltCap;
  1066. HRESULT lError = H245_ERROR_OK;
  1067. uCapDescNumber = pReqCapDesc->capabilityDescriptorNumber & 255;
  1068. H245TRACE(pInstance->dwInst,20,"API:process_term_cap_set_ind - Remote Capability Descriptor #%d", uCapDescNumber);
  1069. // Find corresponding capability descriptor
  1070. pCapDesc = NULL;
  1071. for (uCapDesc = 0; uCapDesc < pTermCapSet->capabilityDescriptors.count; ++uCapDesc)
  1072. {
  1073. if (pTermCapSet->capabilityDescriptors.value[uCapDesc].capabilityDescriptorNumber == uCapDescNumber)
  1074. {
  1075. // Deallocate old simultaneous capabilities
  1076. pCapDesc = &pTermCapSet->capabilityDescriptors.value[uCapDesc];
  1077. if (pCapDesc->smltnsCpblts)
  1078. dealloc_simultaneous_cap(pCapDesc);
  1079. break;
  1080. } // if
  1081. } // for
  1082. if (pCapDesc == NULL)
  1083. {
  1084. // Allocate a new terminal capability descriptor
  1085. ASSERT(pTermCapSet->capabilityDescriptors.count < 256);
  1086. pCapDesc = &pTermCapSet->capabilityDescriptors.value[pTermCapSet->capabilityDescriptors.count++];
  1087. }
  1088. ASSERT(pCapDesc->smltnsCpblts == NULL);
  1089. if (!(pReqCapDesc->bit_mask & smltnsCpblts_present))
  1090. {
  1091. // Delete the terminal capability descriptor
  1092. pTermCapSet->capabilityDescriptors.count--;
  1093. *pCapDesc = pTermCapSet->capabilityDescriptors.value[pTermCapSet->capabilityDescriptors.count];
  1094. return H245_ERROR_OK;
  1095. }
  1096. // Make a copy of the (volatile) new capability descriptor
  1097. pCapDesc->bit_mask = 0;
  1098. pCapDesc->capabilityDescriptorNumber = (CapabilityDescriptorNumber)uCapDescNumber;
  1099. pCapDesc->smltnsCpblts = NULL;
  1100. // We copy the linked list to a temporary so that it
  1101. // gets reversed twice and ends up in same order
  1102. TempCapDesc.smltnsCpblts = NULL;
  1103. uSimCount = 0;
  1104. pReqSimCap = pReqCapDesc->smltnsCpblts;
  1105. while (pReqSimCap)
  1106. {
  1107. // Allocate a new simultaneous capability list element
  1108. pSimCap = MemAlloc(sizeof(*pSimCap));
  1109. if (pSimCap == NULL)
  1110. {
  1111. H245TRACE(pInstance->dwInst, 1,
  1112. "API:process_term_cap_set_ind: malloc failed");
  1113. lError = H245_ERROR_NOMEM;
  1114. break;
  1115. }
  1116. // Verify that each alternative capability in the request
  1117. // simultaneous capability is valid
  1118. // if so, copy it
  1119. uAltCap = 0;
  1120. uReqAltCount = pReqSimCap->value.count;
  1121. for (uReqAltCap = 0; uReqAltCap < uReqAltCount; ++uReqAltCap)
  1122. {
  1123. // Is the Capability in the remote Capability Table?
  1124. if (find_capid_by_entrynumber (pTermCapSet, pReqSimCap->value.value[uReqAltCap]) == NULL)
  1125. {
  1126. // can't find the Capability
  1127. H245TRACE(pInstance->dwInst,1,"API:process_term_cap_set_ind - Remote Capability Table Entry #%d not found",
  1128. pReqSimCap->value.value[uReqAltCap]);
  1129. lError = H245_ERROR_UNKNOWN;
  1130. }
  1131. else if (uAltCap >= H245_MAX_ALTCAPS)
  1132. {
  1133. // Exceeded arbitrary limit
  1134. H245TRACE(pInstance->dwInst,1,
  1135. "API:process_term_cap_set_ind - Too many alternative capabilities (%d)",
  1136. uAltCap);
  1137. lError = H245_ERROR_NORESOURCE;
  1138. break;
  1139. }
  1140. else
  1141. {
  1142. // Copy the capability number
  1143. pSimCap->value.value[uAltCap++] = pReqSimCap->value.value[uReqAltCap];
  1144. }
  1145. } /* for alternative capbilities */
  1146. if (uAltCap)
  1147. {
  1148. // Verify that we have not exceeded arbitrary limit
  1149. if (++uSimCount > H245_MAX_SIMCAPS)
  1150. {
  1151. // Exceeded arbitrary limit
  1152. H245TRACE(pInstance->dwInst, 1,
  1153. "API:process_term_cap_set_ind - Too many simultaneous capabilities (%d)",
  1154. uSimCount);
  1155. MemFree(pSimCap);
  1156. lError = H245_ERROR_NORESOURCE;
  1157. }
  1158. else
  1159. {
  1160. // Add new simultaneous capability to the temporary list
  1161. pSimCap->value.count = (unsigned short)uAltCap;
  1162. pSimCap->next = TempCapDesc.smltnsCpblts;
  1163. TempCapDesc.smltnsCpblts = pSimCap;
  1164. }
  1165. }
  1166. else
  1167. {
  1168. H245TRACE(pInstance->dwInst, 1,
  1169. "API:process_term_cap_set_ind - No valid alternative capabilities found");
  1170. MemFree(pSimCap);
  1171. lError = H245_ERROR_UNKNOWN;
  1172. }
  1173. pReqSimCap = pReqSimCap->next;
  1174. } // while
  1175. while (TempCapDesc.smltnsCpblts)
  1176. {
  1177. // Move elements from temporary to final linked list
  1178. pSimCap = TempCapDesc.smltnsCpblts;
  1179. TempCapDesc.smltnsCpblts = pSimCap->next;
  1180. pSimCap->next = pCapDesc->smltnsCpblts;
  1181. pCapDesc->smltnsCpblts = pSimCap;
  1182. }
  1183. // Error if no simultaneous capabilities found
  1184. if (pCapDesc->smltnsCpblts)
  1185. {
  1186. pCapDesc->bit_mask |= smltnsCpblts_present;
  1187. }
  1188. else
  1189. {
  1190. H245TRACE(pInstance->dwInst, 1,
  1191. "API:process_term_cap_set_ind - No simultaneous capabilities found");
  1192. lError = H245_ERROR_UNKNOWN;
  1193. }
  1194. return lError;
  1195. }
  1196. /*****************************************************************************
  1197. *
  1198. * TYPE: Local
  1199. *
  1200. * PROCEDURE: process_term_cap_set_ind__mux_cap
  1201. *
  1202. * DESCRIPTION
  1203. *
  1204. *
  1205. * RETURN:
  1206. *
  1207. * NOTES:
  1208. * We do a copy to set up a capability structure, then do another copy via
  1209. * H245CopyCap() to create a copy of the capability because the structure
  1210. * given to us by the ASN.1 decoded may contain pointers to data which will
  1211. * be deallocated upon return.
  1212. *
  1213. *****************************************************************************/
  1214. static HRESULT
  1215. process_term_cap_set_ind__mux_cap (struct InstanceStruct *pInstance,
  1216. struct TerminalCapabilitySet *pTermCapSet,
  1217. MultiplexCapability * pReqMuxCap,
  1218. MltmdSystmCntrlMssg *p_pdu_rsp)
  1219. {
  1220. H245_TOTCAP_T TotCap;
  1221. // Initialize temporary capability structure
  1222. memset(&TotCap, 0, sizeof(TotCap));
  1223. TotCap.Dir = H245_CAPDIR_RMTRXTX;
  1224. TotCap.DataType = H245_DATA_MUX;
  1225. // Get rid of old remote multiplex capability, if any
  1226. if (pTermCapSet->bit_mask & multiplexCapability_present)
  1227. {
  1228. del_mux_cap(pTermCapSet);
  1229. }
  1230. switch (pReqMuxCap->choice)
  1231. {
  1232. case MltplxCpblty_nonStandard_chosen:
  1233. // Save a copy of the multiplex capability
  1234. TotCap.Cap.H245Mux_NONSTD = pReqMuxCap->u.MltplxCpblty_nonStandard;
  1235. TotCap.ClientType = H245_CLIENT_MUX_NONSTD;
  1236. H245TRACE(pInstance->dwInst,1,"API:process_term_cap_set_ind__mux_cap - Nonstandard Mux not yet supported");
  1237. break;
  1238. case h222Capability_chosen:
  1239. // Save a copy of the multiplex capability
  1240. TotCap.Cap.H245Mux_H222 = pReqMuxCap->u.h222Capability;
  1241. TotCap.ClientType = H245_CLIENT_MUX_H222;
  1242. break;
  1243. case h223Capability_chosen:
  1244. // Save a copy of the multiplex capability
  1245. TotCap.Cap.H245Mux_H223 = pReqMuxCap->u.h223Capability;
  1246. TotCap.ClientType = H245_CLIENT_MUX_H223;
  1247. break;
  1248. case v76Capability_chosen:
  1249. // Save a copy of the multiplex capability
  1250. TotCap.Cap.H245Mux_VGMUX = pReqMuxCap->u.v76Capability;
  1251. TotCap.ClientType = H245_CLIENT_MUX_VGMUX;
  1252. break;
  1253. case h2250Capability_chosen:
  1254. // Save a copy of the multiplex capability
  1255. TotCap.Cap.H245Mux_H2250 = pReqMuxCap->u.h2250Capability;
  1256. TotCap.ClientType = H245_CLIENT_MUX_H2250;
  1257. break;
  1258. default:
  1259. H245TRACE(pInstance->dwInst,1,"API:process_term_cap_set_ind__mux_cap - invalid mux cap type %d",
  1260. &pReqMuxCap->choice);
  1261. return H245_ERROR_NOSUP;
  1262. }
  1263. return set_mux_cap(pInstance, pTermCapSet, &TotCap);
  1264. }
  1265. /*****************************************************************************
  1266. *
  1267. * TYPE: Local
  1268. *
  1269. * PROCEDURE: process_term_cap_set_ind
  1270. *
  1271. * DESCRIPTION
  1272. *
  1273. **************************************************************
  1274. *
  1275. * (TBD) .. this module will ack all terminal capbilities
  1276. * need to build reject.. (maybe later??)
  1277. *
  1278. * THIS IS A BIG TBD
  1279. *
  1280. **************************************************************
  1281. *
  1282. * RETURN:
  1283. *
  1284. *****************************************************************************/
  1285. static HRESULT
  1286. process_term_cap_set_ind (struct InstanceStruct *pInstance,
  1287. MltmdSystmCntrlMssg *p_pdu_req,
  1288. MltmdSystmCntrlMssg *p_pdu_rsp)
  1289. {
  1290. HRESULT lError = H245_ERROR_OK;
  1291. TerminalCapabilitySet *pTermCapSet;
  1292. ASSERT (p_pdu_req->choice == MltmdSystmCntrlMssg_rqst_chosen);
  1293. ASSERT (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.choice == terminalCapabilitySet_chosen);
  1294. H245TRACE(pInstance->dwInst,10,"API:process_term_cap_set_ind <-");
  1295. /* build ack response */
  1296. p_pdu_rsp->choice = MSCMg_rspns_chosen;
  1297. p_pdu_rsp->u.MSCMg_rspns.choice = terminalCapabilitySetAck_chosen;
  1298. p_pdu_rsp->u.MSCMg_rspns.u.terminalCapabilitySetAck.sequenceNumber =
  1299. p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.sequenceNumber;
  1300. pTermCapSet = &pInstance->API.PDU_RemoteTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
  1301. //***************************
  1302. // Deal with Capability Table
  1303. //***************************
  1304. if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.bit_mask & capabilityTable_present)
  1305. {
  1306. CapabilityTableLink pCapTable = p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable;
  1307. if (pCapTable->value.capability.choice == Capability_nonStandard_chosen &&
  1308. pCapTable->value.capability.u.Capability_nonStandard.nonStandardIdentifier.choice == h221NonStandard_chosen &&
  1309. pCapTable->value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.t35CountryCode == 0xB5 &&
  1310. pCapTable->value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.t35Extension == 0x42 &&
  1311. pCapTable->value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.manufacturerCode == 0x8080)
  1312. {
  1313. pInstance->bMasterSlaveKludge = TRUE;
  1314. pCapTable = pCapTable->next;
  1315. }
  1316. lError = process_term_cap_set_ind__cap_table(pInstance,
  1317. pTermCapSet,
  1318. pCapTable,
  1319. p_pdu_rsp);
  1320. if (lError != H245_ERROR_OK)
  1321. {
  1322. H245TRACE(pInstance->dwInst,1,"API:process_term_cap_set_ind - cap table error %s",map_api_error(lError));
  1323. /* (TBC) need to reject somehow */
  1324. }
  1325. } /* if Capability Table Present */
  1326. //**************************************
  1327. // Deal with Capability Descriptor Table
  1328. // i.e. simultaneous capabilities
  1329. // NOTE: these are not held in the remote terminal capbility set
  1330. //**************************************
  1331. if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.bit_mask & capabilityDescriptors_present)
  1332. {
  1333. int des_cnt;
  1334. int ii;
  1335. des_cnt = p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityDescriptors.count;
  1336. H245TRACE(pInstance->dwInst,20,"API:process_term_cap_set_ind - %d Simultaneous Capabilities",des_cnt);
  1337. for (ii = 0; ii < des_cnt; ++ii)
  1338. {
  1339. lError = process_term_cap_set_ind__cap_desc (pInstance,
  1340. pTermCapSet,
  1341. &p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.
  1342. terminalCapabilitySet.capabilityDescriptors.value[ii],
  1343. p_pdu_rsp);
  1344. if (lError != H245_ERROR_OK)
  1345. {
  1346. H245TRACE(pInstance->dwInst,1,"API:process_term_cap_set_ind - cap desc error %s",map_api_error(lError));
  1347. /* (TBC) need to reject somehow */
  1348. }
  1349. } /* for each descriptor */
  1350. } /* if capability descriptor present */
  1351. /**************************************/
  1352. /* Deal with Multiplex Capability set */
  1353. /**************************************/
  1354. /* NOTE: these are not held in the remote terminal capability set */
  1355. if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.bit_mask & multiplexCapability_present)
  1356. {
  1357. /* send up the indication to the client for each new entry */
  1358. lError = process_term_cap_set_ind__mux_cap(pInstance,
  1359. pTermCapSet,
  1360. &p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.
  1361. terminalCapabilitySet.multiplexCapability,
  1362. p_pdu_rsp);
  1363. if (lError != H245_ERROR_OK)
  1364. {
  1365. H245TRACE(pInstance->dwInst,1,"API:process_term_cap_set_ind - mux cap error %s",map_api_error(lError));
  1366. /* (TBC) need to reject somehow */
  1367. }
  1368. }
  1369. H245TRACE(pInstance->dwInst,10,"API:process_term_cap_set_ind -> OK");
  1370. return H245_ERROR_OK;
  1371. }
  1372. /*****************************************************************************
  1373. *
  1374. * TYPE: Local
  1375. *
  1376. * PROCEDURE: process_open_ind
  1377. *
  1378. * DESCRIPTION
  1379. *
  1380. * RETURN:
  1381. *
  1382. * ASSUME:
  1383. * Callback must happen inside this routine since the
  1384. * datastructures passed back to the application are allocated
  1385. * in this moudle.
  1386. *
  1387. * Application will <<<COPY>>> the needed data structures when
  1388. * callback occurs..
  1389. *
  1390. *****************************************************************************/
  1391. static HRESULT
  1392. process_open_ind (struct InstanceStruct *pInstance,
  1393. MltmdSystmCntrlMssg *p_pdu_req,
  1394. unsigned short *p_FwdChan, /* for return on error */
  1395. H245_ACC_REJ_T *p_AccRej, /* for return error */
  1396. H245_CONF_IND_T *p_conf_ind) /* out */
  1397. {
  1398. static H245_TOTCAP_T rx_totcap; /* for receive caps */
  1399. static H245_TOTCAP_T tx_totcap; /* for transmit caps */
  1400. static H245_MUX_T RxMux;
  1401. static H245_MUX_T TxMux;
  1402. unsigned short choice; /* tmp for type of cap to routine */
  1403. HRESULT lError;
  1404. Tracker_T *p_tracker;
  1405. H245TRACE(pInstance->dwInst,10,"API:process_open_ind <-");
  1406. *p_AccRej = H245_ACC;
  1407. /********************************/
  1408. /* check for forward parameters */
  1409. /********************************/
  1410. /* get forward Rx channel id */
  1411. p_conf_ind->u.Indication.u.IndOpen.RxChannel =
  1412. *p_FwdChan =
  1413. p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelNumber;
  1414. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - channel = %d",p_conf_ind->u.Indication.u.IndOpen.RxChannel);
  1415. /* get port number */
  1416. if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
  1417. u.openLogicalChannel.forwardLogicalChannelParameters.bit_mask & fLCPs_prtNmbr_present)
  1418. {
  1419. p_conf_ind->u.Indication.u.IndOpen.RxPort =
  1420. p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelParameters.fLCPs_prtNmbr;
  1421. }
  1422. else
  1423. p_conf_ind->u.Indication.u.IndOpen.RxPort = H245_INVALID_PORT_NUMBER;
  1424. /* ok.. forward data type selection */
  1425. switch (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelParameters.dataType.choice)
  1426. {
  1427. case DataType_nonStandard_chosen:
  1428. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx nonStandard");
  1429. /* (TBD) what do I do here ?? */
  1430. *p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
  1431. return H245_ERROR_NOSUP;
  1432. case nullData_chosen:
  1433. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx nullData");
  1434. /* (TBD) what do I do here ?? */
  1435. *p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
  1436. return H245_ERROR_NOSUP;
  1437. break;
  1438. case DataType_videoData_chosen:
  1439. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx videoData");
  1440. p_conf_ind->u.Indication.u.IndOpen.RxDataType = H245_DATA_VIDEO;
  1441. choice =
  1442. p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
  1443. u.openLogicalChannel.forwardLogicalChannelParameters.dataType.
  1444. u.DataType_videoData.choice;
  1445. break;
  1446. case DataType_audioData_chosen:
  1447. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx audioData");
  1448. p_conf_ind->u.Indication.u.IndOpen.RxDataType = H245_DATA_AUDIO;
  1449. choice =
  1450. p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
  1451. u.openLogicalChannel.forwardLogicalChannelParameters.dataType.
  1452. u.DataType_audioData.choice;
  1453. break;
  1454. case DataType_data_chosen:
  1455. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx dataData");
  1456. p_conf_ind->u.Indication.u.IndOpen.RxDataType = H245_DATA_DATA;
  1457. choice =
  1458. p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
  1459. u.openLogicalChannel.forwardLogicalChannelParameters.dataType.
  1460. u.DataType_data.application.choice;
  1461. break;
  1462. case encryptionData_chosen:
  1463. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx encryptionData");
  1464. /* (TBC) what do I do here ?? */
  1465. *p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
  1466. return H245_ERROR_NOSUP;
  1467. break;
  1468. default:
  1469. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Rx encryptionData");
  1470. /* (TBC) what do I do here ?? */
  1471. *p_AccRej = H245_REJ_TYPE_UNKNOWN;
  1472. return H245_ERROR_NOSUP;
  1473. break;
  1474. }
  1475. /* load the tot cap's capability and client from capability */
  1476. /* this will give us the client type and the Capability for the indication */
  1477. if ((lError = build_totcap_cap_n_client_from_capability ((struct Capability *)
  1478. &(p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
  1479. u.openLogicalChannel.forwardLogicalChannelParameters.dataType),
  1480. p_conf_ind->u.Indication.u.IndOpen.RxDataType,
  1481. choice,
  1482. &rx_totcap)) != H245_ERROR_OK)
  1483. {
  1484. *p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
  1485. return lError;
  1486. }
  1487. /* load it from the totcap you just built.. then toss it aside.. like an empty can of soda.. */
  1488. p_conf_ind->u.Indication.u.IndOpen.RxClientType = rx_totcap.ClientType;
  1489. p_conf_ind->u.Indication.u.IndOpen.pRxCap = &(rx_totcap.Cap);
  1490. /* H.223/H.222 Mux table parameters for forward channel */
  1491. p_conf_ind->u.Indication.u.IndOpen.pRxMux = &RxMux;
  1492. switch (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
  1493. u.openLogicalChannel.forwardLogicalChannelParameters.multiplexParameters.choice)
  1494. {
  1495. case fLCPs_mPs_h223LCPs_chosen:
  1496. /* H.223 Logical Parameters */
  1497. p_conf_ind->u.Indication.u.IndOpen.pRxMux->Kind = H245_H223;
  1498. lError = load_H223_param(&RxMux.u.H223,
  1499. &p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelParameters.multiplexParameters.u.fLCPs_mPs_h223LCPs);
  1500. if (lError != H245_ERROR_OK)
  1501. {
  1502. *p_AccRej = H245_REJ_AL_COMB;
  1503. return lError;
  1504. }
  1505. break;
  1506. case fLCPs_mPs_h222LCPs_chosen:
  1507. /* H.222 Logical Parameters */
  1508. p_conf_ind->u.Indication.u.IndOpen.pRxMux->Kind = H245_H222;
  1509. lError = load_H222_param(&RxMux.u.H222,
  1510. &p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelParameters.multiplexParameters.u.fLCPs_mPs_h222LCPs);
  1511. break;
  1512. case fLCPs_mPs_v76LCPs_chosen:
  1513. /* VGMUX Logical Parameters */
  1514. p_conf_ind->u.Indication.u.IndOpen.pRxMux->Kind = H245_VGMUX;
  1515. lError =load_VGMUX_param(&RxMux.u.VGMUX,
  1516. &p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelParameters.multiplexParameters.u.fLCPs_mPs_v76LCPs);
  1517. break;
  1518. case fLCPs_mPs_h2250LCPs_chosen:
  1519. /* H.225.0 Logical Parameters */
  1520. p_conf_ind->u.Indication.u.IndOpen.pRxMux->Kind = H245_H2250;
  1521. lError = load_H2250_param(&RxMux.u.H2250,
  1522. &p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.forwardLogicalChannelParameters.multiplexParameters.u.fLCPs_mPs_h2250LCPs);
  1523. break;
  1524. default:
  1525. lError = H245_ERROR_NOSUP;
  1526. } // switch
  1527. if (lError != H245_ERROR_OK)
  1528. {
  1529. *p_AccRej = H245_REJ;
  1530. return lError;
  1531. }
  1532. /********************************/
  1533. /* check for reverse parameters */
  1534. /********************************/
  1535. if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.bit_mask & OLCl_rLCPs_present)
  1536. {
  1537. switch (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.OLCl_rLCPs.dataType.choice)
  1538. {
  1539. case DataType_nonStandard_chosen:
  1540. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Tx nonStandard");
  1541. /* (TBC) what do I do here ?? */
  1542. *p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
  1543. return H245_ERROR_NOSUP;
  1544. case nullData_chosen:
  1545. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Tx nullData");
  1546. /* (TBC) what do I do here ?? */
  1547. *p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
  1548. return H245_ERROR_NOSUP;
  1549. break;
  1550. case DataType_videoData_chosen:
  1551. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Tx videoData");
  1552. p_conf_ind->u.Indication.u.IndOpen.TxDataType = H245_DATA_VIDEO;
  1553. choice =
  1554. p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.OLCl_rLCPs.dataType.u.DataType_videoData.choice;
  1555. break;
  1556. case DataType_audioData_chosen:
  1557. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Tx audioData");
  1558. p_conf_ind->u.Indication.u.IndOpen.TxDataType = H245_DATA_AUDIO;
  1559. choice =
  1560. p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.OLCl_rLCPs.dataType.u.DataType_audioData.choice;
  1561. break;
  1562. case DataType_data_chosen:
  1563. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Tx dataData");
  1564. p_conf_ind->u.Indication.u.IndOpen.TxDataType = H245_DATA_DATA;
  1565. choice =
  1566. p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.OLCl_rLCPs.dataType.u.DataType_data.application.choice;
  1567. break;
  1568. case encryptionData_chosen:
  1569. H245TRACE(pInstance->dwInst,20,"API:process_open_ind - Tx encryptionData");
  1570. /* (TBC) what do I do here ?? */
  1571. *p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
  1572. return H245_ERROR_NOSUP;
  1573. break;
  1574. default:
  1575. /* (TBC) what do I do here ?? */
  1576. *p_AccRej = H245_REJ_TYPE_UNKNOWN;
  1577. H245TRACE(pInstance->dwInst,1,"API:process_open_ind - unknown choice %d",
  1578. p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.OLCl_rLCPs.dataType.choice);
  1579. return H245_ERROR_NOSUP;
  1580. }
  1581. /* load the tot cap's capability and client from capability */
  1582. if ((lError = build_totcap_cap_n_client_from_capability ((struct Capability *)
  1583. &(p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
  1584. u.openLogicalChannel.OLCl_rLCPs.dataType),
  1585. p_conf_ind->u.Indication.u.IndOpen.TxDataType,
  1586. choice,
  1587. &tx_totcap)) != H245_ERROR_OK)
  1588. {
  1589. *p_AccRej = H245_REJ_TYPE_NOTSUPPORT;
  1590. return lError;
  1591. }
  1592. p_conf_ind->u.Indication.u.IndOpen.TxClientType = tx_totcap.ClientType;
  1593. p_conf_ind->u.Indication.u.IndOpen.pTxCap = &(tx_totcap.Cap);
  1594. /* if H223/H222 Mux table parameters for reverse channel availalbe */
  1595. if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
  1596. u.openLogicalChannel.OLCl_rLCPs.bit_mask & OLCl_rLCPs_mltplxPrmtrs_present)
  1597. {
  1598. switch (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
  1599. u.openLogicalChannel.OLCl_rLCPs.OLCl_rLCPs_mltplxPrmtrs.choice)
  1600. {
  1601. case rLCPs_mPs_h223LCPs_chosen:
  1602. p_conf_ind->u.Indication.u.IndOpen.pTxMux = &TxMux;
  1603. p_conf_ind->u.Indication.u.IndOpen.pTxMux->Kind = H245_H223;
  1604. lError = load_H223_param(&TxMux.u.H223,
  1605. &p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.
  1606. OLCl_rLCPs.OLCl_rLCPs_mltplxPrmtrs.u.rLCPs_mPs_h223LCPs);
  1607. if (lError != H245_ERROR_OK)
  1608. {
  1609. *p_AccRej = H245_REJ_AL_COMB;
  1610. return H245_ERROR_NOSUP;
  1611. }
  1612. break;
  1613. case rLCPs_mPs_v76LCPs_chosen:
  1614. p_conf_ind->u.Indication.u.IndOpen.pTxMux = &TxMux;
  1615. p_conf_ind->u.Indication.u.IndOpen.pTxMux->Kind = H245_VGMUX;
  1616. lError = load_VGMUX_param(&TxMux.u.VGMUX,
  1617. &p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.
  1618. OLCl_rLCPs.OLCl_rLCPs_mltplxPrmtrs.u.rLCPs_mPs_v76LCPs);
  1619. break;
  1620. case rLCPs_mPs_h2250LCPs_chosen:
  1621. p_conf_ind->u.Indication.u.IndOpen.pTxMux = &TxMux;
  1622. p_conf_ind->u.Indication.u.IndOpen.pTxMux->Kind = H245_H2250;
  1623. lError = load_H2250_param(&TxMux.u.H2250,
  1624. &p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.
  1625. OLCl_rLCPs.OLCl_rLCPs_mltplxPrmtrs.u.rLCPs_mPs_h2250LCPs);
  1626. break;
  1627. default:
  1628. lError = H245_ERROR_NOSUP;
  1629. }
  1630. if (lError != H245_ERROR_OK)
  1631. {
  1632. *p_AccRej = H245_REJ;
  1633. return lError;
  1634. }
  1635. } /* if H223/H222 mux table reverse parameters */
  1636. } /* if reverse parameters present */
  1637. if (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.bit_mask & OpnLgclChnnl_sprtStck_present)
  1638. {
  1639. p_conf_ind->u.Indication.u.IndOpen.pSeparateStack =
  1640. &p_pdu_req->u.MltmdSystmCntrlMssg_rqst.u.openLogicalChannel.OpnLgclChnnl_sprtStck;
  1641. }
  1642. /* conflict resolution .. just do it now.. */
  1643. /* only on opens.. of same data type .. */
  1644. #if 0
  1645. #ifndef LOOPBACK
  1646. /* if master */
  1647. if (pInstance->API.MasterSlave == APIMS_Master)
  1648. {
  1649. p_tracker = NULL;
  1650. while (p_tracker = find_tracker_by_type (dwInst, API_OPEN_CHANNEL_T, p_tracker))
  1651. {
  1652. /* if allocated locally .. and incoming */
  1653. /* data type == outstanding incoming */
  1654. /* there is a conflict */
  1655. if ((p_tracker->u.Channel.ChannelAlloc == API_CH_ALLOC_LCL) &&
  1656. (p_tracker->u.Channel.DataType == p_conf_ind->u.Indication.u.IndOpen.RxDataType))
  1657. {
  1658. *p_AccRej = H245_REJ;
  1659. return H245_ERROR_INVALID_OP;
  1660. } /* if conflict */
  1661. } /* while */
  1662. } /* if master */
  1663. #endif /* LOOPBACK */
  1664. #endif
  1665. /* setup a tracker for this guy. */
  1666. p_tracker = alloc_link_tracker (pInstance,
  1667. API_OPEN_CHANNEL_T,
  1668. 0,
  1669. API_ST_WAIT_LCLACK,
  1670. API_CH_ALLOC_RMT,
  1671. (p_pdu_req->u.MltmdSystmCntrlMssg_rqst.
  1672. u.openLogicalChannel.bit_mask & OLCl_rLCPs_present)?API_CH_TYPE_BI:API_CH_TYPE_UNI,
  1673. p_conf_ind->u.Indication.u.IndOpen.RxDataType,
  1674. H245_INVALID_CHANNEL,
  1675. p_conf_ind->u.Indication.u.IndOpen.RxChannel,
  1676. 0);
  1677. if (!(p_tracker))
  1678. {
  1679. H245TRACE(pInstance->dwInst,1,"API:process_open_ind -> %s",map_api_error(H245_ERROR_NOMEM));
  1680. *p_AccRej = H245_REJ;
  1681. return H245_ERROR_NOMEM;
  1682. }
  1683. H245TRACE(pInstance->dwInst,10,"API:process_open_ind -> OK");
  1684. return H245_ERROR_OK;
  1685. }
  1686. /*****************************************************************************
  1687. *
  1688. * TYPE: Local
  1689. *
  1690. * PROCEDURE: process_bi_open_rsp
  1691. *
  1692. * DESCRIPTION
  1693. *
  1694. * RETURN:
  1695. *
  1696. * ASSUME:
  1697. * Callback must happen inside this routine since the
  1698. * datastructures passed back to the application are allocated
  1699. * in this moudle.
  1700. *
  1701. * Application will <<<COPY>>> the needed data structures when
  1702. * callback occurs..
  1703. *
  1704. *****************************************************************************/
  1705. static HRESULT
  1706. process_bi_open_rsp (struct InstanceStruct * pInstance, /* in */
  1707. MltmdSystmCntrlMssg *p_pdu_rsp, /* in */
  1708. H245_MUX_T *p_RxMux, /* in */
  1709. DWORD *p_RxChannel, /* out */
  1710. H245_CONF_IND_T *p_conf_ind /* out */
  1711. )
  1712. {
  1713. H245TRACE(pInstance->dwInst,10,"API:process_bi_open_rsp <-");
  1714. p_conf_ind->u.Confirm.Error = H245_ERROR_OK;
  1715. // Get Reverse Logical Channel Number
  1716. *p_RxChannel =
  1717. p_conf_ind->u.Confirm.u.ConfOpenNeedRsp.RxChannel =
  1718. p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.reverseLogicalChannelNumber;
  1719. // Get Reverse Port Number
  1720. if (p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.bit_mask & rLCPs_prtNmbr_present)
  1721. {
  1722. p_conf_ind->u.Confirm.u.ConfOpenNeedRsp.RxPort =
  1723. p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.rLCPs_prtNmbr;
  1724. }
  1725. if (p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.bit_mask & OLCAk_rLCPs_mPs_present)
  1726. {
  1727. // Get Reverse Logical Channel ACK Parameters
  1728. switch (p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.OLCAk_rLCPs_mPs.choice)
  1729. {
  1730. case rLCPs_mPs_h222LCPs_chosen:
  1731. p_RxMux->Kind = H245_H222;
  1732. p_conf_ind->u.Confirm.Error = load_H222_param(&p_RxMux->u.H222,
  1733. &p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.OLCAk_rLCPs_mPs.u.rLCPs_mPs_h222LCPs);
  1734. p_conf_ind->u.Confirm.u.ConfOpenNeedRsp.pRxMux = p_RxMux;
  1735. break;
  1736. case mPs_h2250LgclChnnlPrmtrs_chosen:
  1737. p_RxMux->Kind = H245_H2250ACK;
  1738. p_conf_ind->u.Confirm.Error = load_H2250_param(&p_RxMux->u.H2250,
  1739. &p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.OLCAk_rLCPs_mPs.u. mPs_h2250LgclChnnlPrmtrs);
  1740. p_conf_ind->u.Confirm.u.ConfOpenNeedRsp.pRxMux = p_RxMux;
  1741. break;
  1742. default:
  1743. H245TRACE(pInstance->dwInst,1,"API:process_bi_open_rsp - unknown choice %d",
  1744. p_pdu_rsp->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_rLCPs.OLCAk_rLCPs_mPs.choice);
  1745. p_conf_ind->u.Confirm.Error = H245_ERROR_NOSUP;
  1746. } // switch
  1747. }
  1748. H245TRACE(pInstance->dwInst,10,"API:process_bi_open_rsp -> OK");
  1749. return H245_ERROR_OK;
  1750. }
  1751. WORD awObject[64];
  1752. unsigned int ArrayFromObject(WORD *pwObject, unsigned uSize, POBJECTID pObject)
  1753. {
  1754. register unsigned int uLength = 0;
  1755. while (pObject)
  1756. {
  1757. if (uLength >= uSize)
  1758. {
  1759. H245TRACE(0,1,"API:ArrayFromObject Object ID too long");
  1760. return uLength;
  1761. }
  1762. pwObject[uLength++] = (WORD) pObject->value;
  1763. pObject = pObject->next;
  1764. }
  1765. return uLength;
  1766. } // ArrayFromObject()
  1767. /*****************************************************************************
  1768. *
  1769. * TYPE: Callback
  1770. *
  1771. * PROCEDURE:
  1772. *
  1773. * DESCRIPTION
  1774. *
  1775. *
  1776. * RETURN:
  1777. *
  1778. *****************************************************************************/
  1779. static Tracker_T *
  1780. TrackerValidate(struct InstanceStruct *pInstance, DWORD_PTR dwTransId)
  1781. {
  1782. register Tracker_T *pTracker = (Tracker_T *)dwTransId;
  1783. if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
  1784. {
  1785. H245TRACE(pInstance->dwInst,1,"API:ValidateTracker -> Tracker Not Found");
  1786. return NULL;
  1787. }
  1788. return pTracker;
  1789. }
  1790. static DWORD_PTR
  1791. TranslateTransId(struct InstanceStruct *pInstance, DWORD_PTR dwTransId)
  1792. {
  1793. register Tracker_T *pTracker = (Tracker_T *)dwTransId;
  1794. if (pTracker == NULL)
  1795. {
  1796. H245TRACE(pInstance->dwInst,1,"API:TranslateTransId -> NULL Tracker");
  1797. return 0;
  1798. }
  1799. if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
  1800. {
  1801. H245TRACE(pInstance->dwInst,1,"API:TranslateTransId -> Tracker Not Found");
  1802. return 0;
  1803. }
  1804. return pTracker->TransId;
  1805. }
  1806. static void
  1807. TrackerFree(struct InstanceStruct *pInstance, DWORD_PTR dwTransId)
  1808. {
  1809. register Tracker_T *pTracker = (Tracker_T *)dwTransId;
  1810. if (pTracker == NULL)
  1811. {
  1812. H245TRACE(pInstance->dwInst,1,"API:TrackerFree -> NULL Tracker");
  1813. return;
  1814. }
  1815. if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
  1816. {
  1817. H245TRACE(pInstance->dwInst,1,"API:TrackerFree -> Tracker Not Found");
  1818. return;
  1819. }
  1820. unlink_dealloc_tracker (pInstance, pTracker);
  1821. }
  1822. static DWORD_PTR
  1823. TranslateAndFree(struct InstanceStruct *pInstance, DWORD_PTR dwTransId)
  1824. {
  1825. register Tracker_T *pTracker = (Tracker_T *)dwTransId;
  1826. if (pTracker == NULL)
  1827. {
  1828. H245TRACE(pInstance->dwInst,1,"API:TranslateAndFree -> NULL Tracker");
  1829. return 0;
  1830. }
  1831. if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
  1832. {
  1833. H245TRACE(pInstance->dwInst,1,"API:TranslateAndFree -> Tracker Not Found");
  1834. return 0;
  1835. }
  1836. dwTransId = pTracker->TransId;
  1837. unlink_dealloc_tracker (pInstance, pTracker);
  1838. return dwTransId;
  1839. }
  1840. static void
  1841. TrackerNewState(struct InstanceStruct *pInstance, DWORD_PTR dwTransId, int nNewState)
  1842. {
  1843. register Tracker_T *pTracker = (Tracker_T *)dwTransId;
  1844. if (pTracker == NULL)
  1845. {
  1846. H245TRACE(pInstance->dwInst,1,"API:TrackerNewState -> NULL Tracker");
  1847. return;
  1848. }
  1849. if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
  1850. {
  1851. H245TRACE(pInstance->dwInst,1,"API:TrackerNewState -> Tracker Not Found");
  1852. return;
  1853. }
  1854. pTracker->State = nNewState;
  1855. }
  1856. static WORD
  1857. GetRxChannel(struct InstanceStruct *pInstance, DWORD_PTR dwTransId)
  1858. {
  1859. register Tracker_T *pTracker = (Tracker_T *)dwTransId;
  1860. if (pTracker == NULL)
  1861. {
  1862. H245TRACE(pInstance->dwInst,1,"API:GetRxChannel -> NULL Tracker");
  1863. return 0;
  1864. }
  1865. if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
  1866. {
  1867. H245TRACE(pInstance->dwInst,1,"API:GetRxChannel -> Tracker Not Found");
  1868. return 0;
  1869. }
  1870. return (WORD)pTracker->u.Channel.RxChannel;
  1871. }
  1872. static WORD
  1873. GetTxChannel(struct InstanceStruct *pInstance, DWORD_PTR dwTransId)
  1874. {
  1875. register Tracker_T *pTracker = (Tracker_T *)dwTransId;
  1876. if (pTracker == NULL)
  1877. {
  1878. H245TRACE(pInstance->dwInst,1,"API:GetTxChannel -> NULL Tracker");
  1879. return 0;
  1880. }
  1881. if (find_tracker_by_pointer (pInstance, pTracker) != pTracker)
  1882. {
  1883. H245TRACE(pInstance->dwInst,1,"API:GetTxChannel -> Tracker Not Found");
  1884. return 0;
  1885. }
  1886. return (WORD)pTracker->u.Channel.TxChannel;
  1887. }
  1888. HRESULT
  1889. H245FunctionNotUnderstood(struct InstanceStruct *pInstance, PDU_T *pPdu)
  1890. {
  1891. HRESULT hr = H245_ERROR_OK;
  1892. MltmdSystmCntrlMssg *pMmPdu = NULL;
  1893. pMmPdu = (MltmdSystmCntrlMssg *) MemAlloc(sizeof(MltmdSystmCntrlMssg));
  1894. if(NULL == pMmPdu)
  1895. {
  1896. return H245_ERROR_NOMEM;
  1897. }
  1898. memset(pMmPdu, 0, sizeof(MltmdSystmCntrlMssg));
  1899. pMmPdu->choice = indication_chosen;
  1900. pMmPdu->u.indication.choice = functionNotUnderstood_chosen;
  1901. pMmPdu->u.indication.u.functionNotUnderstood.choice = pPdu->choice;
  1902. switch (pPdu->choice)
  1903. {
  1904. case FnctnNtUndrstd_request_chosen:
  1905. pMmPdu->u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_request =
  1906. pPdu->u.MltmdSystmCntrlMssg_rqst;
  1907. break;
  1908. case FnctnNtUndrstd_response_chosen:
  1909. pMmPdu->u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_response =
  1910. pPdu->u.MSCMg_rspns;
  1911. break;
  1912. case FnctnNtUndrstd_command_chosen:
  1913. pMmPdu->u.indication.u.functionNotUnderstood.u.FnctnNtUndrstd_command =
  1914. pPdu->u.MSCMg_cmmnd;
  1915. default:
  1916. MemFree(pMmPdu);
  1917. return H245_ERROR_OK;
  1918. }
  1919. hr = sendPDU(pInstance, pMmPdu);
  1920. MemFree(pMmPdu);
  1921. return hr;
  1922. } // H245FunctionNotUnderstood()
  1923. HRESULT
  1924. H245FsmConfirm (PDU_t * pPdu,
  1925. DWORD dwEvent,
  1926. struct InstanceStruct * pInstance,
  1927. DWORD_PTR dwTransId,
  1928. HRESULT lError)
  1929. {
  1930. H245_CONF_IND_T ConfInd;
  1931. DWORD dwIndex;
  1932. H245_MUX_T TxMux;
  1933. H245_MUX_T RxMux;
  1934. HRESULT lResult = H245_ERROR_OK;
  1935. ASSERT(pInstance != NULL);
  1936. ASSERT(pInstance->API.ConfIndCallBack != NULL);
  1937. H245TRACE(pInstance->dwInst,4,"H245FsmConfirm <- Event=%s (%d)",
  1938. map_fsm_event(dwEvent),dwEvent);
  1939. memset (&ConfInd, 0, sizeof(ConfInd));
  1940. ConfInd.Kind = H245_CONF;
  1941. ConfInd.u.Confirm.Confirm = dwEvent;
  1942. ConfInd.u.Confirm.dwPreserved = pInstance->API.dwPreserved;
  1943. ConfInd.u.Confirm.dwTransId = dwTransId;
  1944. ConfInd.u.Confirm.Error = lError;
  1945. switch (dwEvent)
  1946. {
  1947. /******************************/
  1948. /* */
  1949. /* master slave determination */
  1950. /* */
  1951. /******************************/
  1952. case H245_CONF_INIT_MSTSLV:
  1953. ConfInd.u.Confirm.dwTransId = TranslateAndFree(pInstance, dwTransId);
  1954. /* handle errors */
  1955. switch (lError)
  1956. {
  1957. case H245_ERROR_OK:
  1958. ASSERT(pPdu != NULL);
  1959. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  1960. ASSERT(pPdu->u.MSCMg_rspns.choice == mstrSlvDtrmntnAck_chosen);
  1961. pInstance->API.SystemState = APIST_Connected;
  1962. if (pPdu->u.MSCMg_rspns.u.mstrSlvDtrmntnAck.decision.choice == master_chosen)
  1963. {
  1964. pInstance->API.MasterSlave = APIMS_Master;
  1965. ConfInd.u.Confirm.u.ConfMstSlv = H245_MASTER;
  1966. }
  1967. else
  1968. {
  1969. pInstance->API.MasterSlave = APIMS_Slave;
  1970. ConfInd.u.Confirm.u.ConfMstSlv = H245_SLAVE;
  1971. }
  1972. break;
  1973. case REJECT:
  1974. H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Master Slave Reject");
  1975. ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
  1976. ConfInd.u.Confirm.u.ConfMstSlv = H245_INDETERMINATE;
  1977. break;
  1978. case TIMER_EXPIRY:
  1979. case ERROR_D_TIMEOUT:
  1980. case ERROR_F_TIMEOUT:
  1981. ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
  1982. ConfInd.u.Confirm.u.ConfMstSlv = H245_INDETERMINATE;
  1983. break;
  1984. // case FUNCT_NOT_SUP:
  1985. // case ERROR_A_INAPPROPRIATE:
  1986. // case ERROR_B_INAPPROPRIATE:
  1987. // case ERROR_C_INAPPROPRIATE:
  1988. // case MS_FAILED:
  1989. default:
  1990. H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Master Slave Error %d", lError);
  1991. ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
  1992. ConfInd.u.Confirm.u.ConfMstSlv = H245_INDETERMINATE;
  1993. break;
  1994. }
  1995. break;
  1996. /****************************************/
  1997. /* */
  1998. /* Terminal Capability exchange confirm */
  1999. /* */
  2000. /****************************************/
  2001. case H245_CONF_SEND_TERMCAP:
  2002. ConfInd.u.Confirm.dwTransId = TranslateAndFree(pInstance, dwTransId);
  2003. /* determine errors */
  2004. switch (lError)
  2005. {
  2006. case H245_ERROR_OK:
  2007. ASSERT(pPdu != NULL);
  2008. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2009. ASSERT(pPdu->u.MSCMg_rspns.choice == terminalCapabilitySetAck_chosen);
  2010. ConfInd.u.Confirm.u.ConfSndTcap.AccRej = H245_ACC;
  2011. clean_cap_table(&pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet);
  2012. break;
  2013. case REJECT:
  2014. ConfInd.u.Confirm.Error = H245_ERROR_OK;
  2015. ConfInd.u.Confirm.u.ConfSndTcap.AccRej = H245_REJ;
  2016. break;
  2017. case TIMER_EXPIRY:
  2018. case ERROR_D_TIMEOUT:
  2019. case ERROR_F_TIMEOUT:
  2020. ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
  2021. break;
  2022. // case FUNCT_NOT_SUP:
  2023. // case ERROR_A_INAPPROPRIATE:
  2024. // case ERROR_B_INAPPROPRIATE:
  2025. // case ERROR_C_INAPPROPRIATE:
  2026. default:
  2027. H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Term Cap Error %d", lError);
  2028. ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
  2029. break;
  2030. }
  2031. break;
  2032. /***************************************/
  2033. /* */
  2034. /* unidirectional logical channel open */
  2035. /* */
  2036. /***************************************/
  2037. case H245_CONF_OPEN:
  2038. ConfInd.u.Confirm.dwTransId = TranslateTransId(pInstance, dwTransId);
  2039. ConfInd.u.Confirm.u.ConfOpen.TxChannel = GetTxChannel(pInstance, dwTransId);
  2040. ConfInd.u.Confirm.u.ConfOpen.RxPort = H245_INVALID_PORT_NUMBER;
  2041. /* determine errors */
  2042. switch (lError)
  2043. {
  2044. case H245_ERROR_OK:
  2045. ASSERT(pPdu != NULL);
  2046. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2047. ASSERT(pPdu->u.MSCMg_rspns.choice == openLogicalChannelAck_chosen);
  2048. ASSERT((pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.bit_mask & OLCAk_rLCPs_present) == 0);
  2049. if (pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.bit_mask & OLCAk_sprtStck_present)
  2050. {
  2051. ConfInd.u.Confirm.u.ConfOpen.pSeparateStack =
  2052. &pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_sprtStck;
  2053. }
  2054. if (pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.bit_mask & frwrdMltplxAckPrmtrs_present)
  2055. {
  2056. switch (pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.frwrdMltplxAckPrmtrs.choice)
  2057. {
  2058. case h2250LgclChnnlAckPrmtrs_chosen:
  2059. TxMux.Kind = H245_H2250ACK;
  2060. load_H2250ACK_param(&TxMux.u.H2250ACK,
  2061. &pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.frwrdMltplxAckPrmtrs.u.h2250LgclChnnlAckPrmtrs);
  2062. ConfInd.u.Confirm.u.ConfOpen.pTxMux = &TxMux;
  2063. break;
  2064. } // switch
  2065. }
  2066. ConfInd.u.Confirm.u.ConfOpen.AccRej = H245_ACC;
  2067. TrackerNewState(pInstance,dwTransId,API_ST_IDLE);
  2068. break;
  2069. case REJECT:
  2070. ASSERT(pPdu != NULL);
  2071. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2072. ASSERT(pPdu->u.MSCMg_rspns.choice == openLogicalChannelReject_chosen);
  2073. ConfInd.u.Confirm.Error = H245_ERROR_OK;
  2074. ConfInd.u.Confirm.u.ConfOpen.AccRej =
  2075. pPdu->u.MSCMg_rspns.u.openLogicalChannelReject.cause.choice;
  2076. TrackerFree(pInstance,dwTransId);
  2077. break;
  2078. case TIMER_EXPIRY:
  2079. case ERROR_D_TIMEOUT:
  2080. case ERROR_F_TIMEOUT:
  2081. ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
  2082. ConfInd.u.Confirm.u.ConfOpen.AccRej = H245_REJ;
  2083. TrackerFree(pInstance,dwTransId);
  2084. break;
  2085. // case FUNCT_NOT_SUP:
  2086. // case ERROR_A_INAPPROPRIATE:
  2087. // case ERROR_B_INAPPROPRIATE:
  2088. // case ERROR_C_INAPPROPRIATE:
  2089. default:
  2090. H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Open Channel Error %d", lError);
  2091. ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
  2092. ConfInd.u.Confirm.u.ConfOpen.AccRej = H245_REJ;
  2093. TrackerFree(pInstance,dwTransId);
  2094. }
  2095. break;
  2096. /***********************************************/
  2097. /* */
  2098. /* bidirectional logical channel open (TBD)??? */
  2099. /* */
  2100. /***********************************************/
  2101. case H245_CONF_NEEDRSP_OPEN:
  2102. {
  2103. Tracker_T *pTracker;
  2104. pTracker = TrackerValidate(pInstance, dwTransId);
  2105. if (pTracker == NULL)
  2106. return H245_ERROR_OK;
  2107. ConfInd.u.Confirm.dwTransId = pTracker->TransId;
  2108. ConfInd.u.Confirm.u.ConfOpenNeedRsp.TxChannel = (WORD)pTracker->u.Channel.TxChannel;
  2109. ConfInd.u.Confirm.u.ConfOpenNeedRsp.RxPort = H245_INVALID_PORT_NUMBER;
  2110. /* determine errors */
  2111. switch (lError)
  2112. {
  2113. case H245_ERROR_OK:
  2114. ASSERT(pPdu != NULL);
  2115. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2116. ASSERT(pPdu->u.MSCMg_rspns.choice == openLogicalChannelAck_chosen);
  2117. ASSERT((pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.bit_mask & OLCAk_rLCPs_present) != 0);
  2118. ConfInd.u.Confirm.u.ConfOpenNeedRsp.AccRej = H245_ACC;
  2119. if (pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.bit_mask & OLCAk_sprtStck_present)
  2120. {
  2121. ConfInd.u.Confirm.u.ConfOpenNeedRsp.pSeparateStack =
  2122. &pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.OLCAk_sprtStck;
  2123. }
  2124. if (pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.bit_mask & frwrdMltplxAckPrmtrs_present)
  2125. {
  2126. switch (pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.frwrdMltplxAckPrmtrs.choice)
  2127. {
  2128. case h2250LgclChnnlAckPrmtrs_chosen:
  2129. TxMux.Kind = H245_H2250ACK;
  2130. load_H2250ACK_param(&TxMux.u.H2250ACK,
  2131. &pPdu->u.MSCMg_rspns.u.openLogicalChannelAck.frwrdMltplxAckPrmtrs.u.h2250LgclChnnlAckPrmtrs);
  2132. ConfInd.u.Confirm.u.ConfOpenNeedRsp.pTxMux = &TxMux;
  2133. break;
  2134. } // switch
  2135. }
  2136. /* NOTE Receive Channel is assigned in this call */
  2137. process_bi_open_rsp (pInstance,
  2138. pPdu,
  2139. &RxMux,
  2140. &(pTracker->u.Channel.RxChannel),
  2141. &ConfInd);
  2142. /* NOTE: this is a special case since we have to assign */
  2143. /* the receive channel to the tracker.. otherwise we */
  2144. /* will not be able to find it later.. */
  2145. /* Here we have to update both the state, and the channel */
  2146. pTracker->State = API_ST_WAIT_CONF;
  2147. break;
  2148. case REJECT:
  2149. ConfInd.u.Confirm.Confirm = H245_CONF_OPEN;
  2150. ConfInd.u.Confirm.u.ConfOpen.TxChannel = (WORD)pTracker->u.Channel.TxChannel;
  2151. ConfInd.u.Confirm.Error = H245_ERROR_OK;
  2152. ConfInd.u.Confirm.u.ConfOpen.AccRej =
  2153. pPdu->u.MSCMg_rspns.u.openLogicalChannelReject.cause.choice;
  2154. unlink_dealloc_tracker (pInstance, pTracker);
  2155. break;
  2156. case TIMER_EXPIRY:
  2157. case ERROR_D_TIMEOUT:
  2158. case ERROR_F_TIMEOUT:
  2159. ConfInd.u.Confirm.Confirm = H245_CONF_OPEN;
  2160. ConfInd.u.Confirm.u.ConfOpen.TxChannel = (WORD)pTracker->u.Channel.TxChannel;
  2161. ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
  2162. ConfInd.u.Confirm.u.ConfOpen.AccRej = H245_REJ;
  2163. unlink_dealloc_tracker (pInstance, pTracker);
  2164. break;
  2165. // case FUNCT_NOT_SUP:
  2166. // case ERROR_A_INAPPROPRIATE:
  2167. // case ERROR_B_INAPPROPRIATE:
  2168. // case ERROR_C_INAPPROPRIATE:
  2169. default:
  2170. H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Open Channel Error %d", lError);
  2171. ConfInd.u.Confirm.Confirm = H245_CONF_OPEN;
  2172. ConfInd.u.Confirm.u.ConfOpen.TxChannel = (WORD)pTracker->u.Channel.TxChannel;
  2173. ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
  2174. ConfInd.u.Confirm.u.ConfOpen.AccRej = H245_REJ;
  2175. unlink_dealloc_tracker (pInstance, pTracker);
  2176. }
  2177. }
  2178. break;
  2179. /************************************************/
  2180. /* */
  2181. /* unidirectional logical channel close */
  2182. /* */
  2183. /* bidirection logical channel close */
  2184. /* */
  2185. /************************************************/
  2186. case H245_CONF_CLOSE:
  2187. ConfInd.u.Confirm.dwTransId = TranslateTransId(pInstance, dwTransId);
  2188. ConfInd.u.Confirm.u.ConfClose.Channel = GetTxChannel(pInstance, dwTransId);
  2189. ConfInd.u.Confirm.u.ConfClose.AccRej = H245_ACC;
  2190. /* determine errors */
  2191. switch (lError)
  2192. {
  2193. case H245_ERROR_OK:
  2194. ASSERT(pPdu != NULL);
  2195. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2196. ASSERT(pPdu->u.MSCMg_rspns.choice == closeLogicalChannelAck_chosen);
  2197. ConfInd.u.Confirm.u.ConfClose.AccRej = H245_ACC;
  2198. TrackerFree(pInstance,dwTransId);
  2199. break;
  2200. case REJECT:
  2201. /* should never be rejected */
  2202. H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Close Channel Rejected");
  2203. TrackerNewState(pInstance,dwTransId,API_ST_IDLE);
  2204. ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
  2205. ConfInd.u.Confirm.u.ConfClose.AccRej = H245_REJ;
  2206. break;
  2207. case TIMER_EXPIRY:
  2208. case ERROR_D_TIMEOUT:
  2209. case ERROR_F_TIMEOUT:
  2210. TrackerNewState(pInstance,dwTransId,API_ST_IDLE);
  2211. ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
  2212. ConfInd.u.Confirm.u.ConfClose.AccRej = H245_REJ;
  2213. break;
  2214. // case FUNCT_NOT_SUP:
  2215. // case ERROR_A_INAPPROPRIATE:
  2216. // case ERROR_B_INAPPROPRIATE:
  2217. // case ERROR_C_INAPPROPRIATE:
  2218. default:
  2219. H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Close Channel Error %d", lError);
  2220. TrackerNewState(pInstance,dwTransId,API_ST_IDLE);
  2221. ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
  2222. ConfInd.u.Confirm.u.ConfClose.AccRej = H245_REJ;
  2223. }
  2224. break;
  2225. /***************************/
  2226. /* */
  2227. /* request channel close */
  2228. /* */
  2229. /***************************/
  2230. case H245_CONF_REQ_CLOSE:
  2231. ConfInd.u.Confirm.dwTransId = TranslateTransId(pInstance, dwTransId);
  2232. ConfInd.u.Confirm.u.ConfReqClose.Channel = GetRxChannel(pInstance, dwTransId);
  2233. TrackerNewState(pInstance,dwTransId,API_ST_IDLE);
  2234. /* determine errors */
  2235. switch (lError)
  2236. {
  2237. case H245_ERROR_OK:
  2238. ASSERT(pPdu != NULL);
  2239. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2240. ASSERT(pPdu->u.MSCMg_rspns.choice == requestChannelCloseAck_chosen);
  2241. ConfInd.u.Confirm.u.ConfReqClose.AccRej = H245_ACC;
  2242. break;
  2243. case REJECT:
  2244. ConfInd.u.Confirm.Error = H245_ERROR_OK;
  2245. ConfInd.u.Confirm.u.ConfReqClose.AccRej = H245_REJ;
  2246. break;
  2247. case TIMER_EXPIRY:
  2248. case ERROR_D_TIMEOUT:
  2249. case ERROR_F_TIMEOUT:
  2250. ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
  2251. ConfInd.u.Confirm.u.ConfReqClose.AccRej = H245_REJ;
  2252. break;
  2253. // case FUNCT_NOT_SUP:
  2254. // case ERROR_A_INAPPROPRIATE:
  2255. // case ERROR_B_INAPPROPRIATE:
  2256. // case ERROR_C_INAPPROPRIATE:
  2257. default:
  2258. H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Request Channel Close Error %d", lError);
  2259. ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
  2260. ConfInd.u.Confirm.u.ConfReqClose.AccRej = H245_REJ;
  2261. }
  2262. break;
  2263. /*******************/
  2264. /* */
  2265. /* mux table entry */
  2266. /* */
  2267. /*******************/
  2268. case H245_CONF_MUXTBL_SND:
  2269. {
  2270. UINT ii;
  2271. Tracker_T *pTracker;
  2272. pTracker = TrackerValidate(pInstance, dwTransId);
  2273. if (pTracker == NULL)
  2274. return H245_ERROR_OK;
  2275. ConfInd.u.Confirm.dwTransId = pTracker->TransId;
  2276. switch (lError)
  2277. {
  2278. case H245_ERROR_OK:
  2279. ASSERT(pPdu != NULL);
  2280. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2281. ASSERT(pPdu->u.MSCMg_rspns.choice == multiplexEntrySendAck_chosen);
  2282. for (ii = 0;
  2283. ii < pPdu->u.MSCMg_rspns.u.multiplexEntrySendAck.multiplexTableEntryNumber.count;
  2284. ii ++)
  2285. {
  2286. pTracker->u.MuxEntryCount--;
  2287. ConfInd.u.Confirm.u.ConfMuxSnd.MuxEntryId =
  2288. pPdu->u.MSCMg_rspns.u.multiplexEntrySendAck.multiplexTableEntryNumber.value[ii];
  2289. ConfInd.u.Confirm.u.ConfMuxSnd.AccRej = H245_ACC;
  2290. if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MSCMg_rspns.u.multiplexEntrySendAck) == H245_ERROR_NOSUP)
  2291. {
  2292. H245FunctionNotUnderstood(pInstance, pPdu);
  2293. }
  2294. pTracker = TrackerValidate(pInstance, dwTransId);
  2295. if (pTracker == NULL)
  2296. return H245_ERROR_OK;
  2297. }
  2298. if (pTracker->u.MuxEntryCount == 0)
  2299. {
  2300. unlink_dealloc_tracker (pInstance, pTracker);
  2301. }
  2302. pPdu = NULL; // Don't do callback again!
  2303. break;
  2304. case REJECT:
  2305. ASSERT(pPdu != NULL);
  2306. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2307. ASSERT(pPdu->u.MSCMg_rspns.choice == multiplexEntrySendReject_chosen);
  2308. ConfInd.u.Confirm.Error = H245_ERROR_OK;
  2309. for (ii = 0;
  2310. ii < pPdu->u.MSCMg_rspns.u.multiplexEntrySendReject.rejectionDescriptions.count;
  2311. ++ii)
  2312. {
  2313. pTracker->u.MuxEntryCount--;
  2314. ConfInd.u.Confirm.u.ConfMuxSnd.MuxEntryId =
  2315. pPdu->u.MSCMg_rspns.u.multiplexEntrySendReject.rejectionDescriptions.value[ii].multiplexTableEntryNumber;
  2316. switch (pPdu->u.MSCMg_rspns.u.multiplexEntrySendReject.rejectionDescriptions.value[ii].cause.choice)
  2317. {
  2318. default:
  2319. H245PANIC();
  2320. case MERDs_cs_unspcfdCs_chosen:
  2321. ConfInd.u.Confirm.u.ConfMuxSnd.AccRej = H245_REJ; /* unspecified */
  2322. break;
  2323. case descriptorTooComplex_chosen:
  2324. ConfInd.u.Confirm.u.ConfMuxSnd.AccRej = H245_REJ_MUX_COMPLICATED;
  2325. break;
  2326. }
  2327. if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MSCMg_rspns.u.multiplexEntrySendReject) == H245_ERROR_NOSUP)
  2328. {
  2329. H245FunctionNotUnderstood(pInstance, pPdu);
  2330. }
  2331. pTracker = TrackerValidate(pInstance, dwTransId);
  2332. if (pTracker == NULL)
  2333. return H245_ERROR_OK;
  2334. }
  2335. if (pTracker->u.MuxEntryCount == 0)
  2336. {
  2337. unlink_dealloc_tracker (pInstance, pTracker);
  2338. }
  2339. pPdu = NULL; // Don't do callback again!
  2340. break;
  2341. case TIMER_EXPIRY:
  2342. case ERROR_D_TIMEOUT:
  2343. case ERROR_F_TIMEOUT:
  2344. unlink_dealloc_tracker (pInstance, pTracker);
  2345. ConfInd.u.Confirm.Error = H245_ERROR_TIMEOUT;
  2346. break;
  2347. // case FUNCT_NOT_SUP:
  2348. // case ERROR_A_INAPPROPRIATE:
  2349. // case ERROR_B_INAPPROPRIATE:
  2350. // case ERROR_C_INAPPROPRIATE:
  2351. default:
  2352. H245TRACE(pInstance->dwInst,1,"H245FsmConfirm - Mux Table Send Error %d", lError);
  2353. unlink_dealloc_tracker (pInstance, pTracker);
  2354. ConfInd.u.Confirm.Error = H245_ERROR_UNKNOWN;
  2355. } // switch
  2356. }
  2357. break;
  2358. case H245_CONF_RMESE:
  2359. ASSERT(pPdu != NULL);
  2360. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2361. ASSERT(pPdu->u.MSCMg_rspns.choice == requestMultiplexEntryAck_chosen);
  2362. ConfInd.u.Confirm.u.ConfRmese.dwCount =
  2363. pPdu->u.MSCMg_rspns.u.requestMultiplexEntryAck.entryNumbers.count;
  2364. for (dwIndex = 0; dwIndex < ConfInd.u.Confirm.u.ConfRmese.dwCount; ++dwIndex)
  2365. {
  2366. ConfInd.u.Confirm.u.ConfRmese.awMultiplexTableEntryNumbers[dwIndex] =
  2367. pPdu->u.MSCMg_rspns.u.requestMultiplexEntryAck.entryNumbers.value[dwIndex];
  2368. }
  2369. break;
  2370. case H245_CONF_RMESE_REJECT:
  2371. ASSERT(pPdu != NULL);
  2372. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2373. ASSERT(pPdu->u.MSCMg_rspns.choice == rqstMltplxEntryRjct_chosen);
  2374. ConfInd.u.Confirm.u.ConfRmeseReject.dwCount =
  2375. pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.count;
  2376. for (dwIndex = 0; dwIndex < ConfInd.u.Confirm.u.ConfRmeseReject.dwCount; ++dwIndex)
  2377. {
  2378. ConfInd.u.Confirm.u.ConfRmeseReject.awMultiplexTableEntryNumbers[dwIndex] =
  2379. pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.value[dwIndex].multiplexTableEntryNumber;
  2380. }
  2381. break;
  2382. case H245_CONF_RMESE_EXPIRED:
  2383. ASSERT(pPdu == NULL);
  2384. break;
  2385. case H245_CONF_MRSE:
  2386. ASSERT(pPdu != NULL);
  2387. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2388. ASSERT(pPdu->u.MSCMg_rspns.choice == requestModeAck_chosen);
  2389. ConfInd.u.Confirm.u.ConfMrse =
  2390. pPdu->u.MSCMg_rspns.u.requestModeAck.response.choice;
  2391. break;
  2392. case H245_CONF_MRSE_REJECT:
  2393. ASSERT(pPdu != NULL);
  2394. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2395. ASSERT(pPdu->u.MSCMg_rspns.choice == requestModeReject_chosen);
  2396. ConfInd.u.Confirm.u.ConfMrseReject =
  2397. pPdu->u.MSCMg_rspns.u.requestModeReject.cause.choice;
  2398. break;
  2399. case H245_CONF_MRSE_EXPIRED:
  2400. ASSERT(pPdu == NULL);
  2401. break;
  2402. case H245_CONF_MLSE:
  2403. ASSERT(pPdu != NULL);
  2404. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2405. ASSERT(pPdu->u.MSCMg_rspns.choice == maintenanceLoopAck_chosen);
  2406. ConfInd.u.Confirm.u.ConfMlse.LoopType =
  2407. pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.choice;
  2408. switch (pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.choice)
  2409. {
  2410. case systemLoop_chosen:
  2411. ConfInd.u.Confirm.u.ConfMlse.Channel = 0;
  2412. break;
  2413. case mediaLoop_chosen:
  2414. case logicalChannelLoop_chosen:
  2415. ConfInd.u.Confirm.u.ConfMlse.Channel =
  2416. pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.u.mediaLoop;
  2417. break;
  2418. default:
  2419. H245TRACE(pInstance->dwInst,1,
  2420. "H245FsmConfirm: Invalid Maintenance Loop Ack type %d",
  2421. pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.choice);
  2422. lResult = H245_ERROR_NOSUP;
  2423. } // switch
  2424. break;
  2425. case H245_CONF_MLSE_REJECT:
  2426. ASSERT(pPdu != NULL);
  2427. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2428. ASSERT(pPdu->u.MSCMg_rspns.choice == maintenanceLoopReject_chosen);
  2429. ConfInd.u.Confirm.u.ConfMlseReject.LoopType =
  2430. pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.choice;
  2431. switch (pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.choice)
  2432. {
  2433. case systemLoop_chosen:
  2434. ConfInd.u.Confirm.u.ConfMlseReject.Channel = 0;
  2435. break;
  2436. case mediaLoop_chosen:
  2437. case logicalChannelLoop_chosen:
  2438. ConfInd.u.Confirm.u.ConfMlseReject.Channel =
  2439. pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.u.mediaLoop;
  2440. break;
  2441. default:
  2442. H245TRACE(pInstance->dwInst,1,
  2443. "H245FsmConfirm: Invalid Maintenance Loop Reject type %d",
  2444. pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.choice);
  2445. lResult = H245_ERROR_NOSUP;
  2446. } // switch
  2447. break;
  2448. case H245_CONF_MLSE_EXPIRED:
  2449. ASSERT(pPdu == NULL);
  2450. break;
  2451. case H245_CONF_RTDSE:
  2452. ASSERT(pPdu != NULL);
  2453. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2454. ASSERT(pPdu->u.MSCMg_rspns.choice == roundTripDelayResponse_chosen);
  2455. break;
  2456. case H245_CONF_RTDSE_EXPIRED:
  2457. ASSERT(pPdu == NULL);
  2458. break;
  2459. default:
  2460. /* Possible Error */
  2461. H245TRACE(pInstance->dwInst, 1,
  2462. "H245FsmConfirm -> Invalid Confirm Event %d",
  2463. dwEvent);
  2464. return H245_ERROR_SUBSYS;
  2465. } // switch
  2466. if (lResult == H245_ERROR_OK)
  2467. {
  2468. if (pPdu)
  2469. {
  2470. if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MSCMg_rspns.u) == H245_ERROR_NOSUP)
  2471. {
  2472. H245FunctionNotUnderstood(pInstance, pPdu);
  2473. }
  2474. }
  2475. else
  2476. {
  2477. (*pInstance->API.ConfIndCallBack)(&ConfInd, NULL);
  2478. }
  2479. H245TRACE(pInstance->dwInst,4,"H245FsmConfirm -> OK");
  2480. }
  2481. else
  2482. {
  2483. H245TRACE(pInstance->dwInst,1,"H245FsmConfirm -> %s", map_api_error(lResult));
  2484. }
  2485. return lResult;
  2486. } // H245FsmConfirm()
  2487. HRESULT
  2488. H245FsmIndication (PDU_t * pPdu,
  2489. DWORD dwEvent,
  2490. struct InstanceStruct * pInstance,
  2491. DWORD_PTR dwTransId,
  2492. HRESULT lError)
  2493. {
  2494. H245_CONF_IND_T ConfInd;
  2495. DWORD dwIndex;
  2496. MltmdSystmCntrlMssg *pRsp;
  2497. HRESULT lResult = H245_ERROR_OK;
  2498. #if 1
  2499. int nLength;
  2500. WCHAR * pwchar = NULL;
  2501. #endif
  2502. ASSERT(dwEvent == H245_IND_OPEN_CONF || pPdu != NULL);
  2503. ASSERT(pInstance != NULL);
  2504. ASSERT(pInstance->API.ConfIndCallBack != NULL);
  2505. H245TRACE(pInstance->dwInst,4,"H245FsmIndication <- Event=%s (%d)",
  2506. map_fsm_event(dwEvent),dwEvent);
  2507. memset (&ConfInd, 0, sizeof(ConfInd));
  2508. ConfInd.Kind = H245_IND;
  2509. ConfInd.u.Indication.Indicator = dwEvent;
  2510. ConfInd.u.Indication.dwPreserved = pInstance->API.dwPreserved;
  2511. switch (dwEvent)
  2512. {
  2513. /******************************/
  2514. /* */
  2515. /* master slave determination */
  2516. /* */
  2517. /******************************/
  2518. case H245_IND_MSTSLV:
  2519. /* handle errors */
  2520. switch (lError)
  2521. {
  2522. case H245_ERROR_OK:
  2523. ASSERT(pPdu != NULL);
  2524. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2525. ASSERT(pPdu->u.MSCMg_rspns.choice == mstrSlvDtrmntnAck_chosen);
  2526. pInstance->API.SystemState = APIST_Connected;
  2527. if (pPdu->u.MSCMg_rspns.u.mstrSlvDtrmntnAck.decision.choice == master_chosen)
  2528. {
  2529. pInstance->API.MasterSlave = APIMS_Master;
  2530. ConfInd.u.Indication.u.IndMstSlv = H245_MASTER;
  2531. }
  2532. else
  2533. {
  2534. pInstance->API.MasterSlave = APIMS_Slave;
  2535. ConfInd.u.Indication.u.IndMstSlv = H245_SLAVE;
  2536. }
  2537. break;
  2538. case MS_FAILED:
  2539. case REJECT:
  2540. case TIMER_EXPIRY:
  2541. ConfInd.u.Indication.u.IndMstSlv = H245_INDETERMINATE;
  2542. break;
  2543. // case ERROR_D_TIMEOUT:
  2544. // case ERROR_F_TIMEOUT:
  2545. // case FUNCT_NOT_SUP:
  2546. // case ERROR_A_INAPPROPRIATE:
  2547. // case ERROR_B_INAPPROPRIATE:
  2548. // case ERROR_C_INAPPROPRIATE:
  2549. default:
  2550. H245PANIC();
  2551. /* (TBC) */
  2552. return H245_ERROR_OK;
  2553. }
  2554. break;
  2555. /****************************************/
  2556. /* */
  2557. /* Terminal Capability exchange */
  2558. /* */
  2559. /****************************************/
  2560. /* decode_termcapset breaks the termcap set up and sends up */
  2561. /* a single indication to the client */
  2562. case H245_IND_CAP:
  2563. ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
  2564. ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == terminalCapabilitySet_chosen);
  2565. pRsp = (PDU_t *)MemAlloc(sizeof(*pPdu));
  2566. if (pRsp == NULL)
  2567. {
  2568. H245TRACE(pInstance->dwInst,1,"H245FsmIndication TermCap: no memory for response");
  2569. return H245_ERROR_NOMEM;
  2570. }
  2571. memset(pRsp, 0, sizeof(*pRsp));
  2572. process_term_cap_set_ind (pInstance, pPdu, pRsp);
  2573. FsmOutgoing(pInstance, pRsp, 0);
  2574. MemFree (pRsp);
  2575. break;
  2576. case H245_IND_CESE_RELEASE:
  2577. break;
  2578. /************************************************/
  2579. /* */
  2580. /* unidirectional logical channel open */
  2581. /* */
  2582. /* bidirectional logical channel open */
  2583. /* */
  2584. /************************************************/
  2585. case H245_IND_OPEN:
  2586. ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
  2587. ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == openLogicalChannel_chosen);
  2588. {
  2589. unsigned short forward_channel;
  2590. H245_ACC_REJ_T acc_rej;
  2591. /* if error, process_open_ind will tell us what to send for reject */
  2592. if (process_open_ind(pInstance,pPdu,&forward_channel,&acc_rej,&ConfInd) != H245_ERROR_OK)
  2593. {
  2594. // Reject the open
  2595. pRsp = (PDU_t *)MemAlloc(sizeof(*pPdu));
  2596. if (pRsp == NULL)
  2597. {
  2598. H245TRACE(pInstance->dwInst,1,"H245FsmIndication TermCap: no memory for response");
  2599. return H245_ERROR_NOMEM;
  2600. }
  2601. memset(pRsp, 0, sizeof(*pRsp));
  2602. pdu_rsp_open_logical_channel_rej(pRsp, forward_channel, (WORD)acc_rej);
  2603. FsmOutgoing(pInstance, pRsp, 0);
  2604. MemFree (pRsp);
  2605. }
  2606. }
  2607. break;
  2608. /************************************************/
  2609. /* */
  2610. /* Confirm bi-directional open */
  2611. /* */
  2612. /************************************************/
  2613. case H245_IND_OPEN_CONF:
  2614. #if defined(_DEBUG)
  2615. if (lError == H245_ERROR_OK)
  2616. {
  2617. ASSERT(pPdu != NULL);
  2618. ASSERT(pPdu->choice == indication_chosen);
  2619. ASSERT(pPdu->u.indication.choice == opnLgclChnnlCnfrm_chosen);
  2620. }
  2621. #endif
  2622. {
  2623. Tracker_T *pTracker;
  2624. pTracker = TrackerValidate(pInstance, dwTransId);
  2625. if (pTracker == NULL)
  2626. return H245_ERROR_OK;
  2627. /* confirm processing */
  2628. ASSERT(pTracker->State == API_ST_WAIT_CONF);
  2629. ASSERT(pTracker->TrackerType == API_OPEN_CHANNEL_T);
  2630. ASSERT(pTracker->u.Channel.ChannelAlloc == API_CH_ALLOC_RMT);
  2631. ASSERT(pTracker->u.Channel.ChannelType == API_CH_TYPE_BI);
  2632. ConfInd.u.Indication.u.IndOpenConf.RxChannel = (WORD)pTracker->u.Channel.RxChannel;
  2633. ConfInd.u.Indication.u.IndOpenConf.TxChannel = (WORD)pTracker->u.Channel.TxChannel;
  2634. pTracker->State = API_ST_IDLE;
  2635. }
  2636. break;
  2637. /************************************************/
  2638. /* */
  2639. /* unidirectional logical channel close */
  2640. /* */
  2641. /* bidirectional logical channel close */
  2642. /* */
  2643. /************************************************/
  2644. case H245_IND_CLOSE:
  2645. ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
  2646. ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == closeLogicalChannel_chosen);
  2647. {
  2648. Tracker_T *pTracker;
  2649. ConfInd.u.Indication.u.IndClose.Channel =
  2650. pPdu->u.MltmdSystmCntrlMssg_rqst.u.closeLogicalChannel.forwardLogicalChannelNumber;
  2651. ConfInd.u.Indication.u.IndClose.Reason =
  2652. (pPdu->u.MltmdSystmCntrlMssg_rqst.u.closeLogicalChannel.source.choice==user_chosen)?H245_USER:H245_LCSE;
  2653. /* find the tracker */
  2654. pTracker = find_tracker_by_rxchannel (pInstance,
  2655. ConfInd.u.Indication.u.IndClose.Channel,
  2656. API_CH_ALLOC_RMT);
  2657. if (!pTracker)
  2658. {
  2659. H245TRACE(pInstance->dwInst,4,"H245FsmIndication -> close indication - Tracker not found");
  2660. return H245_ERROR_OK;
  2661. }
  2662. unlink_dealloc_tracker (pInstance, pTracker);
  2663. }
  2664. break;
  2665. /************************************************/
  2666. /* */
  2667. /* request channel close */
  2668. /* */
  2669. /************************************************/
  2670. case H245_IND_REQ_CLOSE:
  2671. ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
  2672. ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == requestChannelClose_chosen);
  2673. {
  2674. Tracker_T *pTracker;
  2675. ConfInd.u.Indication.u.IndReqClose =
  2676. pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestChannelClose.forwardLogicalChannelNumber;
  2677. /* find the tracker */
  2678. pTracker = find_tracker_by_txchannel (pInstance,
  2679. ConfInd.u.Indication.u.IndReqClose,
  2680. API_CH_ALLOC_LCL);
  2681. if (!pTracker)
  2682. {
  2683. H245TRACE(pInstance->dwInst,4,"H245FsmIndication Request Channel Close: Tracker not found");
  2684. pRsp = (PDU_t *)MemAlloc(sizeof(*pPdu));
  2685. if (pRsp == NULL)
  2686. {
  2687. H245TRACE(pInstance->dwInst,1,"H245FsmIndication Request Channel Close: no memory for response");
  2688. return H245_ERROR_NOMEM;
  2689. }
  2690. memset(pRsp, 0, sizeof(*pRsp));
  2691. /* can't find it.. must be closed.. respond anyway */
  2692. pdu_rsp_request_channel_close_rej(pRsp, (WORD)ConfInd.u.Indication.u.IndReqClose,H245_REJ);
  2693. FsmOutgoing(pInstance, pRsp, 0);
  2694. MemFree(pRsp);
  2695. /* Possible Error.. could have been removed from list or */
  2696. /* could have been allocated remotely... and this is a protocol */
  2697. /* error */
  2698. return H245_ERROR_OK;
  2699. }
  2700. ASSERT(pTracker->State == API_ST_IDLE);
  2701. pTracker->State = API_ST_WAIT_LCLACK;
  2702. pTracker->TrackerType = API_CLOSE_CHANNEL_T;
  2703. }
  2704. break;
  2705. /************************************************/
  2706. /* */
  2707. /* Release Close Request */
  2708. /* */
  2709. /************************************************/
  2710. case H245_IND_CLCSE_RELEASE:
  2711. ASSERT(pPdu->choice == indication_chosen);
  2712. ASSERT(pPdu->u.indication.choice == rqstChnnlClsRls_chosen);
  2713. {
  2714. Tracker_T *pTracker;
  2715. /* find tracker.. and set to LCLACK_CANCEL */
  2716. /* this will tell api to notify user */
  2717. pTracker = find_tracker_by_txchannel (pInstance,
  2718. pPdu->u.indication.u.rqstChnnlClsRls.forwardLogicalChannelNumber,
  2719. API_CH_ALLOC_LCL);
  2720. if (pTracker)
  2721. {
  2722. if (pTracker->State != API_ST_WAIT_LCLACK)
  2723. {
  2724. return H245_ERROR_INVALID_INST;
  2725. }
  2726. pTracker->State = API_ST_WAIT_LCLACK_CANCEL;
  2727. }
  2728. else
  2729. {
  2730. H245TRACE(pInstance->dwInst,1,"H245FsmIndication -> IND_REL_CLSE: Cancel.. NO TRACKER FOUND");
  2731. }
  2732. }
  2733. break;
  2734. /************************************************/
  2735. /* */
  2736. /* mux table entry */
  2737. /* */
  2738. /************************************************/
  2739. case H245_IND_MUX_TBL:
  2740. ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
  2741. ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == multiplexEntrySend_chosen);
  2742. {
  2743. unsigned short seq_num;
  2744. H245_ACC_REJ_MUX_T rej_mux;
  2745. H245_MUX_TABLE_T *p_mux_tbl;
  2746. DWORD rej_cnt;
  2747. DWORD acc_cnt;
  2748. Tracker_T *pTracker;
  2749. /* process the mux table entry */
  2750. p_mux_tbl = process_mux_table_ind(pPdu,&seq_num,rej_mux,&rej_cnt,&acc_cnt);
  2751. if (rej_cnt)
  2752. {
  2753. /* build the reject pdu from the rej_mux table */
  2754. if (!(pRsp = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
  2755. return H245_ERROR_NOMEM;
  2756. memset(pRsp, 0, sizeof(MltmdSystmCntrlMssg));
  2757. pdu_rsp_mux_table_rej (pRsp,seq_num,rej_mux,(rej_cnt+acc_cnt));
  2758. FsmOutgoing(pInstance, pRsp, 0);
  2759. MemFree(pRsp);
  2760. }
  2761. /* if there are any left to send up. */
  2762. if (p_mux_tbl)
  2763. {
  2764. if (!(pTracker = alloc_link_tracker (pInstance,
  2765. API_RECV_MUX_T,
  2766. /* use the TransId.. for the sequence number */
  2767. seq_num,
  2768. API_ST_WAIT_LCLACK,
  2769. API_CH_ALLOC_UNDEF,
  2770. API_CH_TYPE_UNDEF,
  2771. 0,
  2772. H245_INVALID_CHANNEL, H245_INVALID_CHANNEL,
  2773. 0)))
  2774. {
  2775. free_mux_table_list (p_mux_tbl);
  2776. H245TRACE(pInstance->dwInst,1,"API:process_open_ind -> %s",map_api_error(H245_ERROR_NOMEM));
  2777. /* (TBC) this should be a fatal error */
  2778. H245PANIC();
  2779. break;
  2780. }
  2781. pTracker->u.MuxEntryCount = acc_cnt;
  2782. ConfInd.u.Indication.u.IndMuxTbl.Count = acc_cnt;
  2783. ConfInd.u.Indication.u.IndMuxTbl.pMuxTbl = p_mux_tbl;
  2784. if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MltmdSystmCntrlMssg_rqst.u) == H245_ERROR_NOSUP)
  2785. {
  2786. H245FunctionNotUnderstood(pInstance, pPdu);
  2787. }
  2788. free_mux_table_list (p_mux_tbl);
  2789. return H245_ERROR_OK;
  2790. }
  2791. }
  2792. break;
  2793. case H245_IND_MTSE_RELEASE:
  2794. ASSERT(pPdu->choice == indication_chosen);
  2795. ASSERT(pPdu->u.indication.choice == mltplxEntrySndRls_chosen);
  2796. break;
  2797. case H245_IND_RMESE:
  2798. ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
  2799. ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == requestMultiplexEntry_chosen);
  2800. ConfInd.u.Indication.u.IndRmese.dwCount =
  2801. pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMultiplexEntry.entryNumbers.count;
  2802. for (dwIndex = 0; dwIndex < ConfInd.u.Indication.u.IndRmese.dwCount; ++dwIndex)
  2803. {
  2804. ConfInd.u.Indication.u.IndRmese.awMultiplexTableEntryNumbers[dwIndex] =
  2805. pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMultiplexEntry.entryNumbers.value[dwIndex];
  2806. }
  2807. break;
  2808. case H245_IND_RMESE_RELEASE:
  2809. ASSERT(pPdu->choice == indication_chosen);
  2810. ASSERT(pPdu->u.indication.choice == rqstMltplxEntryRls_chosen);
  2811. break;
  2812. case H245_IND_MRSE:
  2813. ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
  2814. ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == requestMode_chosen);
  2815. ConfInd.u.Indication.u.IndMrse.pRequestedModes =
  2816. pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMode.requestedModes;
  2817. break;
  2818. case H245_IND_MRSE_RELEASE:
  2819. ASSERT(pPdu->choice == indication_chosen);
  2820. ASSERT(pPdu->u.indication.choice == requestModeRelease_chosen);
  2821. break;
  2822. case H245_IND_MLSE:
  2823. ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
  2824. ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == maintenanceLoopRequest_chosen);
  2825. ConfInd.u.Indication.u.IndMlse.LoopType =
  2826. pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.choice;
  2827. if (ConfInd.u.Indication.u.IndMlse.LoopType == systemLoop_chosen)
  2828. ConfInd.u.Indication.u.IndMlse.Channel = 0;
  2829. else
  2830. ConfInd.u.Indication.u.IndMlse.Channel =
  2831. pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.u.mediaLoop;
  2832. break;
  2833. case H245_IND_MLSE_RELEASE:
  2834. ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
  2835. ASSERT(pPdu->u.MSCMg_cmmnd.choice == mntnncLpOffCmmnd_chosen);
  2836. break;
  2837. case H245_IND_NONSTANDARD_REQUEST:
  2838. case H245_IND_NONSTANDARD_RESPONSE:
  2839. case H245_IND_NONSTANDARD_COMMAND:
  2840. case H245_IND_NONSTANDARD:
  2841. ConfInd.u.Indication.u.IndNonstandard.pData = pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.value;
  2842. ConfInd.u.Indication.u.IndNonstandard.dwDataLength = pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.length;
  2843. switch (pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.choice)
  2844. {
  2845. case object_chosen:
  2846. ConfInd.u.Indication.u.IndNonstandard.pwObjectId = awObject;
  2847. ConfInd.u.Indication.u.IndNonstandard.dwObjectIdLength =
  2848. ArrayFromObject(&awObject[0], sizeof(awObject)/sizeof(awObject[0]),
  2849. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.object);
  2850. ConfInd.u.Indication.u.IndNonstandard.byCountryCode = 0;
  2851. ConfInd.u.Indication.u.IndNonstandard.byExtension = 0;
  2852. ConfInd.u.Indication.u.IndNonstandard.wManufacturerCode = 0;
  2853. break;
  2854. case h221NonStandard_chosen:
  2855. ConfInd.u.Indication.u.IndNonstandard.pwObjectId = NULL;
  2856. ConfInd.u.Indication.u.IndNonstandard.dwObjectIdLength = 0;
  2857. ConfInd.u.Indication.u.IndNonstandard.byCountryCode = (BYTE)
  2858. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35CountryCode;
  2859. ConfInd.u.Indication.u.IndNonstandard.byExtension = (BYTE)
  2860. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35Extension;
  2861. ConfInd.u.Indication.u.IndNonstandard.wManufacturerCode =
  2862. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.manufacturerCode;
  2863. break;
  2864. default:
  2865. H245TRACE(pInstance->dwInst,1,
  2866. "H245FsmIndication: unrecognized nonstandard identifier type %d",
  2867. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.choice);
  2868. lResult = H245_ERROR_NOSUP;
  2869. } // switch
  2870. break;
  2871. case H245_IND_MISC_COMMAND:
  2872. ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
  2873. ASSERT(pPdu->u.MSCMg_cmmnd.choice == miscellaneousCommand_chosen);
  2874. break;
  2875. case H245_IND_MISC:
  2876. ASSERT(pPdu->choice == indication_chosen);
  2877. ASSERT(pPdu->u.indication.choice == miscellaneousIndication_chosen);
  2878. break;
  2879. case H245_IND_COMM_MODE_REQUEST:
  2880. ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
  2881. ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == communicationModeRequest_chosen);
  2882. break;
  2883. case H245_IND_COMM_MODE_RESPONSE:
  2884. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2885. ASSERT(pPdu->u.MSCMg_rspns.choice == cmmnctnMdRspns_chosen);
  2886. ASSERT(pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.choice == communicationModeTable_chosen);
  2887. {
  2888. unsigned int uCount;
  2889. CommunicationModeTableLink pLink;
  2890. H245_COMM_MODE_ENTRY_T * pTable;
  2891. uCount = 0;
  2892. pLink = pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.u.communicationModeTable;
  2893. while (pLink)
  2894. {
  2895. ++uCount;
  2896. pLink = pLink->next;
  2897. }
  2898. pTable = MemAlloc(uCount * sizeof(*pTable));
  2899. if (pTable)
  2900. {
  2901. ConfInd.u.Indication.u.IndCommRsp.pTable = pTable;
  2902. ConfInd.u.Indication.u.IndCommRsp.byTableCount = (BYTE)uCount;
  2903. pLink = pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.u.communicationModeTable;
  2904. while (pLink)
  2905. {
  2906. lResult = LoadCommModeEntry(pTable, &pLink->value);
  2907. if (lResult != H245_ERROR_OK)
  2908. {
  2909. MemFree(pTable);
  2910. return lResult;
  2911. }
  2912. ++pTable;
  2913. pLink = pLink->next;
  2914. }
  2915. if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MltmdSystmCntrlMssg_rqst.u) == H245_ERROR_NOSUP)
  2916. {
  2917. H245FunctionNotUnderstood(pInstance, pPdu);
  2918. }
  2919. MemFree(pTable);
  2920. H245TRACE(pInstance->dwInst,4,"H245FsmIndication -> OK");
  2921. return H245_ERROR_OK;
  2922. }
  2923. lResult = H245_ERROR_NOMEM;
  2924. }
  2925. break;
  2926. case H245_IND_COMM_MODE_COMMAND:
  2927. ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
  2928. ASSERT(pPdu->u.MSCMg_cmmnd.choice == communicationModeCommand_chosen);
  2929. {
  2930. unsigned int uCount;
  2931. CommunicationModeCommandLink pLink;
  2932. H245_COMM_MODE_ENTRY_T * pTable;
  2933. uCount = 0;
  2934. pLink = pPdu->u.MSCMg_cmmnd.u.communicationModeCommand.communicationModeTable;
  2935. while (pLink)
  2936. {
  2937. ++uCount;
  2938. pLink = pLink->next;
  2939. }
  2940. pTable = MemAlloc(uCount * sizeof(*pTable));
  2941. if (pTable)
  2942. {
  2943. ConfInd.u.Indication.u.IndCommCmd.pTable = pTable;
  2944. ConfInd.u.Indication.u.IndCommCmd.byTableCount = (BYTE)uCount;
  2945. pLink = pPdu->u.MSCMg_cmmnd.u.communicationModeCommand.communicationModeTable;
  2946. while (pLink)
  2947. {
  2948. lResult = LoadCommModeEntry(pTable, &pLink->value);
  2949. if (lResult != H245_ERROR_OK)
  2950. {
  2951. MemFree(pTable);
  2952. return lResult;
  2953. }
  2954. ++pTable;
  2955. pLink = pLink->next;
  2956. }
  2957. {
  2958. H245FunctionNotUnderstood(pInstance, pPdu);
  2959. }
  2960. if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MltmdSystmCntrlMssg_rqst.u) == H245_ERROR_NOSUP)
  2961. {
  2962. H245FunctionNotUnderstood(pInstance, pPdu);
  2963. }
  2964. MemFree(pTable);
  2965. H245TRACE(pInstance->dwInst,4,"H245FsmIndication -> OK");
  2966. return H245_ERROR_OK;
  2967. }
  2968. lResult = H245_ERROR_NOMEM;
  2969. }
  2970. break;
  2971. case H245_IND_CONFERENCE_REQUEST:
  2972. ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
  2973. ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == conferenceRequest_chosen);
  2974. ConfInd.u.Indication.u.IndConferReq.RequestType =
  2975. pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.choice;
  2976. ConfInd.u.Indication.u.IndConferReq.byMcuNumber = (BYTE)
  2977. pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.u.dropTerminal.mcuNumber;
  2978. ConfInd.u.Indication.u.IndConferReq.byTerminalNumber = (BYTE)
  2979. pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.u.dropTerminal.terminalNumber;
  2980. break;
  2981. case H245_IND_CONFERENCE_RESPONSE:
  2982. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  2983. ASSERT(pPdu->u.MSCMg_rspns.choice == conferenceResponse_chosen);
  2984. ConfInd.u.Indication.u.IndConferRsp.ResponseType =
  2985. pPdu->u.MSCMg_rspns.u.conferenceResponse.choice;
  2986. switch (pPdu->u.MSCMg_rspns.u.conferenceResponse.choice)
  2987. {
  2988. case mCTerminalIDResponse_chosen:
  2989. case terminalIDResponse_chosen:
  2990. case conferenceIDResponse_chosen:
  2991. case passwordResponse_chosen:
  2992. ConfInd.u.Indication.u.IndConferRsp.byMcuNumber = (BYTE)
  2993. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalLabel.mcuNumber;
  2994. ConfInd.u.Indication.u.IndConferRsp.byTerminalNumber = (BYTE)
  2995. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalLabel.terminalNumber;
  2996. ConfInd.u.Indication.u.IndConferRsp.pOctetString =
  2997. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalID.value;
  2998. ConfInd.u.Indication.u.IndConferRsp.byOctetStringLength = (BYTE)
  2999. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalID.length;
  3000. break;
  3001. case terminalListResponse_chosen:
  3002. ConfInd.u.Indication.u.IndConferRsp.pTerminalList =
  3003. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.terminalListResponse.value;
  3004. ConfInd.u.Indication.u.IndConferRsp.wTerminalListCount = (WORD)
  3005. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.terminalListResponse.count;
  3006. break;
  3007. case videoCommandReject_chosen:
  3008. case terminalDropReject_chosen:
  3009. break;
  3010. case makeMeChairResponse_chosen:
  3011. switch (pPdu->u.MSCMg_rspns.u.conferenceResponse.u.makeMeChairResponse.choice)
  3012. {
  3013. case grantedChairToken_chosen:
  3014. ConfInd.u.Indication.u.IndConferRsp.ResponseType = H245_RSP_GRANTED_CHAIR_TOKEN;
  3015. break;
  3016. default:
  3017. H245TRACE(pInstance->dwInst, 1,
  3018. "H245FsmIndication: Invalid make me chair response %d",
  3019. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.makeMeChairResponse.choice);
  3020. // Fall-through to next case
  3021. case deniedChairToken_chosen:
  3022. ConfInd.u.Indication.u.IndConferRsp.ResponseType = H245_RSP_DENIED_CHAIR_TOKEN;
  3023. } // switch
  3024. break;
  3025. default:
  3026. H245TRACE(pInstance->dwInst, 1,
  3027. "H245FsmIndication: Invalid Conference Response type %d",
  3028. pPdu->u.MSCMg_rspns.u.conferenceResponse.choice);
  3029. lResult = H245_ERROR_NOSUP;
  3030. } // switch
  3031. break;
  3032. case H245_IND_CONFERENCE_COMMAND:
  3033. ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
  3034. ASSERT(pPdu->u.MSCMg_cmmnd.choice == conferenceCommand_chosen);
  3035. ConfInd.u.Indication.u.IndConferCmd.CommandType =
  3036. pPdu->u.MSCMg_cmmnd.u.conferenceCommand.choice;
  3037. ConfInd.u.Indication.u.IndConferCmd.Channel =
  3038. pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.brdcstMyLgclChnnl;
  3039. ConfInd.u.Indication.u.IndConferCmd.byMcuNumber = (BYTE)
  3040. pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.sendThisSource.mcuNumber;
  3041. ConfInd.u.Indication.u.IndConferCmd.byTerminalNumber = (BYTE)
  3042. pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.sendThisSource.terminalNumber;
  3043. break;
  3044. case H245_IND_CONFERENCE:
  3045. ASSERT(pPdu->choice == indication_chosen);
  3046. ASSERT(pPdu->u.indication.choice == conferenceIndication_chosen);
  3047. ConfInd.u.Indication.u.IndConfer.IndicationType =
  3048. pPdu->u.indication.u.conferenceIndication.choice;
  3049. ConfInd.u.Indication.u.IndConfer.bySbeNumber = (BYTE)
  3050. pPdu->u.indication.u.conferenceIndication.u.sbeNumber;
  3051. ConfInd.u.Indication.u.IndConfer.byMcuNumber = (BYTE)
  3052. pPdu->u.indication.u.conferenceIndication.u.terminalNumberAssign.mcuNumber;
  3053. ConfInd.u.Indication.u.IndConfer.byTerminalNumber = (BYTE)
  3054. pPdu->u.indication.u.conferenceIndication.u.terminalNumberAssign.terminalNumber;
  3055. break;
  3056. case H245_IND_SEND_TERMCAP:
  3057. ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
  3058. ASSERT(pPdu->u.MSCMg_cmmnd.choice == sndTrmnlCpbltySt_chosen);
  3059. break;
  3060. case H245_IND_ENCRYPTION:
  3061. ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
  3062. ASSERT(pPdu->u.MSCMg_cmmnd.choice == encryptionCommand_chosen);
  3063. break;
  3064. case H245_IND_FLOW_CONTROL:
  3065. ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
  3066. ASSERT(pPdu->u.MSCMg_cmmnd.choice == flowControlCommand_chosen);
  3067. ConfInd.u.Indication.u.IndFlowControl.Scope =
  3068. pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.choice;
  3069. switch (pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.choice)
  3070. {
  3071. case FCCd_scp_lgclChnnlNmbr_chosen:
  3072. ConfInd.u.Indication.u.IndFlowControl.Channel =
  3073. pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.u.FCCd_scp_lgclChnnlNmbr;
  3074. break;
  3075. case FlwCntrlCmmnd_scp_rsrcID_chosen:
  3076. ConfInd.u.Indication.u.IndFlowControl.wResourceID =
  3077. pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.u.FlwCntrlCmmnd_scp_rsrcID;
  3078. break;
  3079. case FCCd_scp_whlMltplx_chosen:
  3080. break;
  3081. default:
  3082. H245TRACE(pInstance->dwInst, 1,
  3083. "H245FsmIndication: Invalid Flow Control restriction %d",
  3084. pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice);
  3085. lResult = H245_ERROR_NOSUP;
  3086. } // switch
  3087. switch (pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice)
  3088. {
  3089. case maximumBitRate_chosen:
  3090. ConfInd.u.Indication.u.IndFlowControl.dwRestriction =
  3091. pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.u.maximumBitRate;
  3092. break;
  3093. case noRestriction_chosen:
  3094. ConfInd.u.Indication.u.IndFlowControl.dwRestriction = H245_NO_RESTRICTION;
  3095. break;
  3096. default:
  3097. H245TRACE(pInstance->dwInst, 1,
  3098. "H245FsmIndication: Invalid Flow Control restriction %d",
  3099. pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice);
  3100. lResult = H245_ERROR_NOSUP;
  3101. } // switch
  3102. break;
  3103. case H245_IND_ENDSESSION:
  3104. ASSERT(pPdu->choice == MSCMg_cmmnd_chosen);
  3105. ASSERT(pPdu->u.MSCMg_cmmnd.choice == endSessionCommand_chosen);
  3106. ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_DISCONNECT;
  3107. switch (pPdu->u.MSCMg_cmmnd.u.endSessionCommand.choice)
  3108. {
  3109. case EndSssnCmmnd_nonStandard_chosen:
  3110. ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_NONSTD,
  3111. ConfInd.u.Indication.u.IndEndSession.SessionNonStd =
  3112. pPdu->u.MSCMg_cmmnd.u.endSessionCommand.u.EndSssnCmmnd_nonStandard;
  3113. break;
  3114. case disconnect_chosen:
  3115. break;
  3116. case gstnOptions_chosen:
  3117. switch (pPdu->u.MSCMg_cmmnd.u.endSessionCommand.u.gstnOptions.choice)
  3118. {
  3119. case EndSessionCommand_gstnOptions_telephonyMode_chosen:
  3120. ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_TELEPHONY;
  3121. break;
  3122. case v8bis_chosen:
  3123. ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_V8BIS;
  3124. break;
  3125. case v34DSVD_chosen:
  3126. ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_V34DSVD;
  3127. break;
  3128. case v34DuplexFAX_chosen:
  3129. ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_V34DUPFAX;
  3130. break;
  3131. case v34H324_chosen:
  3132. ConfInd.u.Indication.u.IndEndSession.SessionMode = H245_ENDSESSION_V34H324;
  3133. break;
  3134. default:
  3135. H245TRACE(pInstance->dwInst, 1,
  3136. "H245FsmIndication: Invalid End Session GSTN options %d",
  3137. pPdu->u.MSCMg_cmmnd.u.endSessionCommand.u.gstnOptions.choice);
  3138. } // switch
  3139. break;
  3140. default:
  3141. H245TRACE(pInstance->dwInst, 1,
  3142. "H245FsmIndication: Invalid End Session type %d",
  3143. pPdu->u.MSCMg_cmmnd.u.endSessionCommand.choice);
  3144. } // switch
  3145. break;
  3146. case H245_IND_FUNCTION_NOT_UNDERSTOOD:
  3147. ASSERT(pPdu->choice == indication_chosen);
  3148. ASSERT(pPdu->u.indication.choice == functionNotUnderstood_chosen);
  3149. break;
  3150. case H245_IND_JITTER:
  3151. ASSERT(pPdu->choice == indication_chosen);
  3152. ASSERT(pPdu->u.indication.choice == jitterIndication_chosen);
  3153. break;
  3154. case H245_IND_H223_SKEW:
  3155. ASSERT(pPdu->choice == indication_chosen);
  3156. ASSERT(pPdu->u.indication.choice == h223SkewIndication_chosen);
  3157. ConfInd.u.Indication.u.IndH223Skew.LogicalChannelNumber1 =
  3158. pPdu->u.indication.u.h223SkewIndication.logicalChannelNumber1;
  3159. ConfInd.u.Indication.u.IndH223Skew.LogicalChannelNumber2 =
  3160. pPdu->u.indication.u.h223SkewIndication.logicalChannelNumber2;
  3161. ConfInd.u.Indication.u.IndH223Skew.wSkew =
  3162. pPdu->u.indication.u.h223SkewIndication.skew;
  3163. break;
  3164. case H245_IND_NEW_ATM_VC:
  3165. ASSERT(pPdu->choice == indication_chosen);
  3166. ASSERT(pPdu->u.indication.choice == newATMVCIndication_chosen);
  3167. break;
  3168. case H245_IND_USERINPUT:
  3169. ASSERT(pPdu->choice == indication_chosen);
  3170. ASSERT(pPdu->u.indication.choice == userInput_chosen);
  3171. ConfInd.u.Indication.u.IndUserInput.Kind =
  3172. pPdu->u.indication.u.userInput.choice;
  3173. switch (pPdu->u.indication.u.userInput.choice)
  3174. {
  3175. case UsrInptIndctn_nnStndrd_chosen:
  3176. ConfInd.u.Indication.u.IndUserInput.u.NonStd =
  3177. pPdu->u.indication.u.userInput.u.UsrInptIndctn_nnStndrd;
  3178. break;
  3179. case alphanumeric_chosen:
  3180. #if 1
  3181. nLength = MultiByteToWideChar(CP_ACP, // code page
  3182. 0, // dwFlags
  3183. pPdu->u.indication.u.userInput.u.alphanumeric,
  3184. -1, // ASCII string length (in bytes)
  3185. NULL, // Unicode string
  3186. 0); // max Unicode string length
  3187. pwchar = MemAlloc(nLength * sizeof(WCHAR));
  3188. if (pwchar == NULL)
  3189. {
  3190. H245TRACE(pInstance->dwInst, 1,
  3191. "H245FsmIndication: no memory for user input", 0);
  3192. lResult = H245_ERROR_NOMEM;
  3193. }
  3194. else
  3195. {
  3196. nLength = MultiByteToWideChar(CP_ACP, // code page
  3197. 0, // dwFlags
  3198. pPdu->u.indication.u.userInput.u.alphanumeric,
  3199. -1, // ASCII string length (in bytes)
  3200. pwchar, // Unicode string
  3201. nLength); // max Unicode string length
  3202. ConfInd.u.Indication.u.IndUserInput.u.pGenString = pwchar;
  3203. }
  3204. #else
  3205. ConfInd.u.Indication.u.IndUserInput.u.pGenString =
  3206. pPdu->u.indication.u.userInput.u.alphanumeric;
  3207. #endif
  3208. break;
  3209. default:
  3210. H245TRACE(pInstance->dwInst, 1,
  3211. "H245FsmIndication: unrecognized user input type %d",
  3212. pPdu->u.indication.u.userInput.choice);
  3213. lResult = H245_ERROR_NOSUP;
  3214. } // switch
  3215. break;
  3216. case H245_IND_H2250_MAX_SKEW:
  3217. ASSERT(pPdu->choice == indication_chosen);
  3218. ASSERT(pPdu->u.indication.choice == h2250MxmmSkwIndctn_chosen);
  3219. ConfInd.u.Indication.u.IndH2250MaxSkew.LogicalChannelNumber1 =
  3220. pPdu->u.indication.u.h2250MxmmSkwIndctn.logicalChannelNumber1;
  3221. ConfInd.u.Indication.u.IndH2250MaxSkew.LogicalChannelNumber2 =
  3222. pPdu->u.indication.u.h2250MxmmSkwIndctn.logicalChannelNumber2;
  3223. ConfInd.u.Indication.u.IndH2250MaxSkew.wSkew =
  3224. pPdu->u.indication.u.h2250MxmmSkwIndctn.maximumSkew;
  3225. break;
  3226. case H245_IND_MC_LOCATION:
  3227. ASSERT(pPdu->choice == indication_chosen);
  3228. ASSERT(pPdu->u.indication.choice == mcLocationIndication_chosen);
  3229. lResult = LoadTransportAddress(&ConfInd.u.Indication.u.IndMcLocation,
  3230. &pPdu->u.indication.u.mcLocationIndication.signalAddress);
  3231. break;
  3232. case H245_IND_VENDOR_ID:
  3233. ASSERT(pPdu->choice == indication_chosen);
  3234. ASSERT(pPdu->u.indication.choice == vendorIdentification_chosen);
  3235. ConfInd.u.Indication.u.IndVendorId.Identifier =
  3236. pPdu->u.indication.u.vendorIdentification.vendor;
  3237. if (pPdu->u.indication.u.vendorIdentification.bit_mask & productNumber_present)
  3238. {
  3239. ConfInd.u.Indication.u.IndVendorId.pProductNumber =
  3240. pPdu->u.indication.u.vendorIdentification.productNumber.value;
  3241. ConfInd.u.Indication.u.IndVendorId.byProductNumberLength = (BYTE)
  3242. pPdu->u.indication.u.vendorIdentification.productNumber.length;
  3243. }
  3244. if (pPdu->u.indication.u.vendorIdentification.bit_mask & versionNumber_present)
  3245. {
  3246. ConfInd.u.Indication.u.IndVendorId.pVersionNumber =
  3247. pPdu->u.indication.u.vendorIdentification.versionNumber.value;
  3248. ConfInd.u.Indication.u.IndVendorId.byVersionNumberLength = (BYTE)
  3249. pPdu->u.indication.u.vendorIdentification.versionNumber.length;
  3250. }
  3251. break;
  3252. case H245_IND_FUNCTION_NOT_SUPPORTED:
  3253. ASSERT(pPdu->choice == indication_chosen);
  3254. ASSERT(pPdu->u.indication.choice == IndicationMessage_functionNotSupported_chosen);
  3255. ConfInd.u.Indication.u.IndFns.Cause =
  3256. pPdu->u.indication.u.functionNotSupported.cause.choice;
  3257. ConfInd.u.Indication.u.IndFns.Type = UNKNOWN;
  3258. /*if (pPdu->u.indication.u.functionNotSupported.bit_mask & returnedFunction_present)
  3259. {
  3260. int pduNum = MltmdSystmCntrlMssg_PDU;
  3261. OssBuf ossBuf;
  3262. MltmdSystmCntrlMssg *pPduReturned;
  3263. ossBuf.value = pPdu->u.indication.u.functionNotSupported.returnedFunction.value;
  3264. ossBuf.length = pPdu->u.indication.u.functionNotSupported.returnedFunction.length;
  3265. if (ossDecode(pInstance->p_ossWorld,
  3266. &pduNum,
  3267. &ossBuf,
  3268. (void * *)&pPduReturned) == PDU_DECODED)
  3269. {
  3270. switch (pPduReturned->choice)
  3271. {
  3272. case MltmdSystmCntrlMssg_rqst_chosen:
  3273. ConfInd.u.Indication.u.IndFns.Type =
  3274. pPduReturned->u.MltmdSystmCntrlMssg_rqst.choice -
  3275. RqstMssg_nonStandard_chosen + REQ_NONSTANDARD;
  3276. break;
  3277. case MSCMg_rspns_chosen:
  3278. ConfInd.u.Indication.u.IndFns.Type =
  3279. pPduReturned->u.MSCMg_rspns.choice -
  3280. RspnsMssg_nonStandard_chosen + RSP_NONSTANDARD;
  3281. break;
  3282. case MSCMg_cmmnd_chosen:
  3283. ConfInd.u.Indication.u.IndFns.Type =
  3284. pPduReturned->u.MSCMg_cmmnd.choice -
  3285. CmmndMssg_nonStandard_chosen + CMD_NONSTANDARD;
  3286. break;
  3287. case indication_chosen:
  3288. ConfInd.u.Indication.u.IndFns.Type =
  3289. pPduReturned->u.indication.choice -
  3290. IndctnMssg_nonStandard_chosen + IND_NONSTANDARD;
  3291. break;
  3292. default:
  3293. H245TRACE(pInstance->dwInst, 1,
  3294. "H245FsmIndication: unrecognized FunctionNotSupported message type %d",
  3295. pPduReturned->choice);
  3296. lResult = H245_ERROR_NOSUP;
  3297. } // switch
  3298. // Free the PDU
  3299. if (ossFreePDU(pInstance->p_ossWorld, pduNum, pPduReturned))
  3300. {
  3301. H245TRACE(pInstance->dwInst, 1, "H245FsmIndication: FREE FAILURE");
  3302. }
  3303. }
  3304. }
  3305. */
  3306. break;
  3307. #if(0) // this isn't in H245 Version 3. and this code did nothing with it anyway
  3308. case H245_IND_H223_RECONFIG:
  3309. ASSERT(pPdu->choice == MltmdSystmCntrlMssg_rqst_chosen);
  3310. ASSERT(pPdu->u.MltmdSystmCntrlMssg_rqst.choice == h223AnnxARcnfgrtn_chosen);
  3311. break;
  3312. case H245_IND_H223_RECONFIG_ACK:
  3313. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  3314. ASSERT(pPdu->u.MSCMg_rspns.choice == h223AnnxARcnfgrtnAck_chosen);
  3315. break;
  3316. case H245_IND_H223_RECONFIG_REJECT:
  3317. ASSERT(pPdu->choice == MSCMg_rspns_chosen);
  3318. ASSERT(pPdu->u.MSCMg_rspns.choice == h223AnnxARcnfgrtnRjct_chosen);
  3319. break;
  3320. #endif // if(0)
  3321. default:
  3322. /* Possible Error */
  3323. H245TRACE(pInstance->dwInst, 1,
  3324. "H245FsmIndication -> Invalid Indication Event %d", dwEvent);
  3325. lResult = H245_ERROR_SUBSYS;
  3326. } // switch
  3327. #if 1
  3328. if (pwchar)
  3329. MemFree(pwchar);
  3330. #endif
  3331. if (lResult == H245_ERROR_OK)
  3332. {
  3333. if ((*pInstance->API.ConfIndCallBack)(&ConfInd, &pPdu->u.MltmdSystmCntrlMssg_rqst.u) == H245_ERROR_NOSUP)
  3334. {
  3335. H245FunctionNotUnderstood(pInstance, pPdu);
  3336. }
  3337. H245TRACE(pInstance->dwInst,4,"H245FsmIndication -> OK");
  3338. }
  3339. else
  3340. {
  3341. H245TRACE(pInstance->dwInst,1,"H245FsmIndication -> %s", map_api_error(lResult));
  3342. }
  3343. return lResult;
  3344. } // H245FsmIndication()