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.

335 lines
9.4 KiB

  1. #include "stdafx.h"
  2. #include "cbridge.h"
  3. // SOURCE_Q931_INFO methods
  4. /* virtual */
  5. SOURCE_Q931_INFO::~SOURCE_Q931_INFO(
  6. )
  7. {
  8. }
  9. // this should never get called, but needs to be supported
  10. // as the base class implementation is pure virtual
  11. // virtual
  12. HRESULT SOURCE_Q931_INFO::AcceptCallback (
  13. IN DWORD Status,
  14. IN SOCKET Socket,
  15. IN SOCKADDR_IN * LocalAddress,
  16. IN SOCKADDR_IN * RemoteAddress)
  17. {
  18. // we should never receive an accept call back for the
  19. // Q931 source instance
  20. _ASSERTE(FALSE);
  21. return E_UNEXPECTED;
  22. }
  23. // This function is called by the event manager.
  24. // The caller will free the PDU. This function may modify
  25. // some of the fields of the PDU.
  26. // this is called when an async receive operation completes
  27. // virtual
  28. HRESULT SOURCE_Q931_INFO::ReceiveCallback (
  29. IN Q931_MESSAGE *pQ931Message,
  30. IN H323_UserInformation *pH323UserInfo
  31. )
  32. {
  33. HRESULT HResult;
  34. // we must have valid decoded PDUs
  35. _ASSERTE(NULL != pQ931Message);
  36. // The ASN.1 part is not present in the case of some PDUs
  37. //_ASSERTE(NULL != pH323UserInfo);
  38. // if RELEASE COMPLETE PDU
  39. if (pH323UserInfo != NULL &&
  40. releaseComplete_chosen ==
  41. pH323UserInfo->h323_uu_pdu.h323_message_body.choice)
  42. {
  43. DebugF (_T("Q931: 0x%x caller sent 'Release Complete'.\n"), &GetCallBridge ());
  44. HResult = HandleReleaseCompletePDU(
  45. pQ931Message,
  46. pH323UserInfo
  47. );
  48. return HResult;
  49. }
  50. // check current state and handle the incoming PDU
  51. switch(m_Q931SourceState)
  52. {
  53. case Q931_SOURCE_STATE_CON_ESTD:
  54. {
  55. // processes PDUs when in Q931_SOURCE_STATE_CON_ESTD state
  56. HResult = HandleStateSrcConEstd(
  57. pQ931Message,
  58. pH323UserInfo
  59. );
  60. }
  61. break;
  62. case Q931_SOURCE_STATE_SETUP_RCVD:
  63. {
  64. // Pass on the PDU to the Q931 destination instance which
  65. // passes it on after due modifications
  66. HResult = GetDestQ931Info().ProcessSourcePDU(
  67. pQ931Message,
  68. pH323UserInfo
  69. );
  70. }
  71. break;
  72. case Q931_SOURCE_STATE_INIT:
  73. case Q931_SOURCE_STATE_REL_COMP_RCVD:
  74. default:
  75. {
  76. // we can't be in Q931_SOURCE_STATE_INIT as we wouldn't have
  77. // queued an async receive by then
  78. // we can't be in Q931_SOURCE_STATE_REL_COMP_RCVD as we not have
  79. // queued this receive
  80. // I.K. 0819999 _ASSERTE(FALSE);
  81. HResult = E_UNEXPECTED;
  82. }
  83. break;
  84. };
  85. // if there is an error
  86. if (FAILED(HResult))
  87. {
  88. goto shutdown;
  89. }
  90. // we must queue an async receive irrespective of whether
  91. // the PDU was dropped (IPTEL_E_INVALID_PDU == HResult)
  92. // queue an async receive
  93. HResult = QueueReceive();
  94. if (FAILED(HResult))
  95. {
  96. goto shutdown;
  97. }
  98. return HResult;
  99. shutdown:
  100. // initiate shutdown
  101. GetCallBridge().Terminate ();
  102. return HResult;
  103. }
  104. // handles RELEASE_COMPLETE PDUs
  105. HRESULT
  106. SOURCE_Q931_INFO::HandleReleaseCompletePDU(
  107. IN Q931_MESSAGE *pQ931Message,
  108. IN H323_UserInformation *pH323UserInfo
  109. )
  110. {
  111. // it must be a release complete PDU
  112. _ASSERTE(releaseComplete_chosen == \
  113. pH323UserInfo->h323_uu_pdu.h323_message_body.choice);
  114. // we can handle a RELEASE COMPLETE PDU in any state except the following
  115. _ASSERTE(Q931_SOURCE_STATE_INIT != m_Q931SourceState);
  116. _ASSERTE(Q931_SOURCE_STATE_REL_COMP_RCVD != m_Q931SourceState);
  117. // pass on the pdu to the Q931 source instance
  118. // ignore return error code, if any
  119. GetDestQ931Info().ProcessSourcePDU(
  120. pQ931Message,
  121. pH323UserInfo
  122. );
  123. // state transition to Q931_SOURCE_STATE_REL_COMP_RCVD
  124. m_Q931SourceState = Q931_SOURCE_STATE_REL_COMP_RCVD;
  125. // initiate shutdown - this cancels the timers, but doesn't close
  126. // the sockets. the sockets are closed when the send callback is made
  127. GetCallBridge().TerminateCallOnReleaseComplete();
  128. GetSocketInfo ().Clear (TRUE);
  129. return S_OK;
  130. }
  131. // processes PDUs when in Q931_SOURCE_STATE_CON_EST state
  132. HRESULT
  133. SOURCE_Q931_INFO::HandleStateSrcConEstd(
  134. IN Q931_MESSAGE *pQ931Message,
  135. IN H323_UserInformation *pH323UserInfo
  136. )
  137. {
  138. if (!pH323UserInfo) {
  139. DebugF(_T("SOURCE_Q931_INFO::HandleStateSrcConEstd: no UUIE data! ignoring message.\n"));
  140. return E_INVALIDARG;
  141. }
  142. // we can only handle a setup PDU in this state
  143. // all other PDUs are THROWN AWAY (as we don't know
  144. // whom to pass it to)
  145. if (setup_chosen != pH323UserInfo->h323_uu_pdu.h323_message_body.choice)
  146. {
  147. DebugF(
  148. _T("SOURCE_Q931_INFO::HandleStateSrcConEstd: received a pdu other than Setup before receiving a Setup, pdu cannot be processed\n"));
  149. return E_INVALIDARG;
  150. }
  151. // save the caller's call reference value now as we may reuse the
  152. // PDU structure in ProcessSourcePDU
  153. // The Setup PDU is sent by the originator and so the call reference flag
  154. // should not be set.
  155. // -XXX- this should not be an assert!!!! FIX THIS! -- arlied
  156. _ASSERTE(!(pQ931Message->CallReferenceValue & CALL_REF_FLAG));
  157. m_CallRefVal = pQ931Message->CallReferenceValue | CALL_REF_FLAG;
  158. // pass on the setup pdu to the Q931 destination instance
  159. HRESULT HResult = GetDestQ931Info().ProcessSourcePDU(
  160. pQ931Message,
  161. pH323UserInfo
  162. );
  163. if (FAILED (HResult))
  164. {
  165. return HResult;
  166. }
  167. // state transition to Q931_SOURCE_STATE_SETUP_RCVD
  168. m_Q931SourceState = Q931_SOURCE_STATE_SETUP_RCVD;
  169. // try to create a CALL PROCEEDING PDU
  170. // if we fail, don't try to recover
  171. // Q.931 requires that gateways in the call path must identify
  172. // themselves to the callee
  173. Q931_MESSAGE CallProcQ931Message;
  174. H323_UserInformation CallProcH323UserInfo;
  175. HResult = Q931EncodeCallProceedingMessage(
  176. m_CallRefVal,
  177. &CallProcQ931Message,
  178. &CallProcH323UserInfo
  179. );
  180. // try to send a CALL PROCEEDING PDU to the caller
  181. // if we fail, don't try to recover
  182. HResult = QueueSend(
  183. &CallProcQ931Message,
  184. &CallProcH323UserInfo);
  185. return HResult;
  186. }
  187. // TimerValue contains the timer value in seconds, for a timer event
  188. // to be created when a queued send completes
  189. HRESULT
  190. SOURCE_Q931_INFO::ProcessDestPDU(
  191. IN Q931_MESSAGE *pQ931Message,
  192. IN H323_UserInformation *pH323UserInfo
  193. )
  194. {
  195. HRESULT HResult = E_FAIL;
  196. // handle PDU from the source Q931 instance
  197. switch(m_Q931SourceState)
  198. {
  199. case Q931_SOURCE_STATE_SETUP_RCVD:
  200. {
  201. if (connect_chosen ==
  202. pH323UserInfo->h323_uu_pdu.h323_message_body.choice)
  203. {
  204. DebugF (_T("Q931: 0x%x forwarding 'Connect' to caller.\n"), &GetCallBridge ());
  205. HResult = ProcessConnectPDU(
  206. pQ931Message,
  207. pH323UserInfo
  208. );
  209. if (FAILED(HResult))
  210. {
  211. DebugF(_T("SOURCE_Q931_INFO::ProcessDestPDU: ProcessConnectPDU failed, returning %x\n"),
  212. HResult);
  213. return HResult;
  214. }
  215. }
  216. }
  217. break;
  218. case Q931_SOURCE_STATE_INIT:
  219. case Q931_SOURCE_STATE_CON_ESTD:
  220. case Q931_SOURCE_STATE_REL_COMP_RCVD:
  221. default:
  222. {
  223. DebugF( _T("SOURCE_Q931_INFO::ProcessDestPDU: bogus state, returning E_UNEXPECTED\n"));
  224. return E_UNEXPECTED;
  225. }
  226. break;
  227. };
  228. // Q931 Header - CallReferenceValue
  229. // pQ931Message->CallReferenceValue = GetCallRefVal();
  230. // queue async send for the PDU
  231. HResult = QueueSend(pQ931Message, pH323UserInfo);
  232. if (HResult != S_OK) {
  233. DebugF( _T("SOURCE_Q931_INFO::ProcessDestPDU: failed to queue sendreturning %x\n"), HResult);
  234. return HResult;
  235. }
  236. return HResult;
  237. }
  238. // NOTE: CRV modification is handled in ProcessDestPDU
  239. HRESULT
  240. SOURCE_Q931_INFO::ProcessConnectPDU(
  241. IN Q931_MESSAGE *pQ931Message,
  242. IN H323_UserInformation *pH323UserInfo
  243. )
  244. {
  245. Connect_UUIE * Connect;
  246. HRESULT Result;
  247. SOCKADDR_IN H245ListenAddress;
  248. // it must be a CONNECT PDU
  249. _ASSERTE(connect_chosen == pH323UserInfo->h323_uu_pdu.h323_message_body.choice);
  250. Connect = &pH323UserInfo -> h323_uu_pdu.h323_message_body.u.connect;
  251. // we must have already checked to see if an h245 transport
  252. // address was specified by the callee in the dest instance
  253. _ASSERTE(Connect_UUIE_h245Address_present & Connect -> bit_mask);
  254. _ASSERTE(ipAddress_chosen & Connect -> h245Address.choice);
  255. // queue an overlapped accept, get ready to accept an incoming
  256. // connection on the local address/port
  257. H245ListenAddress.sin_addr.s_addr = htonl (GetCallBridge (). GetSourceInterfaceAddress ());
  258. H245ListenAddress.sin_port = htons (0);
  259. Result = GetSourceH245Info().ListenForCaller (&H245ListenAddress);
  260. if (FAILED (Result))
  261. {
  262. DebugF (_T("H245: 0x%x failed to listen for caller.\n"), &GetCallBridge ());
  263. return Result;
  264. }
  265. //_ASSERTE(S_FALSE != HResult);
  266. // replace the h245 address/port in the connect PDU
  267. FillTransportAddress (H245ListenAddress, Connect -> h245Address);
  268. DebugF (_T("H245: 0x%x listens for H.245 connection from caller on %08X:%04X.\n"),
  269. &GetCallBridge (),
  270. SOCKADDR_IN_PRINTF (&H245ListenAddress));
  271. return S_OK;
  272. }