From 7dbf5682128233b938a3c45e58dcdff8f662cd4a Mon Sep 17 00:00:00 2001 From: meeh <meeh@mail.i2p> Date: Thu, 11 Oct 2018 11:55:05 +0000 Subject: [PATCH] OSX Launcher: Refactor deployment code to own file, + code cleanups. --- launchers/macosx/AppDelegate.h | 18 +++-- launchers/macosx/Deployer.h | 8 ++- launchers/macosx/Deployer.m | 13 ---- launchers/macosx/Deployer.mm | 120 +++++++++++++++++++++++++++++++++ launchers/macosx/main.mm | 110 ++++++------------------------ 5 files changed, 160 insertions(+), 109 deletions(-) delete mode 100644 launchers/macosx/Deployer.m create mode 100644 launchers/macosx/Deployer.mm diff --git a/launchers/macosx/AppDelegate.h b/launchers/macosx/AppDelegate.h index 33c2a0ade0..c1ea98d460 100644 --- a/launchers/macosx/AppDelegate.h +++ b/launchers/macosx/AppDelegate.h @@ -18,12 +18,7 @@ #include "RouterTask.h" - -#define DEF_I2P_VERSION "0.9.36" -#define APPDOMAIN "net.i2p.launcher" -#define NSAPPDOMAIN @APPDOMAIN -#define CFAPPDOMAIN CFSTR(APPDOMAIN) -#define APP_IDSTR @"I2P Launcher" +#include "version.h" @class SwiftMainDelegate; @@ -61,6 +56,17 @@ inline std::string getDefaultBaseDir() return i2pBaseDir; } +inline std::string getDefaultLogDir() +{ + // Figure out log directory + auto homeDir = RealHomeDirectory(); + const char* pathFromHome = "%s/Library/Logs/I2P"; + char buffer[strlen(homeDir)+strlen(pathFromHome)]; + sprintf(buffer, pathFromHome, homeDir); + std::string i2pBaseDir(buffer); + return i2pBaseDir; +} + inline void sendUserNotification(NSString* title, NSString* informativeText, bool makeSound = false) { NSUserNotification *userNotification = [[NSUserNotification alloc] init]; diff --git a/launchers/macosx/Deployer.h b/launchers/macosx/Deployer.h index 13ffc5a743..96f6a20a8f 100644 --- a/launchers/macosx/Deployer.h +++ b/launchers/macosx/Deployer.h @@ -7,9 +7,15 @@ // #import <Foundation/Foundation.h> +#import <Foundation/NSError.h> +#import "AppDelegate.h" +@class ExtractMetaInfo; -@interface NSObject () +@interface I2PDeployer : NSObject +@property (assign) ExtractMetaInfo *metaInfo; +- (I2PDeployer *) initWithMetaInfo:(ExtractMetaInfo*)mi; +- (void) extractI2PBaseDir:(void(^)(BOOL success, NSError *error))completion; @end diff --git a/launchers/macosx/Deployer.m b/launchers/macosx/Deployer.m deleted file mode 100644 index 835237201f..0000000000 --- a/launchers/macosx/Deployer.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// Deployer.m -// I2PLauncher -// -// Created by Mikal Villa on 19/09/2018. -// Copyright © 2018 The I2P Project. All rights reserved. -// - -#import <Foundation/Foundation.h> -#import "Deployer.h" - - - diff --git a/launchers/macosx/Deployer.mm b/launchers/macosx/Deployer.mm new file mode 100644 index 0000000000..ff9ed9e3eb --- /dev/null +++ b/launchers/macosx/Deployer.mm @@ -0,0 +1,120 @@ +// +// Deployer.m +// I2PLauncher +// +// Created by Mikal Villa on 19/09/2018. +// Copyright © 2018 The I2P Project. All rights reserved. +// +#include <functional> +#include <memory> +#include <iostream> +#include <algorithm> +#include <string> +#include <list> +#include <sys/stat.h> +#include <stdlib.h> +#include <future> +#include <vector> + +#import <Foundation/Foundation.h> +#import <Foundation/NSFileManager.h> +#include <CoreFoundation/CFPreferences.h> + +#import <objc/Object.h> +#import <Cocoa/Cocoa.h> +#import <AppKit/AppKit.h> +#import <AppKit/NSApplication.h> + +#import "I2PLauncher-Swift.h" + +#include "AppDelegate.h" +#include "include/fn.h" +#import "SBridge.h" +#include "logger_c.h" + +#include <string> + +#include "include/subprocess.hpp" +#include "include/strutil.hpp" + +#include "Logger.h" +#include "LoggerWorker.hpp" + +#import "Deployer.h" + +#include <string.h> + +using namespace subprocess; + +@implementation I2PDeployer + +- (I2PDeployer *) initWithMetaInfo:(ExtractMetaInfo*)mi +{ + self.metaInfo = mi; + return self; +} + +- (void) extractI2PBaseDir:(void(^)(BOOL success, NSError *error))completion +{ +#ifdef __cplusplus + NSBundle *launcherBundle = [NSBundle mainBundle]; + auto homeDir = RealHomeDirectory(); + NSLog(@"Home directory is %s", homeDir); + + std::string basePath(homeDir); + basePath.append("/Library/I2P"); + + self.metaInfo.zipFile = [launcherBundle pathForResource:@"base" ofType:@"zip"]; + + NSParameterAssert(basePath.c_str()); + NSError *error = NULL; + BOOL success = YES; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + + try { + // Create directory + mkdir(basePath.c_str(), S_IRUSR | S_IWUSR | S_IXUSR); + + auto cli = defaultFlagsForExtractorJob; + setenv("I2PBASE", basePath.c_str(), true); + //setenv("DYLD_LIBRARY_PATH",".:/usr/lib:/lib:/usr/local/lib", true); + + chdir(basePath.c_str()); + + // Everything behind --exec java - would be passed as arguments to the java executable. + std::string execStr = "/usr/bin/unzip "; //std::string([rs.getJavaHome UTF8String]); + execStr += [self.metaInfo.zipFile UTF8String]; + //for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; }); + + NSLog(@"Trying cmd: %@", [NSString stringWithUTF8String:execStr.c_str()]); + sendUserNotification(APP_IDSTR, @"Please hold on while we extract I2P. You'll get a new message once done!"); + int extractStatus = Popen(execStr.c_str(), environment{{ + {"I2PBASE", basePath.c_str()} + }}).wait(); + NSLog(@"Extraction exit code %@",[NSString stringWithUTF8String:(std::to_string(extractStatus)).c_str()]); + if (extractStatus == 0) { + NSLog(@"Extraction process done"); + } else { + NSLog(@"Something went wrong"); + } + + // All done. Assume success and error are already set. + dispatch_async(dispatch_get_main_queue(), ^{ + if (completion) { + completion(YES, error); + } + }); + + + } catch (OSError &err) { + auto errMsg = [NSString stringWithUTF8String:err.what()]; + NSLog(@"Exception: %@", errMsg); + sendUserNotification(APP_IDSTR, [NSString stringWithFormat:@"Error: %@", errMsg]); + } + }); +#endif +} + +@end + diff --git a/launchers/macosx/main.mm b/launchers/macosx/main.mm index f7eba9c349..06aa715c3f 100644 --- a/launchers/macosx/main.mm +++ b/launchers/macosx/main.mm @@ -25,6 +25,8 @@ #include "include/fn.h" #include "include/portcheck.h" #import "SBridge.h" +#import "Deployer.h" +#include "logger_c.h" #ifdef __cplusplus #include <string> @@ -61,83 +63,10 @@ using namespace subprocess; return YES; } -#ifdef __cplusplus - - (void)extractI2PBaseDir:(void(^)(BOOL success, NSError *error))completion { - - NSBundle *launcherBundle = [NSBundle mainBundle]; - auto homeDir = RealHomeDirectory(); - NSLog(@"Home directory is %s", homeDir); - - std::string basePath(homeDir); - basePath.append("/Library/I2P"); - - auto jarResPath = [launcherBundle pathForResource:@"launcher" ofType:@"jar"]; - NSLog(@"Trying to load launcher.jar from url = %@", jarResPath); - self.metaInfo.jarFile = jarResPath; - self.metaInfo.zipFile = [launcherBundle pathForResource:@"base" ofType:@"zip"]; - - NSParameterAssert(basePath.c_str()); - NSError *error = NULL; - BOOL success = NO; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - - - try { - std::string basearg("-Di2p.dir.base="); - basearg += basePath; - - std::string zippath("-Di2p.base.zip="); - zippath += [self.metaInfo.zipFile UTF8String]; - - std::string jarfile("-cp "); - jarfile += [self.metaInfo.jarFile UTF8String]; - - // Create directory - mkdir(basePath.c_str(), S_IRUSR | S_IWUSR | S_IXUSR); - - auto cli = defaultFlagsForExtractorJob; - setenv("I2PBASE", basePath.c_str(), true); - setenv("ZIPPATH", zippath.c_str(), true); - //setenv("DYLD_LIBRARY_PATH",".:/usr/lib:/lib:/usr/local/lib", true); - - cli.push_back(basearg); - cli.push_back(zippath); - cli.push_back(jarfile); - cli.push_back("net.i2p.launchers.BaseExtractor"); - auto rs = [[RouterProcessStatus alloc] init]; - - std::string execStr = std::string([rs.getJavaHome UTF8String]); - for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; }); - - NSLog(@"Trying cmd: %@", [NSString stringWithUTF8String:execStr.c_str()]); - sendUserNotification(APP_IDSTR, @"Please hold on while we extract I2P. You'll get a new message once done!"); - int extractStatus = Popen(execStr.c_str(), environment{{ - {"ZIPPATH", zippath.c_str()}, - {"I2PBASE", basePath.c_str()} - }}).wait(); - NSLog(@"Extraction exit code %@",[NSString stringWithUTF8String:(std::to_string(extractStatus)).c_str()]); - if (extractStatus == 0) { - NSLog(@"Extraction process done"); - } else { - NSLog(@"Something went wrong"); - } - - // All done. Assume success and error are already set. - dispatch_async(dispatch_get_main_queue(), ^{ - if (completion) { - completion(success, error); - } - }); - - - } catch (OSError &err) { - auto errMsg = [NSString stringWithUTF8String:err.what()]; - NSLog(@"Exception: %@", errMsg); - sendUserNotification(APP_IDSTR, [NSString stringWithFormat:@"Error: %@", errMsg]); - } - }); + auto deployer = [[I2PDeployer alloc] initWithMetaInfo:self.metaInfo]; + [deployer extractI2PBaseDir:completion]; } - (void)setApplicationDefaultPreferences { @@ -145,6 +74,9 @@ using namespace subprocess; @"enableLogging": @YES, @"enableVerboseLogging": @YES, @"autoStartRouter": @YES, + @"startRouterAtLogin": @NO, + @"startRouterAtStartup": @NO, + @"letRouterLiveEvenLauncherDied": @NO, @"i2pBaseDirectory": (NSString *)CFStringCreateWithCString(NULL, const_cast<const char *>(getDefaultBaseDir().c_str()), kCFStringEncodingUTF8) }]; @@ -157,8 +89,6 @@ using namespace subprocess; if (self.enableVerboseLogging) NSLog(@"Default preferences stored!"); } -#endif - - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Init application here @@ -183,9 +113,12 @@ using namespace subprocess; RouterProcessStatus* routerStatus = [[RouterProcessStatus alloc] init]; std::string i2pBaseDir(getDefaultBaseDir()); - NSLog(@"i2pBaseDir = %s", i2pBaseDir.c_str()); + MLOG(INFO) << "i2pBaseDir = " << i2pBaseDir.c_str(); bool shouldAutoStartRouter = false; + // Initialize the Swift environment (the UI components) + [self.swiftRuntime applicationDidFinishLaunching]; + // TODO: Make the port a setting which defaults to 7657 if (port_check(7657) != 0) { @@ -217,16 +150,16 @@ using namespace subprocess; // Might be hard to read if you're not used to Objective-C // But this is a "function call" that contains a "callback function" - [routerStatus listenForEventWithEventName:@"router_can_start" callbackActionFn:^(NSString* information) { + /*[routerStatus listenForEventWithEventName:@"router_can_start" callbackActionFn:^(NSString* information) { NSLog(@"Got signal, router can be started"); - [[SBridge sharedInstance] startupI2PRouter:self.metaInfo.i2pBase javaBinPath:self.metaInfo.javaBinary]; - }]; + [[SBridge sharedInstance] startupI2PRouter:self.metaInfo.i2pBase]; + }];*/ // This will trigger the router start after an upgrade. [routerStatus listenForEventWithEventName:@"router_must_upgrade" callbackActionFn:^(NSString* information) { NSLog(@"Got signal, router must be deployed from base.zip"); [self extractI2PBaseDir:^(BOOL success, NSError *error) { - if (success && error != nil) { + if (success) { sendUserNotification(@"I2P is done extracting", @"I2P is now installed and ready to run!"); NSLog(@"Done extracting I2P"); [routerStatus triggerEventWithEn:@"extract_completed" details:@"upgrade complete"]; @@ -237,11 +170,12 @@ using namespace subprocess; }]; }]; - // Initialize the Swift environment (the UI components) - [self.swiftRuntime applicationDidFinishLaunching]; - NSString *nsI2PBaseStr = [NSString stringWithUTF8String:i2pBaseDir.c_str()]; + [routerStatus listenForEventWithEventName:@"extract_completed" callbackActionFn:^(NSString* information) { + NSLog(@"Time to detect I2P version in install directory"); + [self.swiftRuntime findInstalledI2PVersion]; + }]; //struct stat sb; //if ( !(stat(i2pBaseDir.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) ) @@ -265,10 +199,7 @@ using namespace subprocess; [self.swiftRuntime findInstalledI2PVersion]; } else { // The directory exists, but not i2p.jar - most likely we're in mid-extraction state. - [routerStatus listenForEventWithEventName:@"extract_completed" callbackActionFn:^(NSString* information) { - NSLog(@"Time to detect I2P version in install directory"); - [self.swiftRuntime findInstalledI2PVersion]; - }]; + [routerStatus triggerEventWithEn:@"router_must_upgrade" details:@"deploy needed"]; } } @@ -282,6 +213,7 @@ using namespace subprocess; **/ - (void)applicationWillTerminate:(NSNotification *)aNotification { // Tear down here + [self.swiftRuntime applicationWillTerminate]; NSString *string = @"applicationWillTerminate executed"; NSLog(@"%@", string); [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil]; -- GitLab