Changeset c8490a3 for launchers/macosx


Ignore:
Timestamp:
Jul 13, 2018 9:11:46 AM (2 years ago)
Author:
meeh <meeh@…>
Branches:
master
Children:
2daeb6d, 8c78d4f8
Parents:
818e70d
Message:

Starting to get stable and usable. Basically everything is based on callbacks.

Location:
launchers/macosx/obj-cpp
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • launchers/macosx/obj-cpp/AppDelegate.h

    r818e70d rc8490a3  
    1717#include <vector>
    1818
     19
     20#define DEF_I2P_VERSION "0.9.35"
     21#define APPDOMAIN "net.i2p.launcher"
     22#define NSAPPDOMAIN @APPDOMAIN
     23#define CFAPPDOMAIN CFSTR(APPDOMAIN)
     24#define APP_IDSTR @"I2P Launcher"
     25
     26
    1927using namespace neither;
     28
     29using maybeAnRouterRunner = std::experimental::optional<RouterTask*>;
     30
    2031
    2132extern JvmListSharedPtr gRawJvmList;
    2233
    2334// DO NOT ACCESS THIS GLOBAL VARIABLE DIRECTLY.
    24 maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{};
     35static std::mutex globalRouterStatusMutex;
     36static maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{};
    2537
    26 maybeAnRouterRunner getGlobalRouterObject()
    27 {
    28     std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
    29     return globalRouterStatus;
    30 }
     38maybeAnRouterRunner getGlobalRouterObject();
     39void setGlobalRouterObject(RouterTask* newRouter);
    3140
    32 void setGlobalRouterObject(RouterTask* newRouter)
    33 {
    34     std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
    35     globalRouterStatus.emplace(newRouter);
    36 }
     41@class ExtractMetaInfo;
     42@interface ExtractMetaInfo : NSObject
     43@property (strong) NSString* i2pBase;
     44@property (strong) NSString* javaBinary;
     45@property (strong) NSString* zipFile;
     46@property (strong) NSString* jarFile;
     47@end
    3748
     49inline void sendUserNotification(NSString* title, NSString* informativeText, NSImage* contentImage = NULL, bool makeSound = false) {
     50  NSUserNotification *userNotification = [[[NSUserNotification alloc] init] autorelease];
    3851
     52  userNotification.title = title;
     53  userNotification.informativeText = informativeText;
     54  if (contentImage != NULL) userNotification.contentImage = contentImage;
     55  if (makeSound) userNotification.soundName = NSUserNotificationDefaultSoundName;
    3956
    40 std::vector<std::string> globVector(const std::string& pattern){
     57  [[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification:userNotification];
     58};
     59
     60inline std::vector<std::string> globVector(const std::string& pattern){
    4161    glob_t glob_result;
    4262    glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
     
    6484- (void) menuWillOpen:(NSMenu *)menu;
    6585
     86- (void) openRouterConsoleBtnHandler: (NSMenuItem *) menuItem;
    6687- (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem;
    6788- (void) restartJavaRouterBtnHandler: (NSMenuItem *) menuItem;
     
    86107@property BOOL enableLogging;
    87108@property BOOL enableVerboseLogging;
     109@property (copy) NSImage *contentImage NS_AVAILABLE(10_9, NA);
     110- (void)extractI2PBaseDir:(ExtractMetaInfo *)metaInfo completion:(void(^)(BOOL success, NSError *error))completion;
     111- (void)startupI2PRouter:(ExtractMetaInfo *)metaInfo;
    88112- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
    89113- (void)applicationWillTerminate:(NSNotification *)aNotification;
  • launchers/macosx/obj-cpp/JavaHelper.h

    r818e70d rc8490a3  
    2626using namespace subprocess;
    2727using namespace neither;
    28 
    29 using maybeAnRouterRunner = std::experimental::optional<RouterTask*>;
    30 
    31 extern std::mutex globalRouterStatusMutex;
    32 extern maybeAnRouterRunner globalRouterStatus;
    33 
    3428
    3529#define DEF_MIN_JVM_VER "1.7+"
  • launchers/macosx/obj-cpp/RouterTask.h

    r818e70d rc8490a3  
    3131@property (strong) NSPipe *processPipe;
    3232@property (strong) NSFileHandle *input;
     33@property (atomic) BOOL userRequestedRestart;
    3334- (instancetype) initWithOptions : (RTaskOptions*) options;
    3435- (int) execute;
     36- (void) requestShutdown;
     37- (void) requestRestart;
     38- (BOOL) isRunning;
    3539- (int) getPID;
    3640@end
  • launchers/macosx/obj-cpp/RouterTask.mm

    r818e70d rc8490a3  
    77#include "optional.hpp"
    88#include "subprocess.hpp"
     9#include "PidWatcher.h"
    910
    1011#import <AppKit/AppKit.h>
     
    1516@implementation RouterTask
    1617
     18
    1719- (instancetype) initWithOptions : (RTaskOptions*) options
    1820{
     21    self.userRequestedRestart = FALSE;
    1922    self.input = [NSFileHandle fileHandleWithStandardInput];
    2023    self.routerTask = [NSTask new];
     
    2831    [self.routerTask setStandardOutput:self.processPipe];
    2932        [self.routerTask setStandardError:self.processPipe];
     33    [self.routerTask setTerminationHandler:^(NSTask* task) {
     34        NSLog(@"termHandler triggered!");
     35    }];
    3036/*
    3137    self.readLogHandle = [self.processPipe fileHandleForReading];
     
    4147}
    4248
     49- (void) requestShutdown
     50{
     51    [self.routerTask interrupt];
     52}
     53
     54- (void) requestRestart
     55{
     56    self.userRequestedRestart = TRUE;
     57}
     58
     59- (BOOL) isRunning
     60{
     61    return self.routerTask.running;
     62}
     63
    4364- (int) execute
    4465{
    4566    //@try {
    4667        [self.routerTask launch];
     68        watchPid([self.routerTask processIdentifier]);
    4769        [self.input waitForDataInBackgroundAndNotify];
    4870        [[self.processPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
     
    84106
    85107using namespace subprocess;
    86 
    87 std::mutex globalRouterStatusMutex;
    88108
    89109const std::vector<NSString*> JavaRunner::defaultStartupFlags {
  • launchers/macosx/obj-cpp/build.ninja

    r818e70d rc8490a3  
    11cxx = clang++
    2 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
     2cflags = -std=c++14 -g -Wall -I./include -I./include/neither -I/usr/local/include -I/usr/include $
     3    -Wno-unused-function -Wno-incomplete-implementation -Wno-unused-variable -mmacosx-version-min=10.10
    34ldflags = -framework CoreFoundation -framework Foundation -framework Cocoa -g -rdynamic
    45
  • launchers/macosx/obj-cpp/include/strutil.hpp

    r818e70d rc8490a3  
    1515#include <CoreFoundation/CFString.h>
    1616
    17 std::string strprintf(const char *fromat, ...)
     17inline std::string strprintf(const char *fromat, ...)
    1818{
    1919        std::string s;
     
    3838}
    3939
    40 std::string extractString(CFStringRef value)
     40inline std::string extractString(CFStringRef value)
    4141{
    4242  const char * data = CFStringGetCStringPtr(value, kCFStringEncodingUTF8);
     
    5757
    5858// Use CFStringRef instead of NSString*, otherwise disable ARC
    59 optional<CFStringRef> optionalString(bool val) {
     59inline optional<CFStringRef> optionalString(bool val) {
    6060    optional<CFStringRef> myOptString;
    6161    if(val) {
  • launchers/macosx/obj-cpp/main.mm

    r818e70d rc8490a3  
    3232#include "optional.hpp"
    3333
    34 #define DEF_I2P_VERSION "0.9.35"
    35 #define APPDOMAIN "net.i2p.launcher"
    36 #define NSAPPDOMAIN @APPDOMAIN
    37 #define CFAPPDOMAIN CFSTR(APPDOMAIN)
    38 
    3934#define debug(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]);
    4035
     
    4843@end
    4944
     45
     46maybeAnRouterRunner getGlobalRouterObject()
     47{
     48    std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
     49    return globalRouterStatus;
     50}
     51
     52void setGlobalRouterObject(RouterTask* newRouter)
     53{
     54    std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
     55    globalRouterStatus.emplace(newRouter);
     56}
    5057
    5158std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments, NSString* i2pBaseDir) {
     
    7380    });
    7481*/
    75     CFShow(arguments);
     82    //CFShow(arguments);
    7683
    7784    @try {
     
    8188        options.i2pBaseDir = i2pBaseDir;
    8289        auto instance = [[[RouterTask alloc] initWithOptions: options] autorelease];
    83         //auto pid = [instance execute];
     90        setGlobalRouterObject(instance);
    8491        //NSThread *thr = [[NSThread alloc] initWithTarget:instance selector:@selector(execute) object:nil];
    8592        [instance execute];
    86         return std::async(std::launch::async, [&instance]{
    87           return 1;//[instance getPID];
     93        sendUserNotification(APP_IDSTR, @"The I2P router is starting up.");
     94        auto pid = [instance getPID];
     95        return std::async(std::launch::async, [&pid]{
     96          return pid;
    8897        });
    8998    }
    9099    @catch (NSException *e)
    91100        {
    92                 NSLog(@"Expection occurred %@", [e reason]);
     101        auto errStr = [NSString stringWithFormat:@"Expection occurred %@",[e reason]];
     102                NSLog(@"%@", errStr);
     103        sendUserNotification(APP_IDSTR, errStr);
    93104        return std::async(std::launch::async, [&]{
    94105          return 0;
     
    97108}
    98109
     110void openUrl(NSString* url)
     111{
     112    [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString: url]];
     113}
     114
    99115
    100116@implementation MenuBarCtrl
     
    124140}
    125141
     142- (void) openRouterConsoleBtnHandler: (NSMenuItem *) menuItem
     143{
     144  NSLog(@"Clicked openRouterConsoleBtnHandler");
     145  openUrl(@"http://127.0.0.1:7657");
     146}
     147
    126148- (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem
    127149{
     
    132154{
    133155  NSLog(@"Clicked restartJavaRouterBtnHandler");
     156  if (getGlobalRouterObject().has_value())
     157  {
     158      sendUserNotification(APP_IDSTR, @"Requesting the I2P router to restart.");
     159      [getGlobalRouterObject().value() requestRestart];
     160      NSLog(@"Requested restart");
     161  }
    134162}
    135163
     
    139167  if (getGlobalRouterObject().has_value())
    140168  {
    141       //getGlobalRouterObject().value()->requestRouterShutdown();
     169      sendUserNotification(APP_IDSTR, @"Requesting the I2P router to shutdown.");
     170      [getGlobalRouterObject().value() requestShutdown];
    142171      NSLog(@"Requested shutdown");
    143172  }
     
    186215  NSMenu *menu = [[NSMenu alloc] init];
    187216  [menu setAutoenablesItems:NO];
     217
     218  NSMenuItem *openConsoleI2Pbtn =
     219    [[NSMenuItem alloc] initWithTitle:@"Open Console"
     220                        action:@selector(openRouterConsoleBtnHandler:)
     221                        keyEquivalent:@""];
     222  [openConsoleI2Pbtn setTarget:self];
     223  [openConsoleI2Pbtn setEnabled:YES];
     224
    188225  NSMenuItem *startI2Pbtn =
    189226    [[NSMenuItem alloc] initWithTitle:@"Start I2P"
     
    220257
    221258
     259  [menu addItem:openConsoleI2Pbtn];
    222260  [menu addItem:startI2Pbtn];
    223261  [menu addItem:stopI2Pbtn];
     
    229267@end
    230268
     269@implementation ExtractMetaInfo
     270@end
    231271
    232272@implementation AppDelegate
     273
     274- (void)extractI2PBaseDir:(ExtractMetaInfo *)metaInfo completion:(void(^)(BOOL success, NSError *error))completion
     275{
     276  std::string basePath([metaInfo.i2pBase UTF8String]);
     277  NSParameterAssert(metaInfo.i2pBase);
     278  NSError *error = NULL;
     279  BOOL success;
     280  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
     281
     282    // Get paths
     283    NSBundle *launcherBundle = [NSBundle mainBundle];
     284
     285    std::string basearg("-Di2p.dir.base=");
     286    basearg += basePath;
     287
     288    std::string zippath("-Di2p.base.zip=");
     289    zippath += [metaInfo.zipFile UTF8String];
     290
     291    std::string jarfile("-cp ");
     292    jarfile += [metaInfo.jarFile UTF8String];
     293
     294    // Create directory
     295    mkdir(basePath.c_str(), S_IRUSR | S_IWUSR | S_IXUSR);
     296
     297    auto cli = JavaRunner::defaultFlagsForExtractorJob;
     298    setenv("I2PBASE", basePath.c_str(), true);
     299    setenv("ZIPPATH", zippath.c_str(), true);
     300    //setenv("DYLD_LIBRARY_PATH",".:/usr/lib:/lib:/usr/local/lib", true);
     301
     302    cli.push_back(basearg);
     303    cli.push_back(zippath);
     304    cli.push_back(jarfile);
     305    cli.push_back("net.i2p.launchers.BaseExtractor");
     306
     307    //auto charCli = map(cli, [](std::string str){ return str.c_str(); });
     308    std::string execStr = [metaInfo.javaBinary UTF8String];
     309    for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; });
     310
     311    NSLog(@"Trying cmd: %@", [NSString stringWithUTF8String:execStr.c_str()]);
     312    try {
     313        sendUserNotification(APP_IDSTR, @"Please hold on while we extract I2P. You'll get a new message once done!", self.contentImage);
     314        int extractStatus = Popen(execStr.c_str(), environment{{
     315            {"ZIPPATH", zippath.c_str()},
     316            {"I2PBASE", basePath.c_str()}
     317        }}).wait();
     318        NSLog(@"Extraction exit code %@",[NSString stringWithUTF8String:(std::to_string(extractStatus)).c_str()]);
     319        if (extractStatus == 0)
     320        {
     321            //success = YES;
     322        }
     323    } catch (subprocess::OSError &err) {
     324        auto errMsg = [NSString stringWithUTF8String:err.what()];
     325        //success = NO;
     326        NSLog(@"Exception: %@", errMsg);
     327        sendUserNotification(APP_IDSTR, [NSString stringWithFormat:@"Error: %@", errMsg], self.contentImage);
     328    }
     329
     330    // All done. Assume success and error are already set.
     331    dispatch_async(dispatch_get_main_queue(), ^{
     332      sendUserNotification(APP_IDSTR, @"Extraction complete!", self.contentImage);
     333      if (completion) {
     334        completion(success, error);
     335      }
     336    });
     337  });
     338}
     339
     340- (void)startupI2PRouter:(ExtractMetaInfo *)metaInfo
     341{
     342  std::string basePath([metaInfo.i2pBase UTF8String]);
     343  auto buildClassPath = [](std::string basePath) -> std::vector<std::string> {
     344      return globVector(basePath+std::string("/lib/*.jar"));
     345  };
     346    // Expect base to be extracted by now.
     347
     348    // Get paths
     349    NSBundle *launcherBundle = [NSBundle mainBundle];
     350  auto jarList = buildClassPath(basePath);
     351  std::string classpathStrHead = "-classpath";
     352  std::string classpathStr = "";
     353  classpathStr += [[launcherBundle pathForResource:@"launcher" ofType:@"jar"] UTF8String];
     354  std::string prefix(basePath);
     355  prefix += "/lib/";
     356  for_each(jarList, [&classpathStr](std::string str){ classpathStr += std::string(":") + str; });
     357  //if (self.enableVerboseLogging) NSLog(@"Classpath: %@\n",[NSString stringWithUTF8String:classpathStr.c_str()]);
     358
     359  try {
     360    auto argList = JavaRunner::defaultStartupFlags;
     361
     362    std::string baseDirArg("-Di2p.dir.base=");
     363    baseDirArg += basePath;
     364    std::string javaLibArg("-Djava.library.path=");
     365    javaLibArg += basePath;
     366    // TODO: pass this to JVM
     367    auto java_opts = getenv("JAVA_OPTS");
     368
     369    argList.push_back([NSString stringWithUTF8String:baseDirArg.c_str()]);
     370    argList.push_back([NSString stringWithUTF8String:javaLibArg.c_str()]);
     371    argList.push_back([NSString stringWithUTF8String:classpathStrHead.c_str()]);
     372    argList.push_back([NSString stringWithUTF8String:classpathStr.c_str()]);
     373    argList.push_back(@"net.i2p.router.Router");
     374    auto javaBin = std::string([metaInfo.javaBinary UTF8String]);
     375
     376
     377    sendUserNotification(APP_IDSTR, @"I2P Router is starting up!", self.contentImage);
     378    auto nsJavaBin = metaInfo.javaBinary;
     379    auto nsBasePath = metaInfo.i2pBase;
     380    NSArray* arrArguments = [NSArray arrayWithObjects:&argList[0] count:argList.size()];
     381    startupRouter(nsJavaBin, arrArguments, nsBasePath);
     382    //if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]);
     383  } catch (std::exception &err) {
     384    auto errMsg = [NSString stringWithUTF8String:err.what()];
     385    NSLog(@"Exception: %@", errMsg);
     386    sendUserNotification(APP_IDSTR, [NSString stringWithFormat:@"Error: %@", errMsg], self.contentImage);
     387  }
     388}
    233389
    234390- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
     
    303459  self.enableVerboseLogging = [self.userPreferences boolForKey:@"enableVerboseLogging"];
    304460
     461
     462  // Get paths
     463  NSBundle *launcherBundle = [NSBundle mainBundle];
     464  auto iconImage = [launcherBundle pathForResource:@"ItoopieTransparent" ofType:@"png"];
     465  self.contentImage = [NSImage imageNamed:iconImage];
     466
    305467  gRawJvmList = std::make_shared<std::list<JvmVersionPtr> >(std::list<JvmVersionPtr>());
    306468  // In case we are unbundled, make us a proper UI application
     
    361523  };
    362524
    363   auto sendUserNotification = [&](NSString* title, NSString* informativeText) -> void {
    364     NSUserNotification *userNotification = [[[NSUserNotification alloc] init] autorelease];
    365 
    366     userNotification.title = title;
    367     userNotification.informativeText = informativeText;
    368     userNotification.soundName = NSUserNotificationDefaultSoundName;
    369 
    370     [[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification:userNotification];
    371   };
    372 
    373 
    374   // Get paths
    375   NSBundle *launcherBundle = [NSBundle mainBundle];
     525
     526  auto metaInfo = [ExtractMetaInfo alloc];
     527  metaInfo.i2pBase = [NSString stringWithUTF8String:buffer];
     528  metaInfo.javaBinary = [NSString stringWithUTF8String:getJavaBin().c_str()];
     529  metaInfo.jarFile = [launcherBundle pathForResource:@"launcher" ofType:@"jar"];
     530  metaInfo.zipFile = [launcherBundle pathForResource:@"base" ofType:@"zip"];
    376531
    377532  std::string basearg("-Di2p.dir.base=");
    378533  basearg += i2pBaseDir;
    379534
    380   std::string zippath("-Di2p.base.zip=");
    381   zippath += [[launcherBundle pathForResource:@"base" ofType:@"zip"] UTF8String];
    382 
    383535  std::string jarfile("-cp ");
    384   jarfile += [[launcherBundle pathForResource:@"launcher" ofType:@"jar"] UTF8String];
     536  jarfile += [metaInfo.zipFile UTF8String];
    385537
    386538  struct stat sb;
     
    388540  {
    389541    // I2P is not extracted.
    390     if (self.enableVerboseLogging) printf("I2P Directory don't exists!\n");
    391 
    392     // Create directory
    393     mkdir(buffer, S_IRUSR | S_IWUSR | S_IXUSR);
    394 
    395     auto cli = JavaRunner::defaultFlagsForExtractorJob;
    396     setenv("I2PBASE", buffer, true);
    397     setenv("ZIPPATH", zippath.c_str(), true);
    398     //setenv("DYLD_LIBRARY_PATH",".:/usr/lib:/lib:/usr/local/lib", true);
    399 
    400     cli.push_back(basearg);
    401     cli.push_back(zippath);
    402     cli.push_back(jarfile);
    403     cli.push_back("net.i2p.launchers.BaseExtractor");
    404 
    405     //auto charCli = map(cli, [](std::string str){ return str.c_str(); });
    406     std::string execStr = getJavaBin();
    407     for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; });
    408 
    409     printf("\n\nTrying cmd: %s\n\n", execStr.c_str());
    410     try {
    411         sendUserNotification((NSString*)CFSTR("I2P Extraction"), (NSString*)CFSTR("Please hold on while we extract I2P. You'll get a new message once done!"));
    412         int extractStatus = Popen(execStr.c_str(), environment{{
    413             {"ZIPPATH", zippath.c_str()},
    414             {"I2PBASE", buffer}
    415         }}).wait();
    416         printf("Extraction exit code %d\n",extractStatus);
    417         sendUserNotification((NSString*)CFSTR("I2P Extraction"), (NSString*)CFSTR("Extraction complete!"));
    418     } catch (subprocess::OSError &err) {
    419         printf("Something bad happened: %s\n", err.what());
    420     }
     542    if (self.enableVerboseLogging) NSLog(@"I2P Directory don't exists!");
     543
     544    [self extractI2PBaseDir: metaInfo completion:^(BOOL success, NSError *error) {
     545        //__typeof__(self) strongSelf = weakSelf;
     546        //if (strongSelf == nil) return;
     547        [self startupI2PRouter:metaInfo];
     548    }];
    421549
    422550  } else {
    423       if (self.enableVerboseLogging) printf("I2P directory found!\n");
    424   }
    425 
    426   // Expect base to be extracted by now.
    427 
    428   auto jarList = buildClassPath(std::string(buffer));
    429   std::string classpathStrHead = "-classpath";
    430   std::string classpathStr = "";
    431   classpathStr += [[launcherBundle pathForResource:@"launcher" ofType:@"jar"] UTF8String];
    432   std::string prefix(i2pBaseDir);
    433   prefix += "/lib/";
    434   for_each(jarList, [&classpathStr](std::string str){ classpathStr += std::string(":") + str; });
    435   //if (self.enableVerboseLogging) NSLog(@"Classpath: %@\n",[NSString stringWithUTF8String:classpathStr.c_str()]);
    436 
    437 
    438 
    439   try {
    440     auto argList = JavaRunner::defaultStartupFlags;
    441 
    442     std::string baseDirArg("-Di2p.dir.base=");
    443     baseDirArg += i2pBaseDir;
    444     std::string javaLibArg("-Djava.library.path=");
    445     javaLibArg += i2pBaseDir;
    446     // TODO: pass this to JVM
    447     auto java_opts = getenv("JAVA_OPTS");
    448 
    449     argList.push_back([NSString stringWithUTF8String:baseDirArg.c_str()]);
    450     argList.push_back([NSString stringWithUTF8String:javaLibArg.c_str()]);
    451     argList.push_back([NSString stringWithUTF8String:classpathStrHead.c_str()]);
    452     argList.push_back([NSString stringWithUTF8String:classpathStr.c_str()]);
    453     argList.push_back(@"net.i2p.router.Router");
    454     auto javaBin = getJavaBin();
    455 
    456 
    457     sendUserNotification(@"I2P Launcher", @"I2P Router is starting up!");
    458     auto nsJavaBin = [NSString stringWithUTF8String:javaBin.c_str()];
    459     auto nsBasePath = [NSString stringWithUTF8String:i2pBaseDir.c_str()];
    460     NSArray* arrArguments = [NSArray arrayWithObjects:&argList[0] count:argList.size()];
    461     startupRouter(nsJavaBin, arrArguments, nsBasePath);
    462     //if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]);
    463   } catch (std::exception &err) {
    464     std::cerr << "Exception: " << err.what() << std::endl;
    465   }
     551      if (self.enableVerboseLogging) NSLog(@"I2P directory found!");
     552      [self startupI2PRouter:metaInfo];
     553  }
     554
    466555}
    467556
Note: See TracChangeset for help on using the changeset viewer.