proxy progress

This commit is contained in:
rusefi 2020-07-22 15:22:56 -04:00
parent 439ec69481
commit 811b44dae7
9 changed files with 101 additions and 44 deletions

View File

@ -12,16 +12,15 @@ import com.opensr5.io.DataListener;
import com.rusefi.binaryprotocol.IncomingDataBuffer;
import com.rusefi.dfu.DfuLogic;
import com.rusefi.io.ByteReader;
import com.rusefi.io.IoStream;
import com.rusefi.io.serial.AbstractIoStream;
import java.io.IOException;
import java.util.List;
public class AndroidSerial implements IoStream {
public class AndroidSerial extends AbstractIoStream {
private static final int ST_CDC = 0x5740;
private final IncomingDataBuffer dataBuffer;
private boolean isClosed;
private UsbSerialPort usbSerialPort;
static List<UsbSerialDriver> findUsbSerial(UsbManager usbManager) {
@ -53,16 +52,6 @@ public class AndroidSerial implements IoStream {
ByteReader.runReaderLoop("", listener, reader, Logger.CONSOLE);
}
@Override
public boolean isClosed() {
return isClosed;
}
@Override
public void close() {
isClosed = true;
}
@Override
public void write(byte[] bytes) throws IOException {
usbSerialPort.write(bytes, 1000);

View File

@ -4,12 +4,14 @@ import com.opensr5.Logger;
import com.rusefi.Timeouts;
import com.rusefi.config.generated.Fields;
import com.rusefi.io.IoStream;
import com.rusefi.io.serial.AbstractIoStream;
import etch.util.CircularByteBuffer;
import net.jcip.annotations.ThreadSafe;
import java.io.EOFException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
import static com.rusefi.binaryprotocol.IoHelper.*;
@ -28,15 +30,17 @@ public class IncomingDataBuffer {
*/
private final CircularByteBuffer cbb;
private final Logger logger;
private final AbstractIoStream.StreamStats streamStats;
public IncomingDataBuffer(Logger logger) {
public IncomingDataBuffer(Logger logger, AbstractIoStream.StreamStats streamStats) {
this.streamStats = Objects.requireNonNull(streamStats, "streamStats");
this.cbb = new CircularByteBuffer(BUFFER_SIZE);
this.logger = logger;
}
public static IncomingDataBuffer createDataBuffer(String loggingPrefix, IoStream stream, Logger logger) {
IncomingDataBuffer.loggingPrefix = loggingPrefix;
IncomingDataBuffer incomingData = new IncomingDataBuffer(logger);
IncomingDataBuffer incomingData = new IncomingDataBuffer(logger, stream.getStreamStats());
stream.setInputListener(incomingData::addData);
return incomingData;
}
@ -71,6 +75,7 @@ public class IncomingDataBuffer {
logger.trace(String.format("%x", actualCrc) + " vs " + String.format("%x", packetCrc));
return null;
}
streamStats.onPacketArrived();
logger.trace("packet " + Arrays.toString(packet) + ": crc OK");
return packet;

View File

@ -6,6 +6,7 @@ import com.opensr5.io.WriteStream;
import com.rusefi.binaryprotocol.BinaryProtocol;
import com.rusefi.binaryprotocol.IncomingDataBuffer;
import com.rusefi.binaryprotocol.IoHelper;
import com.rusefi.io.serial.AbstractIoStream;
import com.rusefi.io.tcp.BinaryProtocolServer;
import org.jetbrains.annotations.NotNull;
@ -64,6 +65,8 @@ public interface IoStream extends WriteStream {
boolean isClosed();
AbstractIoStream.StreamStats getStreamStats();
void close();
String getLoggingPrefix();

View File

@ -5,6 +5,13 @@ import com.rusefi.io.IoStream;
public abstract class AbstractIoStream implements IoStream {
private boolean isClosed;
protected StreamStats streamStats = new StreamStats();
@Override
public StreamStats getStreamStats() {
return streamStats;
}
@Override
public void close() {
isClosed = true;
@ -14,4 +21,24 @@ public abstract class AbstractIoStream implements IoStream {
public boolean isClosed() {
return isClosed;
}
public class StreamStats {
private long previousPacketArrivalTime;
private int maxPacketGap;
/**
* @return maximum time in MS between full valid packets received via this stream
*/
public int getMaxPacketGap() {
return maxPacketGap;
}
public void onPacketArrived() {
long now = System.currentTimeMillis();
if (previousPacketArrivalTime != 0) {
maxPacketGap = (int) Math.max(maxPacketGap, now - previousPacketArrivalTime);
}
previousPacketArrivalTime = now;
}
}
}

View File

@ -13,14 +13,15 @@ import java.util.ArrayList;
import java.util.List;
public class ProxyClient {
public static final String LIST_PATH = "/list_online";
public static final String LIST_CONTROLLERS_PATH = "/list_controllers";
public static final String LIST_APPLICATIONS_PATH = "/list_applications";
public static List<PublicSession> getOnlineUsers(int httpPort) throws IOException {
return getOnlineUsers(HttpUtil.RUSEFI_PROXY_JSON_API_PREFIX + ":" + httpPort + LIST_PATH);
public static List<PublicSession> getOnlineApplications(int httpPort) throws IOException {
return getOnlineApplications(HttpUtil.RUSEFI_PROXY_JSON_API_PREFIX + ":" + httpPort + LIST_CONTROLLERS_PATH);
}
@NotNull
public static List<PublicSession> getOnlineUsers(String url) throws IOException {
public static List<PublicSession> getOnlineApplications(String url) throws IOException {
HttpResponse httpResponse = HttpUtil.executeGet(url);
List<PublicSession> userLists = new ArrayList<>();

View File

@ -99,6 +99,8 @@ public class FullServerTest {
ConfigurationImage clientImage = clientStreamState.getControllerConfiguration();
String clientValue = iniField.getValue(clientImage);
assertEquals(Double.toString(value), clientValue);
// now let's test that application connector would be terminated by server due to inactivity
}
}

View File

@ -1,9 +1,11 @@
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.proxy.NetworkConnector;
import com.rusefi.server.*;
import com.rusefi.tools.online.HttpUtil;
import com.rusefi.tools.online.ProxyClient;
@ -18,6 +20,7 @@ import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static com.rusefi.Timeouts.READ_IMAGE_TIMEOUT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@ -84,10 +87,10 @@ public class ServerTest {
assertTrue("onConnected", onConnected.await(30, TimeUnit.SECONDS));
List<ControllerConnectionState> clients = backend.getClients();
List<ControllerConnectionState> clients = backend.getControllers();
assertEquals(2, clients.size());
List<PublicSession> onlineUsers = ProxyClient.getOnlineUsers(HttpUtil.RUSEFI_PROXY_JSON_PROTOCOL + TestHelper.LOCALHOST + ":" + httpPort + ProxyClient.LIST_PATH);
List<PublicSession> onlineUsers = ProxyClient.getOnlineApplications(HttpUtil.RUSEFI_PROXY_JSON_PROTOCOL + TestHelper.LOCALHOST + ":" + httpPort + ProxyClient.LIST_CONTROLLERS_PATH);
assertEquals(2, onlineUsers.size());
allConnected.countDown();
@ -97,17 +100,41 @@ public class ServerTest {
}
@Test
public void testApplicationTimeout() throws InterruptedException {
public void testApplicationTimeout() throws InterruptedException, IOException {
int serverPortForRemoteUsers = 6999;
int serverPortForControllers = 6997;
int httpPort = 6998;
int serverPortForControllers = 6997;
int controllerPort = 6996;
int userId = 7;
try (Backend backend = new Backend(createTestUserResolver(), httpPort, logger)) {
UserDetailsResolver userDetailsResolver = authToken -> new UserDetails(authToken.substring(0, 5), userId);
CountDownLatch controllerRegistered = new CountDownLatch(1);
try (Backend backend = new Backend(userDetailsResolver, httpPort, logger) {
@Override
protected void onRegister(ControllerConnectionState controllerConnectionState) {
super.onRegister(controllerConnectionState);
controllerRegistered.countDown();
}
}) {
TestHelper.runApplicationConnectorBlocking(backend, serverPortForRemoteUsers);
TestHelper.runControllerConnectorBlocking(backend, serverPortForControllers);
// create virtual controller to which "rusEFI network connector" connects to
TestHelper.createVirtualController(controllerPort, new ConfigurationImage(Fields.TOTAL_CONFIG_SIZE), logger);
// start "rusEFI network connector" to connect controller with backend since in real life controller has only local serial port it does not have network
SessionDetails deviceSessionDetails = NetworkConnector.runNetworkConnector(MockRusEfiDevice.TEST_TOKEN_1, TestHelper.LOCALHOST + ":" + controllerPort, serverPortForControllers);
assertTrue(controllerRegistered.await(READ_IMAGE_TIMEOUT, TimeUnit.MILLISECONDS));
SessionDetails authenticatorSessionDetails = new SessionDetails(deviceSessionDetails.getControllerInfo(), MockRusEfiDevice.TEST_TOKEN_3, deviceSessionDetails.getOneTimeToken());
ApplicationRequest applicationRequest = new ApplicationRequest(authenticatorSessionDetails, userId);
}
}

View File

@ -35,13 +35,16 @@ public class Backend implements Closeable {
public static final String BACKEND_VERSION = "0.0001";
public static final int SERVER_PORT_FOR_CONTROLLERS = 8003;
private final FkRegex showOnlineUsers = new FkRegex(ProxyClient.LIST_PATH,
(Take) req -> getUsersOnline()
private final FkRegex showOnlineControllers = new FkRegex(ProxyClient.LIST_CONTROLLERS_PATH,
(Take) req -> getControllersOnline()
);
private final FkRegex showOnlineApplications = new FkRegex(ProxyClient.LIST_CONTROLLERS_PATH,
(Take) req -> getControllersOnline()
);
private boolean isClosed;
// guarded by own monitor
private final Set<ControllerConnectionState> clients = new HashSet<>();
private final Set<ControllerConnectionState> controllers = new HashSet<>();
// guarded by clients
private HashMap<ControllerKey, ControllerConnectionState> byId = new HashMap<>();
// private final int clientTimeout;
@ -62,7 +65,7 @@ public class Backend implements Closeable {
System.out.println("Starting http backend on " + httpPort);
try {
new FtBasic(
new TkFork(showOnlineUsers,
new TkFork(showOnlineControllers,
new Monitoring(this).showStatistics,
new FkRegex(VERSION_PATH, BACKEND_VERSION),
new FkRegex("/", new RsHtml("<html><body>\n" +
@ -70,7 +73,8 @@ public class Backend implements Closeable {
"<br/>\n" +
"<a href='" + Monitoring.STATUS + "'>Status</a>\n" +
"<br/>\n" +
"<a href='" + ProxyClient.LIST_PATH + "'>List</a>\n" +
"<a href='" + ProxyClient.LIST_CONTROLLERS_PATH + "'>Controllers</a>\n" +
"<a href='" + ProxyClient.LIST_APPLICATIONS_PATH + "'>Applications</a>\n" +
"<br/>\n" +
"<br/>\n" +
"</body></html>\n"))
@ -121,7 +125,7 @@ public class Backend implements Closeable {
ControllerKey controllerKey = new ControllerKey(applicationRequest.getTargetUserId(), applicationRequest.getSessionDetails().getControllerInfo());
ControllerConnectionState state;
synchronized (clients) {
synchronized (controllers) {
state = byId.get(controllerKey);
}
if (state == null) {
@ -178,9 +182,9 @@ public class Backend implements Closeable {
}
@NotNull
private RsJson getUsersOnline() throws IOException {
private RsJson getControllersOnline() throws IOException {
JsonArrayBuilder builder = Json.createArrayBuilder();
List<ControllerConnectionState> clients = getClients();
List<ControllerConnectionState> clients = getControllers();
for (ControllerConnectionState client : clients) {
JsonObject clientObject = Json.createObjectBuilder()
@ -190,6 +194,7 @@ public class Backend implements Closeable {
.add(ControllerInfo.VEHICLE_NAME, client.getSessionDetails().getControllerInfo().getVehicleName())
.add(ControllerInfo.ENGINE_MAKE, client.getSessionDetails().getControllerInfo().getEngineMake())
.add(ControllerInfo.ENGINE_CODE, client.getSessionDetails().getControllerInfo().getEngineCode())
.add("MAX_PACKET_GAP", client.getStream().getStreamStats().getMaxPacketGap())
.build();
builder.add(clientObject);
}
@ -219,8 +224,8 @@ public class Backend implements Closeable {
public void register(ControllerConnectionState controllerConnectionState) {
Objects.requireNonNull(controllerConnectionState.getControllerKey(), "ControllerKey");
synchronized (clients) {
clients.add(controllerConnectionState);
synchronized (controllers) {
controllers.add(controllerConnectionState);
byId.put(controllerConnectionState.getControllerKey(), controllerConnectionState);
}
onRegister(controllerConnectionState);
@ -231,9 +236,9 @@ public class Backend implements Closeable {
public void close(ControllerConnectionState inactiveClient) {
inactiveClient.close();
synchronized (clients) {
synchronized (controllers) {
// in case of exception in the initialization phase we do not even add client into the the collection
clients.remove(inactiveClient);
controllers.remove(inactiveClient);
byId.remove(inactiveClient.getControllerKey());
}
}
@ -243,15 +248,15 @@ public class Backend implements Closeable {
isClosed = true;
}
public List<ControllerConnectionState> getClients() {
synchronized (clients) {
return new ArrayList<>(clients);
public List<ControllerConnectionState> getControllers() {
synchronized (controllers) {
return new ArrayList<>(controllers);
}
}
public int getCount() {
synchronized (clients) {
return clients.size();
synchronized (controllers) {
return controllers.size();
}
}

View File

@ -53,11 +53,9 @@ public class RemoteTab {
listDownloadExecutor.execute(new Runnable() {
@Override
public void run() {
String url = HttpUtil.RUSEFI_PROXY_JSON_API_PREFIX + "/list_online";
List<PublicSession> userDetails;
try {
userDetails = ProxyClient.getOnlineUsers(HttpUtil.HTTP_PORT);
userDetails = ProxyClient.getOnlineApplications(HttpUtil.HTTP_PORT);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {