public override Task SendAsync(
            ArraySegment <byte> buffer,
            WebSocketMessageType messageType,
            bool endOfMessage,
            CancellationToken cancellationToken)
        {
            _operation.InterlockedCheckValidStates(s_validSendStates);

            using (CancellationTokenRegistration ctr = ThrowOrRegisterCancellation(cancellationToken))
            {
                var bufferType = WebSocketMessageTypeAdapter.GetWinHttpMessageType(messageType, endOfMessage);

                _operation.PinSendBuffer(buffer);

                bool sendOperationAlreadyPending = false;
                if (_operation.PendingWriteOperation == false)
                {
                    lock (_operation.Lock)
                    {
                        _operation.CheckValidState(s_validSendStates);

                        if (_operation.PendingWriteOperation == false)
                        {
                            _operation.PendingWriteOperation = true;
                            _operation.TcsSend = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

                            uint ret = Interop.WinHttp.WinHttpWebSocketSend(
                                _operation.WebSocketHandle,
                                bufferType,
                                buffer.Count > 0 ? Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset) : IntPtr.Zero,
                                (uint)buffer.Count);

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

                if (sendOperationAlreadyPending)
                {
                    var exception = new InvalidOperationException(
                        SR.Format(SR.net_Websockets_AlreadyOneOutstandingOperation, "SendAsync"));

                    _operation.TcsSend.TrySetException(exception);
                    Abort();
                }

                return(_operation.TcsSend.Task);
            }
        }
Beispiel #2
0
        public override async Task <WebSocketReceiveResult> ReceiveAsync(
            ArraySegment <byte> buffer,
            CancellationToken cancellationToken)
        {
            _operation.InterlockedCheckValidStates(s_validReceiveStates);

            using (ThrowOrRegisterCancellation(cancellationToken))
            {
                _operation.PinReceiveBuffer(buffer);

                await InternalReceiveAsync(buffer).ConfigureAwait(false);

                // Check for abort.
                _operation.InterlockedCheckValidStates(s_validAfterReceiveStates);

                bool endOfMessage;
                WebSocketMessageType bufferType = WebSocketMessageTypeAdapter.GetWebSocketMessageType(_operation.BufferType, out endOfMessage);
                int bytesTransferred            = checked ((int)_operation.BytesTransferred);

                WebSocketReceiveResult ret;

                if (bufferType == WebSocketMessageType.Close)
                {
                    UpdateServerCloseStatus();
                    ret = new WebSocketReceiveResult(bytesTransferred, bufferType, endOfMessage, _closeStatus, _closeStatusDescription);
                }
                else
                {
                    ret = new WebSocketReceiveResult(bytesTransferred, bufferType, endOfMessage);
                }

                return(ret);
            }
        }
Beispiel #3
0
        public override async Task <WebSocketReceiveResult> ReceiveAsync(
            ArraySegment <byte> buffer,
            CancellationToken cancellationToken)
        {
            _operation.InterlockedCheckValidStates(s_validReceiveStates);

            using (CancellationTokenRegistration ctr = ThrowOrRegisterCancellation(cancellationToken))
            {
                // TODO (Issue 2505): replace with PinnableBufferCache.
                if (!_cachedReceivePinnedBuffer.IsAllocated || _cachedReceivePinnedBuffer.Target != buffer.Array)
                {
                    if (_cachedReceivePinnedBuffer.IsAllocated)
                    {
                        _cachedReceivePinnedBuffer.Free();
                    }

                    _cachedReceivePinnedBuffer = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
                }

                await InternalReceiveAsync(buffer).ConfigureAwait(false);

                // Check for abort.
                _operation.InterlockedCheckValidStates(s_validAfterReceiveStates);

                WebSocketMessageType bufferType;
                bool endOfMessage;
                bufferType = WebSocketMessageTypeAdapter.GetWebSocketMessageType(_operation.BufferType, out endOfMessage);

                int bytesTransferred = 0;
                checked
                {
                    bytesTransferred = (int)_operation.BytesTransferred;
                }

                WebSocketReceiveResult ret;

                if (bufferType == WebSocketMessageType.Close)
                {
                    UpdateServerCloseStatus();
                    ret = new WebSocketReceiveResult(bytesTransferred, bufferType, endOfMessage, _closeStatus, _closeStatusDescription);
                }
                else
                {
                    ret = new WebSocketReceiveResult(bytesTransferred, bufferType, endOfMessage);
                }

                return(ret);
            }
        }
Beispiel #4
0
        public override async ValueTask <ValueWebSocketReceiveResult> ReceiveAsync(Memory <byte> buffer, CancellationToken cancellationToken)
        {
            _operation.InterlockedCheckValidStates(s_validReceiveStates);

            using (ThrowOrRegisterCancellation(cancellationToken))
                using (buffer.Retain(pin: true))
                {
                    await InternalReceiveAsync(buffer).ConfigureAwait(false);

                    // Check for abort.
                    _operation.InterlockedCheckValidStates(s_validAfterReceiveStates);

                    WebSocketMessageType bufferType = WebSocketMessageTypeAdapter.GetWebSocketMessageType(_operation.BufferType, out bool endOfMessage);
                    int bytesTransferred            = checked ((int)_operation.BytesTransferred);

                    if (bufferType == WebSocketMessageType.Close)
                    {
                        UpdateServerCloseStatus();
                    }

                    return(new ValueWebSocketReceiveResult(bytesTransferred, bufferType, endOfMessage));
                }
        }
Beispiel #5
0
        public override Task SendAsync(
            ArraySegment <byte> buffer,
            WebSocketMessageType messageType,
            bool endOfMessage,
            CancellationToken cancellationToken)
        {
            _operation.InterlockedCheckValidStates(s_validSendStates);

            using (CancellationTokenRegistration ctr = ThrowOrRegisterCancellation(cancellationToken))
            {
                var bufferType = WebSocketMessageTypeAdapter.GetWinHttpMessageType(messageType, endOfMessage);

                // TODO (Issue 2505): replace with PinnableBufferCache.
                if (!_cachedSendPinnedBuffer.IsAllocated || _cachedSendPinnedBuffer.Target != buffer.Array)
                {
                    if (_cachedSendPinnedBuffer.IsAllocated)
                    {
                        _cachedSendPinnedBuffer.Free();
                    }

                    _cachedSendPinnedBuffer = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
                }

                bool sendOperationAlreadyPending = false;
                if (_operation.PendingWriteOperation == false)
                {
                    lock (_operation.Lock)
                    {
                        _operation.CheckValidState(s_validSendStates);

                        if (_operation.PendingWriteOperation == false)
                        {
                            _operation.PendingWriteOperation = true;
                            _operation.TcsSend = new TaskCompletionSource <bool>();

                            uint ret = Interop.WinHttp.WinHttpWebSocketSend(
                                _operation.WebSocketHandle,
                                bufferType,
                                buffer.Count > 0 ? Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset) : IntPtr.Zero,
                                (uint)buffer.Count);

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

                if (sendOperationAlreadyPending)
                {
                    var exception = new InvalidOperationException(
                        SR.Format(SR.net_Websockets_AlreadyOneOutstandingOperation, "SendAsync"));

                    _operation.TcsSend.TrySetException(exception);
                    Abort();
                }

                return(_operation.TcsSend.Task);
            }
        }