Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

342 lines
10 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. //
  124. // NetMeeting client doesn't like the fact that we send RST right after
  125. // a ReleaseComplete.
  126. // Yes, it is ugly and bad practice but this is a QFE
  127. // for details look up bug# WinSE 31054, 691666 (read both 35928 and 33546).
  128. //
  129. Sleep( 500 );
  130. // state transition to Q931_SOURCE_STATE_REL_COMP_RCVD
  131. m_Q931SourceState = Q931_SOURCE_STATE_REL_COMP_RCVD;
  132. // initiate shutdown - this cancels the timers, but doesn't close
  133. // the sockets. the sockets are closed when the send callback is made
  134. GetCallBridge().TerminateCallOnReleaseComplete();
  135. GetSocketInfo ().Clear (TRUE);
  136. return S_OK;
  137. }
  138. // processes PDUs when in Q931_SOURCE_STATE_CON_EST state
  139. HRESULT
  140. SOURCE_Q931_INFO::HandleStateSrcConEstd(
  141. IN Q931_MESSAGE *pQ931Message,
  142. IN H323_UserInformation *pH323UserInfo
  143. )
  144. {
  145. if (!pH323UserInfo) {
  146. DebugF(_T("SOURCE_Q931_INFO::HandleStateSrcConEstd: no UUIE data! ignoring message.\n"));
  147. return E_INVALIDARG;
  148. }
  149. // we can only handle a setup PDU in this state
  150. // all other PDUs are THROWN AWAY (as we don't know
  151. // whom to pass it to)
  152. if (setup_chosen != pH323UserInfo->h323_uu_pdu.h323_message_body.choice)
  153. {
  154. DebugF(
  155. _T("SOURCE_Q931_INFO::HandleStateSrcConEstd: received a pdu other than Setup before receiving a Setup, pdu cannot be processed\n"));
  156. return E_INVALIDARG;
  157. }
  158. // save the caller's call reference value now as we may reuse the
  159. // PDU structure in ProcessSourcePDU
  160. // The Setup PDU is sent by the originator and so the call reference flag
  161. // should not be set.
  162. // -XXX- this should not be an assert!!!! FIX THIS! -- arlied
  163. _ASSERTE(!(pQ931Message->CallReferenceValue & CALL_REF_FLAG));
  164. m_CallRefVal = pQ931Message->CallReferenceValue | CALL_REF_FLAG;
  165. // pass on the setup pdu to the Q931 destination instance
  166. HRESULT HResult = GetDestQ931Info().ProcessSourcePDU(
  167. pQ931Message,
  168. pH323UserInfo
  169. );
  170. if (FAILED (HResult))
  171. {
  172. return HResult;
  173. }
  174. // state transition to Q931_SOURCE_STATE_SETUP_RCVD
  175. m_Q931SourceState = Q931_SOURCE_STATE_SETUP_RCVD;
  176. // try to create a CALL PROCEEDING PDU
  177. // if we fail, don't try to recover
  178. // Q.931 requires that gateways in the call path must identify
  179. // themselves to the callee
  180. Q931_MESSAGE CallProcQ931Message;
  181. H323_UserInformation CallProcH323UserInfo;
  182. HResult = Q931EncodeCallProceedingMessage(
  183. m_CallRefVal,
  184. &CallProcQ931Message,
  185. &CallProcH323UserInfo
  186. );
  187. // try to send a CALL PROCEEDING PDU to the caller
  188. // if we fail, don't try to recover
  189. HResult = QueueSend(
  190. &CallProcQ931Message,
  191. &CallProcH323UserInfo);
  192. return HResult;
  193. }
  194. // TimerValue contains the timer value in seconds, for a timer event
  195. // to be created when a queued send completes
  196. HRESULT
  197. SOURCE_Q931_INFO::ProcessDestPDU(
  198. IN Q931_MESSAGE *pQ931Message,
  199. IN H323_UserInformation *pH323UserInfo
  200. )
  201. {
  202. HRESULT HResult = E_FAIL;
  203. // handle PDU from the source Q931 instance
  204. switch(m_Q931SourceState)
  205. {
  206. case Q931_SOURCE_STATE_SETUP_RCVD:
  207. {
  208. if (connect_chosen ==
  209. pH323UserInfo->h323_uu_pdu.h323_message_body.choice)
  210. {
  211. DebugF (_T("Q931: 0x%x forwarding 'Connect' to caller.\n"), &GetCallBridge ());
  212. HResult = ProcessConnectPDU(
  213. pQ931Message,
  214. pH323UserInfo
  215. );
  216. if (FAILED(HResult))
  217. {
  218. DebugF(_T("SOURCE_Q931_INFO::ProcessDestPDU: ProcessConnectPDU failed, returning %x\n"),
  219. HResult);
  220. return HResult;
  221. }
  222. }
  223. }
  224. break;
  225. case Q931_SOURCE_STATE_INIT:
  226. case Q931_SOURCE_STATE_CON_ESTD:
  227. case Q931_SOURCE_STATE_REL_COMP_RCVD:
  228. default:
  229. {
  230. DebugF( _T("SOURCE_Q931_INFO::ProcessDestPDU: bogus state, returning E_UNEXPECTED\n"));
  231. return E_UNEXPECTED;
  232. }
  233. break;
  234. };
  235. // Q931 Header - CallReferenceValue
  236. // pQ931Message->CallReferenceValue = GetCallRefVal();
  237. // queue async send for the PDU
  238. HResult = QueueSend(pQ931Message, pH323UserInfo);
  239. if (HResult != S_OK) {
  240. DebugF( _T("SOURCE_Q931_INFO::ProcessDestPDU: failed to queue sendreturning %x\n"), HResult);
  241. return HResult;
  242. }
  243. return HResult;
  244. }
  245. // NOTE: CRV modification is handled in ProcessDestPDU
  246. HRESULT
  247. SOURCE_Q931_INFO::ProcessConnectPDU(
  248. IN Q931_MESSAGE *pQ931Message,
  249. IN H323_UserInformation *pH323UserInfo
  250. )
  251. {
  252. Connect_UUIE * Connect;
  253. HRESULT Result;
  254. SOCKADDR_IN H245ListenAddress;
  255. // it must be a CONNECT PDU
  256. _ASSERTE(connect_chosen == pH323UserInfo->h323_uu_pdu.h323_message_body.choice);
  257. Connect = &pH323UserInfo -> h323_uu_pdu.h323_message_body.u.connect;
  258. // we must have already checked to see if an h245 transport
  259. // address was specified by the callee in the dest instance
  260. _ASSERTE(Connect_UUIE_h245Address_present & Connect -> bit_mask);
  261. _ASSERTE(ipAddress_chosen & Connect -> h245Address.choice);
  262. // queue an overlapped accept, get ready to accept an incoming
  263. // connection on the local address/port
  264. H245ListenAddress.sin_addr.s_addr = htonl (GetCallBridge (). GetSourceInterfaceAddress ());
  265. H245ListenAddress.sin_port = htons (0);
  266. Result = GetSourceH245Info().ListenForCaller (&H245ListenAddress);
  267. if (FAILED (Result))
  268. {
  269. DebugF (_T("H245: 0x%x failed to listen for caller.\n"), &GetCallBridge ());
  270. return Result;
  271. }
  272. //_ASSERTE(S_FALSE != HResult);
  273. // replace the h245 address/port in the connect PDU
  274. FillTransportAddress (H245ListenAddress, Connect -> h245Address);
  275. DebugF (_T("H245: 0x%x listens for H.245 connection from caller on %08X:%04X.\n"),
  276. &GetCallBridge (),
  277. SOCKADDR_IN_PRINTF (&H245ListenAddress));
  278. return S_OK;
  279. }