SendHandshake( Uri uri, WebsocketSenderHandler websocketSenderHandler, CancellationToken ct, string?origin = null, IDictionary <string, string>?headers = null) { try { _connectionStatusAction(ConnectionStatus.SendingHandshakeToWebsocketServer, null); await websocketSenderHandler.SendConnectHandShake( uri, ct, origin, headers, _websocketParserHandler.SubprotocolAcceptedNames); } catch (Exception ex) { return( HandshakeStateKind.HandshakeSendFailed, new WebsocketClientLiteException("Handshake send failed.", ex) ); } return(HandshakeStateKind.HandshakeSend, null); }
internal IObservable <(HandshakeStateKind handshakeState, WebsocketClientLiteException?ex)> Handshake( Uri uri, WebsocketSenderHandler sender, TimeSpan timeout, CancellationToken ct, string?origin = null, IDictionary <string, string>?headers = null, IEnumerable <string>?subprotocols = null) { return(Observable.Create <(HandshakeStateKind handshakeState, WebsocketClientLiteException?ex)>(async obs => { using var parserDelegate = new HandshakeParserDelegate(obs); using var parserHandler = new HttpCombinedParser(parserDelegate); var handshakeParser = new HandshakeParser( parserHandler, parserDelegate, _connectionStatusAction); await SendHandshake(uri, sender, ct, origin, headers); await WaitForHandshake(handshakeParser); obs.OnCompleted(); }) .Timeout(timeout) .Catch < (HandshakeStateKind handshakeState, WebsocketClientLiteException?ex), TimeoutException>( tx => Observable.Return( (HandshakeStateKind.HandshakeTimedOut, new WebsocketClientLiteException("Handshake times out.", tx) ?? null) ) )); async Task WaitForHandshake(HandshakeParser handshakeParser) { bool isHandshakeDone; do { isHandshakeDone = await _tcpConnectionService .BytesObservable() .Select(b => handshakeParser.Parse(b, subprotocols)); } while (!isHandshakeDone); } }
internal async Task DisconnectWebsocket( WebsocketSenderHandler sender) { try { await sender.SendCloseHandshakeAsync(StatusCodes.GoingAway) .ToObservable() .Timeout(TimeSpan.FromSeconds(5)); } catch (Exception ex) { throw new WebsocketClientLiteException("Unable to disconnect gracefully", ex); } finally { _connectionStatusAction(ConnectionStatus.Disconnected, null); } }
internal async Task ConnectToWebSocketServer( WebsocketParserHandler websocketParserHandler, WebsocketSenderHandler websocketSenderHandler, Uri uri, bool secure, Stream tcpStream, string origin = null, IDictionary <string, string> headers = null, IEnumerable <string> subprotocols = null) { _websocketParserHandler = websocketParserHandler; _websocketSenderHandler = websocketSenderHandler; TcpStream = tcpStream; _observerConnectionStatus.OnNext(ConnectionStatus.HandshakeSendToWebsocketServer); await SendConnectHandShakeAsync(uri, secure, origin, headers, subprotocols); var waitForHandShakeResult = await _websocketParserHandler.ParserDelegate .HandshakeParserCompletionObservable .Timeout(TimeSpan.FromSeconds(30)) .Catch <ParserState, TimeoutException>(tx => Observable.Return(ParserState.HandshakeTimedOut)); switch (waitForHandShakeResult) { case ParserState.HandshakeCompletedSuccessfully: _observerConnectionStatus.OnNext(ConnectionStatus.HandshakeCompletedSuccessfully); break; case ParserState.HandshakeFailed: throw new WebsocketClientLiteException("Unable to complete handshake"); case ParserState.HandshakeTimedOut: throw new WebsocketClientLiteException("Handshake timed out."); default: throw new ArgumentOutOfRangeException($"Unknown parser state: {waitForHandShakeResult}"); } }