Beispiel #1
0
        public async Task <WebSocket> AcceptWebSocket()
        {
            try
            {
                _isAccepted = true;
                await _receiver.OpenSessionAsync();

                _socket = new SessionWebSocket(this);
                return(_socket);
            }
            catch
            {
                await HandleClientSendErrorAsync();

                throw;
            }
        }
Beispiel #2
0
        public async Task ClientReceiveAsync()
        {
            try
            {
                if (_receiver.IsNotOpen)
                {
                    await _receiver.OpenAsync();
                }
                while (!_receiver.IsClosed)
                {
                    if (_closeMessage != null)
                    {
                        await _receiver.SendCloseAsync(_closeMessage, CancellationToken.None);

                        return;
                    }

                    await _sendDequeueSem.WaitAsync();

                    bool release = true;
                    List <PendingSend> messages = null;
                    try
                    {
                        PendingSend firstSend;
                        bool        timeout = !(await _sendsSem.WaitAsync(_options.HeartbeatInterval, _receiver.Aborted));
                        if (_sendState == SendDisposed)
                        {
                            throw SessionWebSocket.NewDisposedException();
                        }
                        if (timeout)
                        {
                            // heartbeat
                            await _receiver.SendHeartBeatAsync();

                            continue;
                        }
                        _sends.TryDequeue(out firstSend);

                        if (firstSend.Type == WebSocketMessageType.Close)
                        {
                            _sendDequeueSem.Release();
                            release = false;
                            if (_closeMessage == null)
                            {
                                var closeMessage = new byte[firstSend.Buffer.Count];
                                Array.Copy(firstSend.Buffer.Array, firstSend.Buffer.Offset, closeMessage, 0, firstSend.Buffer.Count);
                                Interlocked.CompareExchange(ref _closeMessage, closeMessage, null);
                            }
                            await _receiver.SendCloseAsync(_closeMessage, CancellationToken.None);

                            return;
                        }
                        else // WebSocketMessageType.Text
                        {
                            messages = new List <PendingSend> {
                                firstSend
                            };
                            PendingSend nextSend;
                            int         length = firstSend.Buffer.Count + _receiver.BytesSent;
                            while (_sends.TryPeek(out nextSend) && (nextSend.Type == WebSocketMessageType.Text))
                            {
                                await _sendsSem.WaitAsync(TimeSpan.Zero);

                                _sends.TryDequeue(out nextSend);

                                messages.Add(nextSend);
                                length += nextSend.Buffer.Count;
                                if (length >= _options.MaxResponseLength)
                                {
                                    break;
                                }
                            }
                            _sendDequeueSem.Release();
                            release = false;
                            await _receiver.SendMessagesAsync(messages);
                        }
                    }
                    catch (ObjectDisposedException) // SendDisposed
                    {
                        if (messages != null)
                        {
                            foreach (var message in messages)
                            {
                                message.CompleteDisposed();
                            }
                        }
                        PendingSend send;
                        while (_sends.TryDequeue(out send))
                        {
                            send.CompleteDisposed();
                        }
                        continue; // _closeMessage was set when SendDisposed
                    }
                    finally
                    {
                        if (release)
                        {
                            _sendDequeueSem.Release();
                        }
                    }
                }
            }
            catch
            {
                await HandleClientSendErrorAsync();

                throw;
            }
        }
Beispiel #3
0
        public async Task <WebSocketReceiveResult> ReceiveAsync(ArraySegment <byte> buffer, CancellationToken cancellationToken)
        {
            int oldState = Interlocked.CompareExchange(ref _receiveState, ReceiveOne, ReceiveNone);

            if (oldState == ReceiveDisposed)
            {
                throw SessionWebSocket.NewDisposedException();
            }
            if (oldState == ReceiveCloseReceived)
            {
                throw new InvalidOperationException(ReceiverIsClosed);
            }
            if (oldState == ReceiveOne)
            {
                throw new InvalidOperationException(SimultaneousReceivesNotSupported);
            }

            try
            {
                await _receivesSem.WaitAsync(cancellationToken);

                if (_receiveState == ReceiveDisposed)
                {
                    throw SessionWebSocket.NewDisposedException();
                }
                PendingReceive receive;
                _receives.TryPeek(out receive);

                if (receive.Type == WebSocketMessageType.Text)
                {
                    try
                    {
                        int  length       = receive.TextMessage.Decode(buffer);
                        bool endOfMessage = receive.TextMessage.IsEmpty;
                        var  result       = new WebSocketReceiveResult(length, WebSocketMessageType.Text, endOfMessage);

                        if (endOfMessage)
                        {
                            _receives.TryDequeue(out receive);
                        }
                        else
                        {
                            // undo Wait
                            _receivesSem.Release();
                        }
                        return(result);
                    }
                    catch // Decode exception
                    {
                        _receives.TryDequeue(out receive);
                        throw;
                    }
                }
                else // (receive.Type == WebSocketMessageType.Close)
                {
                    var result = new WebSocketReceiveResult(0, WebSocketMessageType.Close, true, receive.CloseStatus, receive.CloseStatusDescription);
                    Interlocked.CompareExchange(ref _receiveState, ReceiveCloseReceived, ReceiveOne);
                    _receives.TryDequeue(out receive);
                    return(result);
                }
            }
            finally
            {
                Interlocked.CompareExchange(ref _receiveState, ReceiveNone, ReceiveOne);
            }
        }
Beispiel #4
0
 public void CompleteDisposed()
 {
     _tcs?.SetException(SessionWebSocket.NewDisposedException());
 }