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.

956 lines
29 KiB

  1. /****************************************************************************
  2. *
  3. * $Archive: S:/STURGEON/SRC/Q931/VCS/hcall.cpv $
  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-1996 Intel Corporation.
  12. *
  13. * $Revision: 2.7 $
  14. * $Date: 28 Jan 1997 11:17:52 $
  15. * $Author: jdashevx $
  16. *
  17. * Deliverable:
  18. *
  19. * Abstract:
  20. *
  21. *
  22. * Notes:
  23. *
  24. ***************************************************************************/
  25. #pragma warning ( disable : 4100 4115 4201 4214 4514 4702 4710 )
  26. #include "precomp.h"
  27. #include <string.h>
  28. #include <time.h>
  29. #include "h225asn.h"
  30. #include "isrg.h"
  31. #include "common.h"
  32. #include "q931.h"
  33. #include "hcall.h"
  34. #include "utils.h"
  35. #include "tstable.h"
  36. #ifdef UNICODE_TRACE
  37. // We include this header to fix problems with macro expansion when Unicode is turned on.
  38. #include "unifix.h"
  39. #endif
  40. // variable needed to support ISR debug facility.
  41. #if defined(_DEBUG)
  42. extern WORD ghISRInst;
  43. #endif
  44. static BOOL bCallListCreated = FALSE;
  45. // Pointer to our global table. Note that this table replaces the previous
  46. // linked-list implementation.
  47. TSTable<CALL_OBJECT>* gpCallObjectTable = NULL;
  48. // Our call back function for enumerating the table when we want to tear down
  49. // all existing calls
  50. DWORD Q931HangUpAllCalls(P_CALL_OBJECT pCallObject, LPVOID context);
  51. // Our call back function for determining if a timer has expired
  52. DWORD Q931CheckForTimeout(P_CALL_OBJECT pCallObject, LPVOID context);
  53. // Our call back function for determining if a timer has expired
  54. DWORD Q931CallObjectFind(P_CALL_OBJECT pCallObject, LPVOID context);
  55. static struct
  56. {
  57. WORD wCRV; // Call Reference Value (0..7FFF).
  58. CRITICAL_SECTION Lock;
  59. } CRVSource;
  60. static struct
  61. {
  62. BOOL bBusy;
  63. DWORD dwTimerCount;
  64. DWORD dwTicks301;
  65. DWORD dwTicks303;
  66. UINT_PTR uTimerId;
  67. CRITICAL_SECTION Lock;
  68. } Q931GlobalTimer = {0};
  69. typedef struct
  70. {
  71. BOOL bFound;
  72. WORD wCRV;
  73. PCC_ADDR pPeerAddr;
  74. HQ931CALL hQ931Call;
  75. } Q931CALLOBJKEY, *PQ931CALLOBJKEY;
  76. //====================================================================================
  77. //
  78. // PRIVATE FUNCTIONS
  79. //
  80. //====================================================================================
  81. //====================================================================================
  82. //====================================================================================
  83. CS_STATUS
  84. Q931CRVNew(
  85. WORD *pwCRV)
  86. {
  87. EnterCriticalSection(&(CRVSource.Lock));
  88. CRVSource.wCRV = (WORD)((CRVSource.wCRV + 1) & 0x7fff);
  89. if (CRVSource.wCRV == 0)
  90. {
  91. CRVSource.wCRV = 1;
  92. }
  93. *pwCRV = CRVSource.wCRV;
  94. LeaveCriticalSection(&(CRVSource.Lock));
  95. return CS_OK;
  96. }
  97. //====================================================================================
  98. //
  99. // PUBLIC FUNCTIONS
  100. //
  101. //====================================================================================
  102. //====================================================================================
  103. //====================================================================================
  104. CS_STATUS
  105. CallListCreate()
  106. {
  107. if (bCallListCreated == TRUE)
  108. {
  109. ASSERT(FALSE);
  110. return CS_DUPLICATE_INITIALIZE;
  111. }
  112. // list creation is not protected against multiple threads because it is only
  113. // called when a process is started, not when a thread is started.
  114. //
  115. // LAURABU
  116. // BOGUS BUGBUG
  117. //
  118. // This table code was never stressed by the people who wrote it. It
  119. // totally falls apart when it completely fills up
  120. // * Allocating the last item doesn't work
  121. // * Freeing the last item doesn't work
  122. // * Resizing larger doesn't work
  123. //
  124. // Since it doesn't take a lot of memory, a decent solution is to just
  125. // allocate it maximum+1 sized, and leave the last item free.
  126. //
  127. gpCallObjectTable = new TSTable <CALL_OBJECT> (258);
  128. if (gpCallObjectTable == NULL || gpCallObjectTable->IsInitialized() == FALSE)
  129. {
  130. return CS_NO_MEMORY;
  131. }
  132. CRVSource.wCRV = (WORD) (time(NULL) & 0x7fff);
  133. InitializeCriticalSection(&(CRVSource.Lock));
  134. Q931GlobalTimer.dwTicks301 = Q931_TICKS_301;
  135. Q931GlobalTimer.dwTicks303 = Q931_TICKS_303;
  136. InitializeCriticalSection(&(Q931GlobalTimer.Lock));
  137. bCallListCreated = TRUE;
  138. return CS_OK;
  139. }
  140. //====================================================================================
  141. // this routine assumes all of the events and sockets belonging to each object
  142. // are already destroyed. It just makes sure memory is cleaned up.
  143. //====================================================================================
  144. CS_STATUS
  145. CallListDestroy()
  146. {
  147. if (bCallListCreated == FALSE)
  148. {
  149. ASSERT(FALSE);
  150. return CS_INTERNAL_ERROR;
  151. }
  152. // For all entries, hang up the calls
  153. gpCallObjectTable->EnumerateEntries(Q931HangUpAllCalls,
  154. NULL);
  155. // Get rid of the call object table
  156. delete gpCallObjectTable;
  157. gpCallObjectTable = NULL;
  158. DeleteCriticalSection(&(Q931GlobalTimer.Lock));
  159. DeleteCriticalSection(&(CRVSource.Lock));
  160. bCallListCreated = FALSE;
  161. return CS_OK;
  162. }
  163. //====================================================================================
  164. //====================================================================================
  165. void
  166. CallObjectFree(P_CALL_OBJECT pCallObject)
  167. {
  168. if (pCallObject->NonStandardData.sData.pOctetString != NULL)
  169. {
  170. MemFree(pCallObject->NonStandardData.sData.pOctetString);
  171. pCallObject->NonStandardData.sData.pOctetString = NULL;
  172. }
  173. if (pCallObject->VendorInfoPresent)
  174. {
  175. if (pCallObject->VendorInfo.pProductNumber != NULL)
  176. {
  177. MemFree(pCallObject->VendorInfo.pProductNumber);
  178. }
  179. if (pCallObject->VendorInfo.pVersionNumber != NULL)
  180. {
  181. MemFree(pCallObject->VendorInfo.pVersionNumber);
  182. }
  183. }
  184. Q931FreeAliasNames(pCallObject->pCallerAliasList);
  185. pCallObject->pCallerAliasList = NULL;
  186. Q931FreeAliasNames(pCallObject->pCalleeAliasList);
  187. pCallObject->pCalleeAliasList = NULL;
  188. Q931FreeAliasNames(pCallObject->pExtraAliasList);
  189. pCallObject->pExtraAliasList = NULL;
  190. Q931FreeAliasItem(pCallObject->pExtensionAliasItem);
  191. pCallObject->pExtensionAliasItem = NULL;
  192. MemFree(pCallObject);
  193. }
  194. //====================================================================================
  195. //====================================================================================
  196. CS_STATUS
  197. CallObjectCreate(
  198. PHQ931CALL phQ931Call,
  199. DWORD_PTR dwListenToken,
  200. DWORD_PTR dwUserToken,
  201. Q931_CALLBACK ConnectCallback,
  202. BOOL fIsCaller,
  203. CC_ADDR *pLocalAddr, // Local address on which channel is connected
  204. CC_ADDR *pPeerConnectAddr, // Address to which channel is connected
  205. CC_ADDR *pPeerCallAddr, // Address of opposite call end-point.
  206. CC_ADDR *pSourceAddr, // Address of this call end-point.
  207. CC_CONFERENCEID *pConferenceID,
  208. WORD wGoal,
  209. WORD wCallType,
  210. BOOL bCallerIsMC,
  211. char *pszDisplay,
  212. char *pszCalledPartyNumber,
  213. PCC_ALIASNAMES pCallerAliasList,
  214. PCC_ALIASNAMES pCalleeAliasList,
  215. PCC_ALIASNAMES pExtraAliasList,
  216. PCC_ALIASITEM pExtensionAliasItem,
  217. PCC_ENDPOINTTYPE pEndpointType,
  218. PCC_NONSTANDARDDATA pNonStandardData, // questionable!
  219. WORD wCRV,
  220. LPGUID pCallIdentifier)
  221. {
  222. P_CALL_OBJECT pCallObject = NULL;
  223. CS_STATUS status = CS_OK;
  224. CS_STATUS CopyStatus = CS_OK;
  225. DWORD dwIndex = 0;
  226. int rc = 0;
  227. // make sure the call list has been created.
  228. if (bCallListCreated == FALSE)
  229. {
  230. ASSERT(FALSE);
  231. return CS_INTERNAL_ERROR;
  232. }
  233. // validate all parameters for bogus values.
  234. if ((phQ931Call == NULL) || (ConnectCallback == NULL))
  235. {
  236. ASSERT(FALSE);
  237. return CS_BAD_PARAM;
  238. }
  239. // set phQ931Call now, in case we encounter an error later.
  240. *phQ931Call = 0;
  241. pCallObject = (P_CALL_OBJECT)MemAlloc(sizeof(CALL_OBJECT));
  242. if (pCallObject == NULL)
  243. {
  244. return CS_NO_MEMORY;
  245. }
  246. memset(pCallObject, 0, sizeof(CALL_OBJECT));
  247. // create and init an oss world struct for each call object. This is
  248. // necessary to work in MT environments.
  249. rc = Q931_InitWorld(&pCallObject->World);
  250. if (rc != ASN1_SUCCESS)
  251. {
  252. #if defined(_DEBUG)
  253. ISRERROR(ghISRInst, "Q931_InitCoder() returned: %d ", rc);
  254. #endif
  255. return CS_SUBSYSTEM_FAILURE;
  256. }
  257. pCallObject->LocalAddr.bMulticast = FALSE;
  258. pCallObject->PeerConnectAddr.bMulticast = FALSE;
  259. pCallObject->PeerCallAddr.bMulticast = FALSE;
  260. pCallObject->SourceAddr.bMulticast = FALSE;
  261. if(pCallIdentifier)
  262. {
  263. memcpy(&pCallObject->CallIdentifier, pCallIdentifier, sizeof(GUID));
  264. }
  265. if (wCRV == 0)
  266. {
  267. if (Q931CRVNew(&pCallObject->wCRV) != CS_OK)
  268. {
  269. CallObjectFree(pCallObject);
  270. return CS_INTERNAL_ERROR;
  271. }
  272. }
  273. else
  274. {
  275. pCallObject->wCRV = wCRV;
  276. }
  277. pCallObject->szDisplay[0] = '\0';
  278. if (pszDisplay)
  279. {
  280. strcpy(pCallObject->szDisplay, pszDisplay);
  281. }
  282. pCallObject->szCalledPartyNumber[0] = '\0';
  283. if (pszCalledPartyNumber)
  284. {
  285. strcpy(pCallObject->szCalledPartyNumber, pszCalledPartyNumber);
  286. }
  287. pCallObject->dwListenToken = dwListenToken;
  288. pCallObject->dwUserToken = dwUserToken;
  289. pCallObject->Callback = ConnectCallback;
  290. pCallObject->bCallState = CALLSTATE_NULL;
  291. pCallObject->fIsCaller = fIsCaller;
  292. if (pLocalAddr)
  293. {
  294. pCallObject->LocalAddr = *pLocalAddr;
  295. }
  296. if (pPeerConnectAddr)
  297. {
  298. pCallObject->PeerConnectAddr = *pPeerConnectAddr;
  299. }
  300. if (pPeerCallAddr)
  301. {
  302. pCallObject->PeerCallAddr = *pPeerCallAddr;
  303. pCallObject->PeerCallAddrPresent = TRUE;
  304. }
  305. else
  306. {
  307. pCallObject->PeerCallAddrPresent = FALSE;
  308. }
  309. if (pSourceAddr)
  310. {
  311. pCallObject->SourceAddr = *pSourceAddr;
  312. pCallObject->SourceAddrPresent = TRUE;
  313. }
  314. else
  315. {
  316. pCallObject->SourceAddrPresent = FALSE;
  317. }
  318. if (pConferenceID == NULL)
  319. {
  320. memset(&(pCallObject->ConferenceID), 0, sizeof(CC_CONFERENCEID));
  321. }
  322. else
  323. {
  324. int length = min(sizeof(pConferenceID->buffer),
  325. sizeof(pCallObject->ConferenceID.buffer));
  326. memcpy(pCallObject->ConferenceID.buffer,
  327. pConferenceID->buffer, length);
  328. }
  329. pCallObject->wGoal = wGoal;
  330. pCallObject->bCallerIsMC = bCallerIsMC;
  331. pCallObject->wCallType = wCallType;
  332. if (pNonStandardData != NULL)
  333. {
  334. pCallObject->NonStandardData = *pNonStandardData;
  335. if (pNonStandardData->sData.wOctetStringLength > 0)
  336. {
  337. pCallObject->NonStandardData.sData.pOctetString =
  338. (BYTE *) MemAlloc(pNonStandardData->sData.wOctetStringLength);
  339. if (pCallObject->NonStandardData.sData.pOctetString == NULL)
  340. {
  341. CallObjectFree(pCallObject);
  342. return CS_NO_MEMORY;
  343. }
  344. memcpy(pCallObject->NonStandardData.sData.pOctetString,
  345. pNonStandardData->sData.pOctetString,
  346. pNonStandardData->sData.wOctetStringLength);
  347. }
  348. pCallObject->NonStandardDataPresent = TRUE;
  349. }
  350. else
  351. {
  352. pCallObject->NonStandardDataPresent = FALSE;
  353. }
  354. CopyStatus = Q931CopyAliasNames(&(pCallObject->pCallerAliasList),
  355. pCallerAliasList);
  356. if (CopyStatus != CS_OK)
  357. {
  358. CallObjectFree(pCallObject);
  359. return CopyStatus;
  360. }
  361. CopyStatus = Q931CopyAliasNames(&(pCallObject->pCalleeAliasList),
  362. pCalleeAliasList);
  363. if (CopyStatus != CS_OK)
  364. {
  365. CallObjectFree(pCallObject);
  366. return CopyStatus;
  367. }
  368. CopyStatus = Q931CopyAliasNames(&(pCallObject->pExtraAliasList),
  369. pExtraAliasList);
  370. if (CopyStatus != CS_OK)
  371. {
  372. CallObjectFree(pCallObject);
  373. return CopyStatus;
  374. }
  375. CopyStatus = Q931CopyAliasItem(&(pCallObject->pExtensionAliasItem),
  376. pExtensionAliasItem);
  377. if (CopyStatus != CS_OK)
  378. {
  379. CallObjectFree(pCallObject);
  380. return CopyStatus;
  381. }
  382. pCallObject->bResolved = FALSE;
  383. pCallObject->VendorInfoPresent = FALSE;
  384. pCallObject->bIsTerminal = TRUE;
  385. pCallObject->bIsGateway = FALSE;
  386. if (pEndpointType != NULL)
  387. {
  388. PCC_VENDORINFO pVendorInfo = pEndpointType->pVendorInfo;
  389. if (pVendorInfo != NULL)
  390. {
  391. pCallObject->VendorInfoPresent = TRUE;
  392. pCallObject->VendorInfo = *(pVendorInfo);
  393. if (pVendorInfo->pProductNumber && pVendorInfo->pProductNumber->pOctetString &&
  394. pVendorInfo->pProductNumber->wOctetStringLength)
  395. {
  396. memcpy(pCallObject->bufVendorProduct,
  397. pVendorInfo->pProductNumber->pOctetString,
  398. pVendorInfo->pProductNumber->wOctetStringLength);
  399. pCallObject->VendorInfo.pProductNumber = (CC_OCTETSTRING*) MemAlloc(sizeof(CC_OCTETSTRING));
  400. if (pCallObject->VendorInfo.pProductNumber == NULL)
  401. {
  402. CallObjectFree(pCallObject);
  403. return CS_NO_MEMORY;
  404. }
  405. pCallObject->VendorInfo.pProductNumber->pOctetString =
  406. pCallObject->bufVendorProduct;
  407. pCallObject->VendorInfo.pProductNumber->wOctetStringLength =
  408. pVendorInfo->pProductNumber->wOctetStringLength;
  409. }
  410. else
  411. {
  412. pCallObject->VendorInfo.pProductNumber = NULL;
  413. }
  414. if (pVendorInfo->pVersionNumber && pVendorInfo->pVersionNumber->pOctetString &&
  415. pVendorInfo->pVersionNumber->wOctetStringLength)
  416. {
  417. memcpy(pCallObject->bufVendorVersion,
  418. pVendorInfo->pVersionNumber->pOctetString,
  419. pVendorInfo->pVersionNumber->wOctetStringLength);
  420. pCallObject->VendorInfo.pVersionNumber = (CC_OCTETSTRING*) MemAlloc(sizeof(CC_OCTETSTRING));
  421. if (pCallObject->VendorInfo.pVersionNumber == NULL)
  422. {
  423. CallObjectFree(pCallObject);
  424. return CS_NO_MEMORY;
  425. }
  426. pCallObject->VendorInfo.pVersionNumber->pOctetString =
  427. pCallObject->bufVendorVersion;
  428. pCallObject->VendorInfo.pVersionNumber->wOctetStringLength =
  429. pVendorInfo->pVersionNumber->wOctetStringLength;
  430. }
  431. else
  432. {
  433. pCallObject->VendorInfo.pVersionNumber = NULL;
  434. }
  435. }
  436. pCallObject->bIsTerminal = pEndpointType->bIsTerminal;
  437. pCallObject->bIsGateway = pEndpointType->bIsGateway;
  438. }
  439. Q931MakePhysicalID(&pCallObject->dwPhysicalId);
  440. // Insert the object into the table...if that doesn't work, blow away the object.
  441. if (gpCallObjectTable->CreateAndLock(pCallObject,
  442. &dwIndex) == FALSE)
  443. {
  444. CallObjectFree(pCallObject);
  445. return CS_INTERNAL_ERROR;
  446. }
  447. // Save the index as the handle (this makes it easier to find the object later).
  448. *phQ931Call = pCallObject->hQ931Call = (HQ931CALL) dwIndex;
  449. #if defined(_DEBUG)
  450. ISRTRACE(ghISRInst, "CallObjectCreate() -returned-> 0x%.8x", dwIndex);
  451. #endif
  452. // Unlock the entry
  453. gpCallObjectTable->Unlock(dwIndex);
  454. return CS_OK;
  455. }
  456. //====================================================================================
  457. //====================================================================================
  458. CS_STATUS
  459. CallObjectDestroy(
  460. P_CALL_OBJECT pCallObject)
  461. {
  462. if (pCallObject == NULL)
  463. {
  464. ASSERT(FALSE);
  465. return CS_BAD_PARAM;
  466. }
  467. #if defined (_DEBUG)
  468. ISRTRACE(ghISRInst, "CallObjectDestroy(0x%.8x)", (DWORD)pCallObject->hQ931Call);
  469. #endif
  470. Q931_TermWorld(&pCallObject->World);
  471. // Since the caller must already have a lock on the object, remove the entry from
  472. // the table. We won't let the table delete the object as we want to clean up.
  473. if (gpCallObjectTable->Delete((DWORD) pCallObject->hQ931Call) == FALSE)
  474. {
  475. return CS_OK;
  476. }
  477. Q931StopTimer(pCallObject, Q931_TIMER_301);
  478. Q931StopTimer(pCallObject, Q931_TIMER_303);
  479. // Unlock the object
  480. gpCallObjectTable->Unlock((DWORD) pCallObject->hQ931Call);
  481. // Free up the call object
  482. CallObjectFree(pCallObject);
  483. return CS_OK;
  484. }
  485. //====================================================================================
  486. //====================================================================================
  487. CS_STATUS
  488. CallObjectLock(
  489. HQ931CALL hQ931Call,
  490. PP_CALL_OBJECT ppCallObject)
  491. {
  492. if (ppCallObject == NULL)
  493. {
  494. ASSERT(FALSE);
  495. return CS_BAD_PARAM;
  496. }
  497. // Attempt to lock the entry. If that fails, we'll return CS_BAD_PARAM under
  498. // the assumption that the entry is invalid.
  499. *ppCallObject = gpCallObjectTable->Lock((DWORD) hQ931Call);
  500. return (*ppCallObject == NULL ? CS_BAD_PARAM : CS_OK);
  501. }
  502. //====================================================================================
  503. //====================================================================================
  504. CS_STATUS
  505. CallObjectUnlock(
  506. P_CALL_OBJECT pCallObject)
  507. {
  508. if (pCallObject == NULL)
  509. {
  510. ASSERT(FALSE);
  511. return CS_BAD_PARAM;
  512. }
  513. return CallEntryUnlock(pCallObject->hQ931Call);
  514. }
  515. //====================================================================================
  516. //====================================================================================
  517. CS_STATUS
  518. CallEntryUnlock(
  519. HQ931CALL hQ931Call)
  520. {
  521. // Unlock the entry
  522. if (gpCallObjectTable->Unlock(hQ931Call) == FALSE)
  523. {
  524. #if defined(_DEBUG)
  525. ISRERROR(ghISRInst, "gpCallObjectTable->Unlock(0x%.8x) FAILED!!!!", (DWORD)hQ931Call);
  526. #endif
  527. return CS_BAD_PARAM;
  528. }
  529. return CS_OK;
  530. }
  531. //====================================================================================
  532. //====================================================================================
  533. CS_STATUS
  534. CallObjectValidate(
  535. HQ931CALL hQ931Call)
  536. {
  537. if (gpCallObjectTable->Validate((DWORD) hQ931Call) == TRUE)
  538. {
  539. return CS_OK;
  540. }
  541. return CS_BAD_PARAM;
  542. }
  543. //====================================================================================
  544. //====================================================================================
  545. BOOL
  546. CallObjectFind(
  547. HQ931CALL *phQ931Call,
  548. WORD wCRV,
  549. PCC_ADDR pPeerAddr)
  550. {
  551. Q931CALLOBJKEY Q931CallObjKey;
  552. Q931CallObjKey.wCRV = wCRV;
  553. Q931CallObjKey.pPeerAddr = pPeerAddr;
  554. Q931CallObjKey.bFound = FALSE;
  555. gpCallObjectTable->EnumerateEntries(Q931CallObjectFind,
  556. (LPVOID) &Q931CallObjKey);
  557. if(Q931CallObjKey.bFound == TRUE)
  558. {
  559. *phQ931Call = Q931CallObjKey.hQ931Call;
  560. return TRUE;
  561. }
  562. return FALSE;
  563. }
  564. //====================================================================================
  565. //====================================================================================
  566. CS_STATUS CallObjectMarkForDelete(HQ931CALL hQ931Call)
  567. {
  568. // User must have the object already locked to call this.
  569. // Mark the object as deleted but don't let the table delete the object's
  570. // memory.
  571. return (gpCallObjectTable->Delete((DWORD) hQ931Call) == FALSE ? CS_BAD_PARAM : CS_OK);
  572. }
  573. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  574. // Timer Routines...
  575. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  576. //====================================================================================
  577. // This routine will be called every 1000 ms if any call object
  578. // has caused the Q931GlobalTimer to be created.
  579. //====================================================================================
  580. VOID CALLBACK
  581. Q931TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
  582. {
  583. DWORD dwTickCount = GetTickCount();
  584. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  585. if (Q931GlobalTimer.bBusy)
  586. {
  587. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  588. return;
  589. }
  590. Q931GlobalTimer.bBusy = TRUE;
  591. // Check all of the entries for timeout
  592. gpCallObjectTable->EnumerateEntries(Q931CheckForTimeout,
  593. (LPVOID) &dwTickCount);
  594. Q931GlobalTimer.bBusy = FALSE;
  595. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  596. }
  597. //====================================================================================
  598. //====================================================================================
  599. HRESULT
  600. Q931StartTimer(P_CALL_OBJECT pCallObject, DWORD wTimerId)
  601. {
  602. if (pCallObject == NULL)
  603. {
  604. return CS_BAD_PARAM;
  605. }
  606. switch (wTimerId)
  607. {
  608. case Q931_TIMER_301:
  609. if (pCallObject->dwTimerAlarm301)
  610. {
  611. // timer is already set for this call object...
  612. return CS_INTERNAL_ERROR;
  613. }
  614. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  615. pCallObject->dwTimerAlarm301 = GetTickCount() + Q931GlobalTimer.dwTicks301;
  616. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  617. break;
  618. case Q931_TIMER_303:
  619. if (pCallObject->dwTimerAlarm303)
  620. {
  621. // timer is already set for this call object...
  622. return CS_INTERNAL_ERROR;
  623. }
  624. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  625. pCallObject->dwTimerAlarm303 = GetTickCount() + Q931GlobalTimer.dwTicks303;
  626. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  627. break;
  628. default:
  629. return CS_BAD_PARAM;
  630. break;
  631. }
  632. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  633. if (!Q931GlobalTimer.dwTimerCount)
  634. {
  635. Q931GlobalTimer.uTimerId = SetTimer(NULL, 0, 1000, (TIMERPROC)Q931TimerProc);
  636. }
  637. Q931GlobalTimer.dwTimerCount++;
  638. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  639. return CS_OK;
  640. }
  641. //====================================================================================
  642. //====================================================================================
  643. HRESULT
  644. Q931StopTimer(P_CALL_OBJECT pCallObject, DWORD wTimerId)
  645. {
  646. if (pCallObject == NULL)
  647. {
  648. return CS_BAD_PARAM;
  649. }
  650. switch (wTimerId)
  651. {
  652. case Q931_TIMER_301:
  653. if (!pCallObject->dwTimerAlarm301)
  654. {
  655. return CS_OK;
  656. }
  657. pCallObject->dwTimerAlarm301 = 0;
  658. break;
  659. case Q931_TIMER_303:
  660. if (!pCallObject->dwTimerAlarm303)
  661. {
  662. return CS_OK;
  663. }
  664. pCallObject->dwTimerAlarm303 = 0;
  665. break;
  666. default:
  667. return CS_BAD_PARAM;
  668. break;
  669. }
  670. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  671. if (Q931GlobalTimer.dwTimerCount > 0)
  672. {
  673. Q931GlobalTimer.dwTimerCount--;
  674. if (!Q931GlobalTimer.dwTimerCount)
  675. {
  676. KillTimer(NULL, Q931GlobalTimer.uTimerId);
  677. Q931GlobalTimer.uTimerId = 0;
  678. }
  679. }
  680. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  681. return CS_OK;
  682. }
  683. //====================================================================================
  684. //====================================================================================
  685. CS_STATUS
  686. Q931SetAlertingTimeout(DWORD dwDuration)
  687. {
  688. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  689. if (dwDuration)
  690. {
  691. Q931GlobalTimer.dwTicks303 = dwDuration;
  692. }
  693. else
  694. {
  695. Q931GlobalTimer.dwTicks303 = Q931_TICKS_303;
  696. }
  697. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  698. return CS_OK;
  699. }
  700. //====================================================================================
  701. //====================================================================================
  702. DWORD Q931HangUpAllCalls(P_CALL_OBJECT pCallObject, LPVOID context)
  703. {
  704. HQ931CALL hQ931Call = pCallObject->hQ931Call;
  705. // Try to hangup the call object.
  706. Q931Hangup(hQ931Call, CC_REJECT_NORMAL_CALL_CLEARING);
  707. // Try to lock the object. If that succeeds, then we want to force the object to
  708. // be deleted. We should never have to do this as the hang up is supposed to
  709. // take care of that for us.
  710. if (gpCallObjectTable->Lock(hQ931Call) != NULL)
  711. {
  712. CallObjectDestroy(pCallObject);
  713. }
  714. return CALLBACK_DELETE_ENTRY;
  715. }
  716. //====================================================================================
  717. //====================================================================================
  718. DWORD
  719. Q931CallObjectFind(P_CALL_OBJECT pCallObject, LPVOID context)
  720. {
  721. PQ931CALLOBJKEY pQ931CallObjKey = (PQ931CALLOBJKEY) context;
  722. PCC_ADDR pPeerAddr = pQ931CallObjKey->pPeerAddr;
  723. WORD wCRV = pQ931CallObjKey->wCRV;
  724. if (!pCallObject->bResolved)
  725. {
  726. return(CALLBACK_CONTINUE);
  727. }
  728. if ((pCallObject->wCRV & (~0x8000)) == (wCRV & (~0x8000)))
  729. {
  730. if (!pPeerAddr)
  731. {
  732. pQ931CallObjKey->bFound = TRUE;
  733. pQ931CallObjKey->hQ931Call = pCallObject->hQ931Call;
  734. return(CALLBACK_ABORT);
  735. }
  736. else if ((pCallObject->PeerConnectAddr.nAddrType == CC_IP_BINARY) &&
  737. (pPeerAddr->nAddrType == CC_IP_BINARY) &&
  738. (pCallObject->PeerConnectAddr.Addr.IP_Binary.dwAddr == pPeerAddr->Addr.IP_Binary.dwAddr))
  739. {
  740. pQ931CallObjKey->bFound = TRUE;
  741. pQ931CallObjKey->hQ931Call = pCallObject->hQ931Call;
  742. return(CALLBACK_ABORT);
  743. }
  744. }
  745. return(CALLBACK_CONTINUE);
  746. }
  747. //====================================================================================
  748. //====================================================================================
  749. DWORD Q931CheckForTimeout(P_CALL_OBJECT pCallObject, LPVOID context)
  750. {
  751. DWORD dwTickCount = *((LPDWORD) context);
  752. // Determine if a timer has expired for the entry
  753. if (pCallObject->dwTimerAlarm301 &&
  754. (pCallObject->dwTimerAlarm301 <= dwTickCount))
  755. {
  756. Q931StopTimer(pCallObject, Q931_TIMER_301);
  757. Q931StopTimer(pCallObject, Q931_TIMER_303);
  758. if (pCallObject->dwTimerAlarm303 &&
  759. (pCallObject->dwTimerAlarm303 < pCallObject->dwTimerAlarm301) &&
  760. (pCallObject->dwTimerAlarm303 <= dwTickCount))
  761. {
  762. CallBackT303(pCallObject);
  763. }
  764. else
  765. {
  766. CallBackT301(pCallObject);
  767. }
  768. }
  769. else if (pCallObject->dwTimerAlarm303 &&
  770. (pCallObject->dwTimerAlarm303 <= dwTickCount))
  771. {
  772. Q931StopTimer(pCallObject, Q931_TIMER_301);
  773. Q931StopTimer(pCallObject, Q931_TIMER_303);
  774. CallBackT303(pCallObject);
  775. }
  776. return CALLBACK_CONTINUE;
  777. }
  778. /***************************************************************************
  779. *
  780. * NAME
  781. * HangupPendingCalls - Hangs up incoming calls from specified destination
  782. *
  783. * DESCRIPTION
  784. * This function will hang up all calls in waiting
  785. * from the specified destination to prevent DOS attacks
  786. * that would fill up the call object table.
  787. *
  788. * PARAMETERS
  789. * pCallObject Current enumerated call object
  790. * context Callback parameter representing source IP address
  791. *
  792. * RETURN VALUE
  793. * CALLBACK_ABORT Stop enumerating calls
  794. * CALLBACK_CONTINUE Continue enumerating calls
  795. *
  796. ***************************************************************************/
  797. DWORD Q931HangupPendingCallsCallback(P_CALL_OBJECT pCallObject, LPVOID context)
  798. {
  799. ASSERT(NULL != pCallObject);
  800. // Only hang up incoming calls
  801. if(FALSE == pCallObject->fIsCaller)
  802. {
  803. if(CALLSTATE_INITIATED == pCallObject->bCallState)
  804. {
  805. Q931Hangup(pCallObject->hQ931Call, CC_REJECT_SECURITY_DENIED);
  806. }
  807. }
  808. return CALLBACK_CONTINUE;
  809. }
  810. HRESULT Q931HangupPendingCalls(LPVOID context)
  811. {
  812. gpCallObjectTable->EnumerateEntries(Q931HangupPendingCallsCallback, context);
  813. return NOERROR;
  814. }