private void HandleInboundAssociation(InboundAssociation ia, bool writerIsIdle)
{
var readonlyEndpoint = _endpoints.ReadOnlyEndpointFor(ia.Association.RemoteAddress);
var handle = ((AkkaProtocolHandle)ia.Association);
if (readonlyEndpoint != null)
{
var endpoint = readonlyEndpoint.Item1;
if (_pendingReadHandoffs.ContainsKey(endpoint)) _pendingReadHandoffs[endpoint].Disassociate();
_pendingReadHandoffs.AddOrSet(endpoint, handle);
endpoint.Tell(new EndpointWriter.TakeOver(handle, Self));
_endpoints.WritableEndpointWithPolicyFor(handle.RemoteAddress).Match()
.With<Pass>(pass =>
{
pass.Endpoint.Tell(new ReliableDeliverySupervisor.Ungate());
});
}
else
{
if (_endpoints.IsQuarantined(handle.RemoteAddress, handle.HandshakeInfo.Uid))
handle.Disassociate(DisassociateInfo.Quarantined);
else
{
var policy = _endpoints.WritableEndpointWithPolicyFor(handle.RemoteAddress);
var pass = policy as Pass;
if (pass != null && !pass.Uid.HasValue)
{
// Idle writer will never send a GotUid or a Terminated so we need to "provoke it"
// to get an unstash event
if (!writerIsIdle)
{
pass.Endpoint.Tell(ReliableDeliverySupervisor.IsIdle.Instance);
var stashedInboundForEp = _stashedInbound.GetOrElse(pass.Endpoint,
new List<InboundAssociation>());
stashedInboundForEp.Add(ia);
_stashedInbound[pass.Endpoint] = stashedInboundForEp;
}
else
{
CreateAndRegisterEndpoint(handle, _endpoints.RefuseUid(handle.RemoteAddress));
}
}
else if (pass != null) // has a UID value
{
if (handle.HandshakeInfo.Uid == pass.Uid)
{
_pendingReadHandoffs.GetOrElse(pass.Endpoint, null)?.Disassociate();
_pendingReadHandoffs.AddOrSet(pass.Endpoint, handle);
pass.Endpoint.Tell(new EndpointWriter.StopReading(pass.Endpoint, Self));
pass.Endpoint.Tell(new ReliableDeliverySupervisor.Ungate());
}
else
{
Context.Stop(pass.Endpoint);
_endpoints.UnregisterEndpoint(pass.Endpoint);
_pendingReadHandoffs.Remove(pass.Endpoint);
CreateAndRegisterEndpoint(handle, pass.Uid);
}
}
else
{
CreateAndRegisterEndpoint(handle, _endpoints.RefuseUid(handle.RemoteAddress));
}
}
}
}