private async Task <ClusterMaintenanceConnection> ConnectToClientNodeAsync(TcpConnectionInfo tcpConnectionInfo, TimeSpan timeout) { TcpConnectionHeaderMessage.SupportedFeatures supportedFeatures; Stream connection; TcpClient tcpClient; using (_contextPool.AllocateOperationContext(out JsonOperationContext ctx)) { var result = await TcpUtils.ConnectSecuredTcpSocket( tcpConnectionInfo, _parent._server.Server.Certificate.Certificate, _parent._server.Server.CipherSuitesPolicy, TcpConnectionHeaderMessage.OperationTypes.Heartbeats, NegotiateProtocolVersionAsyncForClusterSupervisor, ctx, timeout, null, _token); tcpClient = result.TcpClient; connection = result.Stream; supportedFeatures = result.SupportedFeatures; await using (var writer = new AsyncBlittableJsonTextWriter(ctx, connection)) { await WriteClusterMaintenanceConnectionHeaderAsync(writer); } } return(new ClusterMaintenanceConnection { TcpClient = tcpClient, Stream = connection, SupportedFeatures = supportedFeatures }); }
public static async Task ConnectToClientNodeAsync(RavenServer server, TcpConnectionInfo tcpConnectionInfo, TimeSpan timeout, Logger log, string database, NodeConnectionTestResult result, CancellationToken token = default) { List <string> negLogs = new(); using (server.ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext ctx)) { using var tcpSocketResult = await TcpUtils.ConnectSecuredTcpSocket(tcpConnectionInfo, server.Certificate.Certificate, server.CipherSuitesPolicy, TcpConnectionHeaderMessage.OperationTypes.TestConnection, NegotiateWithRemote, ctx, timeout, negLogs, token); } result.Log = negLogs; async Task <TcpConnectionHeaderMessage.SupportedFeatures> NegotiateWithRemote(string url, TcpConnectionInfo info, Stream stream, JsonOperationContext context, List <string> logs = null) { await using (var writer = new AsyncBlittableJsonTextWriter(context, stream)) { await WriteOperationHeaderToRemote(writer, TcpConnectionHeaderMessage.OperationTypes.TestConnection, database, info.ServerId); using (var responseJson = await context.ReadForMemoryAsync(stream, $"TestConnectionHandler/{url}/Read-Handshake-Response")) { var headerResponse = JsonDeserializationServer.TcpConnectionHeaderResponse(responseJson); switch (headerResponse.Status) { case TcpConnectionStatus.Ok: result.Success = true; result.Error = null; logs?.Add($"Successfully negotiated with {url}."); break; case TcpConnectionStatus.AuthorizationFailed: result.Success = false; result.Error = $"Connection to {url} failed because of authorization failure: {headerResponse.Message}"; logs?.Add(result.Error); throw new AuthorizationException(result.Error); case TcpConnectionStatus.TcpVersionMismatch: result.Success = false; result.Error = $"Connection to {url} failed because of mismatching tcp version: {headerResponse.Message}"; logs?.Add(result.Error); await WriteOperationHeaderToRemote(writer, TcpConnectionHeaderMessage.OperationTypes.Drop, database, info.ServerId); throw new AuthorizationException(result.Error); case TcpConnectionStatus.InvalidNetworkTopology: result.Success = false; result.Error = $"Connection to {url} failed because of {nameof(TcpConnectionStatus.InvalidNetworkTopology)} error: {headerResponse.Message}"; logs?.Add(result.Error); throw new InvalidNetworkTopologyException(result.Error); } } } return(null); } }
private async Task <PingResult> PingOnce(string url) { var sp = Stopwatch.StartNew(); var result = new PingResult { Url = url }; using (var cts = new CancellationTokenSource(ServerStore.Engine.TcpConnectionTimeout)) { var info = await ReplicationUtils.GetTcpInfoAsync(url, null, "PingTest", ServerStore.Engine.ClusterCertificate, cts.Token); result.TcpInfoTime = sp.ElapsedMilliseconds; using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context)) { var log = new List <string>(); using (await TcpUtils.ConnectSecuredTcpSocket(info, ServerStore.Engine.ClusterCertificate, Server.CipherSuitesPolicy, TcpConnectionHeaderMessage.OperationTypes.Ping, NegotiationCallback, context, ServerStore.Engine.TcpConnectionTimeout, log, cts.Token)) { } result.Log = log; async Task <TcpConnectionHeaderMessage.SupportedFeatures> NegotiationCallback(string curUrl, TcpConnectionInfo tcpInfo, Stream stream, JsonOperationContext ctx, List <string> logs = null) { try { var msg = new DynamicJsonValue { [nameof(TcpConnectionHeaderMessage.DatabaseName)] = null, [nameof(TcpConnectionHeaderMessage.Operation)] = TcpConnectionHeaderMessage.OperationTypes.Ping, [nameof(TcpConnectionHeaderMessage.OperationVersion)] = -1, [nameof(TcpConnectionHeaderMessage.ServerId)] = tcpInfo.ServerId }; await using (var writer = new AsyncBlittableJsonTextWriter(ctx, stream)) using (var msgJson = ctx.ReadObject(msg, "message")) { result.SendTime = sp.ElapsedMilliseconds; logs?.Add($"message sent to url {curUrl} at {result.SendTime} ms."); ctx.Write(writer, msgJson); } using (var rawResponse = await ctx.ReadForMemoryAsync(stream, "cluster-ConnectToPeer-header-response")) { TcpConnectionHeaderResponse response = JsonDeserializationServer.TcpConnectionHeaderResponse(rawResponse); result.ReceiveTime = sp.ElapsedMilliseconds; logs?.Add($"response received from url {curUrl} at {result.ReceiveTime} ms."); switch (response.Status) { case TcpConnectionStatus.Ok: result.Error = null; logs?.Add($"Successfully negotiated with {url}."); break; case TcpConnectionStatus.AuthorizationFailed: result.Error = $"Connection to {url} failed because of authorization failure: {response.Message}"; logs?.Add(result.Error); throw new AuthorizationException(result.Error); case TcpConnectionStatus.TcpVersionMismatch: result.Error = $"Connection to {url} failed because of mismatching tcp version: {response.Message}"; logs?.Add(result.Error); throw new AuthorizationException(result.Error); case TcpConnectionStatus.InvalidNetworkTopology: result.Error = $"Connection to {url} failed because of {nameof(TcpConnectionStatus.InvalidNetworkTopology)} error: {response.Message}"; logs?.Add(result.Error); throw new InvalidNetworkTopologyException(result.Error); } } } catch (Exception e) { result.Error = e.ToString(); logs?.Add($"Error occurred while attempting to negotiate with the server. {e.Message}"); throw; } return(null); } } } return(result); }