After much thought, prototyping and research I've finally implemented the solution using Events and Delegates and its working quite well!
The only major design problem is that there will be cases where messages will enter an infinite loop if, for example, 3 distribution nodes were connected in a triangle. Or if a node is connected to itself or 2 nodes connected to each other more than once. I covered each of these edge cases with some simple logic in the event listener connections:
public bool ConnectTo(Node peerNode)
{
EthernetPort peerPort = peerNode.GetFreePort();
EthernetPort myPort = this.GetFreePort();
// Perform a check for free ports for both peers:
if (peerPort == null || myPort == null)
return false; // Either myself or my peer do not have a spare port.
// Perform a check to make sure these nodes aren't already connected:
if (this.HasConnectedNode(peerNode))
return false;
// Connect the two ports:
myPort.Connect(peerNode, peerPort);
peerPort.Connect(this, myPort);
return true;
}
public bool HasConnectedNode(Node node) {
foreach (var port in ethernetSwitch.ethernetPorts)
{
if (port.peerNode == node)
return true; // Found a port already connected to this node.
}
return false; // No port has this node connected to it.
}
Finally, just in case I missed something or to simply feel safe about it, I implemented a custom EventArgs
type with a int timeToLive
variable. This variable is decremented each time a node handles the message and if it hits 0 then the message is discarded.