Initial commit
This commit is contained in:
commit
b4a3793d5d
13 changed files with 404 additions and 0 deletions
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
3
.idea/.gitignore
vendored
Normal file
3
.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
7
.idea/encodings.xml
Normal file
7
.idea/encodings.xml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||||
|
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
14
.idea/misc.xml
Normal file
14
.idea/misc.xml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
|
<component name="MavenProjectsManager">
|
||||||
|
<option name="originalFiles">
|
||||||
|
<list>
|
||||||
|
<option value="$PROJECT_DIR$/pom.xml" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="temurin-17" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
24
pom.xml
Normal file
24
pom.xml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>eu.m724</groupId>
|
||||||
|
<artifactId>autopeerer</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.java-websocket</groupId>
|
||||||
|
<artifactId>Java-WebSocket</artifactId>
|
||||||
|
<version>1.5.7</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
16
src/main/java/eu/m724/autopeerer/client/Main.java
Normal file
16
src/main/java/eu/m724/autopeerer/client/Main.java
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package eu.m724.autopeerer.client;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
System.out.println("Hello world!");
|
||||||
|
|
||||||
|
URI serverUri = URI.create("wss://echo.websocket.org/");
|
||||||
|
|
||||||
|
var packetHandler = new PacketHandler();
|
||||||
|
var client = new MyWebsocketClient(serverUri, packetHandler);
|
||||||
|
|
||||||
|
client.connectBlocking();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package eu.m724.autopeerer.client;
|
||||||
|
|
||||||
|
import eu.m724.autopeerer.packet.Packets;
|
||||||
|
import eu.m724.autopeerer.packet.PingRequestPacket;
|
||||||
|
import org.java_websocket.client.WebSocketClient;
|
||||||
|
import org.java_websocket.handshake.ServerHandshake;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class MyWebsocketClient extends WebSocketClient {
|
||||||
|
private final PacketHandler packetHandler;
|
||||||
|
private long connectStart;
|
||||||
|
|
||||||
|
public MyWebsocketClient(URI serverUri, PacketHandler packetHandler) {
|
||||||
|
super(serverUri);
|
||||||
|
this.packetHandler = packetHandler;
|
||||||
|
packetHandler.sender = this::send;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect() {
|
||||||
|
super.connect();
|
||||||
|
connectStart = System.nanoTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOpen(ServerHandshake serverHandshake) {
|
||||||
|
double connectTime = (System.nanoTime() - connectStart) / 1000000.0;
|
||||||
|
System.out.printf("Connected in %.3f ms\n", connectTime);
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (int i=0; i<10; i++) {
|
||||||
|
send(Packets.compose(new PingRequestPacket((short)i, InetAddress.getByName("1.1.1." + i))));
|
||||||
|
}
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(ByteBuffer bytes) {
|
||||||
|
packetHandler.handle(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose(int code, String reason, boolean remote) {
|
||||||
|
if (remote) {
|
||||||
|
System.out.println("Closed by remote: " + code + " " + reason);
|
||||||
|
} else {
|
||||||
|
System.out.println("Closed by client: " + code + " " + reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception e) {
|
||||||
|
System.err.println("WS error: ");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// we don't do String
|
||||||
|
@Override
|
||||||
|
public void onMessage(String s) { }
|
||||||
|
}
|
74
src/main/java/eu/m724/autopeerer/client/PacketHandler.java
Normal file
74
src/main/java/eu/m724/autopeerer/client/PacketHandler.java
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
package eu.m724.autopeerer.client;
|
||||||
|
|
||||||
|
import eu.m724.autopeerer.packet.Packet;
|
||||||
|
import eu.m724.autopeerer.packet.Packets;
|
||||||
|
import eu.m724.autopeerer.packet.PingRequestPacket;
|
||||||
|
import eu.m724.autopeerer.packet.PingResponsePacket;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.BufferUnderflowException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class PacketHandler {
|
||||||
|
Consumer<ByteBuffer> sender;
|
||||||
|
|
||||||
|
void handle(ByteBuffer bytes) {
|
||||||
|
Packet<?> p;
|
||||||
|
try {
|
||||||
|
p = Packets.parseClient(bytes);
|
||||||
|
} catch (BufferUnderflowException e) {
|
||||||
|
bytes.rewind();
|
||||||
|
byte[] bytez = new byte[bytes.remaining()];
|
||||||
|
bytes.get(bytez);
|
||||||
|
|
||||||
|
System.err.println("Received too short packet");
|
||||||
|
System.err.println("> Length: " + bytez.length);
|
||||||
|
System.err.println("> Packet: " + Base64.getEncoder().encodeToString(bytez));
|
||||||
|
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p instanceof PingRequestPacket packet) {System.out.printf("Ping request #%d to %s\n", packet.requestId, packet.target.getHostAddress());
|
||||||
|
|
||||||
|
CompletableFuture.runAsync(() -> {
|
||||||
|
float average = -1, meanDeviation = -1;
|
||||||
|
var status = PingResponsePacket.PingResponseStatus.ERROR;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Process process = Runtime.getRuntime().exec(new String[] { "ping", "-3Ac", "10", packet.target.getHostAddress() });
|
||||||
|
|
||||||
|
try (BufferedReader reader = process.inputReader()) {
|
||||||
|
for (String l : reader.lines().toList()) {
|
||||||
|
boolean error = l.startsWith("From"); // indicates an error
|
||||||
|
boolean end = l.startsWith("rtt");
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
status = PingResponsePacket.PingResponseStatus.UNREACHABLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end) {
|
||||||
|
String[] results = l.split(" ")[3].split("/");
|
||||||
|
average = Float.parseFloat(results[1]);
|
||||||
|
meanDeviation = Float.parseFloat(results[3]);
|
||||||
|
status = PingResponsePacket.PingResponseStatus.OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Error pinging");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.printf("Ping request #%d to %s - %s avg %.3f / mdev %.3f ms\n", packet.requestId, packet.target.getHostAddress(), status, average, meanDeviation);
|
||||||
|
sender.accept(new PingResponsePacket(packet.requestId, status, average, meanDeviation).serialize());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
src/main/java/eu/m724/autopeerer/packet/Packet.java
Normal file
10
src/main/java/eu/m724/autopeerer/packet/Packet.java
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package eu.m724.autopeerer.packet;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public interface Packet<T extends Packet<T>> {
|
||||||
|
byte getId();
|
||||||
|
|
||||||
|
//T deserialize(ByteArrayInputStream inputStream) throws IOException;
|
||||||
|
ByteBuffer serialize();
|
||||||
|
}
|
41
src/main/java/eu/m724/autopeerer/packet/Packets.java
Normal file
41
src/main/java/eu/m724/autopeerer/packet/Packets.java
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package eu.m724.autopeerer.packet;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class Packets {
|
||||||
|
public static Packet<?> parseClient(ByteBuffer buffer) throws Exception {
|
||||||
|
byte id = buffer.get();
|
||||||
|
|
||||||
|
Packet<?> packet = null;
|
||||||
|
|
||||||
|
if (id == 1) {
|
||||||
|
packet = PingRequestPacket.deserialize(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Packet<?> parseServer(ByteBuffer buffer) throws Exception {
|
||||||
|
byte id = buffer.get();
|
||||||
|
|
||||||
|
Packet<?> packet = null;
|
||||||
|
|
||||||
|
if (id == 1) {
|
||||||
|
PingResponsePacket.deserialize(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ByteBuffer compose(Packet<?> packet) {
|
||||||
|
ByteBuffer packetBuffer = packet.serialize();
|
||||||
|
packetBuffer.rewind();
|
||||||
|
|
||||||
|
var bb = ByteBuffer.allocate(1 + packetBuffer.remaining());
|
||||||
|
bb.put(packet.getId());
|
||||||
|
bb.put(packetBuffer);
|
||||||
|
bb.rewind();
|
||||||
|
|
||||||
|
return bb;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package eu.m724.autopeerer.packet;
|
||||||
|
|
||||||
|
import java.net.Inet6Address;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class PingRequestPacket implements Packet<PingRequestPacket> {
|
||||||
|
public final short requestId;
|
||||||
|
public final InetAddress target;
|
||||||
|
|
||||||
|
public PingRequestPacket(short requestId,InetAddress target) {
|
||||||
|
this.requestId = requestId;
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getId() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PingRequestPacket deserialize(ByteBuffer buffer) throws Exception {
|
||||||
|
var requestId = buffer.getShort();
|
||||||
|
var ipv6 = buffer.get() == 1;
|
||||||
|
|
||||||
|
byte[] addr = new byte[ipv6 ? 16 : 4];
|
||||||
|
buffer.get(addr);
|
||||||
|
InetAddress target = InetAddress.getByAddress(addr);
|
||||||
|
|
||||||
|
return new PingRequestPacket(requestId, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer serialize() {
|
||||||
|
boolean ipv6 = target instanceof Inet6Address;
|
||||||
|
int bytes = 3 + (ipv6 ? 16 : 4);
|
||||||
|
|
||||||
|
var buffer = ByteBuffer.allocate(bytes);
|
||||||
|
buffer.putShort(requestId);
|
||||||
|
buffer.put((byte) (ipv6 ? 1 : 0));
|
||||||
|
buffer.put(target.getAddress());
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package eu.m724.autopeerer.packet;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class PingResponsePacket implements Packet<PingResponsePacket> {
|
||||||
|
public final short requestId;
|
||||||
|
public final PingResponseStatus status;
|
||||||
|
public final float average;
|
||||||
|
public final float meanDeviation;
|
||||||
|
|
||||||
|
public PingResponsePacket(short requestId, PingResponseStatus status, float average, float meanDeviation) {
|
||||||
|
this.requestId = requestId;
|
||||||
|
this.status = status;
|
||||||
|
this.average = average;
|
||||||
|
this.meanDeviation = meanDeviation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getId() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PingResponsePacket deserialize(ByteBuffer buffer) {
|
||||||
|
var requestId = buffer.getShort();
|
||||||
|
var average = buffer.getFloat();
|
||||||
|
var meanDeviation = buffer.getFloat();
|
||||||
|
|
||||||
|
var status = PingResponseStatus.OK;
|
||||||
|
|
||||||
|
if (average == -1) {
|
||||||
|
status = meanDeviation == 0 ? PingResponseStatus.UNREACHABLE : PingResponseStatus.ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PingResponsePacket(requestId, status, average, meanDeviation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBuffer serialize() {
|
||||||
|
var bb = ByteBuffer.allocate(9);
|
||||||
|
bb.putShort(requestId);
|
||||||
|
switch (status) {
|
||||||
|
case OK -> {
|
||||||
|
bb.putFloat(average);
|
||||||
|
bb.putFloat(meanDeviation);
|
||||||
|
}
|
||||||
|
case UNREACHABLE -> {
|
||||||
|
bb.putFloat(-1);
|
||||||
|
bb.putFloat(0);
|
||||||
|
}
|
||||||
|
case ERROR -> {
|
||||||
|
bb.putFloat(-1);
|
||||||
|
bb.putFloat(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PingResponseStatus {
|
||||||
|
OK, UNREACHABLE, ERROR
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue