public override async Task <WebSocketReceiveResult> ReceiveAsync(ArraySegment <byte> buffer,
                                                                         CancellationToken cancellationToken)
        {
            if (_currentReadItem == null)
            {
                await _receiveQueueSemaphore.WaitAsync(cancellationToken);

                _currentReadItem = _receiveQueue.Dequeue();
            }

            var copyLength = Math.Min(buffer.Count, _currentReadItem.Data.Length - _currentReadItem.CurrentDataIndex);

            Array.Copy(_currentReadItem.Data, _currentReadItem.CurrentDataIndex, buffer.Array, buffer.Offset,
                       copyLength);
            _currentReadItem.CurrentDataIndex += copyLength;

            var messageType = _currentReadItem.MessageType;

            if (messageType == WebSocketMessageType.Close)
            {
                _closeStatus            = _currentReadItem.CloseStatus;
                _closeStatusDescription = Encoding.UTF8.GetString(_currentReadItem.Data);
            }

            if (_currentReadItem.Data.Length == _currentReadItem.CurrentDataIndex)
            {
                _currentReadItem = null;
            }

            return(new WebSocketReceiveResult(copyLength, messageType, _currentReadItem == null, _closeStatus,
                                              _closeStatusDescription));
        }
        public override Task SendAsync(ArraySegment <byte> buffer, WebSocketMessageType messageType, bool endOfMessage,
                                       CancellationToken cancellationToken)
        {
            lock (this)
            {
                if (_currentSendItem == null)
                {
                    _currentSendItem = new SocketSimulateSendItem()
                    {
                        Data        = new byte[0],
                        MessageType = messageType
                    };
                }

                var newData = new byte[_currentSendItem.Data.Length + buffer.Count];
                Array.Copy(_currentSendItem.Data, 0, newData, 0, _currentSendItem.Data.Length);
                Array.Copy(buffer.Array, buffer.Offset, newData, _currentSendItem.Data.Length, buffer.Count);

                _currentSendItem.Data = newData;

                if (endOfMessage)
                {
                    SentFromServerQueue.Add(_currentSendItem, cancellationToken);
                    _currentSendItem = null;
                }
            }

            return(Task.CompletedTask);
        }
        public override Task CloseOutputAsync(WebSocketCloseStatus closeStatus, string statusDescription,
                                              CancellationToken cancellationToken)
        {
            _state = WebSocketState.Closed;

            var sendItem = new SocketSimulateSendItem
            {
                CloseStatus = closeStatus,
                MessageType = WebSocketMessageType.Close
            };

            if (statusDescription != null)
            {
                sendItem.Data = Encoding.UTF8.GetBytes(statusDescription);
            }

            SentFromServerQueue.Add(sendItem, cancellationToken);

            return(Task.CompletedTask);
        }