diff --git a/launchers/macosx/obj-cpp/AppDelegate.h b/launchers/macosx/obj-cpp/AppDelegate.h index ad20e10c3639b4b92ee2eea62e3a85eedef2e601..d5592a336820dc910eb7f210703dfac5c9f1b6c8 100644 --- a/launchers/macosx/obj-cpp/AppDelegate.h +++ b/launchers/macosx/obj-cpp/AppDelegate.h @@ -7,9 +7,9 @@ #include <Cocoa/Cocoa.h> +#include "RouterTask.h" #include "StatusItemButton.h" #include "JavaHelper.h" -#include "RouterTask.h" #include "neither/maybe.hpp" #include "optional.hpp" #include "subprocess.hpp" @@ -26,24 +26,33 @@ using namespace neither; -using maybeAnRouterRunner = std::experimental::optional<RouterTask*>; +@class ExtractMetaInfo; +using maybeAnRouterRunner = std::experimental::optional<I2PRouterTask*>; +std::vector<std::string> buildClassPath(std::string basePath); extern JvmListSharedPtr gRawJvmList; // DO NOT ACCESS THIS GLOBAL VARIABLE DIRECTLY. static std::mutex globalRouterStatusMutex; static maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{}; +static bool isRuterRunning = false; maybeAnRouterRunner getGlobalRouterObject(); -void setGlobalRouterObject(RouterTask* newRouter); +void setGlobalRouterObject(I2PRouterTask* newRouter); +bool getGlobalRouterIsRunning(); +void setGlobalRouterIsRunning(bool running); -@class ExtractMetaInfo; @interface ExtractMetaInfo : NSObject -@property (strong) NSString* i2pBase; -@property (strong) NSString* javaBinary; -@property (strong) NSString* zipFile; -@property (strong) NSString* jarFile; +@property (copy) NSString* i2pBase; +@property (copy) NSString* javaBinary; +@property (copy) NSString* zipFile; +@property (copy) NSString* jarFile; +@end + +@class I2PStatusMenu; +@interface I2PStatusMenu : NSMenu +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem; @end inline void sendUserNotification(NSString* title, NSString* informativeText, NSImage* contentImage = NULL, bool makeSound = false) { @@ -68,10 +77,21 @@ inline std::vector<std::string> globVector(const std::string& pattern){ return files; } +inline std::string getDefaultBaseDir() +{ + // 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); + return i2pBaseDir; +} + @interface MenuBarCtrl : NSObject <StatusItemButtonDelegate, NSMenuDelegate> @property BOOL enableLogging; @property BOOL enableVerboseLogging; -@property (strong) NSMenu *menu; +@property (strong) I2PStatusMenu *menu; @property (strong) StatusItemButton* statusBarButton; @property (strong) NSUserDefaults *userPreferences; @property (strong, nonatomic) NSImage * image; @@ -81,7 +101,7 @@ inline std::vector<std::string> globVector(const std::string& pattern){ - (void) statusItemButtonRightClick: (StatusItemButton *) button; - (void) statusBarImageBtnClicked; - (void) btnPressedAction:(id)sender; -- (void) menuWillOpen:(NSMenu *)menu; +- (void) menuWillOpen:(I2PStatusMenu *)menu; - (void) openRouterConsoleBtnHandler: (NSMenuItem *) menuItem; - (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem; @@ -91,7 +111,7 @@ inline std::vector<std::string> globVector(const std::string& pattern){ // Methods - (MenuBarCtrl *) init; - (void) dealloc; -- (NSMenu *) createStatusBarMenu; +- (I2PStatusMenu *) createStatusBarMenu; @end @protocol MenuBarCtrlDelegate @@ -106,9 +126,10 @@ inline std::vector<std::string> globVector(const std::string& pattern){ @property (strong) NSUserDefaults *userPreferences; @property BOOL enableLogging; @property BOOL enableVerboseLogging; +@property ExtractMetaInfo *metaInfo; @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)extractI2PBaseDir:(void(^)(BOOL success, NSError *error))completion; +- (void)startupI2PRouter; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification; - (void)applicationWillTerminate:(NSNotification *)aNotification; - (void)setApplicationDefaultPreferences; @@ -120,57 +141,4 @@ inline std::vector<std::string> globVector(const std::string& pattern){ @end -/* - - -@implementation CNSStatusBarCtrl --(id)initWithSysTray:(I2PCtrlSysIcon *)sys -{ - self = [super init]; - if (self) { - item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain]; - menu = 0; - systray = sys; - imageCell = [[NSImageView alloc] initWithParent:self]; - [item setView: imageCell]; - [item setHidden: NO]; - CFShow(CFSTR("CNSStatusBarCtrl::initWithSysTray executed")); - } - return self; -} --(NSStatusItem*)item { - return item; -} --(void)dealloc { - [[NSStatusBar systemStatusBar] removeStatusItem:item]; - [[NSNotificationCenter defaultCenter] removeObserver:imageCell]; - [imageCell release]; - [item release]; - [super dealloc]; -} -@end - - -class CSystemTrayIcon -{ -public: - CSystemTrayIcon(I2PCtrlSysIcon *sys) - { - item = [[CNSStatusBarCtrl alloc] initWithSysTray:sys]; - [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:item]; - const int menuHeight = [[NSStatusBar systemStatusBar] thickness]; - printf("menuHeight: %d\n", menuHeight); - [[[item item] view] setHidden: NO]; - } - ~CSystemTrayIcon() - { - [[[item item] view] setHidden: YES]; - [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil]; - [item release]; - } - CNSStatusBarCtrl *item; -}; -*/ - - #endif diff --git a/launchers/macosx/obj-cpp/Info.plist b/launchers/macosx/obj-cpp/Info.plist index 79a7a00dad28307e312ce71d4582064a6dc146e4..1e0372a288fb991f6730d6db16250405029dbbed 100644 --- a/launchers/macosx/obj-cpp/Info.plist +++ b/launchers/macosx/obj-cpp/Info.plist @@ -11,7 +11,7 @@ <key>CFBundleGetInfoString</key> <string>0.9.35-experimental</string> <key>CFBundleIconFile</key> - <string>i2p</string> + <string>images/AppIcon.icns</string> <key>CFBundleIdentifier</key> <string>net.i2p.launcher</string> <key>CFBundleInfoDictionaryVersion</key> diff --git a/launchers/macosx/obj-cpp/PidWatcher.h b/launchers/macosx/obj-cpp/PidWatcher.h index acb79673ccc59f5bedc2438e81752bedc65cb303..7cac1c858c42fe9c88600069f8b99e62c0124bc9 100644 --- a/launchers/macosx/obj-cpp/PidWatcher.h +++ b/launchers/macosx/obj-cpp/PidWatcher.h @@ -3,33 +3,12 @@ #include <CoreFoundation/CoreFoundation.h> #include <unistd.h> #include <sys/event.h> -#include <functional> #include "neither/either.hpp" #include "AppDelegate.h" using callbackType = void (CFFileDescriptorRef, CFOptionFlags, void *); using HandleFunction = std::function<void(int)>; -/* -class CallbackWrapper -{ - CallbackWrapper(HandleFunction func) : mCallback(func); - void operator(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) { - struct kevent kev; - int fd = CFFileDescriptorGetNativeDescriptor(fdref); - kevent(fd, NULL, 0, &kev, 1, NULL); - // take action on death of process here - NSLog(@"process with pid '%u' died\n", (unsigned int)kev.ident); - - mCallback(0); - CFFileDescriptorInvalidate(fdref); - CFRelease(fdref); - } - -private: - HandleFunction mCallback; -}; -*/ static void noteProcDeath(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) { struct kevent kev; diff --git a/launchers/macosx/obj-cpp/RouterTask.h b/launchers/macosx/obj-cpp/RouterTask.h index 9c29a1d521fda4dc13757a1f15f699662381ba2f..2f5436e38f3cd8aff53910f284341395596838da 100644 --- a/launchers/macosx/obj-cpp/RouterTask.h +++ b/launchers/macosx/obj-cpp/RouterTask.h @@ -14,22 +14,21 @@ @class RTaskOptions; - @interface RTaskOptions : NSObject @property (strong) NSString* binPath; @property (strong) NSArray<NSString *>* arguments; @property (strong) NSString* i2pBaseDir; @end -@class RouterTask; - -@interface RouterTask : NSObject +@class I2PRouterTask; +@interface I2PRouterTask : NSObject @property (strong) NSTask* routerTask; @property (strong) NSUserDefaults *userPreferences; @property (strong) NSFileHandle *readLogHandle; @property (strong) NSMutableData *totalLogData; @property (strong) NSPipe *processPipe; @property (strong) NSFileHandle *input; +@property (atomic) BOOL isRouterRunning; @property (atomic) BOOL userRequestedRestart; - (instancetype) initWithOptions : (RTaskOptions*) options; - (int) execute; @@ -37,6 +36,7 @@ - (void) requestRestart; - (BOOL) isRunning; - (int) getPID; +- (void)routerStdoutData:(NSNotification *)notification; @end @@ -48,6 +48,8 @@ class JavaRunner; typedef std::function<void(void)> fp_t; typedef std::function<void(JavaRunner *ptr)> fp_proc_t; + + /** * * class JavaRunner diff --git a/launchers/macosx/obj-cpp/RouterTask.mm b/launchers/macosx/obj-cpp/RouterTask.mm index fb54ead119f6ce873348c03c5d8c88730bfa9b00..f12be635da77dbbe7f82c7f547d3b6f13e93307f 100644 --- a/launchers/macosx/obj-cpp/RouterTask.mm +++ b/launchers/macosx/obj-cpp/RouterTask.mm @@ -13,12 +13,19 @@ @implementation RTaskOptions @end -@implementation RouterTask +@implementation I2PRouterTask +- (void)routerStdoutData:(NSNotification *)notification +{ + NSLog(@"%@", [[NSString alloc] initWithData:[notification.object availableData] encoding:NSUTF8StringEncoding]); + [notification.object waitForDataInBackgroundAndNotify]; +} + - (instancetype) initWithOptions : (RTaskOptions*) options { - self.userRequestedRestart = FALSE; + self.userRequestedRestart = NO; + self.isRouterRunning = NO; self.input = [NSFileHandle fileHandleWithStandardInput]; self.routerTask = [NSTask new]; self.processPipe = [NSPipe new]; @@ -30,8 +37,22 @@ [self.routerTask setEnvironment: envDict]; [self.routerTask setStandardOutput:self.processPipe]; [self.routerTask setStandardError:self.processPipe]; + + NSFileHandle *stdoutFileHandle = [self.processPipe fileHandleForReading]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(routerStdoutData:) + name:NSFileHandleDataAvailableNotification + object:stdoutFileHandle]; + + [stdoutFileHandle waitForDataInBackgroundAndNotify]; + [self.routerTask setTerminationHandler:^(NSTask* task) { NSLog(@"termHandler triggered!"); + NSBundle *launcherBundle = [NSBundle mainBundle]; + auto iconImage = [launcherBundle pathForResource:@"ItoopieTransparent" ofType:@"png"]; + sendUserNotification(APP_IDSTR, @"I2P Router has stopped", [NSImage imageNamed:iconImage]); + // Cleanup + self.isRouterRunning = NO; }]; /* self.readLogHandle = [self.processPipe fileHandleForReading]; @@ -53,7 +74,8 @@ - (void) requestRestart { - self.userRequestedRestart = TRUE; + self.userRequestedRestart = YES; + kill([self.routerTask processIdentifier], SIGHUP); } - (BOOL) isRunning @@ -63,35 +85,17 @@ - (int) execute { - //@try { + @try { [self.routerTask launch]; watchPid([self.routerTask processIdentifier]); - [self.input waitForDataInBackgroundAndNotify]; - [[self.processPipe fileHandleForReading] waitForDataInBackgroundAndNotify]; - [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification - object:[self.processPipe fileHandleForReading] queue:nil - usingBlock:^(NSNotification *note) - { - // Read from shell output - NSData *outData = [[self.processPipe fileHandleForReading] availableData]; - NSString *outStr = [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding]; - if ([outStr length] > 1) { - NSLog(@"output: %@", outStr); - } - - // Continue waiting for shell output. - [[self.processPipe fileHandleForReading] waitForDataInBackgroundAndNotify]; - }]; - //[self.routerTask waitUntilExit]; - //NSThread *thr = [[NSThread alloc] initWithTarget:self.routerTask selector:@selector(launch) object:nil]; - //[self.routerTask waitUntilExit]; + self.isRouterRunning = YES; return 1; - /*} + } @catch (NSException *e) { NSLog(@"Expection occurred %@", [e reason]); return 0; - }*/ + } } - (int) getPID diff --git a/launchers/macosx/obj-cpp/StatusItemButton.h b/launchers/macosx/obj-cpp/StatusItemButton.h index e38ca53038a7a2e436885c81a53d5e0e630bc132..93086f5e4fb0870658fa7a6ef1870d40d032d30e 100644 --- a/launchers/macosx/obj-cpp/StatusItemButton.h +++ b/launchers/macosx/obj-cpp/StatusItemButton.h @@ -2,6 +2,12 @@ #import <Cocoa/Cocoa.h> +/** + * + * This is a class representing the "image" in the systray. + * + * + * **/ @class StatusItemButton; @protocol StatusItemButtonDelegate <NSObject> diff --git a/launchers/macosx/obj-cpp/main.mm b/launchers/macosx/obj-cpp/main.mm index e5f6583227f70f47471fe88941b5f642d307f040..9a64c4796e2034ab54062f6f01380720e7f6691f 100644 --- a/launchers/macosx/obj-cpp/main.mm +++ b/launchers/macosx/obj-cpp/main.mm @@ -30,6 +30,7 @@ #include "JavaHelper.h" #include "fn.h" #include "optional.hpp" +#include "portcheck.h" #define debug(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]); @@ -42,6 +43,10 @@ JvmListSharedPtr gRawJvmList = nullptr; @interface AppDelegate () <NSUserNotificationCenterDelegate, NSApplicationDelegate> @end +std::vector<std::string> buildClassPath(std::string basePath) +{ + return globVector(basePath+std::string("/lib/*.jar")); +} maybeAnRouterRunner getGlobalRouterObject() { @@ -49,44 +54,36 @@ maybeAnRouterRunner getGlobalRouterObject() return globalRouterStatus; } -void setGlobalRouterObject(RouterTask* newRouter) +void setGlobalRouterObject(I2PRouterTask* newRouter) { std::lock_guard<std::mutex> lock(globalRouterStatusMutex); globalRouterStatus.emplace(newRouter); } -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) }); +pthread_mutex_t mutex; - NSLog(@"Still fine!"); - return std::async(std::launch::async, [&]{ - getGlobalRouterObject().value()->execute(); - return 0; - }); -*/ - //CFShow(arguments); +bool getGlobalRouterIsRunning() +{ + pthread_mutex_lock(&mutex); + bool current = isRuterRunning; + pthread_mutex_unlock(&mutex); + return current; +} +void setGlobalRouterIsRunning(bool running) +{ + pthread_mutex_lock(&mutex); + isRuterRunning = running; + pthread_mutex_unlock(&mutex); +} +std::future<int> startupRouter(NSString* javaBin, NSArray<NSString*>* arguments, NSString* i2pBaseDir) { @try { RTaskOptions* options = [RTaskOptions alloc]; options.binPath = javaBin; options.arguments = arguments; options.i2pBaseDir = i2pBaseDir; - auto instance = [[[RouterTask alloc] initWithOptions: options] autorelease]; + auto instance = [[[I2PRouterTask alloc] initWithOptions: options] autorelease]; setGlobalRouterObject(instance); //NSThread *thr = [[NSThread alloc] initWithTarget:instance selector:@selector(execute) object:nil]; [instance execute]; @@ -112,6 +109,15 @@ void openUrl(NSString* url) [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString: url]]; } +@implementation I2PStatusMenu + +- (BOOL)validateMenuItem:(NSMenuItem *)item +{ + NSLog(@"item is: %@",item); + return YES; +} + +@end @implementation MenuBarCtrl @@ -148,6 +154,8 @@ void openUrl(NSString* url) - (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem { NSLog(@"Clicked startJavaRouterBtnHandler"); + AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate]; + [appDelegate startupI2PRouter]; } - (void) restartJavaRouterBtnHandler: (NSMenuItem *) menuItem @@ -210,9 +218,9 @@ void openUrl(NSString* url) [self.menu release]; } -- (NSMenu *)createStatusBarMenu +- (I2PStatusMenu *)createStatusBarMenu { - NSMenu *menu = [[NSMenu alloc] init]; + I2PStatusMenu *menu = [[I2PStatusMenu alloc] init]; [menu setAutoenablesItems:NO]; NSMenuItem *openConsoleI2Pbtn = @@ -271,10 +279,10 @@ void openUrl(NSString* url) @implementation AppDelegate -- (void)extractI2PBaseDir:(ExtractMetaInfo *)metaInfo completion:(void(^)(BOOL success, NSError *error))completion +- (void)extractI2PBaseDir:(void(^)(BOOL success, NSError *error))completion { - std::string basePath([metaInfo.i2pBase UTF8String]); - NSParameterAssert(metaInfo.i2pBase); + std::string basePath([self.metaInfo.i2pBase UTF8String]); + NSParameterAssert(self.metaInfo.i2pBase); NSError *error = NULL; BOOL success; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @@ -286,10 +294,10 @@ void openUrl(NSString* url) basearg += basePath; std::string zippath("-Di2p.base.zip="); - zippath += [metaInfo.zipFile UTF8String]; + zippath += [self.metaInfo.zipFile UTF8String]; std::string jarfile("-cp "); - jarfile += [metaInfo.jarFile UTF8String]; + jarfile += [self.metaInfo.jarFile UTF8String]; // Create directory mkdir(basePath.c_str(), S_IRUSR | S_IWUSR | S_IXUSR); @@ -305,7 +313,7 @@ void openUrl(NSString* url) cli.push_back("net.i2p.launchers.BaseExtractor"); //auto charCli = map(cli, [](std::string str){ return str.c_str(); }); - std::string execStr = [metaInfo.javaBinary UTF8String]; + std::string execStr = [self.metaInfo.javaBinary UTF8String]; for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; }); NSLog(@"Trying cmd: %@", [NSString stringWithUTF8String:execStr.c_str()]); @@ -337,16 +345,12 @@ void openUrl(NSString* url) }); } -- (void)startupI2PRouter:(ExtractMetaInfo *)metaInfo +- (void)startupI2PRouter { - 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. + std::string basePath([self.metaInfo.i2pBase UTF8String]); - // Get paths - NSBundle *launcherBundle = [NSBundle mainBundle]; + // Get paths + NSBundle *launcherBundle = [NSBundle mainBundle]; auto jarList = buildClassPath(basePath); std::string classpathStrHead = "-classpath"; std::string classpathStr = ""; @@ -371,12 +375,12 @@ void openUrl(NSString* url) 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]); + auto javaBin = std::string([self.metaInfo.javaBinary UTF8String]); sendUserNotification(APP_IDSTR, @"I2P Router is starting up!", self.contentImage); - auto nsJavaBin = metaInfo.javaBinary; - auto nsBasePath = metaInfo.i2pBase; + auto nsJavaBin = self.metaInfo.javaBinary; + auto nsBasePath = self.metaInfo.i2pBase; NSArray* arrArguments = [NSArray arrayWithObjects:&argList[0] count:argList.size()]; startupRouter(nsJavaBin, arrArguments, nsBasePath); //if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]); @@ -434,7 +438,8 @@ void openUrl(NSString* url) @"lastI2PVersion" : (NSString *)CFSTR(DEF_I2P_VERSION), @"enableLogging": @true, @"enableVerboseLogging": @true, - @"autoStartRouter": @true + @"autoStartRouter": @true, + @"i2pBaseDirectory": (NSString *)CFStringCreateWithCString(NULL, const_cast<const char *>(getDefaultBaseDir().c_str()), kCFStringEncodingUTF8) }]; if (self.enableVerboseLogging) NSLog(@"Default JVM home preference set to: %@", (NSString *)cfDefaultHome); @@ -468,12 +473,9 @@ void openUrl(NSString* url) // In case we are unbundled, make us a proper UI application [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory]; [NSApp activateIgnoringOtherApps:YES]; - //auto prefArray = CFPreferencesCopyKeyList(CFAPPDOMAIN, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); - //CFShow(prefArray); auto javaHomePref = [self.userPreferences stringForKey:@"javaHome"]; if (self.enableVerboseLogging) NSLog(@"Java home from preferences: %@", javaHomePref); - // This is the only GUI the user experience on a regular basis. self.menuBarCtrl = [[MenuBarCtrl alloc] init]; @@ -482,13 +484,8 @@ void openUrl(NSString* url) 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); + std::string i2pBaseDir(getDefaultBaseDir()); + //if (self.enableVerboseLogging) printf("Home directory is: %s\n", buffer); //[statusBarButton setAction:@selector(itemClicked:)]; @@ -499,57 +496,57 @@ void openUrl(NSString* url) self.menuBarCtrl.enableLogging = self.enableLogging; self.menuBarCtrl.enableVerboseLogging = self.enableVerboseLogging; - if (self.enableVerboseLogging) NSLog(@"processinfo %@", [[NSProcessInfo processInfo] arguments]); - auto getJavaHomeLambda = [&pref,&self]() -> std::string { - NSString* val = @""; - val = [pref stringForKey:@"javaHome"]; - if (val == NULL) val = @""; - if (self.enableVerboseLogging) NSLog(@"Javahome: %@", val); - return std::string([val UTF8String]);; - }; - auto getJavaBin = [&getJavaHomeLambda]() -> std::string { - // Get Java home - auto javaHome = getJavaHomeLambda(); + if (port_check() != 0) + { + NSLog(@"Seems i2p is already running - I will not start the router (port 7657 is in use..)"); + return; + } + + if (self.enableVerboseLogging) NSLog(@"processinfo %@", [[NSProcessInfo processInfo] arguments]); + + auto getJavaBin = [&pref,&self]() -> std::string { + // Get Java home + NSString* val = @""; + val = [pref stringForKey:@"javaHome"]; + if (val == NULL) val = @""; + if (self.enableVerboseLogging) NSLog(@"Javahome: %@", val); + auto javaHome = std::string([val UTF8String]); trim(javaHome); // Trim to remove endline auto javaBin = std::string(javaHome); javaBin += "/bin/java"; // Append java binary to path. return javaBin; }; - auto buildClassPath = [](std::string basePath) -> std::vector<std::string> { - return globVector(basePath+std::string("/lib/*.jar")); - }; - - auto metaInfo = [ExtractMetaInfo alloc]; - metaInfo.i2pBase = [NSString stringWithUTF8String:buffer]; - metaInfo.javaBinary = [NSString stringWithUTF8String:getJavaBin().c_str()]; - metaInfo.jarFile = [launcherBundle pathForResource:@"launcher" ofType:@"jar"]; - metaInfo.zipFile = [launcherBundle pathForResource:@"base" ofType:@"zip"]; + self.metaInfo = [[ExtractMetaInfo alloc] init]; + self.metaInfo.i2pBase = [NSString stringWithUTF8String:i2pBaseDir.c_str()]; + self.metaInfo.javaBinary = [NSString stringWithUTF8String:getJavaBin().c_str()]; + self.metaInfo.jarFile = [launcherBundle pathForResource:@"launcher" ofType:@"jar"]; + self.metaInfo.zipFile = [launcherBundle pathForResource:@"base" ofType:@"zip"]; std::string basearg("-Di2p.dir.base="); basearg += i2pBaseDir; std::string jarfile("-cp "); - jarfile += [metaInfo.zipFile UTF8String]; + jarfile += [self.metaInfo.zipFile UTF8String]; struct stat sb; - if ( !(stat(buffer, &sb) == 0 && S_ISDIR(sb.st_mode)) ) + if ( !(stat(i2pBaseDir.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) ) { // I2P is not extracted. if (self.enableVerboseLogging) NSLog(@"I2P Directory don't exists!"); - [self extractI2PBaseDir: metaInfo completion:^(BOOL success, NSError *error) { + [self extractI2PBaseDir:^(BOOL success, NSError *error) { //__typeof__(self) strongSelf = weakSelf; //if (strongSelf == nil) return; - [self startupI2PRouter:metaInfo]; + [self startupI2PRouter]; }]; } else { if (self.enableVerboseLogging) NSLog(@"I2P directory found!"); - [self startupI2PRouter:metaInfo]; + [self startupI2PRouter]; } } diff --git a/launchers/macosx/obj-cpp/portcheck.h b/launchers/macosx/obj-cpp/portcheck.h new file mode 100644 index 0000000000000000000000000000000000000000..fd7838c952a80a3d3ee944aecf51352862bf178d --- /dev/null +++ b/launchers/macosx/obj-cpp/portcheck.h @@ -0,0 +1,59 @@ +#pragma once + +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <errno.h> + +typedef struct sockaddr *sad; /* A necesary dummy typedef */ + + +int port_check(int portNum=7657) +{ +int sock; /* Socket that will be bind */ +struct sockaddr_in sin; /* Address Structure */ + +/* Create the socket */ +/* PF_INET is the option for make a TCP socket. + You can try "man socket" for more info */ +sock = socket( PF_INET, SOCK_STREAM, 0 ); + +/* The socket creation failed */ +if ( 0 > sock ) { + perror( "socket" ); + return ( -1 ); +} + +/* Address */ +sin.sin_family = AF_INET; +sin.sin_port = htons( portNum ); /* htons() convert the number + to big endian */ +sin.sin_addr.s_addr = INADDR_ANY; + +/* We bind the socket to the port PORT to check if + the port is in use */ +if ( 0 > bind( sock, (sad)&sin, sizeof( sin ) ) ) { + /* Bind failed, now we can check if the address is + in use */ + + if ( EADDRINUSE == errno ) { + /* We put the code necesary to manage this case */ + printf( "The TCP port %d is in use.\n", portNum ); + } + + else + /* If the error were other than EADDRINUSE, we print it */ + perror( "bind" ); + + return 1; +} + +/* If we arrive to this point, the port weren't in use and + we have it attached to our program. We can close + the socket or use it */ +close( sock ); /* Close the socket */ + +return 0; +}