From e8decff5cd578db4abb6ad11d65bec7b6be4c660 Mon Sep 17 00:00:00 2001 From: meeh Date: Thu, 20 Sep 2018 03:20:39 +0000 Subject: [PATCH] Mac OS X Launcher: more cleanup and some bugfixes. --- launchers/macosx/AppDelegate.h | 36 +--- .../routermgmt/RouterProcessStatus.swift | 24 +-- launchers/macosx/JavaHelper.h | 167 ------------------ launchers/macosx/RouterTask.h | 35 +--- launchers/macosx/RouterTask.mm | 75 ++------ launchers/macosx/SBridge.h | 45 +++++ launchers/macosx/SBridge.mm | 33 ---- launchers/macosx/main.mm | 62 +------ 8 files changed, 83 insertions(+), 394 deletions(-) delete mode 100644 launchers/macosx/JavaHelper.h diff --git a/launchers/macosx/AppDelegate.h b/launchers/macosx/AppDelegate.h index 8db2f8a88..33c2a0ade 100644 --- a/launchers/macosx/AppDelegate.h +++ b/launchers/macosx/AppDelegate.h @@ -13,10 +13,10 @@ #endif #include +#include "SBridge.h" #include "RouterTask.h" -#include "JavaHelper.h" #define DEF_I2P_VERSION "0.9.36" @@ -34,8 +34,6 @@ @class ExtractMetaInfo; - - @interface ExtractMetaInfo : NSObject @property (copy) NSString* i2pBase; @property (copy) NSString* javaBinary; @@ -63,7 +61,7 @@ inline std::string getDefaultBaseDir() return i2pBaseDir; } -inline void sendUserNotification(NSString* title, NSString* informativeText, NSImage* contentImage = NULL, bool makeSound = false) { +inline void sendUserNotification(NSString* title, NSString* informativeText, bool makeSound = false) { NSUserNotification *userNotification = [[NSUserNotification alloc] init]; userNotification.title = title; @@ -80,32 +78,9 @@ inline void sendUserNotification(NSString* title, NSString* informativeText, NSI [[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification:userNotification]; }; -using maybeAnRouterRunner = I2PRouterTask*; - -std::vector buildClassPath(std::string basePath); - -extern JvmListSharedPtr gRawJvmList; - -// DO NOT ACCESS THIS GLOBAL VARIABLE DIRECTLY. -static std::mutex globalRouterStatusMutex; -static maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{}; -static bool isRuterRunning = false; - -maybeAnRouterRunner getGlobalRouterObject(); -void setGlobalRouterObject(I2PRouterTask* newRouter); -bool getGlobalRouterIsRunning(); -void setGlobalRouterIsRunning(bool running); - -#include "SBridge.h" - #endif -@class MenuBarCtrl; - -@interface AppDelegate : NSObject { -@public - //NSImageView *imageCell; -} +@interface AppDelegate : NSObject @property BOOL enableLogging; @property BOOL enableVerboseLogging; @property (assign) SwiftMainDelegate *swiftRuntime; @@ -118,12 +93,7 @@ void setGlobalRouterIsRunning(bool running); - (void) applicationDidFinishLaunching:(NSNotification *)aNotification; - (void) applicationWillTerminate:(NSNotification *)aNotification; - (void) setApplicationDefaultPreferences; -- (void) userChooseJavaHome; - (AppDelegate *) initWithArgc:(int)argc argv:(const char **)argv; -#ifdef __cplusplus -- (void) startupI2PRouter; -- (NSString *) userSelectJavaHome:(JvmListPtr)rawJvmList; -#endif - (BOOL) userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification; @end diff --git a/launchers/macosx/I2PLauncher/routermgmt/RouterProcessStatus.swift b/launchers/macosx/I2PLauncher/routermgmt/RouterProcessStatus.swift index 0ee054ae4..3ff99f349 100644 --- a/launchers/macosx/I2PLauncher/routermgmt/RouterProcessStatus.swift +++ b/launchers/macosx/I2PLauncher/routermgmt/RouterProcessStatus.swift @@ -26,29 +26,29 @@ import AppKit } @objc func getRouterIsRunning() -> Bool { - if (RouterProcessStatus.isRouterRunning) { - return false; - } else { - let running: Bool = RouterProcessStatus.isRouterRunning - return running - } + return RouterProcessStatus.isRouterRunning } @objc func getJavaHome() -> String { return RouterProcessStatus.knownJavaBinPath! } - - @objc func setJavaHome(_ home: String) { - NSLog("Setting known java to %s", home) - RouterProcessStatus.knownJavaBinPath = home - } } extension RouterProcessStatus { static var isRouterRunning : Bool = false static var isRouterChildProcess : Bool = false static var routerVersion : String? = Optional.none - static var routerUptime : String? = Optional.none + static var routerUptime : String? = Optional.none{ + //Called before the change + willSet(newValue){ + print("RouterProcessStatus.routerUptime will change from ", (self.routerUptime ?? "nil"), " to "+(newValue ?? "nil")) + } + + //Called after the change + didSet{ + print("RouterProcessStatus.routerUptime did change to "+self.routerUptime!) + } + } static var routerStartedAt : Date? = Optional.none static var knownJavaBinPath : String? = Optional.none static var i2pDirectoryPath : String = NSHomeDirectory() + "/Library/I2P" diff --git a/launchers/macosx/JavaHelper.h b/launchers/macosx/JavaHelper.h deleted file mode 100644 index 8cae0dc83..000000000 --- a/launchers/macosx/JavaHelper.h +++ /dev/null @@ -1,167 +0,0 @@ -#pragma once - -#ifdef __cplusplus - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "RouterTask.h" - - -#define DEF_MIN_JVM_VER "1.7+" - -#include "include/strutil.hpp" - -#include -#include -#include - - -class JvmVersion -{ -public: - std::string JVMName; - std::string JVMHomePath; - std::string JVMPlatformVersion; - - inline const char * ToCString() - { - std::stringstream ss; - ss << "JvmVersion(name=" << JVMName.c_str() << ",version="; - ss << JVMPlatformVersion.c_str() << ",home=" << JVMHomePath.c_str() << ")"; - std::string s = ss.str(); - return s.c_str(); - } - - inline bool HasContent() - { - return ( - std::strlen(JVMName.c_str()) > 0 && - std::strlen(JVMHomePath.c_str()) > 0 && - std::strlen(JVMPlatformVersion.c_str()) > 0 - ); - } -}; - - -typedef std::shared_ptr JvmVersionPtr; -typedef std::shared_ptr > JvmListPtr; -typedef std::shared_ptr > > JvmListSharedPtr; -typedef void(^MenuBarControllerActionBlock)(BOOL active); - -extern JvmListSharedPtr gRawJvmList; - -class JvmHomeContext : public std::enable_shared_from_this -{ -public: - - inline void setJvm(JvmVersionPtr* current) - { - mCurrent = *current; - } - - inline JvmListPtr getJvmList() - { - return gRawJvmList; - } - - inline std::shared_ptr getContext() - { - return shared_from_this(); - } - - inline std::string getJavaHome() - { - if (mCurrent) - { - return mCurrent->JVMHomePath; - } - return gRawJvmList->back()->JVMHomePath; - } -private: - JvmVersionPtr mCurrent; -}; - -static void processJvmEntry (const void* key, const void* value, void* context) { - //CFShow(key); - //CFShow(value); - - // The reason for using strprintf is to "force" a copy of the values, - // since local variables gets deleted once this function returns. - auto currentJvm = reinterpret_cast(context); - if (CFEqual((CFStringRef)key,CFSTR("JVMName"))) { - auto strVal = extractString((CFStringRef)value); - currentJvm->JVMName = strprintf("%s",strVal.c_str()); - } - if (CFEqual((CFStringRef)key,CFSTR("JVMHomePath"))) { - auto strVal = extractString((CFStringRef)value); - currentJvm->JVMHomePath = strprintf("%s",strVal.c_str()); - } - if (CFEqual((CFStringRef)key,CFSTR("JVMPlatformVersion"))) { - auto strVal = extractString((CFStringRef)value); - currentJvm->JVMPlatformVersion = strprintf("%s",strVal.c_str()); - } -} - - - -static void processJvmPlistEntries (const void* item, void* context) { - CFDictionaryRef dict = CFDictionaryCreateCopy(kCFAllocatorDefault, (CFDictionaryRef)item); - - JvmVersionPtr currentJvmPtr = std::shared_ptr(new JvmVersion()); - struct CFunctional - { - static void applier(const void* key, const void* value, void* context){ - // The reason for using strprintf is to "force" a copy of the values, - // since local variables gets deleted once this function returns. - auto currentJvm = static_cast(context); - if (CFEqual((CFStringRef)key,CFSTR("JVMName"))) { - auto d = extractString((CFStringRef)value); - currentJvm->JVMName = trim_copy(d); - } - if (CFEqual((CFStringRef)key,CFSTR("JVMHomePath"))) { - auto d = extractString((CFStringRef)value); - currentJvm->JVMHomePath = trim_copy(d); - } - if (CFEqual((CFStringRef)key,CFSTR("JVMPlatformVersion"))) { - auto d = extractString((CFStringRef)value); - currentJvm->JVMPlatformVersion = trim_copy(d); - } - - } - }; - - CFDictionaryApplyFunction(dict, CFunctional::applier, (void*)currentJvmPtr.get()); - - if (currentJvmPtr->HasContent()) - { - printf("Found JVM: %s\n\n", currentJvmPtr->ToCString()); - gRawJvmList->push_back(currentJvmPtr); - } -} - -static void listAllJavaInstallsAvailable() -{ - auto javaHomeRes = check_output({"/usr/libexec/java_home","-v",DEF_MIN_JVM_VER,"-X"}); - CFDataRef javaHomes = CFDataCreate(NULL, (const UInt8 *)javaHomeRes.buf.data(), strlen(javaHomeRes.buf.data())); - - CFPropertyListRef propertyList = CFPropertyListCreateWithData(kCFAllocatorDefault, javaHomes, kCFPropertyListImmutable, NULL, NULL); - - - - auto jCount = CFArrayGetCount((CFArrayRef)propertyList); - - CFArrayApplyFunction((CFArrayRef)propertyList, CFRangeMake(0, jCount), processJvmPlistEntries, NULL); - //CFShow(propertyList); -} - -#endif diff --git a/launchers/macosx/RouterTask.h b/launchers/macosx/RouterTask.h index 3b8e7db18..762a31853 100644 --- a/launchers/macosx/RouterTask.h +++ b/launchers/macosx/RouterTask.h @@ -2,19 +2,13 @@ #include #include -#include #include #import #ifdef __cplusplus -#include "include/subprocess.hpp" - -using namespace subprocess; -class JavaRunner; - -typedef std::function fp_t; -typedef std::function fp_proc_t; +#include +#include const std::vector defaultStartupFlags { @"-Xmx512M", @@ -32,31 +26,6 @@ const std::vector defaultFlagsForExtractorJob { "-Djava.awt.headless=true" }; -/** - * - * class JavaRunner - * - **/ -class JavaRunner -{ -public: - // copy fn - JavaRunner(std::string& javaBin, std::string& arguments, std::string& i2pBaseDir, const fp_proc_t& executingFn, const fp_t& cb); - ~JavaRunner() = default; - - void requestRouterShutdown(); - - std::future execute(); - std::shared_ptr javaProcess; - std::string javaBinaryPath; - std::string javaRouterArgs; - std::string execLine; - std::string _i2pBaseDir; -private: - const fp_proc_t& executingFn; - const fp_t& exitCallbackFn; -}; - #endif diff --git a/launchers/macosx/RouterTask.mm b/launchers/macosx/RouterTask.mm index 51b955d50..8fc231780 100644 --- a/launchers/macosx/RouterTask.mm +++ b/launchers/macosx/RouterTask.mm @@ -9,6 +9,7 @@ #import "I2PLauncher-Swift.h" #include "AppDelegate.h" #endif + #include "include/PidWatcher.h" #import @@ -52,23 +53,13 @@ [stdoutFileHandle waitForDataInBackgroundAndNotify]; [self.routerTask setTerminationHandler:^(NSTask* task) { + // Cleanup NSLog(@"termHandler triggered!"); auto swiftRouterStatus = [[RouterProcessStatus alloc] init]; - [swiftRouterStatus setRouterStatus: true]; + [swiftRouterStatus setRouterStatus: false]; + [swiftRouterStatus setRouterRanByUs: false]; sendUserNotification(APP_IDSTR, @"I2P Router has stopped"); - // Cleanup - //self.isRouterRunning = NO; }]; -/* - self.readLogHandle = [self.processPipe fileHandleForReading]; - NSData *inData = nil; - self.totalLogData = [[[NSMutableData alloc] init] autorelease]; - - while ((inData = [self.readLogHandle availableData]) && - [inData length]) { - [self.totalLogData appendData:inData]; - } -*/ return self; } @@ -91,63 +82,25 @@ - (int) execute { @try { - [self.routerTask launch]; - watchPid([self.routerTask processIdentifier]); - self.isRouterRunning = YES; - return 1; + [self.routerTask launch]; + watchPid([self.routerTask processIdentifier]); + self.isRouterRunning = YES; + return 1; } @catch (NSException *e) { NSLog(@"Expection occurred %@", [e reason]); - return 0; + auto swiftRouterStatus = [[RouterProcessStatus alloc] init]; + [swiftRouterStatus setRouterStatus: false]; + [swiftRouterStatus setRouterRanByUs: false]; + sendUserNotification(@"An error occured, can't start the I2P Router", [e reason]); + return 0; } } - (int) getPID { - return [self.routerTask processIdentifier]; + return [self.routerTask processIdentifier]; } @end - -#ifdef __cplusplus - -JavaRunner::JavaRunner(std::string& javaBin, std::string& arguments, std::string& i2pBaseDir, const fp_proc_t& execFn, const fp_t& cb) - : javaBinaryPath(javaBin), javaRouterArgs(arguments), _i2pBaseDir(i2pBaseDir), executingFn(execFn), exitCallbackFn(cb) -{ - execLine = javaBinaryPath; - execLine += " " + std::string(javaRouterArgs.c_str()); - printf("CLI: %s\n",execLine.c_str()); - javaProcess = std::shared_ptr(new Popen(execLine, environment{{ - {"I2PBASE", _i2pBaseDir}, - {"JAVA_OPTS", getenv("JAVA_OPTS")} - }}, defer_spawn{true})); -} - -void JavaRunner::requestRouterShutdown() -{ - // SIGHUP - javaProcess->kill(1); -} - -std::future JavaRunner::execute() -{ - try { - auto executingFn = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, ^{ - this->executingFn(this); - }); - dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), executingFn); - dispatch_block_wait(executingFn, DISPATCH_TIME_FOREVER); - - // Here, the process is done executing. - - printf("Finished executingFn - Runs callbackFn\n"); - this->exitCallbackFn(); - return std::async(std::launch::async, []{ return 0; }); - } catch (std::exception* ex) { - printf("ERROR: %s\n", ex->what()); - return std::async(std::launch::async, []{ return 1; }); - } -} - -#endif diff --git a/launchers/macosx/SBridge.h b/launchers/macosx/SBridge.h index 09f98a1e8..1b52151ec 100644 --- a/launchers/macosx/SBridge.h +++ b/launchers/macosx/SBridge.h @@ -7,6 +7,51 @@ // #import +#import + +#ifdef __cplusplus +#include +#include +#include +#include +#include +#include "include/fn.h" +std::future startupRouter(NSString* javaBin, NSArray* arguments, NSString* i2pBaseDir); + + +namespace osx { + inline void openUrl(NSString* url) + { + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString: url]]; + } +} + +inline std::vector globVector(const std::string& pattern){ + glob_t glob_result; + glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result); + std::vector files; + for(unsigned int i=0;i startupRouter(NSString* javaBin, NSArray* arguments, options.arguments = arguments; options.i2pBaseDir = i2pBaseDir; auto instance = [[I2PRouterTask alloc] initWithOptions: options]; - //setGlobalRouterObject(instance); - //NSThread *thr = [[NSThread alloc] initWithTarget:instance selector:@selector(execute) object:nil]; [instance execute]; sendUserNotification(APP_IDSTR, @"The I2P router is starting up."); auto pid = [instance getPID]; @@ -53,37 +51,6 @@ std::future startupRouter(NSString* javaBin, NSArray* arguments, } } -namespace osx { - inline void openUrl(NSString* url) - { - [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString: url]]; - } -} - -inline std::vector globVector(const std::string& pattern){ - glob_t glob_result; - glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result); - std::vector files; - for(unsigned int i=0;i #import - - -#include -#include -#include -#include -#include -#include #include #import @@ -30,7 +22,6 @@ #include "AppDelegate.h" #include "RouterTask.h" -#include "JavaHelper.h" #include "include/fn.h" #include "include/portcheck.h" #import "SBridge.h" @@ -111,13 +102,6 @@ using namespace subprocess; cli.push_back(jarfile); cli.push_back("net.i2p.launchers.BaseExtractor"); auto rs = [[RouterProcessStatus alloc] init]; - NSString* jh = [rs getJavaHome]; - if (jh != nil) { - NSLog(@"jh er %@", jh); - } - - NSString* newString = [NSString stringWithFormat:@"file://%@", rs.getJavaHome]; - NSURL *baseURL = [NSURL fileURLWithPath:newString]; std::string execStr = std::string([rs.getJavaHome UTF8String]); for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; }); @@ -132,9 +116,7 @@ using namespace subprocess; NSLog(@"Extraction exit code %@",[NSString stringWithUTF8String:(std::to_string(extractStatus)).c_str()]); if (extractStatus == 0) { - //success = YES; - NSLog(@"Time to detect I2P version in install directory"); - [self.swiftRuntime findInstalledI2PVersion]; + NSLog(@"Extraction complete!"); } } catch (subprocess::OSError &err) { @@ -146,7 +128,6 @@ using namespace subprocess; // All done. Assume success and error are already set. dispatch_async(dispatch_get_main_queue(), ^{ - //sendUserNotification(APP_IDSTR, @"Extraction complete!", self.contentImage); if (completion) { completion(success, error); } @@ -158,45 +139,15 @@ using namespace subprocess; NSLog(@"Exception: %@", errMsg); } }); - - -} - - -- (NSString *)userSelectJavaHome:(JvmListPtr)rawJvmList -{ - NSString *appleScriptString = @"set jvmlist to {\"Newest\""; - for (auto item : *rawJvmList) { - auto str = strprintf(",\"%s\"", item->JVMName.c_str()).c_str(); - NSString* tmp = [NSString stringWithUTF8String:str]; - appleScriptString = [appleScriptString stringByAppendingString:tmp]; - } - appleScriptString = [appleScriptString stringByAppendingString:@"}\nchoose from list jvmlist\n"]; - NSAppleScript *theScript = [[NSAppleScript alloc] initWithSource:appleScriptString]; - NSDictionary *theError = nil; - NSString* userResult = [[theScript executeAndReturnError: &theError] stringValue]; - NSLog(@"User choosed %@.\n", userResult); - if (theError != nil) - { - NSLog(@"Error: %@.\n", theError); - } - return userResult; } - (void)setApplicationDefaultPreferences { - auto defaultJVMHome = check_output({"/usr/libexec/java_home","-v",DEF_MIN_JVM_VER}); - auto tmpStdStr = std::string(defaultJVMHome.buf.data()); - trim(tmpStdStr); - auto cfDefaultHome = CFStringCreateWithCString(NULL, const_cast(tmpStdStr.c_str()), kCFStringEncodingUTF8); [self.userPreferences registerDefaults:@{ - @"javaHome" : (NSString *)cfDefaultHome, - @"lastI2PVersion" : (NSString *)CFSTR(DEF_I2P_VERSION), @"enableLogging": @YES, @"enableVerboseLogging": @YES, @"autoStartRouter": @YES, @"i2pBaseDirectory": (NSString *)CFStringCreateWithCString(NULL, const_cast(getDefaultBaseDir().c_str()), kCFStringEncodingUTF8) }]; - if (self.enableVerboseLogging) NSLog(@"Default JVM home preference set to: %@", cfDefaultHome); auto dict = [self.userPreferences dictionaryRepresentation]; [self.userPreferences setPersistentDomain:dict forName:NSAPPDOMAIN]; @@ -205,10 +156,9 @@ using namespace subprocess; CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); if (self.enableVerboseLogging) NSLog(@"Default preferences stored!"); -#endif } - +#endif - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { @@ -231,7 +181,6 @@ using namespace subprocess; #ifdef __cplusplus - //gRawJvmList = std::make_shared >(std::list()); RouterProcessStatus* routerStatus = [[RouterProcessStatus alloc] init]; std::string i2pBaseDir(getDefaultBaseDir()); @@ -255,6 +204,7 @@ using namespace subprocess; NSBundle *launcherBundle = [NSBundle mainBundle]; + auto sBridge = [[SBridge alloc] init]; // Helper object to hold statefull path information self.metaInfo = [[ExtractMetaInfo alloc] init]; @@ -269,8 +219,6 @@ using namespace subprocess; std::string jarfile("-cp "); jarfile += [self.metaInfo.zipFile UTF8String]; - auto sBridge = [[SBridge alloc] init]; - // Initialize the Swift environment (the UI components) [self.swiftRuntime applicationDidFinishLaunching]; @@ -286,6 +234,8 @@ using namespace subprocess; sendUserNotification(@"I2P is done extracting", @"I2P is now installed and ready to run!"); NSLog(@"Done extracting I2P"); + NSLog(@"Time to detect I2P version in install directory"); + [self.swiftRuntime findInstalledI2PVersion]; if (shouldAutoStartRouter) { [sBridge startupI2PRouter:self.metaInfo.i2pBase javaBinPath:self.metaInfo.javaBinary]; [routerStatus setRouterRanByUs: true]; @@ -294,6 +244,8 @@ using namespace subprocess; } else { // I2P was already found extracted + NSLog(@"Time to detect I2P version in install directory"); + [self.swiftRuntime findInstalledI2PVersion]; if (shouldAutoStartRouter) { [sBridge startupI2PRouter:self.metaInfo.i2pBase javaBinPath:self.metaInfo.javaBinary];