|
| 1 | +package middle; |
| 2 | + |
| 3 | +import commons.CommonRails; |
| 4 | +import middle.director.*; |
| 5 | + |
| 6 | +import java.io.*; |
| 7 | +import java.net.InetAddress; |
| 8 | +import java.net.ServerSocket; |
| 9 | +import java.net.Socket; |
| 10 | +import java.util.List; |
| 11 | +import java.util.concurrent.CopyOnWriteArrayList; |
| 12 | + |
| 13 | +/** |
| 14 | + * MiddleDirectorServer — listens on port 8888, synchronizes finance and target goals |
| 15 | + * across middle nodes and forwards finalized content to national NWE installations (49152). |
| 16 | + * |
| 17 | + * Modules are loaded from configuration/middle-director-modules.xml. |
| 18 | + */ |
| 19 | +public class MiddleDirectorServer extends Thread |
| 20 | +{ |
| 21 | + public static final int PORT = 8888; |
| 22 | + |
| 23 | + private final String HOST; |
| 24 | + private ServerSocket serverSocket; |
| 25 | + |
| 26 | + /** Active director modules. */ |
| 27 | + private final List<DirectorModule> modules = new CopyOnWriteArrayList<>(); |
| 28 | + |
| 29 | + /** Known peer middle nodes (host:port). */ |
| 30 | + private final List<String> middlePeers = new CopyOnWriteArrayList<>(); |
| 31 | + |
| 32 | + /** Known national NWE endpoints (host:49152). */ |
| 33 | + private final List<String> nationalEndpoints = new CopyOnWriteArrayList<>(); |
| 34 | + |
| 35 | + public MiddleDirectorServer(final String HOST) |
| 36 | + { |
| 37 | + this.HOST = HOST; |
| 38 | + this.setName("MiddleDirectorServer-8888"); |
| 39 | + this.setDaemon(true); |
| 40 | + loadModules(); |
| 41 | + } |
| 42 | + |
| 43 | + private void loadModules() |
| 44 | + { |
| 45 | + modules.add(new ShortHopsModule()); |
| 46 | + modules.add(new MediumHopsModule()); |
| 47 | + modules.add(new ThoughtsAsGoalsModule()); |
| 48 | + modules.add(new FinalMediumHopsModule()); |
| 49 | + modules.add(new GamesAsGoalsModule()); |
| 50 | + modules.add(new AuditorContentModule()); |
| 51 | + } |
| 52 | + |
| 53 | + @Override |
| 54 | + public void run() |
| 55 | + { |
| 56 | + try |
| 57 | + { |
| 58 | + serverSocket = new ServerSocket(PORT, 64, InetAddress.getByName(HOST)); |
| 59 | + CommonRails.printSystemComponent(this, this.hashCode(), |
| 60 | + ". MiddleDirectorServer listening on " + HOST + ":" + PORT + " ."); |
| 61 | + |
| 62 | + while (!Thread.currentThread().isInterrupted()) |
| 63 | + { |
| 64 | + Socket client = serverSocket.accept(); |
| 65 | + Thread.ofVirtual().start(() -> handle(client)); |
| 66 | + } |
| 67 | + } |
| 68 | + catch (IOException e) { exceptions.ExceptionHandler.dispatch(e); } |
| 69 | + } |
| 70 | + |
| 71 | + private void handle(final Socket CLIENT) |
| 72 | + { |
| 73 | + try ( |
| 74 | + BufferedReader in = new BufferedReader(new InputStreamReader(CLIENT.getInputStream())); |
| 75 | + BufferedWriter out = new BufferedWriter(new OutputStreamWriter(CLIENT.getOutputStream())) |
| 76 | + ) |
| 77 | + { |
| 78 | + String line; |
| 79 | + while ((line = in.readLine()) != null) |
| 80 | + { |
| 81 | + line = line.trim(); |
| 82 | + if (line.isEmpty()) continue; |
| 83 | + if (line.equalsIgnoreCase("quit")) break; |
| 84 | + |
| 85 | + String result = processGoal(line); |
| 86 | + out.write(result + "\r\n"); |
| 87 | + out.flush(); |
| 88 | + } |
| 89 | + } |
| 90 | + catch (Exception e) { exceptions.ExceptionHandler.dispatch(e); } |
| 91 | + finally { try { CLIENT.close(); } catch (Exception ignored) {} } |
| 92 | + } |
| 93 | + |
| 94 | + /** |
| 95 | + * Passes content through each module in sequence, then routes the result. |
| 96 | + */ |
| 97 | + private String processGoal(final String INPUT) |
| 98 | + { |
| 99 | + String payload = INPUT; |
| 100 | + for (DirectorModule module : modules) |
| 101 | + { |
| 102 | + payload = module.process(payload); |
| 103 | + } |
| 104 | + return payload; |
| 105 | + } |
| 106 | + |
| 107 | + // ── Forwarding ─────────────────────────────────────────────────────────── |
| 108 | + |
| 109 | + /** Send content to another middle node. */ |
| 110 | + public void sendToMiddle(final String HOST, final int PORT, final String CONTENT) |
| 111 | + { |
| 112 | + forward(HOST, PORT, CONTENT); |
| 113 | + } |
| 114 | + |
| 115 | + /** Send content to a national NWE installation (port 49152). */ |
| 116 | + public void sendToNational(final String HOST, final String CONTENT) |
| 117 | + { |
| 118 | + forward(HOST, 49152, CONTENT); |
| 119 | + } |
| 120 | + |
| 121 | + private void forward(final String HOST, final int PORT, final String CONTENT) |
| 122 | + { |
| 123 | + try (Socket s = new Socket(HOST, PORT); |
| 124 | + BufferedWriter w = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()))) |
| 125 | + { |
| 126 | + w.write(CONTENT + "\r\n"); |
| 127 | + w.flush(); |
| 128 | + CommonRails.printSystemComponent(this, this.hashCode(), |
| 129 | + ". MiddleDirector forwarded to " + HOST + ":" + PORT + " ."); |
| 130 | + } |
| 131 | + catch (IOException e) { exceptions.ExceptionHandler.dispatch(e); } |
| 132 | + } |
| 133 | + |
| 134 | + public void addMiddlePeer(String hostPort) { middlePeers.add(hostPort); } |
| 135 | + public void addNationalEndpoint(String host) { nationalEndpoints.add(host); } |
| 136 | + public List<String> getMiddlePeers() { return middlePeers; } |
| 137 | + public List<String> getNationalEndpoints() { return nationalEndpoints; } |
| 138 | +} |
0 commit comments