Ejemplo n.º 1
0
 void IHttpResetFeature.Reset(int errorCode)
 {
     _requestContext.SetResetCode(errorCode);
     _requestContext.Abort();
 }
 void IHttpRequestLifetimeFeature.Abort() => _requestContext.Abort();
Ejemplo n.º 3
0
        // We never expect endOfRequest and data at the same time
        private unsafe void FlushInternal(bool endOfRequest, ArraySegment <byte> data = new ArraySegment <byte>())
        {
            Debug.Assert(!(endOfRequest && data.Count > 0), "Data is not supported at the end of the request.");

            if (_skipWrites)
            {
                return;
            }

            var started = _requestContext.Response.HasStarted;

            if (data.Count == 0 && started && !endOfRequest)
            {
                // No data to send and we've already sent the headers
                return;
            }

            // Make sure all validation is performed before this computes the headers
            var flags = ComputeLeftToWrite(data.Count, endOfRequest);

            if (endOfRequest && _leftToWrite > 0)
            {
                if (!RequestContext.DisconnectToken.IsCancellationRequested)
                {
                    // This is logged rather than thrown because it is too late for an exception to be visible in user code.
                    Logger.LogError(LoggerEventIds.FewerBytesThanExpected, "ResponseStream::Dispose; Fewer bytes were written than were specified in the Content-Length.");
                }
                _requestContext.Abort();
                return;
            }

            uint statusCode = 0;

            HttpApiTypes.HTTP_DATA_CHUNK[] dataChunks;
            var pinnedBuffers = PinDataBuffers(endOfRequest, data, out dataChunks);

            try
            {
                if (!started)
                {
                    statusCode = _requestContext.Response.SendHeaders(dataChunks, null, flags, false);
                }
                else
                {
                    fixed(HttpApiTypes.HTTP_DATA_CHUNK *pDataChunks = dataChunks)
                    {
                        statusCode = HttpApi.HttpSendResponseEntityBody(
                            RequestQueueHandle,
                            RequestId,
                            (uint)flags,
                            (ushort)dataChunks.Length,
                            pDataChunks,
                            null,
                            IntPtr.Zero,
                            0,
                            SafeNativeOverlapped.Zero,
                            IntPtr.Zero);
                    }
                }
            }
            finally
            {
                FreeDataBuffers(pinnedBuffers);
            }

            if (statusCode != ErrorCodes.ERROR_SUCCESS && statusCode != ErrorCodes.ERROR_HANDLE_EOF
                // Don't throw for disconnects, we were already finished with the response.
                && (!endOfRequest || (statusCode != ErrorCodes.ERROR_CONNECTION_INVALID && statusCode != ErrorCodes.ERROR_INVALID_PARAMETER)))
            {
                if (ThrowWriteExceptions)
                {
                    var exception = new IOException(string.Empty, new HttpSysException((int)statusCode));
                    Logger.LogError(LoggerEventIds.WriteError, exception, "Flush");
                    Abort();
                    throw exception;
                }
                else
                {
                    // Abort the request but do not close the stream, let future writes complete silently
                    Logger.LogDebug(LoggerEventIds.WriteErrorIgnored, $"Flush; Ignored write exception: {statusCode}");
                    Abort(dispose: false);
                }
            }
        }