public bool SendHandshake(AeronHandshakeRequest handshakeRequest, int connectionResponseTimeoutMs) { using var handshakeRequestStream = new MemoryStream(); Serializer.SerializeWithLengthPrefix(handshakeRequestStream, handshakeRequest, PrefixStyle.Base128); _buffer.Wrap(handshakeRequestStream.GetBuffer(), 0, (int)handshakeRequestStream.Length); var spinWait = new SpinWait(); var stopwatch = Stopwatch.StartNew(); while (true) { var errorCode = _publication.Offer(_buffer, 0, (int)handshakeRequestStream.Length, (buffer, offset, length) => (long)new AeronReservedValue(Utils.CurrentProtocolVersion, AeronMessageType.Connected, 0)); if (errorCode == Publication.NOT_CONNECTED) { // This will happen as we just created the publication - we need to wait for Aeron to do its stuff if (stopwatch.ElapsedMilliseconds > connectionResponseTimeoutMs) { _log.Error($"Failed to send handshake (not connected): {this}"); return(false); } spinWait.SpinOnce(); continue; } var result = Utils.InterpretPublicationOfferResult(errorCode); if (result == AeronResultType.Success) { break; } if (result == AeronResultType.ShouldRetry) { spinWait.SpinOnce(); continue; } _log.Error($"Failed to send handshake: {this}"); return(false); } _buffer.Release(); return(true); }
public int Connect(string serverHost, int serverPort, Action onConnectedDelegate, Action onDisconnectedDelegate, AeronClientMessageReceivedHandler onMessageReceived, int connectionResponseTimeoutMs) { if (serverHost == null) { throw new ArgumentNullException(nameof(serverHost)); } if (_isTerminatedUnexpectedly) { return(-1); } string serverHostIp; if (serverHost.Equals("localhost", StringComparison.OrdinalIgnoreCase) || serverHost.Equals("127.0.0.1", StringComparison.OrdinalIgnoreCase)) { // TODO IPC channel for local communication serverHostIp = "127.0.0.1"; } else { var ipv4 = Dns.GetHostEntry(serverHost).AddressList .FirstOrDefault(x => x.AddressFamily == AddressFamily.InterNetwork) ?? throw new ArgumentException($"Cannot resolve serverHost ip for {serverHost}"); serverHostIp = ipv4.ToString(); } var serverChannel = Utils.RemoteChannel(serverHostIp, serverPort); var publication = _client.AddExclusivePublication(serverChannel, AeronServer.ServerStreamId); var localIp = UdpUtils.GetLocalIPAddress(serverHostIp, serverPort); var streamId = MachineCounters.Instance.GetNewClientStreamId(); GetChannelAndSubscription(localIp, streamId, out var clientChannel, out var subscription); var session = new AeronClientSession(this, serverChannel, publication, subscription, onConnectedDelegate, onDisconnectedDelegate, onMessageReceived); var connectionId = AddSession(session); _log.Info($"Connecting: {session}"); var handshakeRequest = new AeronHandshakeRequest { Channel = clientChannel, StreamId = streamId }; if (!session.SendHandshake(handshakeRequest, connectionResponseTimeoutMs)) { RemoveSession(session); session.Dispose(); return(-1); } return(connectionId); }