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.

1086 lines
32 KiB

  1. /*++
  2. Copyright (c) 1998 - 2000 Microsoft Corporation
  3. Module Name:
  4. dstq931.cpp
  5. Abstract:
  6. Methods for processing Q.931 messages to/from destination side
  7. of a H.323 connection.
  8. Revision History:
  9. --*/
  10. #include "stdafx.h"
  11. DEST_Q931_INFO::~DEST_Q931_INFO (
  12. void
  13. )
  14. /*++
  15. Routine Description:
  16. Constructor for DEST_Q931_INFO class
  17. Arguments:
  18. None
  19. Return Values:
  20. None
  21. Notes:
  22. Virtual
  23. --*/
  24. {
  25. // release the allocated call reference value
  26. // 0 is not a valid call ref value
  27. // Note that the CRV is allocated for both incoming as well as
  28. // outgoing calls.
  29. if (m_CallRefVal != 0)
  30. {
  31. DeallocCallRefVal(m_CallRefVal);
  32. }
  33. }
  34. HRESULT
  35. DEST_Q931_INFO::AcceptCallback (
  36. IN DWORD Status,
  37. IN SOCKET Socket,
  38. IN SOCKADDR_IN * LocalAddress,
  39. IN SOCKADDR_IN * RemoteAddress
  40. )
  41. /*++
  42. Routine Description:
  43. Routine invoked when Q.931 connection is asynchronously accepted
  44. Arguments:
  45. Status -- status code of the asynchronous accept operation
  46. Socket -- handle of the socket on which the accept completed
  47. LocalAddress - address of the local socket that accepted the connection
  48. RemoteAddress - address of the remote socket that initiated the connection
  49. Return Values:
  50. Result of processing the accept completion
  51. Notes:
  52. 1. Virtual
  53. 2. Currently there are not codepaths that would invoke the
  54. method. It is only provided because the base class declares
  55. the function as virtual.
  56. --*/
  57. {
  58. DebugF (_T("Q931: AcceptCallback: status %08XH socket %08XH local address %08X:%04X remote address %08X:%04X) called.\n"),
  59. Status,
  60. Socket,
  61. ntohl (LocalAddress -> sin_addr.s_addr),
  62. ntohs (LocalAddress -> sin_port),
  63. ntohl (RemoteAddress -> sin_addr.s_addr),
  64. ntohs (RemoteAddress -> sin_port));
  65. // we don't yet have any code that'll result in this method
  66. // getting called
  67. _ASSERTE(FALSE);
  68. // CHECK_TERMINATION;
  69. return E_UNEXPECTED;
  70. }
  71. HRESULT DEST_Q931_INFO::ReceiveCallback (
  72. IN Q931_MESSAGE *pQ931Message,
  73. IN H323_UserInformation *pH323UserInfo
  74. )
  75. /*++
  76. Routine Description:
  77. Routine invoked when Q.931 receive from the network completes.
  78. Arguments:
  79. pQ931Message -- Q.931 message received from the network
  80. pH323UserInfo - ASN.1-encoded part of the Q.931 message
  81. Return Values:
  82. Result of processing the received Q.931 message
  83. Notes:
  84. Virtual
  85. --*/
  86. {
  87. HRESULT HResult;
  88. // CHECK_TERMINATION;
  89. // we must have valid decoded PDUs
  90. _ASSERTE(NULL != pQ931Message);
  91. _ASSERTE(NULL != pH323UserInfo);
  92. // CODEWORK: Ensure that this message has an ASN part
  93. // i.e. pH323UserInfo != NULL
  94. // if RELEASE COMPLETE PDU
  95. if (pH323UserInfo != NULL &&
  96. releaseComplete_chosen ==
  97. pH323UserInfo->h323_uu_pdu.h323_message_body.choice)
  98. {
  99. DebugF (_T("Q931: 0x%x callee sent 'Release Complete'.\n"), &GetCallBridge ());
  100. HResult = HandleReleaseCompletePDU(
  101. pQ931Message,
  102. pH323UserInfo
  103. );
  104. return HResult;
  105. }
  106. // handle new PDU from the remote end
  107. switch(m_Q931DestState)
  108. {
  109. case Q931_DEST_STATE_CON_ESTD:
  110. {
  111. // processes PDUs when in Q931_DEST_STATE_CON_EST state
  112. HResult = HandleStateDestConEstd(
  113. pQ931Message,
  114. pH323UserInfo
  115. );
  116. }
  117. break;
  118. case Q931_DEST_STATE_CALL_PROC_RCVD:
  119. {
  120. // processes PDUs when in Q931_DEST_STATE_CALL_PROC_RCVD state
  121. HResult = HandleStateDestCallProcRcvd(
  122. pQ931Message,
  123. pH323UserInfo
  124. );
  125. }
  126. break;
  127. case Q931_DEST_STATE_ALERTING_RCVD:
  128. {
  129. // processes PDUs when in Q931_DEST_STATE_ALERTING_RCVD state
  130. HResult = HandleStateDestAlertingRcvd(
  131. pQ931Message,
  132. pH323UserInfo
  133. );
  134. }
  135. break;
  136. case Q931_DEST_STATE_CONNECT_RCVD:
  137. {
  138. // processes PDUs when in Q931_DEST_STATE_CONNECT_RCVD state
  139. HResult = HandleStateDestConnectRcvd(
  140. pQ931Message,
  141. pH323UserInfo
  142. );
  143. }
  144. break;
  145. case Q931_DEST_STATE_INIT:
  146. case Q931_DEST_STATE_REL_COMP_RCVD:
  147. default:
  148. {
  149. // we cannot be in Q931_DEST_STATE_INIT as we wouldn't have
  150. // queued an async receive by then
  151. // we cannot be in Q931_DEST_STATE_REL_COMP_RCVD as we would
  152. // not have queue an async receive on transitioning to this state
  153. // Commenting out the assert below is fix for #389657
  154. // _ASSERTE(FALSE);
  155. HResult = E_UNEXPECTED;
  156. }
  157. break;
  158. };
  159. // if there is an error
  160. if (FAILED(HResult))
  161. {
  162. goto shutdown;
  163. }
  164. // we must queue an async receive irrespective of whether the previous
  165. // PDU was dropped
  166. HResult = QueueReceive();
  167. if (FAILED(HResult))
  168. {
  169. goto shutdown;
  170. }
  171. //_ASSERTE(S_FALSE != HResult);
  172. return HResult;
  173. shutdown:
  174. // initiate shutdown
  175. GetCallBridge().Terminate ();
  176. return HResult;
  177. }
  178. HRESULT
  179. DEST_Q931_INFO::HandleStateDestConEstd (
  180. IN Q931_MESSAGE *pQ931Message,
  181. IN H323_UserInformation *pH323UserInfo
  182. )
  183. /*++
  184. Routine Description:
  185. Processes Q.931 PDUs when in Q931_DEST_STATE_CON_ESTD state.
  186. CALL_PROCEEDING, ALERTING and CONNECT PDUs are handled here.
  187. Any other PDU is simply passed on to the Q931 source instance
  188. Arguments:
  189. pQ931Message -- Q.931 message received from the network
  190. pH323UserInfo - ASN.1-encoded part of the Q.931 message
  191. Return Values:
  192. Result of the PDU processing
  193. Notes:
  194. --*/
  195. {
  196. HRESULT HResult = E_FAIL;
  197. // check PDU type
  198. switch (pH323UserInfo->h323_uu_pdu.h323_message_body.choice)
  199. {
  200. case callProceeding_chosen : // CALL_PROCEEDING
  201. DebugF (_T("Q931: 0x%x callee sent 'Call Proceeding'.\n"), &GetCallBridge ());
  202. HResult = HandleCallProceedingPDU(
  203. pQ931Message,
  204. pH323UserInfo
  205. );
  206. break;
  207. case alerting_chosen : // ALERTING
  208. DebugF (_T("Q931: 0x%x callee sent 'Alerting'.\n"), &GetCallBridge ());
  209. HResult = HandleAlertingPDU(
  210. pQ931Message,
  211. pH323UserInfo
  212. );
  213. break;
  214. case connect_chosen : // CONNECT
  215. DebugF (_T("Q931: 0x%x callee sent 'Connect'.\n"), &GetCallBridge ());
  216. HResult = HandleConnectPDU(
  217. pQ931Message,
  218. pH323UserInfo
  219. );
  220. break;
  221. default: // everything else
  222. // pass on the pdu to the Q931 source instance
  223. DebugF (_T("Q931: 0x%x callee sent PDU (type %d). Forwarding without processing.\n"),
  224. &GetCallBridge (),
  225. pH323UserInfo->h323_uu_pdu.h323_message_body.choice);
  226. HResult = GetSourceQ931Info().ProcessDestPDU(
  227. pQ931Message,
  228. pH323UserInfo
  229. );
  230. break;
  231. };
  232. return HResult;
  233. }
  234. HRESULT
  235. DEST_Q931_INFO::HandleCallProceedingPDU (
  236. IN Q931_MESSAGE *pQ931Message,
  237. IN H323_UserInformation *pH323UserInfo
  238. )
  239. /*++
  240. Routine Description:
  241. Handles CALL PROCEEDING PDU
  242. Arguments:
  243. IN Q931_MESSAGE *pQ931Message,
  244. IN H323_UserInformation *pH323UserInfo
  245. Return Values:
  246. Result of PDU processing
  247. --*/
  248. {
  249. HRESULT HResult = E_FAIL;
  250. // for fast connect do the following
  251. // if there is h245 info and no current h245 connection
  252. // handle it (save it, establish connection etc.)
  253. // state transition to Q931_DEST_STATE_CONNECT_RCVD
  254. // else
  255. // create new timer for ALERTING
  256. // state transition to Q931_DEST_STATE_CALL_PROC_RCVD
  257. HResult = GetSourceQ931Info().ProcessDestPDU(
  258. pQ931Message,
  259. pH323UserInfo
  260. );
  261. if (FAILED (HResult))
  262. {
  263. return HResult;
  264. }
  265. _ASSERTE(S_OK == HResult);
  266. // cancel current timer (there MUST be one)
  267. // we can only cancel the timer at this point, as we may drop the
  268. // PDU anytime before this
  269. //_ASSERTE(NULL != m_TimerHandle);
  270. TimprocCancelTimer();
  271. DebugF (_T("Q931: 0x%x cancelled timer.\n"),
  272. &GetCallBridge ());
  273. HResult = CreateTimer(Q931_POST_CALL_PROC_TIMER_VALUE);
  274. if (FAILED(HResult))
  275. {
  276. DebugF (_T("Q931: 0x%x failed to create timer for duration %d milliseconds.('Call Proceeding'). Error - %x.\n"),
  277. &GetCallBridge (),
  278. Q931_POST_CALL_PROC_TIMER_VALUE,
  279. HResult);
  280. return HResult;
  281. }
  282. DebugF (_T("Q931: 0x%x created timer for duration %d milliseconds.('Call Proceeding').\n"),
  283. &GetCallBridge (),
  284. Q931_POST_CALL_PROC_TIMER_VALUE);
  285. m_Q931DestState = Q931_DEST_STATE_CALL_PROC_RCVD;
  286. return S_OK;
  287. }
  288. // handles Alerting PDUs
  289. HRESULT
  290. DEST_Q931_INFO::HandleAlertingPDU(
  291. IN Q931_MESSAGE *pQ931Message,
  292. IN H323_UserInformation *pH323UserInfo
  293. )
  294. {
  295. HRESULT HResult = E_FAIL;
  296. // for fast connect do the following
  297. // if there is h245 info and no current h245 connection
  298. // handle it (save it, establish connection etc.)
  299. // state transition to Q931_DEST_STATE_CONNECT_RCVD
  300. // else
  301. // create new timer for CONNECT
  302. // state transition to Q931_DEST_STATE_ALERTING_RCVD
  303. HResult = GetSourceQ931Info().ProcessDestPDU(
  304. pQ931Message,
  305. pH323UserInfo
  306. );
  307. if (FAILED(HResult))
  308. {
  309. return HResult;
  310. }
  311. _ASSERTE(S_OK == HResult);
  312. // cancel current timer (there MUST be one)
  313. // we can only cancel the timer at this point, as we may drop the
  314. // PDU anytime before this
  315. //_ASSERTE(NULL != m_TimerHandle);
  316. TimprocCancelTimer();
  317. DebugF (_T("Q931: 0x%x cancelled timer.\n"),
  318. &GetCallBridge ());
  319. HResult = CreateTimer(Q931_POST_ALERTING_TIMER_VALUE);
  320. if (FAILED(HResult))
  321. {
  322. DebugF (_T("Q931: 0x%x failed to create timer for duration %d milliseconds('Alerting'). Error - %x.\n"),
  323. &GetCallBridge (),
  324. Q931_POST_ALERTING_TIMER_VALUE,
  325. HResult);
  326. return HResult;
  327. }
  328. DebugF (_T("Q931: 0x%x created timer for duration %d milliseconds ('Alerting').\n"),
  329. &GetCallBridge (),
  330. Q931_POST_ALERTING_TIMER_VALUE);
  331. m_Q931DestState = Q931_DEST_STATE_ALERTING_RCVD;
  332. return HResult;
  333. }
  334. // handles CONNECT PDUs
  335. HRESULT
  336. DEST_Q931_INFO::HandleConnectPDU(
  337. IN Q931_MESSAGE *pQ931Message,
  338. IN H323_UserInformation *pH323UserInfo
  339. )
  340. {
  341. Connect_UUIE * Connect;
  342. HRESULT HResult = E_FAIL;
  343. SOCKADDR_IN H245CalleeAddress;
  344. // it has to be a connect PDU
  345. _ASSERTE(connect_chosen == pH323UserInfo->h323_uu_pdu.h323_message_body.choice);
  346. Connect = &pH323UserInfo->h323_uu_pdu.h323_message_body.u.connect;
  347. // we cannot have an earlier h245 connection
  348. _ASSERTE(m_pH323State->GetH245Info().GetSocketInfo().Socket == INVALID_SOCKET);
  349. // if the pdu doesn't have h245 info or a non-ip address is sent
  350. if (!(Connect_UUIE_h245Address_present & Connect -> bit_mask) ||
  351. !(ipAddress_chosen == Connect -> h245Address.choice)) {
  352. // TO DO ** send back a release complete
  353. // go to shutdown mode
  354. DebugF (_T("Q931: 0x%x addressing information missing or bogus, rejecting 'Connect' PDU.\n"), &GetCallBridge());
  355. return E_INVALIDARG;
  356. }
  357. // convert the destination H.245 transport address to address (dword),
  358. // port (word)
  359. HResult = GetTransportInfo(
  360. pH323UserInfo->h323_uu_pdu.h323_message_body.u.connect.h245Address,
  361. H245CalleeAddress);
  362. if (HResult != S_OK)
  363. {
  364. return HResult;
  365. }
  366. // Pass it on to the source Q931 instance
  367. HResult = GetSourceQ931Info().ProcessDestPDU (pQ931Message, pH323UserInfo);
  368. if (HResult != S_OK) {
  369. return HResult;
  370. }
  371. // save the destination's H.245 address/port
  372. // when the source responds by connecting to our sent address/port,
  373. // we'll connect to the destination's sent address/port
  374. GetDestH245Info().SetCalleeInfo (&H245CalleeAddress);
  375. DebugF (_T("H245: 0x%x will make H.245 connection to %08X:%04X.\n"),
  376. &GetCallBridge (),
  377. SOCKADDR_IN_PRINTF (&H245CalleeAddress));
  378. // cancel current timer (there MUST be one)
  379. // we can only cancel the timer at this point, as we may drop the
  380. // PDU anytime before this
  381. //_ASSERTE(NULL != m_TimerHandle);
  382. TimprocCancelTimer();
  383. DebugF (_T("Q931: 0x%x cancelled timer.\n"),
  384. &GetCallBridge ());
  385. // state transition to Q931_DEST_STATE_CONNECT_RCVD
  386. m_Q931DestState = Q931_DEST_STATE_CONNECT_RCVD;
  387. return HResult;
  388. }
  389. // handles RELEASE_COMPLETE PDUs
  390. HRESULT
  391. DEST_Q931_INFO::HandleReleaseCompletePDU(
  392. IN Q931_MESSAGE *pQ931Message,
  393. IN H323_UserInformation *pH323UserInfo
  394. )
  395. {
  396. // it must be a RELEASE COMPLETE PDU
  397. _ASSERTE(releaseComplete_chosen == \
  398. pH323UserInfo->h323_uu_pdu.h323_message_body.choice);
  399. // we can handle a RELEASE COMPLETE PDU in any state except the following
  400. _ASSERTE(Q931_DEST_STATE_INIT != m_Q931DestState);
  401. _ASSERTE(Q931_DEST_STATE_REL_COMP_RCVD != m_Q931DestState);
  402. // cancel current timer if any
  403. // pass on the pdu to the Q931 source instance
  404. // ignore return error code, if any
  405. GetSourceQ931Info().ProcessDestPDU(
  406. pQ931Message,
  407. pH323UserInfo
  408. );
  409. // state transition to Q931_DEST_STATE_REL_COMP_RCVD
  410. m_Q931DestState = Q931_DEST_STATE_REL_COMP_RCVD;
  411. // initiate shutdown - this cancels the timers, but doesn't close
  412. // the sockets. the sockets are closed when the send callback is made
  413. GetCallBridge().TerminateCallOnReleaseComplete();
  414. GetSocketInfo ().Clear (TRUE);
  415. return S_OK;
  416. }
  417. // processes PDUs when in Q931_DEST_STATE_CALL_PROC_RCVD state
  418. HRESULT
  419. DEST_Q931_INFO::HandleStateDestCallProcRcvd(
  420. IN Q931_MESSAGE *pQ931Message,
  421. IN H323_UserInformation *pH323UserInfo
  422. )
  423. {
  424. // we can handle ALERTING and CONNECT
  425. // PDUs here. Any other PDU is simply passed on to the
  426. // Q931 source instance
  427. HRESULT HResult;
  428. switch (pH323UserInfo->h323_uu_pdu.h323_message_body.choice)
  429. {
  430. case alerting_chosen : // ALERTING
  431. {
  432. DebugF (_T("Q931: 0x%x callee sent 'Alerting'.\n"), &GetCallBridge ());
  433. HResult = HandleAlertingPDU(
  434. pQ931Message,
  435. pH323UserInfo
  436. );
  437. }
  438. break;
  439. case connect_chosen : // CONNECT
  440. {
  441. DebugF (_T("Q931: 0x%x callee sent 'Connect'.\n"), &GetCallBridge ());
  442. HResult = HandleConnectPDU(
  443. pQ931Message,
  444. pH323UserInfo
  445. );
  446. }
  447. break;
  448. default:
  449. {
  450. DebugF (_T("Q931: 0x%x callee sent PDU (type %d). Forwarding without processing.\n"),
  451. &GetCallBridge (),
  452. pH323UserInfo->h323_uu_pdu.h323_message_body.choice);
  453. // pass on the pdu to the Q931 source instance
  454. HResult = GetSourceQ931Info().ProcessDestPDU(
  455. pQ931Message,
  456. pH323UserInfo
  457. );
  458. }
  459. break;
  460. };
  461. return HResult;
  462. }
  463. // processes PDUs when in Q931_DEST_STATE_ALERTING_RCVD state
  464. HRESULT
  465. DEST_Q931_INFO::HandleStateDestAlertingRcvd(
  466. IN Q931_MESSAGE *pQ931Message,
  467. IN H323_UserInformation *pH323UserInfo
  468. )
  469. {
  470. // we can handle CONNECT and RELEASE_COMPLETE
  471. // PDUs here. Any other PDU is simply passed on to the
  472. // Q931 source instance
  473. HRESULT HResult = E_FAIL;
  474. switch (pH323UserInfo->h323_uu_pdu.h323_message_body.choice)
  475. {
  476. case connect_chosen : // CONNECT
  477. {
  478. DebugF (_T("Q931: 0x%x callee sent 'Connect'.\n"), &GetCallBridge ());
  479. HResult = HandleConnectPDU(
  480. pQ931Message,
  481. pH323UserInfo
  482. );
  483. }
  484. break;
  485. default:
  486. {
  487. // pass on the pdu to the Q931 source instance
  488. DebugF (_T("Q931: 0x%x callee sent PDU (type %d). Forwarding without processing.\n"),
  489. &GetCallBridge (),
  490. pH323UserInfo->h323_uu_pdu.h323_message_body.choice);
  491. HResult = GetSourceQ931Info().ProcessDestPDU(
  492. pQ931Message,
  493. pH323UserInfo
  494. );
  495. }
  496. break;
  497. };
  498. return HResult;
  499. }
  500. // processes PDUs when in Q931_DEST_STATE_CONNECT_RCVD state
  501. HRESULT
  502. DEST_Q931_INFO::HandleStateDestConnectRcvd(
  503. IN Q931_MESSAGE *pQ931Message,
  504. IN H323_UserInformation *pH323UserInfo
  505. )
  506. {
  507. // all PDUs are simply passed on to the Q931 source instance
  508. HRESULT HResult = E_FAIL;
  509. DebugF (_T("Q931: 0x%x callee sent PDU (type %d). Forwarding without processing.\n"),
  510. &GetCallBridge (),
  511. pH323UserInfo->h323_uu_pdu.h323_message_body.choice);
  512. // pass on the pdu to the Q931 source instance
  513. HResult = GetSourceQ931Info().ProcessDestPDU(
  514. pQ931Message,
  515. pH323UserInfo
  516. );
  517. return HResult;
  518. }
  519. HRESULT
  520. DEST_Q931_INFO::ProcessSourcePDU(
  521. IN Q931_MESSAGE *pQ931Message,
  522. IN H323_UserInformation *pH323UserInfo
  523. )
  524. {
  525. // handle PDU from the source Q931 instance
  526. switch(m_Q931DestState)
  527. {
  528. case Q931_DEST_STATE_INIT:
  529. {
  530. HRESULT HResult = E_FAIL;
  531. // we can only handle the SETUP PDU in this state
  532. // establishes Q931 connection, forwards the SETUP PDU and
  533. // queues the first async receive on the new socket
  534. DebugF (_T("Q931: 0x%x caller sent 'Setup'.\n"), &GetCallBridge ());
  535. HResult = ProcessSourceSetupPDU(
  536. pQ931Message,
  537. pH323UserInfo
  538. );
  539. return HResult;
  540. }
  541. case Q931_DEST_STATE_CON_ESTD:
  542. case Q931_DEST_STATE_CALL_PROC_RCVD:
  543. case Q931_DEST_STATE_ALERTING_RCVD:
  544. case Q931_DEST_STATE_CONNECT_RCVD:
  545. {
  546. // pass on the PDU after modifications
  547. DebugF (_T("Q931: 0x%x caller sent PDU (type %d). Forwarding without processing.\n"),
  548. &GetCallBridge (),
  549. pH323UserInfo->h323_uu_pdu.h323_message_body.choice);
  550. }
  551. break;
  552. case Q931_DEST_STATE_REL_COMP_RCVD:
  553. default:
  554. {
  555. return E_UNEXPECTED;
  556. }
  557. break;
  558. };
  559. // we come here only if we fall through the switch statement
  560. // Q931 Header - change CallReferenceValue
  561. // pQ931Message->CallReferenceValue = GetCallRefVal();
  562. // queue async send for the PDU
  563. HRESULT HResult = E_FAIL;
  564. HResult = QueueSend(pQ931Message, pH323UserInfo);
  565. if (FAILED(HResult))
  566. {
  567. return HResult;
  568. }
  569. return HResult;
  570. }
  571. HRESULT
  572. DEST_Q931_INFO::ProcessSourceSetupPDU(
  573. IN Q931_MESSAGE *pQ931Message,
  574. IN H323_UserInformation *pH323UserInfo
  575. )
  576. {
  577. Setup_UUIE * Setup;
  578. HRESULT Result;
  579. ULONG Error;
  580. SOCKADDR_IN DestinationAddress = {0};
  581. DWORD TranslatedDestinationAddress = 0;
  582. AliasAddress * Alias;
  583. ANSI_STRING AnsiAlias;
  584. ASN1uint32_t OldFastStartBit = 0U;
  585. ASN1uint32_t OldH245TunnelingBit = 0U;
  586. ASN1bool_t OldH245TunnelingFlag = FALSE;
  587. GetCallBridge ().GetDestinationAddress (&DestinationAddress);
  588. _ASSERTE(Q931_DEST_STATE_INIT == m_Q931DestState);
  589. // it has to be a Setup PDU
  590. if (setup_chosen != pH323UserInfo->h323_uu_pdu.h323_message_body.choice)
  591. {
  592. DebugF(_T("Q931: 0x%x in Setup PDU UUIE is not a Setup-UUIE, rejecting PDU.\n"), &GetCallBridge ());
  593. return E_UNEXPECTED;
  594. }
  595. Setup = &pH323UserInfo -> h323_uu_pdu.h323_message_body.u.setup;
  596. // Generate the Call Reference Value for both incoming/outgoing calls
  597. if (!AllocCallRefVal(m_CallRefVal))
  598. {
  599. DebugF(_T("Q931: 0x%x failed to allocate call reference value.\n"), &GetCallBridge ());
  600. return E_UNEXPECTED;
  601. }
  602. // examine the alias from the Setup-UUIE, query the LDAP translation table
  603. if (Setup -> bit_mask & destinationAddress_present
  604. && Setup -> destinationAddress) {
  605. CHAR AnsiAliasValue [0x100];
  606. INT Length;
  607. Alias = &Setup -> destinationAddress -> value;
  608. switch (Alias -> choice) {
  609. case h323_ID_chosen:
  610. // the expected case
  611. // downgrade to ANSI
  612. Length = WideCharToMultiByte (CP_ACP, 0, (LPWSTR)Alias -> u.h323_ID.value,
  613. Alias -> u.h323_ID.length,
  614. AnsiAliasValue, 0xFF, NULL, NULL);
  615. if (!Length) {
  616. DebugF (_T("Q931: 0x%x failed to convert unicode string. Internal error.\n"), &GetCallBridge ());
  617. return E_FAIL;
  618. }
  619. AnsiAliasValue [Length] = 0;
  620. AnsiAlias.Buffer = AnsiAliasValue;
  621. AnsiAlias.Length = Length * (USHORT)sizeof (CHAR);
  622. break;
  623. case email_ID_chosen:
  624. AnsiAlias.Buffer = Alias -> u.email_ID;
  625. AnsiAlias.Length = (USHORT) strlen (Alias -> u.email_ID) * sizeof (CHAR);
  626. break;
  627. case e164_chosen:
  628. AnsiAlias.Buffer = Alias -> u.e164;
  629. AnsiAlias.Length = (USHORT) strlen (Alias -> u.e164) * sizeof (CHAR);
  630. break;
  631. default:
  632. DebugF (_T("Q931: 0x%x bogus alias address type.\n"), &GetCallBridge());
  633. return E_FAIL;
  634. }
  635. Result = LdapQueryTableByAlias (&AnsiAlias, &TranslatedDestinationAddress);
  636. if (Result == S_OK) {
  637. DebugF (_T("Q931: 0x%x resolved alias (%.*S) to address %08X.\n"),
  638. &GetCallBridge (),
  639. ANSI_STRING_PRINTF (&AnsiAlias),
  640. TranslatedDestinationAddress);
  641. // Change the initial destination address to the one read from
  642. // the LDAP Address Translation Table
  643. DestinationAddress.sin_addr.s_addr = htonl (TranslatedDestinationAddress);
  644. }
  645. else {
  646. DebugF (_T("Q931: 0x%x failed to resolve alias (%.*S) in LDAP table.\n"),
  647. &GetCallBridge (),
  648. ANSI_STRING_PRINTF (&AnsiAlias));
  649. }
  650. }
  651. else {
  652. DebugF (_T("Q931: 0x%x destination not specified. Looking in registry for special destination.\n"),
  653. &GetCallBridge ());
  654. Result = LookupDefaultDestination (&TranslatedDestinationAddress);
  655. if (Result == S_OK) {
  656. DestinationAddress.sin_addr.s_addr = htonl (TranslatedDestinationAddress);
  657. DebugF (_T("Q931: 0x%x found special destination in registry.\n"),
  658. &GetCallBridge ());
  659. }
  660. else {
  661. DebugF (_T("Q931: 0x%x did not find special destination in registry.\n"),
  662. &GetCallBridge ());
  663. }
  664. }
  665. DebugF (_T("Q931: 0x%x will use address %08X:%04X as destination.\n"),
  666. &GetCallBridge (),
  667. SOCKADDR_IN_PRINTF (&DestinationAddress));
  668. Error = GetBestInterfaceAddress (ntohl (DestinationAddress.sin_addr.s_addr), &GetCallBridge ().DestinationInterfaceAddress);
  669. if (ERROR_SUCCESS != Error) {
  670. DebugF (_T("Q931: 0x%x failed to determine destination interface address for %08X:%04X.\n"),
  671. &GetCallBridge (),
  672. SOCKADDR_IN_PRINTF (&DestinationAddress));
  673. return HRESULT_FROM_WIN32 (Error);
  674. }
  675. Result = ConnectToH323Endpoint (&DestinationAddress);
  676. if (Result != S_OK) {
  677. DebugF (_T("Q931: 0x%x failed to connect to address %08X:%04X.\n"),
  678. &GetCallBridge (),
  679. SOCKADDR_IN_PRINTF (&DestinationAddress));
  680. return E_FAIL;
  681. }
  682. // If the call succeeds, then the connection to the destination is
  683. // established. So, the Q.931 PDU can be modified and sent to the
  684. // destination.
  685. // Q931 Header - CallReferenceValue
  686. // pQ931Message->CallReferenceValue = GetCallRefVal();
  687. // H323UserInfo -
  688. // destCallSignalAddress TransportAddress OPTIONAL
  689. // sourceCallSignalAddress TransportAddress OPTIONAL
  690. // if the destCallSignalAddress is set, replace it with the
  691. // remote ip v4 address, port
  692. if (Setup -> bit_mask & Setup_UUIE_destCallSignalAddress_present) {
  693. FillTransportAddress (
  694. m_SocketInfo.RemoteAddress,
  695. Setup -> destCallSignalAddress);
  696. }
  697. // if the sourceCallSignalAddress is set, replace it with
  698. // own ip v4 address, port
  699. if (Setup -> bit_mask & sourceCallSignalAddress_present) {
  700. FillTransportAddress (
  701. m_SocketInfo.LocalAddress,
  702. Setup -> sourceCallSignalAddress);
  703. }
  704. // if ANY of the fields in the extension field are set,
  705. // then make sure that all of the mandatory extension fields
  706. // are set. this is a workaround for a problem caused by
  707. // inconsistent ASN.1 files. -- arlied
  708. if ((sourceCallSignalAddress_present
  709. | Setup_UUIE_remoteExtensionAddress_present
  710. | Setup_UUIE_callIdentifier_present
  711. | h245SecurityCapability_present
  712. | Setup_UUIE_tokens_present
  713. | Setup_UUIE_cryptoTokens_present
  714. | Setup_UUIE_fastStart_present
  715. | canOverlapSend_present
  716. | mediaWaitForConnect_present
  717. ) & Setup -> bit_mask) {
  718. // check each mandatory field
  719. // fill in quasi-bogus values for those that the source did not supply
  720. if (!(Setup -> bit_mask & Setup_UUIE_callIdentifier_present)) {
  721. Debug (_T("Q931: *** warning, source did NOT fill in the mandatory callIdentifier field! using zeroes\n"));
  722. ZeroMemory (Setup -> callIdentifier.guid.value, sizeof (GUID));
  723. Setup -> callIdentifier.guid.length = sizeof (GUID);
  724. Setup -> bit_mask |= Setup_UUIE_callIdentifier_present;
  725. }
  726. if (!(Setup -> bit_mask & canOverlapSend_present)) {
  727. Debug (_T("Q931: *** warning, source did NOT fill in the mandatory canOverlapSend field! using value of FALSE\n"));
  728. Setup -> canOverlapSend = FALSE;
  729. Setup -> bit_mask |= canOverlapSend_present;
  730. }
  731. if (!(Setup -> bit_mask & mediaWaitForConnect_present)) {
  732. Debug (_T("Q931: *** warning, source did NOT fill in the mandatory mediaWaitForConnect field! using value of FALSE\n"));
  733. Setup -> mediaWaitForConnect = FALSE;
  734. Setup -> bit_mask |= mediaWaitForConnect_present;
  735. }
  736. // We don't support FastStart procedures for now
  737. // Save the information on whether fastStart element was present: it will
  738. // have to be restored later.
  739. OldFastStartBit = Setup -> bit_mask & Setup_UUIE_fastStart_present;
  740. // Now unconditionally turn off FastStart
  741. Setup -> bit_mask &= ~Setup_UUIE_fastStart_present;
  742. }
  743. // We don't support H.245 Tunneling
  744. // Save the information on whether this PDU contained H.245 tunneled data: it will
  745. // have to be restored later.
  746. OldH245TunnelingBit = pH323UserInfo -> h323_uu_pdu.bit_mask & h245Tunneling_present;
  747. OldH245TunnelingFlag = pH323UserInfo -> h323_uu_pdu.h245Tunneling;
  748. // Now unconditionally turn off H.245 tunneling
  749. pH323UserInfo -> h323_uu_pdu.bit_mask &= ~h245Tunneling_present;
  750. pH323UserInfo -> h323_uu_pdu.h245Tunneling = FALSE;
  751. // queue async send for SETUP PDU
  752. Result = QueueSend(pQ931Message, pH323UserInfo);
  753. if (FAILED(Result)) {
  754. DebugF (_T("Q931: 0x%x failed to queue send.\n"), &GetCallBridge ());
  755. goto cleanup;
  756. }
  757. // Need to restore information about FastStart and H.245 tunneling so that the
  758. // Setup PDU is properly deallocated by the ASN.1 module
  759. Setup -> bit_mask |= OldFastStartBit;
  760. pH323UserInfo -> h323_uu_pdu.bit_mask |= OldH245TunnelingBit;
  761. pH323UserInfo -> h323_uu_pdu.h245Tunneling = OldH245TunnelingFlag;
  762. // since the socket was created just now, we must
  763. // queue the first async receive
  764. Result = QueueReceive();
  765. if (FAILED(Result)) {
  766. DebugF (_T("Q931: 0x%x failed to queue receive.\n"), &GetCallBridge());
  767. goto cleanup;
  768. }
  769. Result = CreateTimer (Q931_POST_SETUP_TIMER_VALUE);
  770. if (FAILED(Result)) {
  771. DebugF (_T("Q931: 0x%x failed to create timer for duration %d milliseconds ('Setup'). Error - %x.\n"),
  772. &GetCallBridge (),
  773. Q931_POST_SETUP_TIMER_VALUE,
  774. Result);
  775. goto cleanup;
  776. }
  777. DebugF (_T("Q931: 0x%x created timer for duration %d milliseconds('Setup').\n"),
  778. &GetCallBridge (),
  779. Q931_POST_SETUP_TIMER_VALUE);
  780. // state transition to Q931_DEST_STATE_CON_ESTD
  781. m_Q931DestState = Q931_DEST_STATE_CON_ESTD;
  782. return Result;
  783. cleanup:
  784. m_SocketInfo.Clear(TRUE);
  785. return Result;
  786. }
  787. #define IPV4_ADDR_MAX_LEN 0x10 // max length of quad-dotted representation of an IP address
  788. HRESULT DEST_Q931_INFO::LookupDefaultDestination (
  789. OUT DWORD * ReturnAddress) // host order
  790. {
  791. TCHAR szDefaultLocalDestAddr [IPV4_ADDR_MAX_LEN];
  792. LONG Result;
  793. DWORD ValueLength;
  794. DWORD Type;
  795. HKEY Key;
  796. SOCKADDR_IN Address = { 0 };
  797. INT AddressLength = sizeof(SOCKADDR_IN);
  798. // 1. Open the registry key containing the proxy's parameters
  799. Result = RegOpenKeyEx (HKEY_LOCAL_MACHINE, H323ICS_SERVICE_PARAMETERS_KEY_PATH,
  800. 0, KEY_READ, &Key);
  801. if (Result != ERROR_SUCCESS)
  802. {
  803. DebugF(_T("Q931: 0x%x could not open registry parameter key. Error: %d(0x%x)"),
  804. &GetCallBridge (),
  805. Result, Result);
  806. return Result;
  807. }
  808. // 2. Read the value of the default destination on the local subnet
  809. ValueLength = sizeof (szDefaultLocalDestAddr);
  810. Result = RegQueryValueEx (
  811. Key,
  812. H323ICS_REG_VAL_DEFAULT_LOCAL_DEST_ADDR,
  813. 0,
  814. &Type,
  815. (LPBYTE) szDefaultLocalDestAddr,
  816. &ValueLength);
  817. if (Result != ERROR_SUCCESS || Type != REG_SZ)
  818. {
  819. szDefaultLocalDestAddr[0] = '\0';
  820. RegCloseKey (Key);
  821. return S_FALSE;
  822. }
  823. // 3. Close the registry key for the proxy parameters
  824. RegCloseKey (Key);
  825. // 4. Convert the string with the IP address of the default
  826. // destination on the local subnet to its binary representation
  827. Result = WSAStringToAddress(
  828. szDefaultLocalDestAddr,
  829. AF_INET,
  830. NULL,
  831. (SOCKADDR *) &Address,
  832. &AddressLength
  833. );
  834. if (Result != ERROR_SUCCESS)
  835. {
  836. DebugF (_T("Q931: Bogus address (%S).\n"), szDefaultLocalDestAddr);
  837. return Result;
  838. }
  839. // 5. Prepare the return address in host order
  840. *ReturnAddress = htonl (Address.sin_addr.s_addr);
  841. return ERROR_SUCCESS;
  842. }
  843. HRESULT DEST_Q931_INFO::ConnectToH323Endpoint(
  844. IN SOCKADDR_IN * DestinationAddress)
  845. {
  846. INT Status;
  847. // Connect to the destination specifed by the client (for outbound calls)
  848. // or to the selected destination on the local subnet (for inbound calls)
  849. Status = m_SocketInfo.Connect (DestinationAddress);
  850. if (Status == 0)
  851. {
  852. DebugF (_T ("Q931: 0x%x successfully connected to %08X:%04X.\n"),
  853. &GetCallBridge (),
  854. SOCKADDR_IN_PRINTF (DestinationAddress));
  855. return S_OK;
  856. }
  857. else
  858. {
  859. DebugErrorF (Status, _T("Q931: 0x%x failed to connect to %08X:%04X.\n"),
  860. &GetCallBridge (),
  861. SOCKADDR_IN_PRINTF (DestinationAddress));
  862. return HRESULT_FROM_WIN32 (Status);
  863. }
  864. }