public Task SendAsync(ArraySegment <byte> buffer, WebSocketMessageType messageType, bool compressed, bool endOfMessage, CancellationToken cancellationToken)
        {
            if (messageType != WebSocketMessageType.Text && messageType != WebSocketMessageType.Binary)
            {
                throw new ArgumentException("Invalid message type", nameof(messageType));
            }

            WebSocketValidationHelper.ValidateArraySegment(buffer, nameof(buffer));

            try
            {
                WebSocketValidationHelper.ThrowIfInvalidState(_state, _disposed, _validSendStates);
                ThrowIfOperationInProgress(_lastSendTask);
            }
            catch (Exception ex)
            {
                return(TargetFrameworksHelper.FromException(ex));
            }

            WebSocketMessageOpcode opcode = _lastSendWasFragment ? WebSocketMessageOpcode.Continuation : (messageType == WebSocketMessageType.Binary ? WebSocketMessageOpcode.Binary : WebSocketMessageOpcode.Text);

            Task sendTask = SendFrameAsync(opcode, compressed, endOfMessage, buffer, cancellationToken);

            _lastSendWasFragment = !endOfMessage;
            _lastSendTask        = sendTask;

            return(sendTask);
        }
        public override Task CloseOutputAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken cancellationToken)
        {
            WebSocketValidationHelper.ValidateCloseStatus(closeStatus, statusDescription);

            try
            {
                WebSocketValidationHelper.ThrowIfInvalidState(_state, _disposed, _validCloseOutputStates);
            }
            catch (Exception ex)
            {
                return(TargetFrameworksHelper.FromException(ex));
            }

            return(SendCloseFrameAsync(closeStatus, statusDescription, cancellationToken));
        }
        private Task SendFrameLockAcquiredNonCancelableAsync(WebSocketMessageOpcode opcode, bool compressed, bool endOfMessage, ArraySegment <byte> payloadBuffer)
        {
            Task writeTask        = null;
            bool releaseSemaphore = true;

            try
            {
                int sendBytes = WriteFrameToSendBuffer(opcode, compressed, endOfMessage, payloadBuffer);

                writeTask = _stream.WriteAsync(_sendBuffer, 0, sendBytes, CancellationToken.None);

                if (writeTask.IsCompleted)
                {
                    writeTask.GetAwaiter().GetResult();

                    return(TargetFrameworksHelper.CompletedTask);
                }

                releaseSemaphore = false;
            }
            catch (Exception ex)
            {
                return(TargetFrameworksHelper.FromException(_state == WebSocketState.Aborted ? CreateOperationCanceledException(ex) : new WebSocketException(WebSocketError.ConnectionClosedPrematurely, ex)));
            }
            finally
            {
                if (releaseSemaphore)
                {
                    _sendFrameAsyncLock.Release();
                }
            }

            return(writeTask.ContinueWith((task, source) =>
            {
                CompressionWebSocket webSocket = (CompressionWebSocket)source;
                webSocket._sendFrameAsyncLock.Release();

                try
                {
                    task.GetAwaiter().GetResult();
                }
                catch (Exception ex)
                {
                    throw webSocket._state == WebSocketState.Aborted ? CreateOperationCanceledException(ex) : new WebSocketException(WebSocketError.ConnectionClosedPrematurely, ex);
                }
            }, this, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default));
        }
        public override Task <WebSocketReceiveResult> ReceiveAsync(ArraySegment <byte> buffer, CancellationToken cancellationToken)
        {
            WebSocketValidationHelper.ValidateArraySegment(buffer, nameof(buffer));

            try
            {
                WebSocketValidationHelper.ThrowIfInvalidState(_state, _disposed, _validReceiveStates);

                lock (ReceiveAsyncLock)
                {
                    ThrowIfOperationInProgress(_lastReceiveTask);

                    Task <WebSocketReceiveResult> receiveTask = _lastReceiveTask = InternalReceiveAsync(buffer, cancellationToken);
                    return(receiveTask);
                }
            }
            catch (Exception ex)
            {
                return(TargetFrameworksHelper.FromException <WebSocketReceiveResult>(ex));
            }
        }
        private void SendKeepAliveFrameAsync()
        {
            bool acquiredLock = _sendFrameAsyncLock.Wait(0);

            if (acquiredLock)
            {
                SendFrameLockAcquiredNonCancelableAsync(WebSocketMessageOpcode.Ping, false, true, new ArraySegment <byte>(TargetFrameworksHelper.Empty <byte>()));
            }
        }