internal IObservable <string> CreateWebsocketListenerObservable( Stream tcpStream, IEnumerable <string> subProtocols = null) { ParserDelegate = new HttpParserDelegate(); var parserHandler = new HttpCombinedParser(ParserDelegate); _textDataParser.Reinitialize(); _tcpStream = tcpStream; _observerDataReceiveMode.OnNext(DataReceiveState.IsListeningForHandShake); _dataReceiveState = DataReceiveState.IsListeningForHandShake; var listenerObservable = Observable.Create <string>( obs => { var disposableReceiveState = DataReceiveStateObservable.Subscribe(s => { _dataReceiveState = s; }, obs.OnError, () => { Debug.WriteLine("DataReceiveObservable completed"); }); var disposableStreamListener = Observable.While( () => _dataReceiveState == DataReceiveState.IsListeningForHandShake || _dataReceiveState == DataReceiveState.IsListening, Observable.FromAsync(() => ReadOneByteAtTheTimeAsync(tcpStream))) .Select(b => Observable.FromAsync(() => ParseWebSocketAsync(b, ParserDelegate, parserHandler, subProtocols, obs))) .Concat() .Subscribe( _ => { if (_textDataParser.IsCloseReceived) { _observerDataReceiveMode.OnNext(DataReceiveState.Exiting); _observerDataReceiveMode.OnCompleted(); } }, obs.OnError, obs.OnCompleted); return(new CompositeDisposable(disposableReceiveState, disposableStreamListener)); }); return(listenerObservable); }
internal IObservable <string> CreateObservableListener( CancellationTokenSource innerCancellationTokenSource, ITcpSocketClient tcpSocketClient, IEnumerable <string> subProtocols = null) { var parserDelegate = new HttpParserDelegate(); var parserHandler = new HttpCombinedParser(parserDelegate); TextDataParser.Reinitialize(); _innerCancellationTokenSource = innerCancellationTokenSource; _tcpSocketClient = tcpSocketClient; DataReceiveMode = DataReceiveMode.IsListeningForHandShake; IsConnected = false; _isHandshaking = true; WatchHandshakeForTimeout(parserDelegate, _innerCancellationTokenSource); var observable = Observable.Create <string>( obs => { var disp = _tcpSocketClient.ReadStream.ReadOneByteAtTheTimeObservable(innerCancellationTokenSource, isConnectionOpen: IsConnected || _isHandshaking) .Subscribe( b => { if (TextDataParser.IsCloseRecieved) { return; } if (_hasHandshakeTimedout) { _subjectConnectionStatus.OnNext(ConnectionStatus.Aborted); throw new WebsocketClientLiteException("Connection request to server timed out"); } switch (DataReceiveMode) { case DataReceiveMode.IsListeningForHandShake: _handshakeParser.Parse(b, parserDelegate, parserHandler); HandshakeController(parserDelegate, subProtocols); break; case DataReceiveMode.IsListeningForTextData: TextDataParser.Parse(_tcpSocketClient, b[0], ExcludeZeroApplicationDataInPong); if (TextDataParser.IsCloseRecieved) { StopReceivingData(); } if (TextDataParser.HasNewMessage) { obs.OnNext(TextDataParser.NewMessage); } break; } }, ex => { StopReceivingData(); throw ex; }, () => { // ReSharper disable once ConvertClosureToMethodGroup StopReceivingData(); } ); HasReceivedCloseFromServer = false; return(disp); }); return(observable); }