private async Task <ClusterMaintenanceConnection> ConnectToClientNodeAsync(TcpConnectionInfo tcpConnectionInfo, TimeSpan timeout)
            {
                TcpConnectionHeaderMessage.SupportedFeatures supportedFeatures;
                var tcpClient = await TcpUtils.ConnectSocketAsync(tcpConnectionInfo, timeout, _log);

                var connection = await TcpUtils.WrapStreamWithSslAsync(tcpClient, tcpConnectionInfo, _parent._server.Server.Certificate.Certificate, timeout);

                using (_contextPool.AllocateOperationContext(out JsonOperationContext ctx))
                    using (var writer = new BlittableJsonTextWriter(ctx, connection))
                    {
                        var paramaters = new TcpNegotiateParamaters
                        {
                            Database  = null,
                            Operation = TcpConnectionHeaderMessage.OperationTypes.Heartbeats,
                            Version   = TcpConnectionHeaderMessage.HeartbeatsTcpVersion,
                            ReadResponseAndGetVersionAsync = SupervisorReadResponseAndGetVersionAsync,
                            Url = tcpConnectionInfo.Url
                        };
                        supportedFeatures = await TcpNegotiation.NegotiateProtocolVersionAsync(ctx, connection, paramaters).ConfigureAwait(false);

                        WriteClusterMaintenanceConnectionHeader(writer);
                    }

                return(new ClusterMaintenanceConnection
                {
                    TcpClient = tcpClient,
                    Stream = connection,
                    SupportedFeatures = supportedFeatures
                });
            }
            private async Task <ClusterMaintenanceConnection> ConnectToClientNodeAsync(TcpConnectionInfo tcpConnectionInfo, TimeSpan timeout)
            {
                TcpConnectionHeaderMessage.SupportedFeatures supportedFeatures;
                TcpClient tcpClient;
                string    url;

                (tcpClient, url) = await TcpUtils.ConnectSocketAsync(tcpConnectionInfo, timeout, _log);

                var connection = await TcpUtils.WrapStreamWithSslAsync(tcpClient, tcpConnectionInfo, _parent._server.Server.Certificate.Certificate, _parent._server.Server.CipherSuitesPolicy, timeout);

                using (_contextPool.AllocateOperationContext(out JsonOperationContext ctx))
                    using (var writer = new BlittableJsonTextWriter(ctx, connection))
                    {
                        var parameters = new TcpNegotiateParameters
                        {
                            Database  = null,
                            Operation = TcpConnectionHeaderMessage.OperationTypes.Heartbeats,
                            Version   = TcpConnectionHeaderMessage.HeartbeatsTcpVersion,
                            ReadResponseAndGetVersionCallback = SupervisorReadResponseAndGetVersion,
                            DestinationUrl     = url,
                            DestinationNodeTag = ClusterTag
                        };
                        supportedFeatures = TcpNegotiation.NegotiateProtocolVersion(ctx, connection, parameters);

                        WriteClusterMaintenanceConnectionHeader(writer);
                    }

                return(new ClusterMaintenanceConnection
                {
                    TcpClient = tcpClient,
                    Stream = connection,
                    SupportedFeatures = supportedFeatures
                });
            }
        private void WriteHeaderToRemotePeer()
        {
            using (_database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext documentsContext))
                using (var writer = new BlittableJsonTextWriter(documentsContext, _stream))
                {
                    var parameters = new TcpNegotiateParamaters
                    {
                        Database  = Destination.Database,
                        Operation = TcpConnectionHeaderMessage.OperationTypes.Replication,
                        NodeTag   = _parent._server.NodeTag,
                        ReadResponseAndGetVersion = ReadHeaderResponseAndThrowIfUnAuthorized,
                        Version = TcpConnectionHeaderMessage.ReplicationTcpVersion
                    };
                    //This will either throw or return acceptable protocol version.
                    SupportedFeatures = TcpNegotiation.NegotiateProtocolVersion(documentsContext, _stream, parameters);
#if DEBUG
                    Debug.Assert(SupportedFeatures.ProtocolVersion != -1);
                    Debug.Assert(SupportedFeatures.ProtocolVersion != -2);
#endif
                    //start request/response for fetching last etag
                    var request = new DynamicJsonValue
                    {
                        ["Type"] = "GetLastEtag",
                        [nameof(ReplicationLatestEtagRequest.SourceDatabaseId)]   = _database.DbId.ToString(),
                        [nameof(ReplicationLatestEtagRequest.SourceDatabaseName)] = _database.Name,
                        [nameof(ReplicationLatestEtagRequest.SourceUrl)]          = _parent._server.GetNodeHttpServerUrl(),
                        [nameof(ReplicationLatestEtagRequest.SourceTag)]          = _parent._server.NodeTag,
                        [nameof(ReplicationLatestEtagRequest.SourceMachineName)]  = Environment.MachineName
                    };

                    documentsContext.Write(writer, request);
                    writer.Flush();
                }
        }
            private async Task <TcpConnectionHeaderMessage.SupportedFeatures> NegotiateProtocolVersionAsyncForClusterSupervisor(string url, TcpConnectionInfo info, Stream stream, JsonOperationContext context, List <string> _)
            {
                var parameters = new AsyncTcpNegotiateParameters
                {
                    Database  = null,
                    Operation = TcpConnectionHeaderMessage.OperationTypes.Heartbeats,
                    Version   = TcpConnectionHeaderMessage.HeartbeatsTcpVersion,
                    ReadResponseAndGetVersionCallbackAsync = SupervisorReadResponseAndGetVersionAsync,
                    DestinationUrl      = url,
                    DestinationNodeTag  = ClusterTag,
                    DestinationServerId = info.ServerId
                };

                return(await TcpNegotiation.NegotiateProtocolVersionAsync(context, stream, parameters));
            }
        private void WriteHeaderToRemotePeer()
        {
            using (_database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext documentsContext))
                using (var writer = new BlittableJsonTextWriter(documentsContext, _stream))
                {
                    var parameters = new TcpNegotiateParameters
                    {
                        Database           = Destination.Database,
                        Operation          = TcpConnectionHeaderMessage.OperationTypes.Replication,
                        SourceNodeTag      = _parent._server.NodeTag,
                        DestinationNodeTag = GetNode(),
                        DestinationUrl     = Destination.Url,
                        ReadResponseAndGetVersionCallback = ReadHeaderResponseAndThrowIfUnAuthorized,
                        Version = TcpConnectionHeaderMessage.ReplicationTcpVersion
                    };

                    //This will either throw or return acceptable protocol version.
                    SupportedFeatures = TcpNegotiation.NegotiateProtocolVersion(documentsContext, _stream, parameters);

                    if (SupportedFeatures.ProtocolVersion <= 0)
                    {
                        throw new InvalidOperationException(
                                  $"{OutgoingReplicationThreadName}: TCP negotiation resulted with an invalid protocol version:{SupportedFeatures.ProtocolVersion}");
                    }

                    //start request/response for fetching last etag
                    var request = new DynamicJsonValue
                    {
                        ["Type"] = "GetLastEtag",
                        [nameof(ReplicationLatestEtagRequest.SourceDatabaseId)]   = _database.DbId.ToString(),
                        [nameof(ReplicationLatestEtagRequest.SourceDatabaseName)] = _database.Name,
                        [nameof(ReplicationLatestEtagRequest.SourceUrl)]          = _parent._server.GetNodeHttpServerUrl(),
                        [nameof(ReplicationLatestEtagRequest.SourceTag)]          = _parent._server.NodeTag,
                        [nameof(ReplicationLatestEtagRequest.SourceMachineName)]  = Environment.MachineName
                    };

                    documentsContext.Write(writer, request);
                    writer.Flush();
                }
        }