From deb43f98db047774f8b5fa0965a95d86b92fbb6d Mon Sep 17 00:00:00 2001 From: rusefi Date: Mon, 13 Jul 2020 00:44:43 -0400 Subject: [PATCH] proxy progress --- android/.idea/.name | 1 - .../com/rusefi/io/commands/HelloCommand.java | 14 +++++ .../com/rusefi/BaseBroadcastingThread.java | 53 +++++++++++++++++ .../java/com/rusefi/MockRusEfiDevice.java | 46 ++++----------- .../src/test/java/com/rusefi/ServerTest.java | 57 +++++++++++++++--- .../src/test/java/com/rusefi/TestHelper.java | 58 +++++++++++++++++++ .../io/TcpCommunicationIntegrationTest.java | 54 ++++------------- .../rusefi/server/ClientConnectionState.java | 8 +-- 8 files changed, 197 insertions(+), 94 deletions(-) delete mode 100644 android/.idea/.name create mode 100644 java_console/ui/src/test/java/com/rusefi/BaseBroadcastingThread.java create mode 100644 java_console/ui/src/test/java/com/rusefi/TestHelper.java diff --git a/android/.idea/.name b/android/.idea/.name deleted file mode 100644 index cab985bb73..0000000000 --- a/android/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -rusEFI \ No newline at end of file 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 0dd5c01ec8..a1a34e4988 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 @@ -1,12 +1,18 @@ package com.rusefi.io.commands; import com.opensr5.Logger; +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.tcp.BinaryProtocolServer; +import org.jetbrains.annotations.Nullable; +import java.io.EOFException; import java.io.IOException; +import static com.rusefi.binaryprotocol.IoHelper.checkResponseCode; + public class HelloCommand implements Command { private final Logger logger; private final String tsSignature; @@ -20,6 +26,14 @@ public class HelloCommand implements Command { stream.sendPacket(new byte[]{Fields.TS_HELLO_COMMAND}, logger); } + @Nullable + public static String getHelloResponse(IncomingDataBuffer incomingData, Logger logger) throws EOFException { + byte[] response = incomingData.getPacket(logger, "[hello]", false); + if (!checkResponseCode(response, BinaryProtocolCommands.RESPONSE_OK)) + return null; + return new String(response, 1, response.length - 1); + } + @Override public byte getCommand() { return Fields.TS_HELLO_COMMAND; diff --git a/java_console/ui/src/test/java/com/rusefi/BaseBroadcastingThread.java b/java_console/ui/src/test/java/com/rusefi/BaseBroadcastingThread.java new file mode 100644 index 0000000000..554edef6c1 --- /dev/null +++ b/java_console/ui/src/test/java/com/rusefi/BaseBroadcastingThread.java @@ -0,0 +1,53 @@ +package com.rusefi; + +import com.opensr5.Logger; +import com.rusefi.binaryprotocol.IncomingDataBuffer; +import com.rusefi.config.generated.Fields; +import com.rusefi.io.commands.HelloCommand; +import com.rusefi.io.tcp.BinaryProtocolServer; +import com.rusefi.io.tcp.TcpIoStream; +import com.rusefi.server.SessionDetails; + +import java.io.IOException; +import java.net.Socket; + +import static com.rusefi.io.tcp.BinaryProtocolServer.getPacketLength; +import static com.rusefi.io.tcp.BinaryProtocolServer.readPromisedBytes; + +public class BaseBroadcastingThread { + private final Thread thread; + + public BaseBroadcastingThread(Socket socket, SessionDetails sessionDetails, Logger logger) throws IOException { + TcpIoStream stream = new TcpIoStream(logger, socket); + IncomingDataBuffer in = stream.getDataBuffer(); + + thread = new Thread(() -> { + try { + while (true) { + int length = getPacketLength(in, () -> { + throw new UnsupportedOperationException(); + }); + BinaryProtocolServer.Packet packet = readPromisedBytes(in, length); + byte[] payload = packet.getPacket(); + + byte command = payload[0]; + + if (command == Fields.TS_HELLO_COMMAND) { + new HelloCommand(logger, sessionDetails.toJson()).handle(packet, stream); + } else { + handleCommand(); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + + protected void handleCommand() { + } + + public void start() { + thread.start(); + } +} 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 7c31112d53..c268f8c444 100644 --- a/java_console/ui/src/test/java/com/rusefi/MockRusEfiDevice.java +++ b/java_console/ui/src/test/java/com/rusefi/MockRusEfiDevice.java @@ -1,11 +1,6 @@ package com.rusefi; import com.opensr5.Logger; -import com.rusefi.binaryprotocol.IncomingDataBuffer; -import com.rusefi.config.generated.Fields; -import com.rusefi.io.commands.HelloCommand; -import com.rusefi.io.tcp.BinaryProtocolServer; -import com.rusefi.io.tcp.TcpIoStream; import com.rusefi.server.ControllerInfo; import com.rusefi.server.SessionDetails; @@ -13,48 +8,27 @@ import java.io.IOException; import java.net.Socket; import static com.rusefi.tools.online.ProxyClient.LOCALHOST; -import static com.rusefi.io.tcp.BinaryProtocolServer.getPacketLength; -import static com.rusefi.io.tcp.BinaryProtocolServer.readPromisedBytes; public class MockRusEfiDevice { + public static final String TEST_TOKEN_1 = "00000000-1234-1234-1234-123456789012"; private SessionDetails sessionDetails; private final Logger logger; public MockRusEfiDevice(String authToken, String signature, Logger logger) { - ControllerInfo ci = new ControllerInfo("vehicle", "make", "code", signature); - - sessionDetails = new SessionDetails(ci, authToken, SessionDetails.createOneTimeCode()); - + sessionDetails = createTestSession(authToken, signature); this.logger = logger; } - public void connect(int serverPort) throws IOException { - TcpIoStream stream = new TcpIoStream(logger, new Socket(LOCALHOST, serverPort)); - IncomingDataBuffer in = stream.getDataBuffer(); + public static SessionDetails createTestSession(String authToken, String signature) { + ControllerInfo ci = new ControllerInfo("vehicle", "make", "code", signature); - new Thread(() -> { - try { - while (true) { - int length = getPacketLength(in, () -> { - throw new UnsupportedOperationException(); - }); - BinaryProtocolServer.Packet packet = readPromisedBytes(in, length); - byte[] payload = packet.getPacket(); - - byte command = payload[0]; - - if (command == Fields.TS_HELLO_COMMAND) { - new HelloCommand(logger, sessionDetails.toJson()).handle(packet, stream); - } else { - handleCommand(); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - }).start(); + return new SessionDetails(ci, authToken, SessionDetails.createOneTimeCode()); } - protected void handleCommand() { + public void connect(int serverPort) throws IOException { + BaseBroadcastingThread baseBroadcastingThread = new BaseBroadcastingThread(new Socket(LOCALHOST, serverPort), + sessionDetails, + logger); + baseBroadcastingThread.start(); } } 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 85e4f7e6de..8cc5e753e9 100644 --- a/java_console/ui/src/test/java/com/rusefi/ServerTest.java +++ b/java_console/ui/src/test/java/com/rusefi/ServerTest.java @@ -1,18 +1,27 @@ package com.rusefi; +import com.opensr5.ConfigurationImage; import com.opensr5.Logger; +import com.rusefi.config.generated.Fields; +import com.rusefi.io.IoStream; +import com.rusefi.io.commands.HelloCommand; import com.rusefi.server.Backend; import com.rusefi.server.ClientConnectionState; +import com.rusefi.server.SessionDetails; import com.rusefi.server.UserDetails; import com.rusefi.tools.online.ProxyClient; 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; +import static com.rusefi.TestHelper.createIniField; +import static com.rusefi.TestHelper.prepareImage; +import static com.rusefi.tools.online.ProxyClient.LOCALHOST; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -26,16 +35,13 @@ public class ServerTest { @Test public void testSessionTimeout() throws InterruptedException, IOException { int serverPort = 7000; - - CountDownLatch serverCreated = new CountDownLatch(1); - - + int httpPort = 8000; Function userDetailsResolver = authToken -> new UserDetails(authToken.substring(0, 5), authToken.charAt(6)); + CountDownLatch serverCreated = new CountDownLatch(1); CountDownLatch allClientsDisconnected = new CountDownLatch(1); CountDownLatch onConnected = new CountDownLatch(2); - int httpPort = 8000; Backend backend = new Backend(userDetailsResolver, httpPort, logger) { @Override public void register(ClientConnectionState clientConnectionState) { @@ -52,12 +58,11 @@ public class ServerTest { }; Backend.runProxy(serverPort, serverCreated, backend); - assertTrue(serverCreated.await(30, TimeUnit.SECONDS)); assertEquals(0, backend.getCount()); - new MockRusEfiDevice("00000000-1234-1234-1234-123456789012", "rusEFI 2020.07.06.frankenso_na6.2468827536", logger).connect(serverPort); + new MockRusEfiDevice(MockRusEfiDevice.TEST_TOKEN_1, "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); assertTrue(onConnected.await(30, TimeUnit.SECONDS)); @@ -72,4 +77,42 @@ public class ServerTest { } + @Test + public void testRelayWorkflow() throws InterruptedException, IOException { + Function userDetailsResolver = authToken -> new UserDetails(authToken.substring(0, 5), authToken.charAt(6)); + int httpPort = 8001; + Backend backend = new Backend(userDetailsResolver, httpPort, logger); + int serverPort = 7001; + CountDownLatch serverCreated = new CountDownLatch(1); + + // first start backend server + Backend.runProxy(serverPort, serverCreated, backend); + assertTrue(serverCreated.await(30, TimeUnit.SECONDS)); + + + // create virtual controller + int controllerPort = 7002; + ConfigurationImage controllerImage = prepareImage(240, createIniField(Fields.CYLINDERSCOUNT)); + CountDownLatch controllerCreated = new CountDownLatch(1); + TestHelper.createVirtualController(controllerImage, controllerPort, parameter -> controllerCreated.countDown(), logger); + assertTrue(controllerCreated.await(30, TimeUnit.SECONDS)); + + + // start network broadcaster to connect controller with backend since in real life controller has only local serial port it does not have network + IoStream targetEcuSocket = TestHelper.createTestStream(controllerPort, logger); + HelloCommand.send(targetEcuSocket, logger); + String controllerSignature = HelloCommand.getHelloResponse(targetEcuSocket.getDataBuffer(), logger); + + SessionDetails sessionDetails = MockRusEfiDevice.createTestSession(MockRusEfiDevice.TEST_TOKEN_1, controllerSignature); + + BaseBroadcastingThread baseBroadcastingThread = new BaseBroadcastingThread(new Socket(LOCALHOST, serverPort), + sessionDetails, + logger) { + // todo + }; + baseBroadcastingThread.start(); + + } + + } diff --git a/java_console/ui/src/test/java/com/rusefi/TestHelper.java b/java_console/ui/src/test/java/com/rusefi/TestHelper.java new file mode 100644 index 0000000000..c32c40c833 --- /dev/null +++ b/java_console/ui/src/test/java/com/rusefi/TestHelper.java @@ -0,0 +1,58 @@ +package com.rusefi; + +import com.opensr5.ConfigurationImage; +import com.opensr5.Logger; +import com.opensr5.ini.field.ScalarIniField; +import com.rusefi.binaryprotocol.BinaryProtocolState; +import com.rusefi.config.Field; +import com.rusefi.config.generated.Fields; +import com.rusefi.io.IoStream; +import com.rusefi.io.LinkConnector; +import com.rusefi.io.LinkManager; +import com.rusefi.io.tcp.BinaryProtocolServer; +import com.rusefi.io.tcp.TcpIoStream; +import com.rusefi.tools.online.ProxyClient; +import com.rusefi.tune.xml.Constant; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.net.Socket; + +public class TestHelper { + @NotNull + public static ScalarIniField createIniField(Field field) { + return new ScalarIniField(field.getName(), field.getOffset(), "", field.getType(), 1); + } + + @NotNull + public static ConfigurationImage prepareImage(int input, ScalarIniField scalarIniField) { + ConfigurationImage ci = new ConfigurationImage(Fields.TOTAL_CONFIG_SIZE); + + scalarIniField.setValue(ci, new Constant(scalarIniField.getName(), "", Integer.toString(input))); + return ci; + } + + @NotNull + public static BinaryProtocolServer createVirtualController(ConfigurationImage ci, int port, Listener serverSocketCreationCallback, Logger logger) { + BinaryProtocolState state = new BinaryProtocolState(); + state.setController(ci); + state.setCurrentOutputs(new byte[1 + Fields.TS_OUTPUT_SIZE]); + + LinkManager linkManager = new LinkManager(logger); + linkManager.setConnector(LinkConnector.getDetachedConnector(state)); + BinaryProtocolServer server = new BinaryProtocolServer(logger); + server.start(linkManager, port, serverSocketCreationCallback); + return server; + } + + @NotNull + public static IoStream createTestStream(int controllerPort, Logger logger) { + IoStream targetEcuSocket; + try { + targetEcuSocket = new TcpIoStream(logger, new Socket(ProxyClient.LOCALHOST, controllerPort)); + } catch (IOException e) { + throw new IllegalStateException("Failed to connect to controller " + ProxyClient.LOCALHOST + ":" + controllerPort); + } + return targetEcuSocket; + } +} diff --git a/java_console/ui/src/test/java/com/rusefi/io/TcpCommunicationIntegrationTest.java b/java_console/ui/src/test/java/com/rusefi/io/TcpCommunicationIntegrationTest.java index 5248b2ec52..46b5909845 100644 --- a/java_console/ui/src/test/java/com/rusefi/io/TcpCommunicationIntegrationTest.java +++ b/java_console/ui/src/test/java/com/rusefi/io/TcpCommunicationIntegrationTest.java @@ -3,21 +3,14 @@ package com.rusefi.io; import com.opensr5.ConfigurationImage; import com.opensr5.Logger; import com.opensr5.ini.field.ScalarIniField; -import com.rusefi.Listener; +import com.rusefi.TestHelper; import com.rusefi.binaryprotocol.BinaryProtocol; -import com.rusefi.binaryprotocol.BinaryProtocolState; -import com.rusefi.config.Field; import com.rusefi.config.generated.Fields; import com.rusefi.io.tcp.BinaryProtocolProxy; import com.rusefi.io.tcp.BinaryProtocolServer; -import com.rusefi.io.tcp.TcpIoStream; import com.rusefi.tools.online.ProxyClient; -import com.rusefi.tune.xml.Constant; -import org.jetbrains.annotations.NotNull; import org.junit.Test; -import java.io.*; -import java.net.Socket; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -54,13 +47,13 @@ public class TcpCommunicationIntegrationTest { @Test public void testConnectAndTransmitImageOverTcpIp() throws InterruptedException { - ScalarIniField iniField = createIniField(Fields.CYLINDERSCOUNT); + ScalarIniField iniField = TestHelper.createIniField(Fields.CYLINDERSCOUNT); int value = 239; - ConfigurationImage serverImage = prepareImage(value, iniField); + ConfigurationImage serverImage = TestHelper.prepareImage(value, iniField); int port = 6100; CountDownLatch serverCreated = new CountDownLatch(1); - BinaryProtocolServer server = createVirtualController(serverImage, port, parameter -> serverCreated.countDown()); + BinaryProtocolServer server = TestHelper.createVirtualController(serverImage, port, parameter -> serverCreated.countDown(), LOGGER); assertTrue(serverCreated.await(30, TimeUnit.SECONDS)); CountDownLatch connectionEstablishedCountDownLatch = new CountDownLatch(1); @@ -94,25 +87,23 @@ public class TcpCommunicationIntegrationTest { @Test public void testProxy() throws InterruptedException { - ConfigurationImage serverImage = prepareImage(239, createIniField(Fields.CYLINDERSCOUNT)); + ConfigurationImage serverImage = TestHelper.prepareImage(239, TestHelper.createIniField(Fields.CYLINDERSCOUNT)); int controllerPort = 6102; + // create virtual controller CountDownLatch serverCreated = new CountDownLatch(1); - BinaryProtocolServer server = createVirtualController(serverImage, controllerPort, parameter -> serverCreated.countDown()); + BinaryProtocolServer server = TestHelper.createVirtualController(serverImage, controllerPort, parameter -> serverCreated.countDown(), LOGGER); assertTrue(serverCreated.await(30, TimeUnit.SECONDS)); int proxyPort = 6103; - IoStream targetEcuSocket; - try { - targetEcuSocket = new TcpIoStream(LOGGER, new Socket(ProxyClient.LOCALHOST, controllerPort)); - } catch (IOException e) { - throw new IllegalStateException("Failed to connect to controller " + ProxyClient.LOCALHOST + ":" + controllerPort); - } + // connect proxy to virtual controller + IoStream targetEcuSocket = TestHelper.createTestStream(controllerPort, LOGGER); BinaryProtocolProxy.createProxy(targetEcuSocket, proxyPort); CountDownLatch connectionEstablishedCountDownLatch = new CountDownLatch(1); + // connect to proxy and read virtual controller through it LinkManager clientManager = new LinkManager(LOGGER); clientManager.startAndConnect(ProxyClient.LOCALHOST + ":" + proxyPort, new ConnectionStateListener() { @Override @@ -130,29 +121,4 @@ public class TcpCommunicationIntegrationTest { clientManager.stop(); } - @NotNull - private static ScalarIniField createIniField(Field field) { - return new ScalarIniField(field.getName(), field.getOffset(), "", field.getType(), 1); - } - - @NotNull - private BinaryProtocolServer createVirtualController(ConfigurationImage ci, int port, Listener serverSocketCreationCallback) { - BinaryProtocolState state = new BinaryProtocolState(); - state.setController(ci); - state.setCurrentOutputs(new byte[1 + Fields.TS_OUTPUT_SIZE]); - - LinkManager linkManager = new LinkManager(LOGGER); - linkManager.setConnector(LinkConnector.getDetachedConnector(state)); - BinaryProtocolServer server = new BinaryProtocolServer(LOGGER); - server.start(linkManager, port, serverSocketCreationCallback); - return server; - } - - @NotNull - private ConfigurationImage prepareImage(int input, ScalarIniField scalarIniField) { - ConfigurationImage ci = new ConfigurationImage(Fields.TOTAL_CONFIG_SIZE); - - scalarIniField.setValue(ci, new Constant(scalarIniField.getName(), "", Integer.toString(input))); - return ci; - } } diff --git a/java_tools/proxy_server/src/main/java/com/rusefi/server/ClientConnectionState.java b/java_tools/proxy_server/src/main/java/com/rusefi/server/ClientConnectionState.java index b018efc1c1..2a7b342206 100644 --- a/java_tools/proxy_server/src/main/java/com/rusefi/server/ClientConnectionState.java +++ b/java_tools/proxy_server/src/main/java/com/rusefi/server/ClientConnectionState.java @@ -2,7 +2,6 @@ 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.io.IoStream; import com.rusefi.io.commands.GetOutputsCommand; @@ -14,8 +13,6 @@ import java.io.IOException; import java.net.Socket; import java.util.function.Function; -import static com.rusefi.binaryprotocol.IoHelper.checkResponseCode; - public class ClientConnectionState { private final Socket clientSocket; private final Logger logger; @@ -61,10 +58,9 @@ public class ClientConnectionState { public void requestControllerInfo() throws IOException { HelloCommand.send(stream, logger); - byte[] response = incomingData.getPacket(logger, "", false); - if (!checkResponseCode(response, BinaryProtocolCommands.RESPONSE_OK)) + String jsonString = HelloCommand.getHelloResponse(incomingData, logger); + if (jsonString == null) return; - String jsonString = new String(response, 1, response.length - 1); sessionDetails = SessionDetails.valueOf(jsonString); if (!AutoTokenUtil.isToken(sessionDetails.getAuthToken())) throw new IOException("Invalid token in " + jsonString);