package jReto.meta; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import de.tum.in.www1.jReto.LocalPeer; import de.tum.in.www1.jReto.RemotePeer; import de.tum.in.www1.jReto.module.api.Module; import de.tum.in.www1.jReto.routing.Router; import jReto.module.dummy.DummyModule; import jReto.module.dummy.DummyNetworkInterface; import jReto.util.RunLoop; /** * A PeerConfiguration provides various configurations of peers, used to test communication between two peers. * */ public class PeerConfiguration { public final RunLoop runloop; public final LocalPeer peer1; public final LocalPeer peer2; public final List<LocalPeer> participatingPeers; public final List<LocalPeer> reachablePeers; public final List<LocalPeer> destinations; public static List<LocalPeer> destinationPeerList(LocalPeer peer1, List<LocalPeer> participatingPeers) { List<LocalPeer> result = new ArrayList<>(participatingPeers); result.remove(peer1); return result; } public PeerConfiguration(RunLoop runloop, LocalPeer peer1, LocalPeer peer2, List<LocalPeer> participatingPeers) { this(runloop, peer1, peer2, participatingPeers, participatingPeers); } public PeerConfiguration(RunLoop runloop, LocalPeer peer1, LocalPeer peer2, List<LocalPeer> participatingPeers, List<LocalPeer> reachablePeers) { this(runloop, peer1, peer2, participatingPeers, reachablePeers, Arrays.asList(peer2)); } public PeerConfiguration(RunLoop runloop, LocalPeer peer1, LocalPeer peer2, List<LocalPeer> participatingPeers, List<LocalPeer> reachablePeers, List<LocalPeer> destinations) { this.runloop = runloop; this.peer1 = peer1; this.peer2 = peer2; this.participatingPeers = participatingPeers; this.reachablePeers = reachablePeers; this.destinations = destinations; } public Set<UUID> getMulticastDestinationIdentifiers() { Set<UUID> results = new HashSet<>(); for (LocalPeer peer : this.destinations) results.add(peer.getUniqueIdentifier()); return results; } public Set<UUID> getReachablePeerIdentifiers() { Set<UUID> results = new HashSet<>(); for (LocalPeer peer : this.reachablePeers) results.add(peer.getUniqueIdentifier()); return results; } public Set<RemotePeer> getMulticastDestinations(LocalPeer peer) { HashSet<RemotePeer> destinations = new HashSet<>(); Set<UUID> multicastIdentifiers = this.getMulticastDestinationIdentifiers(); for (RemotePeer remotePeer : peer.getPeers()) { if (multicastIdentifiers.contains(remotePeer.getUniqueIdentifier())) destinations.add(remotePeer); } return destinations; } public void startAndExecuteAfterDiscovery(final Runnable onDiscoveryComplete) { final Map<LocalPeer, Set<UUID>> discoveredPeersByPeer = new HashMap<>(); for (final LocalPeer reachablePeer : reachablePeers) { discoveredPeersByPeer.put(reachablePeer, new HashSet<UUID>()); discoveredPeersByPeer.get(reachablePeer).add(reachablePeer.getUniqueIdentifier()); } for (LocalPeer participatingPeer : participatingPeers) { if (reachablePeers.contains(participatingPeer)) { participatingPeer.start(peer -> { System.err.println("Discovered peer: "+peer.getUniqueIdentifier()); discoveredPeersByPeer.get(participatingPeer).add(peer.getUniqueIdentifier()); boolean allDiscovered = true; Set<UUID> allReachablePeers = getReachablePeerIdentifiers(); for (Set<UUID> identifiers : discoveredPeersByPeer.values()) { if (!identifiers.equals(new HashSet<>(allReachablePeers))) { allDiscovered = false; } } if (allDiscovered) onDiscoveryComplete.run(); }, peer -> {}); } else { participatingPeer.start(peer -> {}, peer -> {}); } } this.runloop.start(); } public static LocalPeer createLocalPeer(RunLoop runloop, Module... modules) { return new LocalPeer(UUID.randomUUID(), Arrays.asList(modules), runloop, new Router.BroadcastDelaySettings(0.2, 0.1)); } /** * A simple peer configuration that allows direct communication. * */ public static PeerConfiguration directNeighborConfiguration() { final RunLoop runloop = new RunLoop(false); DummyNetworkInterface manager = new DummyNetworkInterface("test", runloop, 1024, 1); final LocalPeer localPeer1 = createLocalPeer(runloop, new DummyModule(manager, runloop)); final LocalPeer localPeer2 = createLocalPeer(runloop, new DummyModule(manager, runloop)); return new PeerConfiguration(runloop, localPeer1, localPeer2, Arrays.asList(localPeer1, localPeer2)); } /** * A peer configuration that allows communication via 2 hops. * */ public static PeerConfiguration twoHopRoutedConfiguration() { final RunLoop runloop = new RunLoop(false); DummyNetworkInterface manager1 = new DummyNetworkInterface("test1", runloop, 1024, 1); DummyNetworkInterface manager2 = new DummyNetworkInterface("test2", runloop, 1024, 1); final LocalPeer localPeer1 = createLocalPeer(runloop, new DummyModule(manager1, runloop)); final LocalPeer localPeer2 = createLocalPeer(runloop, new DummyModule(manager2, runloop)); final LocalPeer localPeer3 = createLocalPeer(runloop, new DummyModule(manager1, runloop), new DummyModule(manager2, runloop)); return new PeerConfiguration(runloop, localPeer1, localPeer2, Arrays.asList(localPeer1, localPeer2, localPeer3)); } /** * A peer configuration that allows communication via 2 hops and multicasts to both peers. * */ public static PeerConfiguration twoHopRoutedMulticastConfiguration() { PeerConfiguration config = PeerConfiguration.twoHopRoutedConfiguration(); return new PeerConfiguration(config.runloop, config.peer1, config.peer2, config.participatingPeers, config.reachablePeers, destinationPeerList(config.peer1, config.participatingPeers)); } /** * A peer configuration that allows communication via 4 hops. * */ public static PeerConfiguration fourHopRoutedConfiguration() { final RunLoop runloop = new RunLoop(false); DummyNetworkInterface manager1 = new DummyNetworkInterface("test1", runloop, 1024, 1); DummyNetworkInterface manager2 = new DummyNetworkInterface("test2", runloop, 1024, 1); DummyNetworkInterface manager3 = new DummyNetworkInterface("test3", runloop, 1024, 1); DummyNetworkInterface manager4 = new DummyNetworkInterface("test4", runloop, 1024, 1); final LocalPeer localPeer1 = createLocalPeer(runloop, new DummyModule(manager1, runloop)); final LocalPeer localPeer4 = createLocalPeer(runloop, new DummyModule(manager4, runloop)); final LocalPeer localPeer12 = createLocalPeer(runloop, new DummyModule(manager1, runloop), new DummyModule(manager2, runloop)); final LocalPeer localPeer23 = createLocalPeer(runloop, new DummyModule(manager2, runloop), new DummyModule(manager3, runloop)); final LocalPeer localPeer34 = createLocalPeer(runloop, new DummyModule(manager3, runloop), new DummyModule(manager4, runloop)); return new PeerConfiguration(runloop, localPeer1, localPeer4, Arrays.asList(localPeer1, localPeer4, localPeer12, localPeer23, localPeer34)); } /** * A peer configuration that allows communication via 4 hops and multicasts to all peers. * */ public static PeerConfiguration fourHopRoutedMulticastConfiguration() { PeerConfiguration config = PeerConfiguration.fourHopRoutedConfiguration(); return new PeerConfiguration(config.runloop, config.peer1, config.peer2, config.participatingPeers, config.reachablePeers, destinationPeerList(config.peer1, config.participatingPeers)); } /** * A peer configuration that contains a direct route, but a cheaper route via another peer (cost: 10 vs. 2). * */ public static PeerConfiguration nontrivial2HopNetworkConfiguration() { final RunLoop runloop = new RunLoop(false); DummyNetworkInterface manager1 = new DummyNetworkInterface("test1", runloop, 1024, 1); DummyNetworkInterface manager2 = new DummyNetworkInterface("test2", runloop, 1024, 1); DummyNetworkInterface manager3 = new DummyNetworkInterface("test3", runloop, 1024, 10); DummyNetworkInterface manager4 = new DummyNetworkInterface("test4", runloop, 1024, 15); final LocalPeer localPeer1 = createLocalPeer(runloop, new DummyModule(manager1, runloop), new DummyModule(manager3, runloop)); final LocalPeer localPeer2 = createLocalPeer(runloop, new DummyModule(manager2, runloop), new DummyModule(manager3, runloop)); final LocalPeer localPeer3 = createLocalPeer(runloop, new DummyModule(manager1, runloop), new DummyModule(manager2, runloop), new DummyModule(manager4, runloop)); final LocalPeer localPeer4 = createLocalPeer(runloop, new DummyModule(manager4, runloop)); return new PeerConfiguration(runloop, localPeer1, localPeer2, Arrays.asList(localPeer1, localPeer2, localPeer3, localPeer4)); } /** * A peer configuration that contains a direct route, but a cheaper route via another peer (cost: 10 vs. 2). * */ public static PeerConfiguration nontrivial2HopNetworkMulticastConfiguration() { PeerConfiguration config = PeerConfiguration.fourHopRoutedConfiguration(); return new PeerConfiguration(config.runloop, config.peer1, config.peer2, config.participatingPeers, config.reachablePeers, destinationPeerList(config.peer1, config.participatingPeers)); } /** * A peer configuration that includes two peers that cannot connect to peer1 and peer2. * */ public static PeerConfiguration configurationWithDisconnectedPeers() { final RunLoop runloop = new RunLoop(false); DummyNetworkInterface manager1 = new DummyNetworkInterface("test1", runloop, 1024, 1); DummyNetworkInterface manager2 = new DummyNetworkInterface("test2", runloop, 1024, 1); DummyNetworkInterface manager3 = new DummyNetworkInterface("test3", runloop, 1024, 10); DummyNetworkInterface manager4 = new DummyNetworkInterface("test4", runloop, 1024, 15); final LocalPeer localPeer1 = createLocalPeer(runloop, new DummyModule(manager1, runloop), new DummyModule(manager2, runloop)); final LocalPeer localPeer2 = createLocalPeer(runloop, new DummyModule(manager1, runloop), new DummyModule(manager2, runloop)); final LocalPeer localPeer3 = createLocalPeer(runloop, new DummyModule(manager3, runloop), new DummyModule(manager4, runloop)); final LocalPeer localPeer4 = createLocalPeer(runloop, new DummyModule(manager3, runloop)); return new PeerConfiguration(runloop, localPeer1, localPeer2, Arrays.asList(localPeer1, localPeer2, localPeer3, localPeer4), Arrays.asList(localPeer1, localPeer2)); } /** * A peer configuration that contains a direct route, but a cheaper route via another peer (cost: 10 vs. 2). * */ public static PeerConfiguration multicastConfigurationWithDisconnectedPeers() { PeerConfiguration config = PeerConfiguration.configurationWithDisconnectedPeers(); return new PeerConfiguration(config.runloop, config.peer1, config.peer2, config.participatingPeers, config.reachablePeers, destinationPeerList(config.peer1, config.reachablePeers)); } }