Added more logging and minor housekeeping

This commit is contained in:
dorving 2023-03-29 10:08:44 +02:00
parent 8b1acdf9d7
commit 51de1bbecd
11 changed files with 185 additions and 120 deletions

View File

@ -0,0 +1,21 @@
package gearth.misc;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.function.Consumer;
public class StreamGobbler implements Runnable {
private final InputStream inputStream;
private final Consumer<String> consumeInputLine;
public StreamGobbler(InputStream inputStream, Consumer<String> consumeInputLine) {
this.inputStream = inputStream;
this.consumeInputLine = consumeInputLine;
}
public void run() {
new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumeInputLine);
}
}

View File

@ -13,12 +13,16 @@ import gearth.protocol.connection.proxy.ProxyProviderFactory;
import gearth.protocol.connection.proxy.flash.unix.LinuxRawIpFlashProxyProvider;
import gearth.protocol.connection.proxy.unity.UnityProxyProvider;
import gearth.services.extension_handler.ExtensionHandler;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import java.io.IOException;
import java.util.function.Consumer;
public class HConnection {
private final static Logger LOGGER = LoggerFactory.getLogger(HConnection.class);
public static volatile boolean DECRYPTPACKETS = true;
public static volatile boolean DEBUG = true;
@ -31,19 +35,17 @@ public class HConnection {
private volatile HState state = HState.NOT_CONNECTED;
private volatile HProxy proxy = null;
private ProxyProviderFactory proxyProviderFactory;
private final ProxyProviderFactory proxyProviderFactory;
private ProxyProvider proxyProvider = null;
private volatile boolean developerMode = false;
public HConnection() {
HConnection selff = this;
proxyProviderFactory = new ProxyProviderFactory(
proxy -> selff.proxy = proxy,
selff::setState,
providedProxy -> proxy = providedProxy,
this::setState,
this
);
PacketSafetyManager.PACKET_SAFETY_MANAGER.initialize(this);
}
@ -53,6 +55,7 @@ public class HConnection {
private void setState(HState state) {
if (state != this.state) {
LOGGER.debug("Changed state to {}", state);
HState buffer = this.state;
this.state = state;
stateObservable.fireEvent(l -> l.stateChanged(buffer, state));
@ -62,6 +65,7 @@ public class HConnection {
// autodetect mode
public void start() {
proxyProvider = proxyProviderFactory.provide();
LOGGER.debug("Created proxy provider {}",proxyProvider);
startMITM();
}

View File

@ -2,21 +2,20 @@ package gearth.protocol.connection.proxy;
import gearth.misc.Cacher;
import gearth.misc.OSValidator;
import gearth.misc.StreamGobbler;
import gearth.protocol.HConnection;
import gearth.protocol.connection.HProxySetter;
import gearth.protocol.connection.HStateSetter;
import gearth.protocol.connection.proxy.flash.NormalFlashProxyProvider;
import gearth.protocol.connection.proxy.flash.unix.LinuxRawIpFlashProxyProvider;
import gearth.protocol.connection.proxy.flash.windows.WindowsRawIpFlashProxyProvider;
import gearth.ui.titlebar.TitleBarController;
import gearth.ui.alert.AlertUtil;
import gearth.ui.translations.LanguageBundle;
import javafx.application.Platform;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.DialogPane;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.layout.Region;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
@ -24,6 +23,8 @@ import java.util.List;
public class ProxyProviderFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(ProxyProviderFactory.class);
public static final String HOTELS_CACHE_KEY = "hotelsConnectionInfo";
private static SocksConfiguration socksConfig = null;
@ -52,11 +53,24 @@ public class ProxyProviderFactory {
if (OSValidator.isMac()) {
for (int i = 2; i <= autoDetectHosts.size() + 5; i++) {
ProcessBuilder allowLocalHost = new ProcessBuilder("ifconfig", "lo0", "alias", ("127.0.0." + i), "up");
final String alias = ("127.0.0." + i);
final String processName = "Process for lo0 with alias "+alias;
final ProcessBuilder pb = new ProcessBuilder("ifconfig", "lo0", "alias", alias, "up");
try {
allowLocalHost.start();
} catch (IOException e) {
e.printStackTrace();
LOGGER.debug("Launching process with command {}", pb.command());
final Process process = pb.start();
final Logger logger = LoggerFactory.getLogger(processName);
final StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), logger::debug);
final StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), logger::error);
new Thread(outputGobbler).start();
new Thread(errorGobbler).start();
process.waitFor();
LOGGER.debug("Finished process {}", process);
} catch (IOException | InterruptedException e) {
LOGGER.error("Exception occurred for {}", processName, e);
}
}
}
@ -106,18 +120,12 @@ public class ProxyProviderFactory {
return new WindowsRawIpFlashProxyProvider(proxySetter, stateSetter, hConnection, domain, port, true);
}
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.ERROR, "", ButtonType.OK);
alert.getDialogPane().getChildren().add(new Label(LanguageBundle.get("alert.alreadyconnected.content").replaceAll("\\\\n", System.lineSeparator())));
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
alert.setResizable(false);
try {
TitleBarController.create(alert).showAlert();
} catch (IOException e) {
e.printStackTrace();
}
AlertUtil.showAlert(alert -> {
final DialogPane dialogPane = alert.getDialogPane();
dialogPane.setMinHeight(Region.USE_PREF_SIZE);
dialogPane.getChildren()
.add(new Label(LanguageBundle.get("alert.alreadyconnected.content").replaceAll("\\\\n", System.lineSeparator())));
});
return null;
}
else if (OSValidator.isUnix() || OSValidator.isMac()) {
@ -132,6 +140,7 @@ public class ProxyProviderFactory {
return provide(potentialHost);
}
}
private ProxyProvider provide(List<String> potentialHosts) {
return new NormalFlashProxyProvider(proxySetter, stateSetter, hConnection, potentialHosts, socksConfig.useSocks() && !socksConfig.onlyUseIfNeeded());
}

View File

@ -9,10 +9,8 @@ import gearth.protocol.hostreplacer.hostsfile.HostReplacer;
import gearth.protocol.hostreplacer.hostsfile.HostReplacerFactory;
import gearth.protocol.portchecker.PortChecker;
import gearth.protocol.portchecker.PortCheckerFactory;
import gearth.ui.titlebar.TitleBarController;
import javafx.application.Platform;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import gearth.ui.alert.AlertUtil;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.net.*;
@ -21,16 +19,14 @@ import java.util.List;
public class NormalFlashProxyProvider extends FlashProxyProvider {
private List<String> potentialHosts;
private final List<String> potentialHosts;
private static final HostReplacer hostsReplacer = HostReplacerFactory.get();
private volatile boolean hostRedirected = false;
private volatile List<HProxy> potentialProxies = new ArrayList<>();
private final List<HProxy> potentialProxies = new ArrayList<>();
private volatile HProxy proxy = null;
private boolean useSocks;
private final boolean useSocks;
public NormalFlashProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection, List<String> potentialHosts, boolean useSocks) {
super(proxySetter, stateSetter, hConnection);
@ -38,13 +34,12 @@ public class NormalFlashProxyProvider extends FlashProxyProvider {
this.useSocks = useSocks;
}
@Override
public void start() throws IOException {
if (hConnection.getState() != HState.NOT_CONNECTED) {
return;
}
logger.debug("Starting...");
prepare();
addToHosts();
launchProxy();
@ -53,7 +48,7 @@ public class NormalFlashProxyProvider extends FlashProxyProvider {
private void prepare() {
stateSetter.setState(HState.PREPARING);
logger.debug("Preparing with {} potential hosts", potentialHosts);
List<String> willremove = new ArrayList<>();
int c = 0;
for (String host : potentialHosts) {
@ -94,44 +89,27 @@ public class NormalFlashProxyProvider extends FlashProxyProvider {
private void launchProxy() throws IOException {
stateSetter.setState(HState.WAITING_FOR_CLIENT);
for (int c = 0; c < potentialProxies.size(); c++) {
HProxy potentialProxy = potentialProxies.get(c);
logger.debug("Waiting for clients, potentialProxies={}", potentialProxies);
for (HProxy potentialProxy : potentialProxies) {
ServerSocket proxy_server;
try {
proxy_server = new ServerSocket(potentialProxy.getIntercept_port(), 10, InetAddress.getByName(potentialProxy.getIntercept_host()));
} catch (BindException e) {
PortChecker portChecker = PortCheckerFactory.getPortChecker();
String processName = portChecker.getProcessUsingPort(potentialProxy.getIntercept_port());
Platform.runLater(() -> {
Alert a = new Alert(Alert.AlertType.ERROR, "The port is in use by " + processName,
ButtonType.OK);
try {
TitleBarController.create(a).showAlertAndWait();
} catch (IOException ex) {
logger.error("Failed to create port in use error alert", ex);
}
});
throw new IOException(e);
}
potentialProxy.initProxy(proxy_server);
final ServerSocket proxyServer = createProxyServer(potentialProxy);
potentialProxy.initProxy(proxyServer);
new Thread(() -> {
try {
final Thread thread = new Thread(() -> {
try {
Thread.sleep(30);
while ((hConnection.getState() == HState.WAITING_FOR_CLIENT) && !proxy_server.isClosed()) {
while ((hConnection.getState() == HState.WAITING_FOR_CLIENT) && !proxyServer.isClosed()) {
try {
Socket client = proxy_server.accept();
Socket client = proxyServer.accept();
proxy = potentialProxy;
closeAllProxies(proxy);
logger.debug("Accepted proxy {}, starting proxy thread (useSocks={})",proxy, useSocks);
logger.debug("Accepted proxy {}, starting proxy thread (useSocks={})", proxy, useSocks);
new Thread(() -> {
try {
Socket server;
if (!useSocks) {
server = new Socket(proxy.getActual_domain(), proxy.getActual_port());
}
else {
server = new Socket(proxy.getActual_domain(), proxy.getActual_port());
} else {
SocksConfiguration configuration = ProxyProviderFactory.getSocksConfig();
if (configuration == null) {
showInvalidConnectionError();
@ -148,30 +126,49 @@ public class NormalFlashProxyProvider extends FlashProxyProvider {
showInvalidConnectionError();
abort();
logger.error("Failed to configure SOCKS proxy", e);
}
catch (InterruptedException | IOException e) {
} catch (InterruptedException | IOException e) {
logger.error("An unexpected exception occurred", e);
}
}).start();
} catch (IOException e1) {
logger.error("An unexpected exception occurred", e1);
} catch (SocketException exception) {
logger.error("An unexpected exception occurred: {}", exception.getLocalizedMessage());
} catch (IOException exception) {
logger.error("An unexpected exception occurred", exception);
}
}
} catch (Exception e) {
e.printStackTrace();
logger.error("An unexpected error occurred", e);
} finally {
logger.debug("Stopped");
}
}).start();
});
thread.setName("ProxyServerThread ("+ potentialProxy.getInput_domain()+") -> ("+potentialProxy.getActual_domain()+")");
thread.start();
}
logger.debug("Done waiting for clients with connection state {}", hConnection.getState());
}
@NotNull
private static ServerSocket createProxyServer(HProxy potentialProxy) throws IOException {
final ServerSocket proxy_server;
try {
proxy_server = new ServerSocket(potentialProxy.getIntercept_port(), 10, InetAddress.getByName(potentialProxy.getIntercept_host()));
} catch (BindException e) {
final PortChecker portChecker = PortCheckerFactory.getPortChecker();
final String processName = portChecker.getProcessUsingPort(potentialProxy.getIntercept_port());
AlertUtil.showAlertAndWait("The port is in use by " + processName);
throw new IOException(e);
}
return proxy_server;
}
@Override
public void abort() {
stateSetter.setState(HState.ABORTING);
logger.debug("Aborting... hostRedirected={}", hostRedirected);
if (hostRedirected) {
removeFromHosts();
}
clearAllProxies();
super.abort();
}
@ -197,15 +194,10 @@ public class NormalFlashProxyProvider extends FlashProxyProvider {
hostRedirected = true;
}
private void removeFromHosts(){
List<String> linesTemp = new ArrayList<>();
for (HProxy proxy : potentialProxies) {
linesTemp.add(proxy.getIntercept_host() + " " + proxy.getInput_domain());
}
String[] lines = new String[linesTemp.size()];
for (int i = 0; i < linesTemp.size(); i++) {
lines[i] = linesTemp.get(i);
}
final String[] lines = potentialProxies.stream()
.map(proxy -> proxy.getIntercept_host() + " " + proxy.getInput_domain())
.toArray(String[]::new);
logger.debug("Removing {} lines from hosts file (lines={})", lines.length, lines);
hostsReplacer.removeRedirect(lines);
hostRedirected = false;
}

View File

@ -4,6 +4,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

View File

@ -25,7 +25,7 @@ public class MacOSHabboClient extends HabboClient {
private static final Logger LOGGER = LoggerFactory.getLogger(MacOSHabboClient.class);
private static final String G_MEM_EXECUTABLE_FILE_NAME = "/g_mem_mac";
private static final String G_MEM_EXECUTABLE_FILE_NAME = "/G-Mem";
/**
* The header id (opcode) of the packet that contains the value for the {@link #production} field.

View File

@ -4,7 +4,7 @@ import gearth.extensions.InternalExtensionBuilder;
import gearth.misc.HostInfo;
import gearth.misc.listenerpattern.Observable;
import gearth.misc.listenerpattern.SynchronizedObservable;
import gearth.services.extension_handler.extensions.implementations.network.NetworkExtension;
import gearth.services.extension_handler.extensions.implementations.network.NetworkExtensionClient;
import gearth.services.packet_info.PacketInfoManager;
import gearth.protocol.HMessage;
import gearth.protocol.HPacket;
@ -16,9 +16,9 @@ import gearth.services.extension_handler.extensions.listeners.OnDeleteListener;
/**
* Represents a type of extension created with one of the extension APIs.
*
* @see NetworkExtension extensions connecting to G-Earth from a different process.
* @see NetworkExtensionClient xtensions connecting to G-Earth from a different process.
* @see InternalExtensionBuilder internal extensions (JAR files) that follow
* the same communication protocol as {@link NetworkExtension network extensions}.
* the same communication protocol as {@link NetworkExtensionClient network extensions}.
*/
public abstract class GEarthExtension {

View File

@ -1,15 +1,11 @@
package gearth.services.internal_extensions.extensionstore.application.entities;
import gearth.GEarth;
import gearth.protocol.HMessage;
import gearth.protocol.HPacket;
import gearth.services.internal_extensions.extensionstore.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.application.GExtensionStoreController;
import gearth.services.internal_extensions.extensionstore.application.WebUtils;
import gearth.services.internal_extensions.extensionstore.application.entities.extensiondetails.StoreExtensionDetailsOverview;
import gearth.services.internal_extensions.extensionstore.application.entities.queriedoverviews.CategorizedOverview;
import gearth.services.internal_extensions.extensionstore.repository.StoreRepository;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreExtension;
import gearth.services.internal_extensions.extensionstore.application.entities.extensiondetails.StoreExtensionDetailsOverview;
import gearth.ui.translations.LanguageBundle;
import netscape.javascript.JSObject;
@ -27,7 +23,7 @@ public class StoreExtensionItem implements ContentItem {
new StoreExtensionDetailsOverview(
gExtensionStore.getController().getCurrentOverview(),
0,
GExtensionStore.PAGESIZE,
GExtensionStore.MAX_PAGES,
storeExtension,
gExtensionStore.getRepository()
)

View File

@ -44,12 +44,12 @@ public class StoreRepository {
String queryLower = queryString.toLowerCase();
final List<StoreExtension> extensions = getExtensions();
for (StoreExtension extension : extensions) {
System.out.println(extension.getTitle());
for (String system : extension.getCompatibility().getSystems()) {
System.out.println(system);
}
}
// for (StoreExtension extension : extensions) {
// System.out.println(extension.getTitle());
// for (String system : extension.getCompatibility().getSystems()) {
// System.out.println(system);
// }
// }
Stream<StoreExtension> stream = extensions.stream()
.filter(ext -> ext.getTitle().toLowerCase().contains(queryLower) || ext.getDescription().toLowerCase().contains(queryLower)
|| ext.getAuthors().stream().anyMatch(author -> author.getName().toLowerCase().contains(queryLower)

View File

@ -37,6 +37,7 @@ public class StoreExtensionTools {
public final static String EXTENSIONS_PATH = Paths.get(NormalExtensionRunner.JAR_PATH, ExecutionInfo.EXTENSIONS_DIRECTORY).toString();
public static void executeExtension(String extensionPath, int port) {
try {
String installedExtensionId = Paths.get(extensionPath).getFileName().toString();
@ -242,27 +243,28 @@ public class StoreExtensionTools {
}
public static void main(String[] args) {
StoreFetch.fetch(GEarth.version, new StoreFetch.StoreFetchListener() {
@Override
public void success(StoreRepository storeRepository) {
installExtension("G-BuildTools", storeRepository, new InstallExtListener() {
@Override
public void success(String installationFolder) {
System.out.println(String.format("Installed in: %s", installationFolder));
}
@Override
public void fail(String reason) {
System.out.println(reason);
}
});
}
@Override
public void fail(String reason) {
System.out.println("failed fetching repository");
}
});
System.out.println(EXTENSIONS_PATH);
// StoreFetch.fetch(GEarth.version, new StoreFetch.StoreFetchListener() {
// @Override
// public void success(StoreRepository storeRepository) {
// installExtension("G-BuildTools", storeRepository, new InstallExtListener() {
// @Override
// public void success(String installationFolder) {
// System.out.println(String.format("Installed in: %s", installationFolder));
// }
//
// @Override
// public void fail(String reason) {
// System.out.println(reason);
// }
// });
// }
//
// @Override
// public void fail(String reason) {
// System.out.println("failed fetching repository");
// }
// });
}

View File

@ -0,0 +1,40 @@
package gearth.ui.alert;
import gearth.ui.titlebar.TitleBarController;
import javafx.application.Platform;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.function.Consumer;
public class AlertUtil {
private final static Logger LOGGER = LoggerFactory.getLogger(AlertUtil.class);
public static void showAlertAndWait(String contentText) {
Platform.runLater(() -> {
Alert alert = new Alert(Alert.AlertType.ERROR, contentText, ButtonType.OK);
try {
TitleBarController.create(alert).showAlertAndWait();
} catch (IOException ex) {
LOGGER.error("Failed to create alert with content \"{}\"", contentText, ex);
}
});
}
public static void showAlert(Consumer<Alert> consumer) {
Platform.runLater(() -> {
final Alert alert = new Alert(Alert.AlertType.ERROR, "", ButtonType.OK);
alert.setResizable(false);
consumer.accept(alert);
try {
TitleBarController.create(alert).showAlert();
} catch (IOException e) {
e.printStackTrace();
}
});
}
}