forked from I2P_Developers/i2p.i2p
Fixed a load of issues related to my "sync" approach, and Mac OSX's "async" API.
This commit is contained in:
@ -4,7 +4,10 @@
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <experimental/optional>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <future>
|
||||
#include <vector>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@ -23,8 +26,10 @@
|
||||
|
||||
#include "AppDelegate.h"
|
||||
#include "StatusItemButton.h"
|
||||
#include "JavaRunner.h"
|
||||
#include "RouterTask.h"
|
||||
#include "JavaHelper.h"
|
||||
#include "fn.h"
|
||||
#include "optional.hpp"
|
||||
|
||||
#define DEF_I2P_VERSION "0.9.35"
|
||||
#define APPDOMAIN "net.i2p.launcher"
|
||||
@ -43,6 +48,55 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
||||
@end
|
||||
|
||||
|
||||
std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments, NSString* i2pBaseDir) {
|
||||
/*
|
||||
NSLog(@"Arguments: %@", [NSString stringWithUTF8String:arguments.c_str()]);
|
||||
auto launchLambda = [](JavaRunner *javaRun) {
|
||||
javaRun->javaProcess->start_process();
|
||||
auto pid = javaRun->javaProcess->pid();
|
||||
std::cout << "I2P Router process id = " << pid << std::endl;
|
||||
|
||||
// Blocking
|
||||
javaRun->javaProcess->wait();
|
||||
};
|
||||
auto callbackAfterExit = [](){
|
||||
printf("Callback after exit\n");
|
||||
};
|
||||
NSLog(@"Still fine!");
|
||||
|
||||
setGlobalRouterObject(new JavaRunner{ javaBin, arguments, i2pBaseDir, std::move(launchLambda), std::move(callbackAfterExit) });
|
||||
|
||||
NSLog(@"Still fine!");
|
||||
return std::async(std::launch::async, [&]{
|
||||
getGlobalRouterObject().value()->execute();
|
||||
return 0;
|
||||
});
|
||||
*/
|
||||
CFShow(arguments);
|
||||
|
||||
@try {
|
||||
RTaskOptions* options = [RTaskOptions alloc];
|
||||
options.binPath = javaBin;
|
||||
options.arguments = arguments;
|
||||
options.i2pBaseDir = i2pBaseDir;
|
||||
auto instance = [[[RouterTask alloc] initWithOptions: options] autorelease];
|
||||
//auto pid = [instance execute];
|
||||
//NSThread *thr = [[NSThread alloc] initWithTarget:instance selector:@selector(execute) object:nil];
|
||||
[instance execute];
|
||||
return std::async(std::launch::async, [&instance]{
|
||||
return 1;//[instance getPID];
|
||||
});
|
||||
}
|
||||
@catch (NSException *e)
|
||||
{
|
||||
NSLog(@"Expection occurred %@", [e reason]);
|
||||
return std::async(std::launch::async, [&]{
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@implementation MenuBarCtrl
|
||||
|
||||
- (void) statusItemButtonLeftClick: (StatusItemButton *) button
|
||||
@ -82,6 +136,11 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
||||
- (void) stopJavaRouterBtnHandler: (NSMenuItem *) menuItem
|
||||
{
|
||||
NSLog(@"Clicked stopJavaRouterBtnHandler");
|
||||
if (getGlobalRouterObject().has_value())
|
||||
{
|
||||
//getGlobalRouterObject().value()->requestRouterShutdown();
|
||||
NSLog(@"Requested shutdown");
|
||||
}
|
||||
}
|
||||
|
||||
- (void) quitWrapperBtnHandler: (NSMenuItem *) menuItem
|
||||
@ -172,6 +231,11 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
|
||||
shouldPresentNotification:(NSUserNotification *)notification {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSString *)userSelectJavaHome:(JvmListPtr)rawJvmList
|
||||
{
|
||||
NSString *appleScriptString = @"set jvmlist to {\"Newest\"";
|
||||
@ -224,13 +288,14 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
||||
CFPreferencesSetMultiple((CFDictionaryRef)dict, NULL, CFAPPDOMAIN, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
|
||||
CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
|
||||
//CFPreferencesSetAppValue(@"javaHome", (CFPropertyListRef)cfDefaultHome, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
|
||||
|
||||
|
||||
if (self.enableVerboseLogging) NSLog(@"Default preferences stored!");
|
||||
}
|
||||
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
// Init application here
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
|
||||
// Start with user preferences
|
||||
self.userPreferences = [NSUserDefaults standardUserDefaults];
|
||||
[self setApplicationDefaultPreferences];
|
||||
@ -246,7 +311,6 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
||||
auto javaHomePref = [self.userPreferences stringForKey:@"javaHome"];
|
||||
if (self.enableVerboseLogging) NSLog(@"Java home from preferences: %@", javaHomePref);
|
||||
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
|
||||
|
||||
// This is the only GUI the user experience on a regular basis.
|
||||
self.menuBarCtrl = [[MenuBarCtrl alloc] init];
|
||||
@ -255,6 +319,16 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
||||
if (self.enableVerboseLogging) NSLog(@"Appdomain is: %@", appDomain);
|
||||
|
||||
NSLog(@"We should have started the statusbar object by now...");
|
||||
|
||||
// Figure out base directory
|
||||
const char* pathFromHome = "/Users/%s/Library/I2P";
|
||||
auto username = getenv("USER");
|
||||
char buffer[strlen(pathFromHome)+strlen(username)];
|
||||
sprintf(buffer, pathFromHome, username);
|
||||
std::string i2pBaseDir(buffer);
|
||||
if (self.enableVerboseLogging) printf("Home directory is: %s\n", buffer);
|
||||
|
||||
|
||||
//[statusBarButton setAction:@selector(itemClicked:)];
|
||||
//dispatch_async(dispatch_get_main_queue(), ^{
|
||||
//});
|
||||
@ -273,33 +347,121 @@ JvmListSharedPtr gRawJvmList = nullptr;
|
||||
return std::string([val UTF8String]);;
|
||||
};
|
||||
|
||||
|
||||
auto launchLambda = [&pref](JavaRunner *javaRun) {
|
||||
javaRun->javaProcess->start_process();
|
||||
auto pid = javaRun->javaProcess->pid();
|
||||
std::cout << "I2P Router process id = " << pid << std::endl;
|
||||
|
||||
// Blocking
|
||||
javaRun->javaProcess->wait();
|
||||
};
|
||||
auto callbackAfterExit = [=](){
|
||||
printf("Callback after exit\n");
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
// Get Java home
|
||||
auto getJavaBin = [&getJavaHomeLambda]() -> std::string {
|
||||
// Get Java home
|
||||
auto javaHome = getJavaHomeLambda();
|
||||
trim(javaHome); // Trim to remove endline
|
||||
auto javaBin = std::string(javaHome);
|
||||
javaBin += "/bin/java"; // Append java binary to path.
|
||||
//printf("hello world: %s\n", javaBin.c_str());
|
||||
if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]);
|
||||
return javaBin;
|
||||
};
|
||||
|
||||
auto r = new JavaRunner{ javaBin, launchLambda, callbackAfterExit };
|
||||
r->execute();
|
||||
auto buildClassPath = [](std::string basePath) -> std::vector<std::string> {
|
||||
return globVector(basePath+std::string("/lib/*.jar"));
|
||||
};
|
||||
|
||||
auto sendUserNotification = [&](NSString* title, NSString* informativeText) -> void {
|
||||
NSUserNotification *userNotification = [[[NSUserNotification alloc] init] autorelease];
|
||||
|
||||
userNotification.title = title;
|
||||
userNotification.informativeText = informativeText;
|
||||
userNotification.soundName = NSUserNotificationDefaultSoundName;
|
||||
|
||||
[[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification:userNotification];
|
||||
};
|
||||
|
||||
|
||||
// Get paths
|
||||
NSBundle *launcherBundle = [NSBundle mainBundle];
|
||||
|
||||
std::string basearg("-Di2p.dir.base=");
|
||||
basearg += i2pBaseDir;
|
||||
|
||||
std::string zippath("-Di2p.base.zip=");
|
||||
zippath += [[launcherBundle pathForResource:@"base" ofType:@"zip"] UTF8String];
|
||||
|
||||
std::string jarfile("-cp ");
|
||||
jarfile += [[launcherBundle pathForResource:@"launcher" ofType:@"jar"] UTF8String];
|
||||
|
||||
struct stat sb;
|
||||
if ( !(stat(buffer, &sb) == 0 && S_ISDIR(sb.st_mode)) )
|
||||
{
|
||||
// I2P is not extracted.
|
||||
if (self.enableVerboseLogging) printf("I2P Directory don't exists!\n");
|
||||
|
||||
// Create directory
|
||||
mkdir(buffer, S_IRUSR | S_IWUSR | S_IXUSR);
|
||||
|
||||
auto cli = JavaRunner::defaultFlagsForExtractorJob;
|
||||
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 {
|
||||
if (self.enableVerboseLogging) printf("I2P directory found!\n");
|
||||
}
|
||||
|
||||
// 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;
|
||||
std::cerr << "Exception: " << err.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user