diff --git a/java_console/io/src/main/java/com/rusefi/binaryprotocol/BinaryProtocol.java b/java_console/io/src/main/java/com/rusefi/binaryprotocol/BinaryProtocol.java index 45b808ee6d..38fb55e3b7 100644 --- a/java_console/io/src/main/java/com/rusefi/binaryprotocol/BinaryProtocol.java +++ b/java_console/io/src/main/java/com/rusefi/binaryprotocol/BinaryProtocol.java @@ -14,6 +14,7 @@ import com.rusefi.core.Pair; import com.rusefi.core.Sensor; import com.rusefi.core.SensorCentral; import com.rusefi.io.*; +import com.rusefi.io.commands.GetOutputsCommand; import com.rusefi.stream.LogicdataStreamFile; import com.rusefi.stream.StreamFile; import com.rusefi.stream.TSHighSpeedLog; @@ -550,10 +551,7 @@ public class BinaryProtocol implements BinaryProtocolCommands { if (isClosed) return false; - byte packet[] = new byte[5]; - packet[0] = Fields.TS_OUTPUT_COMMAND; - putShort(packet, 1, 0); // offset - putShort(packet, 3, swap16(Fields.TS_OUTPUT_SIZE)); + byte[] packet = GetOutputsCommand.createRequest(); byte[] response = executeCommand(packet, "output channels", false); if (response == null || response.length != (Fields.TS_OUTPUT_SIZE + 1) || response[0] != RESPONSE_OK) diff --git a/java_console/io/src/main/java/com/rusefi/binaryprotocol/IncomingDataBuffer.java b/java_console/io/src/main/java/com/rusefi/binaryprotocol/IncomingDataBuffer.java index 31d4292b4e..96163020a8 100644 --- a/java_console/io/src/main/java/com/rusefi/binaryprotocol/IncomingDataBuffer.java +++ b/java_console/io/src/main/java/com/rusefi/binaryprotocol/IncomingDataBuffer.java @@ -111,6 +111,7 @@ public class IncomingDataBuffer { } public void dropPending() { + // todo: when exactly do we need this logic? synchronized (cbb) { int pending = cbb.length(); if (pending > 0) { diff --git a/java_console/io/src/main/java/com/rusefi/io/commands/GetOutputsCommand.java b/java_console/io/src/main/java/com/rusefi/io/commands/GetOutputsCommand.java new file mode 100644 index 0000000000..fe2a52da3e --- /dev/null +++ b/java_console/io/src/main/java/com/rusefi/io/commands/GetOutputsCommand.java @@ -0,0 +1,16 @@ +package com.rusefi.io.commands; + +import com.rusefi.config.generated.Fields; + +import static com.rusefi.binaryprotocol.IoHelper.putShort; +import static com.rusefi.binaryprotocol.IoHelper.swap16; + +public class GetOutputsCommand { + public static byte[] createRequest() { + byte[] packet = new byte[5]; + packet[0] = Fields.TS_OUTPUT_COMMAND; + putShort(packet, 1, 0); // offset + putShort(packet, 3, swap16(Fields.TS_OUTPUT_SIZE)); + return packet; + } +} diff --git a/java_console/io/src/main/java/com/rusefi/io/commands/HelloCommand.java b/java_console/io/src/main/java/com/rusefi/io/commands/HelloCommand.java index 337c2e49d6..0dd5c01ec8 100644 --- a/java_console/io/src/main/java/com/rusefi/io/commands/HelloCommand.java +++ b/java_console/io/src/main/java/com/rusefi/io/commands/HelloCommand.java @@ -16,6 +16,10 @@ public class HelloCommand implements Command { this.tsSignature = tsSignature; } + public static void send(IoStream stream, Logger logger) throws IOException { + stream.sendPacket(new byte[]{Fields.TS_HELLO_COMMAND}, logger); + } + @Override public byte getCommand() { return Fields.TS_HELLO_COMMAND; diff --git a/java_console/io/src/main/java/com/rusefi/server/Backend.java b/java_console/io/src/main/java/com/rusefi/server/Backend.java index c2e23cd1ab..769e90835c 100644 --- a/java_console/io/src/main/java/com/rusefi/server/Backend.java +++ b/java_console/io/src/main/java/com/rusefi/server/Backend.java @@ -43,6 +43,12 @@ public class Backend { } + public void register(ClientConnectionState clientConnectionState) { + synchronized (clients) { + clients.add(clientConnectionState); + } + } + private void close(ClientConnectionState inactiveClient) { inactiveClient.close(); synchronized (clients) { @@ -50,9 +56,9 @@ public class Backend { } } - public void register(ClientConnectionState clientConnectionState) { + public List getClients() { synchronized (clients) { - clients.add(clientConnectionState); + return new ArrayList<>(clients); } } diff --git a/java_console/io/src/main/java/com/rusefi/server/ClientConnectionState.java b/java_console/io/src/main/java/com/rusefi/server/ClientConnectionState.java index 5ddac44285..8d293f29b8 100644 --- a/java_console/io/src/main/java/com/rusefi/server/ClientConnectionState.java +++ b/java_console/io/src/main/java/com/rusefi/server/ClientConnectionState.java @@ -1,10 +1,11 @@ package com.rusefi.server; import com.opensr5.Logger; +import com.rusefi.auth.AutoTokenUtil; import com.rusefi.binaryprotocol.BinaryProtocolCommands; import com.rusefi.binaryprotocol.IncomingDataBuffer; -import com.rusefi.config.generated.Fields; import com.rusefi.io.IoStream; +import com.rusefi.io.commands.HelloCommand; import com.rusefi.io.tcp.TcpIoStream; import java.io.Closeable; @@ -44,12 +45,17 @@ public class ClientConnectionState { public void sayHello() { try { - stream.sendPacket(new byte[]{Fields.TS_HELLO_COMMAND}, logger); + HelloCommand.send(stream, logger); byte[] response = incomingData.getPacket(logger, "", false); if (!checkResponseCode(response, BinaryProtocolCommands.RESPONSE_OK)) return; - String signature = new String(response, 1, response.length - 1); - logger.info("New client: " + signature); + String tokenAndSignature = new String(response, 1, response.length - 1); + String token = tokenAndSignature.length() > AutoTokenUtil.TOKEN_LENGTH ? tokenAndSignature.substring(0, AutoTokenUtil.TOKEN_LENGTH) : null; + if (!AutoTokenUtil.isToken(token)) + throw new IOException("Invalid token"); + String signature = tokenAndSignature.substring(AutoTokenUtil.TOKEN_LENGTH); + + logger.info(token + " New client: " + signature); } catch (IOException e) { close(); diff --git a/java_console/shared_ui/src/com/rusefi/ui/AutoTokenUtil.java b/java_console/shared_io/src/main/java/com/rusefi/auth/AutoTokenUtil.java similarity index 64% rename from java_console/shared_ui/src/com/rusefi/ui/AutoTokenUtil.java rename to java_console/shared_io/src/main/java/com/rusefi/auth/AutoTokenUtil.java index 11c4612717..cb7d7e0333 100644 --- a/java_console/shared_ui/src/com/rusefi/ui/AutoTokenUtil.java +++ b/java_console/shared_io/src/main/java/com/rusefi/auth/AutoTokenUtil.java @@ -1,11 +1,14 @@ -package com.rusefi.ui; +package com.rusefi.auth; public class AutoTokenUtil { + + public static final int TOKEN_LENGTH = 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12; + public static boolean isToken(String content) { if (content == null) return false; content = content.trim(); - if (content.length() != 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12) + if (content.length() != TOKEN_LENGTH) return false; return content.charAt(8) == '-' && content.charAt(8 + 1 + 4) == '-'; } diff --git a/java_console/shared_ui/src/com/rusefi/ui/AuthTokenPanel.java b/java_console/shared_ui/src/com/rusefi/ui/AuthTokenPanel.java index 59f556f884..0309d80b65 100644 --- a/java_console/shared_ui/src/com/rusefi/ui/AuthTokenPanel.java +++ b/java_console/shared_ui/src/com/rusefi/ui/AuthTokenPanel.java @@ -1,5 +1,6 @@ package com.rusefi.ui; +import com.rusefi.auth.AutoTokenUtil; import com.rusefi.ui.storage.PersistentConfiguration; import com.rusefi.ui.util.URLLabel; import org.jetbrains.annotations.NotNull; diff --git a/java_console/shared_ui/src/com/rusefi/ui/test/AuthTokenUtilTest.java b/java_console/shared_ui/src/com/rusefi/ui/test/AuthTokenUtilTest.java index b12e3789e4..db106da1a7 100644 --- a/java_console/shared_ui/src/com/rusefi/ui/test/AuthTokenUtilTest.java +++ b/java_console/shared_ui/src/com/rusefi/ui/test/AuthTokenUtilTest.java @@ -1,6 +1,6 @@ package com.rusefi.ui.test; -import com.rusefi.ui.AutoTokenUtil; +import com.rusefi.auth.AutoTokenUtil; import org.junit.Test; import static org.junit.Assert.assertFalse; diff --git a/java_console/ui/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java b/java_console/ui/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java index bd7245f40b..933c675737 100644 --- a/java_console/ui/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java +++ b/java_console/ui/src/main/java/com/rusefi/autodetect/SerialAutoChecker.java @@ -6,6 +6,7 @@ import com.rusefi.binaryprotocol.BinaryProtocolCommands; import com.rusefi.binaryprotocol.IncomingDataBuffer; import com.rusefi.config.generated.Fields; import com.rusefi.io.IoStream; +import com.rusefi.io.commands.HelloCommand; import com.rusefi.io.serial.SerialIoStreamJSerialComm; import java.io.IOException; @@ -41,7 +42,7 @@ public class SerialAutoChecker implements Runnable { Logger logger = FileLog.LOGGER; IncomingDataBuffer incomingData = stream.getDataBuffer(); try { - stream.sendPacket(new byte[]{Fields.TS_HELLO_COMMAND}, logger); + HelloCommand.send(stream, logger); byte[] response = incomingData.getPacket(logger, "", false); if (!checkResponseCode(response, BinaryProtocolCommands.RESPONSE_OK)) return; diff --git a/java_console/ui/src/test/java/com/rusefi/MockRusEfiDevice.java b/java_console/ui/src/test/java/com/rusefi/MockRusEfiDevice.java index abfb94a02a..aa829dfd6e 100644 --- a/java_console/ui/src/test/java/com/rusefi/MockRusEfiDevice.java +++ b/java_console/ui/src/test/java/com/rusefi/MockRusEfiDevice.java @@ -15,21 +15,21 @@ import static com.rusefi.io.tcp.BinaryProtocolServer.getPacketLength; import static com.rusefi.io.tcp.BinaryProtocolServer.readPromisedBytes; public class MockRusEfiDevice { + private final String authToken; private final String signature; private final Logger logger; - public MockRusEfiDevice(String signature, Logger logger) { + public MockRusEfiDevice(String authToken, String signature, Logger logger) { + this.authToken = authToken; this.signature = signature; this.logger = logger; } - public void connect(int serverPort) throws IOException { TcpIoStream stream = new TcpIoStream(logger, new Socket(LOCALHOST, serverPort)); IncomingDataBuffer in = stream.getDataBuffer(); new Thread(() -> { - try { while (true) { int length = getPacketLength(in, () -> { @@ -42,14 +42,17 @@ public class MockRusEfiDevice { if (command == Fields.TS_HELLO_COMMAND) { - new HelloCommand(logger, signature).handle(packet, stream); + new HelloCommand(logger, authToken + signature).handle(packet, stream); + } else { + handleCommand(); } - - } } catch (IOException e) { e.printStackTrace(); } }).start(); } + + protected void handleCommand() { + } } diff --git a/java_console/ui/src/test/java/com/rusefi/ServerTest.java b/java_console/ui/src/test/java/com/rusefi/ServerTest.java index 3a7b812496..3de2e37ce1 100644 --- a/java_console/ui/src/test/java/com/rusefi/ServerTest.java +++ b/java_console/ui/src/test/java/com/rusefi/ServerTest.java @@ -8,6 +8,7 @@ import org.junit.Test; import java.io.IOException; import java.net.Socket; +import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -29,7 +30,7 @@ public class ServerTest { CountDownLatch serverCreated = new CountDownLatch(1); - Backend backend = new Backend(3 * Timeouts.SECOND); + Backend backend = new Backend(5 * Timeouts.SECOND); BinaryProtocolServer.tcpServerSocket(serverPort, "Server", new Function() { @@ -42,6 +43,10 @@ public class ServerTest { clientConnectionState.sayHello(); backend.register(clientConnectionState); + while(true) { + + } + } }; } @@ -51,11 +56,16 @@ public class ServerTest { assertEquals(0, backend.getCount()); - new MockRusEfiDevice("rusEFI 2020.07.06.frankenso_na6.2468827536", logger).connect(serverPort); - new MockRusEfiDevice("rusEFI 2020.07.11.proteus_f4.1986715563", logger).connect(serverPort); + new MockRusEfiDevice("00000000-1234-1234-1234-123456789012", "rusEFI 2020.07.06.frankenso_na6.2468827536", logger).connect(serverPort); + new MockRusEfiDevice("12345678-1234-1234-1234-123456789012", "rusEFI 2020.07.11.proteus_f4.1986715563", logger).connect(serverPort); + // todo: technically we should have callbacks for 'connect', will make this better if this would be failing sleep(Timeouts.SECOND); + List clients = backend.getClients(); + assertEquals(2, clients.size()); + + } }