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

            _newMessageBus = resolver.Resolve<IMessageBus>();
            _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 ITransport GetTransport(HostContext context)
 {
     return _transportManager.GetTransport(context);
 }
Example #3
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.");
            }

            var groups = new List<string>(_transport.Groups);

            Connection connection = CreateConnection(connectionId, groups, context.Request);

            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);
            };

            _transport.Reconnected = () =>
            {
                return OnReconnectedAsync(context.Request, groups, connectionId);
            };

            _transport.Received = data =>
            {
                return OnReceivedAsync(context.Request, connectionId, data);
            };

            _transport.Error = OnErrorAsync;

            _transport.Disconnected = () =>
            {
                return OnDisconnectAsync(connectionId);
            };

            return _transport.ProcessRequest(connection) ?? TaskAsyncHelper.Empty;
        }
        public virtual Task ProcessRequestAsync(HostContext context)
        {
            if (IsNegotiationRequest(context.Request))
            {
                return ProcessNegotiationRequest(context);
            }

            _transport = GetTransport(context);

            if (_transport == null)
            {
                throw new InvalidOperationException("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> groups = _transport.Groups;

            Connection = CreateConnection(connectionId, groups, context.Request);

            _transport.Connected = () =>
            {
                return OnConnectedAsync(context.Request, connectionId);
            };

            _transport.Received = data =>
            {
                return OnReceivedAsync(connectionId, data);
            };

            _transport.Error = OnErrorAsync;

            _transport.Disconnected = () =>
            {
                return OnDisconnectAsync(connectionId);
            };

            return _transport.ProcessRequest(Connection) ?? TaskAsyncHelper.Empty;
        }
 private Task ProcessNegotiationRequest(HostContext context)
 {
     context.Response.ContentType = Json.MimeType;
     return context.Response.EndAsync(_jsonSerializer.Stringify(new
     {
         Url = context.Request.Url.LocalPath.Replace("/negotiate", ""),
         ConnectionId = _connectionIdFactory.CreateConnectionId(context.Request),
         TryWebSockets = context.SupportsWebSockets(),
         WebSocketServerUrl = context.WebSocketServerUrl(),
         ProtocolVersion = "1.0"
     }));
 }
        public virtual Task ProcessRequestAsync(HostContext context)
        {
            Task transportEventTask = null;

            if (IsNegotiationRequest(context.Request))
            {
                return ProcessNegotiationRequest(context);
            }

            _transport = GetTransport(context);

            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> groups = _transport.Groups;

            Connection = CreateConnection(connectionId, groups, context.Request);

            // Wire up the events we need
            _transport.Connected += () =>
            {
                transportEventTask = OnConnectedAsync(context.Request, connectionId);
            };

            _transport.Received += (data) =>
            {
                transportEventTask = OnReceivedAsync(connectionId, data);
            };

            _transport.Error += (e) =>
            {
                transportEventTask = OnErrorAsync(e);
            };

            _transport.Disconnected += () =>
            {
                transportEventTask = OnDisconnectAsync(connectionId);
            };

            Func<Task> transportProcessRequest = _transport.ProcessRequest(Connection);

            if (transportProcessRequest != null)
            {
                if (transportEventTask != null)
                {
                    return transportEventTask.Then(transportProcessRequest).FastUnwrap();
                }
                return transportProcessRequest();
            }

            return transportEventTask ?? TaskAsyncHelper.Empty;
        }
 private ITransport GetTransport(HostContext context)
 {
     return TransportManager.GetTransport(context) ??
         new LongPollingTransport(context, _jsonSerializer);
 }
Example #8
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.");
            }

            var groups = new List <string>(_transport.Groups);

            Connection connection = CreateConnection(connectionId, groups, context.Request);

            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));
            };

            _transport.Reconnected = () =>
            {
                return(OnReconnectedAsync(context.Request, groups, connectionId));
            };

            _transport.Received = data =>
            {
                return(OnReceivedAsync(context.Request, connectionId, data));
            };

            _transport.Disconnected = () =>
            {
                return(OnDisconnectAsync(connectionId));
            };

            return(_transport.ProcessRequest(connection) ?? TaskAsyncHelper.Empty);
        }
 private ITransport GetTransport(HostContext context)
 {
     return(_transportManager.GetTransport(context));
 }
        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));
        }
        /// <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 #12
0
 private ITransport GetTransport(HostContext context)
 {
     return(TransportManager.GetTransport(context) ??
            new LongPollingTransport(context, _jsonSerializer));
 }
 private Task ProcessNegotiationRequest(HostContext context)
 {
     context.Response.ContentType = Json.MimeType;
     return context.Response.WriteAsync(_jsonSerializer.Stringify(new
     {
         Url = context.Request.Path.Replace("/negotiate", ""),
         ConnectionId = _connectionIdFactory.CreateConnectionId(context.Request),
         TryWebSockets = context.SupportsWebSockets()
     }));
 }
Example #14
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 #15
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, context.Request);
            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, groups, connectionId).OrEmpty());
            };

            _transport.Received = data =>
            {
                return(OnReceivedAsync(context.Request, connectionId, data).OrEmpty());
            };

            _transport.Disconnected = () =>
            {
                return(OnDisconnectAsync(connectionId).OrEmpty());
            };

            return(_transport.ProcessRequest(connection).OrEmpty().Catch(_allErrorsTotalCounter, _allErrorsPerSecCounter));
        }
Example #16
0
        private Task ProcessNegotiationRequest(HostContext context)
        {
            var payload = new
            {
                Url = context.Request.Url.LocalPath.Replace("/negotiate", ""),
                ConnectionId = _connectionIdGenerator.GenerateConnectionId(context.Request),
                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 #17
0
        private Task ProcessRequestAsync(HttpListenerContext context)
        {
            try
            {
                Debug.WriteLine("Server: Incoming request to {0}.", context.Request.Url);

                PersistentConnection connection;

                string path = ResolvePath(context.Request.Url);

                foreach (var embeddedFileHandler in _embeddedFileHandlers)
                {
                    var result = embeddedFileHandler.Handle(path, context);
                    if (result != null)
                    {
                        return result;
                    }
                }

                if (_routingHost.TryGetConnection(path, out connection))
                {
                    // https://developer.mozilla.org/En/HTTP_Access_Control
                    string origin = context.Request.Headers["Origin"];
                    if (!String.IsNullOrEmpty(origin))
                    {
                        context.Response.AddHeader("Access-Control-Allow-Origin", origin);
                        context.Response.AddHeader("Access-Control-Allow-Credentials", "true");
                    }

                    var request = new HttpListenerRequestWrapper(context);
                    var response = new HttpListenerResponseWrapper(context.Response, _disconnectHandler.GetDisconnectToken(context));
                    var hostContext = new HostContext(request, response);

            #if NET45
                    hostContext.Items[HostConstants.SupportsWebSockets] = Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 2;
            #endif

                    if (OnProcessRequest != null)
                    {
                        OnProcessRequest(hostContext);
                    }

            #if DEBUG
                    hostContext.Items[HostConstants.DebugMode] = true;
            #endif
                    hostContext.Items["System.Net.HttpListenerContext"] = context;

                    // Initialize the connection
                    connection.Initialize(_routingHost.DependencyResolver);

                    return connection.ProcessRequestAsync(hostContext);
                }

                if (path.Equals("/clientaccesspolicy.xml", StringComparison.InvariantCultureIgnoreCase))
                {
                    using (var stream = typeof(WebAppServer).Assembly.GetManifestResourceStream(typeof(WebAppServer), "clientaccesspolicy.xml"))
                    {
                        if (stream == null)
                        {
                            var response = new HttpResponseMessage(HttpStatusCode.NotFound);
                            return context.SendResponseAsync(response);
                        }
                        var bytes = new byte[1024];
                        int byteCount = stream.Read(bytes, 0, bytes.Length);
                        return context.Response.WriteAsync(new ArraySegment<byte>(bytes, 0, byteCount));
                    }
                }

                HttpRequestMessage requestMessage = context.GetHttpRequestMessage();

                return _webApiServer.PublicSendAsync(requestMessage, _disconnectHandler.GetDisconnectToken(context))
                    .Then(response =>
                    {
                        var responseMessage = response ?? new HttpResponseMessage(HttpStatusCode.InternalServerError) { RequestMessage = requestMessage };
                        return context.SendResponseAsync(responseMessage);
                    });
            }
            catch (Exception ex)
            {
                return TaskAsyncHelper.FromError(ex);
            }
        }