System.Net.HttpResponseStreamAsyncResult.IOCompleted C# (CSharp) Method

IOCompleted() private static method

private static IOCompleted ( HttpResponseStreamAsyncResult asyncResult, uint errorCode, uint numBytes ) : void
asyncResult HttpResponseStreamAsyncResult
errorCode uint
numBytes uint
return void
        private static void IOCompleted(HttpResponseStreamAsyncResult asyncResult, uint errorCode, uint numBytes)
        {
            if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"errorCode:0x {errorCode.ToString("x8")} numBytes: {numBytes}");
            object result = null;
            try
            {
                if (errorCode != Interop.HttpApi.ERROR_SUCCESS && errorCode != Interop.HttpApi.ERROR_HANDLE_EOF)
                {
                    asyncResult.ErrorCode = (int)errorCode;
                    result = new HttpListenerException((int)errorCode);
                }
                else
                {
                    // if we sent headers and body together, numBytes will be the total, but we need to only account for the data
                    if (asyncResult._dataChunks == null)
                    {
                        result = (uint)0;
                        if (NetEventSource.IsEnabled) { NetEventSource.DumpBuffer(null, IntPtr.Zero, 0); }
                    }
                    else
                    {
                        result = asyncResult._dataChunks.Length == 1 ? asyncResult._dataChunks[0].BufferLength : 0;
                        if (NetEventSource.IsEnabled) { for (int i = 0; i < asyncResult._dataChunks.Length; i++) { NetEventSource.DumpBuffer(null, (IntPtr)asyncResult._dataChunks[0].pBuffer, (int)asyncResult._dataChunks[0].BufferLength); } }
                    }
                }
                if (NetEventSource.IsEnabled) NetEventSource.Info(null, "Calling Complete()");
            }
            catch (Exception e)
            {
                result = e;
            }
            asyncResult.InvokeCallback(result);
        }

Same methods

HttpResponseStreamAsyncResult::IOCompleted ( uint errorCode, uint numBytes ) : void

Usage Example

/*
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;
        }
All Usage Examples Of System.Net.HttpResponseStreamAsyncResult::IOCompleted