forked from I2P_Developers/i2p.i2p
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:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
/**
|
||||
*
|
||||
* This is a class representing the "image" in the systray.
|
||||
*
|
||||
*
|
||||
* **/
|
||||
@class StatusItemButton;
|
||||
|
||||
@protocol StatusItemButtonDelegate <NSObject>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
/*
|
||||
NSLog(@"Arguments: %@", [NSString stringWithUTF8String:arguments.c_str()]);
|
||||
auto launchLambda = [](JavaRunner *javaRun) {
|
||||
javaRun->javaProcess->start_process();
|
||||
auto pid = javaRun->javaProcess->pid();
|
||||
std::cout << "I2P Router process id = " << pid << std::endl;
|
||||
|
||||
// Blocking
|
||||
javaRun->javaProcess->wait();
|
||||
};
|
||||
auto callbackAfterExit = [](){
|
||||
printf("Callback after exit\n");
|
||||
};
|
||||
NSLog(@"Still fine!");
|
||||
|
||||
setGlobalRouterObject(new JavaRunner{ javaBin, arguments, i2pBaseDir, std::move(launchLambda), std::move(callbackAfterExit) });
|
||||
|
||||
NSLog(@"Still fine!");
|
||||
return std::async(std::launch::async, [&]{
|
||||
getGlobalRouterObject().value()->execute();
|
||||
return 0;
|
||||
});
|
||||
*/
|
||||
//CFShow(arguments);
|
||||
|
||||
@try {
|
||||
RTaskOptions* options = [RTaskOptions alloc];
|
||||
options.binPath = javaBin;
|
||||
options.arguments = arguments;
|
||||
options.i2pBaseDir = i2pBaseDir;
|
||||
auto instance = [[[RouterTask alloc] initWithOptions: options] autorelease];
|
||||
auto 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 (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 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();
|
||||
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];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
59
launchers/macosx/obj-cpp/portcheck.h
Normal file
59
launchers/macosx/obj-cpp/portcheck.h
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user