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.

909 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.1.0 $
  14. * $Date: 20 Jun 1997 14:12:08 $
  15. * $Author: MANDREWS $
  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 <nt.h>
  27. #include <ntrtl.h>
  28. #include <nturtl.h>
  29. #include <windows.h>
  30. #include <string.h>
  31. #include <time.h>
  32. #include "q931asn.h"
  33. #include "isrg.h"
  34. #include "common.h"
  35. #include "q931.h"
  36. #include "hcall.h"
  37. #include "utils.h"
  38. #include "tstable.h"
  39. #include "provider.h"
  40. #ifdef UNICODE_TRACE
  41. // We include this header to fix problems with macro expansion when Unicode is turned on.
  42. #include "unifix.h"
  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. // Create the call object table. We will initially create 30 entries. The
  115. // TSTable can automatically grow, so no worrying about running out of entries.
  116. gpCallObjectTable = new TSTable <CALL_OBJECT> (30);
  117. if (gpCallObjectTable == NULL || gpCallObjectTable->IsInitialized() == FALSE)
  118. {
  119. return CS_NO_MEMORY;
  120. }
  121. __try {
  122. CRVSource.wCRV = (WORD) (time(NULL) & 0x7fff);
  123. InitializeCriticalSectionAndSpinCount(&(CRVSource.Lock),H323_SPIN_COUNT);
  124. Q931GlobalTimer.dwTicks301 = Q931_TICKS_301;
  125. Q931GlobalTimer.dwTicks303 = Q931_TICKS_303;
  126. InitializeCriticalSectionAndSpinCount(&(Q931GlobalTimer.Lock),H323_SPIN_COUNT);
  127. } __except ((GetExceptionCode() == STATUS_NO_MEMORY)
  128. ? EXCEPTION_EXECUTE_HANDLER
  129. : EXCEPTION_CONTINUE_SEARCH
  130. ) {
  131. // failure
  132. return CS_NO_MEMORY;
  133. }
  134. bCallListCreated = TRUE;
  135. return CS_OK;
  136. }
  137. //====================================================================================
  138. // this routine assumes all of the events and sockets belonging to each object
  139. // are already destroyed. It just makes sure memory is cleaned up.
  140. //====================================================================================
  141. CS_STATUS
  142. CallListDestroy()
  143. {
  144. if (bCallListCreated == FALSE)
  145. {
  146. ASSERT(FALSE);
  147. return CS_INTERNAL_ERROR;
  148. }
  149. // For all entries, hang up the calls
  150. gpCallObjectTable->EnumerateEntries(Q931HangUpAllCalls,
  151. NULL);
  152. // Get rid of the call object table
  153. delete gpCallObjectTable;
  154. gpCallObjectTable = NULL;
  155. DeleteCriticalSection(&(Q931GlobalTimer.Lock));
  156. DeleteCriticalSection(&(CRVSource.Lock));
  157. bCallListCreated = FALSE;
  158. return CS_OK;
  159. }
  160. //====================================================================================
  161. //====================================================================================
  162. void
  163. CallObjectFree(P_CALL_OBJECT pCallObject)
  164. {
  165. if (pCallObject->NonStandardData.sData.pOctetString != NULL)
  166. {
  167. Free(pCallObject->NonStandardData.sData.pOctetString);
  168. pCallObject->NonStandardData.sData.pOctetString = NULL;
  169. }
  170. if (pCallObject->VendorInfoPresent)
  171. {
  172. if (pCallObject->VendorInfo.pProductNumber != NULL)
  173. {
  174. Free(pCallObject->VendorInfo.pProductNumber);
  175. }
  176. if (pCallObject->VendorInfo.pVersionNumber != NULL)
  177. {
  178. Free(pCallObject->VendorInfo.pVersionNumber);
  179. }
  180. }
  181. Q931FreeAliasNames(pCallObject->pCallerAliasList);
  182. pCallObject->pCallerAliasList = NULL;
  183. Q931FreeAliasNames(pCallObject->pCalleeAliasList);
  184. pCallObject->pCalleeAliasList = NULL;
  185. Q931FreeAliasNames(pCallObject->pExtraAliasList);
  186. pCallObject->pExtraAliasList = NULL;
  187. Q931FreeAliasItem(pCallObject->pExtensionAliasItem);
  188. pCallObject->pExtensionAliasItem = NULL;
  189. Free(pCallObject);
  190. }
  191. //====================================================================================
  192. //====================================================================================
  193. CS_STATUS
  194. CallObjectCreate(
  195. PHQ931CALL phQ931Call,
  196. DWORD dwListenToken,
  197. DWORD dwUserToken,
  198. Q931_CALLBACK ConnectCallback,
  199. BOOL fIsCaller,
  200. CC_ADDR *pLocalAddr, // Local address on which channel is connected
  201. CC_ADDR *pPeerConnectAddr, // Address to which channel is connected
  202. CC_ADDR *pPeerCallAddr, // Address of opposite call end-point.
  203. CC_ADDR *pSourceAddr, // Address of this call end-point.
  204. CC_CONFERENCEID *pConferenceID,
  205. WORD wGoal,
  206. WORD wCallType,
  207. BOOL bCallerIsMC,
  208. char *pszDisplay,
  209. char *pszCalledPartyNumber,
  210. PCC_ALIASNAMES pCallerAliasList,
  211. PCC_ALIASNAMES pCalleeAliasList,
  212. PCC_ALIASNAMES pExtraAliasList,
  213. PCC_ALIASITEM pExtensionAliasItem,
  214. PCC_ENDPOINTTYPE pEndpointType,
  215. PCC_NONSTANDARDDATA pNonStandardData, // questionable!
  216. DWORD dwBandwidth,
  217. WORD wCRV)
  218. {
  219. P_CALL_OBJECT pCallObject = NULL;
  220. CS_STATUS status = CS_OK;
  221. CS_STATUS CopyStatus = CS_OK;
  222. DWORD dwIndex = 0;
  223. int rc = 0;
  224. // make sure the call list has been created.
  225. if (bCallListCreated == FALSE)
  226. {
  227. ASSERT(FALSE);
  228. return CS_INTERNAL_ERROR;
  229. }
  230. // validate all parameters for bogus values.
  231. if ((phQ931Call == NULL) || (ConnectCallback == NULL))
  232. {
  233. ASSERT(FALSE);
  234. return CS_BAD_PARAM;
  235. }
  236. // set phQ931Call now, in case we encounter an error later.
  237. *phQ931Call = 0;
  238. pCallObject = (P_CALL_OBJECT)Malloc(sizeof(CALL_OBJECT));
  239. if (pCallObject == NULL)
  240. {
  241. return CS_NO_MEMORY;
  242. }
  243. memset(pCallObject, 0, sizeof(CALL_OBJECT));
  244. // create and init an oss world struct for each call object. This is
  245. // necessary to work in MT environments.
  246. rc = Q931_InitWorld(&pCallObject->World);
  247. if (rc != ASN1_SUCCESS)
  248. {
  249. Q931DBG((DBGERROR, "Q931_InitCoder() returned: %d ", rc));
  250. return CS_SUBSYSTEM_FAILURE;
  251. }
  252. pCallObject->LocalAddr.bMulticast = FALSE;
  253. pCallObject->PeerConnectAddr.bMulticast = FALSE;
  254. pCallObject->PeerCallAddr.bMulticast = FALSE;
  255. pCallObject->SourceAddr.bMulticast = FALSE;
  256. if (wCRV == 0)
  257. {
  258. if (Q931CRVNew(&pCallObject->wCRV) != CS_OK)
  259. {
  260. CallObjectFree(pCallObject);
  261. return CS_INTERNAL_ERROR;
  262. }
  263. }
  264. else
  265. {
  266. pCallObject->wCRV = wCRV;
  267. }
  268. pCallObject->szDisplay[0] = '\0';
  269. if (pszDisplay)
  270. {
  271. strcpy(pCallObject->szDisplay, pszDisplay);
  272. }
  273. pCallObject->szCalledPartyNumber[0] = '\0';
  274. if (pszCalledPartyNumber)
  275. {
  276. strcpy(pCallObject->szCalledPartyNumber, pszCalledPartyNumber);
  277. }
  278. pCallObject->dwListenToken = dwListenToken;
  279. pCallObject->dwUserToken = dwUserToken;
  280. pCallObject->Callback = ConnectCallback;
  281. pCallObject->bCallState = CALLSTATE_NULL;
  282. pCallObject->fIsCaller = fIsCaller;
  283. if (pLocalAddr)
  284. {
  285. pCallObject->LocalAddr = *pLocalAddr;
  286. }
  287. if (pPeerConnectAddr)
  288. {
  289. pCallObject->PeerConnectAddr = *pPeerConnectAddr;
  290. }
  291. if (pPeerCallAddr)
  292. {
  293. pCallObject->PeerCallAddr = *pPeerCallAddr;
  294. pCallObject->PeerCallAddrPresent = TRUE;
  295. }
  296. else
  297. {
  298. pCallObject->PeerCallAddrPresent = FALSE;
  299. }
  300. if (pSourceAddr)
  301. {
  302. pCallObject->SourceAddr = *pSourceAddr;
  303. pCallObject->SourceAddrPresent = TRUE;
  304. }
  305. else
  306. {
  307. pCallObject->SourceAddrPresent = FALSE;
  308. }
  309. if (pConferenceID == NULL)
  310. {
  311. memset(&(pCallObject->ConferenceID), 0, sizeof(CC_CONFERENCEID));
  312. }
  313. else
  314. {
  315. int length = min(sizeof(pConferenceID->buffer),
  316. sizeof(pCallObject->ConferenceID.buffer));
  317. memcpy(pCallObject->ConferenceID.buffer,
  318. pConferenceID->buffer, length);
  319. }
  320. pCallObject->wGoal = wGoal;
  321. pCallObject->bCallerIsMC = bCallerIsMC;
  322. pCallObject->wCallType = wCallType;
  323. if (pNonStandardData != NULL)
  324. {
  325. pCallObject->NonStandardData = *pNonStandardData;
  326. if (pNonStandardData->sData.wOctetStringLength > 0)
  327. {
  328. pCallObject->NonStandardData.sData.pOctetString =
  329. (BYTE *) Malloc(pNonStandardData->sData.wOctetStringLength);
  330. if (pCallObject->NonStandardData.sData.pOctetString == NULL)
  331. {
  332. CallObjectFree(pCallObject);
  333. return CS_NO_MEMORY;
  334. }
  335. memcpy(pCallObject->NonStandardData.sData.pOctetString,
  336. pNonStandardData->sData.pOctetString,
  337. pNonStandardData->sData.wOctetStringLength);
  338. }
  339. pCallObject->NonStandardDataPresent = TRUE;
  340. }
  341. else
  342. {
  343. pCallObject->NonStandardDataPresent = FALSE;
  344. }
  345. CopyStatus = Q931CopyAliasNames(&(pCallObject->pCallerAliasList),
  346. pCallerAliasList);
  347. if (CopyStatus != CS_OK)
  348. {
  349. CallObjectFree(pCallObject);
  350. return CopyStatus;
  351. }
  352. CopyStatus = Q931CopyAliasNames(&(pCallObject->pCalleeAliasList),
  353. pCalleeAliasList);
  354. if (CopyStatus != CS_OK)
  355. {
  356. CallObjectFree(pCallObject);
  357. return CopyStatus;
  358. }
  359. CopyStatus = Q931CopyAliasNames(&(pCallObject->pExtraAliasList),
  360. pExtraAliasList);
  361. if (CopyStatus != CS_OK)
  362. {
  363. CallObjectFree(pCallObject);
  364. return CopyStatus;
  365. }
  366. CopyStatus = Q931CopyAliasItem(&(pCallObject->pExtensionAliasItem),
  367. pExtensionAliasItem);
  368. if (CopyStatus != CS_OK)
  369. {
  370. CallObjectFree(pCallObject);
  371. return CopyStatus;
  372. }
  373. pCallObject->bResolved = FALSE;
  374. pCallObject->VendorInfoPresent = FALSE;
  375. pCallObject->bIsTerminal = TRUE;
  376. pCallObject->bIsGateway = FALSE;
  377. if (pEndpointType != NULL)
  378. {
  379. PCC_VENDORINFO pVendorInfo = pEndpointType->pVendorInfo;
  380. if (pVendorInfo != NULL)
  381. {
  382. pCallObject->VendorInfoPresent = TRUE;
  383. pCallObject->VendorInfo = *(pVendorInfo);
  384. if (pVendorInfo->pProductNumber && pVendorInfo->pProductNumber->pOctetString &&
  385. pVendorInfo->pProductNumber->wOctetStringLength)
  386. {
  387. memcpy(pCallObject->bufVendorProduct,
  388. pVendorInfo->pProductNumber->pOctetString,
  389. pVendorInfo->pProductNumber->wOctetStringLength);
  390. pCallObject->VendorInfo.pProductNumber = (CC_OCTETSTRING*) Malloc(sizeof(CC_OCTETSTRING));
  391. if (pCallObject->VendorInfo.pProductNumber == NULL)
  392. {
  393. CallObjectFree(pCallObject);
  394. return CS_NO_MEMORY;
  395. }
  396. pCallObject->VendorInfo.pProductNumber->pOctetString =
  397. pCallObject->bufVendorProduct;
  398. pCallObject->VendorInfo.pProductNumber->wOctetStringLength =
  399. pVendorInfo->pProductNumber->wOctetStringLength;
  400. }
  401. else
  402. {
  403. pCallObject->VendorInfo.pProductNumber = NULL;
  404. }
  405. if (pVendorInfo->pVersionNumber && pVendorInfo->pVersionNumber->pOctetString &&
  406. pVendorInfo->pVersionNumber->wOctetStringLength)
  407. {
  408. memcpy(pCallObject->bufVendorVersion,
  409. pVendorInfo->pVersionNumber->pOctetString,
  410. pVendorInfo->pVersionNumber->wOctetStringLength);
  411. pCallObject->VendorInfo.pVersionNumber = (CC_OCTETSTRING*) Malloc(sizeof(CC_OCTETSTRING));
  412. if (pCallObject->VendorInfo.pVersionNumber == NULL)
  413. {
  414. CallObjectFree(pCallObject);
  415. return CS_NO_MEMORY;
  416. }
  417. pCallObject->VendorInfo.pVersionNumber->pOctetString =
  418. pCallObject->bufVendorVersion;
  419. pCallObject->VendorInfo.pVersionNumber->wOctetStringLength =
  420. pVendorInfo->pVersionNumber->wOctetStringLength;
  421. }
  422. else
  423. {
  424. pCallObject->VendorInfo.pVersionNumber = NULL;
  425. }
  426. }
  427. pCallObject->bIsTerminal = pEndpointType->bIsTerminal;
  428. pCallObject->bIsGateway = pEndpointType->bIsGateway;
  429. pCallObject->dwBandwidth = dwBandwidth;
  430. }
  431. Q931MakePhysicalID(&pCallObject->dwPhysicalId);
  432. // Insert the object into the table...if that doesn't work, blow away the object.
  433. if (gpCallObjectTable->CreateAndLock(pCallObject,
  434. &dwIndex) == FALSE)
  435. {
  436. CallObjectFree(pCallObject);
  437. return CS_INTERNAL_ERROR;
  438. }
  439. // Save the index as the handle (this makes it easier to find the object later).
  440. *phQ931Call = pCallObject->hQ931Call = (HQ931CALL) dwIndex;
  441. Q931DBG((DBGTRACE, "CallObjectCreate() -returned-> 0x%08x", dwIndex));
  442. // Unlock the entry
  443. gpCallObjectTable->Unlock(dwIndex);
  444. return CS_OK;
  445. }
  446. //====================================================================================
  447. //====================================================================================
  448. CS_STATUS
  449. CallObjectDestroy(
  450. P_CALL_OBJECT pCallObject)
  451. {
  452. if (pCallObject == NULL)
  453. {
  454. ASSERT(FALSE);
  455. return CS_BAD_PARAM;
  456. }
  457. Q931DBG((DBGTRACE, "CallObjectDestroy(0x%08lx)", pCallObject->hQ931Call));
  458. Q931_TermWorld(&pCallObject->World);
  459. // Since the caller must already have a lock on the object, remove the entry from
  460. // the table. We won't let the table delete the object as we want to clean up.
  461. if (gpCallObjectTable->Delete((DWORD) pCallObject->hQ931Call) == FALSE)
  462. {
  463. return CS_OK;
  464. }
  465. Q931StopTimer(pCallObject, Q931_TIMER_301);
  466. Q931StopTimer(pCallObject, Q931_TIMER_303);
  467. // Unlock the object
  468. gpCallObjectTable->Unlock((DWORD) pCallObject->hQ931Call);
  469. // Free up the call object
  470. CallObjectFree(pCallObject);
  471. return CS_OK;
  472. }
  473. //====================================================================================
  474. //====================================================================================
  475. CS_STATUS
  476. CallObjectLock(
  477. HQ931CALL hQ931Call,
  478. PP_CALL_OBJECT ppCallObject)
  479. {
  480. if (ppCallObject == NULL)
  481. {
  482. ASSERT(FALSE);
  483. return CS_BAD_PARAM;
  484. }
  485. // Attempt to lock the entry. If that fails, we'll return CS_BAD_PARAM under
  486. // the assumption that the entry is invalid.
  487. *ppCallObject = gpCallObjectTable->Lock((DWORD) hQ931Call);
  488. return (*ppCallObject == NULL ? CS_BAD_PARAM : CS_OK);
  489. }
  490. //====================================================================================
  491. //====================================================================================
  492. CS_STATUS
  493. CallObjectUnlock(
  494. P_CALL_OBJECT pCallObject)
  495. {
  496. if (pCallObject == NULL)
  497. {
  498. ASSERT(FALSE);
  499. return CS_BAD_PARAM;
  500. }
  501. // Unlock the entry
  502. if (gpCallObjectTable->Unlock((DWORD) pCallObject->hQ931Call) == FALSE)
  503. {
  504. Q931DBG((DBGERROR, "gpCallObjectTable->Unlock(0x%08lx) FAILED!!!!", pCallObject->hQ931Call));
  505. return CS_BAD_PARAM;
  506. }
  507. return CS_OK;
  508. }
  509. //====================================================================================
  510. //====================================================================================
  511. CS_STATUS
  512. CallObjectValidate(
  513. HQ931CALL hQ931Call)
  514. {
  515. if (gpCallObjectTable->Validate((DWORD) hQ931Call) == TRUE)
  516. {
  517. return CS_OK;
  518. }
  519. return CS_BAD_PARAM;
  520. }
  521. //====================================================================================
  522. //====================================================================================
  523. BOOL
  524. CallObjectFind(
  525. HQ931CALL *phQ931Call,
  526. WORD wCRV,
  527. PCC_ADDR pPeerAddr)
  528. {
  529. Q931CALLOBJKEY Q931CallObjKey;
  530. Q931CallObjKey.wCRV = wCRV;
  531. Q931CallObjKey.pPeerAddr = pPeerAddr;
  532. Q931CallObjKey.bFound = FALSE;
  533. gpCallObjectTable->EnumerateEntries(Q931CallObjectFind,
  534. (LPVOID) &Q931CallObjKey);
  535. if(Q931CallObjKey.bFound == TRUE)
  536. {
  537. *phQ931Call = Q931CallObjKey.hQ931Call;
  538. return TRUE;
  539. }
  540. return FALSE;
  541. }
  542. //====================================================================================
  543. //====================================================================================
  544. CS_STATUS CallObjectMarkForDelete(HQ931CALL hQ931Call)
  545. {
  546. // User must have the object already locked to call this.
  547. // Mark the object as deleted but don't let the table delete the object's
  548. // memory.
  549. return (gpCallObjectTable->Delete((DWORD) hQ931Call) == FALSE ? CS_BAD_PARAM : CS_OK);
  550. }
  551. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  552. // Timer Routines...
  553. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  554. //====================================================================================
  555. // This routine will be called every 1000 ms if any call object
  556. // has caused the Q931GlobalTimer to be created.
  557. //====================================================================================
  558. VOID CALLBACK
  559. Q931TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
  560. {
  561. DWORD dwTickCount = GetTickCount();
  562. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  563. if (Q931GlobalTimer.bBusy)
  564. {
  565. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  566. return;
  567. }
  568. Q931GlobalTimer.bBusy = TRUE;
  569. // Check all of the entries for timeout
  570. gpCallObjectTable->EnumerateEntries(Q931CheckForTimeout,
  571. (LPVOID) &dwTickCount);
  572. Q931GlobalTimer.bBusy = FALSE;
  573. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  574. }
  575. //====================================================================================
  576. //====================================================================================
  577. HRESULT
  578. Q931StartTimer(P_CALL_OBJECT pCallObject, DWORD wTimerId)
  579. {
  580. if (pCallObject == NULL)
  581. {
  582. return CS_BAD_PARAM;
  583. }
  584. switch (wTimerId)
  585. {
  586. case Q931_TIMER_301:
  587. if (pCallObject->dwTimerAlarm301)
  588. {
  589. // timer is already set for this call object...
  590. return CS_INTERNAL_ERROR;
  591. }
  592. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  593. pCallObject->dwTimerAlarm301 = GetTickCount() + Q931GlobalTimer.dwTicks301;
  594. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  595. break;
  596. case Q931_TIMER_303:
  597. if (pCallObject->dwTimerAlarm303)
  598. {
  599. // timer is already set for this call object...
  600. return CS_INTERNAL_ERROR;
  601. }
  602. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  603. pCallObject->dwTimerAlarm303 = GetTickCount() + Q931GlobalTimer.dwTicks303;
  604. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  605. break;
  606. default:
  607. return CS_BAD_PARAM;
  608. break;
  609. }
  610. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  611. if (!Q931GlobalTimer.dwTimerCount)
  612. {
  613. Q931GlobalTimer.uTimerId = SetTimer(NULL, 0, 1000, (TIMERPROC)Q931TimerProc);
  614. }
  615. Q931GlobalTimer.dwTimerCount++;
  616. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  617. return CS_OK;
  618. }
  619. //====================================================================================
  620. //====================================================================================
  621. HRESULT
  622. Q931StopTimer(P_CALL_OBJECT pCallObject, DWORD wTimerId)
  623. {
  624. if (pCallObject == NULL)
  625. {
  626. return CS_BAD_PARAM;
  627. }
  628. switch (wTimerId)
  629. {
  630. case Q931_TIMER_301:
  631. if (!pCallObject->dwTimerAlarm301)
  632. {
  633. return CS_OK;
  634. }
  635. pCallObject->dwTimerAlarm301 = 0;
  636. break;
  637. case Q931_TIMER_303:
  638. if (!pCallObject->dwTimerAlarm303)
  639. {
  640. return CS_OK;
  641. }
  642. pCallObject->dwTimerAlarm303 = 0;
  643. break;
  644. default:
  645. return CS_BAD_PARAM;
  646. break;
  647. }
  648. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  649. if (Q931GlobalTimer.dwTimerCount > 0)
  650. {
  651. Q931GlobalTimer.dwTimerCount--;
  652. if (!Q931GlobalTimer.dwTimerCount)
  653. {
  654. KillTimer(NULL, Q931GlobalTimer.uTimerId);
  655. Q931GlobalTimer.uTimerId = 0;
  656. }
  657. }
  658. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  659. return CS_OK;
  660. }
  661. //====================================================================================
  662. //====================================================================================
  663. CS_STATUS
  664. Q931SetAlertingTimeout(DWORD dwDuration)
  665. {
  666. EnterCriticalSection(&(Q931GlobalTimer.Lock));
  667. if (dwDuration)
  668. {
  669. Q931GlobalTimer.dwTicks303 = dwDuration;
  670. }
  671. else
  672. {
  673. Q931GlobalTimer.dwTicks303 = Q931_TICKS_303;
  674. }
  675. LeaveCriticalSection(&(Q931GlobalTimer.Lock));
  676. return CS_OK;
  677. }
  678. //====================================================================================
  679. //====================================================================================
  680. DWORD Q931HangUpAllCalls(P_CALL_OBJECT pCallObject, LPVOID context)
  681. {
  682. HQ931CALL hQ931Call = pCallObject->hQ931Call;
  683. // Try to hangup the call object.
  684. Q931Hangup(hQ931Call, CC_REJECT_NORMAL_CALL_CLEARING);
  685. // Try to lock the object. If that succeeds, then we want to force the object to
  686. // be deleted. We should never have to do this as the hang up is supposed to
  687. // take care of that for us.
  688. if (gpCallObjectTable->Lock(hQ931Call) != NULL)
  689. {
  690. CallObjectDestroy(pCallObject);
  691. }
  692. return CALLBACK_DELETE_ENTRY;
  693. }
  694. //====================================================================================
  695. //====================================================================================
  696. DWORD
  697. Q931CallObjectFind(P_CALL_OBJECT pCallObject, LPVOID context)
  698. {
  699. PQ931CALLOBJKEY pQ931CallObjKey = (PQ931CALLOBJKEY) context;
  700. PCC_ADDR pPeerAddr = pQ931CallObjKey->pPeerAddr;
  701. WORD wCRV = pQ931CallObjKey->wCRV;
  702. if (!pCallObject->bResolved)
  703. {
  704. return(CALLBACK_CONTINUE);
  705. }
  706. if ((pCallObject->wCRV & (~0x8000)) == (wCRV & (~0x8000)))
  707. {
  708. if (!pPeerAddr)
  709. {
  710. pQ931CallObjKey->bFound = TRUE;
  711. pQ931CallObjKey->hQ931Call = pCallObject->hQ931Call;
  712. return(CALLBACK_ABORT);
  713. }
  714. else if ((pPeerAddr->nAddrType == CC_IP_BINARY) &&
  715. (pPeerAddr->Addr.IP_Binary.dwAddr == INADDR_LOOPBACK))
  716. {
  717. pQ931CallObjKey->bFound = FALSE;
  718. pQ931CallObjKey->hQ931Call = NULL;
  719. return(CALLBACK_CONTINUE); // allow loopback calls
  720. }
  721. else if ((pCallObject->LocalAddr.nAddrType == CC_IP_BINARY) &&
  722. (pPeerAddr->nAddrType == CC_IP_BINARY) &&
  723. (pCallObject->LocalAddr.Addr.IP_Binary.dwAddr == pPeerAddr->Addr.IP_Binary.dwAddr))
  724. {
  725. pQ931CallObjKey->bFound = FALSE;
  726. pQ931CallObjKey->hQ931Call = NULL;
  727. return(CALLBACK_CONTINUE); // allow loopback calls
  728. }
  729. else if ((pCallObject->PeerConnectAddr.nAddrType == CC_IP_BINARY) &&
  730. (pPeerAddr->nAddrType == CC_IP_BINARY) &&
  731. (pCallObject->PeerConnectAddr.Addr.IP_Binary.dwAddr == pPeerAddr->Addr.IP_Binary.dwAddr))
  732. {
  733. pQ931CallObjKey->bFound = TRUE;
  734. pQ931CallObjKey->hQ931Call = pCallObject->hQ931Call;
  735. return(CALLBACK_ABORT);
  736. }
  737. }
  738. return(CALLBACK_CONTINUE);
  739. }
  740. //====================================================================================
  741. //====================================================================================
  742. DWORD Q931CheckForTimeout(P_CALL_OBJECT pCallObject, LPVOID context)
  743. {
  744. DWORD dwTickCount = *((LPDWORD) context);
  745. // Determine if a timer has expired for the entry
  746. if (pCallObject->dwTimerAlarm301 &&
  747. (pCallObject->dwTimerAlarm301 <= dwTickCount))
  748. {
  749. Q931StopTimer(pCallObject, Q931_TIMER_301);
  750. Q931StopTimer(pCallObject, Q931_TIMER_303);
  751. if (pCallObject->dwTimerAlarm303 &&
  752. (pCallObject->dwTimerAlarm303 < pCallObject->dwTimerAlarm301) &&
  753. (pCallObject->dwTimerAlarm303 <= dwTickCount))
  754. {
  755. CallBackT303(pCallObject);
  756. }
  757. else
  758. {
  759. CallBackT301(pCallObject);
  760. }
  761. }
  762. else if (pCallObject->dwTimerAlarm303 &&
  763. (pCallObject->dwTimerAlarm303 <= dwTickCount))
  764. {
  765. Q931StopTimer(pCallObject, Q931_TIMER_301);
  766. Q931StopTimer(pCallObject, Q931_TIMER_303);
  767. CallBackT303(pCallObject);
  768. }
  769. return CALLBACK_CONTINUE;
  770. }