From 90f50ec2a08faa1f35cc25d2dcb03f12f53ffa6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=88=9A=28noham=29=C2=B2?= <100566912+NohamR@users.noreply.github.com> Date: Sat, 9 May 2026 18:13:53 +0200 Subject: [PATCH] Add MQTT URI patching and hook for Paho --- src/reMarkable/reMarkable.m | 89 +++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/reMarkable/reMarkable.m b/src/reMarkable/reMarkable.m index b730f7d..7be221e 100644 --- a/src/reMarkable/reMarkable.m +++ b/src/reMarkable/reMarkable.m @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -245,6 +246,17 @@ static QNetworkReply *(*original_qNetworkAccessManager_createRequest)( static void (*original_qWebSocket_open)( QWebSocket *self, const QNetworkRequest &request) = NULL; + +typedef void* MQTTAsync; +typedef void* MQTTAsync_createOptions; + +static int (*original_MQTTAsync_createWithOptions)( + MQTTAsync *handle, + const char *serverURI, + const char *clientId, + int persistence_type, + void *persistence_context, + MQTTAsync_createOptions *options) = NULL; #endif #ifdef BUILD_MODE_QMLREBUILD @@ -301,6 +313,12 @@ static inline bool shouldPatchURL(const QString &host) { hookFunction:(void *)hooked_qWebSocket_open originalFunction:(void **)&original_qWebSocket_open logPrefix:@"[reMarkable]"]; + + [MemoryUtils hookSymbol:@"libpaho-mqtt3as.1.dylib" + symbolName:@"_MQTTAsync_createWithOptions" + hookFunction:(void *)hooked_MQTTAsync_createWithOptions + originalFunction:(void **)&original_MQTTAsync_createWithOptions + logPrefix:@"[reMarkable]"]; #endif #ifdef BUILD_MODE_QMLREBUILD @@ -442,6 +460,77 @@ extern "C" void hooked_qWebSocket_open( original_qWebSocket_open(self, req); } + +// Patch a paho URI: "ssl://host.remarkable.com:port" -> "ssl://proxy:port" +// Returns patched string, or empty if no patch needed. +static std::string PatchMqttUri(const char* uri) +{ + if (!uri) return {}; + const std::string original(uri); + + size_t schemeEnd = original.find("://"); + size_t hostStart = (schemeEnd != std::string::npos) ? schemeEnd + 3 : 0; + size_t hostEnd = original.find_first_of(":/", hostStart); + if (hostEnd == std::string::npos) hostEnd = original.size(); + + const std::string origHost = original.substr(hostStart, hostEnd - hostStart); + + // Match any *.remarkable.com or *.remarkable.engineering host + static const char* kSuffixes[] = { + ".remarkable.com", + ".remarkable.engineering", + nullptr + }; + bool shouldPatch = false; + for (int i = 0; kSuffixes[i]; ++i) + { + const std::string suffix(kSuffixes[i]); + if (origHost.size() >= suffix.size() && + origHost.compare(origHost.size() - suffix.size(), + suffix.size(), suffix) == 0) + { + shouldPatch = true; + break; + } + } + if (!shouldPatch) return {}; + + std::string patched = original; + std::string proxyHost = [gConfiguredHost UTF8String]; + patched.replace(hostStart, hostEnd - hostStart, proxyHost); + + // Fix port + size_t colonPos = patched.find(':', hostStart + proxyHost.size()); + if (colonPos != std::string::npos) + { + size_t numEnd = patched.find_first_not_of("0123456789", colonPos + 1); + if (numEnd == std::string::npos) numEnd = patched.size(); + patched.replace(colonPos + 1, numEnd - colonPos - 1, + std::to_string([gConfiguredPort intValue])); + } + return patched; +} + +extern "C" int hooked_MQTTAsync_createWithOptions( + MQTTAsync *handle, + const char *serverURI, + const char *clientId, + int persistence_type, + void *persistence_context, + MQTTAsync_createOptions *options) +{ + if (!original_MQTTAsync_createWithOptions) { + return -1; // error code for MQTTAsync_create failure + } + + std::string patchedUri = PatchMqttUri(serverURI); + if (!patchedUri.empty()) { + NSLogger(@"[reMarkable] Patching MQTT URI from %s to %s", serverURI, patchedUri.c_str()); + return original_MQTTAsync_createWithOptions(handle, patchedUri.c_str(), clientId, persistence_type, persistence_context, options); + } + + return original_MQTTAsync_createWithOptions(handle, serverURI, clientId, persistence_type, persistence_context, options); +} #endif // BUILD_MODE_RMFAKECLOUD #ifdef BUILD_MODE_QMLREBUILD