public static TestableChat GetTestableChat(string connectionId, StateChangeTracker clientState, ChatUser user, IDictionary<string, Cookie> cookies) { // setup things needed for chat var repository = new InMemoryRepository(); var resourceProcessor = new Mock<IResourceProcessor>(); var chatService = new Mock<IChatService>(); var connection = new Mock<IConnection>(); var settings = new Mock<IApplicationSettings>(); var mockPipeline = new Mock<IHubPipelineInvoker>(); // add user to repository repository.Add(user); // create testable chat var chat = new TestableChat(settings, resourceProcessor, chatService, repository, connection); var mockedConnectionObject = chat.MockedConnection.Object; chat.Clients = new HubConnectionContext(mockPipeline.Object, mockedConnectionObject, "Chat", connectionId, clientState); var prinicipal = new Mock<IPrincipal>(); var request = new Mock<IRequest>(); request.Setup(m => m.Cookies).Returns(cookies); request.Setup(m => m.User).Returns(prinicipal.Object); // setup context chat.Context = new HubCallerContext(request.Object, connectionId); return chat; }
public HubInvokerContext(IHub hub, StateChangeTracker tracker, MethodDescriptor methodDescriptor, IList<object> args) { Hub = hub; MethodDescriptor = methodDescriptor; Args = args; StateTracker = tracker; }
private Task ProcessResponse(StateChangeTracker tracker, object result, HubRequest request, Exception error) { var hubResult = new HubResponse { State = tracker.GetChanges(), Result = result, Id = request.Id, }; if (error != null) { _counters.ErrorsHubInvocationTotal.Increment(); _counters.ErrorsHubInvocationPerSec.Increment(); _counters.ErrorsAllTotal.Increment(); _counters.ErrorsAllPerSec.Increment(); if (_enableDetailedErrors) { var exception = error.InnerException ?? error; hubResult.StackTrace = _isDebuggingEnabled ? exception.StackTrace : null; hubResult.Error = exception.Message; } else { hubResult.Error = String.Format(CultureInfo.CurrentCulture, Resources.Error_HubInvocationFailed, request.Hub, request.Method); } } return(Transport.Send(hubResult)); }
private Task ProcessResponse(StateChangeTracker tracker, object result, HubRequest request, Exception error) { var exception = error.Unwrap(); string stackTrace = (exception != null && _isDebuggingEnabled) ? exception.StackTrace : null; string errorMessage = exception != null ? exception.Message : null; if (exception != null) { _counters.ErrorsHubInvocationTotal.Increment(); _counters.ErrorsHubInvocationPerSec.Increment(); _counters.ErrorsAllTotal.Increment(); _counters.ErrorsAllPerSec.Increment(); } var hubResult = new HubResponse { State = tracker.GetChanges(), Result = result, Id = request.Id, Error = errorMessage, StackTrace = stackTrace }; return(Transport.Send(hubResult)); }
/// <summary> /// Processes the hub's incoming method calls. /// </summary> protected override Task OnReceived(IRequest request, string connectionId, string data) { HubRequest hubRequest = _requestParser.Parse(data, _serializer); // Create the hub HubDescriptor descriptor = _manager.EnsureHub(hubRequest.Hub, _counters.ErrorsHubInvocationTotal, _counters.ErrorsHubInvocationPerSec, _counters.ErrorsAllTotal, _counters.ErrorsAllPerSec); IJsonValue[] parameterValues = hubRequest.ParameterValues; // Resolve the method MethodDescriptor methodDescriptor = _manager.GetHubMethod(descriptor.Name, hubRequest.Method, parameterValues); if (methodDescriptor == null) { // Empty (noop) method descriptor // Use: Forces the hub pipeline module to throw an error. This error is encapsulated in the HubDispatcher. // Encapsulating it in the HubDispatcher prevents the error from bubbling up to the transport level. // Specifically this allows us to return a faulted task (call .fail on client) and to not cause the // transport to unintentionally fail. IEnumerable <MethodDescriptor> availableMethods = _manager.GetHubMethods(descriptor.Name, m => m.Name == hubRequest.Method); methodDescriptor = new NullMethodDescriptor(descriptor, hubRequest.Method, availableMethods); } // Resolving the actual state object var tracker = new StateChangeTracker(hubRequest.State); var hub = CreateHub(request, descriptor, connectionId, tracker, throwIfFailedToCreate: true); return(InvokeHubPipeline(hub, parameterValues, methodDescriptor, hubRequest, tracker) .ContinueWithPreservedCulture(task => hub.Dispose(), TaskContinuationOptions.ExecuteSynchronously)); }
public HubInvokerContext(IHub hub, StateChangeTracker tracker, MethodDescriptor methodDescriptor, IList <object> args) { Hub = hub; MethodDescriptor = methodDescriptor; Args = args; StateTracker = tracker; }
/// <summary> /// Initializes a new instance of the <see cref="HubConnectionContext"/>. /// </summary> /// <param name="pipelineInvoker">The pipeline invoker.</param> /// <param name="connection">The connection.</param> /// <param name="hubName">The hub name.</param> /// <param name="connectionId">The connection id.</param> /// <param name="tracker">The connection hub state.</param> public HubConnectionContext(IHubPipelineInvoker pipelineInvoker, IConnection connection, string hubName, string connectionId, StateChangeTracker tracker) : base(connection, pipelineInvoker, hubName) { _connectionId = connectionId; Caller = new StatefulSignalProxy(connection, pipelineInvoker, connectionId, PrefixHelper.HubConnectionIdPrefix, hubName, tracker); All = AllExcept(); Others = AllExcept(connectionId); }
private Task InvokeHubPipeline(IHub hub, IJsonValue[] parameterValues, MethodDescriptor methodDescriptor, HubRequest hubRequest, StateChangeTracker tracker) { // TODO: Make adding parameters here pluggable? IValueProvider? ;) HubInvocationProgress progress = GetProgressInstance(methodDescriptor, value => SendProgressUpdate(hub.Context.ConnectionId, tracker, value, hubRequest)); Task <object> piplineInvocation; try { var args = _binder.ResolveMethodParameters(methodDescriptor, parameterValues); // We need to add the IProgress<T> instance after resolving the method as the resolution // itself looks for overload matches based on the incoming arg values if (progress != null) { args = args.Concat(new [] { progress }).ToList(); } var context = new HubInvokerContext(hub, tracker, methodDescriptor, args); // Invoke the pipeline and save the task piplineInvocation = _pipelineInvoker.Invoke(context); } catch (Exception ex) { piplineInvocation = TaskAsyncHelper.FromError <object>(ex); } // Determine if we have a faulted task or not and handle it appropriately. return(piplineInvocation.ContinueWithPreservedCulture(task => { if (progress != null) { // Stop ability to send any more progress updates progress.SetComplete(); } if (task.IsFaulted) { return ProcessResponse(tracker, result: null, request: hubRequest, error: task.Exception); } else if (task.IsCanceled) { return ProcessResponse(tracker, result: null, request: hubRequest, error: new OperationCanceledException()); } else { return ProcessResponse(tracker, task.Result, hubRequest, error: null); } }) .FastUnwrap()); }
/// <summary> /// Initializes a new instance of the <see cref="HubConnectionContext"/>. /// </summary> /// <param name="pipelineInvoker">The pipeline invoker.</param> /// <param name="connection">The connection.</param> /// <param name="hubName">The hub name.</param> /// <param name="connectionId">The connection id.</param> /// <param name="tracker">The connection hub state.</param> public HubConnectionContext(IHubPipelineInvoker pipelineInvoker, IConnection connection, string hubName, string connectionId, StateChangeTracker tracker) { _send = (signal, invocation, exclude) => pipelineInvoker.Send(new HubOutgoingInvokerContext(connection, signal, invocation, exclude)); _connectionId = connectionId; _hubName = hubName; Caller = new StatefulSignalProxy(_send, connectionId, PrefixHelper.HubConnectionIdPrefix, hubName, tracker); All = AllExcept(); Others = AllExcept(connectionId); }
private Task SendProgressUpdate(string connectionId, StateChangeTracker tracker, object value, HubRequest request) { var hubResult = new HubResponse { State = tracker.GetChanges(), Progress = new { I = request.Id, D = value }, // We prefix the ID here to ensure old clients treat this as a hub response // but fail to lookup a corresponding callback and thus no-op Id = "P|" + request.Id, }; return(Connection.Send(connectionId, hubResult)); }
/// <summary> /// Processes the hub's incoming method calls. /// </summary> protected override Task OnReceivedAsync(IRequest request, string connectionId, string data) { HubRequest hubRequest = _requestParser.Parse(data); // Create the hub HubDescriptor descriptor = _manager.EnsureHub(hubRequest.Hub, _counters.ErrorsHubInvocationTotal, _counters.ErrorsHubInvocationPerSec, _counters.ErrorsAllTotal, _counters.ErrorsAllPerSec); IJsonValue[] parameterValues = hubRequest.ParameterValues; // Resolve the method MethodDescriptor methodDescriptor = _manager.GetHubMethod(descriptor.Name, hubRequest.Method, parameterValues); if (methodDescriptor == null) { _counters.ErrorsHubInvocationTotal.Increment(); _counters.ErrorsHubInvocationPerSec.Increment(); // Empty (noop) method descriptor // Use: Forces the hub pipeline module to throw an error. This error is encapsulated in the HubDispatcher. // Encapsulating it in the HubDispatcher prevents the error from bubbling up to the transport level. // Specifically this allows us to return a faulted task (call .fail on client) and to not cause the // transport to unintentionally fail. methodDescriptor = new MethodDescriptor { Invoker = (emptyHub, emptyParameters) => { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_MethodCouldNotBeResolved, hubRequest.Method)); }, Attributes = new List <Attribute>(), Parameters = new List <ParameterDescriptor>() }; } // Resolving the actual state object var tracker = new StateChangeTracker(hubRequest.State); var hub = CreateHub(request, descriptor, connectionId, tracker, throwIfFailedToCreate: true); return(InvokeHubPipeline(hub, parameterValues, methodDescriptor, hubRequest, tracker) .ContinueWith(task => hub.Dispose(), TaskContinuationOptions.ExecuteSynchronously)); }
public TestableLoadHub() { const string connectionId = "1234"; const string hubName = "LoadHub"; var resolver = new DefaultDependencyResolver(); Config = resolver.Resolve<IConfigurationManager>(); var mockConnection = new Mock<IConnection>(); var mockUser = new Mock<IPrincipal>(); var mockHubPipelineInvoker = new Mock<IHubPipelineInvoker>(); var mockRequest = new Mock<IRequest>(); mockRequest.Setup(r => r.User).Returns(mockUser.Object); var tracker = new StateChangeTracker(); Clients = new HubConnectionContext(mockHubPipelineInvoker.Object, mockConnection.Object, hubName, connectionId, tracker); Context = new HubCallerContext(mockRequest.Object, connectionId); }
private Task ProcessResponse(StateChangeTracker tracker, object result, HubRequest request, Exception error) { var hubResult = new HubResponse { State = tracker.GetChanges(), Result = result, Id = request.Id, }; if (error != null) { _counters.ErrorsHubInvocationTotal.Increment(); _counters.ErrorsHubInvocationPerSec.Increment(); _counters.ErrorsAllTotal.Increment(); _counters.ErrorsAllPerSec.Increment(); var hubError = error.InnerException as HubException; if (_enableDetailedErrors || hubError != null) { var exception = error.InnerException ?? error; hubResult.StackTrace = _isDebuggingEnabled ? exception.StackTrace : null; hubResult.Error = exception.Message; if (hubError != null) { hubResult.IsHubException = true; hubResult.ErrorData = hubError.ErrorData; } } else { hubResult.Error = String.Format(CultureInfo.CurrentCulture, Resources.Error_HubInvocationFailed, request.Hub, request.Method); } } Trace.TraceVerbose("Sending hub invocation result to connection {0} using transport {1}", Transport.ConnectionId, Transport.GetType().Name); return(Transport.Send(hubResult)); }
public void CanDeserializeClientState() { var clientState = new StateChangeTracker(); string clientId = "1"; var user = new ChatUser { Id = "1234", Name = "John", Identity = "foo" }; var cookies = new NameValueCollection(); cookies["jabbr.state"] = JsonConvert.SerializeObject(new ClientState { UserId = user.Id }); TestableChat chat = GetTestableChat(clientId, clientState, user, cookies); bool result = chat.Join(); Assert.Equal("1234", clientState["id"]); Assert.Equal("John", clientState["name"]); Assert.True(result); }
private Task InvokeHubPipeline(IHub hub, IJsonValue[] parameterValues, MethodDescriptor methodDescriptor, HubRequest hubRequest, StateChangeTracker tracker) { Task <object> piplineInvocation; try { var args = _binder.ResolveMethodParameters(methodDescriptor, parameterValues); var context = new HubInvokerContext(hub, tracker, methodDescriptor, args); // Invoke the pipeline and save the task piplineInvocation = _pipelineInvoker.Invoke(context); } catch (Exception ex) { piplineInvocation = TaskAsyncHelper.FromError <object>(ex); } // Determine if we have a faulted task or not and handle it appropriately. return(piplineInvocation.ContinueWith(task => { if (task.IsFaulted) { return ProcessResponse(tracker, result: null, request: hubRequest, error: task.Exception); } else if (task.IsCanceled) { return ProcessResponse(tracker, result: null, request: hubRequest, error: new OperationCanceledException()); } else { return ProcessResponse(tracker, task.Result, hubRequest, error: null); } }) .FastUnwrap()); }
public StatefulSignalProxy(IConnection connection, IHubPipelineInvoker invoker, string signal, string hubName, string prefix, StateChangeTracker tracker) : base(connection, invoker, signal, prefix, hubName, ListHelper <string> .Empty) { _tracker = tracker; }
private IHub CreateHub(IRequest request, HubDescriptor descriptor, string connectionId, StateChangeTracker tracker = null, bool throwIfFailedToCreate = false) { try { var hub = _manager.ResolveHub(descriptor.Name); if (hub != null) { tracker = tracker ?? new StateChangeTracker(); hub.Context = new HubCallerContext(request, connectionId); hub.Clients = new HubConnectionContext(_pipelineInvoker, Connection, descriptor.Name, connectionId, tracker); hub.Groups = new GroupManager(Connection, PrefixHelper.GetHubGroupName(descriptor.Name)); } return(hub); } catch (Exception ex) { Trace.TraceInformation(String.Format(CultureInfo.CurrentCulture, Resources.Error_ErrorCreatingHub + ex.Message, descriptor.Name)); if (throwIfFailedToCreate) { throw; } return(null); } }
public void MissingUsernameReturnsFalse() { var clientState = new StateChangeTracker(); string clientId = "1"; var user = new ChatUser(); TestableChat chat = GetTestableChat(clientId, clientState, user); bool result = chat.Join(); Assert.False(result); }
public static TestableChat GetTestableChat(string clientId, StateChangeTracker clientState, ChatUser user) { return GetTestableChat(clientId, clientState, user, new NameValueCollection()); }
public static TestableChat GetTestableChat(string clientId, StateChangeTracker clientState, ChatUser user) { return GetTestableChat(clientId, clientState, user, new Dictionary<string, Cookie>()); }
public StatefulSignalProxy(IConnection connection, IHubPipelineInvoker invoker, string signal, string hubName, string prefix, StateChangeTracker tracker) : base(connection, invoker, signal, prefix, hubName, ListHelper<string>.Empty) { _tracker = tracker; }
public StatefulSignalProxy(Func<string, ClientHubInvocation, IList<string>, Task> send, string signal, string hubName, string prefix, StateChangeTracker tracker) : base(send, signal, prefix, hubName, ListHelper<string>.Empty) { _tracker = tracker; }
public void CannotJoinChat() { var clientState = new StateChangeTracker(); string clientId = "1"; var user = new ChatUser { Id = "1234", Name = "John" }; TestableChat chat = GetTestableChat(clientId, clientState, user); chat.Clients.Caller.id = "1234"; bool result = chat.Join(); Assert.False(result); }
/// <summary> /// Initializes a new instance of the <see cref="HubConnectionContext"/>. /// </summary> /// <param name="pipelineInvoker">The pipeline invoker.</param> /// <param name="connection">The connection.</param> /// <param name="hubName">The hub name.</param> /// <param name="connectionId">The connection id.</param> /// <param name="tracker">The connection hub state.</param> public HubConnectionContext(IHubPipelineInvoker pipelineInvoker, IConnection connection, string hubName, string connectionId, StateChangeTracker tracker) : base(connection, pipelineInvoker, hubName) { _connectionId = connectionId; Caller = new StatefulSignalProxy(connection, pipelineInvoker, connectionId, PrefixHelper.HubConnectionIdPrefix, hubName, tracker); CallerState = new CallerStateProxy(tracker); All = AllExcept(); Others = AllExcept(connectionId); }
public StatefulSignalProxy(Func <string, ClientHubInvocation, IEnumerable <string>, Task> send, string signal, string hubName, StateChangeTracker tracker) : base(send, signal, hubName) { _tracker = tracker; }
public CallerStateProxy(StateChangeTracker tracker) { _tracker = tracker; }
public void CanJoinChatIfIdentitySet() { var clientState = new StateChangeTracker(); string clientId = "1"; var user = new ChatUser { Id = "1234", Name = "John", Identity = "foo" }; TestableChat chat = GetTestableChat(clientId, clientState, user); chat.Clients.Caller.id = "1234"; bool result = chat.Join(); Assert.Equal("1234", clientState["id"]); Assert.Equal("John", clientState["name"]); Assert.True(result); // TODO: find out why these don't work //Assert.Equal(1, user.ConnectedClients.Count); //Assert.Equal("1", user.ConnectedClients.First().Id); }
public StatefulSignalProxy(Func <string, ClientHubInvocation, IList <string>, Task> send, string signal, string hubName, string prefix, StateChangeTracker tracker) : base(send, signal, prefix, hubName, ListHelper <string> .Empty) { _tracker = tracker; }
private TestableLobby GetHub( string connectionId, StateChangeTracker clientState = null, IDictionary<string, Cookie> cookies = null, Mock<IGroupManager> groupManager = null, Mock<IGameHandler> gameHandler = null, Mock<IRegistrationHandler> registrationHandler = null, Mock<IUserHandler> userHandler = null, Mock<IMappingHandler> mappingHandler = null, Mock<IScenarioHandler> scenarioHandler = null ) { clientState = clientState ?? new StateChangeTracker(); cookies = cookies ?? new Dictionary<string, Cookie>(); var lobby = new TestableLobby( gameHandler ?? new Mock<IGameHandler>(), registrationHandler ?? new Mock<IRegistrationHandler>(), userHandler ?? new Mock<IUserHandler>(), mappingHandler ?? new Mock<IMappingHandler>(), scenarioHandler ?? new Mock<IScenarioHandler>() ); lobby.Clients = new HubConnectionContext( new Mock<IHubPipelineInvoker>().Object, new Mock<IConnection>().Object, "Lobby", connectionId, clientState ); var request = new Mock<IRequest>(); request.Setup( a => a.Cookies ).Returns( cookies ); lobby.Context = new HubCallerContext( request.Object, connectionId ); lobby.Groups = ( groupManager ?? new Mock<IGroupManager>() ).Object; return lobby; }