package the8472.mldht.cli; import static the8472.utils.Functional.tap; import the8472.bencode.BDecoder; import the8472.bencode.BEncoder; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.StandardSocketOptions; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.nio.charset.StandardCharsets; import java.nio.file.Paths; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class Client { SocketChannel serverConnection; public Client(String[] args) throws Exception { serverConnection = SocketChannel.open(new InetSocketAddress(InetAddress.getLoopbackAddress(), Server.SERVER_PORT)); serverConnection.setOption(StandardSocketOptions.SO_KEEPALIVE, true); serverConnection.socket().setSoTimeout(0); String workDir = Paths.get("").toAbsolutePath().normalize().toString(); List<byte[]> argsList = Arrays.asList(args).stream().map(s -> s.getBytes(StandardCharsets.UTF_8)).collect(Collectors.toList()); Map<String, Object> command = new HashMap<>(); command.put("arguments", argsList); command.put("cwd", workDir.getBytes(StandardCharsets.UTF_8)); BEncoder encoder = new BEncoder(); ByteBuffer buf = encoder.encode(command, 65535); serverConnection.write(tap(ByteBuffer.allocate(4), b -> b.putInt(0, buf.limit()))); serverConnection.write(buf); //serverConnection.shutdownOutput(); ByteBuffer header = ByteBuffer.allocate(4); ByteBuffer message; while(serverConnection.isOpen()) { header.clear(); serverConnection.read(header); header.flip(); message = ByteBuffer.allocate(header.getInt(0)); serverConnection.read(message); message.flip(); BDecoder dec = new BDecoder(); Map<String,Object> msg = dec.decode(message); String action = new String((byte[])msg.get("action"), StandardCharsets.ISO_8859_1); switch (action) { case "sysout": System.out.append(new String((byte[])msg.get("payload"), StandardCharsets.UTF_8)); break; case "syserr": System.err.append(new String((byte[])msg.get("payload"), StandardCharsets.UTF_8)); break; case "exit": serverConnection.close(); System.exit(((Long)msg.get("exitCode")).intValue()); break; default: throw new IllegalStateException("unexpected action " + action); } } } public static void main(String[] args) throws Exception { new Client(args); } }