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.

642 lines
16 KiB

  1. /****************************************************************************
  2. *
  3. * $Archive: S:/STURGEON/SRC/CALLCONT/VCS/chanman.c_v $
  4. *
  5. * INTEL Corporation Prorietary Information
  6. *
  7. * This listing is supplied under the terms of a license agreement
  8. * with INTEL Corporation and may not be copied nor disclosed except
  9. * in accordance with the terms of that agreement.
  10. *
  11. * Copyright (c) 1993-1994 Intel Corporation.
  12. *
  13. * $Revision: 1.43.1.0 $
  14. * $Date: 20 Jun 1997 14:18:24 $
  15. * $Author: MANDREWS $
  16. *
  17. * Deliverable:
  18. *
  19. * Abstract:
  20. *
  21. *
  22. * Notes:
  23. *
  24. ***************************************************************************/
  25. #pragma warning ( disable : 4115 4201 4214 )
  26. #include <nt.h>
  27. #include <ntrtl.h>
  28. #include <nturtl.h>
  29. #include <windows.h>
  30. #pragma warning ( default : 4115 4201 4214 )
  31. #include "apierror.h"
  32. #include "incommon.h"
  33. #include "callcont.h"
  34. #include "q931.h"
  35. #include "ccmain.h"
  36. #include "ccutils.h"
  37. #include "listman.h"
  38. #include "q931man.h"
  39. #include "userman.h"
  40. #include "callman.h"
  41. #include "confman.h"
  42. #include "chanman.h"
  43. static BOOL bChannelInited = FALSE;
  44. static struct {
  45. PCHANNEL pHead;
  46. LOCK Lock;
  47. } ChannelTable;
  48. static struct {
  49. CC_HCHANNEL hChannel;
  50. LOCK Lock;
  51. } ChannelHandle;
  52. HRESULT InitChannelManager()
  53. {
  54. ASSERT(bChannelInited == FALSE);
  55. ChannelTable.pHead = NULL;
  56. InitializeLock(&ChannelTable.Lock);
  57. ChannelHandle.hChannel = CC_INVALID_HANDLE + 1;
  58. InitializeLock(&ChannelHandle.Lock);
  59. bChannelInited = TRUE;
  60. return CC_OK;
  61. }
  62. HRESULT DeInitChannelManager()
  63. {
  64. PCHANNEL pChannel;
  65. PCHANNEL pNextChannel;
  66. if (bChannelInited == FALSE)
  67. return CC_OK;
  68. pChannel = ChannelTable.pHead;
  69. while (pChannel != NULL) {
  70. AcquireLock(&pChannel->Lock);
  71. pNextChannel = pChannel->pNextInTable;
  72. FreeChannel(pChannel);
  73. pChannel = pNextChannel;
  74. }
  75. DeleteLock(&ChannelHandle.Lock);
  76. DeleteLock(&ChannelTable.Lock);
  77. bChannelInited = FALSE;
  78. return CC_OK;
  79. }
  80. HRESULT _AddChannelToTable( PCHANNEL pChannel)
  81. {
  82. ASSERT(pChannel != NULL);
  83. ASSERT(pChannel->hChannel != CC_INVALID_HANDLE);
  84. ASSERT(pChannel->bInTable == FALSE);
  85. AcquireLock(&ChannelTable.Lock);
  86. pChannel->pNextInTable = ChannelTable.pHead;
  87. pChannel->pPrevInTable = NULL;
  88. if (ChannelTable.pHead != NULL)
  89. ChannelTable.pHead->pPrevInTable = pChannel;
  90. ChannelTable.pHead = pChannel;
  91. pChannel->bInTable = TRUE;
  92. RelinquishLock(&ChannelTable.Lock);
  93. return CC_OK;
  94. }
  95. HRESULT _RemoveChannelFromTable( PCHANNEL pChannel)
  96. {
  97. CC_HCHANNEL hChannel;
  98. BOOL bTimedOut;
  99. ASSERT(pChannel != NULL);
  100. ASSERT(pChannel->bInTable == TRUE);
  101. // Caller must have a lock on the channel object;
  102. // in order to avoid deadlock, we must:
  103. // 1. unlock the channel object,
  104. // 2. lock the ChannelTable,
  105. // 3. locate the channel object in the ChannelTable (note that
  106. // after step 2, the channel object may be deleted from the
  107. // ChannelTable by another thread),
  108. // 4. lock the channel object (someone else may have the lock)
  109. // 5. remove the channel object from the ChannelTable,
  110. // 6. unlock the ChannelTable
  111. //
  112. // The caller can now safely unlock and destroy the channel object,
  113. // since no other thread will be able to find the object (its been
  114. // removed from the ChannelTable), and therefore no other thread will
  115. // be able to lock it.
  116. // Save the channel handle; its the only way to look up
  117. // the channel object in the ChannelTable. Note that we
  118. // can't use pChannel to find the channel object, since
  119. // pChannel may be free'd up, and another channel object
  120. // allocated at the same address
  121. hChannel = pChannel->hChannel;
  122. // step 1
  123. RelinquishLock(&pChannel->Lock);
  124. step2:
  125. // step 2
  126. AcquireLock(&ChannelTable.Lock);
  127. // step 3
  128. pChannel = ChannelTable.pHead;
  129. while ((pChannel != NULL) && (pChannel->hChannel != hChannel))
  130. pChannel = pChannel->pNextInTable;
  131. if (pChannel != NULL) {
  132. // step 4
  133. AcquireTimedLock(&pChannel->Lock,10,&bTimedOut);
  134. if (bTimedOut) {
  135. RelinquishLock(&ChannelTable.Lock);
  136. Sleep(0);
  137. goto step2;
  138. }
  139. // step 5
  140. if (pChannel->pPrevInTable == NULL)
  141. ChannelTable.pHead = pChannel->pNextInTable;
  142. else
  143. pChannel->pPrevInTable->pNextInTable = pChannel->pNextInTable;
  144. if (pChannel->pNextInTable != NULL)
  145. pChannel->pNextInTable->pPrevInTable = pChannel->pPrevInTable;
  146. pChannel->pPrevInTable = NULL;
  147. pChannel->pNextInTable = NULL;
  148. pChannel->bInTable = FALSE;
  149. }
  150. // step 6
  151. RelinquishLock(&ChannelTable.Lock);
  152. if (pChannel == NULL)
  153. return CC_BAD_PARAM;
  154. else
  155. return CC_OK;
  156. }
  157. HRESULT _MakeChannelHandle( PCC_HCHANNEL phChannel)
  158. {
  159. AcquireLock(&ChannelHandle.Lock);
  160. *phChannel = ChannelHandle.hChannel++;
  161. RelinquishLock(&ChannelHandle.Lock);
  162. return CC_OK;
  163. }
  164. HRESULT AllocAndLockChannel( PCC_HCHANNEL phChannel,
  165. PCONFERENCE pConference,
  166. CC_HCALL hCall,
  167. PCC_TERMCAP pTxTermCap,
  168. PCC_TERMCAP pRxTermCap,
  169. H245_MUX_T *pTxMuxTable,
  170. H245_MUX_T *pRxMuxTable,
  171. H245_ACCESS_T *pSeparateStack,
  172. DWORD dwUserToken,
  173. BYTE bChannelType,
  174. BYTE bSessionID,
  175. BYTE bAssociatedSessionID,
  176. WORD wRemoteChannelNumber,
  177. PCC_ADDR pLocalRTPAddr,
  178. PCC_ADDR pLocalRTCPAddr,
  179. PCC_ADDR pPeerRTPAddr,
  180. PCC_ADDR pPeerRTCPAddr,
  181. BOOL bLocallyOpened,
  182. DWORD dwBandwidth,
  183. PPCHANNEL ppChannel)
  184. {
  185. HRESULT status;
  186. ASSERT(bChannelInited == TRUE);
  187. // all parameters should have been validated by the caller
  188. ASSERT(phChannel != NULL);
  189. ASSERT(pConference != NULL);
  190. ASSERT((bChannelType == TX_CHANNEL) ||
  191. (bChannelType == RX_CHANNEL) ||
  192. (bChannelType == TXRX_CHANNEL) ||
  193. (bChannelType == PROXY_CHANNEL));
  194. ASSERT(ppChannel != NULL);
  195. // set phChannel now, in case we encounter an error
  196. *phChannel = CC_INVALID_HANDLE;
  197. *ppChannel = (PCHANNEL)Malloc(sizeof(CHANNEL));
  198. if (*ppChannel == NULL)
  199. return CC_NO_MEMORY;
  200. (*ppChannel)->bInTable = FALSE;
  201. (*ppChannel)->bMultipointChannel = FALSE;
  202. (*ppChannel)->hCall = hCall;
  203. (*ppChannel)->wNumOutstandingRequests = 0;
  204. (*ppChannel)->pTxH245TermCap = NULL;
  205. (*ppChannel)->pRxH245TermCap = NULL;
  206. (*ppChannel)->pTxMuxTable = NULL;
  207. (*ppChannel)->pRxMuxTable = NULL;
  208. (*ppChannel)->pSeparateStack = NULL;
  209. (*ppChannel)->pCloseRequests = NULL;
  210. (*ppChannel)->pLocalRTPAddr = NULL;
  211. (*ppChannel)->pLocalRTCPAddr = NULL;
  212. (*ppChannel)->pPeerRTPAddr = NULL;
  213. (*ppChannel)->pPeerRTCPAddr = NULL;
  214. (*ppChannel)->dwUserToken = dwUserToken;
  215. (*ppChannel)->hConference = pConference->hConference;
  216. (*ppChannel)->bSessionID = bSessionID;
  217. (*ppChannel)->bAssociatedSessionID = bAssociatedSessionID;
  218. (*ppChannel)->wLocalChannelNumber = 0;
  219. (*ppChannel)->wRemoteChannelNumber = 0;
  220. (*ppChannel)->bLocallyOpened = bLocallyOpened;
  221. (*ppChannel)->dwBandwidth = dwBandwidth;
  222. (*ppChannel)->pNextInTable = NULL;
  223. (*ppChannel)->pPrevInTable = NULL;
  224. (*ppChannel)->pNext = NULL;
  225. (*ppChannel)->pPrev = NULL;
  226. InitializeLock(&(*ppChannel)->Lock);
  227. AcquireLock(&(*ppChannel)->Lock);
  228. status = _MakeChannelHandle(&(*ppChannel)->hChannel);
  229. if (status != CC_OK) {
  230. FreeChannel(*ppChannel);
  231. return status;
  232. }
  233. if (bLocallyOpened == TRUE)
  234. (*ppChannel)->tsAccepted = TS_TRUE;
  235. else
  236. (*ppChannel)->tsAccepted = TS_UNKNOWN;
  237. if (pTxMuxTable != NULL) {
  238. (*ppChannel)->pTxMuxTable = (H245_MUX_T *)Malloc(sizeof(H245_MUX_T));
  239. if ((*ppChannel)->pTxMuxTable == NULL) {
  240. FreeChannel(*ppChannel);
  241. return CC_NO_MEMORY;
  242. }
  243. *(*ppChannel)->pTxMuxTable = *pTxMuxTable;
  244. }
  245. if (pRxMuxTable != NULL) {
  246. (*ppChannel)->pRxMuxTable = (H245_MUX_T *)Malloc(sizeof(H245_MUX_T));
  247. if ((*ppChannel)->pRxMuxTable == NULL) {
  248. FreeChannel(*ppChannel);
  249. return CC_NO_MEMORY;
  250. }
  251. *(*ppChannel)->pRxMuxTable = *pRxMuxTable;
  252. }
  253. if (pSeparateStack != NULL) {
  254. status = CopySeparateStack(&(*ppChannel)->pSeparateStack,
  255. pSeparateStack);
  256. if (status != CC_OK) {
  257. FreeChannel(*ppChannel);
  258. return status;
  259. }
  260. }
  261. (*ppChannel)->bChannelType = bChannelType;
  262. (*ppChannel)->bCallbackInvoked = FALSE;
  263. if (pTxTermCap != NULL) {
  264. status = H245CopyCap(&(*ppChannel)->pTxH245TermCap, pTxTermCap);
  265. if (status != H245_ERROR_OK) {
  266. FreeChannel(*ppChannel);
  267. return status;
  268. }
  269. }
  270. if (pRxTermCap != NULL) {
  271. status = H245CopyCap(&(*ppChannel)->pRxH245TermCap, pRxTermCap);
  272. if (status != H245_ERROR_OK) {
  273. FreeChannel(*ppChannel);
  274. return status;
  275. }
  276. }
  277. if (pLocalRTPAddr != NULL) {
  278. (*ppChannel)->pLocalRTPAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  279. if ((*ppChannel)->pLocalRTPAddr == NULL) {
  280. FreeChannel(*ppChannel);
  281. return CC_NO_MEMORY;
  282. }
  283. *(*ppChannel)->pLocalRTPAddr = *pLocalRTPAddr;
  284. }
  285. if (pLocalRTCPAddr != NULL) {
  286. (*ppChannel)->pLocalRTCPAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  287. if ((*ppChannel)->pLocalRTCPAddr == NULL) {
  288. FreeChannel(*ppChannel);
  289. return CC_NO_MEMORY;
  290. }
  291. *(*ppChannel)->pLocalRTCPAddr = *pLocalRTCPAddr;
  292. }
  293. if (pPeerRTPAddr != NULL) {
  294. (*ppChannel)->pPeerRTPAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  295. if ((*ppChannel)->pPeerRTPAddr == NULL) {
  296. FreeChannel(*ppChannel);
  297. return CC_NO_MEMORY;
  298. }
  299. *(*ppChannel)->pPeerRTPAddr = *pPeerRTPAddr;
  300. }
  301. if (pPeerRTCPAddr != NULL) {
  302. (*ppChannel)->pPeerRTCPAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  303. if ((*ppChannel)->pPeerRTCPAddr == NULL) {
  304. FreeChannel(*ppChannel);
  305. return CC_NO_MEMORY;
  306. }
  307. *(*ppChannel)->pPeerRTCPAddr = *pPeerRTCPAddr;
  308. }
  309. *phChannel = (*ppChannel)->hChannel;
  310. // add the conference to the conference table
  311. status = _AddChannelToTable(*ppChannel);
  312. if (status != CC_OK) {
  313. FreeChannel(*ppChannel);
  314. return status;
  315. }
  316. switch (bChannelType) {
  317. case TX_CHANNEL:
  318. status = AllocateChannelNumber(pConference, &(*ppChannel)->wLocalChannelNumber);
  319. if (status != CC_OK) {
  320. FreeChannel(*ppChannel);
  321. return status;
  322. }
  323. (*ppChannel)->wRemoteChannelNumber = 0;
  324. break;
  325. case RX_CHANNEL:
  326. (*ppChannel)->wLocalChannelNumber = 0;
  327. (*ppChannel)->wRemoteChannelNumber = wRemoteChannelNumber;
  328. break;
  329. case TXRX_CHANNEL:
  330. status = AllocateChannelNumber(pConference, &(*ppChannel)->wLocalChannelNumber);
  331. if (status != CC_OK) {
  332. FreeChannel(*ppChannel);
  333. return status;
  334. }
  335. if (bLocallyOpened)
  336. (*ppChannel)->wRemoteChannelNumber = 0;
  337. else
  338. (*ppChannel)->wRemoteChannelNumber = wRemoteChannelNumber;
  339. break;
  340. case PROXY_CHANNEL:
  341. status = AllocateChannelNumber(pConference, &(*ppChannel)->wLocalChannelNumber);
  342. if (status != CC_OK) {
  343. FreeChannel(*ppChannel);
  344. return status;
  345. }
  346. (*ppChannel)->wRemoteChannelNumber = wRemoteChannelNumber;
  347. break;
  348. default:
  349. ASSERT(0);
  350. break;
  351. }
  352. return CC_OK;
  353. }
  354. HRESULT AddLocalAddrPairToChannel( PCC_ADDR pRTPAddr,
  355. PCC_ADDR pRTCPAddr,
  356. PCHANNEL pChannel)
  357. {
  358. ASSERT(pChannel != NULL);
  359. if (pRTPAddr != NULL) {
  360. if (pChannel->pLocalRTPAddr == NULL) {
  361. pChannel->pLocalRTPAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  362. if (pChannel->pLocalRTPAddr == NULL)
  363. return CC_NO_MEMORY;
  364. }
  365. *pChannel->pLocalRTPAddr = *pRTPAddr;
  366. }
  367. if (pRTCPAddr != NULL) {
  368. if (pChannel->pLocalRTCPAddr == NULL) {
  369. pChannel->pLocalRTCPAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR));
  370. if (pChannel->pLocalRTCPAddr == NULL)
  371. return CC_NO_MEMORY;
  372. }
  373. *pChannel->pLocalRTCPAddr = *pRTCPAddr;
  374. }
  375. return CC_OK;
  376. }
  377. HRESULT AddSeparateStackToChannel( H245_ACCESS_T *pSeparateStack,
  378. PCHANNEL pChannel)
  379. {
  380. ASSERT(pSeparateStack != NULL);
  381. ASSERT(pChannel != NULL);
  382. if (pChannel->pSeparateStack != NULL)
  383. return CC_BAD_PARAM;
  384. pChannel->pSeparateStack = (H245_ACCESS_T *)Malloc(sizeof(H245_ACCESS_T));
  385. if (pChannel->pSeparateStack == NULL)
  386. return CC_NO_MEMORY;
  387. *pChannel->pSeparateStack = *pSeparateStack;
  388. return CC_OK;
  389. }
  390. // Caller must have a lock on the channel object
  391. HRESULT FreeChannel( PCHANNEL pChannel)
  392. {
  393. HRESULT status;
  394. CC_HCHANNEL hChannel;
  395. PCONFERENCE pConference;
  396. ASSERT(pChannel != NULL);
  397. // caller must have a lock on the channel object,
  398. // so there's no need to re-lock it
  399. hChannel = pChannel->hChannel;
  400. if (pChannel->hConference != CC_INVALID_HANDLE) {
  401. UnlockChannel(pChannel);
  402. status = LockChannelAndConference(hChannel, &pChannel, &pConference);
  403. if (status != CC_OK)
  404. return status;
  405. }
  406. if (pChannel->bInTable == TRUE)
  407. if (_RemoveChannelFromTable(pChannel) == CC_BAD_PARAM)
  408. // the channel object was deleted by another thread,
  409. // so just return CC_OK
  410. return CC_OK;
  411. if (pChannel->hConference != CC_INVALID_HANDLE)
  412. RemoveChannelFromConference(pChannel, pConference);
  413. if (pChannel->pSeparateStack != NULL)
  414. FreeSeparateStack(pChannel->pSeparateStack);
  415. if (pChannel->pTxMuxTable != NULL)
  416. Free(pChannel->pTxMuxTable);
  417. if (pChannel->pRxMuxTable != NULL)
  418. Free(pChannel->pRxMuxTable);
  419. if (pChannel->pTxH245TermCap != NULL)
  420. H245FreeCap(pChannel->pTxH245TermCap);
  421. if (pChannel->pRxH245TermCap != NULL)
  422. H245FreeCap(pChannel->pRxH245TermCap);
  423. while (DequeueRequest(&pChannel->pCloseRequests, NULL) == CC_OK);
  424. if (pChannel->pLocalRTPAddr != NULL)
  425. Free(pChannel->pLocalRTPAddr);
  426. if (pChannel->pLocalRTCPAddr != NULL)
  427. Free(pChannel->pLocalRTCPAddr);
  428. if (pChannel->pPeerRTPAddr != NULL)
  429. Free(pChannel->pPeerRTPAddr);
  430. if (pChannel->pPeerRTCPAddr != NULL)
  431. Free(pChannel->pPeerRTCPAddr);
  432. if (pChannel->wLocalChannelNumber != 0) {
  433. FreeChannelNumber(pConference, pChannel->wLocalChannelNumber);
  434. }
  435. if (pChannel->hConference != CC_INVALID_HANDLE)
  436. UnlockConference(pConference);
  437. // Since the channel object has been removed from the ChannelTable,
  438. // no other thread will be able to find the channel object and obtain
  439. // a lock, so its safe to unlock the channel object and delete it here
  440. RelinquishLock(&pChannel->Lock);
  441. DeleteLock(&pChannel->Lock);
  442. Free(pChannel);
  443. return CC_OK;
  444. }
  445. HRESULT LockChannel( CC_HCHANNEL hChannel,
  446. PPCHANNEL ppChannel)
  447. {
  448. BOOL bTimedOut;
  449. ASSERT(hChannel != CC_INVALID_HANDLE);
  450. ASSERT(ppChannel != NULL);
  451. step1:
  452. AcquireLock(&ChannelTable.Lock);
  453. *ppChannel = ChannelTable.pHead;
  454. while ((*ppChannel != NULL) && ((*ppChannel)->hChannel != hChannel))
  455. *ppChannel = (*ppChannel)->pNextInTable;
  456. if (*ppChannel != NULL) {
  457. AcquireTimedLock(&(*ppChannel)->Lock,10,&bTimedOut);
  458. if (bTimedOut) {
  459. RelinquishLock(&ChannelTable.Lock);
  460. Sleep(0);
  461. goto step1;
  462. }
  463. }
  464. RelinquishLock(&ChannelTable.Lock);
  465. if (*ppChannel == NULL)
  466. return CC_BAD_PARAM;
  467. else
  468. return CC_OK;
  469. }
  470. HRESULT LockChannelAndConference( CC_HCHANNEL hChannel,
  471. PPCHANNEL ppChannel,
  472. PPCONFERENCE ppConference)
  473. {
  474. HRESULT status;
  475. CC_HCONFERENCE hConference;
  476. ASSERT(hChannel != CC_INVALID_HANDLE);
  477. ASSERT(ppChannel != NULL);
  478. ASSERT(ppConference != NULL);
  479. status = LockChannel(hChannel, ppChannel);
  480. if (status != CC_OK)
  481. return status;
  482. if ((*ppChannel)->hConference == CC_INVALID_HANDLE) {
  483. UnlockChannel(*ppChannel);
  484. return CC_BAD_PARAM;
  485. }
  486. hConference = (*ppChannel)->hConference;
  487. UnlockChannel(*ppChannel);
  488. status = LockConference(hConference, ppConference);
  489. if (status != CC_OK)
  490. return status;
  491. status = LockChannel(hChannel, ppChannel);
  492. if (status != CC_OK) {
  493. UnlockConference(*ppConference);
  494. return status;
  495. }
  496. return CC_OK;
  497. }
  498. HRESULT ValidateChannel( CC_HCHANNEL hChannel)
  499. {
  500. PCHANNEL pChannel;
  501. ASSERT(hChannel != CC_INVALID_HANDLE);
  502. AcquireLock(&ChannelTable.Lock);
  503. pChannel = ChannelTable.pHead;
  504. while ((pChannel != NULL) && (pChannel->hChannel != hChannel))
  505. pChannel = pChannel->pNextInTable;
  506. RelinquishLock(&ChannelTable.Lock);
  507. if (pChannel == NULL)
  508. return CC_BAD_PARAM;
  509. else
  510. return CC_OK;
  511. }
  512. HRESULT UnlockChannel( PCHANNEL pChannel)
  513. {
  514. ASSERT(pChannel != NULL);
  515. RelinquishLock(&pChannel->Lock);
  516. return CC_OK;
  517. }