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.

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