forked from I2P_Developers/i2p.i2p
OSX Launcher: Refactor deployment code to own file, + code cleanups.
This commit is contained in:
@@ -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];
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
|
||||
120
launchers/macosx/Deployer.mm
Normal file
120
launchers/macosx/Deployer.mm
Normal file
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user