Changeset f9fbc76
- Timestamp:
- Jul 24, 2018 4:26:40 PM (3 years ago)
- Branches:
- master
- Children:
- 7338282b
- Parents:
- 2ee1a21
- Location:
- launchers/macosx/obj-cpp
- Files:
-
- 1 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
launchers/macosx/obj-cpp/AppDelegate.h
r2ee1a21 rf9fbc76 8 8 #include <Cocoa/Cocoa.h> 9 9 10 #include "RouterTask.h" 10 11 #include "StatusItemButton.h" 11 12 #include "JavaHelper.h" 12 #include "RouterTask.h"13 13 #include "neither/maybe.hpp" 14 14 #include "optional.hpp" … … 27 27 using namespace neither; 28 28 29 using maybeAnRouterRunner = std::experimental::optional<RouterTask*>; 29 @class ExtractMetaInfo; 30 using maybeAnRouterRunner = std::experimental::optional<I2PRouterTask*>; 30 31 32 std::vector<std::string> buildClassPath(std::string basePath); 31 33 32 34 extern JvmListSharedPtr gRawJvmList; … … 35 37 static std::mutex globalRouterStatusMutex; 36 38 static maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{}; 39 static bool isRuterRunning = false; 37 40 38 41 maybeAnRouterRunner getGlobalRouterObject(); 39 void setGlobalRouterObject(RouterTask* newRouter); 42 void setGlobalRouterObject(I2PRouterTask* newRouter); 43 bool getGlobalRouterIsRunning(); 44 void setGlobalRouterIsRunning(bool running); 40 45 41 @class ExtractMetaInfo;42 46 @interface ExtractMetaInfo : NSObject 43 @property (strong) NSString* i2pBase; 44 @property (strong) NSString* javaBinary; 45 @property (strong) NSString* zipFile; 46 @property (strong) NSString* jarFile; 47 @property (copy) NSString* i2pBase; 48 @property (copy) NSString* javaBinary; 49 @property (copy) NSString* zipFile; 50 @property (copy) NSString* jarFile; 51 @end 52 53 @class I2PStatusMenu; 54 @interface I2PStatusMenu : NSMenu 55 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem; 47 56 @end 48 57 … … 69 78 } 70 79 80 inline std::string getDefaultBaseDir() 81 { 82 // Figure out base directory 83 const char* pathFromHome = "/Users/%s/Library/I2P"; 84 auto username = getenv("USER"); 85 char buffer[strlen(pathFromHome)+strlen(username)]; 86 sprintf(buffer, pathFromHome, username); 87 std::string i2pBaseDir(buffer); 88 return i2pBaseDir; 89 } 90 71 91 @interface MenuBarCtrl : NSObject <StatusItemButtonDelegate, NSMenuDelegate> 72 92 @property BOOL enableLogging; 73 93 @property BOOL enableVerboseLogging; 74 @property (strong) NSMenu *menu;94 @property (strong) I2PStatusMenu *menu; 75 95 @property (strong) StatusItemButton* statusBarButton; 76 96 @property (strong) NSUserDefaults *userPreferences; … … 82 102 - (void) statusBarImageBtnClicked; 83 103 - (void) btnPressedAction:(id)sender; 84 - (void) menuWillOpen:( NSMenu *)menu;104 - (void) menuWillOpen:(I2PStatusMenu *)menu; 85 105 86 106 - (void) openRouterConsoleBtnHandler: (NSMenuItem *) menuItem; … … 92 112 - (MenuBarCtrl *) init; 93 113 - (void) dealloc; 94 - ( NSMenu *) createStatusBarMenu;114 - (I2PStatusMenu *) createStatusBarMenu; 95 115 @end 96 116 … … 107 127 @property BOOL enableLogging; 108 128 @property BOOL enableVerboseLogging; 129 @property ExtractMetaInfo *metaInfo; 109 130 @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;131 - (void)extractI2PBaseDir:(void(^)(BOOL success, NSError *error))completion; 132 - (void)startupI2PRouter; 112 133 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification; 113 134 - (void)applicationWillTerminate:(NSNotification *)aNotification; … … 121 142 122 143 123 /*124 125 126 @implementation CNSStatusBarCtrl127 -(id)initWithSysTray:(I2PCtrlSysIcon *)sys128 {129 self = [super init];130 if (self) {131 item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];132 menu = 0;133 systray = sys;134 imageCell = [[NSImageView alloc] initWithParent:self];135 [item setView: imageCell];136 [item setHidden: NO];137 CFShow(CFSTR("CNSStatusBarCtrl::initWithSysTray executed"));138 }139 return self;140 }141 -(NSStatusItem*)item {142 return item;143 }144 -(void)dealloc {145 [[NSStatusBar systemStatusBar] removeStatusItem:item];146 [[NSNotificationCenter defaultCenter] removeObserver:imageCell];147 [imageCell release];148 [item release];149 [super dealloc];150 }151 @end152 153 154 class CSystemTrayIcon155 {156 public:157 CSystemTrayIcon(I2PCtrlSysIcon *sys)158 {159 item = [[CNSStatusBarCtrl alloc] initWithSysTray:sys];160 [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:item];161 const int menuHeight = [[NSStatusBar systemStatusBar] thickness];162 printf("menuHeight: %d\n", menuHeight);163 [[[item item] view] setHidden: NO];164 }165 ~CSystemTrayIcon()166 {167 [[[item item] view] setHidden: YES];168 [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil];169 [item release];170 }171 CNSStatusBarCtrl *item;172 };173 */174 175 176 144 #endif -
launchers/macosx/obj-cpp/Info.plist
r2ee1a21 rf9fbc76 12 12 <string>0.9.35-experimental</string> 13 13 <key>CFBundleIconFile</key> 14 <string>i 2p</string>14 <string>images/AppIcon.icns</string> 15 15 <key>CFBundleIdentifier</key> 16 16 <string>net.i2p.launcher</string> -
launchers/macosx/obj-cpp/PidWatcher.h
r2ee1a21 rf9fbc76 4 4 #include <unistd.h> 5 5 #include <sys/event.h> 6 #include <functional>7 6 8 7 #include "neither/either.hpp" … … 11 10 using callbackType = void (CFFileDescriptorRef, CFOptionFlags, void *); 12 11 using HandleFunction = std::function<void(int)>; 13 /*14 class CallbackWrapper15 {16 CallbackWrapper(HandleFunction func) : mCallback(func);17 void operator(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) {18 struct kevent kev;19 int fd = CFFileDescriptorGetNativeDescriptor(fdref);20 kevent(fd, NULL, 0, &kev, 1, NULL);21 // take action on death of process here22 NSLog(@"process with pid '%u' died\n", (unsigned int)kev.ident);23 24 mCallback(0);25 CFFileDescriptorInvalidate(fdref);26 CFRelease(fdref);27 }28 29 private:30 HandleFunction mCallback;31 };32 */33 12 34 13 static void noteProcDeath(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) { -
launchers/macosx/obj-cpp/RouterTask.h
r2ee1a21 rf9fbc76 15 15 16 16 @class RTaskOptions; 17 18 17 @interface RTaskOptions : NSObject 19 18 @property (strong) NSString* binPath; … … 22 21 @end 23 22 24 @class RouterTask; 25 26 @interface RouterTask : NSObject 23 @class I2PRouterTask; 24 @interface I2PRouterTask : NSObject 27 25 @property (strong) NSTask* routerTask; 28 26 @property (strong) NSUserDefaults *userPreferences; … … 31 29 @property (strong) NSPipe *processPipe; 32 30 @property (strong) NSFileHandle *input; 31 @property (atomic) BOOL isRouterRunning; 33 32 @property (atomic) BOOL userRequestedRestart; 34 33 - (instancetype) initWithOptions : (RTaskOptions*) options; … … 38 37 - (BOOL) isRunning; 39 38 - (int) getPID; 39 - (void)routerStdoutData:(NSNotification *)notification; 40 40 @end 41 41 … … 48 48 typedef std::function<void(void)> fp_t; 49 49 typedef std::function<void(JavaRunner *ptr)> fp_proc_t; 50 51 50 52 51 53 /** -
launchers/macosx/obj-cpp/RouterTask.mm
r2ee1a21 rf9fbc76 14 14 @end 15 15 16 @implementation RouterTask16 @implementation I2PRouterTask 17 17 18 19 - (void)routerStdoutData:(NSNotification *)notification 20 { 21 NSLog(@"%@", [[NSString alloc] initWithData:[notification.object availableData] encoding:NSUTF8StringEncoding]); 22 [notification.object waitForDataInBackgroundAndNotify]; 23 } 18 24 19 25 - (instancetype) initWithOptions : (RTaskOptions*) options 20 26 { 21 self.userRequestedRestart = FALSE; 27 self.userRequestedRestart = NO; 28 self.isRouterRunning = NO; 22 29 self.input = [NSFileHandle fileHandleWithStandardInput]; 23 30 self.routerTask = [NSTask new]; … … 31 38 [self.routerTask setStandardOutput:self.processPipe]; 32 39 [self.routerTask setStandardError:self.processPipe]; 40 41 NSFileHandle *stdoutFileHandle = [self.processPipe fileHandleForReading]; 42 [[NSNotificationCenter defaultCenter] addObserver:self 43 selector:@selector(routerStdoutData:) 44 name:NSFileHandleDataAvailableNotification 45 object:stdoutFileHandle]; 46 47 [stdoutFileHandle waitForDataInBackgroundAndNotify]; 48 33 49 [self.routerTask setTerminationHandler:^(NSTask* task) { 34 50 NSLog(@"termHandler triggered!"); 51 NSBundle *launcherBundle = [NSBundle mainBundle]; 52 auto iconImage = [launcherBundle pathForResource:@"ItoopieTransparent" ofType:@"png"]; 53 sendUserNotification(APP_IDSTR, @"I2P Router has stopped", [NSImage imageNamed:iconImage]); 54 // Cleanup 55 self.isRouterRunning = NO; 35 56 }]; 36 57 /* … … 54 75 - (void) requestRestart 55 76 { 56 self.userRequestedRestart = TRUE; 77 self.userRequestedRestart = YES; 78 kill([self.routerTask processIdentifier], SIGHUP); 57 79 } 58 80 … … 64 86 - (int) execute 65 87 { 66 //@try {88 @try { 67 89 [self.routerTask launch]; 68 90 watchPid([self.routerTask processIdentifier]); 69 [self.input waitForDataInBackgroundAndNotify]; 70 [[self.processPipe fileHandleForReading] waitForDataInBackgroundAndNotify]; 71 [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification 72 object:[self.processPipe fileHandleForReading] queue:nil 73 usingBlock:^(NSNotification *note) 74 { 75 // Read from shell output 76 NSData *outData = [[self.processPipe fileHandleForReading] availableData]; 77 NSString *outStr = [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding]; 78 if ([outStr length] > 1) { 79 NSLog(@"output: %@", outStr); 80 } 81 82 // Continue waiting for shell output. 83 [[self.processPipe fileHandleForReading] waitForDataInBackgroundAndNotify]; 84 }]; 85 //[self.routerTask waitUntilExit]; 86 //NSThread *thr = [[NSThread alloc] initWithTarget:self.routerTask selector:@selector(launch) object:nil]; 87 //[self.routerTask waitUntilExit]; 91 self.isRouterRunning = YES; 88 92 return 1; 89 /*}93 } 90 94 @catch (NSException *e) 91 95 { 92 96 NSLog(@"Expection occurred %@", [e reason]); 93 97 return 0; 94 } */98 } 95 99 } 96 100 -
launchers/macosx/obj-cpp/StatusItemButton.h
r2ee1a21 rf9fbc76 3 3 #import <Cocoa/Cocoa.h> 4 4 5 /** 6 * 7 * This is a class representing the "image" in the systray. 8 * 9 * 10 * **/ 5 11 @class StatusItemButton; 6 12 -
launchers/macosx/obj-cpp/main.mm
r2ee1a21 rf9fbc76 31 31 #include "fn.h" 32 32 #include "optional.hpp" 33 #include "portcheck.h" 33 34 34 35 #define debug(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]); … … 43 44 @end 44 45 46 std::vector<std::string> buildClassPath(std::string basePath) 47 { 48 return globVector(basePath+std::string("/lib/*.jar")); 49 } 45 50 46 51 maybeAnRouterRunner getGlobalRouterObject() … … 50 55 } 51 56 52 void setGlobalRouterObject( RouterTask* newRouter)57 void setGlobalRouterObject(I2PRouterTask* newRouter) 53 58 { 54 59 std::lock_guard<std::mutex> lock(globalRouterStatusMutex); … … 56 61 } 57 62 63 64 pthread_mutex_t mutex; 65 66 bool getGlobalRouterIsRunning() 67 { 68 pthread_mutex_lock(&mutex); 69 bool current = isRuterRunning; 70 pthread_mutex_unlock(&mutex); 71 return current; 72 } 73 void setGlobalRouterIsRunning(bool running) 74 { 75 pthread_mutex_lock(&mutex); 76 isRuterRunning = running; 77 pthread_mutex_unlock(&mutex); 78 } 79 58 80 std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments, NSString* i2pBaseDir) { 59 /*60 NSLog(@"Arguments: %@", [NSString stringWithUTF8String:arguments.c_str()]);61 auto launchLambda = [](JavaRunner *javaRun) {62 javaRun->javaProcess->start_process();63 auto pid = javaRun->javaProcess->pid();64 std::cout << "I2P Router process id = " << pid << std::endl;65 66 // Blocking67 javaRun->javaProcess->wait();68 };69 auto callbackAfterExit = [](){70 printf("Callback after exit\n");71 };72 NSLog(@"Still fine!");73 74 setGlobalRouterObject(new JavaRunner{ javaBin, arguments, i2pBaseDir, std::move(launchLambda), std::move(callbackAfterExit) });75 76 NSLog(@"Still fine!");77 return std::async(std::launch::async, [&]{78 getGlobalRouterObject().value()->execute();79 return 0;80 });81 */82 //CFShow(arguments);83 84 81 @try { 85 82 RTaskOptions* options = [RTaskOptions alloc]; … … 87 84 options.arguments = arguments; 88 85 options.i2pBaseDir = i2pBaseDir; 89 auto instance = [[[ RouterTask alloc] initWithOptions: options] autorelease];86 auto instance = [[[I2PRouterTask alloc] initWithOptions: options] autorelease]; 90 87 setGlobalRouterObject(instance); 91 88 //NSThread *thr = [[NSThread alloc] initWithTarget:instance selector:@selector(execute) object:nil]; … … 113 110 } 114 111 112 @implementation I2PStatusMenu 113 114 - (BOOL)validateMenuItem:(NSMenuItem *)item 115 { 116 NSLog(@"item is: %@",item); 117 return YES; 118 } 119 120 @end 115 121 116 122 @implementation MenuBarCtrl … … 149 155 { 150 156 NSLog(@"Clicked startJavaRouterBtnHandler"); 157 AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate]; 158 [appDelegate startupI2PRouter]; 151 159 } 152 160 … … 211 219 } 212 220 213 - ( NSMenu *)createStatusBarMenu214 { 215 NSMenu *menu = [[NSMenu alloc] init];221 - (I2PStatusMenu *)createStatusBarMenu 222 { 223 I2PStatusMenu *menu = [[I2PStatusMenu alloc] init]; 216 224 [menu setAutoenablesItems:NO]; 217 225 … … 272 280 @implementation AppDelegate 273 281 274 - (void)extractI2PBaseDir:( ExtractMetaInfo *)metaInfo completion:(void(^)(BOOL success, NSError *error))completion275 { 276 std::string basePath([ metaInfo.i2pBase UTF8String]);277 NSParameterAssert( metaInfo.i2pBase);282 - (void)extractI2PBaseDir:(void(^)(BOOL success, NSError *error))completion 283 { 284 std::string basePath([self.metaInfo.i2pBase UTF8String]); 285 NSParameterAssert(self.metaInfo.i2pBase); 278 286 NSError *error = NULL; 279 287 BOOL success; … … 287 295 288 296 std::string zippath("-Di2p.base.zip="); 289 zippath += [ metaInfo.zipFile UTF8String];297 zippath += [self.metaInfo.zipFile UTF8String]; 290 298 291 299 std::string jarfile("-cp "); 292 jarfile += [ metaInfo.jarFile UTF8String];300 jarfile += [self.metaInfo.jarFile UTF8String]; 293 301 294 302 // Create directory … … 306 314 307 315 //auto charCli = map(cli, [](std::string str){ return str.c_str(); }); 308 std::string execStr = [ metaInfo.javaBinary UTF8String];316 std::string execStr = [self.metaInfo.javaBinary UTF8String]; 309 317 for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; }); 310 318 … … 338 346 } 339 347 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]; 348 - (void)startupI2PRouter 349 { 350 std::string basePath([self.metaInfo.i2pBase UTF8String]); 351 352 // Get paths 353 NSBundle *launcherBundle = [NSBundle mainBundle]; 350 354 auto jarList = buildClassPath(basePath); 351 355 std::string classpathStrHead = "-classpath"; … … 372 376 argList.push_back([NSString stringWithUTF8String:classpathStr.c_str()]); 373 377 argList.push_back(@"net.i2p.router.Router"); 374 auto javaBin = std::string([ metaInfo.javaBinary UTF8String]);378 auto javaBin = std::string([self.metaInfo.javaBinary UTF8String]); 375 379 376 380 377 381 sendUserNotification(APP_IDSTR, @"I2P Router is starting up!", self.contentImage); 378 auto nsJavaBin = metaInfo.javaBinary;379 auto nsBasePath = metaInfo.i2pBase;382 auto nsJavaBin = self.metaInfo.javaBinary; 383 auto nsBasePath = self.metaInfo.i2pBase; 380 384 NSArray* arrArguments = [NSArray arrayWithObjects:&argList[0] count:argList.size()]; 381 385 startupRouter(nsJavaBin, arrArguments, nsBasePath); … … 435 439 @"enableLogging": @true, 436 440 @"enableVerboseLogging": @true, 437 @"autoStartRouter": @true 441 @"autoStartRouter": @true, 442 @"i2pBaseDirectory": (NSString *)CFStringCreateWithCString(NULL, const_cast<const char *>(getDefaultBaseDir().c_str()), kCFStringEncodingUTF8) 438 443 }]; 439 444 if (self.enableVerboseLogging) NSLog(@"Default JVM home preference set to: %@", (NSString *)cfDefaultHome); … … 469 474 [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory]; 470 475 [NSApp activateIgnoringOtherApps:YES]; 471 //auto prefArray = CFPreferencesCopyKeyList(CFAPPDOMAIN, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);472 //CFShow(prefArray);473 476 auto javaHomePref = [self.userPreferences stringForKey:@"javaHome"]; 474 477 if (self.enableVerboseLogging) NSLog(@"Java home from preferences: %@", javaHomePref); 475 478 476 477 479 // This is the only GUI the user experience on a regular basis. 478 480 self.menuBarCtrl = [[MenuBarCtrl alloc] init]; … … 483 485 NSLog(@"We should have started the statusbar object by now..."); 484 486 485 // Figure out base directory 486 const char* pathFromHome = "/Users/%s/Library/I2P"; 487 auto username = getenv("USER"); 488 char buffer[strlen(pathFromHome)+strlen(username)]; 489 sprintf(buffer, pathFromHome, username); 490 std::string i2pBaseDir(buffer); 491 if (self.enableVerboseLogging) printf("Home directory is: %s\n", buffer); 487 std::string i2pBaseDir(getDefaultBaseDir()); 488 //if (self.enableVerboseLogging) printf("Home directory is: %s\n", buffer); 492 489 493 490 … … 500 497 self.menuBarCtrl.enableVerboseLogging = self.enableVerboseLogging; 501 498 499 500 501 if (port_check() != 0) 502 { 503 NSLog(@"Seems i2p is already running - I will not start the router (port 7657 is in use..)"); 504 return; 505 } 506 502 507 if (self.enableVerboseLogging) NSLog(@"processinfo %@", [[NSProcessInfo processInfo] arguments]); 503 508 504 auto getJavaHomeLambda = [&pref,&self]() -> std::string { 505 NSString* val = @""; 506 val = [pref stringForKey:@"javaHome"]; 507 if (val == NULL) val = @""; 508 if (self.enableVerboseLogging) NSLog(@"Javahome: %@", val); 509 return std::string([val UTF8String]);; 510 }; 511 512 auto getJavaBin = [&getJavaHomeLambda]() -> std::string { 513 // Get Java home 514 auto javaHome = getJavaHomeLambda(); 509 auto getJavaBin = [&pref,&self]() -> std::string { 510 // Get Java home 511 NSString* val = @""; 512 val = [pref stringForKey:@"javaHome"]; 513 if (val == NULL) val = @""; 514 if (self.enableVerboseLogging) NSLog(@"Javahome: %@", val); 515 auto javaHome = std::string([val UTF8String]); 515 516 trim(javaHome); // Trim to remove endline 516 517 auto javaBin = std::string(javaHome); … … 519 520 }; 520 521 521 auto buildClassPath = [](std::string basePath) -> std::vector<std::string> { 522 return globVector(basePath+std::string("/lib/*.jar")); 523 }; 524 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"]; 522 523 self.metaInfo = [[ExtractMetaInfo alloc] init]; 524 self.metaInfo.i2pBase = [NSString stringWithUTF8String:i2pBaseDir.c_str()]; 525 self.metaInfo.javaBinary = [NSString stringWithUTF8String:getJavaBin().c_str()]; 526 self.metaInfo.jarFile = [launcherBundle pathForResource:@"launcher" ofType:@"jar"]; 527 self.metaInfo.zipFile = [launcherBundle pathForResource:@"base" ofType:@"zip"]; 531 528 532 529 std::string basearg("-Di2p.dir.base="); … … 534 531 535 532 std::string jarfile("-cp "); 536 jarfile += [ metaInfo.zipFile UTF8String];533 jarfile += [self.metaInfo.zipFile UTF8String]; 537 534 538 535 struct stat sb; 539 if ( !(stat( buffer, &sb) == 0 && S_ISDIR(sb.st_mode)) )536 if ( !(stat(i2pBaseDir.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) ) 540 537 { 541 538 // I2P is not extracted. 542 539 if (self.enableVerboseLogging) NSLog(@"I2P Directory don't exists!"); 543 540 544 [self extractI2PBaseDir: metaInfo completion:^(BOOL success, NSError *error) {541 [self extractI2PBaseDir:^(BOOL success, NSError *error) { 545 542 //__typeof__(self) strongSelf = weakSelf; 546 543 //if (strongSelf == nil) return; 547 [self startupI2PRouter :metaInfo];544 [self startupI2PRouter]; 548 545 }]; 549 546 550 547 } else { 551 548 if (self.enableVerboseLogging) NSLog(@"I2P directory found!"); 552 [self startupI2PRouter :metaInfo];549 [self startupI2PRouter]; 553 550 } 554 551
Note: See TracChangeset
for help on using the changeset viewer.