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.

3176 lines
87 KiB

  1. /****************************************************************************
  2. *
  3. * $Archive: S:/STURGEON/SRC/Q931/VCS/q931.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-1996 Intel Corporation.
  12. *
  13. * $Revision: 1.122 $
  14. * $Date: 04 Mar 1997 20:59:26 $
  15. * $Author: MANDREWS $
  16. *
  17. * BCL's revision info:
  18. * Revision: 1.99
  19. * Date: 19 Nov 1996 14:54:02
  20. * Author: rodellx
  21. *
  22. * Deliverable:
  23. *
  24. * Abstract:
  25. *
  26. *
  27. * Notes:
  28. *
  29. ***************************************************************************/
  30. // [ ] Add facility ie to FACILITY MSG.
  31. // [ ] Read Q931 Appendix D.
  32. #pragma warning ( disable : 4057 4100 4115 4201 4214 4514 )
  33. #include "precomp.h"
  34. #ifdef __cplusplus
  35. extern "C" {
  36. #endif
  37. #include <string.h>
  38. #include <stdio.h>
  39. #include <rpc.h>
  40. #include "apierror.h"
  41. #include "isrg.h"
  42. #include "incommon.h"
  43. #include "linkapi.h"
  44. #include "common.h"
  45. #include "q931.h"
  46. #include "utils.h"
  47. #include "hlisten.h"
  48. #include "hcall.h"
  49. #include "q931pdu.h"
  50. #if (defined(_DEBUG) || defined(PCS_COMPLIANCE))
  51. #include "interop.h"
  52. #include "q931plog.h"
  53. LPInteropLogger Q931Logger;
  54. #endif
  55. #define RECEIVE_BUFFER_SIZE 0x2000
  56. #define HANGUP_TIMEOUT 1000 // 1 second
  57. #define CANCEL_LISTEN_TIMEOUT 5000 // 5 seconds
  58. // variable needed to support ISR debug facility.
  59. #if (ISRDEBUGINFO >= 1)
  60. WORD ghISRInst = 0;
  61. #endif
  62. #ifdef UNICODE_TRACE
  63. // We include this header to fix problems with macro expansion when Unicode is turned on.
  64. #include "unifix.h"
  65. #endif
  66. #define _Unicode(x) L ## x
  67. #define Unicode(x) _Unicode(x)
  68. // global data used by WinSock.
  69. static BOOL bQ931Initialized = FALSE;
  70. static Q931_RECEIVE_PDU_CALLBACK gReceivePDUHookProc = NULL;
  71. static struct
  72. {
  73. DWORD TempID;
  74. CC_CONFERENCEID ConferenceID;
  75. CRITICAL_SECTION Lock;
  76. } ConferenceIDSource;
  77. extern VOID Q931PduInit();
  78. //====================================================================================
  79. //
  80. // PRIVATE FUNCTIONS
  81. //
  82. //====================================================================================
  83. //====================================================================================
  84. //====================================================================================
  85. void _FreeSetupASN(Q931_SETUP_ASN *pSetupASN)
  86. {
  87. ASSERT(pSetupASN != NULL);
  88. // Cleanup any dynamically allocated fields within SetupASN
  89. if (pSetupASN->NonStandardData.sData.pOctetString)
  90. {
  91. MemFree(pSetupASN->NonStandardData.sData.pOctetString);
  92. pSetupASN->NonStandardData.sData.pOctetString = NULL;
  93. }
  94. if (pSetupASN->VendorInfo.pProductNumber)
  95. {
  96. MemFree(pSetupASN->VendorInfo.pProductNumber);
  97. pSetupASN->VendorInfo.pProductNumber = NULL;
  98. }
  99. if (pSetupASN->VendorInfo.pVersionNumber)
  100. {
  101. MemFree(pSetupASN->VendorInfo.pVersionNumber);
  102. pSetupASN->VendorInfo.pVersionNumber = NULL;
  103. }
  104. Q931FreeAliasNames(pSetupASN->pCallerAliasList);
  105. pSetupASN->pCallerAliasList = NULL;
  106. Q931FreeAliasNames(pSetupASN->pCalleeAliasList);
  107. pSetupASN->pCalleeAliasList = NULL;
  108. Q931FreeAliasNames(pSetupASN->pExtraAliasList);
  109. pSetupASN->pExtraAliasList = NULL;
  110. Q931FreeAliasItem(pSetupASN->pExtensionAliasItem);
  111. pSetupASN->pExtensionAliasItem = NULL;
  112. }
  113. void _FreeReleaseCompleteASN(Q931_RELEASE_COMPLETE_ASN *pReleaseCompleteASN)
  114. {
  115. ASSERT(pReleaseCompleteASN != NULL);
  116. // Cleanup any dynamically allocated fields within SetupASN
  117. if (pReleaseCompleteASN->NonStandardData.sData.pOctetString)
  118. {
  119. MemFree(pReleaseCompleteASN->NonStandardData.sData.pOctetString);
  120. pReleaseCompleteASN->NonStandardData.sData.pOctetString = NULL;
  121. }
  122. }
  123. void _FreeFacilityASN(Q931_FACILITY_ASN *pFacilityASN)
  124. {
  125. ASSERT(pFacilityASN != NULL);
  126. // Cleanup any dynamically allocated fields within SetupASN
  127. if (pFacilityASN->NonStandardData.sData.pOctetString)
  128. {
  129. MemFree(pFacilityASN->NonStandardData.sData.pOctetString);
  130. pFacilityASN->NonStandardData.sData.pOctetString = NULL;
  131. }
  132. }
  133. void _FreeProceedingASN(Q931_CALL_PROCEEDING_ASN *pProceedingASN)
  134. {
  135. ASSERT(pProceedingASN != NULL);
  136. // Cleanup any dynamically allocated fields within SetupASN
  137. if (pProceedingASN->NonStandardData.sData.pOctetString)
  138. {
  139. MemFree(pProceedingASN->NonStandardData.sData.pOctetString);
  140. pProceedingASN->NonStandardData.sData.pOctetString = NULL;
  141. }
  142. }
  143. void _FreeAlertingASN(Q931_ALERTING_ASN *pAlertingASN)
  144. {
  145. ASSERT(pAlertingASN != NULL);
  146. // Cleanup any dynamically allocated fields within SetupASN
  147. if (pAlertingASN->NonStandardData.sData.pOctetString)
  148. {
  149. MemFree(pAlertingASN->NonStandardData.sData.pOctetString);
  150. pAlertingASN->NonStandardData.sData.pOctetString = NULL;
  151. }
  152. }
  153. void _FreeConnectASN(Q931_CONNECT_ASN *pConnectASN)
  154. {
  155. ASSERT(pConnectASN != NULL);
  156. // Cleanup any dynamically allocated fields within SetupASN
  157. if (pConnectASN->NonStandardData.sData.pOctetString)
  158. {
  159. MemFree(pConnectASN->NonStandardData.sData.pOctetString);
  160. pConnectASN->NonStandardData.sData.pOctetString = NULL;
  161. }
  162. if (pConnectASN->VendorInfo.pProductNumber)
  163. {
  164. MemFree(pConnectASN->VendorInfo.pProductNumber);
  165. pConnectASN->VendorInfo.pProductNumber = NULL;
  166. }
  167. if (pConnectASN->VendorInfo.pVersionNumber)
  168. {
  169. MemFree(pConnectASN->VendorInfo.pVersionNumber);
  170. pConnectASN->VendorInfo.pVersionNumber = NULL;
  171. }
  172. }
  173. void
  174. _ConferenceIDNew(
  175. CC_CONFERENCEID *pConferenceID)
  176. {
  177. UUID id;
  178. int iresult;
  179. EnterCriticalSection(&(ConferenceIDSource.Lock));
  180. memset(ConferenceIDSource.ConferenceID.buffer, 0,
  181. sizeof(ConferenceIDSource.ConferenceID.buffer));
  182. iresult = UuidCreate(&id);
  183. if ((iresult == RPC_S_OK) || (iresult ==RPC_S_UUID_LOCAL_ONLY))
  184. {
  185. memcpy(ConferenceIDSource.ConferenceID.buffer, &id,
  186. min(sizeof(ConferenceIDSource.ConferenceID.buffer), sizeof(UUID)));
  187. }
  188. else
  189. ASSERT(0);
  190. memcpy(pConferenceID->buffer, ConferenceIDSource.ConferenceID.buffer,
  191. sizeof(pConferenceID->buffer));
  192. LeaveCriticalSection(&(ConferenceIDSource.Lock));
  193. return;
  194. }
  195. //====================================================================================
  196. // This function is used internally whenever a function needs to send a PDU.
  197. // Note that before a datalinkSendRequest() is done, the call object is unlocked
  198. // and then subsequently locked after returning. This is necessary to prevent deadlock
  199. // in MT apps. Further, it is the responsibility of calling functions to revalidate
  200. // the call object before using it.
  201. //====================================================================================
  202. CS_STATUS
  203. Q931SendMessage(
  204. P_CALL_OBJECT pCallObject,
  205. BYTE* CodedPtrPDU,
  206. DWORD CodedLengthPDU,
  207. BOOL bOkToUnlock)
  208. {
  209. HQ931CALL hQ931Call;
  210. DWORD dwPhysicalId;
  211. HRESULT result;
  212. ASSERT(pCallObject != NULL);
  213. ASSERT(CodedPtrPDU != NULL);
  214. ASSERT(CodedLengthPDU != 0);
  215. hQ931Call = pCallObject->hQ931Call;
  216. dwPhysicalId = pCallObject->dwPhysicalId;
  217. // send the message.
  218. if (pCallObject->bConnected)
  219. {
  220. // Unlock the call object before we call down to Link Layer (if caller said it was ok)
  221. if(bOkToUnlock)
  222. CallObjectUnlock(pCallObject);
  223. #if (defined(_DEBUG) || defined(PCS_COMPLIANCE))
  224. InteropOutput(Q931Logger, (BYTE FAR*)CodedPtrPDU, CodedLengthPDU, Q931LOG_SENT_PDU);
  225. #endif
  226. result = datalinkSendRequest(dwPhysicalId, CodedPtrPDU, CodedLengthPDU);
  227. // Now attempt to lock the object again. Note: higher level funcs must
  228. // be sure to call CallObjectValidate before assuming they have a valid lock
  229. if (bOkToUnlock && ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL)))
  230. {
  231. ISRERROR(ghISRInst, "CallObjectLock() returned error (object not found).", 0L);
  232. }
  233. // Note: if we can't get the lock, perhaps we should pass back a specific return code
  234. // that higher layers can check for??? For now, they should call CallObjectValidate()
  235. // before assuming the call object is still good.
  236. if (FAILED(result))
  237. {
  238. ISRERROR(ghISRInst, "datalinkSendRequest() failed", 0L);
  239. MemFree(CodedPtrPDU);
  240. }
  241. return result;
  242. }
  243. ISRWARNING(ghISRInst, "Q931SendMessage: message not sent because bConnected is FALSE", 0L);
  244. MemFree(CodedPtrPDU);
  245. return CS_OK;
  246. }
  247. //====================================================================================
  248. //====================================================================================
  249. CS_STATUS
  250. Q931RingingInternal(P_CALL_OBJECT pCallObject, WORD wCRV)
  251. {
  252. CC_ENDPOINTTYPE EndpointType;
  253. DWORD CodedLengthASN;
  254. BYTE *CodedPtrASN;
  255. BINARY_STRING UserUserData;
  256. DWORD CodedLengthPDU;
  257. BYTE *CodedPtrPDU;
  258. HRESULT result = CS_OK;
  259. int nError = 0;
  260. HQ931CALL hQ931Call = pCallObject->hQ931Call;
  261. if (pCallObject->VendorInfoPresent)
  262. EndpointType.pVendorInfo = &pCallObject->VendorInfo;
  263. else
  264. EndpointType.pVendorInfo = NULL;
  265. EndpointType.bIsTerminal = pCallObject->bIsTerminal;
  266. EndpointType.bIsGateway = pCallObject->bIsGateway;
  267. result = Q931AlertingEncodeASN(
  268. NULL, /* pNonStandardData */
  269. NULL, /* h245Addr */
  270. &EndpointType,
  271. &pCallObject->World,
  272. &CodedPtrASN,
  273. &CodedLengthASN,
  274. &pCallObject->CallIdentifier);
  275. if (result != CS_OK || CodedLengthASN == 0 || CodedPtrASN == NULL)
  276. {
  277. ISRERROR(ghISRInst, "Q931AlertingEncodeASN() failed, nothing to send.", 0L);
  278. if (CodedPtrASN != NULL)
  279. {
  280. Q931FreeEncodedBuffer(&pCallObject->World, CodedPtrASN);
  281. }
  282. return (result != CS_OK) ? result : CS_INTERNAL_ERROR;
  283. }
  284. UserUserData.length = (WORD)CodedLengthASN;
  285. UserUserData.ptr = CodedPtrASN;
  286. result = Q931AlertingEncodePDU(wCRV, &UserUserData, &CodedPtrPDU,
  287. &CodedLengthPDU);
  288. if (CodedPtrASN != NULL)
  289. {
  290. Q931FreeEncodedBuffer(&pCallObject->World, CodedPtrASN);
  291. }
  292. if ((result != CS_OK) || (CodedLengthPDU == 0) ||
  293. (CodedPtrPDU == NULL))
  294. {
  295. ISRERROR(ghISRInst, "Q931AlertingEncodePDU() failed, nothing to send.", 0L);
  296. if (CodedPtrPDU != NULL)
  297. {
  298. MemFree(CodedPtrPDU);
  299. }
  300. if (result != CS_OK)
  301. {
  302. return result;
  303. }
  304. return CS_INTERNAL_ERROR;
  305. }
  306. else
  307. {
  308. result = Q931SendMessage(pCallObject, CodedPtrPDU, CodedLengthPDU, TRUE);
  309. if(CallObjectValidate(hQ931Call) != CS_OK)
  310. return(CS_INTERNAL_ERROR);
  311. }
  312. return result;
  313. }
  314. //====================================================================================
  315. //====================================================================================
  316. CS_STATUS
  317. Q931OnCallSetup(
  318. P_CALL_OBJECT pCallObject,
  319. Q931MESSAGE *pMessage,
  320. Q931_SETUP_ASN *pSetupASN)
  321. {
  322. DWORD result;
  323. HQ931CALL hQ931Call;
  324. HRESULT Status;
  325. // if the callstate is anything other than null, ignore...
  326. // if (pCallObject->bCallState != CALLSTATE_NULL)
  327. // {
  328. // return CS_OK;
  329. // }
  330. hQ931Call = pCallObject->hQ931Call;
  331. if (pMessage->CallReference & 0x8000)
  332. {
  333. // the message came from the callee, so this should be ignored???
  334. }
  335. pMessage->CallReference &= ~(0x8000); // strip off the high bit.
  336. pCallObject->wCRV = pMessage->CallReference;
  337. pCallObject->wGoal = pSetupASN->wGoal;
  338. pCallObject->bCallerIsMC = pSetupASN->bCallerIsMC;
  339. pCallObject->wCallType = pSetupASN->wCallType;
  340. pCallObject->ConferenceID = pSetupASN->ConferenceID;
  341. pCallObject->CallIdentifier = pSetupASN->CallIdentifier;
  342. pCallObject->bCallState = CALLSTATE_PRESENT;
  343. {
  344. CSS_CALL_INCOMING EventData;
  345. WCHAR szUnicodeDisplay[CC_MAX_DISPLAY_LENGTH + 1];
  346. WCHAR szUnicodeCalledPartyNumber[CC_MAX_PARTY_NUMBER_LEN + 1];
  347. EventData.wGoal = pCallObject->wGoal;
  348. EventData.wCallType = pCallObject->wCallType;
  349. EventData.bCallerIsMC = pCallObject->bCallerIsMC;
  350. EventData.ConferenceID = pCallObject->ConferenceID;
  351. EventData.pSourceAddr = NULL;
  352. if (pSetupASN->SourceAddrPresent)
  353. {
  354. EventData.pSourceAddr = &(pSetupASN->SourceAddr);
  355. }
  356. EventData.pCallerAddr = NULL;
  357. if (pSetupASN->CallerAddrPresent)
  358. {
  359. EventData.pCallerAddr = &(pSetupASN->CallerAddr);
  360. }
  361. EventData.pCalleeDestAddr = NULL;
  362. if (pSetupASN->CalleeDestAddrPresent)
  363. {
  364. EventData.pCalleeDestAddr = &(pSetupASN->CalleeDestAddr);
  365. }
  366. EventData.pLocalAddr = NULL;
  367. if (pSetupASN->CalleeAddrPresent)
  368. {
  369. EventData.pLocalAddr = &(pSetupASN->CalleeAddr);
  370. }
  371. if (!(pSetupASN->NonStandardDataPresent) ||
  372. (pSetupASN->NonStandardData.sData.wOctetStringLength == 0) ||
  373. (pSetupASN->NonStandardData.sData.pOctetString == NULL))
  374. {
  375. EventData.pNonStandardData = NULL;
  376. }
  377. else
  378. {
  379. EventData.pNonStandardData = &(pSetupASN->NonStandardData);
  380. }
  381. EventData.pCallerAliasList = pSetupASN->pCallerAliasList;
  382. EventData.pCalleeAliasList = pSetupASN->pCalleeAliasList;
  383. EventData.pExtraAliasList = pSetupASN->pExtraAliasList;
  384. EventData.pExtensionAliasItem = pSetupASN->pExtensionAliasItem;
  385. EventData.CallIdentifier = pSetupASN->CallIdentifier;
  386. EventData.pszDisplay = NULL;
  387. if (pMessage->Display.Present && pMessage->Display.Contents)
  388. {
  389. MultiByteToWideChar(CP_ACP, 0, (const char *)pMessage->Display.Contents, -1,
  390. szUnicodeDisplay, sizeof(szUnicodeDisplay) / sizeof(szUnicodeDisplay[0]));
  391. EventData.pszDisplay = szUnicodeDisplay;
  392. }
  393. EventData.pszCalledPartyNumber = NULL;
  394. if (pMessage->CalledPartyNumber.Present && pMessage->CalledPartyNumber.PartyNumberLength)
  395. {
  396. MultiByteToWideChar(CP_ACP, 0, (const char *)pMessage->CalledPartyNumber.PartyNumbers, -1,
  397. szUnicodeCalledPartyNumber, sizeof(szUnicodeCalledPartyNumber) / sizeof(szUnicodeCalledPartyNumber[0]));
  398. EventData.pszCalledPartyNumber = szUnicodeCalledPartyNumber;
  399. }
  400. EventData.pSourceEndpointType = &(pSetupASN->EndpointType);
  401. EventData.wCallReference = pMessage->CallReference;
  402. result = pCallObject->Callback((BYTE)Q931_CALL_INCOMING,
  403. pCallObject->hQ931Call, pCallObject->dwListenToken,
  404. pCallObject->dwUserToken, &EventData);
  405. }
  406. Status = CallObjectValidate(hQ931Call);
  407. if (Status != CS_OK)
  408. return Status;
  409. if (result == 0)
  410. {
  411. WORD wCRV = (WORD)(pMessage->CallReference | 0x8000);
  412. Status = Q931RingingInternal(pCallObject, wCRV);
  413. if (Status != CS_OK)
  414. {
  415. return Status;
  416. }
  417. pCallObject->bCallState = CALLSTATE_RECEIVED;
  418. }
  419. return CS_OK;
  420. }
  421. //====================================================================================
  422. //====================================================================================
  423. CS_STATUS
  424. Q931Ringing(
  425. HQ931CALL hQ931Call,
  426. WORD *pwCRV)
  427. {
  428. P_CALL_OBJECT pCallObject = NULL;
  429. CS_STATUS Status;
  430. WORD wCRV;
  431. if (bQ931Initialized == FALSE)
  432. {
  433. ASSERT(FALSE);
  434. return CS_NOT_INITIALIZED;
  435. }
  436. ISRTRACE(ghISRInst, "Entering Q931Ringing()...", 0L);
  437. // need parameter checking...
  438. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  439. {
  440. ISRERROR(ghISRInst, "CallObjectLock() returned error (object not found).", 0L);
  441. return CS_BAD_PARAM;
  442. }
  443. if (pwCRV != NULL)
  444. {
  445. wCRV = *pwCRV;
  446. }
  447. else
  448. {
  449. wCRV = pCallObject->wCRV;
  450. }
  451. Status = Q931RingingInternal(pCallObject, wCRV);
  452. if (Status != CS_OK)
  453. {
  454. return Status;
  455. }
  456. pCallObject->bCallState = CALLSTATE_RECEIVED;
  457. Status = CallObjectUnlock(pCallObject);
  458. return Status;
  459. }
  460. //====================================================================================
  461. //====================================================================================
  462. CS_STATUS
  463. Q931OnCallProceeding(
  464. P_CALL_OBJECT pCallObject,
  465. Q931MESSAGE *pMessage,
  466. Q931_CALL_PROCEEDING_ASN *pProceedingASN)
  467. {
  468. pCallObject->bCallState = CALLSTATE_OUTGOING;
  469. Q931StopTimer(pCallObject, Q931_TIMER_303);
  470. return CS_OK;
  471. }
  472. //====================================================================================
  473. //====================================================================================
  474. CS_STATUS
  475. Q931OnCallAlerting(
  476. P_CALL_OBJECT pCallObject,
  477. Q931MESSAGE *pMessage,
  478. Q931_ALERTING_ASN *pAlertingASN)
  479. {
  480. DWORD result;
  481. pCallObject->bCallState = CALLSTATE_DELIVERED;
  482. if (pAlertingASN != NULL)
  483. {
  484. // we could pass h245addr, userinfo, and conferenceid
  485. // if desired later...
  486. // (this would be passed in the pAlertingASN field)
  487. }
  488. Q931StopTimer(pCallObject, Q931_TIMER_303);
  489. Q931StartTimer(pCallObject, Q931_TIMER_301);
  490. result = pCallObject->Callback((BYTE)Q931_CALL_RINGING,
  491. pCallObject->hQ931Call, pCallObject->dwListenToken,
  492. pCallObject->dwUserToken, NULL);
  493. return CS_OK;
  494. }
  495. //====================================================================================
  496. //====================================================================================
  497. CS_STATUS
  498. Q931OnCallConnect(
  499. P_CALL_OBJECT pCallObject,
  500. Q931MESSAGE *pMessage,
  501. Q931_CONNECT_ASN *pConnectASN)
  502. {
  503. DWORD result;
  504. if ((pMessage->CallReference & 0x8000) == 0)
  505. {
  506. // the message came from the caller, so this should be ignored???
  507. }
  508. pMessage->CallReference &= ~(0x8000); // strip off the high bit.
  509. pCallObject->ConferenceID = pConnectASN->ConferenceID;
  510. pCallObject->bCallState = CALLSTATE_ACTIVE;
  511. {
  512. CSS_CALL_ACCEPTED EventData;
  513. WCHAR szUnicodeDisplay[CC_MAX_DISPLAY_LENGTH + 1];
  514. // populate the event data struct.
  515. EventData.ConferenceID = pCallObject->ConferenceID;
  516. if (pCallObject->PeerCallAddrPresent)
  517. {
  518. EventData.pCalleeAddr = &(pCallObject->PeerCallAddr);
  519. }
  520. else
  521. {
  522. EventData.pCalleeAddr = NULL;
  523. }
  524. EventData.pLocalAddr = &(pCallObject->LocalAddr);
  525. EventData.pH245Addr = NULL;
  526. if (pConnectASN->h245AddrPresent)
  527. {
  528. EventData.pH245Addr = &(pConnectASN->h245Addr);
  529. }
  530. if (!(pConnectASN->NonStandardDataPresent) ||
  531. (pConnectASN->NonStandardData.sData.wOctetStringLength == 0) ||
  532. (pConnectASN->NonStandardData.sData.pOctetString == NULL))
  533. {
  534. EventData.pNonStandardData = NULL;
  535. }
  536. else
  537. {
  538. EventData.pNonStandardData = &(pConnectASN->NonStandardData);
  539. }
  540. EventData.pszDisplay = NULL;
  541. if (pMessage->Display.Present && pMessage->Display.Contents)
  542. {
  543. MultiByteToWideChar(CP_ACP, 0, (const char *)pMessage->Display.Contents, -1,
  544. szUnicodeDisplay, sizeof(szUnicodeDisplay) / sizeof(szUnicodeDisplay[0]));
  545. EventData.pszDisplay = szUnicodeDisplay;
  546. }
  547. EventData.pDestinationEndpointType = &(pConnectASN->EndpointType);
  548. EventData.wCallReference = pMessage->CallReference;
  549. Q931StopTimer(pCallObject, Q931_TIMER_303);
  550. Q931StopTimer(pCallObject, Q931_TIMER_301);
  551. result = pCallObject->Callback((BYTE)Q931_CALL_ACCEPTED,
  552. pCallObject->hQ931Call, pCallObject->dwListenToken,
  553. pCallObject->dwUserToken, &EventData);
  554. }
  555. return CS_OK;
  556. }
  557. //====================================================================================
  558. //====================================================================================
  559. CS_STATUS
  560. Q931OnCallReleaseComplete(
  561. P_CALL_OBJECT pCallObject,
  562. Q931MESSAGE *pMessage,
  563. Q931_RELEASE_COMPLETE_ASN *pReleaseCompleteASN)
  564. {
  565. DWORD result;
  566. BYTE bCause = 0;
  567. if (pMessage && pMessage->Cause.Present &&
  568. (pMessage->Cause.Length >= 3))
  569. {
  570. bCause = (BYTE)(pMessage->Cause.Contents[2] & (~CAUSE_EXT_BIT));
  571. }
  572. Q931StopTimer(pCallObject, Q931_TIMER_303);
  573. Q931StopTimer(pCallObject, Q931_TIMER_301);
  574. // if this is the callee, or the call has been connected already,
  575. // then this message should be treated as hangup (not reject).
  576. if (!(pCallObject->fIsCaller) ||
  577. (pCallObject->bCallState == CALLSTATE_ACTIVE) ||
  578. (bCause == CAUSE_VALUE_NORMAL_CLEAR))
  579. {
  580. CSS_CALL_REMOTE_HANGUP EventData;
  581. EventData.bReason = CC_REJECT_NORMAL_CALL_CLEARING;
  582. pCallObject->bCallState = CALLSTATE_NULL;
  583. result = pCallObject->Callback((BYTE)Q931_CALL_REMOTE_HANGUP,
  584. pCallObject->hQ931Call, pCallObject->dwListenToken,
  585. pCallObject->dwUserToken, &EventData);
  586. }
  587. else
  588. {
  589. CSS_CALL_REJECTED EventData;
  590. pCallObject->bCallState = CALLSTATE_NULL;
  591. // populate the event data struct.
  592. switch (bCause)
  593. {
  594. case CAUSE_VALUE_NORMAL_CLEAR:
  595. EventData.bRejectReason = CC_REJECT_NORMAL_CALL_CLEARING;
  596. break;
  597. case CAUSE_VALUE_USER_BUSY:
  598. EventData.bRejectReason = CC_REJECT_USER_BUSY;
  599. break;
  600. case CAUSE_VALUE_SECURITY_DENIED:
  601. EventData.bRejectReason = CC_REJECT_SECURITY_DENIED;
  602. break;
  603. case CAUSE_VALUE_NO_ANSWER:
  604. EventData.bRejectReason = CC_REJECT_NO_ANSWER;
  605. break;
  606. case CAUSE_VALUE_NOT_IMPLEMENTED:
  607. EventData.bRejectReason = CC_REJECT_NOT_IMPLEMENTED;
  608. break;
  609. case CAUSE_VALUE_INVALID_CRV:
  610. EventData.bRejectReason = CC_REJECT_INVALID_IE_CONTENTS;
  611. break;
  612. case CAUSE_VALUE_IE_MISSING:
  613. EventData.bRejectReason = CC_REJECT_MANDATORY_IE_MISSING;
  614. break;
  615. case CAUSE_VALUE_IE_CONTENTS:
  616. EventData.bRejectReason = CC_REJECT_INVALID_IE_CONTENTS;
  617. break;
  618. case CAUSE_VALUE_TIMER_EXPIRED:
  619. EventData.bRejectReason = CC_REJECT_TIMER_EXPIRED;
  620. break;
  621. default:
  622. EventData.bRejectReason = pReleaseCompleteASN->bReason;
  623. break;
  624. }
  625. EventData.ConferenceID = pCallObject->ConferenceID;
  626. EventData.pAlternateAddr = NULL;
  627. if (!(pReleaseCompleteASN->NonStandardDataPresent) ||
  628. (pReleaseCompleteASN->NonStandardData.sData.wOctetStringLength == 0) ||
  629. (pReleaseCompleteASN->NonStandardData.sData.pOctetString == NULL))
  630. {
  631. EventData.pNonStandardData = NULL;
  632. }
  633. else
  634. {
  635. EventData.pNonStandardData = &(pReleaseCompleteASN->NonStandardData);
  636. }
  637. result = pCallObject->Callback((BYTE)Q931_CALL_REJECTED,
  638. pCallObject->hQ931Call, pCallObject->dwListenToken,
  639. pCallObject->dwUserToken, &EventData);
  640. }
  641. return CS_OK;
  642. }
  643. //====================================================================================
  644. //====================================================================================
  645. CS_STATUS
  646. Q931OnCallFacility(
  647. P_CALL_OBJECT pCallObject,
  648. Q931MESSAGE *pMessage,
  649. Q931_FACILITY_ASN *pFacilityASN)
  650. {
  651. DWORD result;
  652. // if this is the callee, or the call has been connected already,
  653. // then this message should be treated as hangup (not reject).
  654. if (!(pCallObject->fIsCaller) ||
  655. (pCallObject->bCallState == CALLSTATE_ACTIVE))
  656. {
  657. CSS_CALL_REMOTE_HANGUP EventData;
  658. EventData.bReason = pFacilityASN->bReason;
  659. pCallObject->bCallState = CALLSTATE_NULL;
  660. result = pCallObject->Callback((BYTE)Q931_CALL_REMOTE_HANGUP,
  661. pCallObject->hQ931Call, pCallObject->dwListenToken,
  662. pCallObject->dwUserToken, &EventData);
  663. }
  664. else
  665. {
  666. CSS_CALL_REJECTED EventData;
  667. pCallObject->bCallState = CALLSTATE_NULL;
  668. // populate the event data struct.
  669. EventData.bRejectReason = pFacilityASN->bReason;
  670. EventData.ConferenceID = pFacilityASN->ConferenceIDPresent ?
  671. pFacilityASN->ConferenceID : pCallObject->ConferenceID;
  672. EventData.pAlternateAddr = &(pFacilityASN->AlternativeAddr);
  673. if (!(pFacilityASN->NonStandardDataPresent) ||
  674. (pFacilityASN->NonStandardData.sData.wOctetStringLength == 0) ||
  675. (pFacilityASN->NonStandardData.sData.pOctetString == NULL))
  676. {
  677. EventData.pNonStandardData = NULL;
  678. }
  679. else
  680. {
  681. EventData.pNonStandardData = &(pFacilityASN->NonStandardData);
  682. }
  683. result = pCallObject->Callback((BYTE)Q931_CALL_REJECTED,
  684. pCallObject->hQ931Call, pCallObject->dwListenToken,
  685. pCallObject->dwUserToken, &EventData);
  686. }
  687. return CS_OK;
  688. }
  689. //====================================================================================
  690. //====================================================================================
  691. CS_STATUS
  692. Q931SendReleaseCompleteMessage(
  693. P_CALL_OBJECT pCallObject,
  694. BYTE bRejectReason,
  695. PCC_CONFERENCEID pConferenceID,
  696. PCC_ADDR pAlternateAddr,
  697. PCC_NONSTANDARDDATA pNonStandardData)
  698. {
  699. CS_STATUS result = CS_OK;
  700. HQ931CALL hQ931Call = pCallObject->hQ931Call;
  701. // since this call is going away, mark the call object for deletion so any other
  702. // threads attempting to use this object will fail to get a lock on it.
  703. CallObjectMarkForDelete(hQ931Call);
  704. if((bRejectReason == CC_REJECT_ROUTE_TO_GATEKEEPER) ||
  705. (bRejectReason == CC_REJECT_CALL_FORWARDED) ||
  706. (bRejectReason == CC_REJECT_ROUTE_TO_MC))
  707. {
  708. // send the FACILITY message to the peer to reject the call.
  709. DWORD CodedLengthASN;
  710. BYTE *CodedPtrASN;
  711. HRESULT ResultASN = CS_OK;
  712. CC_ADDR AltAddr;
  713. MakeBinaryADDR(pAlternateAddr, &AltAddr);
  714. ResultASN = Q931FacilityEncodeASN(pNonStandardData,
  715. (pAlternateAddr ? &AltAddr : NULL),
  716. bRejectReason, pConferenceID, NULL, &pCallObject->World,
  717. &CodedPtrASN, &CodedLengthASN, &pCallObject->CallIdentifier);
  718. if ((ResultASN != CS_OK) || (CodedLengthASN == 0) ||
  719. (CodedPtrASN == NULL))
  720. {
  721. ISRERROR(ghISRInst, "Q931FacilityEncodeASN() failed, nothing to send.", 0L);
  722. if (CodedPtrASN != NULL)
  723. {
  724. Q931FreeEncodedBuffer(&pCallObject->World, CodedPtrASN);
  725. }
  726. result = CS_INTERNAL_ERROR;
  727. }
  728. else
  729. {
  730. DWORD CodedLengthPDU;
  731. BYTE *CodedPtrPDU;
  732. BINARY_STRING UserUserData;
  733. HRESULT ResultEncode = CS_OK;
  734. WORD wCRV;
  735. if (pCallObject->fIsCaller)
  736. {
  737. wCRV = (WORD)(pCallObject->wCRV & 0x7FFF);
  738. }
  739. else
  740. {
  741. wCRV = (WORD)(pCallObject->wCRV | 0x8000);
  742. }
  743. UserUserData.length = (WORD)CodedLengthASN;
  744. UserUserData.ptr = CodedPtrASN;
  745. ResultEncode = Q931FacilityEncodePDU(wCRV,
  746. &UserUserData, &CodedPtrPDU, &CodedLengthPDU);
  747. if (CodedPtrASN != NULL)
  748. {
  749. Q931FreeEncodedBuffer(&pCallObject->World, CodedPtrASN);
  750. }
  751. if ((ResultEncode != CS_OK) || (CodedLengthPDU == 0) ||
  752. (CodedPtrPDU == NULL))
  753. {
  754. ISRERROR(ghISRInst, "Q931FacilityEncodePDU() failed, nothing to send.", 0L);
  755. if (CodedPtrPDU != NULL)
  756. {
  757. MemFree(CodedPtrPDU);
  758. }
  759. result = CS_INTERNAL_ERROR;
  760. }
  761. else
  762. {
  763. result = Q931SendMessage(pCallObject, CodedPtrPDU, CodedLengthPDU, FALSE);
  764. }
  765. }
  766. }
  767. else
  768. {
  769. // send the RELEASE COMPLETE message to the peer to reject call.
  770. DWORD CodedLengthASN;
  771. BYTE *CodedPtrASN;
  772. HRESULT ResultASN = CS_OK;
  773. BYTE bReasonUU = bRejectReason;
  774. BYTE *pbReasonUU = &bReasonUU;
  775. switch (bReasonUU)
  776. {
  777. case CC_REJECT_NO_BANDWIDTH: //noBandwidth_chosen
  778. case CC_REJECT_GATEKEEPER_RESOURCES: // gatekeeperResources_chosen
  779. case CC_REJECT_UNREACHABLE_DESTINATION: // unreachableDestination_chosen
  780. case CC_REJECT_DESTINATION_REJECTION: // destinationRejection_chosen
  781. case CC_REJECT_INVALID_REVISION: // ReleaseCompleteReason_invalidRevision_chosen
  782. case CC_REJECT_NO_PERMISSION: // noPermission_chosen
  783. case CC_REJECT_UNREACHABLE_GATEKEEPER: // unreachableGatekeeper_chosen
  784. case CC_REJECT_GATEWAY_RESOURCES: // gatewayResources_chosen
  785. case CC_REJECT_BAD_FORMAT_ADDRESS: // badFormatAddress_chosen
  786. case CC_REJECT_ADAPTIVE_BUSY: // adaptiveBusy_chosen
  787. case CC_REJECT_IN_CONF: // inConf_chosen
  788. case CC_REJECT_UNDEFINED_REASON: // ReleaseCompleteReason_undefinedReason_chosen
  789. case CC_REJECT_INTERNAL_ERROR: // will be mapped to ReleaseCompleteReason_undefinedReason_chosen
  790. case CC_REJECT_NORMAL_CALL_CLEARING: // will be mapped to ReleaseCompleteReason_undefinedReason_chosen
  791. case CC_REJECT_USER_BUSY: // will be mapped to inConf_chosen
  792. case CC_REJECT_CALL_DEFLECTION: // facilityCallDeflection_chosen
  793. case CC_REJECT_SECURITY_DENIED: // securityDenied_chosen
  794. break;
  795. default:
  796. pbReasonUU = NULL;
  797. break;
  798. }
  799. ResultASN = Q931ReleaseCompleteEncodeASN(pNonStandardData,
  800. pConferenceID, pbReasonUU, &pCallObject->World,
  801. &CodedPtrASN, &CodedLengthASN, &pCallObject->CallIdentifier);
  802. if ((ResultASN != CS_OK) || (CodedLengthASN == 0) ||
  803. (CodedPtrASN == NULL))
  804. {
  805. ISRERROR(ghISRInst, "Q931ReleaseCompleteEncodeASN() failed, nothing to send.", 0L);
  806. if (CodedPtrASN != NULL)
  807. {
  808. Q931FreeEncodedBuffer(&pCallObject->World, CodedPtrASN);
  809. }
  810. result = CS_INTERNAL_ERROR;
  811. }
  812. else
  813. {
  814. DWORD CodedLengthPDU;
  815. BYTE *CodedPtrPDU;
  816. BINARY_STRING UserUserData;
  817. HRESULT ResultEncode = CS_OK;
  818. BYTE bCause = 0;
  819. BYTE *pbCause = &bCause;
  820. WORD wCRV;
  821. if (pCallObject->fIsCaller)
  822. {
  823. wCRV = (WORD)(pCallObject->wCRV & 0x7FFF);
  824. }
  825. else
  826. {
  827. wCRV = (WORD)(pCallObject->wCRV | 0x8000);
  828. }
  829. UserUserData.length = (WORD)CodedLengthASN;
  830. UserUserData.ptr = CodedPtrASN;
  831. switch (bRejectReason)
  832. {
  833. case CC_REJECT_NORMAL_CALL_CLEARING:
  834. bCause = CAUSE_VALUE_NORMAL_CLEAR;
  835. break;
  836. case CC_REJECT_USER_BUSY:
  837. bCause = CAUSE_VALUE_USER_BUSY;
  838. break;
  839. case CC_REJECT_SECURITY_DENIED:
  840. bCause = CAUSE_VALUE_SECURITY_DENIED;
  841. break;
  842. case CC_REJECT_NO_ANSWER:
  843. bCause = CAUSE_VALUE_NO_ANSWER;
  844. break;
  845. case CC_REJECT_NOT_IMPLEMENTED:
  846. bCause = CAUSE_VALUE_NOT_IMPLEMENTED;
  847. break;
  848. case CC_REJECT_MANDATORY_IE_MISSING:
  849. bCause = CAUSE_VALUE_IE_MISSING;
  850. break;
  851. case CC_REJECT_INVALID_IE_CONTENTS:
  852. bCause = CAUSE_VALUE_IE_CONTENTS;
  853. break;
  854. case CC_REJECT_TIMER_EXPIRED:
  855. bCause = CAUSE_VALUE_TIMER_EXPIRED;
  856. break;
  857. default:
  858. pbCause = NULL;
  859. break;
  860. }
  861. ResultEncode = Q931ReleaseCompleteEncodePDU(wCRV,
  862. pbCause, &UserUserData,
  863. &CodedPtrPDU, &CodedLengthPDU);
  864. if (CodedPtrASN != NULL)
  865. {
  866. Q931FreeEncodedBuffer(&pCallObject->World, CodedPtrASN);
  867. }
  868. if ((ResultEncode != CS_OK) || (CodedLengthPDU == 0) ||
  869. (CodedPtrPDU == NULL))
  870. {
  871. ISRERROR(ghISRInst, "Q931ReleaseCompleteEncodePDU() failed, nothing to send.", 0L);
  872. if (CodedPtrPDU != NULL)
  873. {
  874. MemFree(CodedPtrPDU);
  875. }
  876. result = CS_INTERNAL_ERROR;
  877. }
  878. else
  879. {
  880. result = Q931SendMessage(pCallObject, CodedPtrPDU, CodedLengthPDU, FALSE);
  881. }
  882. }
  883. }
  884. pCallObject->bCallState = CALLSTATE_NULL;
  885. if (result != CS_OK)
  886. {
  887. return result;
  888. }
  889. return CS_OK;
  890. }
  891. //====================================================================================
  892. //====================================================================================
  893. CS_STATUS
  894. Q931SendStatusMessage(
  895. P_CALL_OBJECT pCallObject,
  896. Q931MESSAGE *pMessage,
  897. BYTE bCause)
  898. {
  899. CS_STATUS result = CS_OK;
  900. DWORD CodedLengthPDU;
  901. BYTE *CodedPtrPDU;
  902. HRESULT EncodePDU = CS_OK;
  903. int nError = 0;
  904. HQ931CALL hQ931Call = pCallObject->hQ931Call;
  905. WORD wCRV;
  906. if (pCallObject->fIsCaller)
  907. {
  908. wCRV = (WORD)(pCallObject->wCRV & 0x7FFF);
  909. }
  910. else
  911. {
  912. wCRV = (WORD)(pCallObject->wCRV | 0x8000);
  913. }
  914. EncodePDU = Q931StatusEncodePDU(wCRV, NULL, bCause,
  915. pCallObject->bCallState, &CodedPtrPDU, &CodedLengthPDU);
  916. if ((EncodePDU != CS_OK) || (CodedLengthPDU == 0) ||
  917. (CodedPtrPDU == NULL))
  918. {
  919. ISRERROR(ghISRInst, "Q931StatusEncodePDU() failed, nothing to send.", 0L);
  920. if (CodedPtrPDU != NULL)
  921. {
  922. MemFree(CodedPtrPDU);
  923. }
  924. result = CS_INTERNAL_ERROR;
  925. }
  926. else
  927. {
  928. result = Q931SendMessage(pCallObject, CodedPtrPDU, CodedLengthPDU, TRUE);
  929. if(CallObjectValidate(hQ931Call) != CS_OK)
  930. return(CS_INTERNAL_ERROR);
  931. }
  932. return(result);
  933. }
  934. //====================================================================================
  935. //====================================================================================
  936. CS_STATUS
  937. Q931SendProceedingMessage(
  938. HQ931CALL hQ931Call,
  939. WORD wCallReference,
  940. PCC_ENDPOINTTYPE pDestinationEndpointType,
  941. PCC_NONSTANDARDDATA pNonStandardData)
  942. {
  943. CS_STATUS result = CS_OK;
  944. DWORD CodedLengthASN;
  945. BYTE *CodedPtrASN;
  946. HRESULT ResultASN = CS_OK;
  947. DWORD dwPhysicalId = INVALID_PHYS_ID;
  948. P_CALL_OBJECT pCallObject = NULL;
  949. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  950. {
  951. ISRERROR(ghISRInst, "CallObjectLock() returned error", 0L);
  952. return CS_SUBSYSTEM_FAILURE;
  953. }
  954. dwPhysicalId = pCallObject->dwPhysicalId;
  955. // first build the ASN portion of the message (user to user part)
  956. ResultASN = Q931ProceedingEncodeASN(
  957. pNonStandardData,
  958. NULL, // No H245 address.
  959. pDestinationEndpointType, // EndpointType information.
  960. &pCallObject->World,
  961. &CodedPtrASN,
  962. &CodedLengthASN,
  963. &pCallObject->CallIdentifier);
  964. if ((ResultASN != CS_OK) || (CodedLengthASN == 0) ||
  965. (CodedPtrASN == NULL))
  966. {
  967. ISRERROR(ghISRInst, "Q931ProceedingEncodeASN() failed, nothing to send.", 0L);
  968. if (CodedPtrASN != NULL)
  969. {
  970. Q931FreeEncodedBuffer(&pCallObject->World, CodedPtrASN);
  971. }
  972. result = CS_INTERNAL_ERROR;
  973. }
  974. else
  975. {
  976. // now build the rest of the message
  977. DWORD CodedLengthPDU;
  978. BYTE *CodedPtrPDU;
  979. BINARY_STRING UserUserData;
  980. HRESULT ResultEncode = CS_OK;
  981. WORD wCRV = (WORD)(wCallReference | 0x8000);
  982. UserUserData.length = (WORD)CodedLengthASN;
  983. UserUserData.ptr = CodedPtrASN;
  984. ResultEncode = Q931ProceedingEncodePDU(wCRV,
  985. &UserUserData, &CodedPtrPDU, &CodedLengthPDU);
  986. if (CodedPtrASN != NULL)
  987. {
  988. Q931FreeEncodedBuffer(&pCallObject->World, CodedPtrASN);
  989. }
  990. if ((ResultEncode != CS_OK) || (CodedLengthPDU == 0) ||
  991. (CodedPtrPDU == NULL))
  992. {
  993. ISRERROR(ghISRInst, "Q931ProceedingEncodePDU() failed, nothing to send.", 0L);
  994. if (CodedPtrPDU != NULL)
  995. {
  996. MemFree(CodedPtrPDU);
  997. }
  998. result = CS_INTERNAL_ERROR;
  999. }
  1000. else
  1001. {
  1002. result = Q931SendMessage(pCallObject, CodedPtrPDU, CodedLengthPDU, TRUE);
  1003. if (CallObjectValidate(hQ931Call) != CS_OK)
  1004. {
  1005. CallEntryUnlock(hQ931Call);
  1006. return(CS_INTERNAL_ERROR);
  1007. }
  1008. }
  1009. }
  1010. CallObjectUnlock(pCallObject);
  1011. return(result);
  1012. }
  1013. //====================================================================================
  1014. //====================================================================================
  1015. CS_STATUS
  1016. Q931SendPDU(HQ931CALL hQ931Call, BYTE* CodedPtrPDU, DWORD CodedLengthPDU)
  1017. {
  1018. CS_STATUS result = CS_OK;
  1019. HRESULT TempResult;
  1020. P_CALL_OBJECT pCallObject = NULL;
  1021. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) ||
  1022. (pCallObject == NULL))
  1023. {
  1024. ISRERROR(ghISRInst, "CallObjectLock() returned error", 0L);
  1025. return CS_SUBSYSTEM_FAILURE;
  1026. }
  1027. TempResult = Q931SendMessage(pCallObject, CodedPtrPDU, CodedLengthPDU, TRUE);
  1028. if (CallObjectValidate(hQ931Call) != CS_OK)
  1029. {
  1030. CallEntryUnlock(hQ931Call);
  1031. return(CS_INTERNAL_ERROR);
  1032. }
  1033. if(FAILED(TempResult))
  1034. {
  1035. CSS_CALL_FAILED EventData;
  1036. EventData.error = TempResult;
  1037. if ((pCallObject->bCallState == CALLSTATE_ACTIVE) &&
  1038. (pCallObject->bResolved))
  1039. {
  1040. pCallObject->Callback(Q931_CALL_CONNECTION_CLOSED,
  1041. pCallObject->hQ931Call, pCallObject->dwListenToken,
  1042. pCallObject->dwUserToken, NULL);
  1043. }
  1044. else
  1045. {
  1046. pCallObject->Callback(Q931_CALL_FAILED,
  1047. pCallObject->hQ931Call, pCallObject->dwListenToken,
  1048. pCallObject->dwUserToken, &EventData);
  1049. }
  1050. if (CallObjectValidate(hQ931Call) == CS_OK)
  1051. {
  1052. DWORD dwId = pCallObject->dwPhysicalId;
  1053. if ((pCallObject->bCallState != CALLSTATE_ACTIVE) ||
  1054. (!pCallObject->bResolved))
  1055. {
  1056. CallObjectDestroy(pCallObject);
  1057. pCallObject = NULL;
  1058. }
  1059. linkLayerShutdown(dwId);
  1060. if (pCallObject)
  1061. {
  1062. pCallObject->bConnected = FALSE;
  1063. }
  1064. }
  1065. else
  1066. {
  1067. CallEntryUnlock(hQ931Call);
  1068. }
  1069. return TempResult;
  1070. }
  1071. CallObjectUnlock(pCallObject);
  1072. return CS_OK;
  1073. }
  1074. //====================================================================================
  1075. //====================================================================================
  1076. CS_STATUS
  1077. Q931OnCallStatusEnquiry(
  1078. P_CALL_OBJECT pCallObject,
  1079. Q931MESSAGE *pMessage)
  1080. {
  1081. CS_STATUS SendStatus;
  1082. SendStatus = Q931SendStatusMessage(pCallObject, pMessage,
  1083. CAUSE_VALUE_ENQUIRY_RESPONSE);
  1084. return SendStatus;
  1085. }
  1086. //====================================================================================
  1087. //====================================================================================
  1088. void
  1089. Q931SendComplete(DWORD_PTR instance, HRESULT msg, PBYTE buf, DWORD length)
  1090. {
  1091. HQ931CALL hQ931Call = (HQ931CALL)instance;
  1092. P_CALL_OBJECT pCallObject = NULL;
  1093. ISRTRACE(ghISRInst, "Entering Q931SendComplete()...", 0L);
  1094. if (buf != NULL)
  1095. {
  1096. MemFree(buf);
  1097. }
  1098. if (FAILED(msg))
  1099. {
  1100. // shut down link layer; report failure to client
  1101. CSS_CALL_FAILED EventData;
  1102. ISRERROR(ghISRInst, "error in datalinkSendRequest()", 0L);
  1103. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  1104. {
  1105. ISRERROR(ghISRInst, "CallObjectLock() returned error", 0L);
  1106. return;
  1107. }
  1108. EventData.error = msg;
  1109. if ((pCallObject->bCallState == CALLSTATE_ACTIVE) &&
  1110. (pCallObject->bResolved))
  1111. {
  1112. pCallObject->Callback(Q931_CALL_CONNECTION_CLOSED,
  1113. pCallObject->hQ931Call, pCallObject->dwListenToken,
  1114. pCallObject->dwUserToken, NULL);
  1115. }
  1116. else
  1117. {
  1118. pCallObject->Callback(Q931_CALL_FAILED,
  1119. pCallObject->hQ931Call, pCallObject->dwListenToken,
  1120. pCallObject->dwUserToken, &EventData);
  1121. }
  1122. if (CallObjectValidate(hQ931Call) == CS_OK)
  1123. {
  1124. DWORD dwId = pCallObject->dwPhysicalId;
  1125. if ((pCallObject->bCallState != CALLSTATE_ACTIVE) ||
  1126. (!pCallObject->bResolved))
  1127. {
  1128. CallObjectDestroy(pCallObject);
  1129. pCallObject = NULL;
  1130. }
  1131. linkLayerShutdown(dwId);
  1132. if (pCallObject)
  1133. {
  1134. pCallObject->bConnected = FALSE;
  1135. }
  1136. }
  1137. else
  1138. {
  1139. CallEntryUnlock(hQ931Call);
  1140. }
  1141. return;
  1142. }
  1143. return;
  1144. }
  1145. //====================================================================================
  1146. //====================================================================================
  1147. static DWORD
  1148. PostReceiveBuffer(DWORD dwPhysicalId, BYTE *buf)
  1149. {
  1150. HRESULT hr = S_OK;
  1151. BOOL bAllocated = FALSE;
  1152. if (buf == NULL)
  1153. {
  1154. buf = MemAlloc(RECEIVE_BUFFER_SIZE);
  1155. bAllocated = TRUE;
  1156. }
  1157. hr = datalinkReceiveRequest(dwPhysicalId, buf, RECEIVE_BUFFER_SIZE);
  1158. if (FAILED(hr) && bAllocated)
  1159. {
  1160. MemFree(buf);
  1161. }
  1162. return hr;
  1163. }
  1164. //====================================================================================
  1165. //====================================================================================
  1166. void
  1167. OnReceiveCallback(DWORD_PTR instance, HRESULT message, Q931MESSAGE *pMessage, BYTE *buf, DWORD nbytes)
  1168. {
  1169. HQ931CALL hQ931Call = (HQ931CALL)instance;
  1170. P_CALL_OBJECT pCallObject = NULL;
  1171. DWORD dwPhysicalId;
  1172. ISRTRACE(ghISRInst, "Entering ReceiveCallback()...", 0L);
  1173. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  1174. {
  1175. if (buf)
  1176. {
  1177. MemFree(buf);
  1178. }
  1179. ISRTRACE(ghISRInst, "Call Object no longer available:", (DWORD)hQ931Call);
  1180. return;
  1181. }
  1182. if (message == LINK_RECV_DATA)
  1183. {
  1184. HRESULT Result = CS_OK;
  1185. if ((buf == NULL) || (nbytes == 0))
  1186. {
  1187. ISRERROR(ghISRInst, "Empty buffer received as data.", 0L);
  1188. CallObjectUnlock(pCallObject);
  1189. return;
  1190. }
  1191. // This block is the Q931 call re-connect implementation:
  1192. // if the object related to the incoming message is not yet resolved...
  1193. if (pCallObject->bResolved == FALSE)
  1194. {
  1195. // try to resolve the object.
  1196. HQ931CALL hFoundCallObject;
  1197. P_CALL_OBJECT pFoundCallObject = NULL;
  1198. // If found another object with matching CRV/Addr...
  1199. if (CallObjectFind(&hFoundCallObject, pCallObject->wCRV,
  1200. &(pCallObject->PeerConnectAddr)) &&
  1201. ((CallObjectLock(hFoundCallObject, &pFoundCallObject) == CS_OK) &&
  1202. (pFoundCallObject != NULL)))
  1203. {
  1204. // friendly channel close of the pFoundCallObject.
  1205. Q931SendReleaseCompleteMessage(pFoundCallObject,
  1206. CC_REJECT_UNDEFINED_REASON, &(pFoundCallObject->ConferenceID), NULL, NULL);
  1207. // unlock the call object before calling shutdown
  1208. CallObjectUnlock(pFoundCallObject);
  1209. linkLayerShutdown(pFoundCallObject->dwPhysicalId);
  1210. if((CallObjectLock(hFoundCallObject, &pFoundCallObject) != CS_OK) ||
  1211. (pFoundCallObject == NULL))
  1212. return;
  1213. // assign the new dwPhysicalId to found object.
  1214. pFoundCallObject->dwPhysicalId = pCallObject->dwPhysicalId;
  1215. // new object should be destroyed.
  1216. CallObjectDestroy(pCallObject);
  1217. pCallObject = pFoundCallObject;
  1218. }
  1219. else
  1220. {
  1221. // The call is a newly established call, so resolve it now.
  1222. pCallObject->bResolved = TRUE;
  1223. }
  1224. }
  1225. Result = Q931ParseMessage((BYTE *)buf, nbytes, pMessage);
  1226. #if (defined(_DEBUG) || defined(PCS_COMPLIANCE))
  1227. InteropOutput(Q931Logger, buf, nbytes, Q931LOG_RECEIVED_PDU);
  1228. #endif
  1229. if (Result != CS_OK)
  1230. {
  1231. Result = Q931SendStatusMessage(pCallObject, pMessage,
  1232. CAUSE_VALUE_INVALID_MSG);
  1233. ISRERROR(ghISRInst, "Q931ParseMessage(): failed.", 0L);
  1234. if(CallObjectValidate(hQ931Call) != CS_OK)
  1235. {
  1236. if (buf)
  1237. {
  1238. MemFree(buf);
  1239. }
  1240. CallEntryUnlock(hQ931Call);
  1241. return;
  1242. }
  1243. dwPhysicalId = pCallObject->dwPhysicalId;
  1244. CallObjectUnlock(pCallObject);
  1245. PostReceiveBuffer(dwPhysicalId, buf);
  1246. return;
  1247. }
  1248. if (pMessage->Shift.Present)
  1249. {
  1250. ISRERROR(ghISRInst, "Shift present in message: dropped.", 0L);
  1251. dwPhysicalId = pCallObject->dwPhysicalId;
  1252. CallObjectUnlock(pCallObject);
  1253. PostReceiveBuffer(dwPhysicalId, buf);
  1254. return;
  1255. }
  1256. // If a hooking procedure has been installed,
  1257. // give it first shot at acting on the received PDU.
  1258. // If it returns TRUE, then processing is finished.
  1259. if (gReceivePDUHookProc)
  1260. {
  1261. BOOL bHookProcessedMessage;
  1262. bHookProcessedMessage = gReceivePDUHookProc(pMessage,
  1263. pCallObject->hQ931Call, pCallObject->dwListenToken,
  1264. pCallObject->dwUserToken);
  1265. if (bHookProcessedMessage)
  1266. {
  1267. if (CallObjectValidate(hQ931Call) == CS_OK)
  1268. {
  1269. dwPhysicalId = pCallObject->dwPhysicalId;
  1270. CallObjectUnlock(pCallObject);
  1271. PostReceiveBuffer(dwPhysicalId, buf);
  1272. }
  1273. else
  1274. {
  1275. CallEntryUnlock(hQ931Call);
  1276. }
  1277. return;
  1278. }
  1279. }
  1280. // Message now contains the values of the Q931 PDU elements...
  1281. switch (pMessage->MessageType)
  1282. {
  1283. case SETUPMESSAGETYPE:
  1284. {
  1285. Q931_SETUP_ASN SetupASN;
  1286. if (!pMessage->UserToUser.Present || (pMessage->UserToUser.UserInformationLength == 0))
  1287. {
  1288. ISRERROR(ghISRInst, "ReceiveCallback(): Message is missing ASN.1 UserUser data...", 0L);
  1289. dwPhysicalId = pCallObject->dwPhysicalId;
  1290. CallObjectUnlock(pCallObject);
  1291. PostReceiveBuffer(dwPhysicalId, buf);
  1292. return;
  1293. }
  1294. ISRTRACE(ghISRInst, "ReceiveCallback(): received Setup message...", 0L);
  1295. Result = Q931SetupParseASN(&pCallObject->World, pMessage->UserToUser.UserInformation,
  1296. pMessage->UserToUser.UserInformationLength, &SetupASN);
  1297. if (Result == CS_OPTION_NOT_IMPLEMENTED)
  1298. {
  1299. //... maybe callback callcont in later drop.
  1300. // initiate a disconnect sequence from the caller side.
  1301. if (Q931SendReleaseCompleteMessage(pCallObject,
  1302. CC_REJECT_TIMER_EXPIRED, NULL, NULL, NULL) != CS_OK)
  1303. {
  1304. // nothing to do if this fails.
  1305. }
  1306. dwPhysicalId = pCallObject->dwPhysicalId;
  1307. CallObjectDestroy(pCallObject);
  1308. linkLayerShutdown(dwPhysicalId);
  1309. if (buf)
  1310. {
  1311. MemFree(buf);
  1312. buf = NULL;
  1313. }
  1314. return;
  1315. }
  1316. if (Result != CS_OK)
  1317. {
  1318. ISRERROR(ghISRInst, "ReceiveCallback(): Unable to parse ASN.1 data.", 0L);
  1319. break;
  1320. }
  1321. // The "CallerAddr is not passed in the PDU, so the
  1322. // only valuable addr to use is the connection addr
  1323. // passed from the link layer and saved into the call
  1324. // object at connect-time.
  1325. SetupASN.CallerAddrPresent = TRUE;
  1326. SetupASN.CallerAddr = pCallObject->PeerConnectAddr;
  1327. // The "CalleeAddr" which is passed in the PDU is ignored
  1328. // by the ASN parser, and supplied by the link layer
  1329. // instead and saved into the call object at connect-time.
  1330. // here, this address is used as the callee addr.
  1331. SetupASN.CalleeAddrPresent = TRUE;
  1332. SetupASN.CalleeAddr = pCallObject->LocalAddr;
  1333. Result = Q931OnCallSetup(pCallObject, pMessage, &SetupASN);
  1334. _FreeSetupASN(&SetupASN);
  1335. }
  1336. break;
  1337. case RELEASECOMPLMESSAGETYPE:
  1338. {
  1339. Q931_RELEASE_COMPLETE_ASN ReleaseCompleteASN;
  1340. if (!pMessage->UserToUser.Present || (pMessage->UserToUser.UserInformationLength == 0))
  1341. {
  1342. ISRERROR(ghISRInst, "ReceiveCallback(): Message is missing ASN.1 UserUser data...", 0L);
  1343. dwPhysicalId = pCallObject->dwPhysicalId;
  1344. CallObjectUnlock(pCallObject);
  1345. PostReceiveBuffer(dwPhysicalId, buf);
  1346. return;
  1347. }
  1348. ISRTRACE(ghISRInst, "ReceiveCallback(): received ReleaseComplete message...", 0L);
  1349. Result = Q931ReleaseCompleteParseASN(&pCallObject->World,
  1350. pMessage->UserToUser.UserInformation,
  1351. pMessage->UserToUser.UserInformationLength, &ReleaseCompleteASN);
  1352. if (Result != CS_OK)
  1353. {
  1354. ISRERROR(ghISRInst, "ReceiveCallback(): Unable to parse ASN.1 data.", 0L);
  1355. break;
  1356. }
  1357. Result = Q931OnCallReleaseComplete(pCallObject, pMessage, &ReleaseCompleteASN);
  1358. if (CallObjectValidate(hQ931Call) == CS_OK)
  1359. {
  1360. dwPhysicalId = pCallObject->dwPhysicalId;
  1361. CallObjectDestroy(pCallObject);
  1362. linkLayerShutdown(dwPhysicalId);
  1363. }
  1364. else
  1365. {
  1366. CallEntryUnlock(hQ931Call);
  1367. }
  1368. MemFree(buf);
  1369. _FreeReleaseCompleteASN(&ReleaseCompleteASN);
  1370. return;
  1371. }
  1372. break;
  1373. case FACILITYMESSAGETYPE:
  1374. {
  1375. Q931_FACILITY_ASN FacilityASN;
  1376. if (!pMessage->UserToUser.Present || (pMessage->UserToUser.UserInformationLength == 0))
  1377. {
  1378. ISRERROR(ghISRInst, "ReceiveCallback(): Message is missing ASN.1 UserUser data...", 0L);
  1379. dwPhysicalId = pCallObject->dwPhysicalId;
  1380. CallObjectUnlock(pCallObject);
  1381. PostReceiveBuffer(dwPhysicalId, buf);
  1382. return;
  1383. }
  1384. ISRTRACE(ghISRInst, "ReceiveCallback(): received Facility message...", 0L);
  1385. Result = Q931FacilityParseASN(&pCallObject->World, pMessage->UserToUser.UserInformation,
  1386. pMessage->UserToUser.UserInformationLength, &FacilityASN);
  1387. if (Result != CS_OK)
  1388. {
  1389. ISRERROR(ghISRInst, "ReceiveCallback(): Unable to parse ASN.1 data.", 0L);
  1390. break;
  1391. }
  1392. // initiate a disconnect sequence from the caller side.
  1393. Q931SendReleaseCompleteMessage(pCallObject,
  1394. CC_REJECT_CALL_DEFLECTION, NULL, NULL, NULL);
  1395. Result = Q931OnCallFacility(pCallObject, pMessage, &FacilityASN);
  1396. _FreeFacilityASN(&FacilityASN);
  1397. dwPhysicalId = pCallObject->dwPhysicalId;
  1398. CallObjectDestroy(pCallObject);
  1399. linkLayerShutdown(dwPhysicalId);
  1400. MemFree(buf);
  1401. return;
  1402. }
  1403. break;
  1404. case CONNECTMESSAGETYPE:
  1405. {
  1406. Q931_CONNECT_ASN ConnectASN;
  1407. if (!pMessage->UserToUser.Present || (pMessage->UserToUser.UserInformationLength == 0))
  1408. {
  1409. ISRERROR(ghISRInst, "ReceiveCallback(): Message is missing ASN.1 UserUser data...", 0L);
  1410. dwPhysicalId = pCallObject->dwPhysicalId;
  1411. CallObjectUnlock(pCallObject);
  1412. PostReceiveBuffer(dwPhysicalId, buf);
  1413. return;
  1414. }
  1415. ISRTRACE(ghISRInst, "ReceiveCallback(): received Connect message...", 0L);
  1416. Result = Q931ConnectParseASN(&pCallObject->World, pMessage->UserToUser.UserInformation,
  1417. pMessage->UserToUser.UserInformationLength, &ConnectASN);
  1418. if (Result != CS_OK)
  1419. {
  1420. ISRERROR(ghISRInst, "ReceiveCallback(): Unable to parse ASN.1 data.", 0L);
  1421. break;
  1422. }
  1423. Result = Q931OnCallConnect(pCallObject, pMessage, &ConnectASN);
  1424. _FreeConnectASN(&ConnectASN);
  1425. }
  1426. break;
  1427. case PROCEEDINGMESSAGETYPE:
  1428. {
  1429. Q931_CALL_PROCEEDING_ASN ProceedingASN;
  1430. ISRTRACE(ghISRInst, "ReceiveCallback(): received Proceeding message...", 0L);
  1431. if (!pMessage->UserToUser.Present || (pMessage->UserToUser.UserInformationLength == 0))
  1432. {
  1433. Result = Q931OnCallProceeding(pCallObject, pMessage, NULL);
  1434. }
  1435. else
  1436. {
  1437. Result = Q931ProceedingParseASN(&pCallObject->World, pMessage->UserToUser.UserInformation,
  1438. pMessage->UserToUser.UserInformationLength, &ProceedingASN);
  1439. if (Result != CS_OK)
  1440. {
  1441. ISRERROR(ghISRInst, "ReceiveCallback(): Unable to parse ASN.1 data.", 0L);
  1442. break;
  1443. }
  1444. Result = Q931OnCallProceeding(pCallObject, pMessage, &ProceedingASN);
  1445. _FreeProceedingASN(&ProceedingASN);
  1446. }
  1447. }
  1448. break;
  1449. case ALERTINGMESSAGETYPE:
  1450. {
  1451. Q931_ALERTING_ASN AlertingASN;
  1452. ISRTRACE(ghISRInst, "ReceiveCallback(): received Alerting message...", 0L);
  1453. if (!pMessage->UserToUser.Present || (pMessage->UserToUser.UserInformationLength == 0))
  1454. {
  1455. Result = Q931OnCallAlerting(pCallObject, pMessage, NULL);
  1456. }
  1457. else
  1458. {
  1459. Result = Q931AlertingParseASN(&pCallObject->World, pMessage->UserToUser.UserInformation,
  1460. pMessage->UserToUser.UserInformationLength, &AlertingASN);
  1461. if (Result != CS_OK)
  1462. {
  1463. ISRERROR(ghISRInst, "ReceiveCallback(): Unable to parse ASN.1 data.", 0L);
  1464. break;
  1465. }
  1466. Result = Q931OnCallAlerting(pCallObject, pMessage, &AlertingASN);
  1467. _FreeAlertingASN(&AlertingASN);
  1468. }
  1469. }
  1470. break;
  1471. case RELEASEMESSAGETYPE:
  1472. case STATUSMESSAGETYPE:
  1473. ISRWARNING(ghISRInst, "ReceiveCallback(): message not yet supported.", 0L);
  1474. break;
  1475. case STATUSENQUIRYMESSAGETYPE:
  1476. ISRWARNING(ghISRInst, "ReceiveCallback(): message not yet supported.", 0L);
  1477. Result = Q931OnCallStatusEnquiry(pCallObject, pMessage);
  1478. break;
  1479. default:
  1480. ISRERROR(ghISRInst, "ReceiveCallback(): unknown message received.", 0L);
  1481. break;
  1482. }
  1483. // re-validate the call object:
  1484. if (CallObjectValidate(hQ931Call) == CS_OK)
  1485. {
  1486. dwPhysicalId = pCallObject->dwPhysicalId;
  1487. CallObjectUnlock(pCallObject);
  1488. PostReceiveBuffer(dwPhysicalId, buf);
  1489. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  1490. return;
  1491. }
  1492. else
  1493. {
  1494. if (buf)
  1495. {
  1496. MemFree(buf);
  1497. }
  1498. CallEntryUnlock(hQ931Call);
  1499. return;
  1500. }
  1501. if (Result == CS_INCOMPATIBLE_VERSION)
  1502. {
  1503. // initiate a disconnect sequence from the caller side.
  1504. Q931SendReleaseCompleteMessage(pCallObject,
  1505. CC_REJECT_INVALID_REVISION, NULL, NULL, NULL);
  1506. dwPhysicalId = pCallObject->dwPhysicalId;
  1507. CallObjectDestroy(pCallObject);
  1508. linkLayerShutdown(dwPhysicalId);
  1509. return;
  1510. }
  1511. if (Result == CS_MANDATORY_IE_MISSING)
  1512. {
  1513. Q931SendStatusMessage(pCallObject, pMessage,
  1514. CAUSE_VALUE_IE_MISSING);
  1515. }
  1516. else if (Result == CS_BAD_IE_CONTENT)
  1517. {
  1518. Q931SendStatusMessage(pCallObject, pMessage,
  1519. CAUSE_VALUE_IE_CONTENTS);
  1520. }
  1521. }
  1522. else if (message == LINK_RECV_CLOSED)
  1523. {
  1524. // Socket closed
  1525. if (buf)
  1526. {
  1527. MemFree(buf);
  1528. }
  1529. pCallObject->Callback(Q931_CALL_CONNECTION_CLOSED, pCallObject->hQ931Call,
  1530. pCallObject->dwListenToken,
  1531. pCallObject->dwUserToken, NULL);
  1532. if (CallObjectValidate(hQ931Call) == CS_OK)
  1533. {
  1534. dwPhysicalId = pCallObject->dwPhysicalId;
  1535. pCallObject->bConnected = FALSE;
  1536. CallObjectDestroy(pCallObject);
  1537. linkLayerShutdown(dwPhysicalId);
  1538. }
  1539. else
  1540. {
  1541. CallEntryUnlock(hQ931Call);
  1542. }
  1543. return;
  1544. }
  1545. else if (buf)
  1546. {
  1547. // unknown condition?
  1548. MemFree(buf);
  1549. }
  1550. if (CallObjectValidate(hQ931Call) == CS_OK)
  1551. {
  1552. CallObjectUnlock(pCallObject);
  1553. }
  1554. else
  1555. {
  1556. CallEntryUnlock(hQ931Call);
  1557. }
  1558. return;
  1559. }
  1560. //====================================================================================
  1561. //====================================================================================
  1562. void
  1563. Q931ReceiveCallback(DWORD_PTR instance, HRESULT message, BYTE *buf, DWORD nbytes)
  1564. {
  1565. Q931MESSAGE *pMessage = NULL;
  1566. if (message == LINK_RECV_DATA)
  1567. {
  1568. pMessage = (Q931MESSAGE *)MemAlloc(sizeof(Q931MESSAGE));
  1569. if (pMessage == NULL)
  1570. {
  1571. ISRERROR(ghISRInst, "Not enough memory to process Q931 message.", 0L);
  1572. // something more should be done here to indicate SERIOUS error...
  1573. return;
  1574. }
  1575. }
  1576. OnReceiveCallback(instance, message, pMessage, buf, nbytes);
  1577. if (pMessage)
  1578. {
  1579. MemFree(pMessage);
  1580. }
  1581. return;
  1582. }
  1583. //====================================================================================
  1584. //====================================================================================
  1585. void
  1586. Q931ConnectCallback(DWORD_PTR dwInstance, HRESULT dwMessage,
  1587. CC_ADDR *pLocalAddr, CC_ADDR *pPeerAddr)
  1588. {
  1589. HQ931CALL hQ931Call = (HQ931CALL)dwInstance;
  1590. P_CALL_OBJECT pCallObject = NULL;
  1591. HRESULT TempResult;
  1592. DWORD dwPhysicalId;
  1593. ISRTRACE(ghISRInst, "Entering Q931ConnectCallback()...", 0L);
  1594. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  1595. {
  1596. ISRERROR(ghISRInst, "CallObjectLock() returned error", 0L);
  1597. return;
  1598. }
  1599. pCallObject->bConnected = TRUE;
  1600. if (FAILED(dwMessage))
  1601. {
  1602. // shut down link layer; report failure to client
  1603. CSS_CALL_FAILED EventData;
  1604. ISRERROR(ghISRInst, "error in connect", 0L);
  1605. EventData.error = dwMessage;
  1606. pCallObject->Callback(Q931_CALL_FAILED, pCallObject->hQ931Call,
  1607. pCallObject->dwListenToken,
  1608. pCallObject->dwUserToken, &EventData);
  1609. if (CallObjectValidate(hQ931Call) == CS_OK)
  1610. {
  1611. DWORD dwId = pCallObject->dwPhysicalId;
  1612. CallObjectDestroy(pCallObject);
  1613. linkLayerShutdown(dwId);
  1614. }
  1615. else
  1616. {
  1617. CallEntryUnlock(hQ931Call);
  1618. }
  1619. return;
  1620. }
  1621. if (dwMessage != LINK_CONNECT_COMPLETE)
  1622. {
  1623. ISRERROR(ghISRInst, "unexpected connect callback", 0L);
  1624. CallObjectUnlock(pCallObject);
  1625. return;
  1626. }
  1627. if (pCallObject->bCallState == CALLSTATE_NULL)
  1628. {
  1629. pCallObject->bCallState = CALLSTATE_INITIATED;
  1630. }
  1631. ASSERT(pLocalAddr);
  1632. pCallObject->LocalAddr = *pLocalAddr;
  1633. ASSERT(pPeerAddr);
  1634. pCallObject->PeerConnectAddr = *pPeerAddr;
  1635. // if the user specified a binary source address with address = 0,
  1636. // fill in the address with the local address and send.
  1637. if ((pCallObject->SourceAddrPresent) &&
  1638. (pCallObject->SourceAddr.nAddrType == CC_IP_BINARY) &&
  1639. (!pCallObject->SourceAddr.Addr.IP_Binary.dwAddr))
  1640. {
  1641. pCallObject->SourceAddr = *pLocalAddr;
  1642. }
  1643. if ((pCallObject->fIsCaller) &&
  1644. (pCallObject->bCallState == CALLSTATE_INITIATED))
  1645. {
  1646. // send the SETUP message to the peer.
  1647. DWORD CodedLengthASN;
  1648. BYTE *CodedPtrASN;
  1649. HRESULT ResultASN = CS_OK;
  1650. DWORD CodedLengthPDU;
  1651. BYTE *CodedPtrPDU;
  1652. HRESULT ResultPDU = CS_OK;
  1653. int nError = 0;
  1654. BOOL ResultSend = FALSE;
  1655. BINARY_STRING UserUserData;
  1656. PCC_VENDORINFO pVendorInfo = NULL;
  1657. CC_NONSTANDARDDATA *pNonStandardData = NULL;
  1658. DWORD dwId;
  1659. if (pCallObject->VendorInfoPresent)
  1660. {
  1661. pVendorInfo = &(pCallObject->VendorInfo);
  1662. }
  1663. if (pCallObject->NonStandardDataPresent)
  1664. {
  1665. pNonStandardData = &(pCallObject->NonStandardData);
  1666. }
  1667. // if there is a special callee alias list, load the calledparty#.
  1668. if (pCallObject->szCalledPartyNumber[0] == 0 &&
  1669. pCallObject->pCalleeAliasList != NULL &&
  1670. pCallObject->pCalleeAliasList->wCount == 1 &&
  1671. pCallObject->pCalleeAliasList->pItems[0].wType == CC_ALIAS_H323_PHONE &&
  1672. pCallObject->pCalleeAliasList->pItems[0].wDataLength > 0 &&
  1673. pCallObject->pCalleeAliasList->pItems[0].pData != NULL)
  1674. {
  1675. PCC_ALIASITEM pItem = &pCallObject->pCalleeAliasList->pItems[0];
  1676. WCHAR szWidePartyNumber[CC_MAX_PARTY_NUMBER_LEN + 1];
  1677. memset(szWidePartyNumber, 0 , CC_MAX_PARTY_NUMBER_LEN + 1);
  1678. if (pItem->wPrefixLength > 0 && pItem->pPrefix != NULL)
  1679. {
  1680. ASSERT((pItem->wPrefixLength + pItem->wDataLength +1) <= (sizeof(szWidePartyNumber)/sizeof(szWidePartyNumber[0])));
  1681. memcpy(&szWidePartyNumber[0],
  1682. pItem->pPrefix,
  1683. (pItem->wPrefixLength) * sizeof(WCHAR));
  1684. memcpy(&szWidePartyNumber[pItem->wPrefixLength],
  1685. pItem->pData,
  1686. pItem->wDataLength * sizeof(WCHAR));
  1687. }
  1688. else
  1689. {
  1690. ASSERT((pItem->wDataLength +1) <= (sizeof(szWidePartyNumber)/sizeof(szWidePartyNumber[0])));
  1691. memcpy(szWidePartyNumber,
  1692. pCallObject->pCalleeAliasList->pItems[0].pData,
  1693. pItem->wDataLength * sizeof(WCHAR));
  1694. }
  1695. WideCharToMultiByte(CP_ACP, 0, szWidePartyNumber,
  1696. pItem->wPrefixLength + pItem->wDataLength * sizeof(WCHAR),
  1697. pCallObject->szCalledPartyNumber,
  1698. sizeof(pCallObject->szCalledPartyNumber), NULL, NULL);
  1699. }
  1700. // may wish to pass alias parms later instead of NULL, NULL.
  1701. ResultASN = Q931SetupEncodeASN(pNonStandardData,
  1702. pCallObject->SourceAddrPresent ? &(pCallObject->SourceAddr) : NULL,
  1703. pCallObject->PeerCallAddrPresent ? &(pCallObject->PeerCallAddr) : NULL, // callee
  1704. pCallObject->wGoal,
  1705. pCallObject->wCallType,
  1706. pCallObject->bCallerIsMC,
  1707. &(pCallObject->ConferenceID),
  1708. pCallObject->pCallerAliasList,
  1709. pCallObject->pCalleeAliasList,
  1710. pCallObject->pExtraAliasList,
  1711. pCallObject->pExtensionAliasItem,
  1712. pVendorInfo,
  1713. pCallObject->bIsTerminal,
  1714. pCallObject->bIsGateway,
  1715. &pCallObject->World,
  1716. &CodedPtrASN,
  1717. &CodedLengthASN,
  1718. &pCallObject->CallIdentifier);
  1719. if ((ResultASN != CS_OK) || (CodedLengthASN == 0) ||
  1720. (CodedPtrASN == NULL))
  1721. {
  1722. CSS_CALL_FAILED EventData;
  1723. ISRERROR(ghISRInst, "Q931SetupEncodeASN() failed, nothing to send.", 0L);
  1724. if (CodedPtrASN != NULL)
  1725. {
  1726. Q931FreeEncodedBuffer(&pCallObject->World, CodedPtrASN);
  1727. }
  1728. EventData.error = CS_INTERNAL_ERROR;
  1729. dwId = pCallObject->dwPhysicalId;
  1730. pCallObject->Callback(Q931_CALL_FAILED, pCallObject->hQ931Call,
  1731. pCallObject->dwListenToken,
  1732. pCallObject->dwUserToken, &EventData);
  1733. linkLayerShutdown(dwId);
  1734. if (CallObjectValidate(hQ931Call) == CS_OK)
  1735. {
  1736. CallObjectDestroy(pCallObject);
  1737. }
  1738. else
  1739. {
  1740. CallEntryUnlock(hQ931Call);
  1741. }
  1742. return;
  1743. }
  1744. UserUserData.length = (WORD)CodedLengthASN;
  1745. UserUserData.ptr = CodedPtrASN;
  1746. ResultPDU = Q931SetupEncodePDU(pCallObject->wCRV,
  1747. pCallObject->szDisplay, pCallObject->szCalledPartyNumber,
  1748. &UserUserData, &CodedPtrPDU, &CodedLengthPDU);
  1749. if (CodedPtrASN != NULL)
  1750. {
  1751. Q931FreeEncodedBuffer(&pCallObject->World, CodedPtrASN);
  1752. }
  1753. if ((ResultPDU != CS_OK) || (CodedLengthPDU == 0) ||
  1754. (CodedPtrPDU == NULL))
  1755. {
  1756. CSS_CALL_FAILED EventData;
  1757. ISRERROR(ghISRInst, "Q931SetupEncodePDU() failed, nothing to send.", 0L);
  1758. if (CodedPtrPDU != NULL)
  1759. {
  1760. MemFree(CodedPtrPDU);
  1761. }
  1762. EventData.error = CS_INTERNAL_ERROR;
  1763. dwId = pCallObject->dwPhysicalId;
  1764. pCallObject->Callback(Q931_CALL_FAILED, pCallObject->hQ931Call,
  1765. pCallObject->dwListenToken,
  1766. pCallObject->dwUserToken, &EventData);
  1767. linkLayerShutdown(dwId);
  1768. if (CallObjectValidate(hQ931Call) == CS_OK)
  1769. {
  1770. CallObjectDestroy(pCallObject);
  1771. }
  1772. else
  1773. {
  1774. CallEntryUnlock(hQ931Call);
  1775. }
  1776. return;
  1777. }
  1778. if (pCallObject->NonStandardDataPresent)
  1779. {
  1780. if (pCallObject->NonStandardData.sData.pOctetString != NULL)
  1781. {
  1782. MemFree(pCallObject->NonStandardData.sData.pOctetString);
  1783. pCallObject->NonStandardData.sData.pOctetString = NULL;
  1784. }
  1785. pCallObject->NonStandardDataPresent = FALSE;
  1786. }
  1787. Q931FreeAliasNames(pCallObject->pCallerAliasList);
  1788. pCallObject->pCallerAliasList = NULL;
  1789. Q931FreeAliasNames(pCallObject->pCalleeAliasList);
  1790. pCallObject->pCalleeAliasList = NULL;
  1791. Q931FreeAliasNames(pCallObject->pExtraAliasList);
  1792. pCallObject->pExtraAliasList = NULL;
  1793. Q931FreeAliasItem(pCallObject->pExtensionAliasItem);
  1794. pCallObject->pExtensionAliasItem = NULL;
  1795. TempResult=Q931SendMessage(pCallObject, CodedPtrPDU, CodedLengthPDU, TRUE);
  1796. if (CallObjectValidate(hQ931Call) != CS_OK)
  1797. {
  1798. CallEntryUnlock(hQ931Call);
  1799. return;
  1800. }
  1801. if(FAILED(TempResult))
  1802. {
  1803. CSS_CALL_FAILED EventData;
  1804. EventData.error = TempResult;
  1805. dwId = pCallObject->dwPhysicalId;
  1806. pCallObject->Callback(Q931_CALL_FAILED, pCallObject->hQ931Call,
  1807. pCallObject->dwListenToken,
  1808. pCallObject->dwUserToken, &EventData);
  1809. linkLayerShutdown(dwId);
  1810. if (CallObjectValidate(hQ931Call) == CS_OK)
  1811. {
  1812. CallObjectDestroy(pCallObject);
  1813. }
  1814. else
  1815. {
  1816. CallEntryUnlock(hQ931Call);
  1817. }
  1818. return;
  1819. }
  1820. Q931StartTimer(pCallObject, Q931_TIMER_303);
  1821. }
  1822. dwPhysicalId = pCallObject->dwPhysicalId;
  1823. CallObjectUnlock(pCallObject);
  1824. PostReceiveBuffer(dwPhysicalId, NULL);
  1825. }
  1826. //====================================================================================
  1827. //====================================================================================
  1828. void
  1829. Q931ListenCallback(DWORD_PTR dwInstance, HRESULT dwMessage,
  1830. CC_ADDR *LocalAddr, CC_ADDR *PeerAddr)
  1831. {
  1832. HQ931LISTEN hListenObject = (HQ931LISTEN)dwInstance;
  1833. P_LISTEN_OBJECT pListenObject = NULL;
  1834. CS_STATUS CreateObjectResult;
  1835. HQ931CALL hQ931Call;
  1836. P_CALL_OBJECT pCallObject = NULL;
  1837. HRESULT TempResult;
  1838. DWORD dwPhysicalId;
  1839. ISRTRACE(ghISRInst, "Q931ListenCallback.", 0L);
  1840. if (dwMessage != LINK_CONNECT_REQUEST)
  1841. {
  1842. ISRERROR(ghISRInst, "unexpected callback received on listen socket", 0L);
  1843. return;
  1844. }
  1845. if (FAILED(dwMessage))
  1846. {
  1847. ISRERROR(ghISRInst, "error on listen socket", 0L);
  1848. return;
  1849. }
  1850. if ((ListenObjectLock(hListenObject, &pListenObject) != CS_OK) || (pListenObject == NULL))
  1851. {
  1852. ISRERROR(ghISRInst, "ListenObjectLock() returned error", 0L);
  1853. return;
  1854. }
  1855. // create call object with all known attributes of this call.
  1856. // a handle of the call object is returned in phQ931Call.
  1857. CreateObjectResult = CallObjectCreate(&hQ931Call,
  1858. pListenObject->dwUserToken,
  1859. CC_INVALID_HANDLE,
  1860. pListenObject->ListenCallback,
  1861. FALSE, // I am NOT the caller.
  1862. LocalAddr, // Local address on which channel is connected
  1863. PeerAddr, // Address to which channel is connected
  1864. NULL, // Address of opposite call end-point.
  1865. NULL, // no source addr
  1866. NULL, // no conference id yet.
  1867. CSG_NONE, // no goal yet.
  1868. CC_CALLTYPE_UNKNOWN, // no call type yet.
  1869. FALSE, // caller is assumed to not be the MC.
  1870. NULL, // no display yet.
  1871. NULL, // no called party number yet.
  1872. NULL, // no caller aliases yet.
  1873. NULL, // no callee aliases yet.
  1874. NULL, // no extra aliases yet.
  1875. NULL, // no extension aliases.
  1876. NULL, // no EndpointType info yet.
  1877. NULL,
  1878. 0, // no CRV yet.
  1879. NULL); // no h225 CallIdentifier yet.
  1880. if (CreateObjectResult != CS_OK)
  1881. {
  1882. ISRERROR(ghISRInst, "CallObjectCreate() failed.", 0L);
  1883. ListenObjectUnlock(pListenObject);
  1884. return;
  1885. }
  1886. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  1887. {
  1888. ISRERROR(ghISRInst, "CallObjectLock() returned error", 0L);
  1889. ListenObjectUnlock(pListenObject);
  1890. return;
  1891. }
  1892. TempResult = linkLayerInit(&pCallObject->dwPhysicalId, hQ931Call,
  1893. Q931ReceiveCallback, Q931SendComplete);
  1894. if (FAILED(TempResult))
  1895. {
  1896. ISRERROR(ghISRInst, "linkLayerInit() failed", 0);
  1897. linkLayerReject(pListenObject->dwPhysicalId);
  1898. CallObjectDestroy(pCallObject);
  1899. ListenObjectUnlock(pListenObject);
  1900. return;
  1901. }
  1902. // pCallObject->bCallState = CALLSTATE_NULL;
  1903. // unlock CallObject before calling down into h245ws in order to prevent deadlock - which
  1904. // is probably unlikely with linkLayerAccept(), but just to be safe and consistent...
  1905. // not sure if we need to worry about unlocking the listen object???
  1906. dwPhysicalId = pCallObject->dwPhysicalId;
  1907. CallObjectUnlock(pCallObject);
  1908. TempResult = linkLayerAccept(pListenObject->dwPhysicalId,
  1909. dwPhysicalId, Q931ConnectCallback);
  1910. if (FAILED(TempResult))
  1911. {
  1912. if((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  1913. {
  1914. ListenObjectUnlock(pListenObject);
  1915. return;
  1916. }
  1917. ISRERROR(ghISRInst, "linkLayerAccept() failed", 0);
  1918. {
  1919. DWORD dwId = pCallObject->dwPhysicalId;
  1920. CallObjectDestroy(pCallObject);
  1921. linkLayerShutdown(dwId);
  1922. }
  1923. ListenObjectUnlock(pListenObject);
  1924. return;
  1925. }
  1926. ListenObjectUnlock(pListenObject);
  1927. }
  1928. //====================================================================================
  1929. //
  1930. // PUBLIC FUNCTIONS
  1931. //
  1932. //====================================================================================
  1933. //====================================================================================
  1934. //====================================================================================
  1935. CS_STATUS
  1936. H225Init()
  1937. {
  1938. CS_STATUS result;
  1939. if (H225_InitModule() != ASN1_SUCCESS)
  1940. {
  1941. ASSERT(FALSE);
  1942. return CS_SUBSYSTEM_FAILURE;
  1943. }
  1944. return CS_OK;
  1945. }
  1946. CS_STATUS
  1947. H225DeInit()
  1948. {
  1949. CS_STATUS result;
  1950. result = H225_TermModule();
  1951. if (result != CS_OK)
  1952. {
  1953. return CS_SUBSYSTEM_FAILURE;
  1954. }
  1955. return CS_OK;
  1956. }
  1957. CS_STATUS
  1958. Q931Init()
  1959. {
  1960. CS_STATUS result;
  1961. if (bQ931Initialized == TRUE)
  1962. {
  1963. ASSERT(FALSE);
  1964. return CS_DUPLICATE_INITIALIZE;
  1965. }
  1966. bQ931Initialized = TRUE;
  1967. // Register Call Setup for debug output
  1968. ISRREGISTERMODULE(&ghISRInst, "Q931", "Q931 Call Setup");
  1969. // Initialize the current conference ID to 0's, which is intentionally
  1970. // assigned to an invalid conference ID. Must create one for it
  1971. // to be valid.
  1972. memset(&(ConferenceIDSource), 0, sizeof(ConferenceIDSource));
  1973. InitializeCriticalSection(&(ConferenceIDSource.Lock));
  1974. if ((result = ListenListCreate()) != CS_OK)
  1975. {
  1976. return result;
  1977. }
  1978. if ((result = CallListCreate()) != CS_OK)
  1979. {
  1980. ListenListDestroy();
  1981. return result;
  1982. }
  1983. // init protocol ID structures
  1984. Q931PduInit();
  1985. #if (defined(_DEBUG) || defined(PCS_COMPLIANCE))
  1986. Q931Logger = InteropLoad(Q931LOG_PROTOCOL);
  1987. #endif
  1988. return CS_OK;
  1989. }
  1990. //====================================================================================
  1991. //====================================================================================
  1992. CS_STATUS
  1993. Q931DeInit()
  1994. {
  1995. CS_STATUS result1;
  1996. CS_STATUS result2;
  1997. if (bQ931Initialized == FALSE)
  1998. {
  1999. return CS_NOT_INITIALIZED;
  2000. }
  2001. #if (defined(_DEBUG) || defined(PCS_COMPLIANCE))
  2002. // This causes a protection exception, so don't do it for now. DAC 12/9/96
  2003. // InteropUnload(Q931Logger);
  2004. #endif
  2005. result1 = ListenListDestroy();
  2006. result2 = CallListDestroy();
  2007. DeleteCriticalSection(&(ConferenceIDSource.Lock));
  2008. bQ931Initialized = FALSE;
  2009. if (result1 != CS_OK)
  2010. {
  2011. return result1;
  2012. }
  2013. return result2;
  2014. }
  2015. //====================================================================================
  2016. //====================================================================================
  2017. CS_STATUS
  2018. Q931Listen(
  2019. PHQ931LISTEN phQ931Listen,
  2020. PCC_ADDR pListenAddr,
  2021. DWORD_PTR dwListenToken,
  2022. Q931_CALLBACK ListenCallback)
  2023. {
  2024. CS_STATUS CreateObjectResult;
  2025. P_LISTEN_OBJECT pListenObject = NULL;
  2026. HRESULT TempResult;
  2027. // make sure q931 is initialized with an initialize flag.
  2028. if (bQ931Initialized == FALSE)
  2029. {
  2030. return CS_NOT_INITIALIZED;
  2031. }
  2032. // make sure parms are validated.
  2033. if ((phQ931Listen == NULL) || (ListenCallback == NULL) || (pListenAddr == NULL))
  2034. {
  2035. ASSERT(FALSE);
  2036. return CS_BAD_PARAM;
  2037. }
  2038. SetDefaultPort(pListenAddr);
  2039. // create listen object with all known attributes of this listen session.
  2040. // a handle of the listen object is returned in phQ931Listen.
  2041. CreateObjectResult = ListenObjectCreate(phQ931Listen, dwListenToken, ListenCallback);
  2042. if (CreateObjectResult != CS_OK)
  2043. {
  2044. return CS_SUBSYSTEM_FAILURE;
  2045. }
  2046. if (ListenObjectLock(*phQ931Listen, &pListenObject) != CS_OK)
  2047. {
  2048. return CS_BAD_PARAM;
  2049. }
  2050. TempResult = linkLayerListen(&pListenObject->dwPhysicalId, *phQ931Listen,
  2051. pListenAddr, Q931ListenCallback);
  2052. ListenObjectUnlock(pListenObject);
  2053. if (FAILED(TempResult))
  2054. {
  2055. ISRTRACE(ghISRInst, "Q931Listen() linkLayerListen failed.", 0L);
  2056. return TempResult;
  2057. }
  2058. ISRTRACE(ghISRInst, "Q931Listen() completed successfully.", 0L);
  2059. return CS_OK;
  2060. }
  2061. //====================================================================================
  2062. // In the old code, this blocked until thread and socket were finished
  2063. // closing...
  2064. //====================================================================================
  2065. CS_STATUS
  2066. Q931CancelListen(
  2067. HQ931LISTEN hQ931Listen)
  2068. {
  2069. P_LISTEN_OBJECT pListenObject = NULL;
  2070. CS_STATUS Status;
  2071. // make sure q931 is initialized with an initialize flag.
  2072. if (bQ931Initialized == FALSE)
  2073. {
  2074. return CS_NOT_INITIALIZED;
  2075. }
  2076. ISRTRACE(ghISRInst, "Q931CancelListen() finding listen object...", 0L);
  2077. // lock the listen object, get the event to wait for, and unlock the listen object.
  2078. if (ListenObjectLock(hQ931Listen, &pListenObject) != CS_OK)
  2079. {
  2080. return CS_BAD_PARAM;
  2081. }
  2082. {
  2083. DWORD dwId = pListenObject->dwPhysicalId;
  2084. linkLayerShutdown(dwId);
  2085. // destroy the object. dont need to unlock it since entire object will be destroyed.
  2086. ISRTRACE(ghISRInst, "Q931CancelListen(): destroying listen object...", 0L);
  2087. Status = ListenObjectDestroy(pListenObject);
  2088. }
  2089. return Status;
  2090. }
  2091. //====================================================================================
  2092. //====================================================================================
  2093. CS_STATUS
  2094. Q931PlaceCall(
  2095. PHQ931CALL phQ931Call,
  2096. LPWSTR pszDisplay,
  2097. PCC_ALIASNAMES pCallerAliasList,
  2098. PCC_ALIASNAMES pCalleeAliasList,
  2099. PCC_ALIASNAMES pExtraAliasList,
  2100. PCC_ALIASITEM pExtensionAliasItem,
  2101. PCC_NONSTANDARDDATA pNonStandardData,
  2102. PCC_ENDPOINTTYPE pSourceEndpointType,
  2103. LPWSTR pszCalledPartyNumber,
  2104. PCC_ADDR pControlAddr,
  2105. PCC_ADDR pDestinationAddr,
  2106. PCC_ADDR pSourceAddr,
  2107. BOOL bCallerIsMC,
  2108. CC_CONFERENCEID *pConferenceID,
  2109. WORD wGoal,
  2110. WORD wCallType,
  2111. DWORD_PTR dwUserToken,
  2112. Q931_CALLBACK ConnectCallback,
  2113. WORD wCRV,
  2114. LPGUID pCallIdentifier)
  2115. {
  2116. CS_STATUS CreateObjectResult;
  2117. P_CALL_OBJECT pCallObject = NULL;
  2118. CC_ADDR PeerCallAddr;
  2119. CC_ADDR PeerConnectAddr;
  2120. CC_ADDR SourceAddr;
  2121. HRESULT TempResult;
  2122. char szAsciiDisplay[CC_MAX_DISPLAY_LENGTH + 1];
  2123. char szAsciiPartyNumber[CC_MAX_PARTY_NUMBER_LEN + 1];
  2124. DWORD dwPhysicalId;
  2125. // make sure q931 is initialized with an initialize flag.
  2126. if (bQ931Initialized == FALSE)
  2127. {
  2128. return CS_NOT_INITIALIZED;
  2129. }
  2130. // make sure parms are validated.
  2131. if ((phQ931Call == NULL) || (ConnectCallback == NULL) ||
  2132. ((pControlAddr == NULL) && (pDestinationAddr == NULL)) ||
  2133. (pSourceEndpointType == NULL))
  2134. {
  2135. return CS_BAD_PARAM;
  2136. }
  2137. {
  2138. CS_STATUS TempStatus;
  2139. TempStatus = Q931ValidateAddr(pControlAddr);
  2140. if (TempStatus != CS_OK)
  2141. {
  2142. return TempStatus;
  2143. }
  2144. TempStatus = Q931ValidateAddr(pDestinationAddr);
  2145. if (TempStatus != CS_OK)
  2146. {
  2147. return TempStatus;
  2148. }
  2149. TempStatus = Q931ValidateAddr(pSourceAddr);
  2150. if (TempStatus != CS_OK)
  2151. {
  2152. return TempStatus;
  2153. }
  2154. TempStatus = Q931ValidateVendorInfo(pSourceEndpointType->pVendorInfo);
  2155. if (TempStatus != CS_OK)
  2156. {
  2157. return TempStatus;
  2158. }
  2159. TempStatus = Q931ValidateDisplay(pszDisplay);
  2160. if (TempStatus != CS_OK)
  2161. {
  2162. return TempStatus;
  2163. }
  2164. TempStatus = Q931ValidatePartyNumber(pszCalledPartyNumber);
  2165. if (TempStatus != CS_OK)
  2166. {
  2167. return TempStatus;
  2168. }
  2169. szAsciiDisplay[0] = '\0';
  2170. if (pszDisplay && WideCharToMultiByte(CP_ACP, 0, pszDisplay, -1, szAsciiDisplay,
  2171. sizeof(szAsciiDisplay), NULL, NULL) == 0)
  2172. {
  2173. return CS_BAD_PARAM;
  2174. }
  2175. szAsciiPartyNumber[0] = '\0';
  2176. if (pszCalledPartyNumber && WideCharToMultiByte(CP_ACP, 0, pszCalledPartyNumber, -1, szAsciiPartyNumber,
  2177. sizeof(szAsciiPartyNumber), NULL, NULL) == 0)
  2178. {
  2179. return CS_BAD_PARAM;
  2180. }
  2181. TempStatus = Q931ValidateNonStandardData(pNonStandardData);
  2182. if (TempStatus != CS_OK)
  2183. {
  2184. return TempStatus;
  2185. }
  2186. TempStatus = Q931ValidateAliasNames(pCallerAliasList);
  2187. if (TempStatus != CS_OK)
  2188. {
  2189. return TempStatus;
  2190. }
  2191. TempStatus = Q931ValidateAliasNames(pCalleeAliasList);
  2192. if (TempStatus != CS_OK)
  2193. {
  2194. return TempStatus;
  2195. }
  2196. TempStatus = Q931ValidateAliasNames(pExtraAliasList);
  2197. if (TempStatus != CS_OK)
  2198. {
  2199. return TempStatus;
  2200. }
  2201. TempStatus = Q931ValidateAliasItem(pExtensionAliasItem);
  2202. if (TempStatus != CS_OK)
  2203. {
  2204. return TempStatus;
  2205. }
  2206. }
  2207. // get the correct callee and control address to use for the call.
  2208. if (pDestinationAddr)
  2209. {
  2210. if (!MakeBinaryADDR(pDestinationAddr, &PeerCallAddr))
  2211. {
  2212. return CS_BAD_PARAM;
  2213. }
  2214. SetDefaultPort(&PeerCallAddr);
  2215. }
  2216. if (pControlAddr)
  2217. {
  2218. if (!MakeBinaryADDR(pControlAddr, &PeerConnectAddr))
  2219. {
  2220. return CS_BAD_PARAM;
  2221. }
  2222. SetDefaultPort(&PeerConnectAddr);
  2223. }
  2224. else
  2225. {
  2226. PeerConnectAddr = PeerCallAddr;
  2227. }
  2228. // get the correct callee and control address to use for the call.
  2229. if (pSourceAddr)
  2230. {
  2231. if (!MakeBinaryADDR(pSourceAddr, &SourceAddr))
  2232. {
  2233. return CS_BAD_PARAM;
  2234. }
  2235. SetDefaultPort(&SourceAddr);
  2236. }
  2237. if (wGoal == CSG_CREATE)
  2238. {
  2239. // caller is asking to start a new conference.
  2240. if (((DWORD *)pConferenceID->buffer)[0] == 0 &&
  2241. ((DWORD *)pConferenceID->buffer)[1] == 0 &&
  2242. ((DWORD *)pConferenceID->buffer)[2] == 0 &&
  2243. ((DWORD *)pConferenceID->buffer)[3] == 0)
  2244. {
  2245. _ConferenceIDNew(pConferenceID);
  2246. }
  2247. }
  2248. // create call object with all known attributes of this call.
  2249. // a handle of the call object is returned in phQ931Call.
  2250. CreateObjectResult = CallObjectCreate(phQ931Call,
  2251. CC_INVALID_HANDLE,
  2252. dwUserToken,
  2253. ConnectCallback,
  2254. TRUE, // I am the caller.
  2255. NULL, // no local address yet.
  2256. &PeerConnectAddr,
  2257. pDestinationAddr ? &PeerCallAddr : NULL,
  2258. pSourceAddr ? &SourceAddr : NULL,
  2259. pConferenceID,
  2260. wGoal,
  2261. wCallType,
  2262. bCallerIsMC,
  2263. pszDisplay ? szAsciiDisplay : NULL,
  2264. pszCalledPartyNumber ? szAsciiPartyNumber : NULL,
  2265. pCallerAliasList,
  2266. pCalleeAliasList,
  2267. pExtraAliasList,
  2268. pExtensionAliasItem,
  2269. pSourceEndpointType,
  2270. pNonStandardData,
  2271. wCRV,
  2272. pCallIdentifier);
  2273. if (CreateObjectResult != CS_OK)
  2274. {
  2275. return CS_SUBSYSTEM_FAILURE;
  2276. }
  2277. if ((CallObjectLock(*phQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  2278. {
  2279. ISRERROR(ghISRInst, "CallObjectLock() returned error", 0L);
  2280. return CS_SUBSYSTEM_FAILURE;
  2281. }
  2282. TempResult = linkLayerInit(&pCallObject->dwPhysicalId, *phQ931Call,
  2283. Q931ReceiveCallback, Q931SendComplete);
  2284. if (FAILED(TempResult))
  2285. {
  2286. ISRERROR(ghISRInst, "linkLayerInit() failed", 0);
  2287. CallObjectDestroy(pCallObject);
  2288. *phQ931Call = 0;
  2289. return TempResult;
  2290. }
  2291. // unlock CallObject before calling down into h245ws in order to prevent deadlock - which
  2292. // is probably unlikely with linkLayerConnect(), but just to be safe and consistent...
  2293. dwPhysicalId = pCallObject->dwPhysicalId;
  2294. CallObjectUnlock(pCallObject);
  2295. TempResult = linkLayerConnect(dwPhysicalId, &PeerConnectAddr,
  2296. Q931ConnectCallback);
  2297. if((CallObjectLock(*phQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  2298. {
  2299. *phQ931Call = 0;
  2300. return(CS_INTERNAL_ERROR);
  2301. }
  2302. if (FAILED(TempResult))
  2303. {
  2304. ISRERROR(ghISRInst, "linkLayerConnect() failed", 0);
  2305. {
  2306. DWORD dwId = pCallObject->dwPhysicalId;
  2307. CallObjectDestroy(pCallObject);
  2308. linkLayerShutdown(dwId);
  2309. }
  2310. *phQ931Call = 0;
  2311. return TempResult;
  2312. }
  2313. // pCallObject->bCallState = CALLSTATE_NULL;
  2314. CallObjectUnlock(pCallObject);
  2315. ISRTRACE(ghISRInst, "Q931PlaceCall() completed successfully.", 0L);
  2316. return CS_OK;
  2317. }
  2318. //====================================================================================
  2319. // In the old code, this blocked until thread and socket were finished
  2320. // closing...
  2321. //====================================================================================
  2322. CS_STATUS
  2323. Q931Hangup(
  2324. HQ931CALL hQ931Call,
  2325. BYTE bReason)
  2326. {
  2327. P_CALL_OBJECT pCallObject = NULL;
  2328. CS_STATUS Status;
  2329. if (bQ931Initialized == FALSE)
  2330. {
  2331. return CS_NOT_INITIALIZED;
  2332. }
  2333. ISRTRACE(ghISRInst, "Entering Q931Hangup()...", 0L);
  2334. // need parameter checking...
  2335. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  2336. {
  2337. ISRTRACE(ghISRInst, "Call Object no longer available:", (DWORD)hQ931Call);
  2338. return CS_BAD_PARAM;
  2339. }
  2340. {
  2341. CS_STATUS SendStatus = CS_OK;
  2342. if (pCallObject->bCallState != CALLSTATE_NULL)
  2343. {
  2344. // send the RELEASE COMPLETE message to the peer to hang-up.
  2345. SendStatus = Q931SendReleaseCompleteMessage(pCallObject,
  2346. bReason, &(pCallObject->ConferenceID), NULL, NULL);
  2347. }
  2348. {
  2349. DWORD dwId = pCallObject->dwPhysicalId;
  2350. Status = CallObjectDestroy(pCallObject);
  2351. linkLayerShutdown(dwId);
  2352. }
  2353. if (FAILED(SendStatus))
  2354. {
  2355. return SendStatus;
  2356. }
  2357. }
  2358. return Status;
  2359. }
  2360. //====================================================================================
  2361. //====================================================================================
  2362. CS_STATUS
  2363. Q931AcceptCall(
  2364. HQ931CALL hQ931Call,
  2365. LPWSTR pszDisplay,
  2366. PCC_NONSTANDARDDATA pNonStandardData,
  2367. PCC_ENDPOINTTYPE pDestinationEndpointType,
  2368. PCC_ADDR pH245Addr,
  2369. DWORD_PTR dwUserToken)
  2370. {
  2371. P_CALL_OBJECT pCallObject = NULL;
  2372. CS_STATUS result = CS_OK;
  2373. char szAsciiDisplay[CC_MAX_DISPLAY_LENGTH + 1];
  2374. if (bQ931Initialized == FALSE)
  2375. {
  2376. return CS_NOT_INITIALIZED;
  2377. }
  2378. ISRTRACE(ghISRInst, "Entering Q931AcceptCall()...", 0L);
  2379. if ((pDestinationEndpointType == NULL) ||
  2380. (pDestinationEndpointType->pVendorInfo == NULL))
  2381. {
  2382. return CS_BAD_PARAM;
  2383. }
  2384. {
  2385. CS_STATUS TempStatus;
  2386. TempStatus = Q931ValidateVendorInfo(pDestinationEndpointType->pVendorInfo);
  2387. if (TempStatus != CS_OK)
  2388. {
  2389. return TempStatus;
  2390. }
  2391. TempStatus = Q931ValidateDisplay(pszDisplay);
  2392. if (TempStatus != CS_OK)
  2393. {
  2394. return TempStatus;
  2395. }
  2396. szAsciiDisplay[0] = '\0';
  2397. if (pszDisplay && WideCharToMultiByte(CP_ACP, 0, pszDisplay, -1, szAsciiDisplay,
  2398. sizeof(szAsciiDisplay), NULL, NULL) == 0)
  2399. {
  2400. return CS_BAD_PARAM;
  2401. }
  2402. TempStatus = Q931ValidateNonStandardData(pNonStandardData);
  2403. if (TempStatus != CS_OK)
  2404. {
  2405. return TempStatus;
  2406. }
  2407. }
  2408. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  2409. {
  2410. ISRERROR(ghISRInst, "CallObjectLock() returned error (Socket not found).", 0L);
  2411. return CS_INTERNAL_ERROR;
  2412. }
  2413. if (pCallObject->fIsCaller)
  2414. {
  2415. ISRERROR(ghISRInst, "Caller attempted to accept call.", 0L);
  2416. CallObjectUnlock(pCallObject);
  2417. return CS_OUT_OF_SEQUENCE;
  2418. }
  2419. // label with the user supplied UserToken for this call object.
  2420. pCallObject->dwUserToken = dwUserToken;
  2421. // send the CONNECT message to peer to accept call.
  2422. {
  2423. DWORD CodedLengthASN;
  2424. BYTE *CodedPtrASN;
  2425. HRESULT ResultASN = CS_OK;
  2426. CC_ADDR h245Addr;
  2427. if (pH245Addr != NULL)
  2428. {
  2429. MakeBinaryADDR(pH245Addr, &h245Addr);
  2430. }
  2431. ResultASN = Q931ConnectEncodeASN(pNonStandardData,
  2432. &(pCallObject->ConferenceID),
  2433. (pH245Addr ? &h245Addr : NULL),
  2434. pDestinationEndpointType,
  2435. &pCallObject->World,
  2436. &CodedPtrASN,
  2437. &CodedLengthASN,
  2438. &pCallObject->CallIdentifier);
  2439. if ((ResultASN != CS_OK) || (CodedLengthASN == 0) ||
  2440. (CodedPtrASN == NULL))
  2441. {
  2442. ISRERROR(ghISRInst, "Q931ConnectEncodeASN() failed, nothing to send.", 0L);
  2443. if (CodedPtrASN != NULL)
  2444. {
  2445. Q931FreeEncodedBuffer(&pCallObject->World, CodedPtrASN);
  2446. }
  2447. CallObjectUnlock(pCallObject);
  2448. return CS_SUBSYSTEM_FAILURE;
  2449. }
  2450. else
  2451. {
  2452. DWORD CodedLengthPDU;
  2453. BYTE *CodedPtrPDU;
  2454. BINARY_STRING UserUserData;
  2455. HRESULT ResultEncode = CS_OK;
  2456. HRESULT TempResult;
  2457. WORD wCRV = (WORD)(pCallObject->wCRV | 0x8000);
  2458. UserUserData.length = (WORD)CodedLengthASN;
  2459. UserUserData.ptr = CodedPtrASN;
  2460. ResultEncode = Q931ConnectEncodePDU(wCRV,
  2461. szAsciiDisplay, &UserUserData, &CodedPtrPDU, &CodedLengthPDU);
  2462. if (CodedPtrASN != NULL)
  2463. {
  2464. Q931FreeEncodedBuffer(&pCallObject->World, CodedPtrASN);
  2465. }
  2466. if ((ResultEncode != CS_OK) || (CodedLengthPDU == 0) ||
  2467. (CodedPtrPDU == NULL))
  2468. {
  2469. ISRERROR(ghISRInst, "Q931ConnectEncodePDU() failed, nothing to send.", 0L);
  2470. if (CodedPtrPDU != NULL)
  2471. {
  2472. MemFree(CodedPtrPDU);
  2473. }
  2474. CallObjectUnlock(pCallObject);
  2475. return CS_SUBSYSTEM_FAILURE;
  2476. }
  2477. TempResult = Q931SendMessage(pCallObject, CodedPtrPDU, CodedLengthPDU, TRUE);
  2478. if (CallObjectValidate(hQ931Call) != CS_OK)
  2479. {
  2480. CallEntryUnlock(hQ931Call);
  2481. return CS_INTERNAL_ERROR;
  2482. }
  2483. if (FAILED(TempResult))
  2484. {
  2485. ISRERROR(ghISRInst, "datalinkSendRequest() failed", 0);
  2486. if (CodedPtrPDU != NULL)
  2487. {
  2488. MemFree(CodedPtrPDU);
  2489. }
  2490. // when the connect notification fails...what should we do anyway????
  2491. CallObjectUnlock(pCallObject);
  2492. return TempResult;
  2493. }
  2494. }
  2495. }
  2496. pCallObject->bCallState = CALLSTATE_ACTIVE;
  2497. CallObjectUnlock(pCallObject);
  2498. return CS_OK;
  2499. }
  2500. //====================================================================================
  2501. //====================================================================================
  2502. CS_STATUS
  2503. Q931RejectCall(
  2504. HQ931CALL hQ931Call,
  2505. BYTE bRejectReason,
  2506. PCC_CONFERENCEID pConferenceID,
  2507. PCC_ADDR pAlternateAddr,
  2508. PCC_NONSTANDARDDATA pNonStandardData)
  2509. {
  2510. P_CALL_OBJECT pCallObject = NULL;
  2511. CS_STATUS result = CS_OK;
  2512. CS_STATUS Status = CS_OK;
  2513. if (bQ931Initialized == FALSE)
  2514. {
  2515. return CS_NOT_INITIALIZED;
  2516. }
  2517. ISRTRACE(ghISRInst, "Entering Q931RejectCall()...", 0L);
  2518. {
  2519. CS_STATUS TempStatus;
  2520. TempStatus = Q931ValidateNonStandardData(pNonStandardData);
  2521. if (TempStatus != CS_OK)
  2522. {
  2523. return TempStatus;
  2524. }
  2525. }
  2526. // if reason is alternate addr, but there is no alternate addr -->err
  2527. if (((bRejectReason == CC_REJECT_ROUTE_TO_GATEKEEPER) ||
  2528. (bRejectReason == CC_REJECT_CALL_FORWARDED) ||
  2529. (bRejectReason == CC_REJECT_ROUTE_TO_MC)) &&
  2530. (pAlternateAddr == NULL))
  2531. {
  2532. return CS_BAD_PARAM;
  2533. }
  2534. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  2535. {
  2536. ISRERROR(ghISRInst, "CallObjectLock() returned error (Socket not found).", 0L);
  2537. return CS_INTERNAL_ERROR;
  2538. }
  2539. if (pCallObject->fIsCaller)
  2540. {
  2541. ISRERROR(ghISRInst, "Caller attempted to reject call.", 0L);
  2542. CallObjectUnlock(pCallObject);
  2543. return CS_OUT_OF_SEQUENCE;
  2544. }
  2545. result = Q931SendReleaseCompleteMessage(pCallObject,
  2546. bRejectReason, pConferenceID, pAlternateAddr, pNonStandardData);
  2547. {
  2548. DWORD dwId = pCallObject->dwPhysicalId;
  2549. Status = CallObjectDestroy(pCallObject);
  2550. linkLayerShutdown(dwId);
  2551. }
  2552. if (result != CS_OK)
  2553. {
  2554. return result;
  2555. }
  2556. return Status;
  2557. }
  2558. //====================================================================================
  2559. //====================================================================================
  2560. CS_STATUS
  2561. Q931ReOpenConnection(
  2562. HQ931CALL hQ931Call)
  2563. {
  2564. P_CALL_OBJECT pCallObject = NULL;
  2565. HRESULT TempResult = CS_OK;
  2566. CC_ADDR PeerConnectAddr;
  2567. DWORD dwPhysicalId;
  2568. if (bQ931Initialized == FALSE)
  2569. {
  2570. return CS_NOT_INITIALIZED;
  2571. }
  2572. ISRTRACE(ghISRInst, "Entering Q931ReOpenConnection()...", 0L);
  2573. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  2574. {
  2575. ISRERROR(ghISRInst, "CallObjectLock() returned error.", 0L);
  2576. return CS_INTERNAL_ERROR;
  2577. }
  2578. if (pCallObject->bConnected)
  2579. {
  2580. return CS_OUT_OF_SEQUENCE;
  2581. }
  2582. Q931MakePhysicalID(&pCallObject->dwPhysicalId);
  2583. TempResult = linkLayerInit(&pCallObject->dwPhysicalId, hQ931Call,
  2584. Q931ReceiveCallback, Q931SendComplete);
  2585. if (FAILED(TempResult))
  2586. {
  2587. ISRERROR(ghISRInst, "linkLayerInit() failed on re-connect.", 0);
  2588. CallObjectUnlock(pCallObject);
  2589. return TempResult;
  2590. }
  2591. // unlock CallObject before calling down into h245ws in order to prevent deadlock - which
  2592. // is probably unlikely with linkLayerConnect, but just to be safe and consistent...
  2593. // copy stuff we need out of call object before we unlock it
  2594. dwPhysicalId = pCallObject->dwPhysicalId;
  2595. PeerConnectAddr = pCallObject->PeerConnectAddr;
  2596. CallObjectUnlock(pCallObject);
  2597. TempResult = linkLayerConnect(dwPhysicalId,
  2598. &PeerConnectAddr, Q931ConnectCallback);
  2599. if((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  2600. {
  2601. return(CS_INTERNAL_ERROR);
  2602. }
  2603. if (FAILED(TempResult))
  2604. {
  2605. ISRERROR(ghISRInst, "linkLayerConnect() failed on re-connect.", 0);
  2606. linkLayerShutdown(pCallObject->dwPhysicalId);
  2607. CallObjectUnlock(pCallObject);
  2608. return TempResult;
  2609. }
  2610. CallObjectUnlock(pCallObject);
  2611. ISRTRACE(ghISRInst, "Q931ReOpenConnection() completed successfully.", 0L);
  2612. return CS_OK;
  2613. }
  2614. //====================================================================================
  2615. //====================================================================================
  2616. CS_STATUS
  2617. Q931GetVersion(
  2618. WORD wLength,
  2619. LPWSTR pszVersion)
  2620. {
  2621. WCHAR pszQ931Version[255];
  2622. // parameter validation.
  2623. if ((wLength == 0) || (pszVersion == NULL))
  2624. {
  2625. return CS_BAD_PARAM;
  2626. }
  2627. wcscpy(pszQ931Version, L"Call Setup ");
  2628. wcscat(pszQ931Version, Unicode(__DATE__));
  2629. wcscat(pszQ931Version, L" ");
  2630. wcscat(pszQ931Version, Unicode(__TIME__));
  2631. if (wcslen(pszQ931Version) >= wLength)
  2632. {
  2633. memcpy(pszVersion, pszQ931Version, (wLength-1)*sizeof(WCHAR));
  2634. pszQ931Version[wLength-1] = L'\0';
  2635. return CS_BAD_SIZE;
  2636. }
  2637. wcscpy(pszVersion, pszQ931Version);
  2638. return CS_OK;
  2639. }
  2640. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2641. // Timer Routines...
  2642. //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  2643. //====================================================================================
  2644. // Timer 301 has expired for this object...
  2645. //====================================================================================
  2646. void
  2647. CallBackT301(P_CALL_OBJECT pCallObject)
  2648. {
  2649. CSS_CALL_FAILED EventData;
  2650. HQ931CALL hQ931Call = pCallObject->hQ931Call;
  2651. EventData.error = CS_RINGING_TIMER_EXPIRED;
  2652. pCallObject->Callback(Q931_CALL_FAILED, pCallObject->hQ931Call,
  2653. pCallObject->dwListenToken,
  2654. pCallObject->dwUserToken, &EventData);
  2655. if (CallObjectValidate(hQ931Call) == CS_OK)
  2656. {
  2657. if (Q931SendReleaseCompleteMessage(pCallObject,
  2658. CC_REJECT_TIMER_EXPIRED, NULL, NULL, NULL) == CS_OK)
  2659. {
  2660. // nothing to do...
  2661. }
  2662. {
  2663. DWORD dwId = pCallObject->dwPhysicalId;
  2664. CallObjectDestroy(pCallObject);
  2665. linkLayerShutdown(dwId);
  2666. }
  2667. }
  2668. else
  2669. {
  2670. CallEntryUnlock(hQ931Call);
  2671. }
  2672. return;
  2673. }
  2674. //====================================================================================
  2675. // Timer 303 has expired for this object...
  2676. //====================================================================================
  2677. void
  2678. CallBackT303(P_CALL_OBJECT pCallObject)
  2679. {
  2680. CSS_CALL_FAILED EventData;
  2681. HQ931CALL hQ931Call = pCallObject->hQ931Call;
  2682. EventData.error = CS_SETUP_TIMER_EXPIRED;
  2683. pCallObject->Callback(Q931_CALL_FAILED, pCallObject->hQ931Call,
  2684. pCallObject->dwListenToken,
  2685. pCallObject->dwUserToken, &EventData);
  2686. if (CallObjectValidate(hQ931Call) == CS_OK)
  2687. {
  2688. if (Q931SendReleaseCompleteMessage(pCallObject,
  2689. CC_REJECT_TIMER_EXPIRED, NULL, NULL, NULL) == CS_OK)
  2690. {
  2691. // nothing to do...
  2692. }
  2693. {
  2694. DWORD dwId = pCallObject->dwPhysicalId;
  2695. CallObjectDestroy(pCallObject);
  2696. linkLayerShutdown(dwId);
  2697. }
  2698. }
  2699. else
  2700. {
  2701. CallEntryUnlock(hQ931Call);
  2702. }
  2703. return;
  2704. }
  2705. //====================================================================================
  2706. //====================================================================================
  2707. void
  2708. Q931SetReceivePDUHook(Q931_RECEIVE_PDU_CALLBACK Q931ReceivePDUCallback)
  2709. {
  2710. gReceivePDUHookProc = Q931ReceivePDUCallback;
  2711. return;
  2712. }
  2713. //====================================================================================
  2714. //====================================================================================
  2715. CS_STATUS
  2716. Q931FlushSendQueue(
  2717. HQ931CALL hQ931Call)
  2718. {
  2719. P_CALL_OBJECT pCallObject = NULL;
  2720. HRESULT TempResult = CS_OK;
  2721. DWORD dwPhysicalId;
  2722. if (bQ931Initialized == FALSE)
  2723. {
  2724. return CS_NOT_INITIALIZED;
  2725. }
  2726. ISRTRACE(ghISRInst, "Entering Q931FlushSendQueue()...", 0L);
  2727. // need parameter checking...
  2728. if ((CallObjectLock(hQ931Call, &pCallObject) != CS_OK) || (pCallObject == NULL))
  2729. {
  2730. ISRTRACE(ghISRInst, "Call Object no longer available:", (DWORD)hQ931Call);
  2731. return CS_INTERNAL_ERROR;
  2732. }
  2733. dwPhysicalId = pCallObject->dwPhysicalId;
  2734. CallObjectUnlock(pCallObject);
  2735. TempResult = linkLayerFlushChannel(dwPhysicalId, DATALINK_TRANSMIT);
  2736. if (FAILED(TempResult))
  2737. {
  2738. ISRERROR(ghISRInst, "datalinkSendRequest() failed", 0L);
  2739. }
  2740. return(TempResult);
  2741. }
  2742. #ifdef __cplusplus
  2743. }
  2744. #endif