/// <summary> /// Handles all requests for <see cref="PersistentConnection"/>s. /// </summary> /// <param name="context">The <see cref="HostContext"/> for the current request.</param> /// <returns>A <see cref="Task"/> that completes when the <see cref="PersistentConnection"/> pipeline is complete.</returns> /// <exception cref="T:System.InvalidOperationException"> /// Thrown if connection wasn't initialized. /// Thrown if the transport wasn't specified. /// Thrown if the connection id wasn't specified. /// </exception> public virtual Task ProcessRequest(HostContext context) { if (context == null) { throw new ArgumentNullException("context"); } if (!_initialized) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ConnectionNotInitialized)); } if (IsNegotiationRequest(context.Request)) { return ProcessNegotiationRequest(context); } else if (IsPingRequest(context.Request)) { return ProcessPingRequest(context); } Transport = GetTransport(context); if (Transport == null) { return FailResponse(context.Response, String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorUnknownTransport)); } string connectionToken = context.Request.QueryString["connectionToken"]; // If there's no connection id then this is a bad request if (String.IsNullOrEmpty(connectionToken)) { return FailResponse(context.Response, String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorMissingConnectionToken)); } string connectionId; string message; int statusCode; if (!TryGetConnectionId(context, connectionToken, out connectionId, out message, out statusCode)) { return FailResponse(context.Response, message, statusCode); } // Set the transport's connection id to the unprotected one Transport.ConnectionId = connectionId; // Get the user id from the request string userId = UserIdProvider.GetUserId(context.Request); IList<string> signals = GetSignals(userId, connectionId); IList<string> groups = AppendGroupPrefixes(context, connectionId); Connection connection = CreateConnection(connectionId, signals, groups); Connection = connection; string groupName = PrefixHelper.GetPersistentConnectionGroupName(DefaultSignalRaw); Groups = new GroupManager(connection, groupName); // We handle /start requests after the PersistentConnection has been initialized, // because ProcessStartRequest calls OnConnected. if (IsStartRequest(context.Request)) { return ProcessStartRequest(context, connectionId); } Transport.Connected = () => { return TaskAsyncHelper.FromMethod(() => OnConnected(context.Request, connectionId).OrEmpty()); }; Transport.Reconnected = () => { return TaskAsyncHelper.FromMethod(() => OnReconnected(context.Request, connectionId).OrEmpty()); }; Transport.Received = data => { Counters.ConnectionMessagesSentTotal.Increment(); Counters.ConnectionMessagesSentPerSec.Increment(); return TaskAsyncHelper.FromMethod(() => OnReceived(context.Request, connectionId, data).OrEmpty()); }; Transport.Disconnected = async clean => { await OnDisconnected(context.Request, connectionId, stopCalled: clean).OrEmpty(); if (clean) { // Only call the old OnDisconnected method for disconnects we know // have *not* been caused by clients switching servers. await OnDisconnected(context.Request, connectionId).OrEmpty(); } }; return Transport.ProcessRequest(connection).OrEmpty().Catch(Counters.ErrorsAllTotal, Counters.ErrorsAllPerSec); }
/// <summary> /// Handles all requests for <see cref="PersistentConnection"/>s. /// </summary> /// <param name="context">The <see cref="HostContext"/> for the current request.</param> /// <returns>A <see cref="Task"/> that completes when the <see cref="PersistentConnection"/> pipeline is complete.</returns> /// <exception cref="T:System.InvalidOperationException"> /// Thrown if connection wasn't initialized. /// Thrown if the transport wasn't specified. /// Thrown if the connection id wasn't specified. /// </exception> public virtual Task ProcessRequestAsync(HostContext context) { if (!_initialized) { throw new InvalidOperationException("Connection not initialized."); } if (IsNegotiationRequest(context.Request)) { return(ProcessNegotiationRequest(context)); } _transport = GetTransport(context); if (_transport == null) { throw new InvalidOperationException("Protocol error: Unknown transport."); } string connectionId = _transport.ConnectionId; // If there's no connection id then this is a bad request if (String.IsNullOrEmpty(connectionId)) { throw new InvalidOperationException("Protocol error: Missing connection id."); } IEnumerable <string> signals = GetSignals(connectionId); IEnumerable <string> groups = OnRejoiningGroups(context.Request, _transport.Groups, connectionId); Connection connection = CreateConnection(connectionId, signals, groups); Connection = connection; Groups = new GroupManager(connection, DefaultSignal); _transport.TransportConnected = () => { var command = new ServerCommand { Type = ServerCommandType.RemoveConnection, Value = connectionId }; return(_serverMessageHandler.SendCommand(command)); }; _transport.Connected = () => { return(OnConnectedAsync(context.Request, connectionId).OrEmpty()); }; _transport.Reconnected = () => { return(OnReconnectedAsync(context.Request, connectionId).OrEmpty()); }; _transport.Received = data => { return(OnReceivedAsync(context.Request, connectionId, data).OrEmpty()); }; _transport.Disconnected = () => { return(OnDisconnectAsync(context.Request, connectionId).OrEmpty()); }; return(_transport.ProcessRequest(connection).OrEmpty().Catch(_counters.ErrorsAllTotal, _counters.ErrorsAllPerSec)); }
/// <summary> /// Handles all requests for <see cref="PersistentConnection"/>s. /// </summary> /// <param name="context">The <see cref="HostContext"/> for the current request.</param> /// <returns>A <see cref="Task"/> that completes when the <see cref="PersistentConnection"/> pipeline is complete.</returns> /// <exception cref="T:System.InvalidOperationException"> /// Thrown if connection wasn't initialized. /// Thrown if the transport wasn't specified. /// Thrown if the connection id wasn't specified. /// </exception> public virtual Task ProcessRequest(HostContext context) { if (context == null) { throw new ArgumentNullException("context"); } if (!_initialized) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ConnectionNotInitialized)); } if (IsNegotiationRequest(context.Request)) { return ProcessNegotiationRequest(context); } else if (IsPingRequest(context.Request)) { return ProcessPingRequest(context); } Transport = GetTransport(context); if (Transport == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorUnknownTransport)); } string connectionToken = context.Request.QueryString["connectionToken"]; // If there's no connection id then this is a bad request if (String.IsNullOrEmpty(connectionToken)) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorMissingConnectionToken)); } string connectionId = GetConnectionId(context, connectionToken); // Set the transport's connection id to the unprotected one Transport.ConnectionId = connectionId; IList<string> signals = GetSignals(connectionId); IList<string> groups = AppendGroupPrefixes(context, connectionId); Connection connection = CreateConnection(connectionId, signals, groups); Connection = connection; string groupName = PrefixHelper.GetPersistentConnectionGroupName(DefaultSignalRaw); Groups = new GroupManager(connection, groupName); Transport.TransportConnected = () => { var command = new ServerCommand { ServerCommandType = ServerCommandType.RemoveConnection, Value = connectionId }; return _serverMessageHandler.SendCommand(command); }; Transport.Connected = () => { return TaskAsyncHelper.FromMethod(() => OnConnected(context.Request, connectionId).OrEmpty()); }; Transport.Reconnected = () => { return TaskAsyncHelper.FromMethod(() => OnReconnected(context.Request, connectionId).OrEmpty()); }; Transport.Received = data => { Counters.ConnectionMessagesSentTotal.Increment(); Counters.ConnectionMessagesSentPerSec.Increment(); return TaskAsyncHelper.FromMethod(() => OnReceived(context.Request, connectionId, data).OrEmpty()); }; Transport.Disconnected = () => { return TaskAsyncHelper.FromMethod(() => OnDisconnected(context.Request, connectionId).OrEmpty()); }; return Transport.ProcessRequest(connection).OrEmpty().Catch(Counters.ErrorsAllTotal, Counters.ErrorsAllPerSec); }
/// <summary> /// Handles all requests for <see cref="PersistentConnection"/>s. /// </summary> /// <param name="context">The <see cref="HttpContext"/> for the current request.</param> /// <returns>A <see cref="Task"/> that completes when the <see cref="PersistentConnection"/> pipeline is complete.</returns> /// <exception cref="T:System.InvalidOperationException"> /// Thrown if the transport wasn't specified. /// Thrown if the connection id wasn't specified. /// </exception> public virtual async Task ProcessRequestCore(HttpContext context) { if (context == null) { throw new ArgumentNullException("context"); } if (IsNegotiationRequest(context.Request)) { await ProcessNegotiationRequest(context).PreserveCulture(); return; } else if (IsPingRequest(context.Request)) { await ProcessPingRequest(context).PreserveCulture(); return; } Transport = GetTransport(context); if (Transport == null) { await FailResponse(context.Response, String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorUnknownTransport)).PreserveCulture(); return; } string connectionToken = context.Request.Query["connectionToken"]; // If there's no connection id then this is a bad request if (String.IsNullOrEmpty(connectionToken)) { await FailResponse(context.Response, String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorMissingConnectionToken)).PreserveCulture(); return; } string connectionId; string message; int statusCode; if (!TryGetConnectionId(context, connectionToken, out connectionId, out message, out statusCode)) { await FailResponse(context.Response, message, statusCode).PreserveCulture(); return; } // Set the transport's connection id to the unprotected one Transport.ConnectionId = connectionId; // Get the user id from the request string userId = UserIdProvider.GetUserId(context.Request); // Get the groups oken from the request string groupsToken = await Transport.GetGroupsToken().PreserveCulture(); IList <string> signals = GetSignals(userId, connectionId); IList <string> groups = AppendGroupPrefixes(context, connectionId, groupsToken); Connection connection = CreateConnection(connectionId, signals, groups); Connection = connection; string groupName = PrefixHelper.GetPersistentConnectionGroupName(DefaultSignalRaw); Groups = new GroupManager(connection, groupName); // We handle /start requests after the PersistentConnection has been initialized, // because ProcessStartRequest calls OnConnected. if (IsStartRequest(context.Request)) { await ProcessStartRequest(context, connectionId).PreserveCulture(); return; } Transport.Connected = () => { return(TaskAsyncHelper.FromMethod(() => OnConnected(context.Request, connectionId).OrEmpty())); }; Transport.Reconnected = () => { return(TaskAsyncHelper.FromMethod(() => OnReconnected(context.Request, connectionId).OrEmpty())); }; Transport.Received = data => { Counters.ConnectionMessagesSentTotal.Increment(); Counters.ConnectionMessagesSentPerSec.Increment(); return(TaskAsyncHelper.FromMethod(() => OnReceived(context.Request, connectionId, data).OrEmpty())); }; Transport.Disconnected = async clean => { await OnDisconnected(context.Request, connectionId, stopCalled : clean).OrEmpty().PreserveCulture(); if (clean) { // Only call the old OnDisconnected method for disconnects we know // have *not* been caused by clients switching servers. await OnDisconnected(context.Request, connectionId).OrEmpty().PreserveCulture(); } }; await Transport.ProcessRequest(connection).OrEmpty().Catch(Counters.ErrorsAllTotal, Counters.ErrorsAllPerSec).PreserveCulture(); }
/// <summary> /// Handles all requests for <see cref="PersistentConnection"/>s. /// </summary> /// <param name="context">The <see cref="HostContext"/> for the current request.</param> /// <returns>A <see cref="Task"/> that completes when the <see cref="PersistentConnection"/> pipeline is complete.</returns> /// <exception cref="T:System.InvalidOperationException"> /// Thrown if connection wasn't initialized. /// Thrown if the transport wasn't specified. /// Thrown if the connection id wasn't specified. /// </exception> public virtual Task ProcessRequest(HostContext context) { if (context == null) { throw new ArgumentNullException("context"); } if (!_initialized) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ConnectionNotInitialized)); } if (IsNegotiationRequest(context.Request)) { return(ProcessNegotiationRequest(context)); } else if (IsPingRequest(context.Request)) { return(ProcessPingRequest(context)); } Transport = GetTransport(context); if (Transport == null) { return(FailResponse(context.Response, String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorUnknownTransport))); } string connectionToken = context.Request.QueryString["connectionToken"]; // If there's no connection id then this is a bad request if (String.IsNullOrEmpty(connectionToken)) { return(FailResponse(context.Response, String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorMissingConnectionToken))); } string connectionId; string message; int statusCode; if (!TryGetConnectionId(context, connectionToken, out connectionId, out message, out statusCode)) { return(FailResponse(context.Response, message, statusCode)); } // Set the transport's connection id to the unprotected one Transport.ConnectionId = connectionId; IList <string> signals = GetSignals(connectionId); IList <string> groups = AppendGroupPrefixes(context, connectionId); Connection connection = CreateConnection(connectionId, signals, groups); Connection = connection; string groupName = PrefixHelper.GetPersistentConnectionGroupName(DefaultSignalRaw); Groups = new GroupManager(connection, groupName); Transport.TransportConnected = () => { var command = new ServerCommand { ServerCommandType = ServerCommandType.RemoveConnection, Value = connectionId }; return(_serverMessageHandler.SendCommand(command)); }; Transport.Connected = () => { return(TaskAsyncHelper.FromMethod(() => OnConnected(context.Request, connectionId).OrEmpty())); }; Transport.Reconnected = () => { return(TaskAsyncHelper.FromMethod(() => OnReconnected(context.Request, connectionId).OrEmpty())); }; Transport.Received = data => { Counters.ConnectionMessagesSentTotal.Increment(); Counters.ConnectionMessagesSentPerSec.Increment(); return(TaskAsyncHelper.FromMethod(() => OnReceived(context.Request, connectionId, data).OrEmpty())); }; Transport.Disconnected = () => { return(TaskAsyncHelper.FromMethod(() => OnDisconnected(context.Request, connectionId).OrEmpty())); }; return(Transport.ProcessRequest(connection).OrEmpty().Catch(Counters.ErrorsAllTotal, Counters.ErrorsAllPerSec)); }
/// <summary> /// Handles all requests for <see cref="PersistentConnection"/>s. /// </summary> /// <param name="context">The <see cref="HostContext"/> for the current request.</param> /// <returns>A <see cref="Task"/> that completes when the <see cref="PersistentConnection"/> pipeline is complete.</returns> /// <exception cref="T:System.InvalidOperationException"> /// Thrown if connection wasn't initialized. /// Thrown if the transport wasn't specified. /// Thrown if the connection id wasn't specified. /// </exception> public virtual Task ProcessRequestAsync(HostContext context) { if (!_initialized) { throw new InvalidOperationException("Connection not initialized."); } if (IsNegotiationRequest(context.Request)) { return ProcessNegotiationRequest(context); } _transport = GetTransport(context); if (_transport == null) { throw new InvalidOperationException("Protocol error: Unknown transport."); } string connectionId = _transport.ConnectionId; // If there's no connection id then this is a bad request if (String.IsNullOrEmpty(connectionId)) { throw new InvalidOperationException("Protocol error: Missing connection id."); } IEnumerable<string> signals = GetSignals(connectionId); IEnumerable<string> groups = OnRejoiningGroups(context.Request, _transport.Groups, connectionId); Connection connection = CreateConnection(connectionId, signals, groups); Connection = connection; Groups = new GroupManager(connection, DefaultSignal); _transport.TransportConnected = () => { var command = new ServerCommand { Type = ServerCommandType.RemoveConnection, Value = connectionId }; return _serverMessageHandler.SendCommand(command); }; _transport.Connected = () => { return OnConnectedAsync(context.Request, connectionId).OrEmpty(); }; _transport.Reconnected = () => { return OnReconnectedAsync(context.Request, connectionId).OrEmpty(); }; _transport.Received = data => { return OnReceivedAsync(context.Request, connectionId, data).OrEmpty(); }; _transport.Disconnected = () => { return OnDisconnectAsync(context.Request, connectionId).OrEmpty(); }; return _transport.ProcessRequest(connection).OrEmpty().Catch(_counters.ErrorsAllTotal, _counters.ErrorsAllPerSec); }
/// <summary> /// Handles all requests for <see cref="PersistentConnection"/>s. /// </summary> /// <param name="context">The <see cref="HostContext"/> for the current request.</param> /// <returns>A <see cref="Task"/> that completes when the <see cref="PersistentConnection"/> pipeline is complete.</returns> /// <exception cref="T:System.InvalidOperationException"> /// Thrown if connection wasn't initialized. /// Thrown if the transport wasn't specified. /// Thrown if the connection id wasn't specified. /// </exception> public virtual Task ProcessRequestAsync(HostContext context) { if (context == null) { throw new ArgumentNullException("context"); } if (!_initialized) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ConnectionNotInitialized)); } if (IsNegotiationRequest(context.Request)) { return ProcessNegotiationRequest(context); } Transport = GetTransport(context); if (Transport == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorUnknownTransport)); } string connectionId = Transport.ConnectionId; // If there's no connection id then this is a bad request if (String.IsNullOrEmpty(connectionId)) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorMissingConnectionId)); } IEnumerable<string> signals = GetSignals(connectionId); IEnumerable<string> groups = OnRejoiningGroups(context.Request, Transport.Groups, connectionId); Connection connection = CreateConnection(connectionId, signals, groups); Connection = connection; Groups = new GroupManager(connection, DefaultSignal); Transport.TransportConnected = () => { var command = new ServerCommand { ServerCommandType = ServerCommandType.RemoveConnection, Value = connectionId }; return _serverMessageHandler.SendCommand(command); }; Transport.Connected = () => { return OnConnectedAsync(context.Request, connectionId).OrEmpty(); }; Transport.Reconnected = () => { return OnReconnectedAsync(context.Request, connectionId).OrEmpty(); }; Transport.Received = data => { Counters.ConnectionMessagesSentTotal.Increment(); Counters.ConnectionMessagesSentPerSec.Increment(); return OnReceivedAsync(context.Request, connectionId, data).OrEmpty(); }; Transport.Disconnected = () => { return OnDisconnectAsync(context.Request, connectionId).OrEmpty(); }; return Transport.ProcessRequest(connection).OrEmpty().Catch(Counters.ErrorsAllTotal, Counters.ErrorsAllPerSec); }
/// <summary> /// Handles all requests for <see cref="PersistentConnection"/>s. /// </summary> /// <param name="context">The <see cref="HostContext"/> for the current request.</param> /// <returns>A <see cref="Task"/> that completes when the <see cref="PersistentConnection"/> pipeline is complete.</returns> /// <exception cref="T:System.InvalidOperationException"> /// Thrown if connection wasn't initialized. /// Thrown if the transport wasn't specified. /// Thrown if the connection id wasn't specified. /// </exception> public virtual Task ProcessRequestAsync(HostContext context) { if (context == null) { throw new ArgumentNullException("context"); } if (!_initialized) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ConnectionNotInitialized)); } if (IsNegotiationRequest(context.Request)) { return(ProcessNegotiationRequest(context)); } Transport = GetTransport(context); if (Transport == null) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorUnknownTransport)); } string connectionId = Transport.ConnectionId; // If there's no connection id then this is a bad request if (String.IsNullOrEmpty(connectionId)) { throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_ProtocolErrorMissingConnectionId)); } IEnumerable <string> signals = GetSignals(connectionId); IEnumerable <string> groups = OnRejoiningGroups(context.Request, Transport.Groups, connectionId); Connection connection = CreateConnection(connectionId, signals, groups); Connection = connection; Groups = new GroupManager(connection, DefaultSignal); Transport.TransportConnected = () => { var command = new ServerCommand { ServerCommandType = ServerCommandType.RemoveConnection, Value = connectionId }; return(_serverMessageHandler.SendCommand(command)); }; Transport.Connected = () => { return(TaskAsyncHelper.FromMethod(() => OnConnectedAsync(context.Request, connectionId).OrEmpty())); }; Transport.Reconnected = () => { return(TaskAsyncHelper.FromMethod(() => OnReconnectedAsync(context.Request, connectionId).OrEmpty())); }; Transport.Received = data => { Counters.ConnectionMessagesSentTotal.Increment(); Counters.ConnectionMessagesSentPerSec.Increment(); return(TaskAsyncHelper.FromMethod(() => OnReceivedAsync(context.Request, connectionId, data).OrEmpty())); }; Transport.Disconnected = () => { return(TaskAsyncHelper.FromMethod(() => OnDisconnectAsync(context.Request, connectionId).OrEmpty())); }; return(Transport.ProcessRequest(connection).OrEmpty().Catch(Counters.ErrorsAllTotal, Counters.ErrorsAllPerSec)); }
private Task ProcessRequestPostGroupRead(HostContext context, string groupsToken) { string connectionId = Transport.ConnectionId; // Get the user id from the request string userId = UserIdProvider.GetUserId(context.Request); IList<string> signals = GetSignals(userId, connectionId); IList<string> groups = AppendGroupPrefixes(context, connectionId, groupsToken); Connection connection = CreateConnection(connectionId, signals, groups); Connection = connection; string groupName = PrefixHelper.GetPersistentConnectionGroupName(DefaultSignalRaw); Groups = new GroupManager(connection, groupName); // We handle /start requests after the PersistentConnection has been initialized, // because ProcessStartRequest calls OnConnected. if (IsStartRequest(context.Request)) { return ProcessStartRequest(context, connectionId); } Transport.Connected = () => { return TaskAsyncHelper.FromMethod(() => OnConnected(context.Request, connectionId).OrEmpty()); }; Transport.Reconnected = () => { return TaskAsyncHelper.FromMethod(() => OnReconnected(context.Request, connectionId).OrEmpty()); }; Transport.Received = data => { Counters.ConnectionMessagesSentTotal.Increment(); Counters.ConnectionMessagesSentPerSec.Increment(); return TaskAsyncHelper.FromMethod(() => OnReceived(context.Request, connectionId, data).OrEmpty()); }; Transport.Disconnected = clean => { return TaskAsyncHelper.FromMethod(() => OnDisconnected(context.Request, connectionId, stopCalled: clean).OrEmpty()); }; return Transport.ProcessRequest(connection).OrEmpty().Catch(Trace, Counters.ErrorsAllTotal, Counters.ErrorsAllPerSec); }