diff --git a/README.md b/README.md new file mode 100644 index 0000000..b5d1886 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Setup +1. Get the `-server.jar` or `-client.jar` and make a new directory for it +2. Run the JAR, then stop it +3. Configure in `config` +4. Now run the JAR. Done! \ No newline at end of file diff --git a/src/main/java/eu/m724/autopeerer/client/Main.java b/src/main/java/eu/m724/autopeerer/client/Main.java index 6350240..772f439 100644 --- a/src/main/java/eu/m724/autopeerer/client/Main.java +++ b/src/main/java/eu/m724/autopeerer/client/Main.java @@ -18,6 +18,11 @@ public class Main { throw new RuntimeException("Failed to load configuration", e); } + if (config.isNew) { + System.out.println("The program stopped to let you configure"); + return; + } + URI serverUri = URI.create(config.getString("remote")); var wireGuardLive = new WireGuardLive(new File(config.getString("wireguard.directory"))); diff --git a/src/main/java/eu/m724/autopeerer/common/Configuration.java b/src/main/java/eu/m724/autopeerer/common/Configuration.java index cfde11d..77d0956 100644 --- a/src/main/java/eu/m724/autopeerer/common/Configuration.java +++ b/src/main/java/eu/m724/autopeerer/common/Configuration.java @@ -7,6 +7,7 @@ import java.nio.file.Files; import java.util.Properties; public class Configuration { + public final boolean isNew; public final File directory = new File("config"); private final File configFile; @@ -14,10 +15,11 @@ public class Configuration { public Configuration(String profile) { this.configFile = new File(directory, profile + ".properties"); + this.isNew = !configFile.exists(); } - public void load() throws IOException { + public boolean load() throws IOException { directory.mkdir(); if (!configFile.exists()) { @@ -25,11 +27,15 @@ public class Configuration { Files.write(configFile.toPath(), is.readAllBytes()); properties.load(is); } + return true; } + // this if already exists try (var is = new FileInputStream(configFile)) { properties.load(is); } + + return false; } public String getString(String property) { diff --git a/src/main/java/eu/m724/autopeerer/server/ClientState.java b/src/main/java/eu/m724/autopeerer/server/ClientState.java index d003d73..f04fcaf 100644 --- a/src/main/java/eu/m724/autopeerer/server/ClientState.java +++ b/src/main/java/eu/m724/autopeerer/server/ClientState.java @@ -5,6 +5,8 @@ import eu.m724.autopeerer.common.packet.Packets; import eu.m724.autopeerer.common.packet.c2s.PingResponsePacket; import eu.m724.autopeerer.common.packet.c2s.SessionResponsePacket; import eu.m724.autopeerer.common.packet.s2c.PingRequestPacket; +import eu.m724.autopeerer.common.packet.s2c.SessionRequestPacket; +import inet.ipaddr.ipv6.IPv6Address; import org.java_websocket.WebSocket; import java.net.InetAddress; @@ -50,10 +52,22 @@ public class ClientState { return future; } + CompletableFuture session(long asn, IPv6Address linkLocal, String publicKey, String endpointHost, int endpointPort) { + var future = new CompletableFuture(); + + sessionConsumers.put(asn, future::complete); + send(new SessionRequestPacket( + asn, linkLocal, publicKey, endpointHost, endpointPort + )); + + return future; + } + /* Packet functions */ private Map> pingConsumers = new HashMap<>(); + private Map> sessionConsumers = new HashMap<>(); void onPacketReceived(Packet p) { @@ -70,6 +84,7 @@ public class ClientState { } private void handleSessionResponse(SessionResponsePacket packet) { - System.out.printf("[%d] Session response #%d: %s\n", clientId, packet.sessionId, packet.result); + System.out.printf("[%d] Session response for AS%d: %s\n", clientId, packet.asn, packet.result); + sessionConsumers.remove(packet.asn).accept(packet); } } diff --git a/src/main/java/eu/m724/autopeerer/server/Main.java b/src/main/java/eu/m724/autopeerer/server/Main.java index 8ded69c..9c28776 100644 --- a/src/main/java/eu/m724/autopeerer/server/Main.java +++ b/src/main/java/eu/m724/autopeerer/server/Main.java @@ -23,6 +23,11 @@ public class Main { throw new RuntimeException("Failed to load configuration", e); } + if (config.isNew) { + System.out.println("The program stopped to let you configure"); + return; + } + var packetHandler = new PacketHandler(nodes); var server = new MyWebsocketServer( new InetSocketAddress(config.getString("socket.address"), config.getInt("socket.port")), diff --git a/src/main/java/eu/m724/autopeerer/server/MyHttpHandler.java b/src/main/java/eu/m724/autopeerer/server/MyHttpHandler.java index 14e7a00..86b738d 100644 --- a/src/main/java/eu/m724/autopeerer/server/MyHttpHandler.java +++ b/src/main/java/eu/m724/autopeerer/server/MyHttpHandler.java @@ -3,6 +3,10 @@ package eu.m724.autopeerer.server; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import eu.m724.autopeerer.common.packet.c2s.PingResponsePacket; +import eu.m724.autopeerer.common.packet.c2s.SessionResponsePacket; +import inet.ipaddr.IPAddress; +import inet.ipaddr.IPAddressString; +import inet.ipaddr.ipv6.IPv6Address; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -136,6 +140,69 @@ public class MyHttpHandler implements HttpHandler { return null; }); } else if (path[0].equals("peer")) { + requireMethod(exchange, "POST"); + + var json = getJsonBody(exchange); + + /* */ + + if (!json.has("node")) { + sendResponse(exchange, 400, "node"); + } + + var node = nodes.stream() + .filter(n -> n.id().equals(json.getString("node"))) + .findFirst().orElse(null); + + if (node == null) { + sendResponse(exchange, 400, "node"); + } + + /* */ + + CompletableFuture future = null; + + try { + future = node.getClient().session( + json.getLong("asn"), + new IPAddressString(json.getString("linkLocal")).getAddress().toIPv6(), + json.getString("publicKey"), + json.getString("endpointHost"), + json.getInt("endpointPort") + ); + } catch (Exception e) { + sendResponse(exchange, 400, "params"); + } + + sseStart(exchange); + + future.handle((packet, ex) -> { + try { + if (ex != null) { + sseWrite(exchange, ex.getMessage()); + } else { + var resp = new JSONObject() + .put("result", packet.result); + + if (packet.result == SessionResponsePacket.SessionResult.OK) { + resp.put("port", packet.port) + .put("publicKey", packet.publicKey); + } + + sseWrite(exchange, resp.toString()); + } + } catch (IOException e) { + e.printStackTrace(); + } + + try { + sseClose(exchange); + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + }); } }