Skip to content

Instantly share code, notes, and snippets.

@Exerosis
Created February 20, 2018 21:28
Show Gist options
  • Save Exerosis/d272610c85346956346ef7200f7a095a to your computer and use it in GitHub Desktop.
Save Exerosis/d272610c85346956346ef7200f7a095a to your computer and use it in GitHub Desktop.
public class DebugServer implements Closeable {
private final Map<Number, BiConsumer<ByteBuffer, SocketAddress>> handlers = new HashMap<>();
private final ExecutorService executor = newSingleThreadExecutor();
private final DatagramChannel channel;
private final ByteBuffer in;
private final ByteBuffer out;
public DebugServer(Number port, Number length) throws IOException {
this(port, length, ByteBuffer::get);
}
public DebugServer(Number port, Number length, Function<ByteBuffer, Number> opcodes) throws IOException {
in = allocate(length.intValue());
out = allocate(length.intValue());
in.clear();
channel = open();
channel.configureBlocking(true);
channel.bind(new InetSocketAddress("localhost", port.intValue()));
executor.submit(() -> {
while (channel.isOpen()) {
SocketAddress address = channel.receive(in);
in.flip();
handlers.get(opcodes.apply(in)).accept(in, address);
in.clear();
}
return null;
});
}
public void send(SocketAddress address, Number opcode, Consumer<ByteBuffer> packet) {
try {
synchronized (out) {
out.clear();
out.put(opcode.byteValue());
packet.accept(out);
out.flip();
channel.send(out, address);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void receive(Number opcode, BiConsumer<ByteBuffer, SocketAddress> handler) {
handlers.put(opcode, handler);
}
public void respond(Number opcode, Function<ByteBuffer, Consumer<ByteBuffer>> handler) {
respond(opcode, (request, address) -> handler.apply(request));
}
public void respond(Number opcode, BiFunction<ByteBuffer, SocketAddress, Consumer<ByteBuffer>> handler) {
receive(opcode, (request, address) -> {
Consumer<ByteBuffer> response = handler.apply(request, address);
send(address, opcode, response);
});
}
@Override
public void close() throws IOException {
channel.close();
executor.shutdown();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment