Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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