private static void OnWebSocketWriteComplete(WinHttpWebSocketState state)
        {
            Debug.Assert(state != null, "OnWebSocketWriteComplete: state is null");

            state.PendingWriteOperation = false;
            state.TcsSend.TrySetResult(true);
        }
        private static void OnWebSocketShutdownComplete(WinHttpWebSocketState state)
        {
            Debug.Assert(state != null, "OnWebSocketShutdownComplete: state is null");

            state.UpdateState(WebSocketState.CloseSent);
            state.TcsCloseOutput.TrySetResult(true);
        }
        private static void OnRequestError(
            WinHttpWebSocketState state,
            Interop.WinHttp.WINHTTP_ASYNC_RESULT asyncResult)
        {
            Debug.Assert(state != null, "OnRequestError: state is null");

            var innerException = WinHttpException.CreateExceptionUsingError((int)asyncResult.dwError);

            switch ((uint)asyncResult.dwResult.ToInt32())
            {
            case Interop.WinHttp.API_SEND_REQUEST:
            case Interop.WinHttp.API_RECEIVE_RESPONSE:
            {
                var exception = new WebSocketException(SR.net_webstatus_ConnectFailure, innerException);
                state.UpdateState(WebSocketState.Closed);
                state.TcsUpgrade.TrySetException(exception);
            }
            break;

            default:
            {
                Debug.Fail(
                    "OnRequestError: Result (" + asyncResult.dwResult + ") is not expected.",
                    "Error code: " + asyncResult.dwError + " (" + innerException.Message + ")");
            }
            break;
            }
        }
        private static void OnWebSocketError(
            WinHttpWebSocketState state,
            Interop.WinHttp.WINHTTP_WEB_SOCKET_ASYNC_RESULT asyncResult)
        {
            Debug.Assert(state != null, "OnWebSocketError: state is null");

            var innerException = WinHttpException.CreateExceptionUsingError((int)(asyncResult.AsyncResult.dwError));

            if (asyncResult.AsyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_OPERATION_CANCELLED)
            {
                var exception = new WebSocketException(
                    WebSocketError.InvalidState,
                    SR.Format(
                        SR.net_WebSockets_InvalidState_ClosedOrAborted,
                        "System.Net.WebSockets.InternalClientWebSocket",
                        "Aborted"),
                    innerException);

                state.UpdateState(WebSocketState.Aborted);

                if (state.TcsReceive != null)
                {
                    state.TcsReceive.TrySetException(exception);
                }

                if (state.TcsSend != null)
                {
                    state.TcsSend.TrySetException(exception);
                }

                return;
            }

            switch (asyncResult.Operation)
            {
            case Interop.WinHttp.WINHTTP_WEB_SOCKET_OPERATION.WINHTTP_WEB_SOCKET_SEND_OPERATION:
                state.PendingWriteOperation = false;
                state.TcsSend.TrySetException(innerException);
                break;

            case Interop.WinHttp.WINHTTP_WEB_SOCKET_OPERATION.WINHTTP_WEB_SOCKET_RECEIVE_OPERATION:
                state.PendingReadOperation = false;
                state.TcsReceive.TrySetException(innerException);
                break;

            case Interop.WinHttp.WINHTTP_WEB_SOCKET_OPERATION.WINHTTP_WEB_SOCKET_CLOSE_OPERATION:
                state.TcsClose.TrySetException(innerException);
                break;

            case Interop.WinHttp.WINHTTP_WEB_SOCKET_OPERATION.WINHTTP_WEB_SOCKET_SHUTDOWN_OPERATION:
                state.TcsCloseOutput.TrySetException(innerException);
                break;

            default:
                Debug.Fail(
                    "OnWebSocketError: Operation (" + asyncResult.Operation + ") is not expected.",
                    "Error code: " + asyncResult.AsyncResult.dwError + " (" + innerException.Message + ")");
                break;
            }
        }
        private static void OnWebSocketCloseComplete(WinHttpWebSocketState state)
        {
            Debug.Assert(state != null, "OnWebSocketCloseComplete: state is null");

            state.UpdateState(WebSocketState.Closed);
            state.TcsClose.TrySetResult(true);
        }
        private static void OnWebSocketHandleClosing(WinHttpWebSocketState state)
        {
            Debug.Assert(state != null, "OnWebSocketHandleClosing: state is null");
            Debug.Assert(state.WebSocketHandle != null, "OnWebSocketHandleClosing: WebSocketHandle is null");
            Debug.Assert(!state.WebSocketHandle.IsInvalid, "OnWebSocketHandleClosing: WebSocketHandle is invalid");

            state.WebSocketHandle.DetachCallback();
            state.WebSocketHandle = null;
        }
        private static void WebSocketCallback(
            IntPtr handle,
            WinHttpWebSocketState state,
            uint internetStatus,
            IntPtr statusInformation,
            uint statusInformationLength)
        {
            switch (internetStatus)
            {
            case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE:
                OnWebSocketWriteComplete(state);
                return;

            case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_READ_COMPLETE:
                Debug.Assert(
                    statusInformationLength == Marshal.SizeOf <Interop.WinHttp.WINHTTP_WEB_SOCKET_STATUS>(),
                    "WebSocketCallback: statusInformationLength must be sizeof(WINHTTP_WEB_SOCKET_STATUS).");

                var info = Marshal.PtrToStructure <Interop.WinHttp.WINHTTP_WEB_SOCKET_STATUS>(statusInformation);
                OnWebSocketReadComplete(state, info);
                return;

            case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_CLOSE_COMPLETE:
                OnWebSocketCloseComplete(state);
                return;

            case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_SHUTDOWN_COMPLETE:
                OnWebSocketShutdownComplete(state);
                return;

            case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING:
                OnWebSocketHandleClosing(state);
                return;

            case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
                Debug.Assert(
                    statusInformationLength == Marshal.SizeOf <Interop.WinHttp.WINHTTP_WEB_SOCKET_ASYNC_RESULT>(),
                    "WebSocketCallback: statusInformationLength must be sizeof(WINHTTP_WEB_SOCKET_ASYNC_RESULT).");

                var asyncResult = Marshal.PtrToStructure <Interop.WinHttp.WINHTTP_WEB_SOCKET_ASYNC_RESULT>(statusInformation);
                OnWebSocketError(state, asyncResult);
                return;

            case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_SECURE_FAILURE:
                Debug.Assert(
                    statusInformationLength == Marshal.SizeOf <uint>(),
                    "WebSocketCallback: statusInformationLength must be sizeof(uint).");

                // statusInformation contains a flag: WINHTTP_CALLBACK_STATUS_FLAG_*
                uint flags = (uint)statusInformation;
                OnRequestSecureFailure(state, flags);
                return;
            }
        }
        private static void OnWebSocketSecureFailure(WinHttpWebSocketState state, uint flags)
        {
            Debug.Assert(state != null, "OnWebSocketSecureFailure: state is null");

            var innerException = WinHttpException.CreateExceptionUsingError((int)Interop.WinHttp.ERROR_WINHTTP_SECURE_FAILURE);
            var exception      = new WebSocketException(WebSocketError.ConnectionClosedPrematurely, innerException);

            // TODO (Issue 2509): handle SSL related exceptions.
            state.UpdateState(WebSocketState.Aborted);

            // TODO (Issue 2509): Create exception from WINHTTP_CALLBACK_STATUS_SECURE_FAILURE flags.
            state.TcsUpgrade.TrySetException(exception);
        }
        private static void OnWebSocketHandleClosing(WinHttpWebSocketState state)
        {
            Debug.Assert(state != null, "OnWebSocketHandleClosing: state is null");
            Debug.Assert(state.WebSocketHandle != null, "OnWebSocketHandleClosing: WebSocketHandle is null");
            Debug.Assert(!state.WebSocketHandle.IsInvalid, "OnWebSocketHandleClosing: WebSocketHandle is invalid");

            state.WebSocketHandle.DetachCallback();
            state.WebSocketHandle = null;

            // Unpin the state object if there are no more open handles that are wired to the callback.
            if (state.DecrementHandlesOpenWithCallback() == 0)
            {
                state.Unpin();
            }
        }
示例#10
0
        private static void RequestCallback(
            IntPtr handle,
            WinHttpWebSocketState state,
            uint internetStatus,
            IntPtr statusInformation,
            uint statusInformationLength)
        {
            switch (internetStatus)
            {
                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
                    OnRequestSendRequestComplete(state);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
                    OnRequestHeadersAvailable(state);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING:
                    OnRequestHandleClosing(state);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
                    Debug.Assert(
                        statusInformationLength == Marshal.SizeOf<Interop.WinHttp.WINHTTP_ASYNC_RESULT>(),
                        "RequestCallback: statusInformationLength=" + statusInformationLength +
                        " must be sizeof(WINHTTP_ASYNC_RESULT)=" + Marshal.SizeOf<Interop.WinHttp.WINHTTP_ASYNC_RESULT>());

                    var asyncResult = Marshal.PtrToStructure<Interop.WinHttp.WINHTTP_ASYNC_RESULT>(statusInformation);
                    OnRequestError(state, asyncResult);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_SECURE_FAILURE:
                    Debug.Assert(
                        statusInformationLength == Marshal.SizeOf<uint>(),
                        "RequestCallback: statusInformationLength must be sizeof(uint).");

                    // statusInformation contains a flag: WINHTTP_CALLBACK_STATUS_FLAG_*
                    uint flags = 0;
                    unchecked
                    {
                        flags = (uint)Marshal.ReadInt32(statusInformation);
                    }
                    OnRequestSecureFailure(state, flags);

                    return;
            }
        }
        private static void RequestCallback(
            IntPtr handle,
            WinHttpWebSocketState state,
            uint internetStatus,
            IntPtr statusInformation,
            uint statusInformationLength)
        {
            switch (internetStatus)
            {
            case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
                OnRequestSendRequestComplete(state);
                return;

            case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
                OnRequestHeadersAvailable(state);
                return;

            case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING:
                OnRequestHandleClosing(state);
                return;

            case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
                Debug.Assert(
                    statusInformationLength == Marshal.SizeOf <Interop.WinHttp.WINHTTP_ASYNC_RESULT>(),
                    "RequestCallback: statusInformationLength=" + statusInformationLength +
                    " must be sizeof(WINHTTP_ASYNC_RESULT)=" + Marshal.SizeOf <Interop.WinHttp.WINHTTP_ASYNC_RESULT>());

                var asyncResult = Marshal.PtrToStructure <Interop.WinHttp.WINHTTP_ASYNC_RESULT>(statusInformation);
                OnRequestError(state, asyncResult);
                return;

            case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_SECURE_FAILURE:
                Debug.Assert(
                    statusInformationLength == Marshal.SizeOf <uint>(),
                    "RequestCallback: statusInformationLength must be sizeof(uint).");

                // statusInformation contains a flag: WINHTTP_CALLBACK_STATUS_FLAG_*
                uint flags = 0;
                unchecked
                {
                    flags = (uint)Marshal.ReadInt32(statusInformation);
                }
                OnRequestSecureFailure(state, flags);

                return;
            }
        }
        private static void OnRequestSecureFailure(WinHttpWebSocketState state, uint flags)
        {
            Debug.Assert(state != null, "OnRequestSecureFailure: state is null");

            var innerException = WinHttpException.CreateExceptionUsingError((int)Interop.WinHttp.ERROR_WINHTTP_SECURE_FAILURE);

            var exception = new WebSocketException(
                WebSocketError.Success,
                SR.net_webstatus_ConnectFailure,
                innerException);

            // TODO: handle SSL related exceptions.
            state.UpdateState(WebSocketState.Closed);

            // TODO: Create exception from WINHTTP_CALLBACK_STATUS_SECURE_FAILURE flags.
            state.TcsUpgrade.TrySetException(exception);
        }
        private static void OnWebSocketReadComplete(
            WinHttpWebSocketState state,
            Interop.WinHttp.WINHTTP_WEB_SOCKET_STATUS info)
        {
            Debug.Assert(state != null, "OnWebSocketReadComplete: state is null");

            if (info.eBufferType == Interop.WinHttp.WINHTTP_WEB_SOCKET_BUFFER_TYPE.WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE)
            {
                state.UpdateState(WebSocketState.CloseReceived);
            }

            state.BufferType           = info.eBufferType;
            state.BytesTransferred     = info.dwBytesTransferred;
            state.PendingReadOperation = false;

            state.TcsReceive.TrySetResult(true);
        }
        public static void WinHttpCallback(
            IntPtr handle,
            IntPtr context,
            uint internetStatus,
            IntPtr statusInformation,
            uint statusInformationLength)
        {
            if (Environment.HasShutdownStarted)
            {
                return;
            }

            if (context == IntPtr.Zero)
            {
                Debug.Assert(internetStatus != Interop.WinHttp.WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING);
                return;
            }

            try
            {
                WinHttpWebSocketState state = WinHttpWebSocketState.FromIntPtr(context);
                Debug.Assert(state != null, "WinHttpWebSocketCallback: state should not be null");

                if ((state.RequestHandle != null) &&
                    (state.RequestHandle.DangerousGetHandle() == handle))
                {
                    RequestCallback(handle, state, internetStatus, statusInformation, statusInformationLength);
                    return;
                }

                if ((state.WebSocketHandle != null) &&
                    (state.WebSocketHandle.DangerousGetHandle() == handle))
                {
                    WebSocketCallback(handle, state, internetStatus, statusInformation, statusInformationLength);
                    return;
                }
            }
            catch (Exception ex)
            {
                Debug.Fail("Unhandled exception in WinHTTP callback: " + ex);
            }
        }
示例#15
0
        private static void OnWebSocketError(
            WinHttpWebSocketState state,
            Interop.WinHttp.WINHTTP_WEB_SOCKET_ASYNC_RESULT asyncResult)
        {
            Debug.Assert(state != null, "OnWebSocketError: state is null");

            var innerException = WinHttpException.CreateExceptionUsingError((int)(asyncResult.AsyncResult.dwError));

            if (asyncResult.AsyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_OPERATION_CANCELLED)
            {
                var exception = new WebSocketException(
                    WebSocketError.InvalidState,
                    SR.Format(
                        SR.net_WebSockets_InvalidState_ClosedOrAborted,
                        "System.Net.WebSockets.InternalClientWebSocket",
                        "Aborted"),
                    innerException);

                state.UpdateState(WebSocketState.Aborted);

                if (state.TcsReceive != null)
                {
                    state.TcsReceive.TrySetException(exception);
                }

                if (state.TcsSend != null)
                {
                    state.TcsSend.TrySetException(exception);
                }

                return;
            }

            switch (asyncResult.Operation)
            {
                case Interop.WinHttp.WINHTTP_WEB_SOCKET_OPERATION.WINHTTP_WEB_SOCKET_SEND_OPERATION:
                    state.PendingWriteOperation = false;
                    state.TcsSend.TrySetException(innerException);
                    break;

                case Interop.WinHttp.WINHTTP_WEB_SOCKET_OPERATION.WINHTTP_WEB_SOCKET_RECEIVE_OPERATION:
                    state.PendingReadOperation = false;
                    state.TcsReceive.TrySetException(innerException);
                    break;

                case Interop.WinHttp.WINHTTP_WEB_SOCKET_OPERATION.WINHTTP_WEB_SOCKET_CLOSE_OPERATION:
                    state.TcsClose.TrySetException(innerException);
                    break;

                case Interop.WinHttp.WINHTTP_WEB_SOCKET_OPERATION.WINHTTP_WEB_SOCKET_SHUTDOWN_OPERATION:
                    state.TcsCloseOutput.TrySetException(innerException);
                    break;

                default:
                    Debug.Fail(
                        "OnWebSocketError: Operation (" + asyncResult.Operation + ") is not expected.",
                        "Error code: " + asyncResult.AsyncResult.dwError + " (" + innerException.Message + ")");
                    break;
            }
        }
示例#16
0
        private static void OnWebSocketHandleClosing(WinHttpWebSocketState state)
        {
            Debug.Assert(state != null, "OnWebSocketHandleClosing: state is null");
            Debug.Assert(state.WebSocketHandle != null, "OnWebSocketHandleClosing: WebSocketHandle is null");
            Debug.Assert(!state.WebSocketHandle.IsInvalid, "OnWebSocketHandleClosing: WebSocketHandle is invalid");

            state.WebSocketHandle.DetachCallback();
            state.WebSocketHandle = null;

            // Unpin the state object if there are no more open handles that are wired to the callback.
            if (state.DecrementHandlesOpenWithCallback() == 0)
            {
                state.Unpin();
            }
        }
示例#17
0
        private static void OnWebSocketShutdownComplete(WinHttpWebSocketState state)
        {
            Debug.Assert(state != null, "OnWebSocketShutdownComplete: state is null");

            state.UpdateState(WebSocketState.CloseSent);
            state.TcsCloseOutput.TrySetResult(true);
        }
示例#18
0
        private static void OnWebSocketCloseComplete(WinHttpWebSocketState state)
        {
            Debug.Assert(state != null, "OnWebSocketCloseComplete: state is null");

            state.UpdateState(WebSocketState.Closed);
            state.TcsClose.TrySetResult(true);
        }
示例#19
0
        private static void OnWebSocketReadComplete(
            WinHttpWebSocketState state,
            Interop.WinHttp.WINHTTP_WEB_SOCKET_STATUS info)
        {
            Debug.Assert(state != null, "OnWebSocketReadComplete: state is null");

            if (info.eBufferType == Interop.WinHttp.WINHTTP_WEB_SOCKET_BUFFER_TYPE.WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE)
            {
                state.UpdateState(WebSocketState.CloseReceived);
            }

            state.BufferType = info.eBufferType;
            state.BytesTransferred = info.dwBytesTransferred;
            state.PendingReadOperation = false;

            state.TcsReceive.TrySetResult(true);
        }
示例#20
0
        private static void OnWebSocketWriteComplete(WinHttpWebSocketState state)
        {
            Debug.Assert(state != null, "OnWebSocketWriteComplete: state is null");

            state.PendingWriteOperation = false;
            state.TcsSend.TrySetResult(true);
        }
示例#21
0
        private static void OnRequestSecureFailure(WinHttpWebSocketState state, uint flags)
        {
            Debug.Assert(state != null, "OnRequestSecureFailure: state is null");

            var innerException = WinHttpException.CreateExceptionUsingError((int)Interop.WinHttp.ERROR_WINHTTP_SECURE_FAILURE);

            var exception = new WebSocketException(
                WebSocketError.Success,
                SR.net_webstatus_ConnectFailure,
                innerException);

            // TODO: handle SSL related exceptions.
            state.UpdateState(WebSocketState.Closed);

            // TODO: Create exception from WINHTTP_CALLBACK_STATUS_SECURE_FAILURE flags.
            state.TcsUpgrade.TrySetException(exception);
        }
示例#22
0
        private static void OnRequestError(
            WinHttpWebSocketState state,
            Interop.WinHttp.WINHTTP_ASYNC_RESULT asyncResult)
        {
            Debug.Assert(state != null, "OnRequestError: state is null");

            var innerException = WinHttpException.CreateExceptionUsingError((int)asyncResult.dwError);

            switch ((uint)asyncResult.dwResult.ToInt32())
            {
                case Interop.WinHttp.API_SEND_REQUEST:
                case Interop.WinHttp.API_RECEIVE_RESPONSE:
                    {
                        var exception = new WebSocketException(SR.net_webstatus_ConnectFailure, innerException);
                        state.UpdateState(WebSocketState.Closed);
                        state.TcsUpgrade.TrySetException(exception);
                    }
                    break;

                default:
                    {
                        Debug.Fail(
                            "OnRequestError: Result (" + asyncResult.dwResult + ") is not expected.",
                            "Error code: " + asyncResult.dwError + " (" + innerException.Message + ")");
                    }
                    break;
            }
        }
示例#23
0
 private static void OnRequestHeadersAvailable(WinHttpWebSocketState state)
 {
     Debug.Assert(state != null, "OnRequestHeadersAvailable: state is null");
     Debug.Assert(state.TcsUpgrade != null, "OnRequestHeadersAvailable: task completion source is null");
     state.TcsUpgrade.TrySetResult(true);
 }
 private static void OnRequestHeadersAvailable(WinHttpWebSocketState state)
 {
     Debug.Assert(state != null, "OnRequestHeadersAvailable: state is null");
     Debug.Assert(state.TcsUpgrade != null, "OnRequestHeadersAvailable: task completion source is null");
     state.TcsUpgrade.TrySetResult(true);
 }
示例#25
0
        private static void OnWebSocketSecureFailure(WinHttpWebSocketState state, uint flags)
        {
            Debug.Assert(state != null, "OnWebSocketSecureFailure: state is null");

            var innerException = WinHttpException.CreateExceptionUsingError((int)Interop.WinHttp.ERROR_WINHTTP_SECURE_FAILURE);
            var exception = new WebSocketException(WebSocketError.ConnectionClosedPrematurely, innerException);

            // TODO (Issue 2509): handle SSL related exceptions.
            state.UpdateState(WebSocketState.Aborted);

            // TODO (Issue 2509): Create exception from WINHTTP_CALLBACK_STATUS_SECURE_FAILURE flags.
            state.TcsUpgrade.TrySetException(exception);
        }
示例#26
0
        private static void OnWebSocketHandleClosing(WinHttpWebSocketState state)
        {
            Debug.Assert(state != null, "OnWebSocketHandleClosing: state is null");
            Debug.Assert(state.WebSocketHandle != null, "OnWebSocketHandleClosing: WebSocketHandle is null");
            Debug.Assert(!state.WebSocketHandle.IsInvalid, "OnWebSocketHandleClosing: WebSocketHandle is invalid");

            state.WebSocketHandle.DetachCallback();
            state.WebSocketHandle = null;
        }
示例#27
0
        private static void WebSocketCallback(
            IntPtr handle,
            WinHttpWebSocketState state,
            uint internetStatus,
            IntPtr statusInformation,
            uint statusInformationLength)
        {
            switch (internetStatus)
            {
                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE:
                    OnWebSocketWriteComplete(state);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_READ_COMPLETE:
                    Debug.Assert(
                        statusInformationLength == Marshal.SizeOf<Interop.WinHttp.WINHTTP_WEB_SOCKET_STATUS>(),
                        "WebSocketCallback: statusInformationLength must be sizeof(WINHTTP_WEB_SOCKET_STATUS).");

                    var info = Marshal.PtrToStructure<Interop.WinHttp.WINHTTP_WEB_SOCKET_STATUS>(statusInformation);
                    OnWebSocketReadComplete(state, info);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_CLOSE_COMPLETE:
                    OnWebSocketCloseComplete(state);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_SHUTDOWN_COMPLETE:
                    OnWebSocketShutdownComplete(state);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING:
                    OnWebSocketHandleClosing(state);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
                    Debug.Assert(
                        statusInformationLength == Marshal.SizeOf<Interop.WinHttp.WINHTTP_WEB_SOCKET_ASYNC_RESULT>(),
                        "WebSocketCallback: statusInformationLength must be sizeof(WINHTTP_WEB_SOCKET_ASYNC_RESULT).");

                    var asyncResult = Marshal.PtrToStructure<Interop.WinHttp.WINHTTP_WEB_SOCKET_ASYNC_RESULT>(statusInformation);
                    OnWebSocketError(state, asyncResult);
                    return;

                case Interop.WinHttp.WINHTTP_CALLBACK_STATUS_SECURE_FAILURE:
                    Debug.Assert(
                        statusInformationLength == Marshal.SizeOf<uint>(),
                        "WebSocketCallback: statusInformationLength must be sizeof(uint).");

                    // statusInformation contains a flag: WINHTTP_CALLBACK_STATUS_FLAG_*
                    uint flags = (uint)statusInformation;
                    OnRequestSecureFailure(state, flags);
                    return;
            }
        }