mirror of
https://github.com/sirjonasxx/G-Earth.git
synced 2024-11-23 00:40:51 +01:00
Added websocket proxying for nitro with broken outgoing packets
This commit is contained in:
parent
1c6d086bff
commit
368a21ffcf
@ -0,0 +1,11 @@
|
||||
package gearth.protocol.connection.proxy.nitro;
|
||||
|
||||
public final class NitroConstants {
|
||||
|
||||
public static final int PORT_WEBSOCKET = 2096;
|
||||
public static final int PORT_HTTP = 9090;
|
||||
|
||||
public static final int WEBSOCKET_BUFFER_SIZE = 1024 * 1024 * 10;
|
||||
public static final String WEBSOCKET_REVISION = "PRODUCTION-201611291003-338511768";
|
||||
|
||||
}
|
@ -1,34 +1,52 @@
|
||||
package gearth.protocol.connection.proxy.nitro;
|
||||
|
||||
import gearth.protocol.HConnection;
|
||||
import gearth.protocol.StateChangeListener;
|
||||
import gearth.protocol.connection.HProxySetter;
|
||||
import gearth.protocol.connection.HState;
|
||||
import gearth.protocol.connection.HStateSetter;
|
||||
import gearth.protocol.connection.proxy.ProxyProvider;
|
||||
import gearth.protocol.connection.proxy.nitro.http.NitroHttpProxy;
|
||||
import gearth.protocol.connection.proxy.nitro.http.NitroHttpProxyServerCallback;
|
||||
import gearth.protocol.connection.proxy.nitro.websocket.NitroWebsocketProxy;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class NitroProxyProvider implements ProxyProvider {
|
||||
public class NitroProxyProvider implements ProxyProvider, NitroHttpProxyServerCallback, StateChangeListener {
|
||||
|
||||
private final HProxySetter proxySetter;
|
||||
private final HStateSetter stateSetter;
|
||||
private final HConnection hConnection;
|
||||
private final NitroHttpProxy nitroProxy;
|
||||
private final HConnection connection;
|
||||
private final NitroHttpProxy nitroHttpProxy;
|
||||
private final NitroWebsocketProxy nitroWebsocketProxy;
|
||||
|
||||
public NitroProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection) {
|
||||
private String originalWebsocketUrl;
|
||||
|
||||
public NitroProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection connection) {
|
||||
this.proxySetter = proxySetter;
|
||||
this.stateSetter = stateSetter;
|
||||
this.hConnection = hConnection;
|
||||
this.nitroProxy = new NitroHttpProxy();
|
||||
this.connection = connection;
|
||||
this.nitroHttpProxy = new NitroHttpProxy(this);
|
||||
this.nitroWebsocketProxy = new NitroWebsocketProxy(proxySetter, stateSetter, connection, this);
|
||||
}
|
||||
|
||||
public String getOriginalWebsocketUrl() {
|
||||
return originalWebsocketUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws IOException {
|
||||
if (!nitroProxy.start()) {
|
||||
System.out.println("Failed to start nitro proxy");
|
||||
connection.getStateObservable().addListener(this);
|
||||
|
||||
stateSetter.setState(HState.NOT_CONNECTED);
|
||||
if (!nitroHttpProxy.start()) {
|
||||
System.out.println("Failed to start nitro proxy");
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nitroWebsocketProxy.start()) {
|
||||
System.out.println("Failed to start nitro websocket proxy");
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -41,13 +59,35 @@ public class NitroProxyProvider implements ProxyProvider {
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
nitroProxy.stop();
|
||||
nitroHttpProxy.stop();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
stateSetter.setState(HState.NOT_CONNECTED);
|
||||
}
|
||||
|
||||
try {
|
||||
nitroWebsocketProxy.stop();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
stateSetter.setState(HState.NOT_CONNECTED);
|
||||
|
||||
connection.getStateObservable().removeListener(this);
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String replaceWebsocketServer(String configUrl, String websocketUrl) {
|
||||
originalWebsocketUrl = websocketUrl;
|
||||
return String.format("ws://127.0.0.1:%d", NitroConstants.PORT_WEBSOCKET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(HState oldState, HState newState) {
|
||||
if (oldState == HState.WAITING_FOR_CLIENT && newState == HState.CONNECTED) {
|
||||
// Unregister but do not stop http proxy.
|
||||
// We are not stopping the http proxy because some requests might still require it to be running.
|
||||
nitroHttpProxy.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package gearth.protocol.connection.proxy.nitro.http;
|
||||
|
||||
import gearth.protocol.connection.proxy.nitro.NitroConstants;
|
||||
import gearth.protocol.connection.proxy.nitro.os.NitroOsFunctions;
|
||||
import gearth.protocol.connection.proxy.nitro.os.NitroOsFunctionsFactory;
|
||||
import org.littleshoot.proxy.HttpProxyServer;
|
||||
@ -12,10 +13,12 @@ public class NitroHttpProxy {
|
||||
|
||||
private final Authority authority;
|
||||
private final NitroOsFunctions osFunctions;
|
||||
private final NitroHttpProxyServerCallback serverCallback;
|
||||
|
||||
private HttpProxyServer proxyServer = null;
|
||||
|
||||
public NitroHttpProxy() {
|
||||
public NitroHttpProxy(NitroHttpProxyServerCallback serverCallback) {
|
||||
this.serverCallback = serverCallback;
|
||||
this.authority = new NitroAuthority();
|
||||
this.osFunctions = NitroOsFunctionsFactory.create();
|
||||
}
|
||||
@ -28,7 +31,7 @@ public class NitroHttpProxy {
|
||||
* Register HTTP(s) proxy on the system.
|
||||
*/
|
||||
private boolean registerProxy() {
|
||||
return this.osFunctions.registerSystemProxy("127.0.0.1", 9090);
|
||||
return this.osFunctions.registerSystemProxy("127.0.0.1", NitroConstants.PORT_HTTP);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -39,18 +42,11 @@ public class NitroHttpProxy {
|
||||
}
|
||||
|
||||
public boolean start() {
|
||||
|
||||
|
||||
try {
|
||||
proxyServer = DefaultHttpProxyServer.bootstrap()
|
||||
.withPort(9090)
|
||||
.withPort(NitroConstants.PORT_HTTP)
|
||||
.withManInTheMiddle(new CertificateSniffingMitmManager(authority))
|
||||
// TODO: Replace lambda with some class
|
||||
.withFiltersSource(new NitroHttpProxyFilterSource((configUrl, websocketUrl) -> {
|
||||
System.out.printf("Found %s at %s%n", websocketUrl, configUrl);
|
||||
|
||||
return "wss://127.0.0.1:2096";
|
||||
}))
|
||||
.withFiltersSource(new NitroHttpProxyFilterSource(serverCallback))
|
||||
.start();
|
||||
|
||||
if (!initializeCertificate()) {
|
||||
@ -74,10 +70,14 @@ public class NitroHttpProxy {
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
public void pause() {
|
||||
if (!unregisterProxy()) {
|
||||
System.out.println("Failed to unregister system proxy, please check manually");
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
pause();
|
||||
|
||||
if (proxyServer == null) {
|
||||
return;
|
||||
|
@ -0,0 +1,17 @@
|
||||
package gearth.protocol.connection.proxy.nitro.websocket;
|
||||
|
||||
import gearth.protocol.HConnection;
|
||||
|
||||
public class NitroForwarder {
|
||||
|
||||
private final HConnection connection;
|
||||
private final NitroSession client;
|
||||
private final NitroSession server;
|
||||
|
||||
public NitroForwarder(HConnection connection, NitroSession client, NitroSession server) {
|
||||
this.connection = connection;
|
||||
this.client = client;
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package gearth.protocol.connection.proxy.nitro.websocket;
|
||||
|
||||
import gearth.protocol.HMessage;
|
||||
import gearth.protocol.HPacket;
|
||||
import gearth.protocol.packethandler.PacketHandler;
|
||||
import gearth.services.extension_handler.ExtensionHandler;
|
||||
import gearth.services.extension_handler.OnHMessageHandled;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class NitroPacketHandler extends PacketHandler {
|
||||
|
||||
private final HMessage.Direction direction;
|
||||
private final NitroSession session;
|
||||
|
||||
protected NitroPacketHandler(HMessage.Direction direction, NitroSession session, ExtensionHandler extensionHandler, Object[] trafficObservables) {
|
||||
super(extensionHandler, trafficObservables);
|
||||
this.direction = direction;
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendToStream(byte[] buffer) {
|
||||
session.getSession().getAsyncRemote().sendBinary(ByteBuffer.wrap(buffer));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(byte[] buffer) throws IOException {
|
||||
HMessage hMessage = new HMessage(new HPacket(deepCopy(buffer)), direction, currentIndex);
|
||||
|
||||
OnHMessageHandled afterExtensionIntercept = hMessage1 -> {
|
||||
notifyListeners(2, hMessage1);
|
||||
|
||||
if (!hMessage1.isBlocked()) {
|
||||
sendToStream(hMessage1.getPacket().toBytes());
|
||||
}
|
||||
};
|
||||
|
||||
notifyListeners(0, hMessage);
|
||||
notifyListeners(1, hMessage);
|
||||
extensionHandler.handle(hMessage, afterExtensionIntercept);
|
||||
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
public static byte[] deepCopy(byte[] org) {
|
||||
if (org == null)
|
||||
return null;
|
||||
byte[] result = new byte[org.length];
|
||||
System.arraycopy(org, 0, result, 0, org.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package gearth.protocol.connection.proxy.nitro.websocket;
|
||||
|
||||
import javax.websocket.Session;
|
||||
|
||||
public interface NitroSession {
|
||||
|
||||
Session getSession();
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package gearth.protocol.connection.proxy.nitro.websocket;
|
||||
|
||||
import gearth.protocol.HConnection;
|
||||
import gearth.protocol.HMessage;
|
||||
import gearth.protocol.connection.*;
|
||||
import gearth.protocol.connection.proxy.nitro.NitroConstants;
|
||||
import gearth.protocol.connection.proxy.nitro.NitroProxyProvider;
|
||||
import gearth.services.internal_extensions.uilogger.hexdumper.Hexdump;
|
||||
|
||||
import javax.websocket.*;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
|
||||
@ServerEndpoint(value = "/")
|
||||
public class NitroWebsocketClient implements NitroSession {
|
||||
|
||||
private final HProxySetter proxySetter;
|
||||
private final HStateSetter stateSetter;
|
||||
private final HConnection connection;
|
||||
private final NitroProxyProvider proxyProvider;
|
||||
private final NitroWebsocketServer server;
|
||||
private final NitroPacketHandler packetHandler;
|
||||
|
||||
private Session activeSession = null;
|
||||
private HProxy proxy = null;
|
||||
|
||||
public NitroWebsocketClient(HProxySetter proxySetter, HStateSetter stateSetter, HConnection connection, NitroProxyProvider proxyProvider) {
|
||||
this.proxySetter = proxySetter;
|
||||
this.stateSetter = stateSetter;
|
||||
this.connection = connection;
|
||||
this.proxyProvider = proxyProvider;
|
||||
this.server = new NitroWebsocketServer(connection, this);
|
||||
this.packetHandler = new NitroPacketHandler(HMessage.Direction.TOSERVER, server, connection.getExtensionHandler(), connection.getTrafficObservables());
|
||||
}
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session session) throws IOException {
|
||||
activeSession = session;
|
||||
activeSession.setMaxBinaryMessageBufferSize(NitroConstants.WEBSOCKET_BUFFER_SIZE);
|
||||
|
||||
server.connect(proxyProvider.getOriginalWebsocketUrl());
|
||||
|
||||
proxy = new HProxy(HClient.NITRO, "", "", -1, -1, "");
|
||||
proxy.verifyProxy(
|
||||
this.server.getPacketHandler(),
|
||||
this.packetHandler,
|
||||
NitroConstants.WEBSOCKET_REVISION,
|
||||
"HTML5" // TODO: What is its purpose?
|
||||
);
|
||||
|
||||
proxySetter.setProxy(proxy);
|
||||
stateSetter.setState(HState.CONNECTED);
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(byte[] b, Session session) throws IOException {
|
||||
System.out.printf("onMessage (%d)%n", b.length);
|
||||
System.out.println(session);
|
||||
System.out.println(Hexdump.hexdump(b));
|
||||
|
||||
packetHandler.act(b);
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(Session session) throws IOException {
|
||||
activeSession = null;
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(Session session, Throwable throwable) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session getSession() {
|
||||
return activeSession;
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package gearth.protocol.connection.proxy.nitro.websocket;
|
||||
|
||||
import gearth.protocol.HConnection;
|
||||
import gearth.protocol.connection.HProxySetter;
|
||||
import gearth.protocol.connection.HStateSetter;
|
||||
import gearth.protocol.connection.proxy.nitro.NitroConstants;
|
||||
import gearth.protocol.connection.proxy.nitro.NitroProxyProvider;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.HandlerList;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
|
||||
|
||||
import javax.websocket.server.ServerContainer;
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
public class NitroWebsocketProxy {
|
||||
|
||||
private final HProxySetter proxySetter;
|
||||
private final HStateSetter stateSetter;
|
||||
private final HConnection connection;
|
||||
private final NitroProxyProvider proxyProvider;
|
||||
|
||||
private final Server server;
|
||||
|
||||
public NitroWebsocketProxy(HProxySetter proxySetter, HStateSetter stateSetter, HConnection connection, NitroProxyProvider proxyProvider) {
|
||||
this.proxySetter = proxySetter;
|
||||
this.stateSetter = stateSetter;
|
||||
this.connection = connection;
|
||||
this.proxyProvider = proxyProvider;
|
||||
this.server = new Server(NitroConstants.PORT_WEBSOCKET);
|
||||
}
|
||||
|
||||
public boolean start() {
|
||||
try {
|
||||
final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
context.setContextPath("/");
|
||||
|
||||
final HandlerList handlers = new HandlerList();
|
||||
handlers.setHandlers(new Handler[] { context });
|
||||
|
||||
final ServerContainer wscontainer = WebSocketServerContainerInitializer.configureContext(context);
|
||||
wscontainer.addEndpoint(ServerEndpointConfig.Builder
|
||||
.create(NitroWebsocketClient.class, "/")
|
||||
.configurator(new NitroWebsocketServerConfigurator(proxySetter, stateSetter, connection, proxyProvider))
|
||||
.build());
|
||||
|
||||
server.setHandler(handlers);
|
||||
server.start();
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
try {
|
||||
server.stop();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package gearth.protocol.connection.proxy.nitro.websocket;
|
||||
|
||||
import gearth.protocol.HConnection;
|
||||
import gearth.protocol.HMessage;
|
||||
import gearth.protocol.connection.proxy.nitro.NitroConstants;
|
||||
import gearth.protocol.packethandler.PacketHandler;
|
||||
|
||||
import javax.websocket.*;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
@ClientEndpoint
|
||||
public class NitroWebsocketServer implements NitroSession {
|
||||
|
||||
private final PacketHandler packetHandler;
|
||||
private Session activeSession = null;
|
||||
|
||||
public NitroWebsocketServer(HConnection connection, NitroWebsocketClient client) {
|
||||
this.packetHandler = new NitroPacketHandler(HMessage.Direction.TOCLIENT, client, connection.getExtensionHandler(), connection.getTrafficObservables());
|
||||
}
|
||||
|
||||
public void connect(String websocketUrl) throws IOException {
|
||||
try {
|
||||
ContainerProvider.getWebSocketContainer().connectToServer(this, URI.create(websocketUrl));
|
||||
} catch (DeploymentException e) {
|
||||
throw new IOException("Failed to deploy websocket client", e);
|
||||
}
|
||||
}
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(Session Session) {
|
||||
this.activeSession = Session;
|
||||
this.activeSession.setMaxBinaryMessageBufferSize(NitroConstants.WEBSOCKET_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void onMessage(byte[] b, Session session) throws IOException {
|
||||
//System.out.printf("onMessage (%d)%n", b.length);
|
||||
//System.out.println(session);
|
||||
//System.out.println(Hexdump.hexdump(b));
|
||||
|
||||
packetHandler.act(b);
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(Session userSession, CloseReason reason) {
|
||||
//System.out.println("closing websocket");
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(Session session, Throwable throwable) {
|
||||
//System.out.println("onError");
|
||||
//System.out.println(session);
|
||||
//System.out.println(throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session getSession() {
|
||||
return activeSession;
|
||||
}
|
||||
|
||||
public PacketHandler getPacketHandler() {
|
||||
return packetHandler;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package gearth.protocol.connection.proxy.nitro.websocket;
|
||||
|
||||
import gearth.protocol.HConnection;
|
||||
import gearth.protocol.connection.HProxySetter;
|
||||
import gearth.protocol.connection.HStateSetter;
|
||||
import gearth.protocol.connection.proxy.nitro.NitroProxyProvider;
|
||||
|
||||
import javax.websocket.server.ServerEndpointConfig;
|
||||
|
||||
public class NitroWebsocketServerConfigurator extends ServerEndpointConfig.Configurator {
|
||||
|
||||
private final HProxySetter proxySetter;
|
||||
private final HStateSetter stateSetter;
|
||||
private final HConnection connection;
|
||||
private final NitroProxyProvider proxyProvider;
|
||||
|
||||
public NitroWebsocketServerConfigurator(HProxySetter proxySetter, HStateSetter stateSetter, HConnection connection, NitroProxyProvider proxyProvider) {
|
||||
this.proxySetter = proxySetter;
|
||||
this.stateSetter = stateSetter;
|
||||
this.connection = connection;
|
||||
this.proxyProvider = proxyProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getEndpointInstance(Class<T> endpointClass) {
|
||||
return (T) new NitroWebsocketClient(proxySetter, stateSetter, connection, proxyProvider);
|
||||
}
|
||||
}
|
@ -114,8 +114,7 @@ public class PacketInfoManager {
|
||||
|
||||
if (clientType == HClient.UNITY) {
|
||||
result.addAll(new GEarthUnityPacketInfoProvider(hotelversion).provide());
|
||||
}
|
||||
else if (clientType == HClient.FLASH) {
|
||||
} else if (clientType == HClient.FLASH || clientType == HClient.NITRO) {
|
||||
try {
|
||||
List<RemotePacketInfoProvider> providers = new ArrayList<>();
|
||||
providers.add(new HarblePacketInfoProvider(hotelversion));
|
||||
|
Loading…
Reference in New Issue
Block a user