Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

830 lines
18 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. channel.c
  5. Abstract:
  6. Routines to manipulate H.245 logical channels.
  7. Environment:
  8. User Mode - Win32
  9. Revision History:
  10. --*/
  11. ///////////////////////////////////////////////////////////////////////////////
  12. // //
  13. // Include files //
  14. // //
  15. ///////////////////////////////////////////////////////////////////////////////
  16. #include "globals.h"
  17. #include "termcaps.h"
  18. #include "callback.h"
  19. #include "line.h"
  20. ///////////////////////////////////////////////////////////////////////////////
  21. // //
  22. // Private procedures //
  23. // //
  24. ///////////////////////////////////////////////////////////////////////////////
  25. BOOL
  26. H323ResetChannel(
  27. PH323_CHANNEL pChannel
  28. )
  29. /*++
  30. Routine Description:
  31. Resets channel object original state for re-use.
  32. Arguments:
  33. pChannel - Pointer to channel object to reset.
  34. Return Values:
  35. Returns true if successful.
  36. --*/
  37. {
  38. // change channel state to allocated
  39. pChannel->nState = H323_CHANNELSTATE_ALLOCATED;
  40. // initialize stream description
  41. memset(&pChannel->Settings,0,sizeof(STREAMSETTINGS));
  42. // uninitialize msp channel handle
  43. pChannel->hmChannel = NULL;
  44. // uninitialize channel handle
  45. pChannel->hccChannel = UNINITIALIZED;
  46. // reset local addresses and sync up RTCP ports
  47. pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr = 0;
  48. pChannel->ccLocalRTCPAddr.Addr.IP_Binary.dwAddr = 0;
  49. pChannel->ccLocalRTCPAddr.Addr.IP_Binary.wPort =
  50. pChannel->ccLocalRTPAddr.Addr.IP_Binary.wPort + 1;
  51. // reset remote addresses (including port numbers)
  52. pChannel->ccRemoteRTPAddr.Addr.IP_Binary.dwAddr = 0;
  53. pChannel->ccRemoteRTPAddr.Addr.IP_Binary.wPort = 0;
  54. pChannel->ccRemoteRTCPAddr.Addr.IP_Binary.dwAddr = 0;
  55. pChannel->ccRemoteRTCPAddr.Addr.IP_Binary.wPort = 0;
  56. // initialize caps
  57. memset(&pChannel->ccTermCaps,0,sizeof(CC_TERMCAP));
  58. // initialize other info
  59. pChannel->bPayloadType = (BYTE)UNINITIALIZED;
  60. pChannel->bSessionID = (BYTE)UNINITIALIZED;
  61. // initialize direction
  62. pChannel->fInbound = FALSE;
  63. // success
  64. return TRUE;
  65. }
  66. BOOL
  67. H323AllocChannel(
  68. PH323_CHANNEL * ppChannel
  69. )
  70. /*++
  71. Routine Description:
  72. Allocates new channel object.
  73. Arguments:
  74. ppChannel - Pointer to DWORD-sized value in which service provider
  75. must place the newly allocated channel object.
  76. Return Values:
  77. Returns true if successful.
  78. --*/
  79. {
  80. PH323_CHANNEL pChannel = NULL;
  81. // allocate channel object
  82. pChannel = H323HeapAlloc(sizeof(H323_CHANNEL));
  83. // validate pointer
  84. if (pChannel == NULL) {
  85. H323DBG((
  86. DEBUG_LEVEL_ERROR,
  87. "could not allocate channel object.\n"
  88. ));
  89. // failure
  90. return FALSE;
  91. }
  92. H323DBG((
  93. DEBUG_LEVEL_VERBOSE,
  94. "channel 0x%08lx allocated.\n",
  95. pChannel
  96. ));
  97. // reset channel object
  98. H323ResetChannel(pChannel);
  99. // transfer pointer
  100. *ppChannel = pChannel;
  101. // success
  102. return TRUE;
  103. }
  104. BOOL
  105. H323FreeChannel(
  106. PH323_CHANNEL pChannel
  107. )
  108. /*++
  109. Routine Description:
  110. Release memory associated with channel.
  111. Arguments:
  112. pChannel - Pointer to channel to release.
  113. Return Values:
  114. Returns true if successful.
  115. --*/
  116. {
  117. // release memory
  118. H323HeapFree(pChannel);
  119. H323DBG((
  120. DEBUG_LEVEL_VERBOSE,
  121. "channel 0x%08lx released.\n",
  122. pChannel
  123. ));
  124. // success
  125. return TRUE;
  126. }
  127. ///////////////////////////////////////////////////////////////////////////////
  128. // //
  129. // Public procedures //
  130. // //
  131. ///////////////////////////////////////////////////////////////////////////////
  132. BOOL
  133. H323OpenChannel(
  134. PH323_CHANNEL pChannel
  135. )
  136. /*++
  137. Routine Description:
  138. Opens channel to destination address.
  139. Arguments:
  140. pChannel - Pointer to channel to open.
  141. Return Values:
  142. Returns true if successful.
  143. --*/
  144. {
  145. HRESULT hr;
  146. // open channel
  147. hr = CC_OpenChannel(
  148. pChannel->pCall->hccConf, // hConference
  149. &pChannel->hccChannel, // phChannel
  150. pChannel->bSessionID, // bSessionID
  151. 0, // bAssociatedSessionID
  152. TRUE, // bSilenceSuppression
  153. &pChannel->ccTermCaps, // pTermCap
  154. &pChannel->ccLocalRTCPAddr, // pLocalRTCPAddr
  155. 0, // bDynamicRTPPayloadType
  156. 0, // dwChannelBitRate
  157. PtrToUlong(pChannel->pCall->hdCall) // dwUserToken
  158. );
  159. // validate
  160. if (hr != CC_OK) {
  161. H323DBG((
  162. DEBUG_LEVEL_ERROR,
  163. "error %s (0x%08lx) opening channel 0x%08lx.\n",
  164. H323StatusToString((DWORD)hr), hr,
  165. pChannel
  166. ));
  167. // failure
  168. return FALSE;
  169. }
  170. // change channel state to opening
  171. pChannel->nState = H323_CHANNELSTATE_OPENING;
  172. H323DBG((
  173. DEBUG_LEVEL_VERBOSE,
  174. "channel 0x%08lx opening.\n",
  175. pChannel
  176. ));
  177. // success
  178. return TRUE;
  179. }
  180. BOOL
  181. H323CloseChannel(
  182. PH323_CHANNEL pChannel
  183. )
  184. /*++
  185. Routine Description:
  186. Closes channel.
  187. Arguments:
  188. pChannel - Pointer to channel to close.
  189. Return Values:
  190. Returns true if successful.
  191. --*/
  192. {
  193. HRESULT hr;
  194. // see if channel opened
  195. if (H323IsChannelOpen(pChannel) &&
  196. H323IsCallActive(pChannel->pCall)) {
  197. // give peer close channel indication
  198. hr = CC_CloseChannel(pChannel->hccChannel);
  199. // validate status
  200. if (hr != CC_OK) {
  201. H323DBG((
  202. DEBUG_LEVEL_ERROR,
  203. "error %s (0x%08lx) closing channel 0x%08lx.\n",
  204. H323StatusToString((DWORD)hr), hr,
  205. pChannel
  206. ));
  207. //
  208. // Could not close channel so just
  209. // mark as closed and continue...
  210. //
  211. }
  212. }
  213. // mark entry as allocated
  214. H323FreeChannelFromTable(pChannel,pChannel->pCall->pChannelTable);
  215. H323DBG((
  216. DEBUG_LEVEL_VERBOSE,
  217. "channel 0x%08lx closed.\n",
  218. pChannel
  219. ));
  220. // success
  221. return TRUE;
  222. }
  223. BOOL
  224. H323AllocChannelTable(
  225. PH323_CHANNEL_TABLE * ppChannelTable
  226. )
  227. /*++
  228. Routine Description:
  229. Allocates table of channel objects.
  230. Arguments:
  231. ppChannelTable - Pointer to DWORD-sized value which service
  232. provider must fill in with newly allocated table.
  233. Return Values:
  234. Returns true if successful.
  235. --*/
  236. {
  237. PH323_CHANNEL_TABLE pChannelTable;
  238. // allocate table from heap
  239. pChannelTable = H323HeapAlloc(
  240. sizeof(H323_CHANNEL_TABLE) +
  241. sizeof(PH323_CHANNEL) * H323_DEFMEDIAPERCALL
  242. );
  243. // validate table pointer
  244. if (pChannelTable == NULL) {
  245. H323DBG((
  246. DEBUG_LEVEL_ERROR,
  247. "could not allocate channel table.\n"
  248. ));
  249. // failure
  250. return FALSE;
  251. }
  252. // initialize number of entries in table
  253. pChannelTable->dwNumSlots = H323_DEFMEDIAPERCALL;
  254. // transfer pointer to caller
  255. *ppChannelTable = pChannelTable;
  256. // success
  257. return TRUE;
  258. }
  259. BOOL
  260. H323FreeChannelTable(
  261. PH323_CHANNEL_TABLE pChannelTable
  262. )
  263. /*++
  264. Routine Description:
  265. Deallocates table of channel objects.
  266. Arguments:
  267. pChannelTable - Pointer to channel table to release.
  268. Return Values:
  269. Returns true if successful.
  270. --*/
  271. {
  272. DWORD i;
  273. // loop through each object in table
  274. for (i = 0; i < pChannelTable->dwNumSlots; i++) {
  275. // validate object has been allocated
  276. if (H323IsChannelAllocated(pChannelTable->pChannels[i])) {
  277. // release memory for object
  278. H323FreeChannel(pChannelTable->pChannels[i]);
  279. }
  280. }
  281. // release memory for table
  282. H323HeapFree(pChannelTable);
  283. // success
  284. return TRUE;
  285. }
  286. BOOL
  287. H323CloseChannelTable(
  288. PH323_CHANNEL_TABLE pChannelTable
  289. )
  290. /*++
  291. Routine Description:
  292. Closes table of channel objects.
  293. Arguments:
  294. pChannelTable - Pointer to channel table to close.
  295. Return Values:
  296. Returns true if successful.
  297. --*/
  298. {
  299. DWORD i;
  300. // loop through each object in table
  301. for (i = 0; i < pChannelTable->dwNumSlots; i++) {
  302. // validate object is in use
  303. if (H323IsChannelInUse(pChannelTable->pChannels[i])) {
  304. // close channel object
  305. H323CloseChannel(pChannelTable->pChannels[i]);
  306. }
  307. }
  308. // success
  309. return TRUE;
  310. }
  311. BOOL
  312. H323AllocChannelFromTable(
  313. PH323_CHANNEL * ppChannel,
  314. PH323_CHANNEL_TABLE * ppChannelTable,
  315. PH323_CALL pCall
  316. )
  317. /*++
  318. Routine Description:
  319. Allocates channel object in table.
  320. Arguments:
  321. ppChannel - Specifies a pointer to a DWORD-sized value in which the
  322. service provider must write the allocated channel object.
  323. ppChannelTable - Pointer to pointer to channel table in which to
  324. allocate channel from (expands table if necessary).
  325. pCall - Pointer to containing call object.
  326. Return Values:
  327. Returns true if successful.
  328. --*/
  329. {
  330. DWORD i;
  331. PH323_CHANNEL pChannel = NULL;
  332. PH323_CHANNEL_TABLE pChannelTable = *ppChannelTable;
  333. // retrieve index to next entry
  334. i = pChannelTable->dwNextAvailable;
  335. // see if previously allocated entries available
  336. if (pChannelTable->dwNumAllocated > pChannelTable->dwNumInUse) {
  337. // search table looking for available entry
  338. while (H323IsChannelInUse(pChannelTable->pChannels[i]) ||
  339. !H323IsChannelAllocated(pChannelTable->pChannels[i])) {
  340. // increment index and adjust to wrap
  341. i = H323GetNextIndex(i, pChannelTable->dwNumSlots);
  342. }
  343. // retrieve pointer to object
  344. pChannel = pChannelTable->pChannels[i];
  345. // mark entry as being in use
  346. pChannel->nState = H323_CHANNELSTATE_CLOSED;
  347. // re-initialize rtp address
  348. pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr =
  349. H323IsCallInbound(pCall)
  350. ? pCall->ccCalleeAddr.Addr.IP_Binary.dwAddr
  351. : pCall->ccCallerAddr.Addr.IP_Binary.dwAddr
  352. ;
  353. // re-initialize rtcp address
  354. pChannel->ccLocalRTCPAddr.Addr.IP_Binary.dwAddr =
  355. pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr;
  356. // increment number in use
  357. pChannelTable->dwNumInUse++;
  358. // adjust next available index
  359. pChannelTable->dwNextAvailable =
  360. H323GetNextIndex(i, pChannelTable->dwNumSlots);
  361. // transfer pointer
  362. *ppChannel = pChannel;
  363. // success
  364. return TRUE;
  365. }
  366. // see if table is full and more slots need to be allocated
  367. if (pChannelTable->dwNumAllocated == pChannelTable->dwNumSlots) {
  368. // attempt to double table
  369. pChannelTable = H323HeapReAlloc(
  370. pChannelTable,
  371. sizeof(H323_CHANNEL_TABLE) +
  372. pChannelTable->dwNumSlots * 2 * sizeof(PH323_CHANNEL)
  373. );
  374. // validate pointer
  375. if (pChannelTable == NULL) {
  376. H323DBG((
  377. DEBUG_LEVEL_ERROR,
  378. "could not expand channel table.\n"
  379. ));
  380. // failure
  381. return FALSE;
  382. }
  383. // adjust index into table
  384. i = pChannelTable->dwNumSlots;
  385. // adjust number of slots
  386. pChannelTable->dwNumSlots *= 2;
  387. // transfer pointer to caller
  388. *ppChannelTable = pChannelTable;
  389. }
  390. // allocate new object
  391. if (!H323AllocChannel(&pChannel)) {
  392. // failure
  393. return FALSE;
  394. }
  395. // search table looking for slot with no object allocated
  396. while (H323IsChannelAllocated(pChannelTable->pChannels[i])) {
  397. // increment index and adjust to wrap
  398. i = H323GetNextIndex(i, pChannelTable->dwNumSlots);
  399. }
  400. // store pointer to object
  401. pChannelTable->pChannels[i] = pChannel;
  402. // mark entry as being in use
  403. pChannel->nState = H323_CHANNELSTATE_CLOSED;
  404. // initialize rtp address
  405. pChannel->ccLocalRTPAddr.nAddrType = CC_IP_BINARY;
  406. pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr =
  407. H323IsCallInbound(pCall)
  408. ? pCall->ccCalleeAddr.Addr.IP_Binary.dwAddr
  409. : pCall->ccCallerAddr.Addr.IP_Binary.dwAddr
  410. ;
  411. pChannel->ccLocalRTPAddr.Addr.IP_Binary.wPort =
  412. LOWORD(pCall->pLine->dwNextPort++);
  413. pChannel->ccLocalRTPAddr.bMulticast = FALSE;
  414. // initialize rtcp address
  415. pChannel->ccLocalRTCPAddr.nAddrType = CC_IP_BINARY;
  416. pChannel->ccLocalRTCPAddr.Addr.IP_Binary.dwAddr =
  417. pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr;
  418. pChannel->ccLocalRTCPAddr.Addr.IP_Binary.wPort =
  419. LOWORD(pCall->pLine->dwNextPort++);
  420. pChannel->ccLocalRTCPAddr.bMulticast = FALSE;
  421. // increment number in use
  422. pChannelTable->dwNumInUse++;
  423. // increment number allocated
  424. pChannelTable->dwNumAllocated++;
  425. // adjust next available index
  426. pChannelTable->dwNextAvailable =
  427. H323GetNextIndex(i, pChannelTable->dwNumSlots);
  428. #if DBG
  429. {
  430. DWORD dwIPAddr;
  431. dwIPAddr = htonl(pChannel->ccLocalRTPAddr.Addr.IP_Binary.dwAddr);
  432. H323DBG((
  433. DEBUG_LEVEL_VERBOSE,
  434. "channel 0x%08lx stored in slot %d (%s:%d).\n",
  435. pChannel, i,
  436. H323AddrToString(dwIPAddr),
  437. pChannel->ccLocalRTPAddr.Addr.IP_Binary.wPort
  438. ));
  439. }
  440. #endif
  441. // transfer pointer
  442. *ppChannel = pChannel;
  443. // success
  444. return TRUE;
  445. }
  446. BOOL
  447. H323FreeChannelFromTable(
  448. PH323_CHANNEL pChannel,
  449. PH323_CHANNEL_TABLE pChannelTable
  450. )
  451. /*++
  452. Routine Description:
  453. Deallocates channel object in table.
  454. Arguments:
  455. pChannel - Pointer to object to deallocate.
  456. pChannelTable - Pointer to table containing object.
  457. Return Values:
  458. Returns true if successful.
  459. --*/
  460. {
  461. // reset channel object
  462. H323ResetChannel(pChannel);
  463. // decrement entries in use
  464. pChannelTable->dwNumInUse--;
  465. // success
  466. return TRUE;
  467. }
  468. BOOL
  469. H323LookupChannelByHandle(
  470. PH323_CHANNEL * ppChannel,
  471. PH323_CHANNEL_TABLE pChannelTable,
  472. CC_HCHANNEL hccChannel
  473. )
  474. /*++
  475. Routine Description:
  476. Looks up channel based on handle returned from call control module.
  477. Arguments:
  478. ppChannel - Specifies a pointer to a DWORD-sized value in which the
  479. service provider must write the channel associated with the
  480. call control handle specified.
  481. pChannelTable - Pointer to channel table to search.
  482. hccChannel - Handle return by call control module.
  483. Return Values:
  484. Returns true if successful.
  485. --*/
  486. {
  487. DWORD i;
  488. // loop through each channel in table
  489. for (i = 0; i < pChannelTable->dwNumSlots; i++) {
  490. // see if channel handle matches the one specified
  491. if (H323IsChannelEqual(pChannelTable->pChannels[i],hccChannel)) {
  492. // tranfer channel pointer to caller
  493. *ppChannel = pChannelTable->pChannels[i];
  494. // success
  495. return TRUE;
  496. }
  497. }
  498. // failure
  499. return FALSE;
  500. }
  501. BOOL
  502. H323LookupChannelBySessionID(
  503. PH323_CHANNEL * ppChannel,
  504. PH323_CHANNEL_TABLE pChannelTable,
  505. BYTE bSessionID
  506. )
  507. /*++
  508. Routine Description:
  509. Looks up channel based on session ID negotiated.
  510. Arguments:
  511. ppChannel - Specifies a pointer to a DWORD-sized value in which the
  512. service provider must write the channel associated with the
  513. call control handle specified.
  514. pChannelTable - Pointer to channel table to search.
  515. bSessionID - session id.
  516. Return Values:
  517. Returns true if successful.
  518. --*/
  519. {
  520. DWORD i;
  521. // loop through each channel in table
  522. for (i = 0; i < pChannelTable->dwNumSlots; i++) {
  523. // see if channel handle matches the one specified
  524. if (H323IsSessionIDEqual(pChannelTable->pChannels[i],bSessionID)) {
  525. // tranfer channel pointer to caller
  526. *ppChannel = pChannelTable->pChannels[i];
  527. // success
  528. return TRUE;
  529. }
  530. }
  531. // failure
  532. return FALSE;
  533. }
  534. BOOL
  535. H323AreThereOutgoingChannels(
  536. PH323_CHANNEL_TABLE pChannelTable,
  537. BOOL fIgnoreOpenChannels
  538. )
  539. /*++
  540. Routine Description:
  541. Searchs for outgoing channel objects.
  542. Arguments:
  543. pChannelTable - Pointer to channel table to search.
  544. fIgnoreOpenChannels - Restricts search to unopened channels.
  545. Return Values:
  546. Returns true if successful.
  547. --*/
  548. {
  549. DWORD i;
  550. BOOL fFoundOk = FALSE;
  551. // loop through each channel in table
  552. for (i = 0; i < pChannelTable->dwNumSlots; i++) {
  553. // see if channel is in use and outbound
  554. if (H323IsChannelInUse(pChannelTable->pChannels[i]) &&
  555. !H323IsChannelInbound(pChannelTable->pChannels[i]) &&
  556. (!H323IsChannelOpen(pChannelTable->pChannels[i]) ||
  557. !fIgnoreOpenChannels)) {
  558. // success
  559. return TRUE;
  560. }
  561. }
  562. // failure
  563. return FALSE;
  564. }