proxy progress
This commit is contained in:
parent
f26c30de4d
commit
deb43f98db
|
@ -1 +0,0 @@
|
|||
rusEFI
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 static SessionDetails createTestSession(String authToken, String signature) {
|
||||
ControllerInfo ci = new ControllerInfo("vehicle", "make", "code", signature);
|
||||
|
||||
return new SessionDetails(ci, authToken, SessionDetails.createOneTimeCode());
|
||||
}
|
||||
|
||||
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, () -> {
|
||||
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();
|
||||
}
|
||||
|
||||
protected void handleCommand() {
|
||||
BaseBroadcastingThread baseBroadcastingThread = new BaseBroadcastingThread(new Socket(LOCALHOST, serverPort),
|
||||
sessionDetails,
|
||||
logger);
|
||||
baseBroadcastingThread.start();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String, UserDetails> 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<String, UserDetails> 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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue