private void OnConnectionReceive(TcpConnection connection, object packet)
{
// The thread that call this function is different from actor context thread.
// To deal with this contention lock protection is required.
var p = packet as Packet;
if (p == null)
{
_eventStream.Publish(new Warning(
_self.Path.ToString(), GetType(),
$"Receives null packet from {_connection?.RemoteEndPoint}"));
return;
}
var msg = p.Message as IInterfacedPayload;
if (msg == null)
{
_eventStream.Publish(new Warning(
_self.Path.ToString(), GetType(),
$"Receives a bad packet without a message from {_connection?.RemoteEndPoint}"));
return;
}
var actor = GetBoundActor(p.ActorId);
if (actor == null)
{
if (p.RequestId != 0)
{
_connection.Send(new Packet
{
Type = PacketType.Response,
ActorId = p.ActorId,
RequestId = p.RequestId,
Message = null,
Exception = new RequestTargetException()
});
}
return;
}
var boundType = actor.FindBoundType(msg.GetInterfaceType());
if (boundType == null)
{
if (p.RequestId != 0)
{
_connection.Send(new Packet
{
Type = PacketType.Response,
ActorId = p.ActorId,
RequestId = p.RequestId,
Message = null,
Exception = new RequestHandlerNotFoundException()
});
}
return;
}
if (boundType.IsTagOverridable)
{
var tagOverridable = (IPayloadTagOverridable)p.Message;
tagOverridable.SetTag(boundType.TagValue);
}
var observerUpdatable = p.Message as IPayloadObserverUpdatable;
if (observerUpdatable != null)
{
observerUpdatable.Update(o =>
{
var observer = (InterfacedObserver)o;
if (observer != null)
observer.Channel = new AkkaReceiverNotificationChannel(_self);
});
}
actor.Actor.Tell(new RequestMessage
{
RequestId = p.RequestId,
InvokePayload = (IInterfacedPayload)p.Message
}, _self);
}
}