/// <summary>
        /// Gets the connection.
        /// </summary>
        /// <returns></returns>
        public HubConnection GetConnection()
        {
            var hubUrl = _configuration.GetValue <string>("SignalR:HubUrl");

            if (string.IsNullOrEmpty(hubUrl))
            {
                return(null);
            }

            var builder = new HubConnectionBuilder()
                          .WithUrl(hubUrl)
                          .WithAutomaticReconnect();

            if (_configuration.GetValue <bool>("SignalR:UseMessagePack"))
            {
                builder.AddMessagePackProtocol();
            }

            _hubConnection = builder.Build();

            _hubConnection.Closed += (error) =>
            {
                return(StartConnectionAsync());
            };

            StartConnectionAsync().GetAwaiter().GetResult();

            return(_hubConnection);
        }
Exemple #2
0
        private static async Task <SignalRStreamingCall> GetSignalRStateAsync(int i)
        {
            if (!SignalRCache.TryGetValue(i, out var state))
            {
                var builder = new HubConnectionBuilder();
                builder.WithUrl("http://localhost:5000/greeterhub");
                builder.AddMessagePackProtocol();
                var hubConnection = builder.Build();
                await hubConnection.StartAsync();

                var channel = System.Threading.Channels.Channel.CreateUnbounded <string>(new UnboundedChannelOptions
                {
                    SingleReader = true,
                    SingleWriter = true
                });

                var result = hubConnection.StreamAsync <string>("SayHelloBiDi", channel.Reader);
                state = new SignalRStreamingCall
                {
                    RequestStream  = channel.Writer,
                    ResponseStream = result.GetAsyncEnumerator()
                };

                bool success = SignalRCache.TryAdd(i, state);
                if (!success)
                {
                    throw new InvalidOperationException();
                }
            }

            return(state);
        }
Exemple #3
0
        private HubConnection buildConnection(CancellationToken cancellationToken)
        {
            var builder = new HubConnectionBuilder()
                          .WithUrl(endpoint, options =>
            {
                options.Headers.Add("Authorization", $"Bearer {api.AccessToken}");
                options.Headers.Add("OsuVersionHash", versionHash);
            });

            if (RuntimeInfo.SupportsJIT)
            {
                builder.AddMessagePackProtocol();
            }
            else
            {
                // eventually we will precompile resolvers for messagepack, but this isn't working currently
                // see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308.
                builder.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; });
            }

            var newConnection = builder.Build();

            ConfigureConnection?.Invoke(newConnection);

            newConnection.Closed += ex => onConnectionClosed(ex, cancellationToken);
            return(newConnection);
        }
        static async Task Main(string[] args)
        {
            var url = "http://localhost:5000/benchmark";

            var transportType = HttpTransportType.WebSockets;
            // var transportType = HttpTransportType.ServerSentEvents;
            // var transportType = HttpTransportType.LongPolling;

            var hubConnectionBuilder = new HubConnectionBuilder()
                                       .WithUrl(url, httpConnectionOptions =>
            {
                // set transport type
                httpConnectionOptions.Transports = transportType;
            });

            if (useMessagePack)
            {
                hubConnectionBuilder.AddMessagePackProtocol();
            }

            var connection = hubConnectionBuilder.Build();

            await connection.StartAsync();

            Console.WriteLine($"Starting connection with transport type {transportType}. Press Ctrl-C to close.");

            var cts = new CancellationTokenSource();

            Console.CancelKeyPress += (sender, a) =>
            {
                a.Cancel = true;
                cts.Cancel();
            };

            connection.Closed += e =>
            {
                if (e != null)
                {
                    Console.WriteLine("Connection closed with error: {0}", e);
                }
                else
                {
                    Console.WriteLine("Connection closed");
                }
                cts.Cancel();
                return(Task.CompletedTask);
            };

            connection.On("echo", (string name, string message) =>
            {
                Console.WriteLine($"INFO: server -> client: {name}: {message}");
            });

            await connection.InvokeAsync <string>("Echo", "albert", "hello");

            await connection.StopAsync();
        }
Exemple #5
0
        public void GlobalSetup()
        {
            var writer = MemoryBufferWriter.Get();

            try
            {
                HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer);
                var handshakeResponseResult = new ReadResult(new ReadOnlySequence <byte>(writer.ToArray()), false, false);

                _pipe = new TestDuplexPipe();
                _pipe.AddReadResult(new ValueTask <ReadResult>(handshakeResponseResult));
            }
            finally
            {
                MemoryBufferWriter.Return(writer);
            }

            _tcs = new TaskCompletionSource <ReadResult>();
            _pipe.AddReadResult(new ValueTask <ReadResult>(_tcs.Task));

            var hubConnectionBuilder = new HubConnectionBuilder();

            if (Protocol == "json")
            {
                // JSON protocol added by default
            }
            else
            {
                hubConnectionBuilder.AddMessagePackProtocol();
            }

            var delegateConnectionFactory = new DelegateConnectionFactory(format =>
            {
                var connection = new DefaultConnectionContext();
                // prevents keep alive time being activated
                connection.Features.Set <IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature());
                connection.Transport = _pipe;
                return(Task.FromResult <ConnectionContext>(connection));
            },
                                                                          connection =>
            {
                connection.Transport.Output.Complete();
                connection.Transport.Input.Complete();
                return(Task.CompletedTask);
            });

            hubConnectionBuilder.Services.AddSingleton <IConnectionFactory>(delegateConnectionFactory);

            _hubConnection = hubConnectionBuilder.Build();
            _hubConnection.StartAsync().GetAwaiter().GetResult();

            _arguments = new object[ArgumentCount];
            for (var i = 0; i < _arguments.Length; i++)
            {
                _arguments[i] = "Hello world!";
            }
        }
Exemple #6
0
        protected void CreateConnections(HttpTransportType transportType = HttpTransportType.WebSockets)
        {
            _pkg.Connections = new List <HubConnection>(_pkg.Job.Connections);
            _pkg.SentMassage = new List <int>(_pkg.Job.Connections);

            for (var i = 0; i < _pkg.Job.Connections; i++)
            {
                var hubConnectionBuilder = new HubConnectionBuilder()
                                           .WithUrl(_pkg.Job.ServerBenchmarkUri, transportType, httpConnectionOptions =>
                {
                    httpConnectionOptions.HttpMessageHandlerFactory = _ => _httpClientHandler;
                    httpConnectionOptions.Transports   = transportType;
                    httpConnectionOptions.CloseTimeout = TimeSpan.FromMinutes(100);
                    //httpConnectionOptions.SkipNegotiation = true;
                    //httpConnectionOptions.Url = new Uri(_pkg.Job.ServerBenchmarkUri);
                });

                //hubConnectionBuilder = hubConnectionBuilder.ConfigureLogging(builder => builder.SetMinimumLevel(LogLevel.Trace));

                HubConnection connection = null;
                switch (_pkg.Job.HubProtocol)
                {
                case "json":
                    // json hub protocol is set by default
                    connection = hubConnectionBuilder.ConfigureLogging(builder => builder.SetMinimumLevel(LogLevel.Debug)).Build();
                    break;

                case "messagepack":
                    connection = hubConnectionBuilder.AddMessagePackProtocol().ConfigureLogging(builder => builder.SetMinimumLevel(LogLevel.Trace)).Build();
                    break;

                default:
                    throw new Exception($"{_pkg.Job.HubProtocol} is an invalid hub protocol name.");
                }


                _pkg.Connections.Add(connection);
                _pkg.SentMassage.Add(0);
                // Capture the connection ID
                var ind = i;

                connection.Closed += e =>
                {
                    if (!_stopped)
                    {
                        var error = $"{ind}th Connection closed early: {e}";
                        _pkg.Job.Error += Environment.NewLine + $"[{DateTime.Now.ToString("hh:mm:ss.fff")}] " + error;
                        Util.Log(error);
                    }

                    return(Task.CompletedTask);
                };
            }
        }
        public void AddMessagePackProtocolAddsProtocol()
        {
            var connectionBuilder = new HubConnectionBuilder();

            connectionBuilder.AddMessagePackProtocol();

            var serviceProvider = connectionBuilder.Services.BuildServiceProvider();

            var resolvedHubProtocol = serviceProvider.GetService <IHubProtocol>();

            Assert.IsType <MessagePackHubProtocol>(resolvedHubProtocol);
        }
Exemple #8
0
        /// <summary>
        /// Gets the connection.
        /// </summary>
        /// <returns></returns>
        public HubConnection GetConnection(CancellationToken cancellationToken)
        {
            var hubUrl = _configuration.GetValue <string>("SignalR:HubUrl");

            if (string.IsNullOrEmpty(hubUrl))
            {
                return(null);
            }

            if (_hubConnection != null)
            {
                return(_hubConnection);
            }

            lock (_syncLock)
            {
                if (_hubConnection != null)
                {
                    return(_hubConnection);
                }

                var builder = new HubConnectionBuilder()
                              .WithUrl(hubUrl, options =>
                {
                    options.HttpMessageHandlerFactory = _ => _provider.GetRequiredService <HubHttpMessageHandlerAccessor>().Handler;
                    options.AccessTokenProvider       = async() =>
                    {
                        var manager = _provider.GetRequiredService <OAuthTokenManager>();
                        var token   = await manager.GetTokenAsync().ConfigureAwait(false);
                        return(token.Parameter);
                    };
                })
                              .WithAutomaticReconnect();

                if (_configuration.GetValue <bool>("SignalR:UseMessagePack"))
                {
                    builder.AddMessagePackProtocol();
                }

                _hubConnection = builder.Build();

                _hubConnection.Closed += (error) =>
                {
                    return(StartConnectionAsync(cancellationToken));
                };

                return(_hubConnection);
            }
        }
Exemple #9
0
        private HubConnection BuildHubConnection(string endpoint, string authToken)
        {
            var connectionBuilder = new HubConnectionBuilder()
                                    .WithUrl(endpoint, options =>
            {
                options.Headers.Add("Auth-Token", authToken);
            });

            if (GetSelectedProtocol() == Protocol.MessagePack)
            {
                connectionBuilder.AddMessagePackProtocol();
            }

            return(connectionBuilder.Build());
        }
Exemple #10
0
        private HubConnection createConnection(CancellationToken cancellationToken)
        {
            var builder = new HubConnectionBuilder()
                          .WithUrl(endpoint, options => { options.Headers.Add("Authorization", $"Bearer {api.AccessToken}"); });

            if (RuntimeInfo.SupportsJIT)
            {
                builder.AddMessagePackProtocol();
            }
            else
            {
                // eventually we will precompile resolvers for messagepack, but this isn't working currently
                // see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308.
                builder.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; });
            }

            var newConnection = builder.Build();

            // this is kind of SILLY
            // https://github.com/dotnet/aspnetcore/issues/15198
            newConnection.On <MultiplayerRoomState>(nameof(IMultiplayerClient.RoomStateChanged), ((IMultiplayerClient)this).RoomStateChanged);
            newConnection.On <MultiplayerRoomUser>(nameof(IMultiplayerClient.UserJoined), ((IMultiplayerClient)this).UserJoined);
            newConnection.On <MultiplayerRoomUser>(nameof(IMultiplayerClient.UserLeft), ((IMultiplayerClient)this).UserLeft);
            newConnection.On <int>(nameof(IMultiplayerClient.HostChanged), ((IMultiplayerClient)this).HostChanged);
            newConnection.On <MultiplayerRoomSettings>(nameof(IMultiplayerClient.SettingsChanged), ((IMultiplayerClient)this).SettingsChanged);
            newConnection.On <int, MultiplayerUserState>(nameof(IMultiplayerClient.UserStateChanged), ((IMultiplayerClient)this).UserStateChanged);
            newConnection.On(nameof(IMultiplayerClient.LoadRequested), ((IMultiplayerClient)this).LoadRequested);
            newConnection.On(nameof(IMultiplayerClient.MatchStarted), ((IMultiplayerClient)this).MatchStarted);
            newConnection.On(nameof(IMultiplayerClient.ResultsReady), ((IMultiplayerClient)this).ResultsReady);
            newConnection.On <int, IEnumerable <APIMod> >(nameof(IMultiplayerClient.UserModsChanged), ((IMultiplayerClient)this).UserModsChanged);
            newConnection.On <int, BeatmapAvailability>(nameof(IMultiplayerClient.UserBeatmapAvailabilityChanged), ((IMultiplayerClient)this).UserBeatmapAvailabilityChanged);

            newConnection.Closed += ex =>
            {
                isConnected.Value = false;

                Logger.Log(ex != null ? $"Multiplayer client lost connection: {ex}" : "Multiplayer client disconnected", LoggingTarget.Network);

                // make sure a disconnect wasn't triggered (and this is still the active connection).
                if (!cancellationToken.IsCancellationRequested)
                {
                    Task.Run(connect, default);
                }

                return(Task.CompletedTask);
            };
            return(newConnection);
        }
Exemple #11
0
        private HubConnection buildConnection(CancellationToken cancellationToken)
        {
            var builder = new HubConnectionBuilder()
                          .WithUrl(endpoint, options =>
            {
                // Use HttpClient.DefaultProxy once on net6 everywhere.
                // The credential setter can also be removed at this point.
                options.Proxy = WebRequest.DefaultWebProxy;
                if (options.Proxy != null)
                {
                    options.Proxy.Credentials = CredentialCache.DefaultCredentials;
                }

                options.Headers.Add("Authorization", $"Bearer {api.AccessToken}");
                options.Headers.Add("OsuVersionHash", versionHash);
            });

            if (RuntimeInfo.SupportsJIT && preferMessagePack)
            {
                builder.AddMessagePackProtocol(options =>
                {
                    options.SerializerOptions = SignalRUnionWorkaroundResolver.OPTIONS;
                });
            }
            else
            {
                // eventually we will precompile resolvers for messagepack, but this isn't working currently
                // see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308.
                builder.AddNewtonsoftJsonProtocol(options =>
                {
                    options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                    options.PayloadSerializerSettings.Converters            = new List <JsonConverter>
                    {
                        new SignalRDerivedTypeWorkaroundJsonConverter(),
                    };
                });
            }

            var newConnection = builder.Build();

            ConfigureConnection?.Invoke(newConnection);

            newConnection.Closed += ex => onConnectionClosed(ex, cancellationToken);
            return(newConnection);
        }
        /// <summary>
        /// Open connection
        /// </summary>
        /// <returns></returns>
        private async Task <HubConnection> OpenAsync()
        {
            var builder = new HubConnectionBuilder()
                          .WithAutomaticReconnect();

            if (_useMessagePack && _msgPack != null)
            {
                builder = builder.AddMessagePackProtocol(options => {
                    options.FormatterResolvers = _msgPack.GetResolvers().ToList();
                });
            }
            else
            {
                var jsonSettings = _jsonSettings?.Settings;
                if (jsonSettings != null)
                {
                    builder = builder.AddNewtonsoftJsonProtocol(options => {
                        options.PayloadSerializerSettings = jsonSettings;
                    });
                }
            }
            var connection = builder
                             .WithUrl(_endpointUri, options => {
                if (_provider != null)
                {
                    options.AccessTokenProvider = async() => {
                        var token = await _provider.GetTokenForAsync(_resourceId);
                        if (token?.RawToken == null)
                        {
                            _logger.Error("Failed to aquire token for hub calling " +
                                          "({resource}) - calling without...",
                                          _resourceId);
                        }
                        return(token?.RawToken);
                    };
                }
            })
                             .Build();

            connection.Closed += ex => OnClosedAsync(connection, ex);
            await connection.StartAsync();

            return(connection);
        }
Exemple #13
0
        private HubConnection buildConnection(CancellationToken cancellationToken)
        {
            var builder = new HubConnectionBuilder()
                          .WithUrl(endpoint, options =>
            {
                options.Headers.Add("Authorization", $"Bearer {api.AccessToken}");
                options.Headers.Add("OsuVersionHash", versionHash);
            });

            if (RuntimeInfo.SupportsJIT && preferMessagePack)
            {
                builder.AddMessagePackProtocol(options =>
                {
                    options.SerializerOptions = SignalRUnionWorkaroundResolver.OPTIONS;
                });
            }
            else
            {
                // eventually we will precompile resolvers for messagepack, but this isn't working currently
                // see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308.
                builder.AddNewtonsoftJsonProtocol(options =>
                {
                    options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                    // TODO: This should only be required to be `TypeNameHandling.Auto`.
                    // See usage in osu-server-spectator for further documentation as to why this is required.
                    options.PayloadSerializerSettings.TypeNameHandling = TypeNameHandling.All;
                });
            }

            var newConnection = builder.Build();

            ConfigureConnection?.Invoke(newConnection);

            newConnection.Closed += ex => onConnectionClosed(ex, cancellationToken);
            return(newConnection);
        }
Exemple #14
0
        /// <summary>
        /// Starts the connection.
        /// </summary>
        /// <returns></returns>
        public async Task StartAsync()
        {
            if (IsStarted)
            {
                return;
            }


            var builder = new HubConnectionBuilder().WithUrl(Url).WithAutomaticReconnect();

            if (UseMessagePackProtocol)
            {
                builder = builder.AddMessagePackProtocol();
            }

            if (EnableAutoReconnection)
            {
                builder = builder.WithAutomaticReconnect(new TimeSpan[]
                {
                    TimeSpan.FromSeconds(1),
                    TimeSpan.FromSeconds(1),
                    TimeSpan.FromSeconds(1),
                    TimeSpan.FromSeconds(1)
                });
            }

            _connection = builder.Build();

            bool reconnecting = false;

            _connection.Closed += (exception) =>
            {
                if (EnableAutoReconnection)
                {
                    if (reconnecting && _connection.State == HubConnectionState.Disconnected && exception.GetType() == typeof(OperationCanceledException))
                    {
                        Error?.Invoke(this, new ResonanceExceptionEventArgs(exception));
                    }
                }

                return(Task.FromResult(true));
            };

            _connection.Reconnecting += (ex) =>
            {
                if (!reconnecting)
                {
                    reconnecting = true;

                    if (EnableAutoReconnection)
                    {
                        Reconnecting?.Invoke(this, new EventArgs());
                    }
                    else
                    {
                        try
                        {
                            Stop();
                            Error?.Invoke(this, new ResonanceExceptionEventArgs(ex));
                        }
                        catch { }
                    }
                }

                return(Task.FromResult(true));
            };

            _connection.Reconnected += (msg) =>
            {
                if (EnableAutoReconnection)
                {
                    Reconnected?.Invoke(this, new EventArgs());
                    reconnecting = false;
                }

                return(Task.FromResult(true));
            };

            await _connection.StartAsync();

            IsStarted = true;
        }
Exemple #15
0
        private async Task RefreshConnection()
        {
            var connectionText = $"{addressBox.Text}/ua";

            if (connection != null && connection.State == HubConnectionState.Connected)
            {
                await connection.StopAsync();
            }

            var connectionBuilder = new HubConnectionBuilder()
                                    .WithUrl(connectionText);

            connectionBuilder.AddMessagePackProtocol();
            connection = connectionBuilder.Build();
            connection.On(
                "ShowSimpleTextStatistics",
                (ServerPresentationComputationSummary summary) =>
            {
                Invoke(new Action(() =>
                {
                    int toCompute = summary.total - summary.finishedAutomata.Count;
                    chart1.Series["UnaryFinishedSeries"].Points.Clear();
                    chart1.Series["UnaryFinishedSeries"].Points.AddXY("To compute", toCompute);
                    chart1.Series["UnaryFinishedSeries"].Points.AddXY("Computed", summary.finishedAutomata.Count);

                    if (summary.finishedAutomata.Count > 0)
                    {
                        chart1.Titles[0].Text = $"Unary Automata with n = {summary.n}";
                        totalComputingTime    = GetTotalComputationTime(summary.finishedAutomata);
                        var totalSpeed        = GetAverageSpeed(summary.finishedAutomata);
                        double leftSeconds;
                        if (totalSpeed == 0)
                        {
                            if (toCompute == 0)
                            {
                                leftSeconds = 0;
                            }
                            else
                            {
                                leftSeconds = Double.MaxValue;
                            }
                        }
                        else
                        {
                            leftSeconds = toCompute / totalSpeed;
                        }

                        startCountingTime = DateTime.Now;
                        if (!timerLaunched && summary.finishedAutomata.Count == summary.total)
                        {
                            materialLabel1.Text = "Total computation time: " + totalComputingTime.ToString();
                        }
                        else if (!timerLaunched && summary.finishedAutomata.Count < summary.total)
                        {
                            timer1.Tick += (o, e) =>
                            {
                                materialLabel1.Text = "Total computation time: " + (totalComputingTime + (DateTime.Now - startCountingTime)).ToString();
                            };
                            timer1.Start();
                            timerLaunched = true;
                        }
                        else if (summary.finishedAutomata.Count == summary.total)
                        {
                            timer1.Stop();
                            timerLaunched = false;
                        }
                        materialLabel3.Text = $"Total speed: {totalSpeed:F2} automata per second.";
                        materialLabel2.Text = "Expected end of computation at: " + DateTime.Now.AddSeconds(leftSeconds).ToString();
                    }

                    var sortedLengths = new List <int>();
                    var sortedResults = new List <Tuple <int, string> >();

                    foreach (var a in summary.finishedAutomata)
                    {
                        if (a.solution.solvedB.Count > 0)
                        {
                            string b_tab, a_tab = byteTabToString(a.solution.unaryArray);
                            for (int i = 0; i < a.solution.solvedB.Count; i++)
                            {
                                var b = a.solution.solvedB[i];
                                b_tab = byteTabToString(b);
                                sortedLengths.Add(-a.solution.solvedSyncLength[i]);
                                sortedResults.Add(new Tuple <int, string>(a.solution.unaryIndex, $"[{a_tab},{b_tab}]"));
                            }
                        }
                    }

                    listOfAutomata.Items.Clear();
                    automataToLaunch.Clear();
                    var resultingArray          = sortedResults.ToArray();
                    var resultingLengthsNegated = sortedLengths.ToArray();
                    Array.Sort(resultingLengthsNegated, resultingArray);
                    for (int i = 0; i < resultingArray.Length; i++)
                    {
                        automataToLaunch.Add(resultingArray[i].Item2);
                        listOfAutomata.Items.Add($"{resultingArray[i].Item2}, index = {resultingArray[i].Item1} - synchronizing length {-1 * resultingLengthsNegated[i]}");
                    }
                    var cernyLength             = (summary.n - 1) * (summary.n - 1);
                    var cernyConjectureViolated = resultingLengthsNegated.Length > 0 && Math.Abs(resultingLengthsNegated[0]) > cernyLength;
                    var yetText = summary.finishedAutomata.Count < summary.total ? "yet " : string.Empty;
                    var cernyConjectureViolatedText = cernyConjectureViolated ? $"VIOLATED for n = {summary.n}!" : $"not {yetText}violated for n = {summary.n}";
                    labelAutomataCount.Text         = $"There are {listOfAutomata.Items.Count} interesting automata.\nCerny conjecture is {cernyConjectureViolatedText}";
                }));
            }
                );

            try
            {
                await connection.StartAsync();

                connectionAddress = connectionText;
            }
            catch (Exception e)
            {
            }
        }
        protected virtual async Task Connect()
        {
            if (connection != null)
            {
                return;
            }

            var builder = new HubConnectionBuilder()
                          .WithUrl(endpoint, options => { options.Headers.Add("Authorization", $"Bearer {api.AccessToken}"); });

            if (RuntimeInfo.SupportsJIT)
            {
                builder.AddMessagePackProtocol();
            }
            else
            {
                // eventually we will precompile resolvers for messagepack, but this isn't working currently
                // see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308.
                builder.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; });
            }

            connection = builder.Build();
            // until strong typed client support is added, each method must be manually bound (see https://github.com/dotnet/aspnetcore/issues/15198)
            connection.On <int, SpectatorState>(nameof(ISpectatorClient.UserBeganPlaying), ((ISpectatorClient)this).UserBeganPlaying);
            connection.On <int, FrameDataBundle>(nameof(ISpectatorClient.UserSentFrames), ((ISpectatorClient)this).UserSentFrames);
            connection.On <int, SpectatorState>(nameof(ISpectatorClient.UserFinishedPlaying), ((ISpectatorClient)this).UserFinishedPlaying);

            connection.Closed += async ex =>
            {
                isConnected = false;
                playingUsers.Clear();

                if (ex != null)
                {
                    Logger.Log($"Spectator client lost connection: {ex}", LoggingTarget.Network);
                    await tryUntilConnected();
                }
            };

            await tryUntilConnected();

            async Task tryUntilConnected()
            {
                Logger.Log("Spectator client connecting...", LoggingTarget.Network);

                while (api.State.Value == APIState.Online)
                {
                    try
                    {
                        // reconnect on any failure
                        await connection.StartAsync();

                        Logger.Log("Spectator client connected!", LoggingTarget.Network);

                        // get all the users that were previously being watched
                        int[] users;

                        lock (userLock)
                        {
                            users = watchingUsers.ToArray();
                            watchingUsers.Clear();
                        }

                        // success
                        isConnected = true;

                        // resubscribe to watched users
                        foreach (var userId in users)
                        {
                            WatchUser(userId);
                        }

                        // re-send state in case it wasn't received
                        if (isPlaying)
                        {
                            beginPlaying();
                        }

                        break;
                    }
                    catch (Exception e)
                    {
                        Logger.Log($"Spectator client connection error: {e}", LoggingTarget.Network);
                        await Task.Delay(5000);
                    }
                }
            }
        }
Exemple #17
0
        private List <HubConnection> Create(int conn, string url,
                                            string transportTypeName = "Websockets",
                                            string hubProtocol       = "json")
        {
            Util.Log($"transport type: {transportTypeName}");
            var transportType = HttpTransportType.WebSockets;

            switch (transportTypeName)
            {
            case "LongPolling":
                transportType = HttpTransportType.LongPolling;
                break;

            case "ServerSentEvents":
                transportType = HttpTransportType.ServerSentEvents;
                break;

            case "None":
                transportType = HttpTransportType.None;
                break;

            default:
                transportType = HttpTransportType.WebSockets;
                break;
            }

            // Many Urls are allowed for sharding every connection to different Server
            var serverUrls = url.Split(';');

            _tk.State = Stat.Types.State.HubconnCreating;
            var connections = new List <HubConnection>(conn);

            for (var i = 0; i < conn; i++)
            {
                var cookies           = new CookieContainer();
                var httpClientHandler = new HttpClientHandler
                {
                    ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,
                    CookieContainer = cookies,
                };
                var hubConnectionBuilder = new HubConnectionBuilder()

                                           /* TODO. Console log is important for finding errors.
                                            * But if every connection enables it, there will be thousands of
                                            * 'Console logger queue processing thread' which degrade the system
                                            * response, and bring issues to counters statistic.
                                            * Temporarily, we disable it. We need to find the best way
                                            * to enable it.
                                            */
                                           //.ConfigureLogging(logging =>
                                           //{
                                           //    logging.AddConsole();
                                           //    logging.SetMinimumLevel(LogLevel.Warning);
                                           //})
                                           .WithUrl(serverUrls[i % serverUrls.Length], httpConnectionOptions =>
                {
                    httpConnectionOptions.HttpMessageHandlerFactory = _ => httpClientHandler;
                    httpConnectionOptions.Transports   = transportType;
                    httpConnectionOptions.CloseTimeout = TimeSpan.FromMinutes(100);
                    httpConnectionOptions.Cookies      = cookies;
                });

                HubConnection connection = null;
                switch (hubProtocol)
                {
                case "json":
                    connection = hubConnectionBuilder.Build();
                    break;

                case "messagepack":
                    connection = hubConnectionBuilder.AddMessagePackProtocol().Build();
                    break;

                default:
                    throw new Exception($"{hubProtocol} is invalid.");
                }

                connection.Closed += e =>
                {
                    if (_tk.State <= Stat.Types.State.SendComplete && _tk.State >= Stat.Types.State.SendReady)
                    {
                        var error = $"Connection closed early: {e}";
                        Util.Log(error);
                    }

                    return(Task.CompletedTask);
                };
                connections.Add(connection);
            }

            _tk.State = Stat.Types.State.HubconnCreated;
            return(connections);
        }
Exemple #18
0
        protected virtual async Task Connect()
        {
            if (connection != null)
            {
                return;
            }

            var builder = new HubConnectionBuilder()
                          .WithUrl(endpoint, options => { options.Headers.Add("Authorization", $"Bearer {api.AccessToken}"); });

            if (RuntimeInfo.SupportsJIT)
            {
                builder.AddMessagePackProtocol();
            }
            else
            {
                // eventually we will precompile resolvers for messagepack, but this isn't working currently
                // see https://github.com/neuecc/MessagePack-CSharp/issues/780#issuecomment-768794308.
                builder.AddNewtonsoftJsonProtocol(options => { options.PayloadSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; });
            }

            connection = builder.Build();

            // this is kind of SILLY
            // https://github.com/dotnet/aspnetcore/issues/15198
            connection.On <MultiplayerRoomState>(nameof(IMultiplayerClient.RoomStateChanged), ((IMultiplayerClient)this).RoomStateChanged);
            connection.On <MultiplayerRoomUser>(nameof(IMultiplayerClient.UserJoined), ((IMultiplayerClient)this).UserJoined);
            connection.On <MultiplayerRoomUser>(nameof(IMultiplayerClient.UserLeft), ((IMultiplayerClient)this).UserLeft);
            connection.On <int>(nameof(IMultiplayerClient.HostChanged), ((IMultiplayerClient)this).HostChanged);
            connection.On <MultiplayerRoomSettings>(nameof(IMultiplayerClient.SettingsChanged), ((IMultiplayerClient)this).SettingsChanged);
            connection.On <int, MultiplayerUserState>(nameof(IMultiplayerClient.UserStateChanged), ((IMultiplayerClient)this).UserStateChanged);
            connection.On(nameof(IMultiplayerClient.LoadRequested), ((IMultiplayerClient)this).LoadRequested);
            connection.On(nameof(IMultiplayerClient.MatchStarted), ((IMultiplayerClient)this).MatchStarted);
            connection.On(nameof(IMultiplayerClient.ResultsReady), ((IMultiplayerClient)this).ResultsReady);

            connection.Closed += async ex =>
            {
                isConnected.Value = false;

                Logger.Log(ex != null
                    ? $"Multiplayer client lost connection: {ex}"
                    : "Multiplayer client disconnected", LoggingTarget.Network);

                if (connection != null)
                {
                    await tryUntilConnected();
                }
            };

            await tryUntilConnected();

            async Task tryUntilConnected()
            {
                Logger.Log("Multiplayer client connecting...", LoggingTarget.Network);

                while (api.State.Value == APIState.Online)
                {
                    try
                    {
                        Debug.Assert(connection != null);

                        // reconnect on any failure
                        await connection.StartAsync();

                        Logger.Log("Multiplayer client connected!", LoggingTarget.Network);

                        // Success.
                        isConnected.Value = true;
                        break;
                    }
                    catch (Exception e)
                    {
                        Logger.Log($"Multiplayer client connection error: {e}", LoggingTarget.Network);
                        await Task.Delay(5000);
                    }
                }
            }
        }