public void Properly_quarantine_stashed_inbound_connections() { var localAddress = new Address("akka.test", "system1", "localhost", 1); var rawLocalAddress = new Address("test", "system1", "localhost", 1); var remoteAddress = new Address("akka.test", "system2", "localhost", 2); var rawRemoteAddress = new Address("test", "system2", "localhost", 2); var remoteUID = 16; var config = ConfigurationFactory.ParseString(@" akka.remote.enabled-transports = [""akka.remote.test""] akka.remote.retry-gate-closed-for = 5s akka.remote.log-remote-lifecycle-events = on akka.remote.test { registry-key = JMeMndLLsw local-address = """ + $"test://{localAddress.System}@{localAddress.Host}:{localAddress.Port}" + @""" }").WithFallback(_remoteSystem.Settings.Config); var thisSystem = ActorSystem.Create("this-system", config); MuteSystem(thisSystem); try { // Set up a mock remote system using the test transport var registry = AssociationRegistry.Get("JMeMndLLsw"); var remoteTransport = new TestTransport(rawRemoteAddress, registry); var remoteTransportProbe = CreateTestProbe(); registry.RegisterTransport(remoteTransport, Task.FromResult <IAssociationEventListener> (new ActorAssociationEventListener(remoteTransportProbe))); // Hijack associations through the test transport AwaitCondition(() => registry.TransportsReady(rawLocalAddress, rawRemoteAddress)); var testTransport = registry.TransportFor(rawLocalAddress).Item1; testTransport.WriteBehavior.PushConstant(true); // Force an outbound associate on the real system (which we will hijack) // we send no handshake packet, so this remains a pending connection var dummySelection = thisSystem.ActorSelection(ActorPath.Parse(remoteAddress + "/user/noonethere")); dummySelection.Tell("ping", Sys.DeadLetters); var remoteHandle = remoteTransportProbe.ExpectMsg <InboundAssociation>(TimeSpan.FromMinutes(4)); remoteHandle.Association.ReadHandlerSource.TrySetResult((IHandleEventListener)(new ActionHandleEventListener(ev => {}))); // Now we initiate an emulated inbound connection to the real system var inboundHandleProbe = CreateTestProbe(); var inboundHandleTask = remoteTransport.Associate(rawLocalAddress); inboundHandleTask.Wait(TimeSpan.FromSeconds(3)); var inboundHandle = inboundHandleTask.Result; inboundHandle.ReadHandlerSource.SetResult(new ActorHandleEventListener(inboundHandleProbe)); AwaitAssert(() => { registry.GetRemoteReadHandlerFor(inboundHandle.AsInstanceOf <TestAssociationHandle>()).Should().NotBeNull(); }); var pduCodec = new AkkaPduProtobuffCodec(Sys); var handshakePacket = pduCodec.ConstructAssociate(new HandshakeInfo(rawRemoteAddress, remoteUID)); // Finish the inbound handshake so now it is handed up to Remoting inboundHandle.Write(handshakePacket); // No disassociation now, the connection is still stashed inboundHandleProbe.ExpectNoMsg(1000); // Quarantine unrelated connection RARP.For(thisSystem).Provider.Quarantine(remoteAddress, -1); inboundHandleProbe.ExpectNoMsg(1000); // Quarantine the connection RARP.For(thisSystem).Provider.Quarantine(remoteAddress, remoteUID); // Even though the connection is stashed it will be disassociated inboundHandleProbe.ExpectMsg <Disassociated>(); } finally { Shutdown(thisSystem); } }
public void Stash_inbound_connections_until_UID_is_known_for_pending_outbound() { var localAddress = new Address("akka.test", "system1", "localhost", 1); var rawLocalAddress = new Address("test", "system1", "localhost", 1); var remoteAddress = new Address("akka.test", "system2", "localhost", 2); var rawRemoteAddress = new Address("test", "system2", "localhost", 2); var config = ConfigurationFactory.ParseString(@" akka.remote.enabled-transports = [""akka.remote.test""] akka.remote.retry-gate-closed-for = 5s akka.remote.log-remote-lifecycle-events = on akka.loglevel = DEBUG akka.remote.test { registry-key = TRKAzR local-address = """ + $"test://{localAddress.System}@{localAddress.Host}:{localAddress.Port}" + @""" }").WithFallback(_remoteSystem.Settings.Config); var thisSystem = ActorSystem.Create("this-system", config); MuteSystem(thisSystem); try { // Set up a mock remote system using the test transport var registry = AssociationRegistry.Get("TRKAzR"); var remoteTransport = new TestTransport(rawRemoteAddress, registry); var remoteTransportProbe = CreateTestProbe(); registry.RegisterTransport(remoteTransport, Task.FromResult <IAssociationEventListener> (new ActorAssociationEventListener(remoteTransportProbe))); // Hijack associations through the test transport AwaitCondition(() => registry.TransportsReady(rawLocalAddress, rawRemoteAddress)); var testTransport = registry.TransportFor(rawLocalAddress).Item1; testTransport.WriteBehavior.PushConstant(true); // Force an outbound associate on the real system (which we will hijack) // we send no handshake packet, so this remains a pending connection var dummySelection = thisSystem.ActorSelection(ActorPath.Parse(remoteAddress + "/user/noonethere")); dummySelection.Tell("ping", Sys.DeadLetters); var remoteHandle = remoteTransportProbe.ExpectMsg <InboundAssociation>(TimeSpan.FromMinutes(4)); remoteHandle.Association.ReadHandlerSource.TrySetResult((IHandleEventListener)(new ActionHandleEventListener(ev => { }))); // Now we initiate an emulated inbound connection to the real system var inboundHandleProbe = CreateTestProbe(); var inboundHandleTask = remoteTransport.Associate(rawLocalAddress); inboundHandleTask.Wait(TimeSpan.FromSeconds(3)); var inboundHandle = inboundHandleTask.Result; inboundHandle.ReadHandlerSource.SetResult(new ActorHandleEventListener(inboundHandleProbe)); AwaitAssert(() => { registry.GetRemoteReadHandlerFor(inboundHandle.AsInstanceOf <TestAssociationHandle>()).Should().NotBeNull(); }); var pduCodec = new AkkaPduProtobuffCodec(Sys); var handshakePacket = pduCodec.ConstructAssociate(new HandshakeInfo(rawRemoteAddress, 0)); var brokenPacket = pduCodec.ConstructPayload(ByteString.CopyFrom(0, 1, 2, 3, 4, 5, 6)); // Finish the inbound handshake so now it is handed up to Remoting inboundHandle.Write(handshakePacket); // Now bork the connection with a malformed packet that can only signal an error if the Endpoint is already registered // but not while it is stashed inboundHandle.Write(brokenPacket); // No disassociation now - the connection is still stashed inboundHandleProbe.ExpectNoMsg(1000); // Finish the handshake for the outbound connection - this will unstash the inbound pending connection. remoteHandle.Association.Write(handshakePacket); inboundHandleProbe.ExpectMsg <Disassociated>(TimeSpan.FromMinutes(5)); } finally { Shutdown(thisSystem); } }