From ccabbbc5167ef65ccf99d55939145d349f1de0de Mon Sep 17 00:00:00 2001 From: David Fowler Date: Wed, 18 Jan 2017 17:33:00 +0000 Subject: [PATCH] Hacks from hell --- samples/SocketsSample/Hubs/Chat.cs | 6 - samples/SocketsSample/Hubs/Game.cs | 119 ++++++++++++++++++ samples/SocketsSample/Startup.cs | 2 + samples/SocketsSample/wwwroot/game.html | 103 +++++++++++++++ samples/SocketsSample/wwwroot/index.html | 1 + .../HubConnection.ts | 27 +++- 6 files changed, 246 insertions(+), 12 deletions(-) create mode 100644 samples/SocketsSample/Hubs/Game.cs create mode 100644 samples/SocketsSample/wwwroot/game.html diff --git a/samples/SocketsSample/Hubs/Chat.cs b/samples/SocketsSample/Hubs/Chat.cs index 5ea5247528..32fb18c626 100644 --- a/samples/SocketsSample/Hubs/Chat.cs +++ b/samples/SocketsSample/Hubs/Chat.cs @@ -24,12 +24,6 @@ public async Task Send(string message) await Clients.All.InvokeAsync("Send", $"{Context.ConnectionId}: {message}"); } - public async Task Add(int a, int b) - { - var result = await Clients.Client(Context.ConnectionId).InvokeAsync("Add", a, b); - await Clients.All.InvokeAsync("Send", $"Added {a} + {b} on client {Context.ConnectionId} = {result}"); - } - public Task SendToGroup(string groupName, string message) { return Clients.Group(groupName).InvokeAsync("Send", $"{Context.ConnectionId}@{groupName}: {message}"); diff --git a/samples/SocketsSample/Hubs/Game.cs b/samples/SocketsSample/Hubs/Game.cs new file mode 100644 index 0000000000..6d02da219b --- /dev/null +++ b/samples/SocketsSample/Hubs/Game.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR; + +namespace SocketsSample.Hubs +{ + public class GameLogic + { + private readonly HashSet _connections = new HashSet(); + private bool _gameRunning; + private readonly IHubContext _hubContext; + private Task _gameTask; + + public GameLogic(IHubContext hubContext) + { + _hubContext = hubContext; + } + + public void RemoveConnection(string connectionId) + { + lock (_connections) + { + _connections.Remove(connectionId); + } + } + + public void AddConnection(string connectionId) + { + lock (_connections) + { + _connections.Add(connectionId); + + if (_connections.Count == 2 && !_gameRunning) + { + _gameTask = RunGame(); + } + } + } + + private async Task RunGame() + { + _gameRunning = true; + + // Start the game on all clients + var winner = await Task.WhenAny(InvokeOnAll("Ask")); + + var result = await winner; + + var ignore = _hubContext.Clients.Client(result.ConnectionId).InvokeAsync("Send", "You win :)"); + + foreach (var item in _connections) + { + if (item == result.ConnectionId) + { + continue; + } + + ignore = _hubContext.Clients.Client(item).InvokeAsync("Send", "You lose :("); + } + } + + private Task[] InvokeOnAll(string method, params object[] args) + { + Task[] tasks; + lock (_connections) + { + tasks = new Task[_connections.Count]; + + int i = 0; + foreach (var id in _connections) + { + tasks[i++] = Invoke(id, method, args); + } + } + + return tasks; + } + + private async Task Invoke(string id, string method, object[] args) + { + + return new Result + { + Value = await _hubContext.Clients.Client(id).InvokeAsync(method, args), + ConnectionId = id + }; + } + + private class Result + { + public object Value { get; set; } + public string ConnectionId { get; set; } + } + } + + public class Game : Hub + { + private readonly GameLogic _gameLogic; + + public Game(GameLogic gameLogic) + { + _gameLogic = gameLogic; + } + + public override Task OnConnectedAsync() + { + _gameLogic.AddConnection(Context.ConnectionId); + return base.OnConnectedAsync(); + } + + public override Task OnDisconnectedAsync(Exception exception) + { + _gameLogic.RemoveConnection(Context.ConnectionId); + return base.OnDisconnectedAsync(exception); + } + } +} diff --git a/samples/SocketsSample/Startup.cs b/samples/SocketsSample/Startup.cs index e8e5a81cc9..b784f40487 100644 --- a/samples/SocketsSample/Startup.cs +++ b/samples/SocketsSample/Startup.cs @@ -29,6 +29,7 @@ public void ConfigureServices(IServiceCollection services) }); // .AddRedis(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -51,6 +52,7 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF { routes.MapHub("/hubs"); routes.MapHub("/clock"); + routes.MapHub("/game"); }); app.UseSockets(routes => diff --git a/samples/SocketsSample/wwwroot/game.html b/samples/SocketsSample/wwwroot/game.html new file mode 100644 index 0000000000..9cdd446eec --- /dev/null +++ b/samples/SocketsSample/wwwroot/game.html @@ -0,0 +1,103 @@ + + + + + + + +

+ + + +
    + + + + \ No newline at end of file diff --git a/samples/SocketsSample/wwwroot/index.html b/samples/SocketsSample/wwwroot/index.html index 564f6eb80e..8f924aa3a9 100644 --- a/samples/SocketsSample/wwwroot/index.html +++ b/samples/SocketsSample/wwwroot/index.html @@ -16,6 +16,7 @@

    ASP.NET SignalR

    diff --git a/src/Microsoft.AspNetCore.SignalR.Client.TS/HubConnection.ts b/src/Microsoft.AspNetCore.SignalR.Client.TS/HubConnection.ts index 71f556a1f5..f938f1406b 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client.TS/HubConnection.ts +++ b/src/Microsoft.AspNetCore.SignalR.Client.TS/HubConnection.ts @@ -56,12 +56,27 @@ export class HubConnection { // TODO: bind? args? let result = method.apply(this, invocation.Arguments); if (invocation.Id) { - let invocationResultDescriptor: InvocationResultDescriptor = { - "Id": invocation.Id.toString(), - "Result": result, - "Error": null - }; - this.connection.send(JSON.stringify(invocationResultDescriptor)); + if (result && result.constructor && result.constructor.name === "Promise") + { + let promise: Promise = result; + + promise.then(() => { + let invocationResultDescriptor: InvocationResultDescriptor = { + "Id": invocation.Id.toString(), + "Result": null, + "Error": null + }; + this.connection.send(JSON.stringify(invocationResultDescriptor)); + }); + } + else { + let invocationResultDescriptor: InvocationResultDescriptor = { + "Id": invocation.Id.toString(), + "Result": result || null, + "Error": null + }; + this.connection.send(JSON.stringify(invocationResultDescriptor)); + } } } }