public Task<NegotiationResponse> Negotiate(IConnection connection, string connectionData)
        {
            Task<NegotiationResponse> response = _httpClient.GetNegotiationResponse(connection, connectionData);

            response.Then(negotiationResponse => _negotiationResponse = negotiationResponse);

            return response;
        }
 public void GlobalSetup()
 {
     _negotiateResponse = new NegotiationResponse
     {
         ConnectionId        = "d100338e-8c01-4281-92c2-9a967fdeebcb",
         AvailableTransports = new List <AvailableTransport>
         {
             new AvailableTransport
             {
                 Transport       = "WebSockets",
                 TransferFormats = new List <string>
                 {
                     "Text",
                     "Binary"
                 }
             }
         }
     };
     _stream = Stream.Null;
 }
Example #3
0
        private async Task RedirectToService(HttpContext context, string hubName, IList <IAuthorizeData> authorizationData)
        {
            if (!await AuthorizeHelper.AuthorizeAsync(context, authorizationData))
            {
                return;
            }

            NegotiationResponse negotiateResponse = null;

            try
            {
                negotiateResponse = _negotiateHandler.Process(context, hubName);
            }
            catch (AzureSignalRAccessTokenTooLongException ex)
            {
                Log.NegotiateFailed(_logger, ex.Message);
                context.Response.StatusCode = 413;
                await HttpResponseWritingExtensions.WriteAsync(context.Response, ex.Message);

                return;
            }

            var writer = new MemoryBufferWriter();

            try
            {
                context.Response.ContentType = "application/json";
                NegotiateProtocol.WriteResponse(negotiateResponse, writer);
                // Write it out to the response with the right content length
                context.Response.ContentLength = writer.Length;
                await writer.CopyToAsync(context.Response.Body);
            }
            finally
            {
                writer.Reset();
            }
        }
        public async Task NegotiateInvokesGetNegotiationResponseOnTransportHelperAsync()
        {
            const string transportName = "fakeTransport";

            var connection = new Connection("http://fake.url/");
            var client = new DefaultHttpClient();
            var negotiationResponse = new NegotiationResponse();

            var mockTransportHelper = new Mock<TransportHelper>();
            mockTransportHelper.Setup(
                h => h.GetNegotiationResponse(It.IsAny<IHttpClient>(), It.IsAny<IConnection>(), It.IsAny<string>()))
                .Returns(Task.FromResult(negotiationResponse));

            var transport =
                new Mock<ClientTransportBase>(client, transportName, mockTransportHelper.Object,
                    new TransportAbortHandler(client, transportName))
                {
                    CallBase = true
                }.Object;

            Assert.Same(negotiationResponse, await transport.Negotiate(connection, "test"));

            mockTransportHelper.Verify(m => m.GetNegotiationResponse(client, connection, "test"), Times.Once());
        }
Example #5
0
        public static async Task RedirectToService(HttpContext context, string hubName, IList <IAuthorizeData> authorizationData)
        {
            var handler       = context.RequestServices.GetRequiredService <NegotiateHandler>();
            var loggerFactory = context.RequestServices.GetService <ILoggerFactory>();
            var logger        = loggerFactory.CreateLogger <ServiceRouteHelper>();

            if (authorizationData != null && !await AuthorizeHelper.AuthorizeAsync(context, authorizationData))
            {
                return;
            }

            NegotiationResponse negotiateResponse = null;

            try
            {
                negotiateResponse = handler.Process(context, hubName);

                if (context.Response.HasStarted)
                {
                    // Inner handler already write to context.Response, no need to continue with error case
                    return;
                }

                // Consider it as internal server error when we don't successfully get negotiate response
                if (negotiateResponse == null)
                {
                    var message = "Unable to get the negotiate endpoint";
                    Log.NegotiateFailed(logger, message);
                    context.Response.StatusCode = 500;
                    await context.Response.WriteAsync(message);

                    return;
                }
            }
            catch (AzureSignalRAccessTokenTooLongException ex)
            {
                Log.NegotiateFailed(logger, ex.Message);
                context.Response.StatusCode = 413;
                await context.Response.WriteAsync(ex.Message);

                return;
            }
            catch (AzureSignalRNotConnectedException e)
            {
                Log.NegotiateFailed(logger, e.Message);
                context.Response.StatusCode = 500;
                await context.Response.WriteAsync(e.Message);

                return;
            }

            var writer = new MemoryBufferWriter();

            try
            {
                context.Response.ContentType = "application/json";
                NegotiateProtocol.WriteResponse(negotiateResponse, writer);
                // Write it out to the response with the right content length
                context.Response.ContentLength = writer.Length;
                await writer.CopyToAsync(context.Response.Body);
            }
            finally
            {
                writer.Reset();
            }
        }
Example #6
0
        public void WebSocketRemovedFromTransportList()
        {
            var tcs = new TaskCompletionSource<NegotiationResponse>();
            var mre = new ManualResetEventSlim();

            var transports = new List<IClientTransport>();

            var webSocketTransport = new Mock<WebSocketTransport>();
            webSocketTransport.Protected()
                .Setup("OnStart", ItExpr.IsAny<IConnection>(), ItExpr.IsAny<string>(), CancellationToken.None)
                .Callback(mre.Set);
            
            transports.Add(webSocketTransport.Object);
            transports.Add(new ServerSentEventsTransport());
            transports.Add(new LongPollingTransport());

            var negotiationResponse = new NegotiationResponse();
            negotiationResponse.TryWebSockets = false;

            tcs.SetResult(negotiationResponse);

            var autoTransport = new Mock<AutoTransport>(It.IsAny<IHttpClient>(), transports);
            autoTransport.Setup(c => c.GetNegotiateResponse(It.IsAny<Connection>(), It.IsAny<string>())).Returns(tcs.Task);
            autoTransport.Object.Negotiate(new Connection("http://foo", string.Empty), string.Empty).Wait();

            Assert.False(mre.IsSet);
        }
Example #7
0
    /// <summary>
    /// Writes the <paramref name="response"/> to the <paramref name="output"/>.
    /// </summary>
    /// <param name="response">The negotiation response generated in response to a negotiation request.</param>
    /// <param name="output">Where the <paramref name="response"/> is written to as Json.</param>
    public static void WriteResponse(NegotiationResponse response, IBufferWriter <byte> output)
    {
        var reusableWriter = ReusableUtf8JsonWriter.Get(output);

        try
        {
            var writer = reusableWriter.GetJsonWriter();
            writer.WriteStartObject();

            // If we already have an error its due to a protocol version incompatibility.
            // We can just write the error and complete the JSON object and return.
            if (!string.IsNullOrEmpty(response.Error))
            {
                writer.WriteString(ErrorPropertyNameBytes, response.Error);
                writer.WriteEndObject();
                writer.Flush();
                Debug.Assert(writer.CurrentDepth == 0);
                return;
            }

            writer.WriteNumber(NegotiateVersionPropertyNameBytes, response.Version);

            if (!string.IsNullOrEmpty(response.Url))
            {
                writer.WriteString(UrlPropertyNameBytes, response.Url);
            }

            if (!string.IsNullOrEmpty(response.AccessToken))
            {
                writer.WriteString(AccessTokenPropertyNameBytes, response.AccessToken);
            }

            if (!string.IsNullOrEmpty(response.ConnectionId))
            {
                writer.WriteString(ConnectionIdPropertyNameBytes, response.ConnectionId);
            }

            if (response.Version > 0 && !string.IsNullOrEmpty(response.ConnectionToken))
            {
                writer.WriteString(ConnectionTokenPropertyNameBytes, response.ConnectionToken);
            }

            writer.WriteStartArray(AvailableTransportsPropertyNameBytes);

            if (response.AvailableTransports != null)
            {
                var transportCount = response.AvailableTransports.Count;
                for (var i = 0; i < transportCount; ++i)
                {
                    var availableTransport = response.AvailableTransports[i];
                    writer.WriteStartObject();
                    if (availableTransport.Transport != null)
                    {
                        writer.WriteString(TransportPropertyNameBytes, availableTransport.Transport);
                    }
                    else
                    {
                        // Might be able to remove this after https://github.com/dotnet/corefx/issues/34632 is resolved
                        writer.WriteNull(TransportPropertyNameBytes);
                    }
                    writer.WriteStartArray(TransferFormatsPropertyNameBytes);

                    if (availableTransport.TransferFormats != null)
                    {
                        var formatCount = availableTransport.TransferFormats.Count;
                        for (var j = 0; j < formatCount; ++j)
                        {
                            writer.WriteStringValue(availableTransport.TransferFormats[j]);
                        }
                    }

                    writer.WriteEndArray();
                    writer.WriteEndObject();
                }
            }

            writer.WriteEndArray();
            writer.WriteEndObject();

            writer.Flush();
            Debug.Assert(writer.CurrentDepth == 0);
        }
        finally
        {
            ReusableUtf8JsonWriter.Return(reusableWriter);
        }
    }