diff --git a/src/Common/CodeAnalysisDictionary.xml b/src/Common/CodeAnalysisDictionary.xml
new file mode 100644
index 000000000..857f46c4e
--- /dev/null
+++ b/src/Common/CodeAnalysisDictionary.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ Ack
+ Minifier
+ Jsonp
+ Linktionary
+ Scaleout
+ Redis
+ Owin
+ Stringify
+ Unminify
+ Unminified
+ Stateful
+ SignalR
+ Hubservable
+ Sse
+ GitHub
+
+
+
\ No newline at end of file
diff --git a/src/Common/CommonAssemblyInfo.cs b/src/Common/CommonAssemblyInfo.cs
new file mode 100644
index 000000000..c245672c6
--- /dev/null
+++ b/src/Common/CommonAssemblyInfo.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyCompany("Microsoft Open Technologies, Inc.")]
+[assembly: AssemblyCopyright("© Microsoft Open Technologies, Inc. All rights reserved.")]
+
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: ComVisible(false)]
+[assembly: CLSCompliant(false)]
+
+[assembly: NeutralResourcesLanguage("en-US")]
\ No newline at end of file
diff --git a/src/Common/CommonVersionInfo.cs b/src/Common/CommonVersionInfo.cs
new file mode 100644
index 000000000..beed2ca20
--- /dev/null
+++ b/src/Common/CommonVersionInfo.cs
@@ -0,0 +1,7 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+using System.Reflection;
+
+[assembly: AssemblyVersion("1.1.0")]
+[assembly: AssemblyFileVersion("1.1.0.0")]
+[assembly: AssemblyInformationalVersion("1.1.3")]
diff --git a/src/Common/GlobalSuppressions.cs b/src/Common/GlobalSuppressions.cs
new file mode 100644
index 000000000..ec9dfe318
--- /dev/null
+++ b/src/Common/GlobalSuppressions.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Code Analysis results, point to "Suppress Message", and click
+// "In Suppression File".
+// You do not need to add suppressions to this file manually.
+
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "Strong naming is done on the CI.")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "param", Scope = "resource", Target = "Microsoft.AspNet.SignalR.Resources.resources")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly", Justification = "We use semver")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations", Scope = "member", Target = "Microsoft.AspNet.SignalR.Messaging.ScaleoutTaskQueue.#.cctor()", Justification = "The task is cached")]
diff --git a/src/Common/Microsoft.AspNet.SignalR.ruleset b/src/Common/Microsoft.AspNet.SignalR.ruleset
new file mode 100644
index 000000000..38ad3e9ec
--- /dev/null
+++ b/src/Common/Microsoft.AspNet.SignalR.ruleset
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Common/Microsoft.AspNet.SignalR.targets b/src/Common/Microsoft.AspNet.SignalR.targets
new file mode 100644
index 000000000..291b985a8
--- /dev/null
+++ b/src/Common/Microsoft.AspNet.SignalR.targets
@@ -0,0 +1,40 @@
+
+
+
+ $(ArtifactsDir)\$(MSBuildProjectName)
+ $(ArtifactsDir)\$(MSBuildProjectName)\bin
+
+
+
+ $(MSBuildThisFileDirectory)Microsoft.AspNet.SignalR.ruleset
+ false
+ 1591
+ true
+
+
+
+ $(DefineConstants);CODE_ANALYSIS
+ 11.0
+
+
+
+ $(DefineConstants);MONO
+
+
+
+ $(DefineConstants);SIGNED
+ true
+ true
+ $(KeyFile)
+
+
+
+
+ GlobalSuppressions.cs
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.SignalR.Core/AuthorizeAttribute.cs b/src/Microsoft.AspNet.SignalR.Core/AuthorizeAttribute.cs
new file mode 100644
index 000000000..82ef77896
--- /dev/null
+++ b/src/Microsoft.AspNet.SignalR.Core/AuthorizeAttribute.cs
@@ -0,0 +1,160 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Security.Principal;
+using Microsoft.AspNet.SignalR.Hubs;
+
+namespace Microsoft.AspNet.SignalR
+{
+ ///
+ /// Apply to Hubs and Hub methods to authorize client connections to Hubs and authorize client invocations of Hub methods.
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
+ [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "MVC and WebAPI don't seal their AuthorizeAttributes")]
+ public class AuthorizeAttribute : Attribute, IAuthorizeHubConnection, IAuthorizeHubMethodInvocation
+ {
+ private string _roles;
+ private string[] _rolesSplit = new string[0];
+ private string _users;
+ private string[] _usersSplit = new string[0];
+
+ [SuppressMessage("Microsoft.Design", "CA1051:DoNotDeclareVisibleInstanceFields", Justification = "Already somewhat represented by set-only RequiredOutgoing property.")]
+ protected bool? _requireOutgoing;
+
+ ///
+ /// Set to false to apply authorization only to the invocations of any of the Hub's server-side methods.
+ /// This property only affects attributes applied to the Hub class.
+ /// This property cannot be read.
+ ///
+ [SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations", Justification = "Must be property because this is an attribute parameter.")]
+ public bool RequireOutgoing
+ {
+ // It is impossible to tell here whether the attribute is being applied to a method or class. This makes
+ // it impossible to determine whether the value should be true or false when _requireOutgoing is null.
+ // It is also impossible to have a Nullable attribute parameter type.
+ get { throw new NotImplementedException(Resources.Error_DoNotReadRequireOutgoing); }
+ set { _requireOutgoing = value; }
+ }
+
+ ///
+ /// Gets or sets the user roles.
+ ///
+ public string Roles
+ {
+ get { return _roles ?? String.Empty; }
+ set
+ {
+ _roles = value;
+ _rolesSplit = SplitString(value);
+ }
+ }
+
+ ///
+ /// Gets or sets the authorized users.
+ ///
+ public string Users
+ {
+ get { return _users ?? String.Empty; }
+ set
+ {
+ _users = value;
+ _usersSplit = SplitString(value);
+ }
+ }
+
+ ///
+ /// Determines whether client is authorized to connect to .
+ ///
+ /// Description of the hub client is attempting to connect to.
+ /// The (re)connect request from the client.
+ /// true if the caller is authorized to connect to the hub; otherwise, false.
+ public virtual bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
+ {
+ if (request == null)
+ {
+ throw new ArgumentNullException("request");
+ }
+
+ // If RequireOutgoing is explicitly set to false, authorize all connections.
+ if (_requireOutgoing.HasValue && !_requireOutgoing.Value)
+ {
+ return true;
+ }
+
+ return UserAuthorized(request.User);
+ }
+
+ ///
+ /// Determines whether client is authorized to invoke the method.
+ ///
+ /// An providing details regarding the method invocation.
+ /// Indicates whether the interface instance is an attribute applied directly to a method.
+ /// true if the caller is authorized to invoke the method; otherwise, false.
+ public virtual bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
+ {
+ if (hubIncomingInvokerContext == null)
+ {
+ throw new ArgumentNullException("hubIncomingInvokerContext");
+ }
+
+ // It is impossible to require outgoing auth at the method level with SignalR's current design.
+ // Even though this isn't the stage at which outgoing auth would be applied, we want to throw a runtime error
+ // to indicate when the attribute is being used with obviously incorrect expectations.
+
+ // We must explicitly check if _requireOutgoing is true since it is a Nullable type.
+ if (appliesToMethod && (_requireOutgoing == true))
+ {
+ throw new ArgumentException(Resources.Error_MethodLevelOutgoingAuthorization);
+ }
+
+ return UserAuthorized(hubIncomingInvokerContext.Hub.Context.User);
+ }
+
+ ///
+ /// When overridden, provides an entry point for custom authorization checks.
+ /// Called by and .
+ ///
+ /// The for the client being authorize
+ /// true if the user is authorized, otherwise, false
+ protected virtual bool UserAuthorized(IPrincipal user)
+ {
+ if (user == null)
+ {
+ throw new ArgumentNullException("user");
+ }
+
+ if (!user.Identity.IsAuthenticated)
+ {
+ return false;
+ }
+
+ if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+
+ if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private static string[] SplitString(string original)
+ {
+ if (String.IsNullOrEmpty(original))
+ {
+ return new string[0];
+ }
+
+ var split = from piece in original.Split(',')
+ let trimmed = piece.Trim()
+ where !String.IsNullOrEmpty(trimmed)
+ select trimmed;
+ return split.ToArray();
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.SignalR.Core/Configuration/ConfigurationExtensions.cs b/src/Microsoft.AspNet.SignalR.Core/Configuration/ConfigurationExtensions.cs
new file mode 100644
index 000000000..630fad897
--- /dev/null
+++ b/src/Microsoft.AspNet.SignalR.Core/Configuration/ConfigurationExtensions.cs
@@ -0,0 +1,61 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+using System;
+
+namespace Microsoft.AspNet.SignalR.Configuration
+{
+ internal static class ConfigurationExtensions
+ {
+ public const int MissedTimeoutsBeforeClientReconnect = 2;
+ public const int HeartBeatsPerKeepAlive = 2;
+ public const int HeartBeatsPerDisconnectTimeout = 6;
+
+ ///
+ /// The amount of time the client should wait without seeing a keep alive before trying to reconnect.
+ ///
+ public static TimeSpan? KeepAliveTimeout(this IConfigurationManager config)
+ {
+ if (config.KeepAlive != null)
+ {
+ return TimeSpan.FromTicks(config.KeepAlive.Value.Ticks * MissedTimeoutsBeforeClientReconnect);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// The interval between successively checking connection states.
+ ///
+ public static TimeSpan HeartbeatInterval(this IConfigurationManager config)
+ {
+ if (config.KeepAlive != null)
+ {
+ return TimeSpan.FromTicks(config.KeepAlive.Value.Ticks / HeartBeatsPerKeepAlive);
+ }
+ else
+ {
+ // If KeepAlives are disabled, have the heartbeat run at the same rate it would if the KeepAlive was
+ // kept at the default value.
+ return TimeSpan.FromTicks(config.DisconnectTimeout.Ticks / HeartBeatsPerDisconnectTimeout);
+ }
+ }
+
+ ///
+ /// The amount of time a Topic should stay in memory after its last subscriber is removed.
+ ///
+ ///
+ ///
+ public static TimeSpan TopicTtl(this IConfigurationManager config)
+ {
+ // If the deep-alive is disabled, don't take it into account when calculating the topic TTL.
+ var keepAliveTimeout = config.KeepAliveTimeout() ?? TimeSpan.Zero;
+
+ // Keep topics alive for twice as long as we let connections to reconnect. (The DisconnectTimeout)
+ // Also add twice the keep-alive timeout since clients might take a while to notice they are disconnected.
+ // This should be a very conservative estimate for how long we must wait before considering a topic dead.
+ return TimeSpan.FromTicks((config.DisconnectTimeout.Ticks + keepAliveTimeout.Ticks) * 2);
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.SignalR.Core/Configuration/DefaultConfigurationManager.cs b/src/Microsoft.AspNet.SignalR.Core/Configuration/DefaultConfigurationManager.cs
new file mode 100644
index 000000000..af49f1978
--- /dev/null
+++ b/src/Microsoft.AspNet.SignalR.Core/Configuration/DefaultConfigurationManager.cs
@@ -0,0 +1,89 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+using System;
+
+namespace Microsoft.AspNet.SignalR.Configuration
+{
+ public class DefaultConfigurationManager : IConfigurationManager
+ {
+ // The below effectively sets the minimum heartbeat to once per second.
+ // if _minimumKeepAlive != 2 seconds, update the ArguementOutOfRanceExceptionMessage below
+ private static readonly TimeSpan _minimumKeepAlive = TimeSpan.FromSeconds(2);
+
+ // if _minimumKeepAlivesPerDisconnectTimeout != 3, update the ArguementOutOfRanceExceptionMessage below
+ private const int _minimumKeepAlivesPerDisconnectTimeout = 3;
+
+ // if _minimumDisconnectTimeout != 6 seconds, update the ArguementOutOfRanceExceptionMessage below
+ private static readonly TimeSpan _minimumDisconnectTimeout = TimeSpan.FromTicks(_minimumKeepAlive.Ticks * _minimumKeepAlivesPerDisconnectTimeout);
+
+ private bool _keepAliveConfigured;
+ private TimeSpan? _keepAlive;
+ private TimeSpan _disconnectTimeout;
+
+ public DefaultConfigurationManager()
+ {
+ ConnectionTimeout = TimeSpan.FromSeconds(110);
+ DisconnectTimeout = TimeSpan.FromSeconds(30);
+ DefaultMessageBufferSize = 1000;
+ }
+
+ // TODO: Should we guard against negative TimeSpans here like everywhere else?
+ public TimeSpan ConnectionTimeout
+ {
+ get;
+ set;
+ }
+
+ public TimeSpan DisconnectTimeout
+ {
+ get
+ {
+ return _disconnectTimeout;
+ }
+ set
+ {
+ if (value < _minimumDisconnectTimeout)
+ {
+ throw new ArgumentOutOfRangeException("value", Resources.Error_DisconnectTimeoutMustBeAtLeastSixSeconds);
+ }
+
+ if (_keepAliveConfigured)
+ {
+ throw new InvalidOperationException(Resources.Error_DisconnectTimeoutCannotBeConfiguredAfterKeepAlive);
+ }
+
+ _disconnectTimeout = value;
+ _keepAlive = TimeSpan.FromTicks(_disconnectTimeout.Ticks / _minimumKeepAlivesPerDisconnectTimeout);
+ }
+ }
+
+ public TimeSpan? KeepAlive
+ {
+ get
+ {
+ return _keepAlive;
+ }
+ set
+ {
+ if (value < _minimumKeepAlive)
+ {
+ throw new ArgumentOutOfRangeException("value", Resources.Error_KeepAliveMustBeGreaterThanTwoSeconds);
+ }
+
+ if (value > TimeSpan.FromTicks(_disconnectTimeout.Ticks / _minimumKeepAlivesPerDisconnectTimeout))
+ {
+ throw new ArgumentOutOfRangeException("value", Resources.Error_KeepAliveMustBeNoMoreThanAThirdOfTheDisconnectTimeout);
+ }
+
+ _keepAlive = value;
+ _keepAliveConfigured = true;
+ }
+ }
+
+ public int DefaultMessageBufferSize
+ {
+ get;
+ set;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.SignalR.Core/Configuration/IConfigurationManager.cs b/src/Microsoft.AspNet.SignalR.Core/Configuration/IConfigurationManager.cs
new file mode 100644
index 000000000..9dd79a241
--- /dev/null
+++ b/src/Microsoft.AspNet.SignalR.Core/Configuration/IConfigurationManager.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+using System;
+
+namespace Microsoft.AspNet.SignalR.Configuration
+{
+ ///
+ /// Provides access to server configuration.
+ ///
+ public interface IConfigurationManager
+ {
+ ///
+ /// Gets or sets a representing the amount of time to leave a connection open before timing out.
+ ///
+ TimeSpan ConnectionTimeout { get; set; }
+
+ ///
+ /// Gets or sets a representing the amount of time to wait after a connection goes away before raising the disconnect event.
+ ///
+ TimeSpan DisconnectTimeout { get; set; }
+
+ ///
+ /// Gets or sets a representing the amount of time between send keep alive messages.
+ /// If enabled, this value must be at least two seconds. Set to null to disable.
+ ///
+ TimeSpan? KeepAlive { get; set; }
+
+ ///
+ /// Gets of sets the number of messages to buffer for a specific signal.
+ ///
+ int DefaultMessageBufferSize { get; set; }
+ }
+}
diff --git a/src/Microsoft.AspNet.SignalR.Core/ConnectionConfiguration.cs b/src/Microsoft.AspNet.SignalR.Core/ConnectionConfiguration.cs
new file mode 100644
index 000000000..eef56241e
--- /dev/null
+++ b/src/Microsoft.AspNet.SignalR.Core/ConnectionConfiguration.cs
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+namespace Microsoft.AspNet.SignalR
+{
+ public class ConnectionConfiguration
+ {
+ // Resolver isn't set to GlobalHost.DependencyResolver in the ctor because it is lazily created.
+ private IDependencyResolver _resolver;
+
+ ///
+ /// The dependency resolver to use for the hub connection.
+ ///
+ public IDependencyResolver Resolver
+ {
+ get { return _resolver ?? GlobalHost.DependencyResolver; }
+ set { _resolver = value; }
+ }
+
+ ///
+ /// Determines if browsers can make cross domain requests to SignalR endpoints.
+ ///
+ public bool EnableCrossDomain { get; set; }
+ }
+}
diff --git a/src/Microsoft.AspNet.SignalR.Core/ConnectionExtensions.cs b/src/Microsoft.AspNet.SignalR.Core/ConnectionExtensions.cs
new file mode 100644
index 000000000..6f03e1c82
--- /dev/null
+++ b/src/Microsoft.AspNet.SignalR.Core/ConnectionExtensions.cs
@@ -0,0 +1,62 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNet.SignalR.Infrastructure;
+
+namespace Microsoft.AspNet.SignalR
+{
+ public static class ConnectionExtensions
+ {
+ ///
+ /// Sends a message to all connections subscribed to the specified signal. An example of signal may be a
+ /// specific connection id.
+ ///
+ /// The connection
+ /// The connectionId to send to.
+ /// The value to publish.
+ /// The list of connection ids to exclude
+ /// A task that represents when the broadcast is complete.
+ public static Task Send(this IConnection connection, string connectionId, object value, params string[] excludeConnectionIds)
+ {
+ if (connection == null)
+ {
+ throw new ArgumentNullException("connection");
+ }
+
+ if (string.IsNullOrEmpty(connectionId))
+ {
+ throw new ArgumentException(Resources.Error_ArgumentNullOrEmpty, "connectionId");
+ }
+
+ var message = new ConnectionMessage(PrefixHelper.GetConnectionId(connectionId),
+ value,
+ PrefixHelper.GetPrefixedConnectionIds(excludeConnectionIds));
+
+ return connection.Send(message);
+ }
+
+ ///
+ /// Broadcasts a value to all connections, excluding the connection ids specified.
+ ///
+ /// The connection
+ /// The value to broadcast.
+ /// The list of connection ids to exclude
+ /// A task that represents when the broadcast is complete.
+ public static Task Broadcast(this IConnection connection, object value, params string[] excludeConnectionIds)
+ {
+ if (connection == null)
+ {
+ throw new ArgumentNullException("connection");
+ }
+
+ var message = new ConnectionMessage(connection.DefaultSignal,
+ value,
+ PrefixHelper.GetPrefixedConnectionIds(excludeConnectionIds));
+
+ return connection.Send(message);
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.SignalR.Core/ConnectionMessage.cs b/src/Microsoft.AspNet.SignalR.Core/ConnectionMessage.cs
new file mode 100644
index 000000000..6c632c9f6
--- /dev/null
+++ b/src/Microsoft.AspNet.SignalR.Core/ConnectionMessage.cs
@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.AspNet.SignalR.Infrastructure;
+
+namespace Microsoft.AspNet.SignalR
+{
+ ///
+ /// A message sent to one more connections.
+ ///
+ [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "Messags are never compared, just used as data.")]
+ public struct ConnectionMessage
+ {
+ ///
+ /// The signal to this message should be sent to. Connections subscribed to this signal
+ /// will receive the message payload.
+ ///
+ public string Signal { get; private set; }
+
+ ///
+ /// The payload of the message.
+ ///
+ public object Value { get; private set; }
+
+ ///
+ /// Represents a list of signals that should be used to filter what connections
+ /// receive this message.
+ ///
+ public IList ExcludedSignals { get; private set; }
+
+ public ConnectionMessage(string signal, object value)
+ : this(signal, value, ListHelper.Empty)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The signal
+ /// The payload of the message
+ /// The signals to exclude.
+ public ConnectionMessage(string signal, object value, IList excludedSignals)
+ : this()
+ {
+ Signal = signal;
+ Value = value;
+ ExcludedSignals = excludedSignals;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.SignalR.Core/Cookie.cs b/src/Microsoft.AspNet.SignalR.Core/Cookie.cs
new file mode 100644
index 000000000..b251da93d
--- /dev/null
+++ b/src/Microsoft.AspNet.SignalR.Core/Cookie.cs
@@ -0,0 +1,28 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+using System;
+
+namespace Microsoft.AspNet.SignalR
+{
+ public class Cookie
+ {
+ public Cookie(string name, string value)
+ : this(name, value, String.Empty, String.Empty)
+ {
+
+ }
+
+ public Cookie(string name, string value, string domain, string path)
+ {
+ Name = name;
+ Value = value;
+ Domain = domain;
+ Path = path;
+ }
+
+ public string Name { get; private set; }
+ public string Domain { get; private set; }
+ public string Path { get; private set; }
+ public string Value { get; private set; }
+ }
+}
diff --git a/src/Microsoft.AspNet.SignalR.Core/DefaultDependencyResolver.cs b/src/Microsoft.AspNet.SignalR.Core/DefaultDependencyResolver.cs
new file mode 100644
index 000000000..da8cb14fc
--- /dev/null
+++ b/src/Microsoft.AspNet.SignalR.Core/DefaultDependencyResolver.cs
@@ -0,0 +1,231 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using Microsoft.AspNet.SignalR.Configuration;
+using Microsoft.AspNet.SignalR.Hubs;
+using Microsoft.AspNet.SignalR.Infrastructure;
+using Microsoft.AspNet.SignalR.Json;
+using Microsoft.AspNet.SignalR.Messaging;
+using Microsoft.AspNet.SignalR.Tracing;
+using Microsoft.AspNet.SignalR.Transports;
+
+namespace Microsoft.AspNet.SignalR
+{
+ public class DefaultDependencyResolver : IDependencyResolver
+ {
+ private readonly Dictionary>> _resolvers = new Dictionary>>();
+ private readonly HashSet _trackedDisposables = new HashSet();
+ private int _disposed;
+
+ [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "It's easiest")]
+ public DefaultDependencyResolver()
+ {
+ RegisterDefaultServices();
+
+ // Hubs
+ RegisterHubExtensions();
+ }
+
+ [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "The resolver is the class that does the most coupling by design.")]
+ [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "The resolver disposes dependencies on Dispose.")]
+ private void RegisterDefaultServices()
+ {
+ var traceManager = new Lazy(() => new TraceManager());
+ Register(typeof(ITraceManager), () => traceManager.Value);
+
+ var serverIdManager = new ServerIdManager();
+ Register(typeof(IServerIdManager), () => serverIdManager);
+
+ var serverMessageHandler = new Lazy(() => new ServerCommandHandler(this));
+ Register(typeof(IServerCommandHandler), () => serverMessageHandler.Value);
+
+ var newMessageBus = new Lazy(() => new MessageBus(this));
+ Register(typeof(IMessageBus), () => newMessageBus.Value);
+
+ var stringMinifier = new Lazy(() => new StringMinifier());
+ Register(typeof(IStringMinifier), () => stringMinifier.Value);
+
+ var serializer = new Lazy();
+ Register(typeof(IJsonSerializer), () => serializer.Value);
+
+ var transportManager = new Lazy(() => new TransportManager(this));
+ Register(typeof(ITransportManager), () => transportManager.Value);
+
+ var configurationManager = new DefaultConfigurationManager();
+ Register(typeof(IConfigurationManager), () => configurationManager);
+
+ var transportHeartbeat = new Lazy(() => new TransportHeartbeat(this));
+ Register(typeof(ITransportHeartbeat), () => transportHeartbeat.Value);
+
+ var connectionManager = new Lazy(() => new ConnectionManager(this));
+ Register(typeof(IConnectionManager), () => connectionManager.Value);
+
+ var ackHandler = new Lazy();
+ Register(typeof(IAckHandler), () => ackHandler.Value);
+
+ var perfCounterWriter = new Lazy(() => new PerformanceCounterManager(this));
+ Register(typeof(IPerformanceCounterManager), () => perfCounterWriter.Value);
+
+ var protectedData = new DefaultProtectedData();
+ Register(typeof(IProtectedData), () => protectedData);
+ }
+
+ private void RegisterHubExtensions()
+ {
+ var methodDescriptorProvider = new Lazy();
+ Register(typeof(IMethodDescriptorProvider), () => methodDescriptorProvider.Value);
+
+ var hubDescriptorProvider = new Lazy(() => new ReflectedHubDescriptorProvider(this));
+ Register(typeof(IHubDescriptorProvider), () => hubDescriptorProvider.Value);
+
+ var parameterBinder = new Lazy();
+ Register(typeof(IParameterResolver), () => parameterBinder.Value);
+
+ var activator = new Lazy(() => new DefaultHubActivator(this));
+ Register(typeof(IHubActivator), () => activator.Value);
+
+ var hubManager = new Lazy(() => new DefaultHubManager(this));
+ Register(typeof(IHubManager), () => hubManager.Value);
+
+ var proxyGenerator = new Lazy(() => new DefaultJavaScriptProxyGenerator(this));
+ Register(typeof(IJavaScriptProxyGenerator), () => proxyGenerator.Value);
+
+ var requestParser = new Lazy();
+ Register(typeof(IHubRequestParser), () => requestParser.Value);
+
+ var assemblyLocator = new Lazy(() => new DefaultAssemblyLocator());
+ Register(typeof(IAssemblyLocator), () => assemblyLocator.Value);
+
+ // Setup the default hub pipeline
+ var dispatcher = new Lazy(() => new HubPipeline().AddModule(new AuthorizeModule()));
+ Register(typeof(IHubPipeline), () => dispatcher.Value);
+ Register(typeof(IHubPipelineInvoker), () => dispatcher.Value);
+ }
+
+ public virtual object GetService(Type serviceType)
+ {
+ if (serviceType == null)
+ {
+ throw new ArgumentNullException("serviceType");
+ }
+
+ IList> activators;
+ if (_resolvers.TryGetValue(serviceType, out activators))
+ {
+ if (activators.Count == 0)
+ {
+ return null;
+ }
+ if (activators.Count > 1)
+ {
+ throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.Error_MultipleActivatorsAreaRegisteredCallGetServices, serviceType.FullName));
+ }
+ return Track(activators[0]);
+ }
+ return null;
+ }
+
+ public virtual IEnumerable