public async Task <WebSocket> AcceptWebSocket() { try { _isAccepted = true; await _receiver.OpenSessionAsync(); _socket = new SessionWebSocket(this); return(_socket); } catch { await HandleClientSendErrorAsync(); throw; } }
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; } }
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); } }
public void CompleteDisposed() { _tcs?.SetException(SessionWebSocket.NewDisposedException()); }