// Runs one of FILIUS' own example files (corpus/java-examples) in Java FILIUS, // loaded and started as FILIUS opens and starts it (ScenarioNetwork.fromFile), // plays a story on it and records every frame each card saw, the capture's // tables, the story's calls and each host's addresses at the end. // // ExampleRun // // The stories: // routing internetwork_komplett: Notebook 1.10 pings Webserver 5.10 across // three routers; then Notebook 1.11, which has no gateway // dhcp einfaches_rechnernetz_komplett: four notebooks get addresses // from the server // dns dns_server: the notebook asks its DNS server (recursive) for // www.filius.de, then for the mail server of filius.de // nat nat_with_mapped_port: Notebook 1.10 (behind Heimrouter Paul) // pings Webserver www.jupiter.de, then Heimrouter Vincent's WAN // address // firewall Internet_Komplett_…_DE: when the DHCP clients have their // addresses (8 s), iPad 1 (its network dropped by the firewall, // which leaves ICMP to its own switch) pings mail.gmx.de, then // the first Notebook (accepted), then mail.gmx.de pings the // firewall's WAN address. Targets with one shortest RIP path // each: where two are equal, Java takes whichever its threads // learn first // // The classics of the classroom (the acceptance of F3), with what each // program told its window ("programs": time, program, text) and where each // ended ("end"): // web internetwork_komplett: Notebook 1.10 types www.filius.de into // its browser; the name is asked of DNS-Server 2.10 in another // network, the page comes from Webserver 5.10, two routers away // email Internet_Komplett_…_DE: when the DHCP clients have their // addresses (8 s), herbert@gmx.de (the first Notebook, in the // school's network behind the firewall) writes to // frimp@webmail.de; mail.gmx.de hands it on to mail.webmail.de // in another network; at 22 s frimp (Notebook#2) fetches. The // file keeps the programs' accounts only in the older kontoListe, // which FILIUS 2.14 no longer reads (the reader takes it, // importEmail.ts): they are set as one types them into the // program's account dialog, with the values the list holds // gnutella zwei_rechnernetze_komplett with FILIUS' Gnutella program on // Notebook 1.10, Notebook 1.11 and DNS-Server 2.10 (in the other // network; it shares "Lied der Woche.txt"), each keeping three // peers: 1.10 joins 2.10; 1.11 joins 1.10 (its ping goes on to // 2.10, the pong comes back through 1.10); 1.10 searches "woche" // (1.11 passes the query on) and downloads the hit through the // router (1.11 has no gateway: it could not fetch from the other // network) import filius.hardware.knoten.Knoten; import filius.software.dateiaustausch.PeerToPeerAnwendung; import filius.software.dns.Resolver; import filius.software.email.Email; import filius.software.email.EmailAnwendung; import filius.software.email.EmailKonto; import filius.software.email.EmailServer; import filius.software.email.EmailUtils; import filius.software.system.Datei; import filius.software.www.HTTPNachricht; import filius.software.www.WebBrowser; import filius.software.www.WebServer; import filius.software.rip.RIPRoute; import filius.software.rip.RIPTable; import filius.software.system.VermittlungsrechnerBetriebssystem; import filius.software.system.InternetKnotenBetriebssystem; import filius.software.vermittlungsschicht.IcmpPaket; import java.util.ArrayList; import java.util.List; import java.util.Map; public class ExampleRun { static ScenarioNetwork network; static final List events = new ArrayList<>(); /** Every change of a RIP router's table: time, router, table. */ static final List ripChanges = new ArrayList<>(); static final Map lastTables = new java.util.HashMap<>(); /** A RIP router's table as one line: `network/mask gateway interface hops; …`, in its order. */ static String tableText(RIPTable table) { StringBuilder text = new StringBuilder(); synchronized (table) { for (RIPRoute route : table.routes) { if (text.length() > 0) text.append("; "); text.append(route.getNetAddress()).append('/').append(route.getNetMask()).append(' ').append(route.getGateway()) .append(' ').append(route.getInterfaceIpAddress()).append(' ').append(route.hops); } } return text.toString(); } static synchronized void pollTables() { for (Map.Entry entry : network.nodes.entrySet()) { if (!(entry.getValue().getSystemSoftware() instanceof VermittlungsrechnerBetriebssystem)) continue; RIPTable table = ((VermittlungsrechnerBetriebssystem) entry.getValue().getSystemSoftware()).getRIPTable(); if (table == null) continue; String text = tableText(table); if (!text.equals(lastTables.get(entry.getKey()))) { lastTables.put(entry.getKey(), text); ripChanges.add(new Object[] { System.currentTimeMillis() - network.start, entry.getKey(), text }); } } } static synchronized void event(String what) { events.add(new Object[] { System.currentTimeMillis() - network.start, what }); } /** What a program told its window: time, program, text. */ static final List told = new ArrayList<>(); static synchronized void tell(String program, String text) { told.add(new Object[] { System.currentTimeMillis() - network.start, program, text }); } static T program(String node, String name) { @SuppressWarnings("unchecked") T program = (T) network.system(node).holeSoftware(name); return program; } static void watchServer(String node, String program) { filius.software.Anwendung server = program(node, program.equals("webServer") ? "filius.software.www.WebServer" : "filius.software.email.EmailServer"); server.hinzuBeobachter((observable, data) -> tell(node, String.valueOf(data))); } /** GUIApplicationEmailAnwendungWindow's send button, as EmailClientRun makes it. */ static void send(EmailAnwendung program, EmailKonto account, String to, String subject, String text) { Email mail = new Email(); mail.setAbsender(account.getVorname() + (!account.getNachname().isEmpty() ? (" " + account.getNachname()) : "") + " <" + account.getEmailAdresse() + ">"); mail.setEmpfaenger(EmailUtils.stringToAddressEntryList(to)); mail.setCc(EmailUtils.stringToAddressEntryList("")); mail.setBcc(EmailUtils.stringToAddressEntryList("")); mail.setBetreff(subject); mail.setText(text); program.versendeEmail(account.getSmtpserver(), mail, account.getEmailAdresse()); } static EmailKonto account(EmailAnwendung program) { return program.holeKontoListe().values().iterator().next(); } /** The account dialog's fields: user, password, first name, last name, address, and the server for both POP3 and SMTP. */ static void setAccount(EmailAnwendung program, String user, String password, String first, String last, String address, String server) { EmailKonto account = new EmailKonto(); account.setBenutzername(user); account.setPasswort(password); account.setVorname(first); account.setNachname(last); account.setEmailAdresse(address); account.setPop3server(server); account.setPop3port("110"); account.setSmtpserver(server); account.setSmtpport("25"); program.setzeKonto(account); } static final String[] GNUTELLA_PEERS = { "Notebook 1.10", "Notebook 1.11", "DNS-Server 2.10" }; interface Call { String run() throws Exception; } static void call(String label, Call call) { event(label + " called"); try { event(label + " returned " + call.run()); } catch (Exception e) { event(label + " failed " + e.getClass().getSimpleName()); } } static String icmp(IcmpPaket packet) { return packet == null ? "null" : "ICMP " + packet.getIcmpType() + "/" + packet.getIcmpCode() + " from " + packet.getSender(); } static void ping(String node, String target, int sequence) { call("sendProbe " + target, () -> icmp(network.system(node).holeICMP().sendProbe(target, 64, 1, sequence))); } static Resolver resolver(String node) { return network.system(node).holeDNSClient(); } public static void main(String[] args) throws Exception { network = ScenarioNetwork.fromFile(args[0]); String story = args[1]; long end = Long.parseLong(args[2]); if (story.equals("web")) { watchServer("Webserver 5.10", "webServer"); WebBrowser browser = program("Notebook 1.10", "filius.software.www.WebBrowser"); browser.hinzuBeobachter((observable, data) -> { if (data instanceof HTTPNachricht) { HTTPNachricht page = (HTTPNachricht) data; tell("browser", "page " + page.getStatusCode() + " " + page.getContentType() + "\n" + page.getDaten()); } else { tell("browser", data == null ? "update" : String.valueOf(data)); } }); } if (story.equals("email")) { watchServer("mail.gmx.de (130.100.200.25)", "emailServer"); watchServer("mail.webmail.de (140.100.200.25)", "emailServer"); setAccount(program("Notebook", "filius.software.email.EmailAnwendung"), "herbert", "herbert1234", "Herbert", "Schmidt", "herbert@gmx.de", "mail.gmx.de"); setAccount(program("Notebook#2", "filius.software.email.EmailAnwendung"), "frimp", "frimp1234", "Frimp", "Mueller", "frimp@webmail.de", "mail.webmail.de"); for (String node : new String[] { "Notebook", "Notebook#2" }) { EmailAnwendung client = program(node, "filius.software.email.EmailAnwendung"); client.hinzuBeobachter((observable, data) -> tell(node, String.valueOf(data))); } } if (story.equals("gnutella")) { for (String node : GNUTELLA_PEERS) { network.system(node).installApp("filius.software.dateiaustausch.PeerToPeerAnwendung", false); PeerToPeerAnwendung peer = program(node, "filius.software.dateiaustausch.PeerToPeerAnwendung"); peer.setMaxTeilnehmerZahl(3); peer.hinzuBeobachter((observable, data) -> { tell(node, "peers " + String.join(",", peer.holeBekanntePeerToPeerTeilnehmer())); tell(node, "results " + String.join("|", peer.holeErgebnisse())); }); } network.system("DNS-Server 2.10").getDateisystem().speicherDatei("/peer2peer", new Datei("Lied der Woche.txt", "txt", "La la la")); } network.start(); Thread poller = new Thread(() -> { while (true) { pollTables(); try { Thread.sleep(2); } catch (InterruptedException e) { return; } } }); poller.setDaemon(true); poller.start(); Thread.sleep(500); switch (story) { case "routing": ping("Notebook 1.10", "141.99.5.10", 1); ping("Notebook 1.11", "141.99.5.10", 2); break; case "dhcp": break; case "dns": call("holeIPAdresse www.filius.de", () -> resolver("Notebook").holeIPAdresse("www.filius.de")); call("holeIPAdresseMailServer filius.de", () -> resolver("Notebook").holeIPAdresseMailServer("filius.de")); break; case "nat": ping("Notebook 1.10", "141.99.4.10", 1); ping("Notebook 1.10", "141.99.5.10", 2); break; case "firewall": Thread.sleep(7500); ping("iPad 1", "130.100.200.25", 1); ping("Notebook", "130.100.200.25", 2); ping("mail.gmx.de (130.100.200.25)", "42.0.0.10", 3); break; case "web": { tell("browser", "call holeWebseite www.filius.de"); WebBrowser browser = program("Notebook 1.10", "filius.software.www.WebBrowser"); browser.holeWebseite(WebRun.url("www.filius.de")); break; } case "email": { Thread.sleep(7500); EmailAnwendung herbert = program("Notebook", "filius.software.email.EmailAnwendung"); tell("Notebook", "call versendeEmail frimp@webmail.de"); send(herbert, account(herbert), "frimp@webmail.de", "Treffen", "Hallo Frimp,\nbis morgen!\nHerbert"); long until = network.start + 22000 - System.currentTimeMillis(); if (until > 0) Thread.sleep(until); EmailAnwendung frimp = program("Notebook#2", "filius.software.email.EmailAnwendung"); EmailKonto account = account(frimp); tell("Notebook#2", "call emailsAbholenEmails"); frimp.emailsAbholenEmails(account.getBenutzername(), account.getPasswort(), account.getPop3port(), account.getPop3server()); break; } case "gnutella": { PeerToPeerAnwendung searching = program("Notebook 1.10", "filius.software.dateiaustausch.PeerToPeerAnwendung"); PeerToPeerAnwendung near = program("Notebook 1.11", "filius.software.dateiaustausch.PeerToPeerAnwendung"); tell("Notebook 1.10", "call join 141.99.2.10"); searching.beitretenNetzwerk("141.99.2.10"); Thread.sleep(network.start + 3000 - System.currentTimeMillis()); tell("Notebook 1.11", "call join 141.99.1.10"); near.beitretenNetzwerk("141.99.1.10"); Thread.sleep(network.start + 5500 - System.currentTimeMillis()); tell("Notebook 1.10", "call search woche"); searching.sucheDatei("woche"); Thread.sleep(network.start + 8500 - System.currentTimeMillis()); tell("Notebook 1.10", "call download 0"); if (searching.holeErgebnisse().isEmpty()) tell("Notebook 1.10", "skipped download 0"); else searching.herunterladenDatei(0); break; } default: throw new IllegalArgumentException("unknown story " + story); } long rest = network.start + end - System.currentTimeMillis(); if (rest > 0) Thread.sleep(rest); ScenarioNetwork.Json out = new ScenarioNetwork.Json(); out.open('{'); network.writeFrames(out); network.writeDevices(out); // Every change of each RIP router's table (polled every 2 ms), as RipRun writes them. synchronized (ExampleRun.class) { out.key("ripTables").open('['); for (Object[] each : ripChanges) out.open('[').number((Long) each[0]).string((String) each[1]).string((String) each[2]).close(']'); out.close(']'); } synchronized (ExampleRun.class) { out.key("events").open('['); for (Object[] each : events) out.open('[').number((Long) each[0]).string((String) each[1]).close(']'); out.close(']'); } synchronized (ExampleRun.class) { out.key("programs").open('['); for (Object[] each : told) out.open('[').number((Long) each[0]).string((String) each[1]).string((String) each[2]).close(']'); out.close(']'); } // Where the programs ended: each e-mail server's accounts with their mails, each e-mail program's // inbox and sent mails (as EmailClientRun writes them); each Gnutella program's peers, results and files. out.key("end").open('{'); if (story.equals("email")) { for (String node : new String[] { "mail.gmx.de (130.100.200.25)", "mail.webmail.de (140.100.200.25)" }) { out.key(node); EmailClientRun.accounts(out, program(node, "filius.software.email.EmailServer")); } for (String node : new String[] { "Notebook", "Notebook#2" }) { EmailAnwendung client = program(node, "filius.software.email.EmailAnwendung"); out.key(node).open('{'); out.key("inbox"); EmailClientRun.mails(out, client.getEmpfangeneNachrichten()); out.key("sent"); EmailClientRun.mails(out, client.getGesendeteNachrichten()); out.close('}'); } } if (story.equals("gnutella")) { for (String node : GNUTELLA_PEERS) { PeerToPeerAnwendung peer = program(node, "filius.software.dateiaustausch.PeerToPeerAnwendung"); out.key(node).open('{'); out.key("peers").open('['); for (String each : peer.holeBekanntePeerToPeerTeilnehmer()) out.string(each); out.close(']'); out.key("results").open('['); for (String each : peer.holeErgebnisse()) out.string(each); out.close(']'); out.key("files").open('['); for (Datei file : network.system(node).getDateisystem().holeDateien(peer.holeVerzeichnis())) { out.open('[').string(file.getName()).string(file.getDateiTyp()).string(file.getDateiInhalt()).close(']'); } out.close(']'); out.close('}'); } } out.close('}'); out.close('}'); network.stop(); ScenarioNetwork.write(args[3], out); System.exit(0); } }