From 335a1826f944f08f6f82b60231bc9a0fe7b6df19 Mon Sep 17 00:00:00 2001
From: "Liangying.Wei" <lianwei@microsoft.com>
Date: Mon, 25 Feb 2019 17:18:32 +0800
Subject: [PATCH 1/3] Revert "Upgrade from 1.0.0 to 1.1.0 (#403)" (#409)

* Revert "Upgrade from 1.0.0 to 1.1.0 (#403)"

This reverts commit 9fe2a1dde3b7ec3324b6c30cc8cd0686544702b0.

* Try fix test failure
---
 build/dependencies.props                             |  8 ++++----
 .../ServiceConnectionTests.cs                        | 12 ++++++++----
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/build/dependencies.props b/build/dependencies.props
index f94daabf3..0084856a8 100644
--- a/build/dependencies.props
+++ b/build/dependencies.props
@@ -5,8 +5,8 @@
   <PropertyGroup Label="Package Versions">
     <!-- Azure ASP.NET Core SignalR -->
     <MessagePackPackageVersion>1.7.3.4</MessagePackPackageVersion>
-    <MicrosoftAspNetCoreHttpConnectionsClientPackageVersion>1.1.0</MicrosoftAspNetCoreHttpConnectionsClientPackageVersion>
-    <MicrosoftAspNetCoreSignalRPackageVersion>1.1.0</MicrosoftAspNetCoreSignalRPackageVersion>
+    <MicrosoftAspNetCoreHttpConnectionsClientPackageVersion>1.0.0</MicrosoftAspNetCoreHttpConnectionsClientPackageVersion>
+    <MicrosoftAspNetCoreSignalRPackageVersion>1.0.0</MicrosoftAspNetCoreSignalRPackageVersion>
     <MicrosoftIdentitiyModelClientsActiveDirectoryPackageVersion>3.19.1</MicrosoftIdentitiyModelClientsActiveDirectoryPackageVersion>
     <MicrosoftAzureKeyVaultPackageVersion>2.3.2</MicrosoftAzureKeyVaultPackageVersion>
     <SystemBuffersPackageVersion>4.5.0</SystemBuffersPackageVersion>
@@ -19,7 +19,7 @@
     
     <!-- Azure ASP.NET SignalR -->
     <MicrosoftAspNetSignalRPackageVersion>2.4.0</MicrosoftAspNetSignalRPackageVersion>
-    <MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>2.2.0</MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>
+    <MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>2.1.0</MicrosoftAspNetCoreConnectionsAbstractionsPackageVersion>
     <MicrosoftExtensionsLoggingTraceSourcePackageVersion>2.1.0</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
     <SystemThreadingChannelsPackageVersion>4.5.0</SystemThreadingChannelsPackageVersion>
     
@@ -40,7 +40,7 @@
     <OwinPackageVersion>1.0.0</OwinPackageVersion>
 
     <!--Testing -->
-    <MicrosoftAspNetCoreSignalRProtocolsMessagePackPackageVersion>1.1.0</MicrosoftAspNetCoreSignalRProtocolsMessagePackPackageVersion>
+    <MicrosoftAspNetCoreSignalRProtocolsMessagePackPackageVersion>1.0.0</MicrosoftAspNetCoreSignalRProtocolsMessagePackPackageVersion>
     <MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
     <MoqPackageVersion>4.7.49</MoqPackageVersion>
     <XunitPackageVersion>2.4.0</XunitPackageVersion>
diff --git a/test/Microsoft.Azure.SignalR.AspNet.Tests/ServiceConnectionTests.cs b/test/Microsoft.Azure.SignalR.AspNet.Tests/ServiceConnectionTests.cs
index e164db903..547d8d01b 100644
--- a/test/Microsoft.Azure.SignalR.AspNet.Tests/ServiceConnectionTests.cs
+++ b/test/Microsoft.Azure.SignalR.AspNet.Tests/ServiceConnectionTests.cs
@@ -47,18 +47,21 @@ public async Task ServiceConnectionDispatchTest()
 
                     // Application layer sends OpenConnectionMessage
                     var openConnectionMessage = new OpenConnectionMessage(clientConnection, new Claim[0], null, "?transport=webSockets");
+                    var task = proxy.WaitForClientConnectAsync(clientConnection).OrTimeout();
                     await proxy.WriteMessageAsync(openConnectionMessage);
-                    await proxy.WaitForClientConnectAsync(clientConnection).OrTimeout();
+                    await task;
                     
                     while (count < 1000)
                     {
+                        task = proxy.WaitForApplicationMessageAsync(clientConnection).OrTimeout();
                         await proxy.WriteMessageAsync(new ConnectionDataMessage(clientConnection, GetPayload("Hello World")));
-                        await proxy.WaitForApplicationMessageAsync(clientConnection).OrTimeout();
+                        await task;
                         count++;
                     }
 
+                    task = proxy.WaitForClientDisconnectAsync(clientConnection).OrTimeout();
                     await proxy.WriteMessageAsync(new CloseConnectionMessage(clientConnection));
-                    await proxy.WaitForClientDisconnectAsync(clientConnection).OrTimeout();
+                    await task;
 
                     // Validate in transport for 1000 data messages.
                     _clientConnectionManager.CurrentTransports.TryGetValue(clientConnection, out var transport);
@@ -113,8 +116,9 @@ public async Task ServiceConnectionDispatchGroupMessagesTest()
                     await lgTask;
                     await gbTask;
 
+                    var dTask = proxy.WaitForClientDisconnectAsync(clientConnection).OrTimeout();
                     await proxy.WriteMessageAsync(new CloseConnectionMessage(clientConnection));
-                    await proxy.WaitForClientDisconnectAsync(clientConnection).OrTimeout();
+                    await dTask;
                 }
             }
         }

From e2e1b18632c2c3689d04da67d0e71864b217695d Mon Sep 17 00:00:00 2001
From: "Liangying.Wei" <lianwei@microsoft.com>
Date: Tue, 26 Feb 2019 10:18:12 +0800
Subject: [PATCH 2/3] revert version to 1.0.0 as 1.1.0 requires netcoreapp2.2
 and use an InternalTraceSourceLogger instead (#408)

---
 .../TraceManagerLoggerProvider.cs             | 32 +++++++++-
 .../TestServiceMessageHandler.cs              | 19 +++++-
 .../TraceManagerLoggerProviderTest.cs         | 64 +++++++++++++++++++
 3 files changed, 111 insertions(+), 4 deletions(-)
 create mode 100644 test/Microsoft.Azure.SignalR.AspNet.Tests/TraceManagerLoggerProviderTest.cs

diff --git a/src/Microsoft.Azure.SignalR.AspNet/TraceManagerLoggerProvider.cs b/src/Microsoft.Azure.SignalR.AspNet/TraceManagerLoggerProvider.cs
index 87359710f..2c6056ab2 100644
--- a/src/Microsoft.Azure.SignalR.AspNet/TraceManagerLoggerProvider.cs
+++ b/src/Microsoft.Azure.SignalR.AspNet/TraceManagerLoggerProvider.cs
@@ -1,6 +1,8 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
+using System;
+using System.Diagnostics;
 using Microsoft.AspNet.SignalR.Tracing;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging.TraceSource;
@@ -19,11 +21,39 @@ public TraceManagerLoggerProvider(ITraceManager traceManager)
         public ILogger CreateLogger(string categoryName)
         {
             var traceSource = _traceManager[categoryName];
-            return new TraceSourceLogger(traceSource);
+            return new InternalTraceSourceLogger(traceSource);
         }
 
         public void Dispose()
         {
         }
+
+        /// <summary>
+        /// Use an InternalTraceSourceLogger to get rid of LogicalOperationStack inside the TraceSourceScope
+        /// </summary>
+        private class InternalTraceSourceLogger : ILogger
+        {
+            private readonly ILogger _inner;
+
+            public InternalTraceSourceLogger(TraceSource traceSource)
+            {
+                _inner = new TraceSourceLogger(traceSource);
+            }
+
+            public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
+            {
+                _inner.Log(logLevel, eventId, state, exception, formatter);
+            }
+
+            public bool IsEnabled(LogLevel logLevel)
+            {
+                return _inner.IsEnabled(logLevel);
+            }
+
+            public IDisposable BeginScope<TState>(TState state)
+            {
+                return null;
+            }
+        }
     }
 }
\ No newline at end of file
diff --git a/test/Microsoft.Azure.SignalR.AspNet.Tests/Infrastructure/TestServiceMessageHandler.cs b/test/Microsoft.Azure.SignalR.AspNet.Tests/Infrastructure/TestServiceMessageHandler.cs
index 86d726696..5722d0ead 100644
--- a/test/Microsoft.Azure.SignalR.AspNet.Tests/Infrastructure/TestServiceMessageHandler.cs
+++ b/test/Microsoft.Azure.SignalR.AspNet.Tests/Infrastructure/TestServiceMessageHandler.cs
@@ -23,8 +23,15 @@ public TestServiceConnectionManager(string appName, IReadOnlyList<string> hubs)
 
         public override Task WriteAsync(ServiceMessage serviceMessage)
         {
-            var tcs = _waitForTransportOutputMessage.GetOrAdd(serviceMessage.GetType(), i => new TaskCompletionSource<ServiceMessage>());
-            tcs.TrySetResult(serviceMessage);
+            if (_waitForTransportOutputMessage.TryGetValue(serviceMessage.GetType(), out var tcs))
+            {
+                tcs.SetResult(serviceMessage);
+            }
+            else
+            {
+                throw new InvalidOperationException("Not expected to write before tcs is inited");
+            }
+
             return Task.CompletedTask;
         }
 
@@ -44,7 +51,13 @@ public override Task WriteAsync(string partitionKey, ServiceMessage serviceMessa
 
         public Task WaitForTransportOutputMessageAsync(Type messageType)
         {
-            var tcs = _waitForTransportOutputMessage[messageType] = new TaskCompletionSource<ServiceMessage>();
+            if (_waitForTransportOutputMessage.TryGetValue(messageType, out var tcs))
+            {
+                tcs.TrySetCanceled();
+            }
+
+            // re-init the tcs
+            tcs = _waitForTransportOutputMessage[messageType] = new TaskCompletionSource<ServiceMessage>();
 
             return tcs.Task;
         }
diff --git a/test/Microsoft.Azure.SignalR.AspNet.Tests/TraceManagerLoggerProviderTest.cs b/test/Microsoft.Azure.SignalR.AspNet.Tests/TraceManagerLoggerProviderTest.cs
new file mode 100644
index 000000000..78875f3b9
--- /dev/null
+++ b/test/Microsoft.Azure.SignalR.AspNet.Tests/TraceManagerLoggerProviderTest.cs
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IdentityModel.Tokens.Jwt;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Security.Claims;
+using System.Threading.Tasks;
+using Microsoft.AspNet.SignalR;
+using Microsoft.AspNet.SignalR.Hubs;
+using Microsoft.AspNet.SignalR.Json;
+using Microsoft.AspNet.SignalR.Messaging;
+using Microsoft.AspNet.SignalR.Tracing;
+using Microsoft.AspNet.SignalR.Transports;
+using Microsoft.AspNetCore.Connections;
+using Microsoft.AspNetCore.Http.Connections.Client;
+using Microsoft.Azure.SignalR.Protocol;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Microsoft.Owin.Hosting;
+using Newtonsoft.Json;
+using Owin;
+using Xunit;
+
+namespace Microsoft.Azure.SignalR.AspNet.Tests
+{
+    public class TraceManagerLoggerProviderTest
+    {
+        /// <summary>
+        /// TraceManagerLoggerProvider throws when its CreateLogger returns TraceSourceLogger when using HttpConnections.Client 1.0.0
+        /// </summary>
+        /// <returns></returns>
+        [Fact]
+        public async Task TestTraceManagerLoggerProviderCanDisposeHttpConnection()
+        {
+            var lf = new LoggerFactory();
+            lf.AddProvider(new TraceManagerLoggerProvider(new TraceManager()));
+            await StartAsync(lf);
+        }
+
+        private static async Task StartAsync(ILoggerFactory lf)
+        {
+            var connection = await ConnectAsync(lf);
+            // var connection = Connect(lf);
+            await ((HttpConnection)connection).DisposeAsync();
+        }
+
+        public static async Task<ConnectionContext> ConnectAsync(ILoggerFactory lf)
+        {
+            // Await to enforce it run in another thread
+            await Task.Yield();
+            var httpConnectionOptions = new HttpConnectionOptions
+            {
+                Url = new Uri("http://locolhost"),
+            };
+
+            return new HttpConnection(httpConnectionOptions, lf);
+        }
+    }
+}
\ No newline at end of file

From af6709d2e159f19243ff016533d9bd413a0e48ae Mon Sep 17 00:00:00 2001
From: Chenyang Liu <zackliu1995@hotmail.com>
Date: Tue, 26 Feb 2019 11:18:53 +0800
Subject: [PATCH 3/3] Add on-demand connection specific handshake error (#410)

* Add handshake error for on-demand connection

* correct log messages
---
 .../ServiceConnectionBase.cs                  | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/Microsoft.Azure.SignalR.Common/ServiceConnections/ServiceConnectionBase.cs b/src/Microsoft.Azure.SignalR.Common/ServiceConnections/ServiceConnectionBase.cs
index 3166eb17a..82433bbb1 100644
--- a/src/Microsoft.Azure.SignalR.Common/ServiceConnections/ServiceConnectionBase.cs
+++ b/src/Microsoft.Azure.SignalR.Common/ServiceConnections/ServiceConnectionBase.cs
@@ -308,7 +308,16 @@ private async Task<bool> ReceiveHandshakeResponseAsync(PipeReader input, Cancell
                             }
 
                             // Handshake error. Will stop reconnect.
-                            Log.HandshakeError(_logger, handshakeResponse.ErrorMessage);
+                            if (_connectionType == ServerConnectionType.OnDemand)
+                            {
+                                // Handshake errors on on-demand connections are acceptable.
+                                Log.OnDemandConnectionHandshakeResponse(_logger, handshakeResponse.ErrorMessage);
+                            }
+                            else
+                            {
+                                Log.HandshakeError(_logger, handshakeResponse.ErrorMessage);
+                            }
+                            
                             return false;
                         }
                     }
@@ -603,6 +612,9 @@ private static class Log
             private static readonly Action<ILogger, string, Exception> _unexpectedExceptionInStop =
                 LoggerMessage.Define<string>(LogLevel.Warning, new EventId(29, "UnexpectedExceptionInStop"), "Connection {ServiceConnectionId} got unexpected exception in StopAsync.");
 
+            private static readonly Action<ILogger, string, Exception> _onDemandConnectionHandshakeResponse =
+                LoggerMessage.Define<string>(LogLevel.Information, new EventId(30, "OnDemandConnectionHandshakeResponse"), "Service returned handshake response: {Message}");
+
             public static void FailedToWrite(ILogger logger, Exception exception)
             {
                 _failedToWrite(logger, exception);
@@ -730,6 +742,11 @@ public static void HandshakeError(ILogger logger, string error)
                 _handshakeError(logger, error, null);
             }
 
+            public static void OnDemandConnectionHandshakeResponse(ILogger logger, string message)
+            {
+                _onDemandConnectionHandshakeResponse(logger, message, null);
+            }
+
             public static void SentPing(ILogger logger)
             {
                 _sentPing(logger, null);