示例#1
0
        public async Task <Task> ConnectAsync(
            EndPoint endPoint,
            bool sendHandshakeRequestMessage      = true,
            bool expectedHandshakeResponseMessage = true)
        {
            if (sendHandshakeRequestMessage)
            {
                using (var memoryStream = new MemoryStream())
                {
                    HandshakeProtocol.WriteRequestMessage(new HandshakeRequestMessage(_protocol.Name), memoryStream);
                    await Connection.Application.Output.WriteAsync(memoryStream.ToArray());
                }
            }

            var connection = endPoint.OnConnectedAsync(Connection);

            if (expectedHandshakeResponseMessage)
            {
                // note that the handshake response might not immediately be readable
                // e.g. server is waiting for request, times out after configured duration,
                // and sends response with timeout error
                HandshakeResponseMessage = (HandshakeResponseMessage) await ReadAsync(true).OrTimeout();
            }

            return(connection);
        }
示例#2
0
        private bool ProcessHandshakeResponse(ref ReadOnlyMemory <byte> data)
        {
            HandshakeResponseMessage message;

            try
            {
                // read first message out of the incoming data
                if (!TextMessageParser.TryParseMessage(ref data, out var payload))
                {
                    throw new InvalidDataException("Unable to parse payload as a handshake response message.");
                }

                message = HandshakeProtocol.ParseResponseMessage(payload);
            }
            catch (Exception ex)
            {
                // shutdown if we're unable to read handshake
                Log.ErrorReceivingHandshakeResponse(_logger, ex);
                Shutdown(ex);
                return(false);
            }

            if (!string.IsNullOrEmpty(message.Error))
            {
                // shutdown if handshake returns an error
                Log.HandshakeServerError(_logger, message.Error);
                Shutdown();
                return(false);
            }

            return(true);
        }
示例#3
0
        public void GlobalSetup()
        {
            using (var writer = new MemoryBufferWriter())
            {
                HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer);
                var handshakeResponseResult = new ReadResult(new ReadOnlySequence <byte>(writer.ToArray()), false, false);

                _pipe = new TestDuplexPipe();
                _pipe.AddReadResult(new ValueTask <ReadResult>(handshakeResponseResult));
            }

            _tcs = new TaskCompletionSource <ReadResult>();
            _pipe.AddReadResult(new ValueTask <ReadResult>(_tcs.Task));

            var connection = new TestConnection();

            // prevents keep alive time being activated
            connection.Features.Set <IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature());
            connection.Transport = _pipe;

            var protocol = Protocol == "json" ? (IHubProtocol) new JsonHubProtocol() : new MessagePackHubProtocol();

            _hubConnection = new HubConnection(() => connection, protocol, new NullLoggerFactory());
            _hubConnection.StartAsync().GetAwaiter().GetResult();

            _arguments = new object[ArgumentCount];
            for (int i = 0; i < _arguments.Length; i++)
            {
                _arguments[i] = "Hello world!";
            }
        }
示例#4
0
        public async void ServiceConnectionShouldIgnoreFirstHandshakeResponse()
        {
            var factory    = new TestClientConnectionFactory();
            var connection = MockServiceConnection(null, factory);

            // create a connection with migration header.
            await connection.OnClientConnectedAsyncForTest(new OpenConnectionMessage("foo", new Claim[0])
            {
                Headers = new Dictionary <string, StringValues> {
                    { Constants.AsrsMigrateIn, "another-server" }
                }
            });

            Assert.Equal(1, factory.Connections.Count);
            var context = factory.Connections[0];

            Assert.True(context.IsMigrated);

            var message = new AspNetCore.SignalR.Protocol.HandshakeResponseMessage("");

            HandshakeProtocol.WriteResponseMessage(message, context.Transport.Output);
            await context.Transport.Output.FlushAsync();

            var task = context.Transport.Input.ReadAsync();
            await Task.Delay(100);

            // nothing should be written into the transport
            Assert.False(task.IsCompleted);
            // but the `migrated` status should remain False (readonly)
            Assert.True(context.IsMigrated);
        }
示例#5
0
    public void GlobalSetup()
    {
        var writer = MemoryBufferWriter.Get();

        try
        {
            HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer);
            _handshakeResponseResult = new ReadResult(new ReadOnlySequence <byte>(writer.ToArray()), false, false);
        }
        finally
        {
            MemoryBufferWriter.Return(writer);
        }

        _pipe = new TestDuplexPipe();

        var hubConnectionBuilder = new HubConnectionBuilder();

        hubConnectionBuilder.WithUrl("http://doesntmatter");

        var delegateConnectionFactory = new DelegateConnectionFactory(endPoint =>
        {
            var connection = new DefaultConnectionContext();
            // prevents keep alive time being activated
            connection.Features.Set <IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature());
            connection.Transport = _pipe;
            return(new ValueTask <ConnectionContext>(connection));
        });

        hubConnectionBuilder.Services.AddSingleton <IConnectionFactory>(delegateConnectionFactory);

        _hubConnection = hubConnectionBuilder.Build();
    }
        public void GlobalSetup()
        {
            var writer = MemoryBufferWriter.Get();

            try
            {
                HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer);
                _handshakeResponseResult = new ReadResult(new ReadOnlySequence <byte>(writer.ToArray()), false, false);
            }
            finally
            {
                MemoryBufferWriter.Return(writer);
            }

            _pipe = new TestDuplexPipe();

            var hubConnectionBuilder = new HubConnectionBuilder();

            hubConnectionBuilder.WithHubProtocol(new JsonHubProtocol());
            hubConnectionBuilder.WithConnectionFactory(format =>
            {
                var connection = new DefaultConnectionContext();
                // prevents keep alive time being activated
                connection.Features.Set <IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature());
                connection.Transport = _pipe;
                return(Task.FromResult <ConnectionContext>(connection));
            });

            _hubConnection = hubConnectionBuilder.Build();
        }
示例#7
0
        public void GlobalSetup()
        {
            var arguments = new object[ArgumentCount];

            for (var i = 0; i < arguments.Length; i++)
            {
                arguments[i] = "Hello world!";
            }

            var writer = MemoryBufferWriter.Get();

            try
            {
                HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer);
                var handshakeResponseResult = new ReadResult(new ReadOnlySequence <byte>(writer.ToArray()), false, false);

                _pipe = new TestDuplexPipe();
                _pipe.AddReadResult(new ValueTask <ReadResult>(handshakeResponseResult));
            }
            finally
            {
                MemoryBufferWriter.Return(writer);
            }

            _nextReadTcs = new TaskCompletionSource <ReadResult>();
            _pipe.AddReadResult(new ValueTask <ReadResult>(_nextReadTcs.Task));

            IHubProtocol hubProtocol;

            var hubConnectionBuilder = new HubConnectionBuilder();

            if (Protocol == "json")
            {
                hubProtocol = new NewtonsoftJsonHubProtocol();
            }
            else
            {
                hubProtocol = new MessagePackHubProtocol();
            }

            hubConnectionBuilder.Services.TryAddEnumerable(ServiceDescriptor.Singleton(typeof(IHubProtocol), hubProtocol));
            hubConnectionBuilder.WithUrl("http://doesntmatter");

            _invocationMessageBytes = hubProtocol.GetMessageBytes(new InvocationMessage(MethodName, arguments));

            var delegateConnectionFactory = new DelegateConnectionFactory(endPoint =>
            {
                var connection = new DefaultConnectionContext();
                // prevents keep alive time being activated
                connection.Features.Set <IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature());
                connection.Transport = _pipe;
                return(new ValueTask <ConnectionContext>(connection));
            });

            hubConnectionBuilder.Services.AddSingleton <IConnectionFactory>(delegateConnectionFactory);

            _hubConnection = hubConnectionBuilder.Build();
            _hubConnection.On(MethodName, arguments.Select(v => v.GetType()).ToArray(), OnInvoke);
            _hubConnection.StartAsync().GetAwaiter().GetResult();
        }
        public async Task TestServiceConnectionForMigratedIn()
        {
            var factory    = new TestClientConnectionFactory();
            var connection = MockServiceConnection(null, factory);

            // create a connection with migration header.
            await connection.OnClientConnectedAsyncForTest(new OpenConnectionMessage("foo", new Claim[0])
            {
                Headers = new Dictionary <string, StringValues> {
                    { Constants.AsrsMigrateFrom, "another-server" }
                }
            });

            Assert.Equal(1, factory.Connections.Count);
            var context = factory.Connections[0];

            Assert.True(context.IsMigrated);

            var message = new AspNetCore.SignalR.Protocol.HandshakeResponseMessage("");

            HandshakeProtocol.WriteResponseMessage(message, context.Transport.Output);
            await context.Transport.Output.FlushAsync();

            var task = context.Transport.Input.ReadAsync();
            await Task.Delay(100);

            // nothing should be written into the transport
            Assert.False(task.IsCompleted);
            Assert.True(context.IsMigrated);

            var feature = context.Features.Get <IConnectionMigrationFeature>();

            Assert.NotNull(feature);
            Assert.Equal("another-server", feature.MigrateFrom);
        }
示例#9
0
        private static async Task ProvideServerHandshake(PipeReader reader, PipeWriter writer, CancellationToken cancellationToken)
        {
            bool isHandshakeCompleted = false;

            while (!isHandshakeCompleted)
            {
                var result = await reader.ReadAsync(cancellationToken).ConfigureAwait(false);

                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                var buffer = result.Buffer;
                if (HandshakeProtocol.TryParseRequestMessage(ref buffer, out var requestMessage))
                {
                    var responseMessage = HandshakeResponseMessage.Empty;
                    if (requestMessage.Protocol != nameof(MessageStoreHubProtocol))
                    {
                        responseMessage = new HandshakeResponseMessage($"Protocol '{requestMessage.Protocol}' is not supported.");
                    }

                    reader.AdvanceTo(buffer.Start, buffer.Start);

                    HandshakeProtocol.WriteResponseMessage(responseMessage, writer);
                    await writer.FlushAsync(cancellationToken).ConfigureAwait(false);

                    isHandshakeCompleted = true;
                }
示例#10
0
        public void GlobalSetup()
        {
            var memoryBufferWriter = MemoryBufferWriter.Get();

            try
            {
                HandshakeProtocol.WriteRequestMessage(new HandshakeRequestMessage("json", 1), memoryBufferWriter);
                _handshakeRequestResult = new ReadResult(new ReadOnlySequence <byte>(memoryBufferWriter.ToArray()), false, false);
            }
            finally
            {
                MemoryBufferWriter.Return(memoryBufferWriter);
            }

            _pipe = new TestDuplexPipe();

            var connection = new DefaultConnectionContext(Guid.NewGuid().ToString(), _pipe, _pipe);

            _hubConnectionContext = new HubConnectionContext(connection, Timeout.InfiniteTimeSpan, NullLoggerFactory.Instance);

            _successHubProtocolResolver = new TestHubProtocolResolver(new JsonHubProtocol());
            _failureHubProtocolResolver = new TestHubProtocolResolver(null);
            _userIdProvider             = new TestUserIdProvider();
            _supportedProtocols         = new List <string> {
                "json"
            };
        }
示例#11
0
        public void ParsingHandshakeResponseMessageSuccessForValidMessages(string json, string error)
        {
            var message = Encoding.UTF8.GetBytes(json);

            var response = HandshakeProtocol.ParseResponseMessage(message);

            Assert.Equal(error, response.Error);
        }
示例#12
0
        public void ParsingHandshakeRequestMessageSuccessForValidMessages(string json, string protocol)
        {
            var message = Encoding.UTF8.GetBytes(json);

            Assert.True(HandshakeProtocol.TryParseRequestMessage(new ReadOnlySequence <byte>(message), out var deserializedMessage, out _, out _));

            Assert.Equal(protocol, deserializedMessage.Protocol);
        }
示例#13
0
 static HubConnectionContext()
 {
     using (var memoryBufferWriter = new MemoryBufferWriter())
     {
         HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, memoryBufferWriter);
         _successHandshakeResponseData = memoryBufferWriter.ToArray();
     }
 }
示例#14
0
        public void ParsingHandshakeResponseMessageThrowsForInvalidMessages(string payload, string expectedMessage)
        {
            var message = Encoding.UTF8.GetBytes(payload);

            var exception = Assert.Throws <InvalidDataException>(() =>
                                                                 HandshakeProtocol.ParseResponseMessage(message));

            Assert.Equal(expectedMessage, exception.Message);
        }
示例#15
0
    public void ParsingHandshakeRequestMessageThrowsForInvalidMessages(string payload, string expectedMessage)
    {
        var message = new ReadOnlySequence <byte>(Encoding.UTF8.GetBytes(payload));

        var exception = Assert.Throws <InvalidDataException>(() =>
                                                             Assert.True(HandshakeProtocol.TryParseRequestMessage(ref message, out _)));

        Assert.Equal(expectedMessage, exception.Message);
    }
示例#16
0
        public void GlobalSetup()
        {
            var writer = MemoryBufferWriter.Get();

            try
            {
                HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer);
                var handshakeResponseResult = new ReadResult(new ReadOnlySequence <byte>(writer.ToArray()), false, false);

                _pipe = new TestDuplexPipe();
                _pipe.AddReadResult(new ValueTask <ReadResult>(handshakeResponseResult));
            }
            finally
            {
                MemoryBufferWriter.Return(writer);
            }

            _tcs = new TaskCompletionSource <ReadResult>();
            _pipe.AddReadResult(new ValueTask <ReadResult>(_tcs.Task));

            var hubConnectionBuilder = new HubConnectionBuilder();

            if (Protocol == "json")
            {
                // JSON protocol added by default
            }
            else
            {
                hubConnectionBuilder.AddMessagePackProtocol();
            }

            var delegateConnectionFactory = new DelegateConnectionFactory(format =>
            {
                var connection = new DefaultConnectionContext();
                // prevents keep alive time being activated
                connection.Features.Set <IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature());
                connection.Transport = _pipe;
                return(Task.FromResult <ConnectionContext>(connection));
            },
                                                                          connection =>
            {
                connection.Transport.Output.Complete();
                connection.Transport.Input.Complete();
                return(Task.CompletedTask);
            });

            hubConnectionBuilder.Services.AddSingleton <IConnectionFactory>(delegateConnectionFactory);

            _hubConnection = hubConnectionBuilder.Build();
            _hubConnection.StartAsync().GetAwaiter().GetResult();

            _arguments = new object[ArgumentCount];
            for (var i = 0; i < _arguments.Length; i++)
            {
                _arguments[i] = "Hello world!";
            }
        }
示例#17
0
        public async Task ReadHandshakeAndSendResponseAsync()
        {
            await SentMessages.ReadAsync();

            var output = new MemoryStream();

            HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, output);

            await _receivedMessages.Writer.WriteAsync(output.ToArray());
        }
示例#18
0
        public async Task <string> ReadHandshakeAndSendResponseAsync()
        {
            var s = await ReadSentTextMessageAsync();

            using (var output = new MemoryBufferWriter())
            {
                HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, output);
                await Application.Output.WriteAsync(output.ToArray());
            }

            return(s);
        }
    public void HandShakeWriteResponseEmpty_MemoryBufferWriter()
    {
        var writer = MemoryBufferWriter.Get();

        try
        {
            HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer);
        }
        finally
        {
            MemoryBufferWriter.Return(writer);
        }
    }
    public void HandShakeWriteRequest_MemoryBufferWriter()
    {
        var memoryBufferWriter = MemoryBufferWriter.Get();

        try
        {
            HandshakeProtocol.WriteRequestMessage(new HandshakeRequestMessage("json", 1), memoryBufferWriter);
        }
        finally
        {
            MemoryBufferWriter.Return(memoryBufferWriter);
        }
    }
示例#21
0
        /// <summary>
        /// WebSocket 接收到消息的处理时间
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WebSocket_MessageReceived(object sender, MessageReceivedEventArgs e)
        {
            var data = e.Message;

            Log.Debug($"收到服务端消息:{data}");
            if (data.Length < 1)
            {
                return; //非 signalR 协议中的返回
            }
            data = data.Substring(0, data.Length - 1);
            var separator = new byte[1] {
                0x1e
            };
            var separatorStr = Encoding.UTF8.GetString(separator);
            var messages     = data.Split(separatorStr[0]);

            if (messages == null || messages.Length <= 0)
            {
                Log.Debug("收到的服务端消息未解析到有用信息");
                return;
            }
            foreach (var message in messages)
            {
                try
                {
                    if (!string.IsNullOrEmpty(message))
                    {
                        bool isHandshakeResponse = HandshakeProtocol
                                                   .TryParseHandshakeResponseMessage(message, out HandshakeResponseMessage handshakeResponseMessage);
                        Log.Debug($"SuccessfulHandshake={SuccessfulHandshake}, TryParseHandshakeResponseMessage={isHandshakeResponse}");
                        if (SuccessfulHandshake && !isHandshakeResponse)
                        {
                            if (ReceiveMessageLoop != null)
                            {
                                ReceiveMessageLoop.BeginInvoke(message, null, null);
                            }
                        }
                        else if (!SuccessfulHandshake && isHandshakeResponse)
                        {
                            SuccessfulHandshake = true;
                            HandshakeMessage    = handshakeResponseMessage;
                        }
                    }
                }
                catch (Exception e1)
                {
                    Log.Error("WebSocket 处理消息出错", e1);
                    continue;
                }
            }
        }
示例#22
0
        public HubMessage TryRead(bool isHandshake = false)
        {
            if (_messages.Count > 0)
            {
                return(_messages.Dequeue());
            }

            if (!Connection.Application.Input.TryRead(out var result))
            {
                return(null);
            }

            var buffer   = result.Buffer;
            var consumed = buffer.End;
            var examined = consumed;

            try
            {
                if (!isHandshake)
                {
                    var messages = new List <HubMessage>();
                    if (_protocol.TryParseMessages(result.Buffer.ToArray(), _invocationBinder, messages))
                    {
                        foreach (var m in messages)
                        {
                            _messages.Enqueue(m);
                        }

                        return(_messages.Dequeue());
                    }
                }
                else
                {
                    HandshakeProtocol.TryReadMessageIntoSingleMemory(buffer, out consumed, out examined, out var data);

                    // read first message out of the incoming data
                    if (!TextMessageParser.TryParseMessage(ref data, out var payload))
                    {
                        throw new InvalidDataException("Unable to parse payload as a handshake response message.");
                    }

                    return(HandshakeProtocol.ParseResponseMessage(payload));
                }
            }
            finally
            {
                Connection.Application.Input.AdvanceTo(consumed, examined);
            }

            return(null);
        }
示例#23
0
        static HubConnectionContext()
        {
            var memoryBufferWriter = MemoryBufferWriter.Get();

            try
            {
                HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, memoryBufferWriter);
                _successHandshakeResponseData = memoryBufferWriter.ToArray();
            }
            finally
            {
                MemoryBufferWriter.Return(memoryBufferWriter);
            }
        }
    public void HandShakeWriteResponse_MemoryBufferWriter()
    {
        ReadOnlyMemory <byte> result;
        var memoryBufferWriter = MemoryBufferWriter.Get();

        try
        {
            HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, memoryBufferWriter);
            result = memoryBufferWriter.ToArray();
        }
        finally
        {
            MemoryBufferWriter.Return(memoryBufferWriter);
        }
    }
示例#25
0
        public async Task <string> ReadHandshakeAndSendResponseAsync()
        {
            var s = await ReadSentTextMessageAsync();

            var output = MemoryBufferWriter.Get();

            try
            {
                HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, output);
                await Application.Output.WriteAsync(output.ToArray());
            }
            finally
            {
                MemoryBufferWriter.Return(output);
            }

            return(s);
        }
示例#26
0
        public void GlobalSetup()
        {
            using (var writer = new MemoryBufferWriter())
            {
                HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer);
                _handshakeResponseResult = new ReadResult(new ReadOnlySequence <byte>(writer.ToArray()), false, false);
            }

            _pipe = new TestDuplexPipe();

            var connection = new TestConnection();

            // prevents keep alive time being activated
            connection.Features.Set <IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature());
            connection.Transport = _pipe;

            _hubConnection = new HubConnection(() => connection, new JsonHubProtocol(), new NullLoggerFactory());
        }
示例#27
0
        public void GlobalSetup()
        {
            var writer = MemoryBufferWriter.Get();

            try
            {
                HandshakeProtocol.WriteResponseMessage(HandshakeResponseMessage.Empty, writer);
                var handshakeResponseResult = new ReadResult(new ReadOnlySequence <byte>(writer.ToArray()), false, false);

                _pipe = new TestDuplexPipe();
                _pipe.AddReadResult(new ValueTask <ReadResult>(handshakeResponseResult));
            }
            finally
            {
                MemoryBufferWriter.Return(writer);
            }

            _tcs = new TaskCompletionSource <ReadResult>();
            _pipe.AddReadResult(new ValueTask <ReadResult>(_tcs.Task));


            var protocol = Protocol == "json" ? (IHubProtocol) new JsonHubProtocol() : new MessagePackHubProtocol();

            var hubConnectionBuilder = new HubConnectionBuilder();

            hubConnectionBuilder.WithHubProtocol(protocol);
            hubConnectionBuilder.WithConnectionFactory(format =>
            {
                var connection = new DefaultConnectionContext();
                // prevents keep alive time being activated
                connection.Features.Set <IConnectionInherentKeepAliveFeature>(new TestConnectionInherentKeepAliveFeature());
                connection.Transport = _pipe;
                return(Task.FromResult <ConnectionContext>(connection));
            });

            _hubConnection = hubConnectionBuilder.Build();
            _hubConnection.StartAsync().GetAwaiter().GetResult();

            _arguments = new object[ArgumentCount];
            for (var i = 0; i < _arguments.Length; i++)
            {
                _arguments[i] = "Hello world!";
            }
        }
示例#28
0
        private async Task StartAsyncCore()
        {
            await _connection.StartAsync(_protocol.TransferFormat);

            _needKeepAlive             = _connection.Features.Get <IConnectionInherentKeepAliveFeature>() == null;
            _receivedHandshakeResponse = false;

            Log.HubProtocol(_logger, _protocol.Name);

            _connectionActive = new CancellationTokenSource();
            using (var memoryStream = new MemoryStream())
            {
                Log.SendingHubHandshake(_logger);
                HandshakeProtocol.WriteRequestMessage(new HandshakeRequestMessage(_protocol.Name), memoryStream);
                await _connection.SendAsync(memoryStream.ToArray(), _connectionActive.Token);
            }

            ResetTimeoutTimer();
        }
示例#29
0
        public async Task <string> ReadHandshakeAndSendResponseAsync(int minorVersion = 0)
        {
            var s = await ReadSentTextMessageAsync();

            byte[] response;

            var output = MemoryBufferWriter.Get();

            try
            {
                HandshakeProtocol.WriteResponseMessage(new HandshakeResponseMessage(minorVersion), output);
                response = output.ToArray();
            }
            finally
            {
                MemoryBufferWriter.Return(output);
            }

            await Application.Output.WriteAsync(response);

            return(s);
        }
        public async ValueTask <ConnectionContext> ConnectAsync(EndPoint endpoint, CancellationToken cancellationToken = default)
        {
            if (!(endpoint is AzureSignalREndPoint azEndpoint))
            {
                throw new NotSupportedException($"{endpoint} is not supported");
            }

            var options = new HttpConnectionOptions
            {
                Url             = azEndpoint.Uri,
                Transports      = HttpTransportType.WebSockets,
                SkipNegotiation = true
            };

            options.Headers["Authorization"] = $"Bearer {azEndpoint.AccessToken}";
            var httpConnection = new HttpConnection(options, _loggerFactory);
            await httpConnection.StartAsync();

            // The SignalR service expects the handshake in default mode, this isn't relevant when using it like a byte stream
            HandshakeProtocol.WriteRequestMessage(new HandshakeRequestMessage("unknown", 1), httpConnection.Transport.Output);
            await httpConnection.Transport.Output.FlushAsync();

            return(httpConnection);
        }