private static void OnReadCompleted(object sender, HttpListenerAsyncEventArgs eventArgs) { Contract.Assert(eventArgs != null, "'eventArgs' MUST NOT be NULL."); WebSocketHttpListenerDuplexStream thisPtr = eventArgs.CurrentStream; Contract.Assert(thisPtr != null, "'thisPtr' MUST NOT be NULL."); #if DEBUG Contract.Assert(Interlocked.Decrement(ref thisPtr.m_OutstandingOperations.m_Reads) >= 0, "'thisPtr.m_OutstandingOperations.m_Reads' MUST NOT be negative."); #endif if (WebSocketBase.LoggingEnabled) { Logging.Enter(Logging.WebSockets, thisPtr, Methods.OnReadCompleted, string.Empty); } if (eventArgs.Exception != null) { thisPtr.m_ReadTaskCompletionSource.TrySetException(eventArgs.Exception); } else { thisPtr.m_ReadTaskCompletionSource.TrySetResult(eventArgs.BytesTransferred); } if (WebSocketBase.LoggingEnabled) { Logging.Exit(Logging.WebSockets, thisPtr, Methods.OnReadCompleted, string.Empty); } }
public void SwitchToOpaqueMode(WebSocketBase webSocket) { Debug.Assert(webSocket != null, "'webSocket' MUST NOT be NULL."); Debug.Assert(_outputStream != null, "'m_OutputStream' MUST NOT be NULL."); Debug.Assert(_outputStream.InternalHttpContext != null, "'m_OutputStream.InternalHttpContext' MUST NOT be NULL."); Debug.Assert(_outputStream.InternalHttpContext.Response != null, "'m_OutputStream.InternalHttpContext.Response' MUST NOT be NULL."); Debug.Assert(_outputStream.InternalHttpContext.Response.SentHeaders, "Headers MUST have been sent at this point."); Debug.Assert(!_inOpaqueMode, "SwitchToOpaqueMode MUST NOT be called multiple times."); if (_inOpaqueMode) { throw new InvalidOperationException(); } _webSocket = webSocket; _inOpaqueMode = true; _readEventArgs = new HttpListenerAsyncEventArgs(webSocket, this); _readEventArgs.Completed += s_OnReadCompleted; _writeEventArgs = new HttpListenerAsyncEventArgs(webSocket, this); _writeEventArgs.Completed += s_OnWriteCompleted; if (NetEventSource.IsEnabled) { NetEventSource.Associate(this, webSocket); } }
public void SwitchToOpaqueMode(WebSocketBase webSocket) { Contract.Assert(webSocket != null, "'webSocket' MUST NOT be NULL."); Contract.Assert(m_OutputStream != null, "'m_OutputStream' MUST NOT be NULL."); Contract.Assert(m_OutputStream.InternalHttpContext != null, "'m_OutputStream.InternalHttpContext' MUST NOT be NULL."); Contract.Assert(m_OutputStream.InternalHttpContext.Response != null, "'m_OutputStream.InternalHttpContext.Response' MUST NOT be NULL."); Contract.Assert(m_OutputStream.InternalHttpContext.Response.SentHeaders, "Headers MUST have been sent at this point."); Contract.Assert(!m_InOpaqueMode, "SwitchToOpaqueMode MUST NOT be called multiple times."); if (m_InOpaqueMode) { throw new InvalidOperationException(); } m_WebSocket = webSocket; m_InOpaqueMode = true; m_ReadEventArgs = new HttpListenerAsyncEventArgs(webSocket, this); m_ReadEventArgs.Completed += s_OnReadCompleted; m_WriteEventArgs = new HttpListenerAsyncEventArgs(webSocket, this); m_WriteEventArgs.Completed += s_OnWriteCompleted; if (WebSocketBase.LoggingEnabled) { Logging.Associate(Logging.WebSockets, this, webSocket); } }
private static void OnReadCompleted(object sender, HttpListenerAsyncEventArgs eventArgs) { Debug.Assert(eventArgs != null, "'eventArgs' MUST NOT be NULL."); WebSocketHttpListenerDuplexStream thisPtr = eventArgs.CurrentStream; Debug.Assert(thisPtr != null, "'thisPtr' MUST NOT be NULL."); #if DEBUG Debug.Assert(Interlocked.Decrement(ref thisPtr._outstandingOperations._reads) >= 0, "'thisPtr.m_OutstandingOperations.m_Reads' MUST NOT be negative."); #endif if (NetEventSource.IsEnabled) { NetEventSource.Enter(thisPtr); } if (eventArgs.Exception != null) { thisPtr._readTaskCompletionSource.TrySetException(eventArgs.Exception); } else { thisPtr._readTaskCompletionSource.TrySetResult(eventArgs.BytesTransferred); } if (NetEventSource.IsEnabled) { NetEventSource.Exit(thisPtr); } }
protected virtual void OnCompleted(HttpListenerAsyncEventArgs e) { EventHandler <HttpListenerAsyncEventArgs> handler = m_Completed; if (handler != null) { handler(e.m_CurrentStream, e); } }
private static void OnWriteCompleted(object?sender, HttpListenerAsyncEventArgs eventArgs) { Debug.Assert(eventArgs != null, "'eventArgs' MUST NOT be NULL."); WebSocketHttpListenerDuplexStream thisPtr = eventArgs.CurrentStream; Debug.Assert(thisPtr != null, "'thisPtr' MUST NOT be NULL."); #if DEBUG Debug.Assert(Interlocked.Decrement(ref thisPtr._outstandingOperations._writes) >= 0, "'thisPtr.m_OutstandingOperations.m_Writes' MUST NOT be negative."); #endif if (eventArgs.Exception != null) { thisPtr._writeTaskCompletionSource !.TrySetException(eventArgs.Exception); } else { thisPtr._writeTaskCompletionSource !.TrySetResult(); } }
protected virtual void OnCompleted(HttpListenerAsyncEventArgs e) { m_Completed?.Invoke(e._currentStream, e); }
// return value indicates [....] vs async completion // false: [....] completion // true: async completion private bool WriteAsyncFast(HttpListenerAsyncEventArgs eventArgs) { if (WebSocketBase.LoggingEnabled) { Logging.Enter(Logging.WebSockets, this, Methods.WriteAsyncFast, string.Empty); } UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE; eventArgs.StartOperationCommon(this); eventArgs.StartOperationSend(); uint statusCode; bool completedAsynchronously = false; try { if (m_OutputStream.Closed || (eventArgs.Buffer != null && eventArgs.Count == 0)) { eventArgs.FinishOperationSuccess(eventArgs.Count, true); return(false); } if (eventArgs.ShouldCloseOutput) { flags |= UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT; } else { flags |= UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; // When using HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA HTTP.SYS will copy the payload to // kernel memory (Non-Paged Pool). Http.Sys will buffer up to // Math.Min(16 MB, current TCP window size) flags |= UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA; } m_OutputStream.InternalHttpContext.EnsureBoundHandle(); uint bytesSent; statusCode = UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody2( m_OutputStream.InternalHttpContext.RequestQueueHandle, m_OutputStream.InternalHttpContext.RequestId, (uint)flags, eventArgs.EntityChunkCount, eventArgs.EntityChunks, out bytesSent, SafeLocalFree.Zero, 0, eventArgs.NativeOverlapped, IntPtr.Zero); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) { throw new HttpListenerException((int)statusCode); } else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. eventArgs.FinishOperationSuccess((int)bytesSent, true); completedAsynchronously = false; } else { completedAsynchronously = true; } } catch (Exception e) { m_WriteEventArgs.FinishOperationFailure(e, true); m_OutputStream.SetClosedFlag(); m_OutputStream.InternalHttpContext.Abort(); throw; } finally { if (WebSocketBase.LoggingEnabled) { Logging.Exit(Logging.WebSockets, this, Methods.WriteAsyncFast, completedAsynchronously); } } return(completedAsynchronously); }
// return value indicates sync vs async completion // false: sync completion // true: async completion or error private unsafe bool ReadAsyncFast(HttpListenerAsyncEventArgs eventArgs) { eventArgs.StartOperationCommon(this, _inputStream.InternalHttpContext.RequestQueueBoundHandle); eventArgs.StartOperationReceive(); bool completedAsynchronouslyOrWithError; try { Debug.Assert(eventArgs.Buffer != null, "'BufferList' is not supported for read operations."); if (eventArgs.Count == 0 || _inputStream.Closed) { eventArgs.FinishOperationSuccess(0, true); return(false); } uint dataRead = 0; int offset = eventArgs.Offset; int remainingCount = eventArgs.Count; if (_inputStream.BufferedDataChunksAvailable) { dataRead = _inputStream.GetChunks(eventArgs.Buffer, eventArgs.Offset, eventArgs.Count); if (_inputStream.BufferedDataChunksAvailable && dataRead == eventArgs.Count) { eventArgs.FinishOperationSuccess(eventArgs.Count, true); return(false); } } Debug.Assert(!_inputStream.BufferedDataChunksAvailable, "'m_InputStream.BufferedDataChunksAvailable' MUST BE 'FALSE' at this point."); Debug.Assert(dataRead <= eventArgs.Count, "'dataRead' MUST NOT be bigger than 'eventArgs.Count'."); if (dataRead != 0) { offset += (int)dataRead; remainingCount -= (int)dataRead; //the http.sys team recommends that we limit the size to 128kb if (remainingCount > HttpRequestStream.MaxReadSize) { remainingCount = HttpRequestStream.MaxReadSize; } eventArgs.SetBuffer(eventArgs.Buffer, offset, remainingCount); } else if (remainingCount > HttpRequestStream.MaxReadSize) { remainingCount = HttpRequestStream.MaxReadSize; eventArgs.SetBuffer(eventArgs.Buffer, offset, remainingCount); } uint flags = 0; uint bytesReturned = 0; uint statusCode = Interop.HttpApi.HttpReceiveRequestEntityBody( _inputStream.InternalHttpContext.RequestQueueHandle, _inputStream.InternalHttpContext.RequestId, flags, (byte *)_webSocket !.InternalBuffer.ToIntPtr(eventArgs.Offset), (uint)eventArgs.Count, out bytesReturned, eventArgs.NativeOverlapped); if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF) { throw new HttpListenerException((int)statusCode); } else if (statusCode == Interop.HttpApi.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously. No IO completion port callback is used because // it was disabled in SwitchToOpaqueMode() eventArgs.FinishOperationSuccess((int)bytesReturned, true); completedAsynchronouslyOrWithError = false; } else if (statusCode == Interop.HttpApi.ERROR_HANDLE_EOF) { eventArgs.FinishOperationSuccess(0, true); completedAsynchronouslyOrWithError = false; } else { completedAsynchronouslyOrWithError = true; } } catch (Exception e) { _readEventArgs !.FinishOperationFailure(e, true); _outputStream.SetClosedFlag(); _outputStream.InternalHttpContext.Abort(); completedAsynchronouslyOrWithError = true; } return(completedAsynchronouslyOrWithError); }
// return value indicates sync vs async completion // false: sync completion // true: async completion private bool WriteAsyncFast(HttpListenerAsyncEventArgs eventArgs) { if (WebSocketBase.LoggingEnabled) { Logging.Enter(Logging.WebSockets, this, Methods.WriteAsyncFast, string.Empty); } UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE; eventArgs.StartOperationCommon(this); eventArgs.StartOperationSend(); uint statusCode; bool completedAsynchronously = false; try { if (m_OutputStream.Closed || (eventArgs.Buffer != null && eventArgs.Count == 0)) { eventArgs.FinishOperationSuccess(eventArgs.Count, true); return false; } if (eventArgs.ShouldCloseOutput) { flags |= UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT; } else { flags |= UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; // When using HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA HTTP.SYS will copy the payload to // kernel memory (Non-Paged Pool). Http.Sys will buffer up to // Math.Min(16 MB, current TCP window size) flags |= UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA; } m_OutputStream.InternalHttpContext.EnsureBoundHandle(); uint bytesSent; statusCode = UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody2( m_OutputStream.InternalHttpContext.RequestQueueHandle, m_OutputStream.InternalHttpContext.RequestId, (uint)flags, eventArgs.EntityChunkCount, eventArgs.EntityChunks, out bytesSent, SafeLocalFree.Zero, 0, eventArgs.NativeOverlapped, IntPtr.Zero); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) { throw new HttpListenerException((int)statusCode); } else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. eventArgs.FinishOperationSuccess((int)bytesSent, true); completedAsynchronously = false; } else { completedAsynchronously = true; } } catch (Exception e) { m_WriteEventArgs.FinishOperationFailure(e, true); m_OutputStream.SetClosedFlag(); m_OutputStream.InternalHttpContext.Abort(); throw; } finally { if (WebSocketBase.LoggingEnabled) { Logging.Exit(Logging.WebSockets, this, Methods.WriteAsyncFast, completedAsynchronously); } } return completedAsynchronously; }
protected virtual void OnCompleted(HttpListenerAsyncEventArgs e) { EventHandler<HttpListenerAsyncEventArgs> handler = m_Completed; if (handler != null) { handler(e.m_CurrentStream, e); } }
// return value indicates sync vs async completion // false: sync completion // true: async completion private unsafe bool ReadAsyncFast(HttpListenerAsyncEventArgs eventArgs) { if (NetEventSource.IsEnabled) { NetEventSource.Enter(this); } eventArgs.StartOperationCommon(this, _inputStream.InternalHttpContext.RequestQueueBoundHandle); eventArgs.StartOperationReceive(); uint statusCode = 0; bool completedAsynchronously = false; try { Debug.Assert(eventArgs.Buffer != null, "'BufferList' is not supported for read operations."); if (eventArgs.Count == 0 || _inputStream.Closed) { eventArgs.FinishOperationSuccess(0, true); return false; } uint dataRead = 0; int offset = eventArgs.Offset; int remainingCount = eventArgs.Count; if (_inputStream.BufferedDataChunksAvailable) { dataRead = _inputStream.GetChunks(eventArgs.Buffer, eventArgs.Offset, eventArgs.Count); if (_inputStream.BufferedDataChunksAvailable && dataRead == eventArgs.Count) { eventArgs.FinishOperationSuccess(eventArgs.Count, true); return false; } } Debug.Assert(!_inputStream.BufferedDataChunksAvailable, "'m_InputStream.BufferedDataChunksAvailable' MUST BE 'FALSE' at this point."); Debug.Assert(dataRead <= eventArgs.Count, "'dataRead' MUST NOT be bigger than 'eventArgs.Count'."); if (dataRead != 0) { offset += (int)dataRead; remainingCount -= (int)dataRead; //the http.sys team recommends that we limit the size to 128kb if (remainingCount > HttpRequestStream.MaxReadSize) { remainingCount = HttpRequestStream.MaxReadSize; } eventArgs.SetBuffer(eventArgs.Buffer, offset, remainingCount); } else if (remainingCount > HttpRequestStream.MaxReadSize) { remainingCount = HttpRequestStream.MaxReadSize; eventArgs.SetBuffer(eventArgs.Buffer, offset, remainingCount); } uint flags = 0; uint bytesReturned = 0; statusCode = Interop.HttpApi.HttpReceiveRequestEntityBody( _inputStream.InternalHttpContext.RequestQueueHandle, _inputStream.InternalHttpContext.RequestId, flags, (byte*)_webSocket.InternalBuffer.ToIntPtr(eventArgs.Offset), (uint)eventArgs.Count, out bytesReturned, eventArgs.NativeOverlapped); if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF) { throw new HttpListenerException((int)statusCode); } else if (statusCode == Interop.HttpApi.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously. No IO completion port callback is used because // it was disabled in SwitchToOpaqueMode() eventArgs.FinishOperationSuccess((int)bytesReturned, true); completedAsynchronously = false; } else { completedAsynchronously = true; } } catch (Exception e) { _readEventArgs.FinishOperationFailure(e, true); _outputStream.SetClosedFlag(); _outputStream.InternalHttpContext.Abort(); throw; } finally { if (NetEventSource.IsEnabled) { NetEventSource.Exit(this, completedAsynchronously); } } return completedAsynchronously; }
// return value indicates sync vs async completion // false: sync completion // true: async completion or with error private unsafe bool WriteAsyncFast(HttpListenerAsyncEventArgs eventArgs) { Interop.HttpApi.HTTP_FLAGS flags = Interop.HttpApi.HTTP_FLAGS.NONE; eventArgs.StartOperationCommon(this, _outputStream.InternalHttpContext.RequestQueueBoundHandle); eventArgs.StartOperationSend(); uint statusCode; bool completedAsynchronouslyOrWithError; try { if (_outputStream.Closed || (eventArgs.Buffer != null && eventArgs.Count == 0)) { eventArgs.FinishOperationSuccess(eventArgs.Count, true); return(false); } if (eventArgs.ShouldCloseOutput) { flags |= Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT; } else { flags |= Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; // When using HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA HTTP.SYS will copy the payload to // kernel memory (Non-Paged Pool). Http.Sys will buffer up to // Math.Min(16 MB, current TCP window size) flags |= Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA; } uint bytesSent; statusCode = Interop.HttpApi.HttpSendResponseEntityBody( _outputStream.InternalHttpContext.RequestQueueHandle, _outputStream.InternalHttpContext.RequestId, (uint)flags, eventArgs.EntityChunkCount, (Interop.HttpApi.HTTP_DATA_CHUNK *)eventArgs.EntityChunks, &bytesSent, SafeLocalAllocHandle.Zero, 0, eventArgs.NativeOverlapped, null); if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING) { throw new HttpListenerException((int)statusCode); } else if (statusCode == Interop.HttpApi.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. eventArgs.FinishOperationSuccess((int)bytesSent, true); completedAsynchronouslyOrWithError = false; } else { completedAsynchronouslyOrWithError = true; } } catch (Exception e) { _writeEventArgs !.FinishOperationFailure(e, true); _outputStream.SetClosedFlag(); _outputStream.InternalHttpContext.Abort(); completedAsynchronouslyOrWithError = true; } return(completedAsynchronouslyOrWithError); }
// return value indicates sync vs async completion // false: sync completion // true: async completion private unsafe bool WriteAsyncFast(HttpListenerAsyncEventArgs eventArgs) { if (NetEventSource.IsEnabled) { NetEventSource.Enter(this); } Interop.HttpApi.HTTP_FLAGS flags = Interop.HttpApi.HTTP_FLAGS.NONE; eventArgs.StartOperationCommon(this, _outputStream.InternalHttpContext.RequestQueueBoundHandle); eventArgs.StartOperationSend(); uint statusCode; bool completedAsynchronously = false; try { if (_outputStream.Closed || (eventArgs.Buffer != null && eventArgs.Count == 0)) { eventArgs.FinishOperationSuccess(eventArgs.Count, true); return false; } if (eventArgs.ShouldCloseOutput) { flags |= Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT; } else { flags |= Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; // When using HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA HTTP.SYS will copy the payload to // kernel memory (Non-Paged Pool). Http.Sys will buffer up to // Math.Min(16 MB, current TCP window size) flags |= Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA; } uint bytesSent; statusCode = Interop.HttpApi.HttpSendResponseEntityBody( _outputStream.InternalHttpContext.RequestQueueHandle, _outputStream.InternalHttpContext.RequestId, (uint)flags, eventArgs.EntityChunkCount, (Interop.HttpApi.HTTP_DATA_CHUNK*)eventArgs.EntityChunks, &bytesSent, SafeLocalAllocHandle.Zero, 0, eventArgs.NativeOverlapped, null); if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING) { throw new HttpListenerException((int)statusCode); } else if (statusCode == Interop.HttpApi.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously - callback won't be called to signal completion. eventArgs.FinishOperationSuccess((int)bytesSent, true); completedAsynchronously = false; } else { completedAsynchronously = true; } } catch (Exception e) { _writeEventArgs.FinishOperationFailure(e, true); _outputStream.SetClosedFlag(); _outputStream.InternalHttpContext.Abort(); throw; } finally { if (NetEventSource.IsEnabled) { NetEventSource.Exit(this, completedAsynchronously); } } return completedAsynchronously; }
private void OnCompleted(HttpListenerAsyncEventArgs e) { m_Completed?.Invoke(e._currentStream, e); }
// return value indicates [....] vs async completion // false: [....] completion // true: async completion private unsafe bool ReadAsyncFast(HttpListenerAsyncEventArgs eventArgs) { if (WebSocketBase.LoggingEnabled) { Logging.Enter(Logging.WebSockets, this, Methods.ReadAsyncFast, string.Empty); } eventArgs.StartOperationCommon(this); eventArgs.StartOperationReceive(); uint statusCode = 0; bool completedAsynchronously = false; try { Contract.Assert(eventArgs.Buffer != null, "'BufferList' is not supported for read operations."); if (eventArgs.Count == 0 || m_InputStream.Closed) { eventArgs.FinishOperationSuccess(0, true); return(false); } uint dataRead = 0; int offset = eventArgs.Offset; int remainingCount = eventArgs.Count; if (m_InputStream.BufferedDataChunksAvailable) { dataRead = m_InputStream.GetChunks(eventArgs.Buffer, eventArgs.Offset, eventArgs.Count); if (m_InputStream.BufferedDataChunksAvailable && dataRead == eventArgs.Count) { eventArgs.FinishOperationSuccess(eventArgs.Count, true); return(false); } } Contract.Assert(!m_InputStream.BufferedDataChunksAvailable, "'m_InputStream.BufferedDataChunksAvailable' MUST BE 'FALSE' at this point."); Contract.Assert(dataRead <= eventArgs.Count, "'dataRead' MUST NOT be bigger than 'eventArgs.Count'."); if (dataRead != 0) { offset += (int)dataRead; remainingCount -= (int)dataRead; //the http.sys team recommends that we limit the size to 128kb if (remainingCount > HttpRequestStream.MaxReadSize) { remainingCount = HttpRequestStream.MaxReadSize; } eventArgs.SetBuffer(eventArgs.Buffer, offset, remainingCount); } else if (remainingCount > HttpRequestStream.MaxReadSize) { remainingCount = HttpRequestStream.MaxReadSize; eventArgs.SetBuffer(eventArgs.Buffer, offset, remainingCount); } m_InputStream.InternalHttpContext.EnsureBoundHandle(); uint flags = 0; uint bytesReturned = 0; statusCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveRequestEntityBody2( m_InputStream.InternalHttpContext.RequestQueueHandle, m_InputStream.InternalHttpContext.RequestId, flags, (byte *)m_WebSocket.InternalBuffer.ToIntPtr(eventArgs.Offset), (uint)eventArgs.Count, out bytesReturned, eventArgs.NativeOverlapped); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF) { throw new HttpListenerException((int)statusCode); } else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess) { // IO operation completed synchronously. No IO completion port callback is used because // it was disabled in SwitchToOpaqueMode() eventArgs.FinishOperationSuccess((int)bytesReturned, true); completedAsynchronously = false; } else { completedAsynchronously = true; } } catch (Exception e) { m_ReadEventArgs.FinishOperationFailure(e, true); m_OutputStream.SetClosedFlag(); m_OutputStream.InternalHttpContext.Abort(); throw; } finally { if (WebSocketBase.LoggingEnabled) { Logging.Exit(Logging.WebSockets, this, Methods.ReadAsyncFast, completedAsynchronously); } } return(completedAsynchronously); }