forked from I2P_Developers/i2p.i2p
Starting to get stable and usable. Basically everything is based on callbacks.
This commit is contained in:
@ -16,28 +16,48 @@
|
|||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
#define DEF_I2P_VERSION "0.9.35"
|
||||||
|
#define APPDOMAIN "net.i2p.launcher"
|
||||||
|
#define NSAPPDOMAIN @APPDOMAIN
|
||||||
|
#define CFAPPDOMAIN CFSTR(APPDOMAIN)
|
||||||
|
#define APP_IDSTR @"I2P Launcher"
|
||||||
|
|
||||||
|
|
||||||
using namespace neither;
|
using namespace neither;
|
||||||
|
|
||||||
|
using maybeAnRouterRunner = std::experimental::optional<RouterTask*>;
|
||||||
|
|
||||||
|
|
||||||
extern JvmListSharedPtr gRawJvmList;
|
extern JvmListSharedPtr gRawJvmList;
|
||||||
|
|
||||||
// DO NOT ACCESS THIS GLOBAL VARIABLE DIRECTLY.
|
// DO NOT ACCESS THIS GLOBAL VARIABLE DIRECTLY.
|
||||||
maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{};
|
static std::mutex globalRouterStatusMutex;
|
||||||
|
static maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{};
|
||||||
|
|
||||||
maybeAnRouterRunner getGlobalRouterObject()
|
maybeAnRouterRunner getGlobalRouterObject();
|
||||||
{
|
void setGlobalRouterObject(RouterTask* newRouter);
|
||||||
std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
|
|
||||||
return globalRouterStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setGlobalRouterObject(RouterTask* newRouter)
|
@class ExtractMetaInfo;
|
||||||
{
|
@interface ExtractMetaInfo : NSObject
|
||||||
std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
|
@property (strong) NSString* i2pBase;
|
||||||
globalRouterStatus.emplace(newRouter);
|
@property (strong) NSString* javaBinary;
|
||||||
}
|
@property (strong) NSString* zipFile;
|
||||||
|
@property (strong) NSString* jarFile;
|
||||||
|
@end
|
||||||
|
|
||||||
|
inline void sendUserNotification(NSString* title, NSString* informativeText, NSImage* contentImage = NULL, bool makeSound = false) {
|
||||||
|
NSUserNotification *userNotification = [[[NSUserNotification alloc] init] autorelease];
|
||||||
|
|
||||||
|
userNotification.title = title;
|
||||||
|
userNotification.informativeText = informativeText;
|
||||||
|
if (contentImage != NULL) userNotification.contentImage = contentImage;
|
||||||
|
if (makeSound) userNotification.soundName = NSUserNotificationDefaultSoundName;
|
||||||
|
|
||||||
std::vector<std::string> globVector(const std::string& pattern){
|
[[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification:userNotification];
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::vector<std::string> globVector(const std::string& pattern){
|
||||||
glob_t glob_result;
|
glob_t glob_result;
|
||||||
glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
|
glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
@ -63,6 +83,7 @@ std::vector<std::string> globVector(const std::string& pattern){
|
|||||||
- (void) btnPressedAction:(id)sender;
|
- (void) btnPressedAction:(id)sender;
|
||||||
- (void) menuWillOpen:(NSMenu *)menu;
|
- (void) menuWillOpen:(NSMenu *)menu;
|
||||||
|
|
||||||
|
- (void) openRouterConsoleBtnHandler: (NSMenuItem *) menuItem;
|
||||||
- (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem;
|
- (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem;
|
||||||
- (void) restartJavaRouterBtnHandler: (NSMenuItem *) menuItem;
|
- (void) restartJavaRouterBtnHandler: (NSMenuItem *) menuItem;
|
||||||
- (void) stopJavaRouterBtnHandler: (NSMenuItem *) menuItem;
|
- (void) stopJavaRouterBtnHandler: (NSMenuItem *) menuItem;
|
||||||
@ -85,6 +106,9 @@ std::vector<std::string> globVector(const std::string& pattern){
|
|||||||
@property (strong) NSUserDefaults *userPreferences;
|
@property (strong) NSUserDefaults *userPreferences;
|
||||||
@property BOOL enableLogging;
|
@property BOOL enableLogging;
|
||||||
@property BOOL enableVerboseLogging;
|
@property BOOL enableVerboseLogging;
|
||||||
|
@property (copy) NSImage *contentImage NS_AVAILABLE(10_9, NA);
|
||||||
|
- (void)extractI2PBaseDir:(ExtractMetaInfo *)metaInfo completion:(void(^)(BOOL success, NSError *error))completion;
|
||||||
|
- (void)startupI2PRouter:(ExtractMetaInfo *)metaInfo;
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
|
||||||
- (void)applicationWillTerminate:(NSNotification *)aNotification;
|
- (void)applicationWillTerminate:(NSNotification *)aNotification;
|
||||||
- (void)setApplicationDefaultPreferences;
|
- (void)setApplicationDefaultPreferences;
|
||||||
|
@ -26,12 +26,6 @@
|
|||||||
using namespace subprocess;
|
using namespace subprocess;
|
||||||
using namespace neither;
|
using namespace neither;
|
||||||
|
|
||||||
using maybeAnRouterRunner = std::experimental::optional<RouterTask*>;
|
|
||||||
|
|
||||||
extern std::mutex globalRouterStatusMutex;
|
|
||||||
extern maybeAnRouterRunner globalRouterStatus;
|
|
||||||
|
|
||||||
|
|
||||||
#define DEF_MIN_JVM_VER "1.7+"
|
#define DEF_MIN_JVM_VER "1.7+"
|
||||||
|
|
||||||
class JvmVersion
|
class JvmVersion
|
||||||
|
@ -30,8 +30,12 @@
|
|||||||
@property (strong) NSMutableData *totalLogData;
|
@property (strong) NSMutableData *totalLogData;
|
||||||
@property (strong) NSPipe *processPipe;
|
@property (strong) NSPipe *processPipe;
|
||||||
@property (strong) NSFileHandle *input;
|
@property (strong) NSFileHandle *input;
|
||||||
|
@property (atomic) BOOL userRequestedRestart;
|
||||||
- (instancetype) initWithOptions : (RTaskOptions*) options;
|
- (instancetype) initWithOptions : (RTaskOptions*) options;
|
||||||
- (int) execute;
|
- (int) execute;
|
||||||
|
- (void) requestShutdown;
|
||||||
|
- (void) requestRestart;
|
||||||
|
- (BOOL) isRunning;
|
||||||
- (int) getPID;
|
- (int) getPID;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include "optional.hpp"
|
#include "optional.hpp"
|
||||||
#include "subprocess.hpp"
|
#include "subprocess.hpp"
|
||||||
|
#include "PidWatcher.h"
|
||||||
|
|
||||||
#import <AppKit/AppKit.h>
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
@ -14,8 +15,10 @@
|
|||||||
|
|
||||||
@implementation RouterTask
|
@implementation RouterTask
|
||||||
|
|
||||||
|
|
||||||
- (instancetype) initWithOptions : (RTaskOptions*) options
|
- (instancetype) initWithOptions : (RTaskOptions*) options
|
||||||
{
|
{
|
||||||
|
self.userRequestedRestart = FALSE;
|
||||||
self.input = [NSFileHandle fileHandleWithStandardInput];
|
self.input = [NSFileHandle fileHandleWithStandardInput];
|
||||||
self.routerTask = [NSTask new];
|
self.routerTask = [NSTask new];
|
||||||
self.processPipe = [NSPipe new];
|
self.processPipe = [NSPipe new];
|
||||||
@ -27,6 +30,9 @@
|
|||||||
[self.routerTask setEnvironment: envDict];
|
[self.routerTask setEnvironment: envDict];
|
||||||
[self.routerTask setStandardOutput:self.processPipe];
|
[self.routerTask setStandardOutput:self.processPipe];
|
||||||
[self.routerTask setStandardError:self.processPipe];
|
[self.routerTask setStandardError:self.processPipe];
|
||||||
|
[self.routerTask setTerminationHandler:^(NSTask* task) {
|
||||||
|
NSLog(@"termHandler triggered!");
|
||||||
|
}];
|
||||||
/*
|
/*
|
||||||
self.readLogHandle = [self.processPipe fileHandleForReading];
|
self.readLogHandle = [self.processPipe fileHandleForReading];
|
||||||
NSData *inData = nil;
|
NSData *inData = nil;
|
||||||
@ -40,10 +46,26 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) requestShutdown
|
||||||
|
{
|
||||||
|
[self.routerTask interrupt];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) requestRestart
|
||||||
|
{
|
||||||
|
self.userRequestedRestart = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isRunning
|
||||||
|
{
|
||||||
|
return self.routerTask.running;
|
||||||
|
}
|
||||||
|
|
||||||
- (int) execute
|
- (int) execute
|
||||||
{
|
{
|
||||||
//@try {
|
//@try {
|
||||||
[self.routerTask launch];
|
[self.routerTask launch];
|
||||||
|
watchPid([self.routerTask processIdentifier]);
|
||||||
[self.input waitForDataInBackgroundAndNotify];
|
[self.input waitForDataInBackgroundAndNotify];
|
||||||
[[self.processPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
|
[[self.processPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
|
||||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
|
[[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
|
||||||
@ -84,8 +106,6 @@
|
|||||||
|
|
||||||
using namespace subprocess;
|
using namespace subprocess;
|
||||||
|
|
||||||
std::mutex globalRouterStatusMutex;
|
|
||||||
|
|
||||||
const std::vector<NSString*> JavaRunner::defaultStartupFlags {
|
const std::vector<NSString*> JavaRunner::defaultStartupFlags {
|
||||||
@"-Xmx512M",
|
@"-Xmx512M",
|
||||||
@"-Xms128m",
|
@"-Xms128m",
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
cxx = clang++
|
cxx = clang++
|
||||||
cflags = -std=c++14 -g -Wall -I./include -I./include/neither -I/usr/local/include -I/usr/include -Wno-unused-variable -mmacosx-version-min=10.10
|
cflags = -std=c++14 -g -Wall -I./include -I./include/neither -I/usr/local/include -I/usr/include $
|
||||||
|
-Wno-unused-function -Wno-incomplete-implementation -Wno-unused-variable -mmacosx-version-min=10.10
|
||||||
ldflags = -framework CoreFoundation -framework Foundation -framework Cocoa -g -rdynamic
|
ldflags = -framework CoreFoundation -framework Foundation -framework Cocoa -g -rdynamic
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#include <CoreFoundation/CFArray.h>
|
#include <CoreFoundation/CFArray.h>
|
||||||
#include <CoreFoundation/CFString.h>
|
#include <CoreFoundation/CFString.h>
|
||||||
|
|
||||||
std::string strprintf(const char *fromat, ...)
|
inline std::string strprintf(const char *fromat, ...)
|
||||||
{
|
{
|
||||||
std::string s;
|
std::string s;
|
||||||
s.resize(128); // best guess
|
s.resize(128); // best guess
|
||||||
@ -37,7 +37,7 @@ std::string strprintf(const char *fromat, ...)
|
|||||||
return s; // move semantics FTW
|
return s; // move semantics FTW
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string extractString(CFStringRef value)
|
inline std::string extractString(CFStringRef value)
|
||||||
{
|
{
|
||||||
const char * data = CFStringGetCStringPtr(value, kCFStringEncodingUTF8);
|
const char * data = CFStringGetCStringPtr(value, kCFStringEncodingUTF8);
|
||||||
if (data != NULL)
|
if (data != NULL)
|
||||||
@ -56,7 +56,7 @@ std::string extractString(CFStringRef value)
|
|||||||
using std::experimental::optional;
|
using std::experimental::optional;
|
||||||
|
|
||||||
// Use CFStringRef instead of NSString*, otherwise disable ARC
|
// Use CFStringRef instead of NSString*, otherwise disable ARC
|
||||||
optional<CFStringRef> optionalString(bool val) {
|
inline optional<CFStringRef> optionalString(bool val) {
|
||||||
optional<CFStringRef> myOptString;
|
optional<CFStringRef> myOptString;
|
||||||
if(val) {
|
if(val) {
|
||||||
// Cast to corresponding CoreFoundation object
|
// Cast to corresponding CoreFoundation object
|
||||||
|
@ -31,11 +31,6 @@
|
|||||||
#include "fn.h"
|
#include "fn.h"
|
||||||
#include "optional.hpp"
|
#include "optional.hpp"
|
||||||
|
|
||||||
#define DEF_I2P_VERSION "0.9.35"
|
|
||||||
#define APPDOMAIN "net.i2p.launcher"
|
|
||||||
#define NSAPPDOMAIN @APPDOMAIN
|
|
||||||
#define CFAPPDOMAIN CFSTR(APPDOMAIN)
|
|
||||||
|
|
||||||
#define debug(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]);
|
#define debug(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]);
|
||||||
|
|
||||||
JvmListSharedPtr gRawJvmList = nullptr;
|
JvmListSharedPtr gRawJvmList = nullptr;
|
||||||
@ -48,6 +43,18 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
maybeAnRouterRunner getGlobalRouterObject()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
|
||||||
|
return globalRouterStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setGlobalRouterObject(RouterTask* newRouter)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
|
||||||
|
globalRouterStatus.emplace(newRouter);
|
||||||
|
}
|
||||||
|
|
||||||
std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments, NSString* i2pBaseDir) {
|
std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments, NSString* i2pBaseDir) {
|
||||||
/*
|
/*
|
||||||
NSLog(@"Arguments: %@", [NSString stringWithUTF8String:arguments.c_str()]);
|
NSLog(@"Arguments: %@", [NSString stringWithUTF8String:arguments.c_str()]);
|
||||||
@ -72,7 +79,7 @@ std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments,
|
|||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
CFShow(arguments);
|
//CFShow(arguments);
|
||||||
|
|
||||||
@try {
|
@try {
|
||||||
RTaskOptions* options = [RTaskOptions alloc];
|
RTaskOptions* options = [RTaskOptions alloc];
|
||||||
@ -80,22 +87,31 @@ std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments,
|
|||||||
options.arguments = arguments;
|
options.arguments = arguments;
|
||||||
options.i2pBaseDir = i2pBaseDir;
|
options.i2pBaseDir = i2pBaseDir;
|
||||||
auto instance = [[[RouterTask alloc] initWithOptions: options] autorelease];
|
auto instance = [[[RouterTask alloc] initWithOptions: options] autorelease];
|
||||||
//auto pid = [instance execute];
|
setGlobalRouterObject(instance);
|
||||||
//NSThread *thr = [[NSThread alloc] initWithTarget:instance selector:@selector(execute) object:nil];
|
//NSThread *thr = [[NSThread alloc] initWithTarget:instance selector:@selector(execute) object:nil];
|
||||||
[instance execute];
|
[instance execute];
|
||||||
return std::async(std::launch::async, [&instance]{
|
sendUserNotification(APP_IDSTR, @"The I2P router is starting up.");
|
||||||
return 1;//[instance getPID];
|
auto pid = [instance getPID];
|
||||||
|
return std::async(std::launch::async, [&pid]{
|
||||||
|
return pid;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@catch (NSException *e)
|
@catch (NSException *e)
|
||||||
{
|
{
|
||||||
NSLog(@"Expection occurred %@", [e reason]);
|
auto errStr = [NSString stringWithFormat:@"Expection occurred %@",[e reason]];
|
||||||
|
NSLog(@"%@", errStr);
|
||||||
|
sendUserNotification(APP_IDSTR, errStr);
|
||||||
return std::async(std::launch::async, [&]{
|
return std::async(std::launch::async, [&]{
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void openUrl(NSString* url)
|
||||||
|
{
|
||||||
|
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString: url]];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@implementation MenuBarCtrl
|
@implementation MenuBarCtrl
|
||||||
|
|
||||||
@ -123,6 +139,12 @@ std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments,
|
|||||||
NSEvent *event = [NSApp currentEvent];
|
NSEvent *event = [NSApp currentEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) openRouterConsoleBtnHandler: (NSMenuItem *) menuItem
|
||||||
|
{
|
||||||
|
NSLog(@"Clicked openRouterConsoleBtnHandler");
|
||||||
|
openUrl(@"http://127.0.0.1:7657");
|
||||||
|
}
|
||||||
|
|
||||||
- (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem
|
- (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem
|
||||||
{
|
{
|
||||||
NSLog(@"Clicked startJavaRouterBtnHandler");
|
NSLog(@"Clicked startJavaRouterBtnHandler");
|
||||||
@ -131,6 +153,12 @@ std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments,
|
|||||||
- (void) restartJavaRouterBtnHandler: (NSMenuItem *) menuItem
|
- (void) restartJavaRouterBtnHandler: (NSMenuItem *) menuItem
|
||||||
{
|
{
|
||||||
NSLog(@"Clicked restartJavaRouterBtnHandler");
|
NSLog(@"Clicked restartJavaRouterBtnHandler");
|
||||||
|
if (getGlobalRouterObject().has_value())
|
||||||
|
{
|
||||||
|
sendUserNotification(APP_IDSTR, @"Requesting the I2P router to restart.");
|
||||||
|
[getGlobalRouterObject().value() requestRestart];
|
||||||
|
NSLog(@"Requested restart");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) stopJavaRouterBtnHandler: (NSMenuItem *) menuItem
|
- (void) stopJavaRouterBtnHandler: (NSMenuItem *) menuItem
|
||||||
@ -138,7 +166,8 @@ std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments,
|
|||||||
NSLog(@"Clicked stopJavaRouterBtnHandler");
|
NSLog(@"Clicked stopJavaRouterBtnHandler");
|
||||||
if (getGlobalRouterObject().has_value())
|
if (getGlobalRouterObject().has_value())
|
||||||
{
|
{
|
||||||
//getGlobalRouterObject().value()->requestRouterShutdown();
|
sendUserNotification(APP_IDSTR, @"Requesting the I2P router to shutdown.");
|
||||||
|
[getGlobalRouterObject().value() requestShutdown];
|
||||||
NSLog(@"Requested shutdown");
|
NSLog(@"Requested shutdown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,6 +214,14 @@ std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments,
|
|||||||
{
|
{
|
||||||
NSMenu *menu = [[NSMenu alloc] init];
|
NSMenu *menu = [[NSMenu alloc] init];
|
||||||
[menu setAutoenablesItems:NO];
|
[menu setAutoenablesItems:NO];
|
||||||
|
|
||||||
|
NSMenuItem *openConsoleI2Pbtn =
|
||||||
|
[[NSMenuItem alloc] initWithTitle:@"Open Console"
|
||||||
|
action:@selector(openRouterConsoleBtnHandler:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[openConsoleI2Pbtn setTarget:self];
|
||||||
|
[openConsoleI2Pbtn setEnabled:YES];
|
||||||
|
|
||||||
NSMenuItem *startI2Pbtn =
|
NSMenuItem *startI2Pbtn =
|
||||||
[[NSMenuItem alloc] initWithTitle:@"Start I2P"
|
[[NSMenuItem alloc] initWithTitle:@"Start I2P"
|
||||||
action:@selector(startJavaRouterBtnHandler:)
|
action:@selector(startJavaRouterBtnHandler:)
|
||||||
@ -219,6 +256,7 @@ std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments,
|
|||||||
[quitWrapperBtn setEnabled:YES];
|
[quitWrapperBtn setEnabled:YES];
|
||||||
|
|
||||||
|
|
||||||
|
[menu addItem:openConsoleI2Pbtn];
|
||||||
[menu addItem:startI2Pbtn];
|
[menu addItem:startI2Pbtn];
|
||||||
[menu addItem:stopI2Pbtn];
|
[menu addItem:stopI2Pbtn];
|
||||||
[menu addItem:restartI2Pbtn];
|
[menu addItem:restartI2Pbtn];
|
||||||
@ -228,9 +266,127 @@ std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments,
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation ExtractMetaInfo
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation AppDelegate
|
@implementation AppDelegate
|
||||||
|
|
||||||
|
- (void)extractI2PBaseDir:(ExtractMetaInfo *)metaInfo completion:(void(^)(BOOL success, NSError *error))completion
|
||||||
|
{
|
||||||
|
std::string basePath([metaInfo.i2pBase UTF8String]);
|
||||||
|
NSParameterAssert(metaInfo.i2pBase);
|
||||||
|
NSError *error = NULL;
|
||||||
|
BOOL success;
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
|
|
||||||
|
// Get paths
|
||||||
|
NSBundle *launcherBundle = [NSBundle mainBundle];
|
||||||
|
|
||||||
|
std::string basearg("-Di2p.dir.base=");
|
||||||
|
basearg += basePath;
|
||||||
|
|
||||||
|
std::string zippath("-Di2p.base.zip=");
|
||||||
|
zippath += [metaInfo.zipFile UTF8String];
|
||||||
|
|
||||||
|
std::string jarfile("-cp ");
|
||||||
|
jarfile += [metaInfo.jarFile UTF8String];
|
||||||
|
|
||||||
|
// Create directory
|
||||||
|
mkdir(basePath.c_str(), S_IRUSR | S_IWUSR | S_IXUSR);
|
||||||
|
|
||||||
|
auto cli = JavaRunner::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 charCli = map(cli, [](std::string str){ return str.c_str(); });
|
||||||
|
std::string execStr = [metaInfo.javaBinary UTF8String];
|
||||||
|
for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; });
|
||||||
|
|
||||||
|
NSLog(@"Trying cmd: %@", [NSString stringWithUTF8String:execStr.c_str()]);
|
||||||
|
try {
|
||||||
|
sendUserNotification(APP_IDSTR, @"Please hold on while we extract I2P. You'll get a new message once done!", self.contentImage);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
//success = YES;
|
||||||
|
}
|
||||||
|
} catch (subprocess::OSError &err) {
|
||||||
|
auto errMsg = [NSString stringWithUTF8String:err.what()];
|
||||||
|
//success = NO;
|
||||||
|
NSLog(@"Exception: %@", errMsg);
|
||||||
|
sendUserNotification(APP_IDSTR, [NSString stringWithFormat:@"Error: %@", errMsg], self.contentImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)startupI2PRouter:(ExtractMetaInfo *)metaInfo
|
||||||
|
{
|
||||||
|
std::string basePath([metaInfo.i2pBase UTF8String]);
|
||||||
|
auto buildClassPath = [](std::string basePath) -> std::vector<std::string> {
|
||||||
|
return globVector(basePath+std::string("/lib/*.jar"));
|
||||||
|
};
|
||||||
|
// Expect base to be extracted by now.
|
||||||
|
|
||||||
|
// Get paths
|
||||||
|
NSBundle *launcherBundle = [NSBundle mainBundle];
|
||||||
|
auto jarList = buildClassPath(basePath);
|
||||||
|
std::string classpathStrHead = "-classpath";
|
||||||
|
std::string classpathStr = "";
|
||||||
|
classpathStr += [[launcherBundle pathForResource:@"launcher" ofType:@"jar"] UTF8String];
|
||||||
|
std::string prefix(basePath);
|
||||||
|
prefix += "/lib/";
|
||||||
|
for_each(jarList, [&classpathStr](std::string str){ classpathStr += std::string(":") + str; });
|
||||||
|
//if (self.enableVerboseLogging) NSLog(@"Classpath: %@\n",[NSString stringWithUTF8String:classpathStr.c_str()]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto argList = JavaRunner::defaultStartupFlags;
|
||||||
|
|
||||||
|
std::string baseDirArg("-Di2p.dir.base=");
|
||||||
|
baseDirArg += basePath;
|
||||||
|
std::string javaLibArg("-Djava.library.path=");
|
||||||
|
javaLibArg += basePath;
|
||||||
|
// TODO: pass this to JVM
|
||||||
|
auto java_opts = getenv("JAVA_OPTS");
|
||||||
|
|
||||||
|
argList.push_back([NSString stringWithUTF8String:baseDirArg.c_str()]);
|
||||||
|
argList.push_back([NSString stringWithUTF8String:javaLibArg.c_str()]);
|
||||||
|
argList.push_back([NSString stringWithUTF8String:classpathStrHead.c_str()]);
|
||||||
|
argList.push_back([NSString stringWithUTF8String:classpathStr.c_str()]);
|
||||||
|
argList.push_back(@"net.i2p.router.Router");
|
||||||
|
auto javaBin = std::string([metaInfo.javaBinary UTF8String]);
|
||||||
|
|
||||||
|
|
||||||
|
sendUserNotification(APP_IDSTR, @"I2P Router is starting up!", self.contentImage);
|
||||||
|
auto nsJavaBin = metaInfo.javaBinary;
|
||||||
|
auto nsBasePath = metaInfo.i2pBase;
|
||||||
|
NSArray* arrArguments = [NSArray arrayWithObjects:&argList[0] count:argList.size()];
|
||||||
|
startupRouter(nsJavaBin, arrArguments, nsBasePath);
|
||||||
|
//if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]);
|
||||||
|
} catch (std::exception &err) {
|
||||||
|
auto errMsg = [NSString stringWithUTF8String:err.what()];
|
||||||
|
NSLog(@"Exception: %@", errMsg);
|
||||||
|
sendUserNotification(APP_IDSTR, [NSString stringWithFormat:@"Error: %@", errMsg], self.contentImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
|
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
|
||||||
shouldPresentNotification:(NSUserNotification *)notification {
|
shouldPresentNotification:(NSUserNotification *)notification {
|
||||||
return YES;
|
return YES;
|
||||||
@ -302,6 +458,12 @@ std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments,
|
|||||||
self.enableLogging = [self.userPreferences boolForKey:@"enableLogging"];
|
self.enableLogging = [self.userPreferences boolForKey:@"enableLogging"];
|
||||||
self.enableVerboseLogging = [self.userPreferences boolForKey:@"enableVerboseLogging"];
|
self.enableVerboseLogging = [self.userPreferences boolForKey:@"enableVerboseLogging"];
|
||||||
|
|
||||||
|
|
||||||
|
// Get paths
|
||||||
|
NSBundle *launcherBundle = [NSBundle mainBundle];
|
||||||
|
auto iconImage = [launcherBundle pathForResource:@"ItoopieTransparent" ofType:@"png"];
|
||||||
|
self.contentImage = [NSImage imageNamed:iconImage];
|
||||||
|
|
||||||
gRawJvmList = std::make_shared<std::list<JvmVersionPtr> >(std::list<JvmVersionPtr>());
|
gRawJvmList = std::make_shared<std::list<JvmVersionPtr> >(std::list<JvmVersionPtr>());
|
||||||
// In case we are unbundled, make us a proper UI application
|
// In case we are unbundled, make us a proper UI application
|
||||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
|
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
|
||||||
@ -360,109 +522,36 @@ std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments,
|
|||||||
return globVector(basePath+std::string("/lib/*.jar"));
|
return globVector(basePath+std::string("/lib/*.jar"));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto sendUserNotification = [&](NSString* title, NSString* informativeText) -> void {
|
|
||||||
NSUserNotification *userNotification = [[[NSUserNotification alloc] init] autorelease];
|
|
||||||
|
|
||||||
userNotification.title = title;
|
auto metaInfo = [ExtractMetaInfo alloc];
|
||||||
userNotification.informativeText = informativeText;
|
metaInfo.i2pBase = [NSString stringWithUTF8String:buffer];
|
||||||
userNotification.soundName = NSUserNotificationDefaultSoundName;
|
metaInfo.javaBinary = [NSString stringWithUTF8String:getJavaBin().c_str()];
|
||||||
|
metaInfo.jarFile = [launcherBundle pathForResource:@"launcher" ofType:@"jar"];
|
||||||
[[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification:userNotification];
|
metaInfo.zipFile = [launcherBundle pathForResource:@"base" ofType:@"zip"];
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Get paths
|
|
||||||
NSBundle *launcherBundle = [NSBundle mainBundle];
|
|
||||||
|
|
||||||
std::string basearg("-Di2p.dir.base=");
|
std::string basearg("-Di2p.dir.base=");
|
||||||
basearg += i2pBaseDir;
|
basearg += i2pBaseDir;
|
||||||
|
|
||||||
std::string zippath("-Di2p.base.zip=");
|
|
||||||
zippath += [[launcherBundle pathForResource:@"base" ofType:@"zip"] UTF8String];
|
|
||||||
|
|
||||||
std::string jarfile("-cp ");
|
std::string jarfile("-cp ");
|
||||||
jarfile += [[launcherBundle pathForResource:@"launcher" ofType:@"jar"] UTF8String];
|
jarfile += [metaInfo.zipFile UTF8String];
|
||||||
|
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
if ( !(stat(buffer, &sb) == 0 && S_ISDIR(sb.st_mode)) )
|
if ( !(stat(buffer, &sb) == 0 && S_ISDIR(sb.st_mode)) )
|
||||||
{
|
{
|
||||||
// I2P is not extracted.
|
// I2P is not extracted.
|
||||||
if (self.enableVerboseLogging) printf("I2P Directory don't exists!\n");
|
if (self.enableVerboseLogging) NSLog(@"I2P Directory don't exists!");
|
||||||
|
|
||||||
// Create directory
|
[self extractI2PBaseDir: metaInfo completion:^(BOOL success, NSError *error) {
|
||||||
mkdir(buffer, S_IRUSR | S_IWUSR | S_IXUSR);
|
//__typeof__(self) strongSelf = weakSelf;
|
||||||
|
//if (strongSelf == nil) return;
|
||||||
auto cli = JavaRunner::defaultFlagsForExtractorJob;
|
[self startupI2PRouter:metaInfo];
|
||||||
setenv("I2PBASE", buffer, 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 charCli = map(cli, [](std::string str){ return str.c_str(); });
|
|
||||||
std::string execStr = getJavaBin();
|
|
||||||
for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; });
|
|
||||||
|
|
||||||
printf("\n\nTrying cmd: %s\n\n", execStr.c_str());
|
|
||||||
try {
|
|
||||||
sendUserNotification((NSString*)CFSTR("I2P Extraction"), (NSString*)CFSTR("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", buffer}
|
|
||||||
}}).wait();
|
|
||||||
printf("Extraction exit code %d\n",extractStatus);
|
|
||||||
sendUserNotification((NSString*)CFSTR("I2P Extraction"), (NSString*)CFSTR("Extraction complete!"));
|
|
||||||
} catch (subprocess::OSError &err) {
|
|
||||||
printf("Something bad happened: %s\n", err.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (self.enableVerboseLogging) printf("I2P directory found!\n");
|
if (self.enableVerboseLogging) NSLog(@"I2P directory found!");
|
||||||
|
[self startupI2PRouter:metaInfo];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expect base to be extracted by now.
|
|
||||||
|
|
||||||
auto jarList = buildClassPath(std::string(buffer));
|
|
||||||
std::string classpathStrHead = "-classpath";
|
|
||||||
std::string classpathStr = "";
|
|
||||||
classpathStr += [[launcherBundle pathForResource:@"launcher" ofType:@"jar"] UTF8String];
|
|
||||||
std::string prefix(i2pBaseDir);
|
|
||||||
prefix += "/lib/";
|
|
||||||
for_each(jarList, [&classpathStr](std::string str){ classpathStr += std::string(":") + str; });
|
|
||||||
//if (self.enableVerboseLogging) NSLog(@"Classpath: %@\n",[NSString stringWithUTF8String:classpathStr.c_str()]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
auto argList = JavaRunner::defaultStartupFlags;
|
|
||||||
|
|
||||||
std::string baseDirArg("-Di2p.dir.base=");
|
|
||||||
baseDirArg += i2pBaseDir;
|
|
||||||
std::string javaLibArg("-Djava.library.path=");
|
|
||||||
javaLibArg += i2pBaseDir;
|
|
||||||
// TODO: pass this to JVM
|
|
||||||
auto java_opts = getenv("JAVA_OPTS");
|
|
||||||
|
|
||||||
argList.push_back([NSString stringWithUTF8String:baseDirArg.c_str()]);
|
|
||||||
argList.push_back([NSString stringWithUTF8String:javaLibArg.c_str()]);
|
|
||||||
argList.push_back([NSString stringWithUTF8String:classpathStrHead.c_str()]);
|
|
||||||
argList.push_back([NSString stringWithUTF8String:classpathStr.c_str()]);
|
|
||||||
argList.push_back(@"net.i2p.router.Router");
|
|
||||||
auto javaBin = getJavaBin();
|
|
||||||
|
|
||||||
|
|
||||||
sendUserNotification(@"I2P Launcher", @"I2P Router is starting up!");
|
|
||||||
auto nsJavaBin = [NSString stringWithUTF8String:javaBin.c_str()];
|
|
||||||
auto nsBasePath = [NSString stringWithUTF8String:i2pBaseDir.c_str()];
|
|
||||||
NSArray* arrArguments = [NSArray arrayWithObjects:&argList[0] count:argList.size()];
|
|
||||||
startupRouter(nsJavaBin, arrArguments, nsBasePath);
|
|
||||||
//if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]);
|
|
||||||
} catch (std::exception &err) {
|
|
||||||
std::cerr << "Exception: " << err.what() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user