Example #1
0
        private async Task ParseWebSocketAsync(
            byte[] b,
            HttpParserDelegate parserDelegate,
            HttpCombinedParser parserHandler,
            IEnumerable <string> subProtocols,
            IObserver <string> obs)
        {
            switch (_dataReceiveState)
            {
            case DataReceiveState.IsListeningForHandShake:

                _handshakeParser.Parse(b, parserDelegate, parserHandler);

                HandshakeController(parserDelegate, subProtocols);
                break;

            case DataReceiveState.IsListening:

                await _textDataParser.ParseAsync(_tcpStream, b[0], ExcludeZeroApplicationDataInPong);

                if (_textDataParser.IsCloseReceived)
                {
                    StopReceivingData();
                }

                if (_textDataParser.HasNewMessage)
                {
                    obs.OnNext(_textDataParser.NewMessage);
                }

                break;
            }
        }
        private async Task <IObservable <IHttpRequestReponse> > GetTcpRequestResponseObservable(
            int port,
            ICommunicationInterface communicationInterface = null,
            bool allowMultipleBindToSamePort = false)
        {
            var tcpListener = new TcpSocketListener();

            var observeTcpRequest = await tcpListener.CreateObservableListener(
                port,
                communicationInterface,
                allowMultipleBindToSamePort);

            var observable = Observable.Create <IHttpRequestReponse>(
                obs =>
            {
                var disp = observeTcpRequest.Subscribe(
                    tcpSocket =>
                {
                    var stream = tcpSocket.ReadStream;

                    var requestHandler = new HttpParserDelegate
                    {
                        HttpRequestReponse =
                        {
                            RemoteAddress   = tcpSocket.RemoteAddress,
                            RemotePort      = tcpSocket.RemotePort,
                            TcpSocketClient = tcpSocket,
                            RequestType     = RequestType.TCP
                        }
                    };

                    var result = _httpStreamParser.Parse(requestHandler, stream, Timeout);
                    obs.OnNext(result);
                },
                    ex =>
                {
                    Cleanup();
                    obs.OnError(ex);
                },
                    () =>
                {
                    Cleanup();
                    obs.OnCompleted();
                });

                return(disp);

                void Cleanup()
                {
                    _tcpListenerPortToObservable.Remove(port);
                    tcpListener.Dispose();
                }
            });

            return(observable);
        }
        private async Task <IObservable <IHttpRequestReponse> > GetUdpRequestResponseObservable(
            int port,
            ICommunicationInterface communicationInterface = null,
            bool allowMultipleBindToSamePort = false)
        {
            IUdpSocketReceiver udpListener = new UdpSocketReceiver();

            var observeUdpRequest = await udpListener.ObservableUnicastListener(
                port,
                communicationInterface,
                allowMultipleBindToSamePort);

            var observable = Observable.Create <IHttpRequestReponse>(
                obs =>
            {
                var disp = observeUdpRequest.Subscribe(
                    udpSocket =>
                {
                    var stream         = new MemoryStream(udpSocket.ByteData);
                    var requestHandler = new HttpParserDelegate
                    {
                        HttpRequestReponse =
                        {
                            RemoteAddress = udpSocket.RemoteAddress,
                            RemotePort    = int.Parse(udpSocket.RemotePort),
                            RequestType   = RequestType.UDP
                        }
                    };

                    var result = _httpStreamParser.Parse(requestHandler, stream, Timeout);
                    obs.OnNext(result);
                },
                    ex =>
                {
                    Cleanup();
                    obs.OnError(ex);
                },
                    () =>
                {
                    Cleanup();
                    obs.OnCompleted();
                });

                return(disp);

                void Cleanup()
                {
                    _udpReceiverPortToObservable.Remove(port);
                    udpListener.Dispose();
                }
            });

            return(observable);
        }
Example #4
0
        private void HandshakeController(HttpParserDelegate parserDelegate, IEnumerable <string> subProtocols)
        {
            if (parserDelegate.HttpRequestReponse.IsEndOfMessage)
            {
                if (parserDelegate.HttpRequestReponse.StatusCode == 101)
                {
                    if (subProtocols != null)
                    {
                        SubprotocolAccepted =
                            parserDelegate?.HttpRequestReponse?.Headers?.ContainsKey(
                                "SEC-WEBSOCKET-PROTOCOL") ?? false;

                        if (SubprotocolAccepted)
                        {
                            SubprotocolAcceptedName =
                                parserDelegate?.HttpRequestReponse?.Headers?["SEC-WEBSOCKET-PROTOCOL"];
                            if (!string.IsNullOrEmpty(SubprotocolAcceptedName))
                            {
                                Success();
                            }
                            else
                            {
                                _subjectConnectionStatus.OnNext(ConnectionStatus.Aborted);
                                throw new WebsocketClientLiteException("Server responded with blank Sub Protocol name");
                            }
                        }
                        else
                        {
                            _subjectConnectionStatus.OnNext(ConnectionStatus.Aborted);
                            throw new WebsocketClientLiteException("Server did not support any of the needed Sub Protocols");
                        }
                    }
                    else
                    {
                        Success();
                    }

                    void Success()
                    {
                        _subjectConnectionStatus.OnNext(ConnectionStatus.Connected);
                        System.Diagnostics.Debug.WriteLine("HandShake completed");
                        DataReceiveMode = DataReceiveMode.IsListeningForTextData;
                        IsConnected     = true;
                        _isHandshaking  = false;
                    }
                }
                else
                {
                    throw new WebsocketClientLiteException($"Unable to connect to websocket Server. " +
                                                           $"Error code: {parserDelegate.HttpRequestReponse.StatusCode}, " +
                                                           $"Error reason: {parserDelegate.HttpRequestReponse.ResponseReason}");
                }
            }
        }
Example #5
0
        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);
        }
        private static async Task <IHttpRequestResponse> ParseAsync(
            HttpRequestResponse requestResponseObj,
            CancellationToken ct,
            params ErrorCorrection[] errorCorrections)
        {
            using (var requestHandler = new HttpParserDelegate(requestResponseObj))
                using (var httpStreamParser = new HttpStreamParser(requestHandler, errorCorrections))
                {
                    var result = await httpStreamParser.ParseAsync(requestResponseObj.ResponseStream, ct);

                    if (httpStreamParser.HasParsingError)
                    {
                        ((HttpRequestResponse)result).HasParsingErrors = httpStreamParser.HasParsingError;
                    }

                    return(result);
                }
        }
Example #7
0
        private async void WatchHandshakeForTimeout(HttpParserDelegate parserDelegate, CancellationTokenSource cancellationTokenSource)
        {
            var handshakeTimer = Task.Run(async() =>
            {
                while (!parserDelegate.HttpRequestReponse.IsEndOfMessage &&
                       !parserDelegate.HttpRequestReponse.IsRequestTimedOut &&
                       !parserDelegate.HttpRequestReponse.IsUnableToParseHttp)
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(10));
                }
            }, cancellationTokenSource.Token);

            var timeout = Task.Delay(TimeSpan.FromSeconds(10), cancellationTokenSource.Token);

            var taskRetun = await Task.WhenAny(handshakeTimer, timeout);

            if (taskRetun == timeout)
            {
                _hasHandshakeTimedout = true;
            }
        }
Example #8
0
        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);
        }