Code changes:

* Port check to see if i2p is already running.
* All buttons in the menu should work now.
* Rewrote some C++ to Objective-C, which fits better with the integration.
* Misc cleanup.
* Made the launch of router repeatable.
This commit is contained in:
meeh
2018-07-24 16:26:40 +00:00
parent 2ee1a212c8
commit f9fbc76dd0
8 changed files with 214 additions and 199 deletions

View File

@@ -7,9 +7,9 @@
#include <Cocoa/Cocoa.h> #include <Cocoa/Cocoa.h>
#include "RouterTask.h"
#include "StatusItemButton.h" #include "StatusItemButton.h"
#include "JavaHelper.h" #include "JavaHelper.h"
#include "RouterTask.h"
#include "neither/maybe.hpp" #include "neither/maybe.hpp"
#include "optional.hpp" #include "optional.hpp"
#include "subprocess.hpp" #include "subprocess.hpp"
@@ -26,24 +26,33 @@
using namespace neither; 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; extern JvmListSharedPtr gRawJvmList;
// DO NOT ACCESS THIS GLOBAL VARIABLE DIRECTLY. // DO NOT ACCESS THIS GLOBAL VARIABLE DIRECTLY.
static std::mutex globalRouterStatusMutex; static std::mutex globalRouterStatusMutex;
static maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{}; static maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{};
static bool isRuterRunning = false;
maybeAnRouterRunner getGlobalRouterObject(); maybeAnRouterRunner getGlobalRouterObject();
void setGlobalRouterObject(RouterTask* newRouter); void setGlobalRouterObject(I2PRouterTask* newRouter);
bool getGlobalRouterIsRunning();
void setGlobalRouterIsRunning(bool running);
@class ExtractMetaInfo;
@interface ExtractMetaInfo : NSObject @interface ExtractMetaInfo : NSObject
@property (strong) NSString* i2pBase; @property (copy) NSString* i2pBase;
@property (strong) NSString* javaBinary; @property (copy) NSString* javaBinary;
@property (strong) NSString* zipFile; @property (copy) NSString* zipFile;
@property (strong) NSString* jarFile; @property (copy) NSString* jarFile;
@end
@class I2PStatusMenu;
@interface I2PStatusMenu : NSMenu
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem;
@end @end
inline void sendUserNotification(NSString* title, NSString* informativeText, NSImage* contentImage = NULL, bool makeSound = false) { 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; 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> @interface MenuBarCtrl : NSObject <StatusItemButtonDelegate, NSMenuDelegate>
@property BOOL enableLogging; @property BOOL enableLogging;
@property BOOL enableVerboseLogging; @property BOOL enableVerboseLogging;
@property (strong) NSMenu *menu; @property (strong) I2PStatusMenu *menu;
@property (strong) StatusItemButton* statusBarButton; @property (strong) StatusItemButton* statusBarButton;
@property (strong) NSUserDefaults *userPreferences; @property (strong) NSUserDefaults *userPreferences;
@property (strong, nonatomic) NSImage * image; @property (strong, nonatomic) NSImage * image;
@@ -81,7 +101,7 @@ inline std::vector<std::string> globVector(const std::string& pattern){
- (void) statusItemButtonRightClick: (StatusItemButton *) button; - (void) statusItemButtonRightClick: (StatusItemButton *) button;
- (void) statusBarImageBtnClicked; - (void) statusBarImageBtnClicked;
- (void) btnPressedAction:(id)sender; - (void) btnPressedAction:(id)sender;
- (void) menuWillOpen:(NSMenu *)menu; - (void) menuWillOpen:(I2PStatusMenu *)menu;
- (void) openRouterConsoleBtnHandler: (NSMenuItem *) menuItem; - (void) openRouterConsoleBtnHandler: (NSMenuItem *) menuItem;
- (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem; - (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem;
@@ -91,7 +111,7 @@ inline std::vector<std::string> globVector(const std::string& pattern){
// Methods // Methods
- (MenuBarCtrl *) init; - (MenuBarCtrl *) init;
- (void) dealloc; - (void) dealloc;
- (NSMenu *) createStatusBarMenu; - (I2PStatusMenu *) createStatusBarMenu;
@end @end
@protocol MenuBarCtrlDelegate @protocol MenuBarCtrlDelegate
@@ -106,9 +126,10 @@ inline 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 ExtractMetaInfo *metaInfo;
@property (copy) NSImage *contentImage NS_AVAILABLE(10_9, NA); @property (copy) NSImage *contentImage NS_AVAILABLE(10_9, NA);
- (void)extractI2PBaseDir:(ExtractMetaInfo *)metaInfo completion:(void(^)(BOOL success, NSError *error))completion; - (void)extractI2PBaseDir:(void(^)(BOOL success, NSError *error))completion;
- (void)startupI2PRouter:(ExtractMetaInfo *)metaInfo; - (void)startupI2PRouter;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
- (void)applicationWillTerminate:(NSNotification *)aNotification; - (void)applicationWillTerminate:(NSNotification *)aNotification;
- (void)setApplicationDefaultPreferences; - (void)setApplicationDefaultPreferences;
@@ -120,57 +141,4 @@ inline std::vector<std::string> globVector(const std::string& pattern){
@end @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 #endif

View File

@@ -11,7 +11,7 @@
<key>CFBundleGetInfoString</key> <key>CFBundleGetInfoString</key>
<string>0.9.35-experimental</string> <string>0.9.35-experimental</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>i2p</string> <string>images/AppIcon.icns</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>net.i2p.launcher</string> <string>net.i2p.launcher</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>

View File

@@ -3,33 +3,12 @@
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#include <unistd.h> #include <unistd.h>
#include <sys/event.h> #include <sys/event.h>
#include <functional>
#include "neither/either.hpp" #include "neither/either.hpp"
#include "AppDelegate.h" #include "AppDelegate.h"
using callbackType = void (CFFileDescriptorRef, CFOptionFlags, void *); using callbackType = void (CFFileDescriptorRef, CFOptionFlags, void *);
using HandleFunction = std::function<void(int)>; 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) { static void noteProcDeath(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) {
struct kevent kev; struct kevent kev;

View File

@@ -14,22 +14,21 @@
@class RTaskOptions; @class RTaskOptions;
@interface RTaskOptions : NSObject @interface RTaskOptions : NSObject
@property (strong) NSString* binPath; @property (strong) NSString* binPath;
@property (strong) NSArray<NSString *>* arguments; @property (strong) NSArray<NSString *>* arguments;
@property (strong) NSString* i2pBaseDir; @property (strong) NSString* i2pBaseDir;
@end @end
@class RouterTask; @class I2PRouterTask;
@interface I2PRouterTask : NSObject
@interface RouterTask : NSObject
@property (strong) NSTask* routerTask; @property (strong) NSTask* routerTask;
@property (strong) NSUserDefaults *userPreferences; @property (strong) NSUserDefaults *userPreferences;
@property (strong) NSFileHandle *readLogHandle; @property (strong) NSFileHandle *readLogHandle;
@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 isRouterRunning;
@property (atomic) BOOL userRequestedRestart; @property (atomic) BOOL userRequestedRestart;
- (instancetype) initWithOptions : (RTaskOptions*) options; - (instancetype) initWithOptions : (RTaskOptions*) options;
- (int) execute; - (int) execute;
@@ -37,6 +36,7 @@
- (void) requestRestart; - (void) requestRestart;
- (BOOL) isRunning; - (BOOL) isRunning;
- (int) getPID; - (int) getPID;
- (void)routerStdoutData:(NSNotification *)notification;
@end @end
@@ -48,6 +48,8 @@ class JavaRunner;
typedef std::function<void(void)> fp_t; typedef std::function<void(void)> fp_t;
typedef std::function<void(JavaRunner *ptr)> fp_proc_t; typedef std::function<void(JavaRunner *ptr)> fp_proc_t;
/** /**
* *
* class JavaRunner * class JavaRunner

View File

@@ -13,12 +13,19 @@
@implementation RTaskOptions @implementation RTaskOptions
@end @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 - (instancetype) initWithOptions : (RTaskOptions*) options
{ {
self.userRequestedRestart = FALSE; self.userRequestedRestart = NO;
self.isRouterRunning = NO;
self.input = [NSFileHandle fileHandleWithStandardInput]; self.input = [NSFileHandle fileHandleWithStandardInput];
self.routerTask = [NSTask new]; self.routerTask = [NSTask new];
self.processPipe = [NSPipe new]; self.processPipe = [NSPipe new];
@@ -30,8 +37,22 @@
[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];
NSFileHandle *stdoutFileHandle = [self.processPipe fileHandleForReading];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(routerStdoutData:)
name:NSFileHandleDataAvailableNotification
object:stdoutFileHandle];
[stdoutFileHandle waitForDataInBackgroundAndNotify];
[self.routerTask setTerminationHandler:^(NSTask* task) { [self.routerTask setTerminationHandler:^(NSTask* task) {
NSLog(@"termHandler triggered!"); 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]; self.readLogHandle = [self.processPipe fileHandleForReading];
@@ -53,7 +74,8 @@
- (void) requestRestart - (void) requestRestart
{ {
self.userRequestedRestart = TRUE; self.userRequestedRestart = YES;
kill([self.routerTask processIdentifier], SIGHUP);
} }
- (BOOL) isRunning - (BOOL) isRunning
@@ -63,35 +85,17 @@
- (int) execute - (int) execute
{ {
//@try { @try {
[self.routerTask launch]; [self.routerTask launch];
watchPid([self.routerTask processIdentifier]); watchPid([self.routerTask processIdentifier]);
[self.input waitForDataInBackgroundAndNotify]; self.isRouterRunning = YES;
[[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];
return 1; return 1;
/*} }
@catch (NSException *e) @catch (NSException *e)
{ {
NSLog(@"Expection occurred %@", [e reason]); NSLog(@"Expection occurred %@", [e reason]);
return 0; return 0;
}*/ }
} }
- (int) getPID - (int) getPID

View File

@@ -2,6 +2,12 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
/**
*
* This is a class representing the "image" in the systray.
*
*
* **/
@class StatusItemButton; @class StatusItemButton;
@protocol StatusItemButtonDelegate <NSObject> @protocol StatusItemButtonDelegate <NSObject>

View File

@@ -30,6 +30,7 @@
#include "JavaHelper.h" #include "JavaHelper.h"
#include "fn.h" #include "fn.h"
#include "optional.hpp" #include "optional.hpp"
#include "portcheck.h"
#define debug(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]); #define debug(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]);
@@ -42,6 +43,10 @@ JvmListSharedPtr gRawJvmList = nullptr;
@interface AppDelegate () <NSUserNotificationCenterDelegate, NSApplicationDelegate> @interface AppDelegate () <NSUserNotificationCenterDelegate, NSApplicationDelegate>
@end @end
std::vector<std::string> buildClassPath(std::string basePath)
{
return globVector(basePath+std::string("/lib/*.jar"));
}
maybeAnRouterRunner getGlobalRouterObject() maybeAnRouterRunner getGlobalRouterObject()
{ {
@@ -49,44 +54,36 @@ maybeAnRouterRunner getGlobalRouterObject()
return globalRouterStatus; return globalRouterStatus;
} }
void setGlobalRouterObject(RouterTask* newRouter) void setGlobalRouterObject(I2PRouterTask* newRouter)
{ {
std::lock_guard<std::mutex> lock(globalRouterStatusMutex); std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
globalRouterStatus.emplace(newRouter); globalRouterStatus.emplace(newRouter);
} }
pthread_mutex_t mutex;
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) { 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 { @try {
RTaskOptions* options = [RTaskOptions alloc]; RTaskOptions* options = [RTaskOptions alloc];
options.binPath = javaBin; options.binPath = javaBin;
options.arguments = arguments; options.arguments = arguments;
options.i2pBaseDir = i2pBaseDir; options.i2pBaseDir = i2pBaseDir;
auto instance = [[[RouterTask alloc] initWithOptions: options] autorelease]; auto instance = [[[I2PRouterTask alloc] initWithOptions: options] autorelease];
setGlobalRouterObject(instance); 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];
@@ -112,6 +109,15 @@ void openUrl(NSString* url)
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString: url]]; [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString: url]];
} }
@implementation I2PStatusMenu
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
NSLog(@"item is: %@",item);
return YES;
}
@end
@implementation MenuBarCtrl @implementation MenuBarCtrl
@@ -148,6 +154,8 @@ void openUrl(NSString* url)
- (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem - (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem
{ {
NSLog(@"Clicked startJavaRouterBtnHandler"); NSLog(@"Clicked startJavaRouterBtnHandler");
AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
[appDelegate startupI2PRouter];
} }
- (void) restartJavaRouterBtnHandler: (NSMenuItem *) menuItem - (void) restartJavaRouterBtnHandler: (NSMenuItem *) menuItem
@@ -210,9 +218,9 @@ void openUrl(NSString* url)
[self.menu release]; [self.menu release];
} }
- (NSMenu *)createStatusBarMenu - (I2PStatusMenu *)createStatusBarMenu
{ {
NSMenu *menu = [[NSMenu alloc] init]; I2PStatusMenu *menu = [[I2PStatusMenu alloc] init];
[menu setAutoenablesItems:NO]; [menu setAutoenablesItems:NO];
NSMenuItem *openConsoleI2Pbtn = NSMenuItem *openConsoleI2Pbtn =
@@ -271,10 +279,10 @@ void openUrl(NSString* url)
@implementation AppDelegate @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]); std::string basePath([self.metaInfo.i2pBase UTF8String]);
NSParameterAssert(metaInfo.i2pBase); NSParameterAssert(self.metaInfo.i2pBase);
NSError *error = NULL; NSError *error = NULL;
BOOL success; BOOL success;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@@ -286,10 +294,10 @@ void openUrl(NSString* url)
basearg += basePath; basearg += basePath;
std::string zippath("-Di2p.base.zip="); std::string zippath("-Di2p.base.zip=");
zippath += [metaInfo.zipFile UTF8String]; zippath += [self.metaInfo.zipFile UTF8String];
std::string jarfile("-cp "); std::string jarfile("-cp ");
jarfile += [metaInfo.jarFile UTF8String]; jarfile += [self.metaInfo.jarFile UTF8String];
// Create directory // Create directory
mkdir(basePath.c_str(), S_IRUSR | S_IWUSR | S_IXUSR); 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"); cli.push_back("net.i2p.launchers.BaseExtractor");
//auto charCli = map(cli, [](std::string str){ return str.c_str(); }); //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; }); for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; });
NSLog(@"Trying cmd: %@", [NSString stringWithUTF8String:execStr.c_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]); std::string basePath([self.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 // Get paths
NSBundle *launcherBundle = [NSBundle mainBundle]; NSBundle *launcherBundle = [NSBundle mainBundle];
auto jarList = buildClassPath(basePath); auto jarList = buildClassPath(basePath);
std::string classpathStrHead = "-classpath"; std::string classpathStrHead = "-classpath";
std::string classpathStr = ""; std::string classpathStr = "";
@@ -371,12 +375,12 @@ void openUrl(NSString* url)
argList.push_back([NSString stringWithUTF8String:classpathStrHead.c_str()]); argList.push_back([NSString stringWithUTF8String:classpathStrHead.c_str()]);
argList.push_back([NSString stringWithUTF8String:classpathStr.c_str()]); argList.push_back([NSString stringWithUTF8String:classpathStr.c_str()]);
argList.push_back(@"net.i2p.router.Router"); 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); sendUserNotification(APP_IDSTR, @"I2P Router is starting up!", self.contentImage);
auto nsJavaBin = metaInfo.javaBinary; auto nsJavaBin = self.metaInfo.javaBinary;
auto nsBasePath = metaInfo.i2pBase; auto nsBasePath = self.metaInfo.i2pBase;
NSArray* arrArguments = [NSArray arrayWithObjects:&argList[0] count:argList.size()]; NSArray* arrArguments = [NSArray arrayWithObjects:&argList[0] count:argList.size()];
startupRouter(nsJavaBin, arrArguments, nsBasePath); startupRouter(nsJavaBin, arrArguments, nsBasePath);
//if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]); //if (self.enableVerboseLogging) NSLog(@"Defaults: %@", [pref dictionaryRepresentation]);
@@ -434,7 +438,8 @@ void openUrl(NSString* url)
@"lastI2PVersion" : (NSString *)CFSTR(DEF_I2P_VERSION), @"lastI2PVersion" : (NSString *)CFSTR(DEF_I2P_VERSION),
@"enableLogging": @true, @"enableLogging": @true,
@"enableVerboseLogging": @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); 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 // In case we are unbundled, make us a proper UI application
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory]; [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
[NSApp activateIgnoringOtherApps:YES]; [NSApp activateIgnoringOtherApps:YES];
//auto prefArray = CFPreferencesCopyKeyList(CFAPPDOMAIN, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
//CFShow(prefArray);
auto javaHomePref = [self.userPreferences stringForKey:@"javaHome"]; auto javaHomePref = [self.userPreferences stringForKey:@"javaHome"];
if (self.enableVerboseLogging) NSLog(@"Java home from preferences: %@", javaHomePref); if (self.enableVerboseLogging) NSLog(@"Java home from preferences: %@", javaHomePref);
// This is the only GUI the user experience on a regular basis. // This is the only GUI the user experience on a regular basis.
self.menuBarCtrl = [[MenuBarCtrl alloc] init]; self.menuBarCtrl = [[MenuBarCtrl alloc] init];
@@ -482,13 +484,8 @@ void openUrl(NSString* url)
NSLog(@"We should have started the statusbar object by now..."); NSLog(@"We should have started the statusbar object by now...");
// Figure out base directory std::string i2pBaseDir(getDefaultBaseDir());
const char* pathFromHome = "/Users/%s/Library/I2P"; //if (self.enableVerboseLogging) printf("Home directory is: %s\n", buffer);
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:)]; //[statusBarButton setAction:@selector(itemClicked:)];
@@ -499,57 +496,57 @@ void openUrl(NSString* url)
self.menuBarCtrl.enableLogging = self.enableLogging; self.menuBarCtrl.enableLogging = self.enableLogging;
self.menuBarCtrl.enableVerboseLogging = self.enableVerboseLogging; self.menuBarCtrl.enableVerboseLogging = self.enableVerboseLogging;
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]); if (self.enableVerboseLogging) NSLog(@"processinfo %@", [[NSProcessInfo processInfo] arguments]);
auto getJavaHomeLambda = [&pref,&self]() -> std::string { auto getJavaBin = [&pref,&self]() -> std::string {
NSString* val = @""; // Get Java home
val = [pref stringForKey:@"javaHome"]; NSString* val = @"";
if (val == NULL) val = @""; val = [pref stringForKey:@"javaHome"];
if (self.enableVerboseLogging) NSLog(@"Javahome: %@", val); if (val == NULL) val = @"";
return std::string([val UTF8String]);; if (self.enableVerboseLogging) NSLog(@"Javahome: %@", val);
}; auto javaHome = std::string([val UTF8String]);
auto getJavaBin = [&getJavaHomeLambda]() -> std::string {
// Get Java home
auto javaHome = getJavaHomeLambda();
trim(javaHome); // Trim to remove endline trim(javaHome); // Trim to remove endline
auto javaBin = std::string(javaHome); auto javaBin = std::string(javaHome);
javaBin += "/bin/java"; // Append java binary to path. javaBin += "/bin/java"; // Append java binary to path.
return javaBin; return javaBin;
}; };
auto buildClassPath = [](std::string basePath) -> std::vector<std::string> {
return globVector(basePath+std::string("/lib/*.jar"));
};
self.metaInfo = [[ExtractMetaInfo alloc] init];
auto metaInfo = [ExtractMetaInfo alloc]; self.metaInfo.i2pBase = [NSString stringWithUTF8String:i2pBaseDir.c_str()];
metaInfo.i2pBase = [NSString stringWithUTF8String:buffer]; self.metaInfo.javaBinary = [NSString stringWithUTF8String:getJavaBin().c_str()];
metaInfo.javaBinary = [NSString stringWithUTF8String:getJavaBin().c_str()]; self.metaInfo.jarFile = [launcherBundle pathForResource:@"launcher" ofType:@"jar"];
metaInfo.jarFile = [launcherBundle pathForResource:@"launcher" ofType:@"jar"]; self.metaInfo.zipFile = [launcherBundle pathForResource:@"base" ofType:@"zip"];
metaInfo.zipFile = [launcherBundle pathForResource:@"base" ofType:@"zip"];
std::string basearg("-Di2p.dir.base="); std::string basearg("-Di2p.dir.base=");
basearg += i2pBaseDir; basearg += i2pBaseDir;
std::string jarfile("-cp "); std::string jarfile("-cp ");
jarfile += [metaInfo.zipFile UTF8String]; jarfile += [self.metaInfo.zipFile UTF8String];
struct stat sb; 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. // I2P is not extracted.
if (self.enableVerboseLogging) NSLog(@"I2P Directory don't exists!"); 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; //__typeof__(self) strongSelf = weakSelf;
//if (strongSelf == nil) return; //if (strongSelf == nil) return;
[self startupI2PRouter:metaInfo]; [self startupI2PRouter];
}]; }];
} else { } else {
if (self.enableVerboseLogging) NSLog(@"I2P directory found!"); if (self.enableVerboseLogging) NSLog(@"I2P directory found!");
[self startupI2PRouter:metaInfo]; [self startupI2PRouter];
} }
} }

View File

@@ -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;
}