proxy progress - backend version validation on start-up

This commit is contained in:
rusefi 2020-07-22 18:30:17 -04:00
parent 2b8f93f337
commit 553db5c479
5 changed files with 53 additions and 21 deletions

View File

@ -8,6 +8,8 @@ import com.rusefi.io.tcp.TcpIoStream;
import com.rusefi.server.ApplicationRequest;
import com.rusefi.server.rusEFISSLContext;
import com.rusefi.tools.online.HttpUtil;
import com.rusefi.tools.online.ProxyClient;
import org.apache.http.HttpResponse;
import java.io.IOException;
@ -23,10 +25,17 @@ public class LocalApplicationProxy {
/**
* @param serverPortForRemoteUsers port on which rusEFI proxy accepts authenticator connections
* @param applicationRequest remote session we want to connect to
* @param authenticatorPort local port we would bind for TunerStudio to connect to
* @param applicationRequest remote session we want to connect to
* @param authenticatorPort local port we would bind for TunerStudio to connect to
* @param httpPort
*/
static void startAndRun(Logger logger, int serverPortForRemoteUsers, ApplicationRequest applicationRequest, int authenticatorPort) throws IOException {
static void startAndRun(Logger logger, int serverPortForRemoteUsers, ApplicationRequest applicationRequest, int authenticatorPort, int httpPort) throws IOException {
HttpResponse httpResponse = HttpUtil.executeGet(ProxyClient.getHttpAddress(httpPort) + ProxyClient.VERSION_PATH);
String version = HttpUtil.getResponse(httpResponse);
logger.info("Version=" + version);
if (!version.contains(ProxyClient.BACKEND_VERSION))
throw new IOException("Unexpected backend version " + version + " while we want " + ProxyClient.BACKEND_VERSION);
IoStream authenticatorToProxyStream = new TcpIoStream("authenticatorToProxyStream ", logger, rusEFISSLContext.getSSLSocket(HttpUtil.RUSEFI_PROXY_HOSTNAME, serverPortForRemoteUsers));
LocalApplicationProxy localApplicationProxy = new LocalApplicationProxy(logger, applicationRequest);
localApplicationProxy.run(authenticatorToProxyStream);

View File

@ -82,9 +82,8 @@ public class FullServerTest {
ApplicationRequest applicationRequest = new ApplicationRequest(authenticatorSessionDetails, userId);
// start authenticator
int authenticatorPort = 7004; // local port on which authenticator accepts connections from Tuner Studio
LocalApplicationProxy.startAndRun(logger, serverPortForRemoteUsers, applicationRequest, authenticatorPort);
LocalApplicationProxy.startAndRun(logger, serverPortForRemoteUsers, applicationRequest, authenticatorPort, httpPort);
CountDownLatch connectionEstablishedCountDownLatch = new CountDownLatch(1);

View File

@ -56,7 +56,8 @@ public class NetworkConnector {
private static SessionDetails runNetworkConnector(int serverPortForControllers, LinkManager linkManager, final Logger logger, String authToken) throws IOException {
IoStream targetEcuSocket = linkManager.getConnector().getBinaryProtocol().getStream();
HelloCommand.send(targetEcuSocket, logger);
String controllerSignature = HelloCommand.getHelloResponse(targetEcuSocket.getDataBuffer(), logger).trim();
String helloResponse = HelloCommand.getHelloResponse(targetEcuSocket.getDataBuffer(), logger);
String controllerSignature = helloResponse.trim();
ConfigurationImage image = linkManager.getConnector().getBinaryProtocol().getControllerConfiguration();
String vehicleName = Fields.VEHICLENAME.getStringValue(image);

View File

@ -9,10 +9,17 @@ public class ApplicationConnectionState {
private final UserDetails userDetails;
@NotNull
private final IoStream clientStream;
private final ControllerConnectionState state;
public ApplicationConnectionState(UserDetails userDetails, ApplicationRequest applicationRequest, IoStream clientStream) {
public ApplicationConnectionState(UserDetails userDetails, ApplicationRequest applicationRequest, IoStream clientStream, ControllerConnectionState state) {
this.userDetails = Objects.requireNonNull(userDetails, "userDetails");
this.clientStream = Objects.requireNonNull(clientStream, "clientStream");
this.state = Objects.requireNonNull(state, "state");
if (clientStream.getStreamStats().getPreviousPacketArrivalTime() == 0)
throw new IllegalStateException("Invalid state - no packets on " + this);
if (!state.isUsed())
throw new IllegalArgumentException("state is supposed to be used by us");
}
@NotNull
@ -25,7 +32,11 @@ public class ApplicationConnectionState {
}
public void close() {
clientStream.close();
try {
clientStream.close();
} finally {
state.release();
}
}
@Override

View File

@ -34,10 +34,9 @@ import java.util.function.Function;
* See NetworkConnectorStartup
*/
public class Backend implements Closeable {
public static final String VERSION_PATH = "/version";
public static final String BACKEND_VERSION = "0.0001";
public static final int SERVER_PORT_FOR_CONTROLLERS = 8003;
public static final String MAX_PACKET_GAP = "MAX_PACKET_GAP";
private static final String MAX_PACKET_GAP = "MAX_PACKET_GAP";
private static final String IS_USED = "isUsed";
private final FkRegex showOnlineControllers = new FkRegex(ProxyClient.LIST_CONTROLLERS_PATH,
(Take) req -> getControllersOnline()
@ -83,12 +82,13 @@ public class Backend implements Closeable {
new FtBasic(
new TkFork(showOnlineControllers,
new Monitoring(this).showStatistics,
new FkRegex(VERSION_PATH, BACKEND_VERSION),
new FkRegex(ProxyClient.VERSION_PATH, ProxyClient.BACKEND_VERSION),
new FkRegex("/", new RsHtml("<html><body>\n" +
"<a href='https://rusefi.com/online/'>rusEFI Online</a>\n" +
"<br/>\n" +
"<a href='" + Monitoring.STATUS + "'>Status</a>\n" +
"<br/>\n" +
"<a href='" + ProxyClient.VERSION_PATH + "'>Version</a>\n" +
"<a href='" + ProxyClient.LIST_CONTROLLERS_PATH + "'>Controllers</a>\n" +
"<a href='" + ProxyClient.LIST_APPLICATIONS_PATH + "'>Applications</a>\n" +
"<br/>\n" +
@ -127,7 +127,7 @@ public class Backend implements Closeable {
public void run() {
totalSessions.incrementAndGet();
// connection from authenticator app which proxies for Tuner Studio
IoStream applicationClientStream;
IoStream applicationClientStream = null;
ApplicationConnectionState applicationConnectionState = null;
try {
applicationClientStream = new TcpIoStream("[app] ", logger, applicationSocket);
@ -142,24 +142,19 @@ public class Backend implements Closeable {
UserDetails userDetails = userDetailsResolver.apply(authToken);
if (userDetails == null) {
logger.info("Authentication failed for application " + authToken);
applicationClientStream.close();
return;
}
applicationConnectionState = new ApplicationConnectionState(userDetails, applicationRequest, applicationClientStream);
ControllerKey controllerKey = new ControllerKey(applicationRequest.getTargetUserId(), applicationRequest.getSessionDetails().getControllerInfo());
ControllerConnectionState state;
synchronized (lock) {
state = controllersByKey.get(controllerKey);
state = acquire(controllerKey);
}
if (state == null) {
close(applicationConnectionState);
logger.info("No controller for " + controllerKey);
return;
}
if (applicationConnectionState.getClientStream().getStreamStats().getPreviousPacketArrivalTime() == 0)
throw new IllegalStateException("Invalid state - no packets on " + applicationConnectionState);
applicationConnectionState = new ApplicationConnectionState(userDetails, applicationRequest, applicationClientStream, state);
synchronized (lock) {
applications.add(applicationConnectionState);
}
@ -169,6 +164,7 @@ public class Backend implements Closeable {
} catch (Throwable e) {
logger.info("Application Connector: Got error " + e);
} finally {
applicationClientStream.close();
close(applicationConnectionState);
}
}
@ -177,6 +173,21 @@ public class Backend implements Closeable {
}, serverPortForApplications, "ApplicationServer", serverSocketCreationCallback, BinaryProtocolServer.SECURE_SOCKET_FACTORY);
}
private ControllerConnectionState acquire(ControllerKey controllerKey) {
synchronized (lock) {
ControllerConnectionState state = controllersByKey.get(controllerKey);
if (state == null) {
// no such controller
return null;
}
if (!state.acquire()) {
// someone is already talking to this controller
return null;
}
return state;
}
}
protected void close(ApplicationConnectionState applicationConnectionState) {
if (applicationConnectionState != null)
applicationConnectionState.close();
@ -194,7 +205,7 @@ public class Backend implements Closeable {
public void runControllerConnector(int serverPortForControllers, Listener serverSocketCreationCallback) {
this.serverPortForControllers = serverPortForControllers;
System.out.println("Starting controller connector at " + serverPortForControllers);
logger.info("Starting controller connector at " + serverPortForControllers);
BinaryProtocolServer.tcpServerSocket(logger, new Function<Socket, Runnable>() {
@Override
public Runnable apply(Socket controllerSocket) {
@ -242,6 +253,7 @@ public class Backend implements Closeable {
JsonObject controllerObject = Json.createObjectBuilder()
.add(UserDetails.USER_ID, client.getUserDetails().getUserId())
.add(UserDetails.USERNAME, client.getUserDetails().getUserName())
.add(IS_USED, client.isUsed())
.add(ControllerInfo.SIGNATURE, client.getSessionDetails().getControllerInfo().getSignature())
.add(ControllerInfo.VEHICLE_NAME, client.getSessionDetails().getControllerInfo().getVehicleName())
.add(ControllerInfo.ENGINE_MAKE, client.getSessionDetails().getControllerInfo().getEngineMake())