in src/AmqpSession.cs [599:656]
void OnReceiveLinkFrame(Frame frame)
{
AmqpLink link = null;
Performative command = frame.Command;
if (command.DescriptorCode == Attach.Code)
{
Attach attach = (Attach)command;
var linkIdentifier = new AmqpLinkIdentifier(attach.LinkName, !attach.IsReceiver(), this.Connection.Settings.ContainerId); // local Role will be opposite of the Role sent from remote for the same link.
lock (this.ThisLock)
{
this.links.TryGetValue(linkIdentifier, out link);
}
if (link == null || link.State >= AmqpObjectState.OpenReceived)
{
// If the link state is past OpenReceived, it means that the link has already received an Attach frame from remote, regardless if the link open was initiated by local or remote.
// A single link should receive Attach only once, therefore if the existing link has already received an Attach, then the current Attach must be intended for opening another link.
// In that case, we can try to open a new link and potentially do link stealing.
if (!this.TryCreateRemoteLink(attach, out link))
{
return;
}
}
else
{
// This scenario indicates that the existing link has already been created locally but no Attach has been received yet.
// This could only mean that the link open was initiated from local, so this Attach frame received is the reply from remote in response to the initial Attach sent by local.
// Therefore, we do not need to open or close anything from local side because we just need to complete the open process locally.
lock (this.ThisLock)
{
link.RemoteHandle = attach.Handle;
this.linksByRemoteHandle.Add(attach.Handle.Value, link);
}
}
}
else
{
LinkPerformative linkBody = (LinkPerformative)command;
if (!this.linksByRemoteHandle.TryGetObject(linkBody.Handle.Value, out link))
{
if (this.Settings.IgnoreMissingLinks)
{
AmqpTrace.Provider.AmqpMissingHandle(this, "link", linkBody.Handle.Value);
return;
}
if (linkBody.DescriptorCode != Detach.Code)
{
this.SafeClose(new AmqpException(AmqpErrorCode.UnattachedHandle, AmqpResources.GetString(AmqpResources.AmqpHandleNotFound, linkBody.Handle.Value, this)));
}
return;
}
}
link.ProcessFrame(frame);
}