Ejemplo n.º 1
0
 private UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS ComputeLeftToWrite(bool endOfRequest = false)
 {
     UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE;
     if (!_requestContext.Response.ComputedHeaders)
     {
         flags = _requestContext.Response.ComputeHeaders(endOfRequest, _buffer.TotalBytes);
     }
     if (_leftToWrite == long.MinValue)
     {
         UnsafeNclNativeMethods.HttpApi.HTTP_VERB method = _requestContext.Request.GetKnownMethod();
         if (method == UnsafeNclNativeMethods.HttpApi.HTTP_VERB.HttpVerbHEAD)
         {
             _leftToWrite = 0;
         }
         else if (_requestContext.Response.BoundaryType == BoundaryType.ContentLength)
         {
             _leftToWrite = _requestContext.Response.ExpectedBodyLength;
         }
         else
         {
             _leftToWrite = -1; // unlimited
         }
     }
     return(flags);
 }
Ejemplo n.º 2
0
 internal UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS ComputeLeftToWrite()
 {
     UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS nONE = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE;
     if (!this.m_HttpContext.Response.ComputedHeaders)
     {
         nONE = this.m_HttpContext.Response.ComputeHeaders();
     }
     if (this.m_LeftToWrite == -9223372036854775808L)
     {
         UnsafeNclNativeMethods.HttpApi.HTTP_VERB knownMethod = this.m_HttpContext.GetKnownMethod();
         this.m_LeftToWrite = (knownMethod != UnsafeNclNativeMethods.HttpApi.HTTP_VERB.HttpVerbHEAD) ? this.m_HttpContext.Response.ContentLength64 : 0L;
     }
     return(nONE);
 }
Ejemplo n.º 3
0
 internal UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS ComputeLeftToWrite()
 {
     GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::ComputeLeftToWrite() on entry m_LeftToWrite:" + m_LeftToWrite);
     UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE;
     if (!m_HttpContext.Response.ComputedHeaders)
     {
         flags = m_HttpContext.Response.ComputeHeaders();
     }
     if (m_LeftToWrite == long.MinValue)
     {
         UnsafeNclNativeMethods.HttpApi.HTTP_VERB method = m_HttpContext.GetKnownMethod();
         m_LeftToWrite = method != UnsafeNclNativeMethods.HttpApi.HTTP_VERB.HttpVerbHEAD ? m_HttpContext.Response.ContentLength64 : 0;
         GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::ComputeLeftToWrite() computed m_LeftToWrite:" + m_LeftToWrite);
     }
     return(flags);
 }
Ejemplo n.º 4
0
        protected override void Dispose(bool disposing)
        {
            if (Logging.On)
            {
                Logging.Enter(Logging.HttpListener, this, "Close", "");
            }

            try {
                if (disposing)
                {
                    GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Close() m_Closed:" + m_Closed);
                    if (m_Closed)
                    {
                        if (Logging.On)
                        {
                            Logging.Exit(Logging.HttpListener, this, "Close", "");
                        }
                        return;
                    }
                    m_Closed = true;
                    UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite();
                    if (m_LeftToWrite > 0 && !m_InOpaqueMode)
                    {
                        throw new InvalidOperationException(SR.GetString(SR.net_io_notenoughbyteswritten));
                    }
                    bool sentHeaders = m_HttpContext.Response.SentHeaders;
                    if (sentHeaders && m_LeftToWrite == 0)
                    {
                        if (Logging.On)
                        {
                            Logging.Exit(Logging.HttpListener, this, "Close", "");
                        }
                        return;
                    }

                    uint statusCode = 0;
                    if ((m_HttpContext.Response.BoundaryType == BoundaryType.Chunked || m_HttpContext.Response.BoundaryType == BoundaryType.None) && (String.Compare(m_HttpContext.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase) != 0))
                    {
                        if (m_HttpContext.Response.BoundaryType == BoundaryType.None)
                        {
                            flags |= UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT;
                        }
                        fixed(void *pBuffer = NclConstants.ChunkTerminator)
                        {
                            UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK *pDataChunk = null;
                            if (m_HttpContext.Response.BoundaryType == BoundaryType.Chunked)
                            {
                                UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK dataChunk = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK();
                                dataChunk.DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
                                dataChunk.pBuffer       = (byte *)pBuffer;
                                dataChunk.BufferLength  = (uint)NclConstants.ChunkTerminator.Length;
                                pDataChunk = &dataChunk;
                            }
                            if (!sentHeaders)
                            {
                                statusCode = m_HttpContext.Response.SendHeaders(pDataChunk, null, flags, false);
                            }
                            else
                            {
                                GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Close() calling UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody");

                                statusCode =
                                    UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody(
                                        m_HttpContext.RequestQueueHandle,
                                        m_HttpContext.RequestId,
                                        (uint)flags,
                                        pDataChunk != null ? (ushort)1 : (ushort)0,
                                        pDataChunk,
                                        null,
                                        SafeLocalFree.Zero,
                                        0,
                                        null,
                                        null);

                                GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Close() call to UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody returned:" + statusCode);
                                if (m_HttpContext.Listener.IgnoreWriteExceptions)
                                {
                                    GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Close() suppressing error");
                                    statusCode = UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS;
                                }
                            }
                        }
                    }
                    else
                    {
                        if (!sentHeaders)
                        {
                            statusCode = m_HttpContext.Response.SendHeaders(null, null, flags, false);
                        }
                    }
                    if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF)
                    {
                        Exception exception = new HttpListenerException((int)statusCode);
                        if (Logging.On)
                        {
                            Logging.Exception(Logging.HttpListener, this, "Close", exception);
                        }
                        m_HttpContext.Abort();
                        throw exception;
                    }
                    m_LeftToWrite = 0;
                }
            }
            finally {
                base.Dispose(disposing);
            }
            if (Logging.On)
            {
                Logging.Exit(Logging.HttpListener, this, "Dispose", "");
            }
        }
Ejemplo n.º 5
0
        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
        {
            GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::BeginWrite() buffer.Length:" + buffer.Length + " size:" + size + " offset:" + offset);
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }
            if (offset < 0 || offset > buffer.Length)
            {
                throw new ArgumentOutOfRangeException("offset");
            }
            if (size < 0 || size > buffer.Length - offset)
            {
                throw new ArgumentOutOfRangeException("size");
            }
            UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite();
            if (m_Closed || (size == 0 && m_LeftToWrite != 0))
            {
                if (Logging.On)
                {
                    Logging.Exit(Logging.HttpListener, this, "BeginWrite", "");
                }
                HttpResponseStreamAsyncResult result = new HttpResponseStreamAsyncResult(this, state, callback);
                result.InvokeCallback((uint)0);
                return(result);
            }
            if (m_LeftToWrite >= 0 && size > m_LeftToWrite)
            {
                throw new ProtocolViolationException(SR.GetString(SR.net_entitytoobig));
            }

            uint statusCode;
            uint bytesSent = 0;

            flags |= m_LeftToWrite == size ? UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE : UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA;
            bool sentHeaders = m_HttpContext.Response.SentHeaders;
            HttpResponseStreamAsyncResult asyncResult = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, m_HttpContext.Response.BoundaryType == BoundaryType.Chunked, sentHeaders);

            // Update m_LeftToWrite now so we can queue up additional BeginWrite's without waiting for EndWrite.
            UpdateAfterWrite((uint)((m_HttpContext.Response.BoundaryType == BoundaryType.Chunked) ? 0 : size));

            try {
                if (!sentHeaders)
                {
                    statusCode = m_HttpContext.Response.SendHeaders(null, asyncResult, flags, false);
                }
                else
                {
                    GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::BeginWrite() calling UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody");

                    m_HttpContext.EnsureBoundHandle();
                    statusCode =
                        UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody(
                            m_HttpContext.RequestQueueHandle,
                            m_HttpContext.RequestId,
                            (uint)flags,
                            asyncResult.dataChunkCount,
                            asyncResult.pDataChunks,
                            &bytesSent,
                            SafeLocalFree.Zero,
                            0,
                            asyncResult.m_pOverlapped,
                            null);

                    GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::BeginWrite() call to UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody returned:" + statusCode);
                }
            }
            catch (Exception e) {
                if (Logging.On)
                {
                    Logging.Exception(Logging.HttpListener, this, "BeginWrite", e);
                }
                asyncResult.InternalCleanup();
                m_Closed = true;
                m_HttpContext.Abort();
                throw;
            }

            if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
            {
                asyncResult.InternalCleanup();
                if (m_HttpContext.Listener.IgnoreWriteExceptions && sentHeaders)
                {
                    GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::BeginWrite() suppressing error");
                }
                else
                {
                    Exception exception = new HttpListenerException((int)statusCode);
                    if (Logging.On)
                    {
                        Logging.Exception(Logging.HttpListener, this, "BeginWrite", exception);
                    }
                    m_Closed = true;
                    m_HttpContext.Abort();
                    throw exception;
                }
            }

            if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess)
            {
                // IO operation completed synchronously - callback won't be called to signal completion.
                asyncResult.IOCompleted(statusCode, bytesSent);
            }

            // Last write, cache it for special cancelation handling.
            if ((flags & UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0)
            {
                m_LastWrite = asyncResult;
            }

            if (Logging.On)
            {
                Logging.Exit(Logging.HttpListener, this, "BeginWrite", "");
            }
            return(asyncResult);
        }
Ejemplo n.º 6
0
        public override void Write(byte[] buffer, int offset, int size)
        {
            if (Logging.On)
            {
                Logging.Enter(Logging.HttpListener, this, "Write", "");
            }
            GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Write() buffer.Length:" + buffer.Length + " size:" + size + " offset:" + offset);
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }
            if (offset < 0 || offset > buffer.Length)
            {
                throw new ArgumentOutOfRangeException("offset");
            }
            if (size < 0 || size > buffer.Length - offset)
            {
                throw new ArgumentOutOfRangeException("size");
            }
            UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite();
            if (m_Closed || (size == 0 && m_LeftToWrite != 0))
            {
                if (Logging.On)
                {
                    Logging.Exit(Logging.HttpListener, this, "Write", "");
                }
                return;
            }
            if (m_LeftToWrite >= 0 && size > m_LeftToWrite)
            {
                throw new ProtocolViolationException(SR.GetString(SR.net_entitytoobig));
            }

            uint          statusCode;
            uint          dataToWrite     = (uint)size;
            SafeLocalFree bufferAsIntPtr  = null;
            IntPtr        pBufferAsIntPtr = IntPtr.Zero;
            bool          sentHeaders     = m_HttpContext.Response.SentHeaders;

            try {
                if (size == 0)
                {
                    statusCode = m_HttpContext.Response.SendHeaders(null, null, flags, false);
                }
                else
                {
                    fixed(byte *pDataBuffer = buffer)
                    {
                        byte *pBuffer = pDataBuffer;

                        if (m_HttpContext.Response.BoundaryType == BoundaryType.Chunked)
                        {
                            //


                            string chunkHeader = size.ToString("x", CultureInfo.InvariantCulture);
                            dataToWrite     = dataToWrite + (uint)(chunkHeader.Length + 4);
                            bufferAsIntPtr  = SafeLocalFree.LocalAlloc((int)dataToWrite);
                            pBufferAsIntPtr = bufferAsIntPtr.DangerousGetHandle();
                            for (int i = 0; i < chunkHeader.Length; i++)
                            {
                                Marshal.WriteByte(pBufferAsIntPtr, i, (byte)chunkHeader[i]);
                            }
                            Marshal.WriteInt16(pBufferAsIntPtr, chunkHeader.Length, 0x0A0D);
                            Marshal.Copy(buffer, offset, IntPtrHelper.Add(pBufferAsIntPtr, chunkHeader.Length + 2), size);
                            Marshal.WriteInt16(pBufferAsIntPtr, (int)(dataToWrite - 2), 0x0A0D);
                            pBuffer = (byte *)pBufferAsIntPtr;
                            offset  = 0;
                        }
                        UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK dataChunk = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK();
                        dataChunk.DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
                        dataChunk.pBuffer       = (byte *)(pBuffer + offset);
                        dataChunk.BufferLength  = dataToWrite;

                        flags |= m_LeftToWrite == size ? UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE : UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA;
                        if (!sentHeaders)
                        {
                            statusCode = m_HttpContext.Response.SendHeaders(&dataChunk, null, flags, false);
                        }
                        else
                        {
                            GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Write() calling UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody");

                            statusCode =
                                UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody(
                                    m_HttpContext.RequestQueueHandle,
                                    m_HttpContext.RequestId,
                                    (uint)flags,
                                    1,
                                    &dataChunk,
                                    null,
                                    SafeLocalFree.Zero,
                                    0,
                                    null,
                                    null);

                            GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Write() call to UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody returned:" + statusCode);
                            if (m_HttpContext.Listener.IgnoreWriteExceptions)
                            {
                                GlobalLog.Print("HttpResponseStream#" + ValidationHelper.HashString(this) + "::Write() suppressing error");
                                statusCode = UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS;
                            }
                        }
                    }
                }
            }
            finally {
                if (bufferAsIntPtr != null)
                {
                    // free unmanaged buffer
                    bufferAsIntPtr.Close();
                }
            }

            if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_HANDLE_EOF)
            {
                Exception exception = new HttpListenerException((int)statusCode);
                if (Logging.On)
                {
                    Logging.Exception(Logging.HttpListener, this, "Write", exception);
                }
                m_Closed = true;
                m_HttpContext.Abort();
                throw exception;
            }
            UpdateAfterWrite(dataToWrite);
            if (Logging.On)
            {
                Logging.Dump(Logging.HttpListener, this, "Write", buffer, offset, (int)dataToWrite);
            }
            if (Logging.On)
            {
                Logging.Exit(Logging.HttpListener, this, "Write", "");
            }
        }
Ejemplo n.º 7
0
        internal UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS ComputeHeaders()
        {
            UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE;
            GlobalLog.Print("HttpListenerResponse#" + ValidationHelper.HashString(this) + "::ComputeHeaders()");
            GlobalLog.Assert(!ComputedHeaders, "HttpListenerResponse#{0}::ComputeHeaders()|ComputedHeaders is true.", ValidationHelper.HashString(this));
            m_ResponseState = ResponseState.ComputedHeaders;

            /*
             * // here we would check for BoundaryType.Raw, in this case we wouldn't need to do anything
             * if (m_BoundaryType==BoundaryType.Raw) {
             *  return flags;
             * }
             */

            ComputeCoreHeaders();

            GlobalLog.Print("HttpListenerResponse#" + ValidationHelper.HashString(this) + "::ComputeHeaders() flags:" + flags + " m_BoundaryType:" + m_BoundaryType + " m_ContentLength:" + m_ContentLength + " m_KeepAlive:" + m_KeepAlive);
            if (m_BoundaryType == BoundaryType.None)
            {
                if (HttpListenerRequest.ProtocolVersion.Minor == 0)
                {
                    //
                    m_KeepAlive = false;
                }
                else
                {
                    m_BoundaryType = BoundaryType.Chunked;
                }
                if (CanSendResponseBody(m_HttpContext.Response.StatusCode))
                {
                    m_ContentLength = -1;
                }
                else
                {
                    ContentLength64 = 0;
                }
            }

            GlobalLog.Print("HttpListenerResponse#" + ValidationHelper.HashString(this) + "::ComputeHeaders() flags:" + flags + " m_BoundaryType:" + m_BoundaryType + " m_ContentLength:" + m_ContentLength + " m_KeepAlive:" + m_KeepAlive);
            if (m_BoundaryType == BoundaryType.ContentLength)
            {
                Headers.SetInternal(HttpResponseHeader.ContentLength, m_ContentLength.ToString("D", NumberFormatInfo.InvariantInfo));
                if (m_ContentLength == 0)
                {
                    flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE;
                }
            }
            else if (m_BoundaryType == BoundaryType.Chunked)
            {
                Headers.SetInternal(HttpResponseHeader.TransferEncoding, HttpWebRequest.ChunkedHeader);
            }
            else if (m_BoundaryType == BoundaryType.None)
            {
                flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE; // seems like HTTP_SEND_RESPONSE_FLAG_MORE_DATA but this hangs the app;
            }
            else
            {
                m_KeepAlive = false;
            }
            if (!m_KeepAlive)
            {
                Headers.Add(HttpResponseHeader.Connection, "close");
                if (flags == UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE)
                {
                    flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT;
                }
            }
            else
            {
                if (HttpListenerRequest.ProtocolVersion.Minor == 0)
                {
                    Headers.SetInternal(HttpResponseHeader.KeepAlive, "true");
                }
            }
            GlobalLog.Print("HttpListenerResponse#" + ValidationHelper.HashString(this) + "::ComputeHeaders() flags:" + flags + " m_BoundaryType:" + m_BoundaryType + " m_ContentLength:" + m_ContentLength + " m_KeepAlive:" + m_KeepAlive);
            return(flags);
        }
Ejemplo n.º 8
0
/*
 * 12.3
 * HttpSendHttpResponse() and HttpSendResponseEntityBody() Flag Values.
 * The following flags can be used on calls to HttpSendHttpResponse() and HttpSendResponseEntityBody() API calls:
 *
 #define HTTP_SEND_RESPONSE_FLAG_DISCONNECT          0x00000001
 #define HTTP_SEND_RESPONSE_FLAG_MORE_DATA           0x00000002
 #define HTTP_SEND_RESPONSE_FLAG_RAW_HEADER          0x00000004
 #define HTTP_SEND_RESPONSE_FLAG_VALID               0x00000007
 *
 * HTTP_SEND_RESPONSE_FLAG_DISCONNECT:
 *  specifies that the network connection should be disconnected immediately after
 *  sending the response, overriding the HTTP protocol's persistent connection features.
 * HTTP_SEND_RESPONSE_FLAG_MORE_DATA:
 *  specifies that additional entity body data will be sent by the caller. Thus,
 *  the last call HttpSendResponseEntityBody for a RequestId, will have this flag reset.
 * HTTP_SEND_RESPONSE_RAW_HEADER:
 *  specifies that a caller of HttpSendResponseEntityBody() is intentionally omitting
 *  a call to HttpSendHttpResponse() in order to bypass normal header processing. The
 *  actual HTTP header will be generated by the application and sent as entity body.
 *  This flag should be passed on the first call to HttpSendResponseEntityBody, and
 *  not after. Thus, flag is not applicable to HttpSendHttpResponse.
 */
        internal unsafe uint SendHeaders(UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK *pDataChunk,
                                         HttpResponseStreamAsyncResult asyncResult,
                                         UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags,
                                         bool isWebSocketHandshake)
        {
            GlobalLog.Print("HttpListenerResponse#" + ValidationHelper.HashString(this) + "::SendHeaders() pDataChunk:" + ValidationHelper.ToString((IntPtr)pDataChunk) + " asyncResult:" + ValidationHelper.ToString(asyncResult));
            GlobalLog.Assert(!SentHeaders, "HttpListenerResponse#{0}::SendHeaders()|SentHeaders is true.", ValidationHelper.HashString(this));

            if (StatusCode == (int)HttpStatusCode.Unauthorized)   // User set 401
            // Using the configured Auth schemes, populate the auth challenge headers. This is for scenarios where
            // Anonymous access is allowed for some resources, but the server later determines that authorization
            // is required for this request.
            {
                HttpListenerContext.SetAuthenticationHeaders();
            }

            // Log headers
            if (Logging.On)
            {
                StringBuilder sb = new StringBuilder("HttpListenerResponse Headers:\n");
                for (int i = 0; i < Headers.Count; i++)
                {
                    sb.Append("\t");
                    sb.Append(Headers.GetKey(i));
                    sb.Append(" : ");
                    sb.Append(Headers.Get(i));
                    sb.Append("\n");
                }
                Logging.PrintInfo(Logging.HttpListener, this, ".ctor", sb.ToString());
            }
            m_ResponseState = ResponseState.SentHeaders;

            /*
             * if (m_BoundaryType==BoundaryType.Raw) {
             *  use HTTP_SEND_RESPONSE_FLAG_RAW_HEADER;
             * }
             */
            uint            statusCode;
            uint            bytesSent;
            List <GCHandle> pinnedHeaders = SerializeHeaders(ref m_NativeResponse.Headers, isWebSocketHandshake);

            try {
                if (pDataChunk != null)
                {
                    m_NativeResponse.EntityChunkCount = 1;
                    m_NativeResponse.pEntityChunks    = pDataChunk;
                }
                else if (asyncResult != null && asyncResult.pDataChunks != null)
                {
                    m_NativeResponse.EntityChunkCount = asyncResult.dataChunkCount;
                    m_NativeResponse.pEntityChunks    = asyncResult.pDataChunks;
                }
                else
                {
                    m_NativeResponse.EntityChunkCount = 0;
                    m_NativeResponse.pEntityChunks    = null;
                }
                GlobalLog.Print("HttpListenerResponse#" + ValidationHelper.HashString(this) + "::SendHeaders() calling UnsafeNclNativeMethods.HttpApi.HttpSendHttpResponse flags:" + flags);
                if (StatusDescription.Length > 0)
                {
                    byte[] statusDescriptionBytes = new byte[WebHeaderCollection.HeaderEncoding.GetByteCount(StatusDescription)];
                    fixed(byte *pStatusDescription = statusDescriptionBytes)
                    {
                        m_NativeResponse.ReasonLength = (ushort)statusDescriptionBytes.Length;
                        WebHeaderCollection.HeaderEncoding.GetBytes(StatusDescription, 0, statusDescriptionBytes.Length, statusDescriptionBytes, 0);
                        m_NativeResponse.pReason = (sbyte *)pStatusDescription;
                        fixed(UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE *pResponse = &m_NativeResponse)
                        {
                            if (asyncResult != null)
                            {
                                HttpListenerContext.EnsureBoundHandle();
                            }
                            statusCode =
                                UnsafeNclNativeMethods.HttpApi.HttpSendHttpResponse(
                                    HttpListenerContext.RequestQueueHandle,
                                    HttpListenerRequest.RequestId,
                                    (uint)flags,
                                    pResponse,
                                    null,
                                    &bytesSent,
                                    SafeLocalFree.Zero,
                                    0,
                                    asyncResult == null ? null : asyncResult.m_pOverlapped,
                                    null);

                            if (asyncResult != null &&
                                statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
                                HttpListener.SkipIOCPCallbackOnSuccess)
                            {
                                asyncResult.IOCompleted(statusCode, bytesSent);
                                // IO operation completed synchronously - callback won't be called to signal completion.
                            }
                        }
                    }
                }
                else
                {
                    fixed(UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE *pResponse = &m_NativeResponse)
                    {
                        if (asyncResult != null)
                        {
                            HttpListenerContext.EnsureBoundHandle();
                        }
                        statusCode =
                            UnsafeNclNativeMethods.HttpApi.HttpSendHttpResponse(
                                HttpListenerContext.RequestQueueHandle,
                                HttpListenerRequest.RequestId,
                                (uint)flags,
                                pResponse,
                                null,
                                &bytesSent,
                                SafeLocalFree.Zero,
                                0,
                                asyncResult == null ? null : asyncResult.m_pOverlapped,
                                null);

                        if (asyncResult != null &&
                            statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
                            HttpListener.SkipIOCPCallbackOnSuccess)
                        {
                            asyncResult.IOCompleted(statusCode, bytesSent);
                            // IO operation completed synchronously - callback won't be called to signal completion.
                        }
                    }
                }
                GlobalLog.Print("HttpListenerResponse#" + ValidationHelper.HashString(this) + "::SendHeaders() call to UnsafeNclNativeMethods.HttpApi.HttpSendHttpResponse returned:" + statusCode);
            }
            finally {
                FreePinnedHeaders(pinnedHeaders);
            }
            return(statusCode);
        }
        // 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);
        }
Ejemplo n.º 10
0
        internal unsafe uint SendHeaders(UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK *pDataChunk, HttpResponseStreamAsyncResult asyncResult, UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags)
        {
            uint num2;

            if (Logging.On)
            {
                StringBuilder builder = new StringBuilder("HttpListenerResponse Headers:\n");
                for (int i = 0; i < this.Headers.Count; i++)
                {
                    builder.Append("\t");
                    builder.Append(this.Headers.GetKey(i));
                    builder.Append(" : ");
                    builder.Append(this.Headers.Get(i));
                    builder.Append("\n");
                }
                Logging.PrintInfo(Logging.HttpListener, this, ".ctor", builder.ToString());
            }
            this.m_ResponseState = ResponseState.SentHeaders;
            List <GCHandle> pinnedHeaders = this.SerializeHeaders(ref this.m_NativeResponse.Headers);

            try
            {
                if (pDataChunk != null)
                {
                    this.m_NativeResponse.EntityChunkCount = 1;
                    this.m_NativeResponse.pEntityChunks    = pDataChunk;
                }
                else if ((asyncResult != null) && (asyncResult.pDataChunks != null))
                {
                    this.m_NativeResponse.EntityChunkCount = asyncResult.dataChunkCount;
                    this.m_NativeResponse.pEntityChunks    = asyncResult.pDataChunks;
                }
                else
                {
                    this.m_NativeResponse.EntityChunkCount = 0;
                    this.m_NativeResponse.pEntityChunks    = null;
                }
                if (this.StatusDescription.Length > 0)
                {
                    ref byte pinned numRef;
                    byte[]          bytes = new byte[WebHeaderCollection.HeaderEncoding.GetByteCount(this.StatusDescription)];
                    try
                    {
                        byte[] buffer2;
                        if (((buffer2 = bytes) == null) || (buffer2.Length == 0))
                        {
                            numRef = null;
                        }
                        else
                        {
                            numRef = buffer2;
                        }
                        this.m_NativeResponse.ReasonLength = (ushort)bytes.Length;
                        WebHeaderCollection.HeaderEncoding.GetBytes(this.StatusDescription, 0, bytes.Length, bytes, 0);
                        this.m_NativeResponse.pReason = (sbyte *)numRef;
                        fixed(UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE *http_responseRef = &this.m_NativeResponse)
                        {
                            if (asyncResult != null)
                            {
                                this.HttpListenerContext.EnsureBoundHandle();
                            }
                            num2 = UnsafeNclNativeMethods.HttpApi.HttpSendHttpResponse(this.HttpListenerContext.RequestQueueHandle, this.HttpListenerRequest.RequestId, (uint)flags, http_responseRef, null, null, SafeLocalFree.Zero, 0, (asyncResult == null) ? null : asyncResult.m_pOverlapped, null);
                        }
                        return(num2);
                    }
                    finally
                    {
                        numRef = null;
                    }
                }
                fixed(UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE *http_responseRef2 = &this.m_NativeResponse)
                {
                    if (asyncResult != null)
                    {
                        this.HttpListenerContext.EnsureBoundHandle();
                    }
                    num2 = UnsafeNclNativeMethods.HttpApi.HttpSendHttpResponse(this.HttpListenerContext.RequestQueueHandle, this.HttpListenerRequest.RequestId, (uint)flags, http_responseRef2, null, null, SafeLocalFree.Zero, 0, (asyncResult == null) ? null : asyncResult.m_pOverlapped, null);
                }
            }
Ejemplo n.º 11
0
 internal UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS ComputeHeaders()
 {
     UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS nONE = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE;
     this.m_ResponseState = ResponseState.ComputedHeaders;
     if ((this.HttpListenerContext.MutualAuthentication != null) && (this.HttpListenerContext.MutualAuthentication.Length > 0))
     {
         this.Headers.SetInternal(HttpResponseHeader.WwwAuthenticate, this.HttpListenerContext.MutualAuthentication);
     }
     this.ComputeCookies();
     if (this.m_BoundaryType == System.Net.BoundaryType.None)
     {
         if (this.HttpListenerRequest.ProtocolVersion.Minor == 0)
         {
             this.m_KeepAlive = false;
         }
         else
         {
             this.m_BoundaryType = System.Net.BoundaryType.Chunked;
         }
         if (this.CanSendResponseBody(this.m_HttpContext.Response.StatusCode))
         {
             this.m_ContentLength = -1L;
         }
         else
         {
             this.ContentLength64 = 0L;
         }
     }
     if (this.m_BoundaryType == System.Net.BoundaryType.ContentLength)
     {
         this.Headers.SetInternal(HttpResponseHeader.ContentLength, this.m_ContentLength.ToString("D", NumberFormatInfo.InvariantInfo));
         if (this.m_ContentLength == 0L)
         {
             nONE = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE;
         }
     }
     else if (this.m_BoundaryType == System.Net.BoundaryType.Chunked)
     {
         this.Headers.SetInternal(HttpResponseHeader.TransferEncoding, "chunked");
     }
     else if (this.m_BoundaryType == System.Net.BoundaryType.None)
     {
         nONE = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE;
     }
     else
     {
         this.m_KeepAlive = false;
     }
     if (!this.m_KeepAlive)
     {
         this.Headers.Add(HttpResponseHeader.Connection, "close");
         if (nONE == UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE)
         {
             nONE = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_INITIALIZE_SERVER;
         }
         return(nONE);
     }
     if (this.HttpListenerRequest.ProtocolVersion.Minor == 0)
     {
         this.Headers.SetInternal(HttpResponseHeader.KeepAlive, "true");
     }
     return(nONE);
 }
Ejemplo n.º 12
0
        public override unsafe void Write(byte[] buffer, int offset, int size)
        {
            if (Logging.On)
            {
                Logging.Enter(Logging.HttpListener, this, "Write", "");
            }
            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }
            if ((offset < 0) || (offset > buffer.Length))
            {
                throw new ArgumentOutOfRangeException("offset");
            }
            if ((size < 0) || (size > (buffer.Length - offset)))
            {
                throw new ArgumentOutOfRangeException("size");
            }
            UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = this.ComputeLeftToWrite();
            if (this.m_Closed || ((size == 0) && (this.m_LeftToWrite != 0L)))
            {
                if (Logging.On)
                {
                    Logging.Exit(Logging.HttpListener, this, "Write", "");
                }
            }
            else
            {
                uint num;
                if ((this.m_LeftToWrite >= 0L) && (size > this.m_LeftToWrite))
                {
                    throw new ProtocolViolationException(SR.GetString("net_entitytoobig"));
                }
                uint          dataWritten = (uint)size;
                SafeLocalFree free        = null;
                IntPtr        zero        = IntPtr.Zero;
                bool          sentHeaders = this.m_HttpContext.Response.SentHeaders;
                try
                {
                    if (size == 0)
                    {
                        num = this.m_HttpContext.Response.SendHeaders(null, null, flags);
                    }
                    else
                    {
                        try
                        {
                            byte[] buffer2;
                            if (((buffer2 = buffer) == null) || (buffer2.Length == 0))
                            {
                                numRef = null;
                                goto Label_0109;
                            }
                            fixed(byte *numRef = buffer2)
                            {
                                byte *numPtr;

Label_0109:
                                numPtr = numRef;
                                if (this.m_HttpContext.Response.BoundaryType == BoundaryType.Chunked)
                                {
                                    string str = size.ToString("x", CultureInfo.InvariantCulture);
                                    dataWritten += (uint)(str.Length + 4);
                                    free         = SafeLocalFree.LocalAlloc((int)dataWritten);
                                    zero         = free.DangerousGetHandle();
                                    for (int i = 0; i < str.Length; i++)
                                    {
                                        Marshal.WriteByte(zero, i, (byte)str[i]);
                                    }
                                    Marshal.WriteInt16(zero, str.Length, (short)0xa0d);
                                    Marshal.Copy(buffer, offset, IntPtrHelper.Add(zero, str.Length + 2), size);
                                    Marshal.WriteInt16(zero, ((int)dataWritten) - 2, (short)0xa0d);
                                    numPtr = (byte *)zero;
                                    offset = 0;
                                }
                                UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK pDataChunk = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK {
                                    DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory,
                                    pBuffer       = numPtr + offset,
                                    BufferLength  = dataWritten
                                };
                                flags |= (this.m_LeftToWrite == size) ? UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE : UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA;
                                if (!sentHeaders)
                                {
                                    num = this.m_HttpContext.Response.SendHeaders(&pDataChunk, null, flags);
                                }
                                else
                                {
                                    num = UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody(this.m_HttpContext.RequestQueueHandle, this.m_HttpContext.RequestId, (uint)flags, 1, &pDataChunk, null, SafeLocalFree.Zero, 0, null, null);
                                    if (this.m_HttpContext.Listener.IgnoreWriteExceptions)
                                    {
                                        num = 0;
                                    }
                                }
                            }
                        }
                        finally
                        {
                            numRef = null;
                        }
                    }
                }
                finally
                {
                    if (free != null)
                    {
                        free.Close();
                    }
                }
                switch (num)
                {
                case 0:
                case 0x26:
                    this.UpdateAfterWrite(dataWritten);
                    if (Logging.On)
                    {
                        Logging.Dump(Logging.HttpListener, this, "Write", buffer, offset, (int)dataWritten);
                    }
                    if (Logging.On)
                    {
                        Logging.Exit(Logging.HttpListener, this, "Write", "");
                    }
                    return;
                }
                Exception e = new HttpListenerException((int)num);
                if (Logging.On)
                {
                    Logging.Exception(Logging.HttpListener, this, "Write", e);
                }
                this.m_HttpContext.Abort();
                throw e;
            }
        }
Ejemplo n.º 13
0
        public override unsafe IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
        {
            uint num;

            if (buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }
            if ((offset < 0) || (offset > buffer.Length))
            {
                throw new ArgumentOutOfRangeException("offset");
            }
            if ((size < 0) || (size > (buffer.Length - offset)))
            {
                throw new ArgumentOutOfRangeException("size");
            }
            UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = this.ComputeLeftToWrite();
            if (this.m_Closed || ((size == 0) && (this.m_LeftToWrite != 0L)))
            {
                if (Logging.On)
                {
                    Logging.Exit(Logging.HttpListener, this, "BeginWrite", "");
                }
                HttpResponseStreamAsyncResult result = new HttpResponseStreamAsyncResult(this, state, callback);
                result.InvokeCallback(0);
                return(result);
            }
            if ((this.m_LeftToWrite >= 0L) && (size > this.m_LeftToWrite))
            {
                throw new ProtocolViolationException(SR.GetString("net_entitytoobig"));
            }
            flags |= (this.m_LeftToWrite == size) ? UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE : UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA;
            bool sentHeaders = this.m_HttpContext.Response.SentHeaders;
            HttpResponseStreamAsyncResult asyncResult = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, this.m_HttpContext.Response.BoundaryType == BoundaryType.Chunked, sentHeaders);

            try
            {
                if (!sentHeaders)
                {
                    num = this.m_HttpContext.Response.SendHeaders(null, asyncResult, flags);
                }
                else
                {
                    this.m_HttpContext.EnsureBoundHandle();
                    num = UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody(this.m_HttpContext.RequestQueueHandle, this.m_HttpContext.RequestId, (uint)flags, asyncResult.dataChunkCount, asyncResult.pDataChunks, null, SafeLocalFree.Zero, 0, asyncResult.m_pOverlapped, null);
                }
            }
            catch (Exception exception)
            {
                if (Logging.On)
                {
                    Logging.Exception(Logging.HttpListener, this, "BeginWrite", exception);
                }
                asyncResult.InternalCleanup();
                this.m_HttpContext.Abort();
                throw;
            }
            switch (num)
            {
            case 0:
            case 0x3e5:
                break;

            default:
                asyncResult.InternalCleanup();
                if (!this.m_HttpContext.Listener.IgnoreWriteExceptions || !sentHeaders)
                {
                    Exception e = new HttpListenerException((int)num);
                    if (Logging.On)
                    {
                        Logging.Exception(Logging.HttpListener, this, "BeginWrite", e);
                    }
                    this.m_HttpContext.Abort();
                    throw e;
                }
                break;
            }
            if (Logging.On)
            {
                Logging.Exit(Logging.HttpListener, this, "BeginWrite", "");
            }
            return(asyncResult);
        }
Ejemplo n.º 14
0
        protected override unsafe void Dispose(bool disposing)
        {
            if (Logging.On)
            {
                Logging.Enter(Logging.HttpListener, this, "Close", "");
            }
            try
            {
                if (!disposing)
                {
                    goto Label_023F;
                }
                if (this.m_Closed)
                {
                    if (Logging.On)
                    {
                        Logging.Exit(Logging.HttpListener, this, "Close", "");
                    }
                    return;
                }
                this.m_Closed = true;
                UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = this.ComputeLeftToWrite();
                if (this.m_LeftToWrite > 0L)
                {
                    throw new InvalidOperationException(SR.GetString("net_io_notenoughbyteswritten"));
                }
                bool sentHeaders = this.m_HttpContext.Response.SentHeaders;
                if (sentHeaders && (this.m_LeftToWrite == 0L))
                {
                    if (Logging.On)
                    {
                        Logging.Exit(Logging.HttpListener, this, "Close", "");
                    }
                    return;
                }
                uint num = 0;
                if (((this.m_HttpContext.Response.BoundaryType == BoundaryType.Chunked) || (this.m_HttpContext.Response.BoundaryType == BoundaryType.None)) && (string.Compare(this.m_HttpContext.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase) != 0))
                {
                    if (this.m_HttpContext.Response.BoundaryType == BoundaryType.None)
                    {
                        flags |= UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_INITIALIZE_SERVER;
                    }
                    try
                    {
                        byte[] buffer;
                        if (((buffer = NclConstants.ChunkTerminator) == null) || (buffer.Length == 0))
                        {
                            ptrRef = null;
                            goto Label_0132;
                        }
                        fixed(IntPtr *ptrRef = buffer)
                        {
                            UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK *http_data_chunkPtr;
Label_0132:
                            http_data_chunkPtr = null;
                            if (this.m_HttpContext.Response.BoundaryType == BoundaryType.Chunked)
                            {
                                UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK http_data_chunk = new UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK {
                                    DataChunkType = UnsafeNclNativeMethods.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory,
                                    pBuffer       = (byte *)ptrRef,
                                    BufferLength  = (uint)NclConstants.ChunkTerminator.Length
                                };
                                http_data_chunkPtr = &http_data_chunk;
                            }
                            if (!sentHeaders)
                            {
                                num = this.m_HttpContext.Response.SendHeaders(http_data_chunkPtr, null, flags);
                            }
                            else
                            {
                                num = UnsafeNclNativeMethods.HttpApi.HttpSendResponseEntityBody(this.m_HttpContext.RequestQueueHandle, this.m_HttpContext.RequestId, (uint)flags, (http_data_chunkPtr != null) ? ((ushort)1) : ((ushort)0), http_data_chunkPtr, null, SafeLocalFree.Zero, 0, null, null);
                                if (this.m_HttpContext.Listener.IgnoreWriteExceptions)
                                {
                                    num = 0;
                                }
                            }
                            goto Label_01F6;
                        }
                    }
                    finally
                    {
                        ptrRef = null;
                    }
                }
                if (!sentHeaders)
                {
                    num = this.m_HttpContext.Response.SendHeaders(null, null, flags);
                }
Label_01F6:
                switch (num)
                {
                case 0:
                case 0x26:
                    break;

                default:
                {
                    Exception e = new HttpListenerException((int)num);
                    if (Logging.On)
                    {
                        Logging.Exception(Logging.HttpListener, this, "Close", e);
                    }
                    this.m_HttpContext.Abort();
                    throw e;
                }
                }
                this.m_LeftToWrite = 0L;
            }
            finally
            {
                base.Dispose(disposing);
            }
Label_023F:
            if (Logging.On)
            {
                Logging.Exit(Logging.HttpListener, this, "Dispose", "");
            }
        }
Ejemplo n.º 15
0
        internal unsafe Task SendFileAsyncCore(string fileName, long offset, long?count, CancellationToken cancellationToken)
        {
            _requestContext.Response.Start();
            UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite();
            if (count == 0 && _leftToWrite != 0)
            {
                return(Helpers.CompletedTask());
            }
            if (_leftToWrite >= 0 && count > _leftToWrite)
            {
                throw new InvalidOperationException(Resources.Exception_TooMuchWritten);
            }
            // TODO: Verbose log

            if (cancellationToken.IsCancellationRequested)
            {
                return(Helpers.CanceledTask <int>());
            }

            var cancellationRegistration = default(CancellationTokenRegistration);

            if (cancellationToken.CanBeCanceled)
            {
                cancellationRegistration = cancellationToken.Register(RequestContext.AbortDelegate, _requestContext);
            }

            uint statusCode;
            uint bytesSent      = 0;
            bool startedSending = _requestContext.Response.HasStartedSending;
            var  chunked        = _requestContext.Response.BoundaryType == BoundaryType.Chunked;
            ResponseStreamAsyncResult asyncResult = new ResponseStreamAsyncResult(this, fileName, offset, count, chunked, cancellationRegistration);

            long bytesWritten;

            if (chunked)
            {
                bytesWritten = 0;
            }
            else if (count.HasValue)
            {
                bytesWritten = count.Value;
            }
            else
            {
                bytesWritten = asyncResult.FileLength - offset;
            }
            // Update _leftToWrite now so we can queue up additional calls to SendFileAsync.
            flags |= _leftToWrite == bytesWritten ? HttpApi.HTTP_FLAGS.NONE : HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA;
            UpdateWritenCount((uint)bytesWritten);

            try
            {
                if (!startedSending)
                {
                    statusCode = _requestContext.Response.SendHeaders(null, asyncResult, flags, false);
                    bytesSent  = asyncResult.BytesSent;
                }
                else
                {
                    // TODO: If opaque then include the buffer data flag.
                    statusCode = HttpApi.HttpSendResponseEntityBody(
                        _requestContext.RequestQueueHandle,
                        _requestContext.RequestId,
                        (uint)flags,
                        asyncResult.DataChunkCount,
                        asyncResult.DataChunks,
                        &bytesSent,
                        SafeLocalFree.Zero,
                        0,
                        asyncResult.NativeOverlapped,
                        IntPtr.Zero);
                }
            }
            catch (Exception e)
            {
                LogHelper.LogException(_requestContext.Logger, "SendFileAsync", e);
                asyncResult.Dispose();
                Abort();
                throw;
            }

            if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
            {
                asyncResult.Dispose();
                if (_requestContext.Server.IgnoreWriteExceptions && startedSending)
                {
                    asyncResult.Complete();
                }
                else
                {
                    Exception exception = new IOException(string.Empty, new WebListenerException((int)statusCode));
                    LogHelper.LogException(_requestContext.Logger, "SendFileAsync", exception);
                    Abort();
                    throw exception;
                }
            }

            if (statusCode == ErrorCodes.ERROR_SUCCESS && WebListener.SkipIOCPCallbackOnSuccess)
            {
                // IO operation completed synchronously - callback won't be called to signal completion.
                asyncResult.IOCompleted(statusCode, bytesSent);
            }

            // Last write, cache it for special cancellation handling.
            if ((flags & HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0)
            {
                _lastWrite = asyncResult;
            }

            return(asyncResult.Task);
        }