// 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 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 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; }
// 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); }