private Task <bool> InternalReceiveAsync(ArraySegment <byte> buffer)
        {
            bool receiveOperationAlreadyPending = false;

            if (_operation.PendingReadOperation == false)
            {
                lock (_operation.Lock)
                {
                    if (_operation.PendingReadOperation == false)
                    {
                        _operation.CheckValidState(s_validReceiveStates);

                        // Prevent continuations from running on the same thread as the callback to prevent re-entrance deadlocks
                        _operation.TcsReceive           = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
                        _operation.PendingReadOperation = true;

                        uint bytesRead = 0;
                        Interop.WinHttp.WINHTTP_WEB_SOCKET_BUFFER_TYPE winHttpBufferType = 0;

                        uint status = Interop.WinHttp.WinHttpWebSocketReceive(
                            _operation.WebSocketHandle,
                            Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset),
                            (uint)buffer.Count,
                            out bytesRead,                          // Unused in async mode: ignore.
                            out winHttpBufferType);                 // Unused in async mode: ignore.

                        if (Interop.WinHttp.ERROR_SUCCESS != status)
                        {
                            throw WinHttpException.CreateExceptionUsingError((int)status);
                        }
                    }
                    else
                    {
                        receiveOperationAlreadyPending = true;
                    }
                }
            }
            else
            {
                receiveOperationAlreadyPending = true;
            }

            if (receiveOperationAlreadyPending)
            {
                var exception = new InvalidOperationException(
                    SR.Format(SR.net_Websockets_AlreadyOneOutstandingOperation, "ReceiveAsync"));
                _operation.TcsReceive.TrySetException(exception);

                Abort();
            }

            return(_operation.TcsReceive.Task);
        }
Exemple #2
0
        private Task <bool> InternalReceiveAsync(Memory <byte> pinnedBuffer)
        {
            bool receiveOperationAlreadyPending = false;

            if (_operation.PendingReadOperation == false)
            {
                lock (_operation.Lock)
                {
                    if (_operation.PendingReadOperation == false)
                    {
                        _operation.CheckValidState(s_validReceiveStates);

                        // Prevent continuations from running on the same thread as the callback to prevent re-entrance deadlocks
                        _operation.TcsReceive           = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);
                        _operation.PendingReadOperation = true;

                        uint bytesRead = 0;
                        Interop.WinHttp.WINHTTP_WEB_SOCKET_BUFFER_TYPE winHttpBufferType = 0;
                        IntPtr pinnedBufferPtr;
                        unsafe
                        {
                            fixed(byte *p = &pinnedBuffer.Span.DangerousGetPinnableReference())
                            {
                                pinnedBufferPtr = (IntPtr)p;
                            }
                        }

                        uint status = Interop.WinHttp.WinHttpWebSocketReceive(
                            _operation.WebSocketHandle,
                            pinnedBufferPtr,
                            (uint)pinnedBuffer.Length,
                            out bytesRead,                          // Unused in async mode: ignore.
                            out winHttpBufferType);                 // Unused in async mode: ignore.

                        if (Interop.WinHttp.ERROR_SUCCESS != status)
                        {
                            throw WinHttpException.CreateExceptionUsingError((int)status);
                        }
                    }
                    else
                    {
                        receiveOperationAlreadyPending = true;
                    }
                }
            }
            else
            {
                receiveOperationAlreadyPending = true;
            }

            if (receiveOperationAlreadyPending)
            {
                var exception = new InvalidOperationException(
                    SR.Format(SR.net_Websockets_AlreadyOneOutstandingOperation, "ReceiveAsync"));
                _operation.TcsReceive.TrySetException(exception);

                Abort();
            }

            return(_operation.TcsReceive.Task);
        }