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.

947 lines
27 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> (257);
  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. // Unlock the entry
  514. if (gpCallObjectTable->Unlock((DWORD) pCallObject->hQ931Call) == FALSE)
  515. {
  516. #if defined(_DEBUG)
  517. ISRERROR(ghISRInst, "gpCallObjectTable->Unlock(0x%.8x) FAILED!!!!", (DWORD)pCallObject->hQ931Call);
  518. #endif
  519. return CS_BAD_PARAM;
  520. }
  521. return CS_OK;
  522. }
  523. //====================================================================================
  524. //====================================================================================
  525. CS_STATUS
  526. CallObjectValidate(
  527. HQ931CALL hQ931Call)
  528. {
  529. if (gpCallObjectTable->Validate((DWORD) hQ931Call) == TRUE)
  530. {
  531. return CS_OK;
  532. }
  533. return CS_BAD_PARAM;
  534. }
  535. //====================================================================================
  536. //====================================================================================
  537. BOOL
  538. CallObjectFind(
  539. HQ931CALL *phQ931Call,
  540. WORD wCRV,
  541. PCC_ADDR pPeerAddr)
  542. {
  543. Q931CALLOBJKEY Q931CallObjKey;
  544. Q931CallObjKey.wCRV = wCRV;
  545. Q931CallObjKey.pPeerAddr = pPeerAddr;
  546. Q931CallObjKey.bFound = FALSE;
  547. gpCallObjectTable->EnumerateEntries(Q931CallObjectFind,
  548. (LPVOID) &Q931CallObjKey);
  549. if(Q931CallObjKey.bFound == TRUE)
  550. {
  551. *phQ931Call = Q931CallObjKey.hQ931Call;
  552. return TRUE;
  553. }
  554. return FALSE;
  555. }
  556. //====================================================================================
  557. //====================================================================================
  558. CS_STATUS CallObjectMarkForDelete(HQ931CALL hQ931Call)
  559. {
  560. // User must have the object already locked to call this.
  561. // Mark the object as deleted but don't let the table delete the object's
  562. // memory.
  563. return (gpCallObjectTable->Delete((DWORD) hQ931Call) == FALSE ? CS_BAD_PARAM : CS_OK);
  564. }
  565. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  566. // Timer Routines...
  567. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  568. //====================================================================================
  569. // This routine will be called every 1000 ms if any call object
  570. // has caused the Q931GlobalTimer to be created.
  571. //====================================================================================
  572. VOID CALLBACK
  573. Q931TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
  574. {
  575. DWORD dwTickCount = GetTickCount();
  576. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  577. if (Q931GlobalTimer.bBusy)
  578. {
  579. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  580. return;
  581. }
  582. Q931GlobalTimer.bBusy = TRUE;
  583. // Check all of the entries for timeout
  584. gpCallObjectTable->EnumerateEntries(Q931CheckForTimeout,
  585. (LPVOID) &dwTickCount);
  586. Q931GlobalTimer.bBusy = FALSE;
  587. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  588. }
  589. //====================================================================================
  590. //====================================================================================
  591. HRESULT
  592. Q931StartTimer(P_CALL_OBJECT pCallObject, DWORD wTimerId)
  593. {
  594. if (pCallObject == NULL)
  595. {
  596. return CS_BAD_PARAM;
  597. }
  598. switch (wTimerId)
  599. {
  600. case Q931_TIMER_301:
  601. if (pCallObject->dwTimerAlarm301)
  602. {
  603. // timer is already set for this call object...
  604. return CS_INTERNAL_ERROR;
  605. }
  606. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  607. pCallObject->dwTimerAlarm301 = GetTickCount() + Q931GlobalTimer.dwTicks301;
  608. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  609. break;
  610. case Q931_TIMER_303:
  611. if (pCallObject->dwTimerAlarm303)
  612. {
  613. // timer is already set for this call object...
  614. return CS_INTERNAL_ERROR;
  615. }
  616. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  617. pCallObject->dwTimerAlarm303 = GetTickCount() + Q931GlobalTimer.dwTicks303;
  618. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  619. break;
  620. default:
  621. return CS_BAD_PARAM;
  622. break;
  623. }
  624. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  625. if (!Q931GlobalTimer.dwTimerCount)
  626. {
  627. Q931GlobalTimer.uTimerId = SetTimer(NULL, 0, 1000, (TIMERPROC)Q931TimerProc);
  628. }
  629. Q931GlobalTimer.dwTimerCount++;
  630. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  631. return CS_OK;
  632. }
  633. //====================================================================================
  634. //====================================================================================
  635. HRESULT
  636. Q931StopTimer(P_CALL_OBJECT pCallObject, DWORD wTimerId)
  637. {
  638. if (pCallObject == NULL)
  639. {
  640. return CS_BAD_PARAM;
  641. }
  642. switch (wTimerId)
  643. {
  644. case Q931_TIMER_301:
  645. if (!pCallObject->dwTimerAlarm301)
  646. {
  647. return CS_OK;
  648. }
  649. pCallObject->dwTimerAlarm301 = 0;
  650. break;
  651. case Q931_TIMER_303:
  652. if (!pCallObject->dwTimerAlarm303)
  653. {
  654. return CS_OK;
  655. }
  656. pCallObject->dwTimerAlarm303 = 0;
  657. break;
  658. default:
  659. return CS_BAD_PARAM;
  660. break;
  661. }
  662. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  663. if (Q931GlobalTimer.dwTimerCount > 0)
  664. {
  665. Q931GlobalTimer.dwTimerCount--;
  666. if (!Q931GlobalTimer.dwTimerCount)
  667. {
  668. KillTimer(NULL, Q931GlobalTimer.uTimerId);
  669. Q931GlobalTimer.uTimerId = 0;
  670. }
  671. }
  672. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  673. return CS_OK;
  674. }
  675. //====================================================================================
  676. //====================================================================================
  677. CS_STATUS
  678. Q931SetAlertingTimeout(DWORD dwDuration)
  679. {
  680. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  681. if (dwDuration)
  682. {
  683. Q931GlobalTimer.dwTicks303 = dwDuration;
  684. }
  685. else
  686. {
  687. Q931GlobalTimer.dwTicks303 = Q931_TICKS_303;
  688. }
  689. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  690. return CS_OK;
  691. }
  692. //====================================================================================
  693. //====================================================================================
  694. DWORD Q931HangUpAllCalls(P_CALL_OBJECT pCallObject, LPVOID context)
  695. {
  696. HQ931CALL hQ931Call = pCallObject->hQ931Call;
  697. // Try to hangup the call object.
  698. Q931Hangup(hQ931Call, CC_REJECT_NORMAL_CALL_CLEARING);
  699. // Try to lock the object. If that succeeds, then we want to force the object to
  700. // be deleted. We should never have to do this as the hang up is supposed to
  701. // take care of that for us.
  702. if (gpCallObjectTable->Lock(hQ931Call) != NULL)
  703. {
  704. CallObjectDestroy(pCallObject);
  705. }
  706. return CALLBACK_DELETE_ENTRY;
  707. }
  708. //====================================================================================
  709. //====================================================================================
  710. DWORD
  711. Q931CallObjectFind(P_CALL_OBJECT pCallObject, LPVOID context)
  712. {
  713. PQ931CALLOBJKEY pQ931CallObjKey = (PQ931CALLOBJKEY) context;
  714. PCC_ADDR pPeerAddr = pQ931CallObjKey->pPeerAddr;
  715. WORD wCRV = pQ931CallObjKey->wCRV;
  716. if (!pCallObject->bResolved)
  717. {
  718. return(CALLBACK_CONTINUE);
  719. }
  720. if ((pCallObject->wCRV & (~0x8000)) == (wCRV & (~0x8000)))
  721. {
  722. if (!pPeerAddr)
  723. {
  724. pQ931CallObjKey->bFound = TRUE;
  725. pQ931CallObjKey->hQ931Call = pCallObject->hQ931Call;
  726. return(CALLBACK_ABORT);
  727. }
  728. else if ((pCallObject->PeerConnectAddr.nAddrType == CC_IP_BINARY) &&
  729. (pPeerAddr->nAddrType == CC_IP_BINARY) &&
  730. (pCallObject->PeerConnectAddr.Addr.IP_Binary.dwAddr == pPeerAddr->Addr.IP_Binary.dwAddr))
  731. {
  732. pQ931CallObjKey->bFound = TRUE;
  733. pQ931CallObjKey->hQ931Call = pCallObject->hQ931Call;
  734. return(CALLBACK_ABORT);
  735. }
  736. }
  737. return(CALLBACK_CONTINUE);
  738. }
  739. //====================================================================================
  740. //====================================================================================
  741. DWORD Q931CheckForTimeout(P_CALL_OBJECT pCallObject, LPVOID context)
  742. {
  743. DWORD dwTickCount = *((LPDWORD) context);
  744. // Determine if a timer has expired for the entry
  745. if (pCallObject->dwTimerAlarm301 &&
  746. (pCallObject->dwTimerAlarm301 <= dwTickCount))
  747. {
  748. Q931StopTimer(pCallObject, Q931_TIMER_301);
  749. Q931StopTimer(pCallObject, Q931_TIMER_303);
  750. if (pCallObject->dwTimerAlarm303 &&
  751. (pCallObject->dwTimerAlarm303 < pCallObject->dwTimerAlarm301) &&
  752. (pCallObject->dwTimerAlarm303 <= dwTickCount))
  753. {
  754. CallBackT303(pCallObject);
  755. }
  756. else
  757. {
  758. CallBackT301(pCallObject);
  759. }
  760. }
  761. else if (pCallObject->dwTimerAlarm303 &&
  762. (pCallObject->dwTimerAlarm303 <= dwTickCount))
  763. {
  764. Q931StopTimer(pCallObject, Q931_TIMER_301);
  765. Q931StopTimer(pCallObject, Q931_TIMER_303);
  766. CallBackT303(pCallObject);
  767. }
  768. return CALLBACK_CONTINUE;
  769. }
  770. /***************************************************************************
  771. *
  772. * NAME
  773. * HangupPendingCalls - Hangs up incoming calls from specified destination
  774. *
  775. * DESCRIPTION
  776. * This function will hang up all calls in waiting
  777. * from the specified destination to prevent DOS attacks
  778. * that would fill up the call object table.
  779. *
  780. * PARAMETERS
  781. * pCallObject Current enumerated call object
  782. * context Callback parameter representing source IP address
  783. *
  784. * RETURN VALUE
  785. * CALLBACK_ABORT Stop enumerating calls
  786. * CALLBACK_CONTINUE Continue enumerating calls
  787. *
  788. ***************************************************************************/
  789. DWORD Q931HangupPendingCallsCallback(P_CALL_OBJECT pCallObject, LPVOID context)
  790. {
  791. ASSERT(NULL != pCallObject);
  792. // Only hang up incoming calls
  793. if(FALSE == pCallObject->fIsCaller)
  794. {
  795. if(CALLSTATE_INITIATED == pCallObject->bCallState)
  796. {
  797. Q931Hangup(pCallObject->hQ931Call, CC_REJECT_SECURITY_DENIED);
  798. }
  799. }
  800. return CALLBACK_CONTINUE;
  801. }
  802. HRESULT Q931HangupPendingCalls(LPVOID context)
  803. {
  804. gpCallObjectTable->EnumerateEntries(Q931HangupPendingCallsCallback, context);
  805. return NOERROR;
  806. }