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.

281 lines
7.7 KiB

  1. /*
  2. * Copyright (c) 1998, Microsoft Corporation
  3. * File: emsend.cpp
  4. *
  5. * Purpose:
  6. *
  7. * Contains all the event manager routines which
  8. * manage the overlapped send operations
  9. *
  10. *
  11. * History:
  12. *
  13. * 1. created
  14. * Ajay Chitturi (ajaych) 12-Jun-1998
  15. *
  16. */
  17. #include "stdafx.h"
  18. #include "cbridge.h"
  19. #include "ovioctx.h"
  20. static
  21. HRESULT
  22. EventMgrIssueSendHelperFn (
  23. IN PSendRecvContext pSendCtxt
  24. );
  25. /*
  26. * This function allocates and returns an initialized SendRecvContext or
  27. * NULL in case of no memory
  28. */
  29. static
  30. PSendRecvContext
  31. EventMgrCreateSendContext(
  32. IN SOCKET sock,
  33. IN OVERLAPPED_PROCESSOR & rOvProcessor,
  34. IN BYTE *pBuf,
  35. IN DWORD BufLen
  36. )
  37. {
  38. PSendRecvContext pSendContext;
  39. pSendContext = (PSendRecvContext) HeapAlloc (GetProcessHeap (),
  40. 0, // No Flags
  41. sizeof(SendRecvContext));
  42. if (!pSendContext)
  43. return NULL;
  44. memset(pSendContext, 0, sizeof(SendRecvContext));
  45. // IO Context part - make this a separate inline function
  46. pSendContext->ioCtxt.reqType = EMGR_OV_IO_REQ_SEND;
  47. pSendContext->ioCtxt.pOvProcessor = &rOvProcessor;
  48. // Send Context part
  49. pSendContext->pbData = pBuf;
  50. pSendContext->dwDataLen = BufLen;
  51. pSendContext->sock = sock;
  52. pSendContext->dwTpktHdrBytesDone = 0;
  53. pSendContext->dwDataBytesDone = 0;
  54. return pSendContext;
  55. }
  56. void
  57. EventMgrFreeSendContext(
  58. IN PSendRecvContext pSendCtxt
  59. )
  60. {
  61. // Socket, OvProcessor are owned by the
  62. // Call Bridge Machine
  63. EM_FREE(pSendCtxt->pbData);
  64. HeapFree (GetProcessHeap (),
  65. 0, // no flags
  66. pSendCtxt);
  67. }
  68. /*++
  69. Routine Description:
  70. This function issues an asynch send of the buffer on the socket.
  71. Calling this passes the ownership of the buffer and this buffer is
  72. freed right here in case of an error. If the call succeeds,
  73. HandleSendCompletion() is responsible for freeing the buffer once
  74. all the bytes are sent.
  75. Arguments:
  76. Return Values:
  77. --*/
  78. HRESULT EventMgrIssueSend(
  79. IN SOCKET sock,
  80. IN OVERLAPPED_PROCESSOR & rOverlappedProcessor,
  81. IN BYTE *pBuf,
  82. IN DWORD BufLen
  83. )
  84. {
  85. PSendRecvContext pSendCtxt;
  86. HRESULT hRes;
  87. // Create Send overlapped I/O context
  88. pSendCtxt = EventMgrCreateSendContext(sock,
  89. rOverlappedProcessor,
  90. pBuf, BufLen);
  91. if (!pSendCtxt)
  92. {
  93. return E_OUTOFMEMORY;
  94. }
  95. // TPKT is already filled in by the encode functions in pdu.cpp
  96. // Fill in the TPKT header based on the packet length
  97. // SetupTPKTHeader(pSendCtxt->pbTpktHdr, pSendCtxt->dwDataLen);
  98. // Do an asynchronous Write
  99. hRes = EventMgrIssueSendHelperFn(pSendCtxt);
  100. if (hRes != S_OK)
  101. {
  102. // This calls also frees the buffer.
  103. EventMgrFreeSendContext(pSendCtxt);
  104. }
  105. return hRes;
  106. }
  107. /*
  108. * Call WriteFile to start an overlapped request
  109. * on a socket. Make sure we handle errors
  110. * that are recoverable.
  111. *
  112. * pSendCtxt is not freed. It is freed only in HandleSendCompletion.
  113. * NO more TPKT stuff.
  114. */
  115. static
  116. HRESULT EventMgrIssueSendHelperFn(
  117. IN PSendRecvContext pSendCtxt
  118. )
  119. {
  120. DWORD dwWritten, dwToSend;
  121. int i = 0;
  122. BOOL bResult;
  123. int err;
  124. PBYTE pbSendBuf;
  125. _ASSERTE(pSendCtxt);
  126. if (pSendCtxt ->ioCtxt.pOvProcessor->IsSocketValid())
  127. {
  128. dwToSend = pSendCtxt->dwDataLen - pSendCtxt->dwDataBytesDone;
  129. pbSendBuf = pSendCtxt->pbData + pSendCtxt->dwDataBytesDone;
  130. // Kick off the first write
  131. while (++i)
  132. {
  133. // make an overlapped I/O Request
  134. memset(&pSendCtxt->ioCtxt.ov, 0, sizeof(OVERLAPPED));
  135. pSendCtxt->ioCtxt.pOvProcessor->GetCallBridge().AddRef();
  136. bResult = WriteFile((HANDLE)pSendCtxt->sock,
  137. pbSendBuf,
  138. dwToSend,
  139. &dwWritten,
  140. &pSendCtxt->ioCtxt.ov
  141. );
  142. // It succeeded immediately, but do not process it
  143. // here, wait for the completion packet.
  144. if (bResult)
  145. return S_OK;
  146. err = GetLastError();
  147. // This is what we want to happen, its not an error
  148. if (err == ERROR_IO_PENDING)
  149. return S_OK;
  150. pSendCtxt->ioCtxt.pOvProcessor->GetCallBridge().Release();
  151. // Handle recoverable errors
  152. if ( err == ERROR_INVALID_USER_BUFFER ||
  153. err == ERROR_NOT_ENOUGH_QUOTA ||
  154. err == ERROR_NOT_ENOUGH_MEMORY )
  155. {
  156. if (i <= 5) // I just picked a number
  157. {
  158. Sleep(50); // Wait around and try later
  159. continue;
  160. }
  161. DebugF(_T("H323: System ran out of non-paged space.\n"));
  162. }
  163. // This means this is an unrecoverable error
  164. // one possibility is that that Call bridge could have closed
  165. // the socket some time in between
  166. break;
  167. }
  168. DebugF(_T("H323: WriteFile(sock: %d) failed. Error: %d.\n"), pSendCtxt->sock, err);
  169. return E_FAIL;
  170. } else {
  171. DebugF (_T("H323: 0x%x overlapped processor %x had invalid socket.\n"),
  172. &pSendCtxt ->ioCtxt.pOvProcessor -> GetCallBridge (),
  173. pSendCtxt ->ioCtxt.pOvProcessor);
  174. return E_ABORT;
  175. }
  176. // Treat as success if overlapped process had its socket disabled
  177. return S_OK;
  178. }
  179. /*
  180. * This function is called by the event loop when a send I/O completes.
  181. * The Call Bridge Machine's send call back function is called.
  182. *
  183. * This function does not return any error code. In case of an error,
  184. * the call bridge machine is notified about the error in the callback.
  185. *
  186. * This function always frees pSendCtxt if another Send is not issued
  187. *
  188. * NO More TPKT stuff.
  189. */
  190. void
  191. HandleSendCompletion (
  192. IN PSendRecvContext pSendCtxt,
  193. IN DWORD dwNumSent,
  194. IN DWORD status
  195. )
  196. {
  197. if (status != NO_ERROR || dwNumSent == 0)
  198. {
  199. // This means the send request failed
  200. HRESULT hRes;
  201. if (status != NO_ERROR)
  202. {
  203. hRes = E_FAIL; //the socket was closed
  204. }
  205. else
  206. {
  207. hRes = HRESULT_FROM_WIN32_ERROR_CODE(status);
  208. }
  209. DebugF(_T("H323: 0x%x rror 0x%x on send callback. dwNumSent: %d\n"),
  210. &pSendCtxt -> ioCtxt.pOvProcessor -> GetCallBridge (),
  211. status, dwNumSent);
  212. pSendCtxt->ioCtxt.pOvProcessor->SendCallback(hRes);
  213. }
  214. else
  215. {
  216. pSendCtxt->dwDataBytesDone += dwNumSent;
  217. // Check if the send completed
  218. if (pSendCtxt->dwDataBytesDone < pSendCtxt->dwDataLen)
  219. {
  220. HRESULT hRes = S_OK;
  221. hRes = EventMgrIssueSendHelperFn(pSendCtxt);
  222. if (hRes != S_OK)
  223. {
  224. pSendCtxt->ioCtxt.pOvProcessor->SendCallback(hRes);
  225. EventMgrFreeSendContext(pSendCtxt);
  226. }
  227. return;
  228. }
  229. // The send completed. Make the callback
  230. pSendCtxt->ioCtxt.pOvProcessor->SendCallback(S_OK);
  231. }
  232. // clean up I/O context structure
  233. EventMgrFreeSendContext(pSendCtxt);
  234. }