Example #1
0
        public virtual void Initialize(IDependencyResolver resolver, HostContext context)
        {
            if (_initialized)
            {
                return;
            }

            _newMessageBus = resolver.Resolve<IMessageBus>();
            _configurationManager = resolver.Resolve<IConfigurationManager>();
            _connectionIdPrefixGenerator = resolver.Resolve<IConnectionIdPrefixGenerator>();
            _jsonSerializer = resolver.Resolve<IJsonSerializer>();
            _transportManager = resolver.Resolve<ITransportManager>();
            _trace = resolver.Resolve<ITraceManager>();
            _serverMessageHandler = resolver.Resolve<IServerCommandHandler>();
            _counters = resolver.Resolve<IPerformanceCounterManager>();
            _ackHandler = resolver.Resolve<IAckHandler>();

            _initialized = true;
        }
Example #2
0
        private Task ProcessJsonpNegotiationRequest(HostContext context, object payload)
        {
            context.Response.ContentType = Json.JsonpMimeType;
            var data = Json.CreateJsonpCallback(context.Request.QueryString["callback"], _jsonSerializer.Stringify(payload));

            return context.Response.EndAsync(data);
        }
Example #3
0
        private Task ProcessNegotiationRequest(HostContext context)
        {
            var keepAlive = _configurationManager.KeepAlive;
            var payload = new
            {
                Url = context.Request.Url.LocalPath.Replace("/negotiate", ""),
                ConnectionId = _connectionIdPrefixGenerator.GenerateConnectionIdPrefix(context.Request) + Guid.NewGuid().ToString("d"),
                KeepAlive = (keepAlive != null) ? keepAlive.Value.TotalSeconds : (double?)null,
                TryWebSockets = _transportManager.SupportsTransport(WebSocketsTransportName) && context.SupportsWebSockets(),
                WebSocketServerUrl = context.WebSocketServerUrl(),
                ProtocolVersion = "1.0"
            };

            if (!String.IsNullOrEmpty(context.Request.QueryString["callback"]))
            {
                return ProcessJsonpNegotiationRequest(context, payload);
            }

            context.Response.ContentType = Json.MimeType;
            return context.Response.EndAsync(_jsonSerializer.Stringify(payload));
        }
Example #4
0
        /// <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);
        }
Example #5
0
 private ITransport GetTransport(HostContext context)
 {
     return _transportManager.GetTransport(context);
 }
Example #6
0
        /// <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);
        }
Example #7
0
        public virtual void Initialize(IDependencyResolver resolver, HostContext context)
        {
            if (resolver == null)
            {
                throw new ArgumentNullException("resolver");
            }

            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (_initialized)
            {
                return;
            }

            MessageBus = resolver.Resolve<IMessageBus>();
            ConnectionIdPrefixGenerator = resolver.Resolve<IConnectionIdPrefixGenerator>();
            JsonSerializer = resolver.Resolve<IJsonSerializer>();
            TraceManager = resolver.Resolve<ITraceManager>();
            Counters = resolver.Resolve<IPerformanceCounterManager>();
            AckHandler = resolver.Resolve<IAckHandler>();

            _configurationManager = resolver.Resolve<IConfigurationManager>();
            _transportManager = resolver.Resolve<ITransportManager>();
            _serverMessageHandler = resolver.Resolve<IServerCommandHandler>();

            _initialized = true;
        }
 private ITransport GetTransport(HostContext context)
 {
     return(_transportManager.GetTransport(context));
 }
 private IList <string> AppendGroupPrefixes(HostContext context, string connectionId)
 {
     return((from g in OnRejoiningGroups(context.Request, VerifyGroups(context, connectionId), connectionId)
             select GroupPrefix + g).ToList());
 }
        /// <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));
        }