diff --git a/src/Microsoft.AspNet.SignalR.Core/AuthorizeAttribute.cs b/src/Microsoft.AspNet.SignalR.Core/AuthorizeAttribute.cs
index 82ef77896..05caef0a0 100644
--- a/src/Microsoft.AspNet.SignalR.Core/AuthorizeAttribute.cs
+++ b/src/Microsoft.AspNet.SignalR.Core/AuthorizeAttribute.cs
@@ -122,7 +122,7 @@ namespace Microsoft.AspNet.SignalR
{
if (user == null)
{
- throw new ArgumentNullException("user");
+ return false;
}
if (!user.Identity.IsAuthenticated)
diff --git a/src/Microsoft.AspNet.SignalR.Core/Hosting/HostDependencyResolverExtensions.cs b/src/Microsoft.AspNet.SignalR.Core/Hosting/HostDependencyResolverExtensions.cs
index ce4f239f1..c674b317b 100644
--- a/src/Microsoft.AspNet.SignalR.Core/Hosting/HostDependencyResolverExtensions.cs
+++ b/src/Microsoft.AspNet.SignalR.Core/Hosting/HostDependencyResolverExtensions.cs
@@ -20,8 +20,12 @@ namespace Microsoft.AspNet.SignalR.Hosting
throw new ArgumentNullException("instanceName");
}
- // Initialize the performance counters
- resolver.InitializePerformanceCounters(instanceName, hostShutdownToken);
+ // Performance counters are broken on mono so just skip this step
+ if (!MonoUtility.IsRunningMono)
+ {
+ // Initialize the performance counters
+ resolver.InitializePerformanceCounters(instanceName, hostShutdownToken);
+ }
// Dispose the dependency resolver on host shut down (cleanly)
resolver.InitializeResolverDispose(hostShutdownToken);
@@ -41,12 +45,11 @@ namespace Microsoft.AspNet.SignalR.Hosting
// TODO: Guard against multiple calls to this
// When the host triggers the shutdown token, dispose the resolver
- hostShutdownToken.Register(state =>
+ hostShutdownToken.SafeRegister(state =>
{
((IDependencyResolver)state).Dispose();
},
- resolver,
- useSynchronizationContext: false);
+ resolver);
}
}
}
diff --git a/src/Microsoft.AspNet.SignalR.Core/Hosting/IResponse.cs b/src/Microsoft.AspNet.SignalR.Core/Hosting/IResponse.cs
index f6dd60434..3d26f0e61 100644
--- a/src/Microsoft.AspNet.SignalR.Core/Hosting/IResponse.cs
+++ b/src/Microsoft.AspNet.SignalR.Core/Hosting/IResponse.cs
@@ -17,6 +17,11 @@ namespace Microsoft.AspNet.SignalR.Hosting
///
CancellationToken CancellationToken { get; }
+ ///
+ /// Gets or sets the status code of the response.
+ ///
+ int StatusCode { get; set; }
+
///
/// Gets or sets the content type of the response.
///
diff --git a/src/Microsoft.AspNet.SignalR.Core/Hosting/IWebSocket.cs b/src/Microsoft.AspNet.SignalR.Core/Hosting/IWebSocket.cs
index 8db4362cc..60c448f2a 100644
--- a/src/Microsoft.AspNet.SignalR.Core/Hosting/IWebSocket.cs
+++ b/src/Microsoft.AspNet.SignalR.Core/Hosting/IWebSocket.cs
@@ -16,9 +16,9 @@ namespace Microsoft.AspNet.SignalR.Hosting
Action OnMessage { get; set; }
///
- /// Invoked when the websocket gracefully closes
+ /// Invoked when the websocket closes
///
- Action OnClose { get; set; }
+ Action OnClose { get; set; }
///
/// Invoked when there is an error
diff --git a/src/Microsoft.AspNet.SignalR.Core/Hosting/IWebSocketRequest.cs b/src/Microsoft.AspNet.SignalR.Core/Hosting/IWebSocketRequest.cs
index ce7109af0..95f5438f2 100644
--- a/src/Microsoft.AspNet.SignalR.Core/Hosting/IWebSocketRequest.cs
+++ b/src/Microsoft.AspNet.SignalR.Core/Hosting/IWebSocketRequest.cs
@@ -11,6 +11,7 @@ namespace Microsoft.AspNet.SignalR.Hosting
/// Accepts an websocket request using the specified user function.
///
/// The callback that fires when the websocket is ready.
- Task AcceptWebSocketRequest(Func callback);
+ /// The task that completes when the websocket transport is ready.
+ Task AcceptWebSocketRequest(Func callback, Task initTask);
}
}
diff --git a/src/Microsoft.AspNet.SignalR.Core/Hubs/HubDispatcher.cs b/src/Microsoft.AspNet.SignalR.Core/Hubs/HubDispatcher.cs
index 8dc80894c..b97aa74c5 100644
--- a/src/Microsoft.AspNet.SignalR.Core/Hubs/HubDispatcher.cs
+++ b/src/Microsoft.AspNet.SignalR.Core/Hubs/HubDispatcher.cs
@@ -358,7 +358,7 @@ namespace Microsoft.AspNet.SignalR.Hubs
private Task ExecuteHubEvent(IRequest request, string connectionId, Func action)
{
var hubs = GetHubs(request, connectionId).ToList();
- var operations = hubs.Select(instance => action(instance).Catch().OrEmpty()).ToArray();
+ var operations = hubs.Select(instance => action(instance).OrEmpty().Catch()).ToArray();
if (operations.Length == 0)
{
diff --git a/src/Microsoft.AspNet.SignalR.Core/Infrastructure/BinaryTextWriter.cs b/src/Microsoft.AspNet.SignalR.Core/Infrastructure/BinaryTextWriter.cs
new file mode 100644
index 000000000..a5f958b47
--- /dev/null
+++ b/src/Microsoft.AspNet.SignalR.Core/Infrastructure/BinaryTextWriter.cs
@@ -0,0 +1,34 @@
+using System;
+using Microsoft.AspNet.SignalR.Hosting;
+
+namespace Microsoft.AspNet.SignalR.Infrastructure
+{
+ ///
+ /// A buffering text writer that supports writing binary directly as well
+ ///
+ internal unsafe class BinaryTextWriter : BufferTextWriter, IBinaryWriter
+ {
+ public BinaryTextWriter(IResponse response) :
+ base((data, state) => ((IResponse)state).Write(data), response, reuseBuffers: true, bufferSize: 128)
+ {
+
+ }
+
+ public BinaryTextWriter(IWebSocket socket) :
+ base((data, state) => ((IWebSocket)state).SendChunk(data), socket, reuseBuffers: false, bufferSize: 1024)
+ {
+
+ }
+
+
+ public BinaryTextWriter(Action, object> write, object state, bool reuseBuffers, int bufferSize) :
+ base(write, state, reuseBuffers, bufferSize)
+ {
+ }
+
+ public void Write(ArraySegment data)
+ {
+ Writer.Write(data);
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.SignalR.Core/Infrastructure/BufferTextWriter.cs b/src/Microsoft.AspNet.SignalR.Core/Infrastructure/BufferTextWriter.cs
index 2cf39d536..6334f3533 100644
--- a/src/Microsoft.AspNet.SignalR.Core/Infrastructure/BufferTextWriter.cs
+++ b/src/Microsoft.AspNet.SignalR.Core/Infrastructure/BufferTextWriter.cs
@@ -13,7 +13,7 @@ namespace Microsoft.AspNet.SignalR.Infrastructure
/// we don't need to write to a long lived buffer. This saves massive amounts of memory
/// as the number of connections grows.
///
- internal unsafe class BufferTextWriter : TextWriter, IBinaryWriter
+ internal abstract unsafe class BufferTextWriter : TextWriter
{
private readonly Encoding _encoding;
@@ -31,13 +31,13 @@ namespace Microsoft.AspNet.SignalR.Infrastructure
}
public BufferTextWriter(IWebSocket socket) :
- this((data, state) => ((IWebSocket)state).SendChunk(data), socket, reuseBuffers: false, bufferSize: 128)
+ this((data, state) => ((IWebSocket)state).SendChunk(data), socket, reuseBuffers: false, bufferSize: 1024 * 4)
{
}
[SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.TextWriter.#ctor", Justification = "It won't be used")]
- public BufferTextWriter(Action, object> write, object state, bool reuseBuffers, int bufferSize)
+ protected BufferTextWriter(Action, object> write, object state, bool reuseBuffers, int bufferSize)
{
_write = write;
_writeState = state;
@@ -46,7 +46,7 @@ namespace Microsoft.AspNet.SignalR.Infrastructure
_bufferSize = bufferSize;
}
- private ChunkedWriter Writer
+ protected internal ChunkedWriter Writer
{
get
{
@@ -79,17 +79,12 @@ namespace Microsoft.AspNet.SignalR.Infrastructure
Writer.Write(value);
}
- public void Write(ArraySegment data)
- {
- Writer.Write(data);
- }
-
public override void Flush()
{
Writer.Flush();
}
- private class ChunkedWriter
+ internal class ChunkedWriter
{
private int _charPos;
private int _charLen;
diff --git a/src/Microsoft.AspNet.SignalR.Core/Infrastructure/CancellationTokenExtensions.cs b/src/Microsoft.AspNet.SignalR.Core/Infrastructure/CancellationTokenExtensions.cs
index 71736b3df..6dec33dac 100644
--- a/src/Microsoft.AspNet.SignalR.Core/Infrastructure/CancellationTokenExtensions.cs
+++ b/src/Microsoft.AspNet.SignalR.Core/Infrastructure/CancellationTokenExtensions.cs
@@ -1,20 +1,25 @@
// 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.Expressions;
+using System.Reflection;
using System.Threading;
namespace Microsoft.AspNet.SignalR.Infrastructure
{
internal static class CancellationTokenExtensions
{
+ private delegate CancellationTokenRegistration RegisterDelegate(ref CancellationToken token, Action