From f76874ac19104ba519a6e59e945832fa1519ad61 Mon Sep 17 00:00:00 2001
From: meeh <meeh@mail.i2p>
Date: Tue, 18 Sep 2018 15:39:32 +0000
Subject: [PATCH] Adding XCode workspace & Xcode project, and some files
 missing from last commit.

Please note that Xcode project embedds the packing script (meaning it runs "ant" - zip files, and moves it to bundle)
---
 launchers/macosx/.vscode/settings.json        |   36 +
 launchers/macosx/AppDelegate.h                |  148 +--
 .../I2PLauncher.xcodeproj/project.pbxproj     |  569 +++++++++
 .../contents.xcworkspacedata                  |    7 +
 .../xcshareddata/IDEWorkspaceChecks.plist     |    8 +
 .../contents.xcworkspacedata                  |    7 +
 .../xcshareddata/IDEWorkspaceChecks.plist     |    8 +
 launchers/macosx/Info.plist                   |   47 +
 launchers/macosx/JavaHelper.h                 |   38 +-
 launchers/macosx/RouterTask.h                 |   83 +-
 launchers/macosx/RouterTask.mm                |   59 +-
 launchers/macosx/dmgconfig.py                 |  246 ++++
 launchers/macosx/include/PidWatcher.h         |    4 +-
 launchers/macosx/include/optional.h           | 1066 +++++++++++++++++
 launchers/macosx/include/portcheck.h          |   87 +-
 launchers/macosx/include/strutil.hpp          |    2 +-
 launchers/macosx/main.mm                      |  385 ++----
 launchers/macosx/requirements.txt             |    1 +
 18 files changed, 2283 insertions(+), 518 deletions(-)
 create mode 100644 launchers/macosx/.vscode/settings.json
 create mode 100644 launchers/macosx/I2PLauncher.xcodeproj/project.pbxproj
 create mode 100644 launchers/macosx/I2PLauncher.xcodeproj/project.xcworkspace/contents.xcworkspacedata
 create mode 100644 launchers/macosx/I2PLauncher.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
 create mode 100644 launchers/macosx/I2PLauncher.xcworkspace/contents.xcworkspacedata
 create mode 100644 launchers/macosx/I2PLauncher.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
 create mode 100644 launchers/macosx/Info.plist
 create mode 100644 launchers/macosx/dmgconfig.py
 create mode 100644 launchers/macosx/include/optional.h
 create mode 100644 launchers/macosx/requirements.txt

diff --git a/launchers/macosx/.vscode/settings.json b/launchers/macosx/.vscode/settings.json
new file mode 100644
index 0000000000..0245bc1183
--- /dev/null
+++ b/launchers/macosx/.vscode/settings.json
@@ -0,0 +1,36 @@
+{
+  "files.associations": {
+    "*.jsm": "javascript",
+    "*.grd": "xml",
+    "*.plist": "xml",
+    "*.jxa": "javascript",
+    "*.gni": "javascript",
+    "*.gn": "javascript",
+    "type_traits": "cpp",
+    "__config": "cpp",
+    "__nullptr": "cpp",
+    "cstddef": "cpp",
+    "exception": "cpp",
+    "initializer_list": "cpp",
+    "new": "cpp",
+    "stdexcept": "cpp",
+    "typeinfo": "cpp",
+    "algorithm": "cpp",
+    "ios": "cpp",
+    "iosfwd": "cpp",
+    "__split_buffer": "cpp",
+    "list": "cpp",
+    "string": "cpp",
+    "vector": "cpp",
+    "iterator": "cpp",
+    "optional": "cpp",
+    "memory": "cpp",
+    "map": "cpp",
+    "__mutex_base": "cpp",
+    "mutex": "cpp",
+    "functional": "cpp",
+    "__functional_03": "cpp",
+    "__string": "cpp",
+    "system_error": "cpp"
+  }
+}
\ No newline at end of file
diff --git a/launchers/macosx/AppDelegate.h b/launchers/macosx/AppDelegate.h
index d5592a3368..431ed3b2a3 100644
--- a/launchers/macosx/AppDelegate.h
+++ b/launchers/macosx/AppDelegate.h
@@ -1,47 +1,33 @@
 #ifndef __APPDELEGATE_H__
 #define __APPDELEGATE_H__
 
-#include <algorithm>
-#include <string>
-#include <memory>
+
+#include <string.h>
+#include <memory.h>
 
 #include <Cocoa/Cocoa.h>
 
+
 #include "RouterTask.h"
-#include "StatusItemButton.h"
 #include "JavaHelper.h"
-#include "neither/maybe.hpp"
-#include "optional.hpp"
-#include "subprocess.hpp"
-#include <glob.h>
-#include <vector>
 
 
-#define DEF_I2P_VERSION "0.9.35"
+#define DEF_I2P_VERSION "0.9.36"
 #define APPDOMAIN "net.i2p.launcher"
 #define NSAPPDOMAIN @APPDOMAIN
 #define CFAPPDOMAIN CFSTR(APPDOMAIN)
 #define APP_IDSTR @"I2P Launcher"
 
+@class SwiftMainDelegate;
 
-using namespace neither;
-
-@class ExtractMetaInfo;
-using maybeAnRouterRunner = std::experimental::optional<I2PRouterTask*>;
+@protocol SwiftMainDelegateProto
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
+@end
 
-std::vector<std::string> buildClassPath(std::string basePath);
 
-extern JvmListSharedPtr gRawJvmList;
+@class ExtractMetaInfo;
 
-// DO NOT ACCESS THIS GLOBAL VARIABLE DIRECTLY.
-static std::mutex globalRouterStatusMutex;
-static maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{};
-static bool isRuterRunning = false;
 
-maybeAnRouterRunner getGlobalRouterObject();
-void setGlobalRouterObject(I2PRouterTask* newRouter);
-bool getGlobalRouterIsRunning();
-void setGlobalRouterIsRunning(bool running);
 
 @interface ExtractMetaInfo : NSObject
 @property (copy) NSString* i2pBase;
@@ -49,96 +35,74 @@ void setGlobalRouterIsRunning(bool running);
 @property (copy) NSString* zipFile;
 @property (copy) NSString* jarFile;
 @end
-
-@class I2PStatusMenu;
-@interface I2PStatusMenu : NSMenu
-- (BOOL)validateMenuItem:(NSMenuItem *)menuItem;
-@end
+#ifdef __cplusplus
+#include "JavaHelper.h"
 
 inline void sendUserNotification(NSString* title, NSString* informativeText, NSImage* contentImage = NULL, bool makeSound = false) {
   NSUserNotification *userNotification = [[[NSUserNotification alloc] init] autorelease];
-
+  
   userNotification.title = title;
   userNotification.informativeText = informativeText;
-  if (contentImage != NULL) userNotification.contentImage = contentImage;
+  NSBundle *launcherBundle = [NSBundle mainBundle];
+  auto resPath = [launcherBundle resourcePath];
+  auto stdResPath = std::string([resPath UTF8String]);
+  stdResPath += "/AppImage.png";
+  auto nsString = [[NSString alloc] initWithUTF8String:(const char*)stdResPath.c_str()];
+  NSImage *appImage = [[NSImage alloc] initWithContentsOfFile:nsString];
+  userNotification.contentImage = appImage;
   if (makeSound) userNotification.soundName = NSUserNotificationDefaultSoundName;
-
+  
   [[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification:userNotification];
 };
 
-inline std::vector<std::string> globVector(const std::string& pattern){
-    glob_t glob_result;
-    glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
-    std::vector<std::string> files;
-    for(unsigned int i=0;i<glob_result.gl_pathc;++i){
-        files.push_back(std::string(glob_result.gl_pathv[i]));
-    }
-    globfree(&glob_result);
-    return files;
-}
+using maybeAnRouterRunner = I2PRouterTask*;
 
-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;
-}
+std::vector<std::string> buildClassPath(std::string basePath);
 
-@interface MenuBarCtrl : NSObject <StatusItemButtonDelegate, NSMenuDelegate>
-@property BOOL enableLogging;
-@property BOOL enableVerboseLogging;
-@property (strong) I2PStatusMenu *menu;
-@property (strong) StatusItemButton* statusBarButton;
-@property (strong) NSUserDefaults *userPreferences;
-@property (strong, nonatomic) NSImage * image;
-@property (strong, nonatomic) NSStatusItem *statusItem;
-// Event handlers
-- (void) statusItemButtonLeftClick: (StatusItemButton *) button;
-- (void) statusItemButtonRightClick: (StatusItemButton *) button;
-- (void) statusBarImageBtnClicked;
-- (void) btnPressedAction:(id)sender;
-- (void) menuWillOpen:(I2PStatusMenu *)menu;
-
-- (void) openRouterConsoleBtnHandler: (NSMenuItem *) menuItem;
-- (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem;
-- (void) restartJavaRouterBtnHandler: (NSMenuItem *) menuItem;
-- (void) stopJavaRouterBtnHandler: (NSMenuItem *) menuItem;
-- (void) quitWrapperBtnHandler: (NSMenuItem *) menuItem;
-// Methods
-- (MenuBarCtrl *) init;
-- (void) dealloc;
-- (I2PStatusMenu *) createStatusBarMenu;
-@end
+extern JvmListSharedPtr gRawJvmList;
 
-@protocol MenuBarCtrlDelegate
-- (void) menuBarCtrlStatusChanged: (BOOL) active;
-@end
+// DO NOT ACCESS THIS GLOBAL VARIABLE DIRECTLY.
+static std::mutex globalRouterStatusMutex;
+static maybeAnRouterRunner globalRouterStatus = maybeAnRouterRunner{};
+static bool isRuterRunning = false;
+
+maybeAnRouterRunner getGlobalRouterObject();
+void setGlobalRouterObject(I2PRouterTask* newRouter);
+bool getGlobalRouterIsRunning();
+void setGlobalRouterIsRunning(bool running);
+
+#include "SBridge.h"
+
+#endif
+
+@class MenuBarCtrl;
 
 @interface AppDelegate : NSObject <NSUserNotificationCenterDelegate, NSApplicationDelegate> {
 @public
   //NSImageView *imageCell;
 }
-@property (strong) MenuBarCtrl *menuBarCtrl;
-@property (strong) NSUserDefaults *userPreferences;
 @property BOOL enableLogging;
 @property BOOL enableVerboseLogging;
-@property ExtractMetaInfo *metaInfo;
+@property (assign) NSUserDefaults *userPreferences;
+@property (assign) ExtractMetaInfo *metaInfo;
 @property (copy) NSImage *contentImage NS_AVAILABLE(10_9, NA);
-- (void)extractI2PBaseDir:(void(^)(BOOL success, NSError *error))completion;
-- (void)startupI2PRouter;
-- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
-- (void)applicationWillTerminate:(NSNotification *)aNotification;
-- (void)setApplicationDefaultPreferences;
-- (void)userChooseJavaHome;
-- (AppDelegate *)initWithArgc:(int)argc argv:(const char **)argv;
-- (NSString *)userSelectJavaHome:(JvmListPtr)rawJvmList;
-- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
+
+- (void) extractI2PBaseDir:(void(^)(BOOL success, NSError *error))completion;
+- (void) awakeFromNib;
+- (void) startupI2PRouter;
+- (void) applicationDidFinishLaunching:(NSNotification *)aNotification;
+- (void) applicationWillTerminate:(NSNotification *)aNotification;
+- (void) setApplicationDefaultPreferences;
+- (void) userChooseJavaHome;
+- (AppDelegate *) initWithArgc:(int)argc argv:(const char **)argv;
+#ifdef __cplusplus
+- (NSString *) userSelectJavaHome:(JvmListPtr)rawJvmList;
+#endif
+- (BOOL) userNotificationCenter:(NSUserNotificationCenter *)center
                                shouldPresentNotification:(NSUserNotification *)notification;
 @end
 
 
+
+
 #endif
diff --git a/launchers/macosx/I2PLauncher.xcodeproj/project.pbxproj b/launchers/macosx/I2PLauncher.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..3cd99bf9ad
--- /dev/null
+++ b/launchers/macosx/I2PLauncher.xcodeproj/project.pbxproj
@@ -0,0 +1,569 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 50;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		BF07789721506C810014EB07 /* Storyboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BF07789621506C810014EB07 /* Storyboard.storyboard */; };
+		BF07789E21506D2B0014EB07 /* PopoverViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF07789C21506D2B0014EB07 /* PopoverViewController.swift */; };
+		BF1EFA3A215140E60014EB07 /* SBridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = BF1EFA39215140E60014EB07 /* SBridge.mm */; };
+		BF1EFA40215141110014EB07 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = BF1EFA3D215141100014EB07 /* main.mm */; };
+		BF1EFA41215141110014EB07 /* RouterTask.mm in Sources */ = {isa = PBXBuildFile; fileRef = BF1EFA3E215141100014EB07 /* RouterTask.mm */; };
+		BF1EFA47215141640014EB07 /* base.zip in Resources */ = {isa = PBXBuildFile; fileRef = BF1EFA44215141630014EB07 /* base.zip */; };
+		BF1EFA48215141640014EB07 /* ItoopieTransparent.png in Resources */ = {isa = PBXBuildFile; fileRef = BF1EFA45215141640014EB07 /* ItoopieTransparent.png */; };
+		BF1EFA4A215141CD0014EB07 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF5061932113C6ED0014EB07 /* NetworkExtension.framework */; };
+		BF5061702113C48E0014EB07 /* I2PLauncher.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = BF50616E2113C48E0014EB07 /* I2PLauncher.xcdatamodeld */; };
+		BF5061722113C4900014EB07 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BF5061712113C4900014EB07 /* Assets.xcassets */; };
+		BF5061752113C4900014EB07 /* UserInterfaces.xib in Resources */ = {isa = PBXBuildFile; fileRef = BF5061732113C4900014EB07 /* UserInterfaces.xib */; };
+		BF5061962113C84E0014EB07 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF5061952113C84E0014EB07 /* Cocoa.framework */; };
+		BF5315072150C55B0014EB07 /* RouterRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5315062150C55B0014EB07 /* RouterRunner.swift */; };
+		BF5315092150C6760014EB07 /* RouterDeployer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5315082150C6760014EB07 /* RouterDeployer.swift */; };
+		BF53150B2150C6E80014EB07 /* I2PSubprocess.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF53150A2150C6E80014EB07 /* I2PSubprocess.swift */; };
+		BF53150D2150CE310014EB07 /* DateTimeUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF53150C2150CE310014EB07 /* DateTimeUtils.swift */; };
+		BF5315132150EB510014EB07 /* RouterProcessStatus+ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5315122150EB510014EB07 /* RouterProcessStatus+ObjectiveC.swift */; };
+		BF531515215105B40014EB07 /* LogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF531514215105B40014EB07 /* LogViewController.swift */; };
+		BF7506CB21509CFD0014EB07 /* RouterProcessStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF7506CA21509CFD0014EB07 /* RouterProcessStatus.swift */; };
+		BFBDCAE9215040670014EB07 /* Subprocess.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBDCAE8215040670014EB07 /* Subprocess.swift */; };
+		BFBDCAEB215041630014EB07 /* TaskPipeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBDCAEA215041630014EB07 /* TaskPipeline.swift */; };
+		BFBDCAED215041C10014EB07 /* Subprocess+CompactAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBDCAEC215041C10014EB07 /* Subprocess+CompactAPI.swift */; };
+		BFBDCAEF215041E30014EB07 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBDCAEE215041E30014EB07 /* Error.swift */; };
+		BFBDCAF12150420C0014EB07 /* ExecutionResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBDCAF02150420C0014EB07 /* ExecutionResult.swift */; };
+		BFBDCAF4215042670014EB07 /* AppleStuffExceptionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = BFBDCAF3215042670014EB07 /* AppleStuffExceptionHandler.m */; };
+		BFBDCAF62150428D0014EB07 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBDCAF52150428D0014EB07 /* StringExtensions.swift */; };
+		BFBDCAF8215047FE0014EB07 /* ArrayExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBDCAF7215047FE0014EB07 /* ArrayExtensions.swift */; };
+		BFBDCAFA215050810014EB07 /* ReflectionFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBDCAF9215050810014EB07 /* ReflectionFunctions.swift */; };
+		BFBDCAFE2150567D0014EB07 /* SwiftMainDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBDCAFD2150567D0014EB07 /* SwiftMainDelegate.swift */; };
+		BFBDCB0021505BEE0014EB07 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFBDCAFF21505BED0014EB07 /* AppKit.framework */; };
+		BFBDCB02215060190014EB07 /* DetectJava.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBDCB01215060190014EB07 /* DetectJava.swift */; };
+		BFBDCB04215060970014EB07 /* StatusBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBDCB03215060970014EB07 /* StatusBarController.swift */; };
+		BFF4581C213C48EA0014EB07 /* EventMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF4581B213C48EA0014EB07 /* EventMonitor.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		BF07789621506C810014EB07 /* Storyboard.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Storyboard.storyboard; sourceTree = "<group>"; };
+		BF07789C21506D2B0014EB07 /* PopoverViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopoverViewController.swift; sourceTree = "<group>"; };
+		BF1EFA38215140E60014EB07 /* SBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBridge.h; sourceTree = SOURCE_ROOT; };
+		BF1EFA39215140E60014EB07 /* SBridge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SBridge.mm; sourceTree = SOURCE_ROOT; };
+		BF1EFA3B215141100014EB07 /* RouterTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RouterTask.h; sourceTree = SOURCE_ROOT; };
+		BF1EFA3C215141100014EB07 /* JavaHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaHelper.h; sourceTree = SOURCE_ROOT; };
+		BF1EFA3D215141100014EB07 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = SOURCE_ROOT; };
+		BF1EFA3E215141100014EB07 /* RouterTask.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RouterTask.mm; sourceTree = SOURCE_ROOT; };
+		BF1EFA3F215141110014EB07 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = SOURCE_ROOT; };
+		BF1EFA42215141220014EB07 /* include */ = {isa = PBXFileReference; lastKnownFileType = folder; path = include; sourceTree = SOURCE_ROOT; };
+		BF1EFA44215141630014EB07 /* base.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = base.zip; sourceTree = "<group>"; };
+		BF1EFA45215141640014EB07 /* ItoopieTransparent.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ItoopieTransparent.png; sourceTree = "<group>"; };
+		BF1EFA46215141640014EB07 /* launcher.jar */ = {isa = PBXFileReference; lastKnownFileType = archive.jar; path = launcher.jar; sourceTree = "<group>"; };
+		BF5061682113C48E0014EB07 /* I2PLauncher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = I2PLauncher.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		BF50616F2113C48E0014EB07 /* I2PLauncher.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = I2PLauncher.xcdatamodel; sourceTree = "<group>"; };
+		BF5061712113C4900014EB07 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		BF5061742113C4900014EB07 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UserInterfaces.xib; sourceTree = "<group>"; };
+		BF5061762113C4900014EB07 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		BF5061792113C4900014EB07 /* I2PLauncher.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = I2PLauncher.entitlements; sourceTree = "<group>"; };
+		BF5061932113C6ED0014EB07 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; };
+		BF5061952113C84E0014EB07 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+		BF5315062150C55B0014EB07 /* RouterRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterRunner.swift; sourceTree = "<group>"; };
+		BF5315082150C6760014EB07 /* RouterDeployer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterDeployer.swift; sourceTree = "<group>"; };
+		BF53150A2150C6E80014EB07 /* I2PSubprocess.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = I2PSubprocess.swift; sourceTree = "<group>"; };
+		BF53150C2150CE310014EB07 /* DateTimeUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTimeUtils.swift; sourceTree = "<group>"; };
+		BF5315122150EB510014EB07 /* RouterProcessStatus+ObjectiveC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RouterProcessStatus+ObjectiveC.swift"; sourceTree = "<group>"; };
+		BF531514215105B40014EB07 /* LogViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogViewController.swift; sourceTree = "<group>"; };
+		BF7506CA21509CFD0014EB07 /* RouterProcessStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterProcessStatus.swift; sourceTree = "<group>"; };
+		BFBDCAE8215040670014EB07 /* Subprocess.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Subprocess.swift; sourceTree = "<group>"; };
+		BFBDCAEA215041630014EB07 /* TaskPipeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskPipeline.swift; sourceTree = "<group>"; };
+		BFBDCAEC215041C10014EB07 /* Subprocess+CompactAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Subprocess+CompactAPI.swift"; sourceTree = "<group>"; };
+		BFBDCAEE215041E30014EB07 /* Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
+		BFBDCAF02150420C0014EB07 /* ExecutionResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExecutionResult.swift; sourceTree = "<group>"; };
+		BFBDCAF22150422C0014EB07 /* AppleStuffExceptionHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleStuffExceptionHandler.h; sourceTree = "<group>"; };
+		BFBDCAF3215042670014EB07 /* AppleStuffExceptionHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppleStuffExceptionHandler.m; sourceTree = "<group>"; };
+		BFBDCAF52150428D0014EB07 /* StringExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = "<group>"; };
+		BFBDCAF7215047FE0014EB07 /* ArrayExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrayExtensions.swift; sourceTree = "<group>"; };
+		BFBDCAF9215050810014EB07 /* ReflectionFunctions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReflectionFunctions.swift; sourceTree = "<group>"; };
+		BFBDCAFD2150567D0014EB07 /* SwiftMainDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftMainDelegate.swift; sourceTree = "<group>"; };
+		BFBDCAFF21505BED0014EB07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
+		BFBDCB01215060190014EB07 /* DetectJava.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetectJava.swift; sourceTree = "<group>"; };
+		BFBDCB03215060970014EB07 /* StatusBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBarController.swift; sourceTree = "<group>"; };
+		BFF45818213C428E0014EB07 /* I2PLauncher-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "I2PLauncher-Bridging-Header.h"; sourceTree = "<group>"; };
+		BFF4581B213C48EA0014EB07 /* EventMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventMonitor.swift; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		BF5061652113C48E0014EB07 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				BF1EFA4A215141CD0014EB07 /* NetworkExtension.framework in Frameworks */,
+				BFBDCB0021505BEE0014EB07 /* AppKit.framework in Frameworks */,
+				BF5061962113C84E0014EB07 /* Cocoa.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		BF0778A0215080910014EB07 /* subprocesses */ = {
+			isa = PBXGroup;
+			children = (
+				BFBDCAE8215040670014EB07 /* Subprocess.swift */,
+				BFBDCAEA215041630014EB07 /* TaskPipeline.swift */,
+				BFBDCAEC215041C10014EB07 /* Subprocess+CompactAPI.swift */,
+				BFBDCAEE215041E30014EB07 /* Error.swift */,
+				BFBDCAF02150420C0014EB07 /* ExecutionResult.swift */,
+				BFBDCAF22150422C0014EB07 /* AppleStuffExceptionHandler.h */,
+				BFBDCAF3215042670014EB07 /* AppleStuffExceptionHandler.m */,
+			);
+			path = subprocesses;
+			sourceTree = "<group>";
+		};
+		BF0778A12150897A0014EB07 /* userinterface */ = {
+			isa = PBXGroup;
+			children = (
+				BF07789C21506D2B0014EB07 /* PopoverViewController.swift */,
+				BFBDCB03215060970014EB07 /* StatusBarController.swift */,
+				BF531514215105B40014EB07 /* LogViewController.swift */,
+			);
+			path = userinterface;
+			sourceTree = "<group>";
+		};
+		BF50615F2113C48E0014EB07 = {
+			isa = PBXGroup;
+			children = (
+				BF1EFA44215141630014EB07 /* base.zip */,
+				BF1EFA45215141640014EB07 /* ItoopieTransparent.png */,
+				BF1EFA46215141640014EB07 /* launcher.jar */,
+				BF50616A2113C48E0014EB07 /* I2PLauncher */,
+				BF5061692113C48E0014EB07 /* Products */,
+				BF5061922113C6ED0014EB07 /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		BF5061692113C48E0014EB07 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				BF5061682113C48E0014EB07 /* I2PLauncher.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		BF50616A2113C48E0014EB07 /* I2PLauncher */ = {
+			isa = PBXGroup;
+			children = (
+				BF1EFA42215141220014EB07 /* include */,
+				BF1EFA3F215141110014EB07 /* AppDelegate.h */,
+				BF1EFA3C215141100014EB07 /* JavaHelper.h */,
+				BF1EFA3D215141100014EB07 /* main.mm */,
+				BF1EFA3B215141100014EB07 /* RouterTask.h */,
+				BF1EFA3E215141100014EB07 /* RouterTask.mm */,
+				BF1EFA38215140E60014EB07 /* SBridge.h */,
+				BF1EFA39215140E60014EB07 /* SBridge.mm */,
+				BF5315052150C4AB0014EB07 /* Utils */,
+				BF5315042150C4860014EB07 /* routermgmt */,
+				BF0778A12150897A0014EB07 /* userinterface */,
+				BF0778A0215080910014EB07 /* subprocesses */,
+				BF5061712113C4900014EB07 /* Assets.xcassets */,
+				BF5061732113C4900014EB07 /* UserInterfaces.xib */,
+				BF5061762113C4900014EB07 /* Info.plist */,
+				BF5061792113C4900014EB07 /* I2PLauncher.entitlements */,
+				BF50616E2113C48E0014EB07 /* I2PLauncher.xcdatamodeld */,
+				BFF45818213C428E0014EB07 /* I2PLauncher-Bridging-Header.h */,
+				BF07789621506C810014EB07 /* Storyboard.storyboard */,
+				BFBDCAFD2150567D0014EB07 /* SwiftMainDelegate.swift */,
+			);
+			path = I2PLauncher;
+			sourceTree = "<group>";
+		};
+		BF5061922113C6ED0014EB07 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				BFBDCAFF21505BED0014EB07 /* AppKit.framework */,
+				BF5061952113C84E0014EB07 /* Cocoa.framework */,
+				BF5061932113C6ED0014EB07 /* NetworkExtension.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		BF5315042150C4860014EB07 /* routermgmt */ = {
+			isa = PBXGroup;
+			children = (
+				BFBDCB01215060190014EB07 /* DetectJava.swift */,
+				BF7506CA21509CFD0014EB07 /* RouterProcessStatus.swift */,
+				BF5315122150EB510014EB07 /* RouterProcessStatus+ObjectiveC.swift */,
+				BF5315062150C55B0014EB07 /* RouterRunner.swift */,
+				BF5315082150C6760014EB07 /* RouterDeployer.swift */,
+				BF53150A2150C6E80014EB07 /* I2PSubprocess.swift */,
+			);
+			path = routermgmt;
+			sourceTree = "<group>";
+		};
+		BF5315052150C4AB0014EB07 /* Utils */ = {
+			isa = PBXGroup;
+			children = (
+				BFF4581B213C48EA0014EB07 /* EventMonitor.swift */,
+				BFBDCAF9215050810014EB07 /* ReflectionFunctions.swift */,
+				BFBDCAF52150428D0014EB07 /* StringExtensions.swift */,
+				BFBDCAF7215047FE0014EB07 /* ArrayExtensions.swift */,
+				BF53150C2150CE310014EB07 /* DateTimeUtils.swift */,
+			);
+			path = Utils;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		BF5061672113C48E0014EB07 /* I2PLauncher */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = BF50617C2113C4900014EB07 /* Build configuration list for PBXNativeTarget "I2PLauncher" */;
+			buildPhases = (
+				BF5061642113C48E0014EB07 /* Sources */,
+				BF5061652113C48E0014EB07 /* Frameworks */,
+				BF1EFA4B215142030014EB07 /* ShellScript */,
+				BF5061662113C48E0014EB07 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = I2PLauncher;
+			productName = I2PLauncher;
+			productReference = BF5061682113C48E0014EB07 /* I2PLauncher.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		BF5061602113C48E0014EB07 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0940;
+				ORGANIZATIONNAME = "The I2P Project";
+				TargetAttributes = {
+					BF5061672113C48E0014EB07 = {
+						CreatedOnToolsVersion = 9.4.1;
+						LastSwiftMigration = 0940;
+						SystemCapabilities = {
+							com.apple.NetworkExtensions = {
+								enabled = 1;
+							};
+							com.apple.Sandbox = {
+								enabled = 0;
+							};
+						};
+					};
+				};
+			};
+			buildConfigurationList = BF5061632113C48E0014EB07 /* Build configuration list for PBXProject "I2PLauncher" */;
+			compatibilityVersion = "Xcode 9.3";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = BF50615F2113C48E0014EB07;
+			productRefGroup = BF5061692113C48E0014EB07 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				BF5061672113C48E0014EB07 /* I2PLauncher */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		BF5061662113C48E0014EB07 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				BF07789721506C810014EB07 /* Storyboard.storyboard in Resources */,
+				BF5061722113C4900014EB07 /* Assets.xcassets in Resources */,
+				BF5061752113C4900014EB07 /* UserInterfaces.xib in Resources */,
+				BF1EFA48215141640014EB07 /* ItoopieTransparent.png in Resources */,
+				BF1EFA47215141640014EB07 /* base.zip in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		BF1EFA4B215142030014EB07 /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "# Run from launchers/macosx\nexport BUILDDIR=$(pwd)\ncd ../..\nant preppkg-osx\ncd pkg-temp\nrm -f ../base.zip\nzip -r7 ../base.zip *\ncp ../base.zip $BUILDDIR\ncd $BUILDDIR\n\n\n\n";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		BF5061642113C48E0014EB07 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				BFBDCB04215060970014EB07 /* StatusBarController.swift in Sources */,
+				BFBDCAF8215047FE0014EB07 /* ArrayExtensions.swift in Sources */,
+				BF5315072150C55B0014EB07 /* RouterRunner.swift in Sources */,
+				BFBDCAF12150420C0014EB07 /* ExecutionResult.swift in Sources */,
+				BF5315092150C6760014EB07 /* RouterDeployer.swift in Sources */,
+				BFBDCAEF215041E30014EB07 /* Error.swift in Sources */,
+				BF1EFA41215141110014EB07 /* RouterTask.mm in Sources */,
+				BF7506CB21509CFD0014EB07 /* RouterProcessStatus.swift in Sources */,
+				BFBDCAE9215040670014EB07 /* Subprocess.swift in Sources */,
+				BFBDCAFA215050810014EB07 /* ReflectionFunctions.swift in Sources */,
+				BFBDCAED215041C10014EB07 /* Subprocess+CompactAPI.swift in Sources */,
+				BFBDCB02215060190014EB07 /* DetectJava.swift in Sources */,
+				BF07789E21506D2B0014EB07 /* PopoverViewController.swift in Sources */,
+				BF1EFA40215141110014EB07 /* main.mm in Sources */,
+				BFBDCAF4215042670014EB07 /* AppleStuffExceptionHandler.m in Sources */,
+				BF531515215105B40014EB07 /* LogViewController.swift in Sources */,
+				BF5315132150EB510014EB07 /* RouterProcessStatus+ObjectiveC.swift in Sources */,
+				BFBDCAFE2150567D0014EB07 /* SwiftMainDelegate.swift in Sources */,
+				BF53150B2150C6E80014EB07 /* I2PSubprocess.swift in Sources */,
+				BFF4581C213C48EA0014EB07 /* EventMonitor.swift in Sources */,
+				BF1EFA3A215140E60014EB07 /* SBridge.mm in Sources */,
+				BFBDCAF62150428D0014EB07 /* StringExtensions.swift in Sources */,
+				BF5061702113C48E0014EB07 /* I2PLauncher.xcdatamodeld in Sources */,
+				BFBDCAEB215041630014EB07 /* TaskPipeline.swift in Sources */,
+				BF53150D2150CE310014EB07 /* DateTimeUtils.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		BF5061732113C4900014EB07 /* UserInterfaces.xib */ = {
+			isa = PBXVariantGroup;
+			children = (
+				BF5061742113C4900014EB07 /* Base */,
+			);
+			name = UserInterfaces.xib;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		BF50617A2113C4900014EB07 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.13;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		BF50617B2113C4900014EB07 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGN_IDENTITY = "-";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.13;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		BF50617D2113C4900014EB07 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = YES;
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = NO;
+				CODE_SIGN_ENTITLEMENTS = I2PLauncher/I2PLauncher.entitlements;
+				CODE_SIGN_IDENTITY = "Mac Developer";
+				CODE_SIGN_STYLE = Automatic;
+				COMBINE_HIDPI_IMAGES = YES;
+				DEVELOPMENT_TEAM = W3C42P2LA8;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				HEADER_SEARCH_PATHS = (
+					"$(SRCROOT)/include",
+					"$(SRCROOT)/include/neither",
+				);
+				INCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = include;
+				INFOPLIST_FILE = I2PLauncher/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/../Frameworks",
+				);
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				PRODUCT_BUNDLE_IDENTIFIER = net.i2p.launcher.I2PLauncher;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE_SPECIFIER = "";
+				SWIFT_OBJC_BRIDGING_HEADER = "I2PLauncher/I2PLauncher-Bridging-Header.h";
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_VERSION = 3.0;
+				SYSTEM_HEADER_SEARCH_PATHS = "$(SRCROOT)/include/**";
+				USER_HEADER_SEARCH_PATHS = "";
+			};
+			name = Debug;
+		};
+		BF50617E2113C4900014EB07 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = YES;
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = NO;
+				CODE_SIGN_ENTITLEMENTS = I2PLauncher/I2PLauncher.entitlements;
+				CODE_SIGN_IDENTITY = "Mac Developer";
+				CODE_SIGN_STYLE = Automatic;
+				COMBINE_HIDPI_IMAGES = YES;
+				DEVELOPMENT_TEAM = W3C42P2LA8;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				HEADER_SEARCH_PATHS = (
+					"$(SRCROOT)/include",
+					"$(SRCROOT)/include/neither",
+				);
+				INCLUDED_RECURSIVE_SEARCH_PATH_SUBDIRECTORIES = include;
+				INFOPLIST_FILE = I2PLauncher/Info.plist;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/../Frameworks",
+				);
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				PRODUCT_BUNDLE_IDENTIFIER = net.i2p.launcher.I2PLauncher;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE_SPECIFIER = "";
+				SWIFT_OBJC_BRIDGING_HEADER = "I2PLauncher/I2PLauncher-Bridging-Header.h";
+				SWIFT_VERSION = 3.0;
+				SYSTEM_HEADER_SEARCH_PATHS = "$(SRCROOT)/include/**";
+				USER_HEADER_SEARCH_PATHS = "";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		BF5061632113C48E0014EB07 /* Build configuration list for PBXProject "I2PLauncher" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				BF50617A2113C4900014EB07 /* Debug */,
+				BF50617B2113C4900014EB07 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		BF50617C2113C4900014EB07 /* Build configuration list for PBXNativeTarget "I2PLauncher" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				BF50617D2113C4900014EB07 /* Debug */,
+				BF50617E2113C4900014EB07 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+
+/* Begin XCVersionGroup section */
+		BF50616E2113C48E0014EB07 /* I2PLauncher.xcdatamodeld */ = {
+			isa = XCVersionGroup;
+			children = (
+				BF50616F2113C48E0014EB07 /* I2PLauncher.xcdatamodel */,
+			);
+			currentVersion = BF50616F2113C48E0014EB07 /* I2PLauncher.xcdatamodel */;
+			path = I2PLauncher.xcdatamodeld;
+			sourceTree = "<group>";
+			versionGroupType = wrapper.xcdatamodel;
+		};
+/* End XCVersionGroup section */
+	};
+	rootObject = BF5061602113C48E0014EB07 /* Project object */;
+}
diff --git a/launchers/macosx/I2PLauncher.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/launchers/macosx/I2PLauncher.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000000..919434a625
--- /dev/null
+++ b/launchers/macosx/I2PLauncher.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:">
+   </FileRef>
+</Workspace>
diff --git a/launchers/macosx/I2PLauncher.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/launchers/macosx/I2PLauncher.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000000..18d981003d
--- /dev/null
+++ b/launchers/macosx/I2PLauncher.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>
diff --git a/launchers/macosx/I2PLauncher.xcworkspace/contents.xcworkspacedata b/launchers/macosx/I2PLauncher.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000000..89a270c199
--- /dev/null
+++ b/launchers/macosx/I2PLauncher.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:I2PLauncher.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/launchers/macosx/I2PLauncher.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/launchers/macosx/I2PLauncher.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000000..18d981003d
--- /dev/null
+++ b/launchers/macosx/I2PLauncher.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>
diff --git a/launchers/macosx/Info.plist b/launchers/macosx/Info.plist
new file mode 100644
index 0000000000..b63c2dbba9
--- /dev/null
+++ b/launchers/macosx/Info.plist
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>I2PLauncher</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>Public Domain</string>
+	<key>CFBundleGetInfoString</key>
+	<string>0.9.35-experimental</string>
+	<key>CFBundleIconFile</key>
+	<string>images/AppIcon.icns</string>
+	<key>CFBundleIdentifier</key>
+	<string>net.i2p.launcher</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>I2P</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>0.0.1</string>
+	<key>CFBundleSignature</key>
+	<string>I2P</string>
+	<key>CFBundleVersion</key>
+	<string>0.0.1</string>
+    <key>NSUserNotificationAlertStyle</key>
+    <string>alert</string>
+	<key>NSAppleScriptEnabled</key>
+	<true/>
+	<key>CGDisableCoalescedUpdates</key>
+	<true/>
+	<key>LSMinimumSystemVersion</key>
+	<string>10.5</string>
+	<key>CFBundleDisplayName</key>
+	<string>I2P</string>
+	<key>LSMinimumSystemVersionByArchitecture</key>
+	<dict>
+		<key>x86_64</key>
+		<string>10.6.0</string>
+	</dict>
+    <key>LSUIElement</key>
+    <string>1</string>
+</dict>
+</plist>
diff --git a/launchers/macosx/JavaHelper.h b/launchers/macosx/JavaHelper.h
index 06c90e51e1..9bb65274ee 100644
--- a/launchers/macosx/JavaHelper.h
+++ b/launchers/macosx/JavaHelper.h
@@ -1,12 +1,7 @@
 #pragma once
 
-#include <functional>
-#include <memory>
-#include <iostream>
-#include <algorithm>
-#include <cstring>
-#include <sstream>
-#include <list>
+#include <memory.h>
+#include <string.h>
 #include <stdlib.h>
 
 #include <Foundation/Foundation.h>
@@ -17,17 +12,20 @@
 #include <CoreFoundation/CFArray.h>
 #include <CoreFoundation/CFString.h>
 
-#include "optional.hpp"
-#include "strutil.hpp"
-#include "subprocess.hpp"
-#include "neither/maybe.hpp"
 #include "RouterTask.h"
 
-using namespace subprocess;
-using namespace neither;
 
 #define DEF_MIN_JVM_VER "1.7+"
 
+#ifdef __cplusplus
+
+#include "include/strutil.hpp"
+
+#include <functional>
+#include <memory>
+#include <list>
+
+
 class JvmVersion
 {
 public:
@@ -54,6 +52,7 @@ public:
   }
 };
 
+
 typedef std::shared_ptr<JvmVersion> JvmVersionPtr;
 typedef std::shared_ptr<std::list<JvmVersionPtr> > JvmListPtr;
 typedef std::shared_ptr<std::list<std::shared_ptr<JvmVersion> > > JvmListSharedPtr;
@@ -113,6 +112,8 @@ static void processJvmEntry (const void* key, const void* value, void* context)
   }
 }
 
+
+
 static void processJvmPlistEntries (const void* item, void* context) {
   CFDictionaryRef dict = CFDictionaryCreateCopy(kCFAllocatorDefault, (CFDictionaryRef)item);
 
@@ -153,15 +154,15 @@ static void listAllJavaInstallsAvailable()
   auto javaHomeRes = check_output({"/usr/libexec/java_home","-v",DEF_MIN_JVM_VER,"-X"});
   CFDataRef javaHomes = CFDataCreate(NULL, (const UInt8 *)javaHomeRes.buf.data(), strlen(javaHomeRes.buf.data()));
 
-  //CFErrorRef err;
+  CFErrorRef err;
   CFPropertyListRef propertyList = CFPropertyListCreateWithData(kCFAllocatorDefault, javaHomes, kCFPropertyListImmutable, NULL, NULL);
-  /*if (err)
+  if (err)
   {
     NSError *error = (__bridge NSError *)err;
     NSLog(@"Failed to read property list: %@", error);
     [NSApp presentError: error];
-    return nullptr;
-  }*/
+    return;
+  }
 
 
   //auto typeId = CFCopyTypeIDDescription(CFGetTypeID(propertyList));
@@ -170,8 +171,11 @@ static void listAllJavaInstallsAvailable()
 
   // Count number of entries in the property array list.
   // This is used to set max CRange for CFArrayApplyFunction.
+
   auto jCount = CFArrayGetCount((CFArrayRef)propertyList);
 
   CFArrayApplyFunction((CFArrayRef)propertyList, CFRangeMake(0, jCount), processJvmPlistEntries, NULL);
   //CFShow(propertyList);
 }
+
+#endif
diff --git a/launchers/macosx/RouterTask.h b/launchers/macosx/RouterTask.h
index 2f5436e38f..e81cd924c7 100644
--- a/launchers/macosx/RouterTask.h
+++ b/launchers/macosx/RouterTask.h
@@ -1,48 +1,16 @@
 #pragma once
 
 #include <dispatch/dispatch.h>
-#include <functional>
-#include <memory>
-#include <string>
-#include <vector>
+#include <memory.h>
+#include <string.h>
 
 #include <Cocoa/Cocoa.h>
 #import <AppKit/AppKit.h>
 
-#include "optional.hpp"
-#include "subprocess.hpp"
-
-
-@class RTaskOptions;
-@interface RTaskOptions : NSObject
-@property (strong) NSString* binPath;
-@property (strong) NSArray<NSString *>* arguments;
-@property (strong) NSString* i2pBaseDir;
-@end
-
-@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;
-- (void) requestShutdown;
-- (void) requestRestart;
-- (BOOL) isRunning;
-- (int) getPID;
-- (void)routerStdoutData:(NSNotification *)notification;
-@end
-
-
+#ifdef __cplusplus
+#include "include/subprocess.hpp"
 
 using namespace subprocess;
-
 class JavaRunner;
 
 typedef std::function<void(void)> fp_t;
@@ -61,14 +29,14 @@ public:
   // copy fn
   JavaRunner(std::string& javaBin, std::string& arguments, std::string& i2pBaseDir, const fp_proc_t& executingFn, const fp_t& cb);
   ~JavaRunner() = default;
-
+  
   static const std::vector<NSString*> defaultStartupFlags;
   static const std::vector<std::string> defaultFlagsForExtractorJob;
-
+  
   void requestRouterShutdown();
-
-  std::experimental::optional<std::future<int> > execute();
-  std::shared_ptr<Popen> javaProcess;
+  
+  std::future<int> execute();
+  std::shared_ptr<subprocess::Popen> javaProcess;
   std::string javaBinaryPath;
   std::string javaRouterArgs;
   std::string execLine;
@@ -78,4 +46,37 @@ private:
   const fp_t& exitCallbackFn;
 };
 
+#endif
+
+
+@class RTaskOptions;
+@interface RTaskOptions : NSObject
+@property (strong) NSString* binPath;
+@property (strong) NSArray<NSString *>* arguments;
+@property (strong) NSString* i2pBaseDir;
+@end
+
+@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;
+- (void) requestShutdown;
+- (void) requestRestart;
+- (BOOL) isRunning;
+- (int) getPID;
+- (void)routerStdoutData:(NSNotification *)notification;
+@end
+
+
+
+
+
 
diff --git a/launchers/macosx/RouterTask.mm b/launchers/macosx/RouterTask.mm
index f12be635da..202614011b 100644
--- a/launchers/macosx/RouterTask.mm
+++ b/launchers/macosx/RouterTask.mm
@@ -4,11 +4,15 @@
 #include <future>
 #include <stdlib.h>
 
-#include "optional.hpp"
-#include "subprocess.hpp"
-#include "PidWatcher.h"
+#ifdef __cplusplus
+#include "include/subprocess.hpp"
+#import "I2PLauncher-Swift.h"
+#include "AppDelegate.h"
+#endif
+#include "include/PidWatcher.h"
 
 #import <AppKit/AppKit.h>
+#import <Foundation/Foundation.h>
 
 @implementation RTaskOptions
 @end
@@ -24,18 +28,19 @@
 
 - (instancetype) initWithOptions : (RTaskOptions*) options
 {
-    self.userRequestedRestart = NO;
-    self.isRouterRunning = NO;
-    self.input = [NSFileHandle fileHandleWithStandardInput];
-    self.routerTask = [NSTask new];
-    self.processPipe = [NSPipe new];
-    [self.routerTask setLaunchPath:options.binPath];
-    [self.routerTask setArguments:options.arguments];
-    NSDictionary *envDict = @{
-        @"I2PBASE": options.i2pBaseDir
-    };
-    [self.routerTask setEnvironment: envDict];
-    [self.routerTask setStandardOutput:self.processPipe];
+  self.userRequestedRestart = NO;
+  self.isRouterRunning = NO;
+  self.input = [NSFileHandle fileHandleWithStandardInput];
+  self.routerTask = [NSTask new];
+  self.processPipe = [NSPipe new];
+  [self.routerTask setLaunchPath:options.binPath];
+  [self.routerTask setArguments:options.arguments];
+  NSDictionary *envDict = @{
+    @"I2PBASE": options.i2pBaseDir
+  };
+  [self.routerTask setEnvironment: envDict];
+  NSLog(@"Using environment variables: %@", envDict);
+  [self.routerTask setStandardOutput:self.processPipe];
 	[self.routerTask setStandardError:self.processPipe];
 
     NSFileHandle *stdoutFileHandle = [self.processPipe fileHandleForReading];
@@ -47,12 +52,14 @@
     [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;
+      NSLog(@"termHandler triggered!");
+      auto swiftRouterStatus = [[RouterProcessStatus alloc] init];
+      [swiftRouterStatus setRouterStatus: true];
+      NSBundle *launcherBundle = [NSBundle mainBundle];
+      auto iconImage = [launcherBundle pathForResource:@"AppIcon" ofType:@"png"];
+      sendUserNotification(APP_IDSTR, @"I2P Router has stopped");
+      // Cleanup
+      self.isRouterRunning = NO;
     }];
 /*
     self.readLogHandle = [self.processPipe fileHandleForReading];
@@ -105,11 +112,9 @@
 
 @end
 
+#ifdef __cplusplus
 
 
-
-using namespace subprocess;
-
 const std::vector<NSString*> JavaRunner::defaultStartupFlags {
     @"-Xmx512M",
     @"-Xms128m",
@@ -144,7 +149,7 @@ void JavaRunner::requestRouterShutdown()
     javaProcess->kill(1);
 }
 
-std::experimental::optional<std::future<int> > JavaRunner::execute()
+std::future<int> JavaRunner::execute()
 {
   try {
     auto executingFn = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, ^{
@@ -160,6 +165,8 @@ std::experimental::optional<std::future<int> > JavaRunner::execute()
     return std::async(std::launch::async, []{ return 0; });
   } catch (std::exception* ex) {
     printf("ERROR: %s\n", ex->what());
-    return std::experimental::nullopt;
+    return std::async(std::launch::async, []{ return 1; });
   }
 }
+
+#endif
diff --git a/launchers/macosx/dmgconfig.py b/launchers/macosx/dmgconfig.py
new file mode 100644
index 0000000000..bbb5bd5d32
--- /dev/null
+++ b/launchers/macosx/dmgconfig.py
@@ -0,0 +1,246 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+import biplist
+import os.path
+
+#
+# Example settings file for dmgbuild
+#
+
+# Use like this: dmgbuild -s settings.py "Test Volume" test.dmg
+
+# You can actually use this file for your own application (not just TextEdit)
+# by doing e.g.
+#
+#   dmgbuild -s settings.py -D app=/path/to/My.app "My Application" MyApp.dmg
+
+# .. Useful stuff ..............................................................
+
+application = defines.get('app', 'I2PLauncher.app')
+appname = os.path.basename(application)
+
+def icon_from_app(app_path):
+    plist_path = os.path.join(app_path, 'Contents', 'Info.plist')
+    plist = biplist.readPlist(plist_path)
+    icon_name = plist['CFBundleIconFile']
+    icon_root,icon_ext = os.path.splitext(icon_name)
+    if not icon_ext:
+        icon_ext = '.icns'
+    icon_name = icon_root + icon_ext
+    return os.path.join(app_path, 'Contents', 'Resources', icon_name)
+
+# .. Basics ....................................................................
+
+# Uncomment to override the output filename
+filename = 'i2p-for-osx.dmg'
+
+# Uncomment to override the output volume name
+volume_name = 'I2P'
+
+# Volume format (see hdiutil create -help)
+format = defines.get('format', 'UDBZ')
+
+# Volume size
+size = defines.get('size', None)
+
+# Files to include
+files = [ application ]
+
+# Symlinks to create
+symlinks = { 'Applications': '/Applications' }
+
+# Volume icon
+#
+# You can either define icon, in which case that icon file will be copied to the
+# image, *or* you can define badge_icon, in which case the icon file you specify
+# will be used to badge the system's Removable Disk icon
+#
+#icon = '/path/to/icon.icns'
+badge_icon = icon_from_app(application)
+
+# Where to put the icons
+icon_locations = {
+    appname:        (140, 120),
+    'Applications': (500, 120)
+    }
+
+# .. Window configuration ......................................................
+
+# Background
+#
+# This is a STRING containing any of the following:
+#
+#    #3344ff          - web-style RGB color
+#    #34f             - web-style RGB color, short form (#34f == #3344ff)
+#    rgb(1,0,0)       - RGB color, each value is between 0 and 1
+#    hsl(120,1,.5)    - HSL (hue saturation lightness) color
+#    hwb(300,0,0)     - HWB (hue whiteness blackness) color
+#    cmyk(0,1,0,0)    - CMYK color
+#    goldenrod        - X11/SVG named color
+#    builtin-arrow    - A simple built-in background with a blue arrow
+#    /foo/bar/baz.png - The path to an image file
+#
+# The hue component in hsl() and hwb() may include a unit; it defaults to
+# degrees ('deg'), but also supports radians ('rad') and gradians ('grad'
+# or 'gon').
+#
+# Other color components may be expressed either in the range 0 to 1, or
+# as percentages (e.g. 60% is equivalent to 0.6).
+background = 'builtin-arrow'
+
+show_status_bar = False
+show_tab_view = False
+show_toolbar = False
+show_pathbar = False
+show_sidebar = False
+sidebar_width = 180
+
+# Window position in ((x, y), (w, h)) format
+window_rect = ((100, 100), (640, 280))
+
+# Select the default view; must be one of
+#
+#    'icon-view'
+#    'list-view'
+#    'column-view'
+#    'coverflow'
+#
+default_view = 'icon-view'
+
+# General view configuration
+show_icon_preview = False
+
+# Set these to True to force inclusion of icon/list view settings (otherwise
+# we only include settings for the default view)
+include_icon_view_settings = 'auto'
+include_list_view_settings = 'auto'
+
+# .. Icon view configuration ...................................................
+
+arrange_by = None
+grid_offset = (0, 0)
+grid_spacing = 100
+scroll_position = (0, 0)
+label_pos = 'bottom' # or 'right'
+text_size = 16
+icon_size = 128
+
+# .. List view configuration ...................................................
+
+# Column names are as follows:
+#
+#   name
+#   date-modified
+#   date-created
+#   date-added
+#   date-last-opened
+#   size
+#   kind
+#   label
+#   version
+#   comments
+#
+list_icon_size = 16
+list_text_size = 12
+list_scroll_position = (0, 0)
+list_sort_by = 'name'
+list_use_relative_dates = True
+list_calculate_all_sizes = False,
+list_columns = ('name', 'date-modified', 'size', 'kind', 'date-added')
+list_column_widths = {
+    'name': 300,
+    'date-modified': 181,
+    'date-created': 181,
+    'date-added': 181,
+    'date-last-opened': 181,
+    'size': 97,
+    'kind': 115,
+    'label': 100,
+    'version': 75,
+    'comments': 300,
+    }
+list_column_sort_directions = {
+    'name': 'ascending',
+    'date-modified': 'descending',
+    'date-created': 'descending',
+    'date-added': 'descending',
+    'date-last-opened': 'descending',
+    'size': 'descending',
+    'kind': 'ascending',
+    'label': 'ascending',
+    'version': 'ascending',
+    'comments': 'ascending',
+    }
+
+# .. License configuration .....................................................
+
+# Text in the license configuration is stored in the resources, which means
+# it gets stored in a legacy Mac encoding according to the language.  dmgbuild
+# will *try* to convert Unicode strings to the appropriate encoding, *but*
+# you should be aware that Python doesn't support all of the necessary encodings;
+# in many cases you will need to encode the text yourself and use byte strings
+# instead here.
+
+# Recognized language names are:
+#
+#  af_ZA, ar, be_BY, bg_BG, bn, bo, br, ca_ES, cs_CZ, cy, da_DK, de_AT, de_CH,
+#  de_DE, dz_BT, el_CY, el_GR, en_AU, en_CA, en_GB, en_IE, en_SG, en_US, eo,
+#  es_419, es_ES, et_EE, fa_IR, fi_FI, fo_FO, fr_001, fr_BE, fr_CA, fr_CH,
+#  fr_FR, ga-Latg_IE, ga_IE, gd, grc, gu_IN, gv, he_IL, hi_IN, hr_HR, hu_HU,
+#  hy_AM, is_IS, it_CH, it_IT, iu_CA, ja_JP, ka_GE, kl, ko_KR, lt_LT, lv_LV,
+#  mk_MK, mr_IN, mt_MT, nb_NO, ne_NP, nl_BE, nl_NL, nn_NO, pa, pl_PL, pt_BR,
+#  pt_PT, ro_RO, ru_RU, se, sk_SK, sl_SI, sr_RS, sv_SE, th_TH, to_TO, tr_TR,
+#  uk_UA, ur_IN, ur_PK, uz_UZ, vi_VN, zh_CN, zh_TW
+
+# license = {
+#     'default-language': 'en_US',
+#     'licenses': {
+#         # For each language, the text of the license.  This can be plain text,
+#         # RTF (in which case it must start "{\rtf1"), or a path to a file
+#         # containing the license text.  If you're using RTF,
+#         # watch out for Python escaping (or read it from a file).
+#         'English': b'''{\\rtf1\\ansi\\ansicpg1252\\cocoartf1504\\cocoasubrtf820
+# {\\fonttbl\\f0\\fnil\\fcharset0 Helvetica-Bold;\\f1\\fnil\\fcharset0 Helvetica;}
+# {\\colortbl;\\red255\\green255\\blue255;\\red0\\green0\\blue0;}
+# {\\*\\expandedcolortbl;;\\cssrgb\\c0\\c0\\c0;}
+# \\paperw11905\\paperh16837\\margl1133\\margr1133\\margb1133\\margt1133
+# \\deftab720
+# \\pard\\pardeftab720\\sa160\\partightenfactor0
+
+# \\f0\\b\\fs60 \\cf2 \\expnd0\\expndtw0\\kerning0
+# \\up0 \\nosupersub \\ulnone \\outl0\\strokewidth0 \\strokec2 Test License\\
+# \\pard\\pardeftab720\\sa160\\partightenfactor0
+
+# \\fs36 \\cf2 \\strokec2 What is this?\\
+# \\pard\\pardeftab720\\sa160\\partightenfactor0
+
+# \\f1\\b0\\fs22 \\cf2 \\strokec2 This is the English license. It says what you are allowed to do with this software.\\
+# \\
+# }''',
+#     },
+#     'buttons': {
+#         # For each language, text for the buttons on the licensing window.
+#         #
+#         # Default buttons and text are built-in for the following languages:
+#         #
+#         #   English (en_US), German (de_DE), Spanish (es_ES), French (fr_FR),
+#         #   Italian (it_IT), Japanese (ja_JP), Dutch (nl_NL), Swedish (sv_SE),
+#         #   Brazilian Portuguese (pt_BR), Simplified Chinese (zh_CN),
+#         #   Traditional Chinese (zh_TW), Danish (da_DK), Finnish (fi_FI),
+#         #   Korean (ko_KR), Norwegian (nb_NO)
+#         #
+#         # You don't need to specify them for those languages; if you fail to
+#         # specify them for some other language, English will be used instead.
+
+#         'en_US': (
+#             b'English',
+#             b'Agree',
+#             b'Disagree',
+#             b'Print',
+#             b'Save',
+#             b'If you agree with the terms of this license, press "Agree" to '
+#             b'install the software.  If you do not agree, press "Disagree".'
+#         ),
+#     },
+# }
diff --git a/launchers/macosx/include/PidWatcher.h b/launchers/macosx/include/PidWatcher.h
index 7cac1c858c..8ae10e09f6 100644
--- a/launchers/macosx/include/PidWatcher.h
+++ b/launchers/macosx/include/PidWatcher.h
@@ -4,8 +4,6 @@
 #include <unistd.h>
 #include <sys/event.h>
 
-#include "neither/either.hpp"
-#include "AppDelegate.h"
 
 using callbackType = void (CFFileDescriptorRef, CFOptionFlags, void *);
 using HandleFunction = std::function<void(int)>;
@@ -16,7 +14,7 @@ static void noteProcDeath(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes
     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);
-    sendUserNotification(APP_IDSTR, @"The I2P router has stopped.");
+    //sendUserNotification(APP_IDSTR, @"The I2P router has stopped.");
     CFFileDescriptorInvalidate(fdref);
     CFRelease(fdref); // the CFFileDescriptorRef is no longer of any use in this example
 }
diff --git a/launchers/macosx/include/optional.h b/launchers/macosx/include/optional.h
new file mode 100644
index 0000000000..cd6f025ac6
--- /dev/null
+++ b/launchers/macosx/include/optional.h
@@ -0,0 +1,1066 @@
+// Copyright (C) 2011 - 2012 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The idea and interface is based on Boost.Optional library
+// authored by Fernando Luis Cacciola Carballal
+
+# ifndef ___OPTIONAL_HPP___
+# define ___OPTIONAL_HPP___
+
+# include <utility>
+# include <type_traits>
+# include <initializer_list>
+# include <cassert>
+# include <functional>
+# include <string>
+# include <stdexcept>
+
+# define TR2_OPTIONAL_REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false
+
+# if defined __GNUC__ // NOTE: GNUC is also defined for Clang
+#   if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
+#     define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+#   elif (__GNUC__ > 4)
+#     define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+#   endif
+#
+#   if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)
+#     define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
+#   elif (__GNUC__ > 4)
+#     define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
+#   endif
+#
+#   if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1)
+#     define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+#   elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)
+#     define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+#   elif (__GNUC__ > 4)
+#     define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+#   endif
+# endif
+#
+# if defined __clang_major__
+#   if (__clang_major__ == 3 && __clang_minor__ >= 5)
+#     define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
+#   elif (__clang_major__ > 3)
+#     define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
+#   endif
+#   if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
+#     define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+#   elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2)
+#     define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+#   endif
+# endif
+#
+# if defined _MSC_VER
+#   if (_MSC_VER >= 1900)
+#     define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+#   endif
+# endif
+
+# if defined __clang__
+#   if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9)
+#     define OPTIONAL_HAS_THIS_RVALUE_REFS 1
+#   else
+#     define OPTIONAL_HAS_THIS_RVALUE_REFS 0
+#   endif
+# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+#   define OPTIONAL_HAS_THIS_RVALUE_REFS 1
+# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+#   define OPTIONAL_HAS_THIS_RVALUE_REFS 1
+# else
+#   define OPTIONAL_HAS_THIS_RVALUE_REFS 0
+# endif
+
+
+# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+#   define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1
+#   define OPTIONAL_CONSTEXPR_INIT_LIST constexpr
+# else
+#   define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0
+#   define OPTIONAL_CONSTEXPR_INIT_LIST
+# endif
+
+# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L)
+#   define OPTIONAL_HAS_MOVE_ACCESSORS 1
+# else
+#   define OPTIONAL_HAS_MOVE_ACCESSORS 0
+# endif
+
+# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr
+# if (defined __cplusplus) && (__cplusplus == 201103L)
+#   define OPTIONAL_MUTABLE_CONSTEXPR
+# else
+#   define OPTIONAL_MUTABLE_CONSTEXPR constexpr
+# endif
+
+namespace std{
+
+namespace experimental{
+
+// BEGIN workaround for missing is_trivially_destructible
+# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+    // leave it: it is already there
+# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+    // leave it: it is already there
+# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+    // leave it: it is already there
+# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
+    // leave it: the user doesn't want it
+# else
+	template <typename T>
+	using is_trivially_destructible = std::has_trivial_destructor<T>;
+# endif
+// END workaround for missing is_trivially_destructible
+
+# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___)
+    // leave it; our metafunctions are already defined.
+# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+    // leave it; our metafunctions are already defined.
+# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+    // leave it: it is already there
+# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
+    // leave it: the user doesn't want it
+# else
+
+
+// workaround for missing traits in GCC and CLANG
+template <class T>
+struct is_nothrow_move_constructible
+{
+  constexpr static bool value = std::is_nothrow_constructible<T, T&&>::value;
+};
+
+
+template <class T, class U>
+struct is_assignable
+{
+  template <class X, class Y>
+  constexpr static bool has_assign(...) { return false; }
+
+  template <class X, class Y, size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true)) >
+  // the comma operator is necessary for the cases where operator= returns void
+  constexpr static bool has_assign(bool) { return true; }
+
+  constexpr static bool value = has_assign<T, U>(true);
+};
+
+
+template <class T>
+struct is_nothrow_move_assignable
+{
+  template <class X, bool has_any_move_assign>
+  struct has_nothrow_move_assign {
+    constexpr static bool value = false;
+  };
+
+  template <class X>
+  struct has_nothrow_move_assign<X, true> {
+    constexpr static bool value = noexcept( std::declval<X&>() = std::declval<X&&>() );
+  };
+
+  constexpr static bool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value;
+};
+// end workaround
+
+
+# endif
+
+
+
+// 20.5.4, optional for object types
+template <class T> class optional;
+
+// 20.5.5, optional for lvalue reference types
+template <class T> class optional<T&>;
+
+
+// workaround: std utility functions aren't constexpr yet
+template <class T> inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type& t) noexcept
+{
+  return static_cast<T&&>(t);
+}
+
+template <class T> inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type&& t) noexcept
+{
+    static_assert(!std::is_lvalue_reference<T>::value, "!!");
+    return static_cast<T&&>(t);
+}
+
+template <class T> inline constexpr typename std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept
+{
+    return static_cast<typename std::remove_reference<T>::type&&>(t);
+}
+
+
+#if defined NDEBUG
+# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
+#else
+# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR)))
+#endif
+
+
+namespace detail_
+{
+
+// static_addressof: a constexpr version of addressof
+template <typename T>
+struct has_overloaded_addressof
+{
+  template <class X>
+  constexpr static bool has_overload(...) { return false; }
+
+  template <class X, size_t S = sizeof(std::declval<X&>().operator&()) >
+  constexpr static bool has_overload(bool) { return true; }
+
+  constexpr static bool value = has_overload<T>(true);
+};
+
+template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
+constexpr T* static_addressof(T& ref)
+{
+  return &ref;
+}
+
+template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)>
+T* static_addressof(T& ref)
+{
+  return std::addressof(ref);
+}
+
+
+// the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A
+template <class U>
+constexpr U convert(U v) { return v; }
+
+
+namespace swap_ns
+{
+  using std::swap;
+
+  template <class T>
+  void adl_swap(T& t, T& u) noexcept(noexcept(swap(t, u)))
+  {
+    swap(t, u);
+  }
+
+} // namespace swap_ns
+
+} // namespace detail
+
+
+constexpr struct trivial_init_t{} trivial_init{};
+
+
+// 20.5.6, In-place construction
+constexpr struct in_place_t{} in_place{};
+
+
+// 20.5.7, Disengaged state indicator
+struct nullopt_t
+{
+  struct init{};
+  constexpr explicit nullopt_t(init){}
+};
+constexpr nullopt_t nullopt{nullopt_t::init()};
+
+
+// 20.5.8, class bad_optional_access
+class bad_optional_access : public logic_error {
+public:
+  explicit bad_optional_access(const string& what_arg) : logic_error{what_arg} {}
+  explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {}
+};
+
+
+template <class T>
+union storage_t
+{
+  unsigned char dummy_;
+  T value_;
+
+  constexpr storage_t( trivial_init_t ) noexcept : dummy_() {};
+
+  template <class... Args>
+  constexpr storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
+
+  ~storage_t(){}
+};
+
+
+template <class T>
+union constexpr_storage_t
+{
+    unsigned char dummy_;
+    T value_;
+
+    constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {};
+
+    template <class... Args>
+    constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {}
+
+    ~constexpr_storage_t() = default;
+};
+
+
+template <class T>
+struct optional_base
+{
+    bool init_;
+    storage_t<T> storage_;
+
+    constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {};
+
+    explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {}
+
+    explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {}
+
+    template <class... Args> explicit optional_base(in_place_t, Args&&... args)
+        : init_(true), storage_(constexpr_forward<Args>(args)...) {}
+
+    template <class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)>
+    explicit optional_base(in_place_t, std::initializer_list<U> il, Args&&... args)
+        : init_(true), storage_(il, std::forward<Args>(args)...) {}
+
+    ~optional_base() { if (init_) storage_.value_.T::~T(); }
+};
+
+
+template <class T>
+struct constexpr_optional_base
+{
+    bool init_;
+    constexpr_storage_t<T> storage_;
+
+    constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {};
+
+    explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {}
+
+    explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {}
+
+    template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
+      : init_(true), storage_(constexpr_forward<Args>(args)...) {}
+
+    template <class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)>
+    OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list<U> il, Args&&... args)
+      : init_(true), storage_(il, std::forward<Args>(args)...) {}
+
+    ~constexpr_optional_base() = default;
+};
+
+template <class T>
+using OptionalBase = typename std::conditional<
+    is_trivially_destructible<T>::value,                          // if possible
+    constexpr_optional_base<typename std::remove_const<T>::type>, // use base with trivial destructor
+    optional_base<typename std::remove_const<T>::type>
+>::type;
+
+
+
+template <class T>
+class optional : private OptionalBase<T>
+{
+  static_assert( !std::is_same<typename std::decay<T>::type, nullopt_t>::value, "bad T" );
+  static_assert( !std::is_same<typename std::decay<T>::type, in_place_t>::value, "bad T" );
+
+
+  constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; }
+  typename std::remove_const<T>::type* dataptr() {  return std::addressof(OptionalBase<T>::storage_.value_); }
+  constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage_.value_); }
+
+# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
+  constexpr const T& contained_val() const& { return OptionalBase<T>::storage_.value_; }
+#   if OPTIONAL_HAS_MOVE_ACCESSORS == 1
+  OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return std::move(OptionalBase<T>::storage_.value_); }
+  OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage_.value_; }
+#   else
+  T& contained_val() & { return OptionalBase<T>::storage_.value_; }
+  T&& contained_val() && { return std::move(OptionalBase<T>::storage_.value_); }
+#   endif
+# else
+  constexpr const T& contained_val() const { return OptionalBase<T>::storage_.value_; }
+  T& contained_val() { return OptionalBase<T>::storage_.value_; }
+# endif
+
+  void clear() noexcept {
+    if (initialized()) dataptr()->T::~T();
+    OptionalBase<T>::init_ = false;
+  }
+
+  template <class... Args>
+  void initialize(Args&&... args) noexcept(noexcept(T(std::forward<Args>(args)...)))
+  {
+    assert(!OptionalBase<T>::init_);
+    ::new (static_cast<void*>(dataptr())) T(std::forward<Args>(args)...);
+    OptionalBase<T>::init_ = true;
+  }
+
+  template <class U, class... Args>
+  void initialize(std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, std::forward<Args>(args)...)))
+  {
+    assert(!OptionalBase<T>::init_);
+    ::new (static_cast<void*>(dataptr())) T(il, std::forward<Args>(args)...);
+    OptionalBase<T>::init_ = true;
+  }
+
+public:
+  typedef T value_type;
+
+  // 20.5.5.1, constructors
+  constexpr optional() noexcept : OptionalBase<T>()  {};
+  constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {};
+
+  optional(const optional& rhs)
+  : OptionalBase<T>()
+  {
+    if (rhs.initialized()) {
+        ::new (static_cast<void*>(dataptr())) T(*rhs);
+        OptionalBase<T>::init_ = true;
+    }
+  }
+
+  optional(optional&& rhs) noexcept(is_nothrow_move_constructible<T>::value)
+  : OptionalBase<T>()
+  {
+    if (rhs.initialized()) {
+        ::new (static_cast<void*>(dataptr())) T(std::move(*rhs));
+        OptionalBase<T>::init_ = true;
+    }
+  }
+
+  constexpr optional(const T& v) : OptionalBase<T>(v) {}
+
+  constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {}
+
+  template <class... Args>
+  explicit constexpr optional(in_place_t, Args&&... args)
+  : OptionalBase<T>(in_place_t{}, constexpr_forward<Args>(args)...) {}
+
+  template <class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)>
+  OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, std::initializer_list<U> il, Args&&... args)
+  : OptionalBase<T>(in_place_t{}, il, constexpr_forward<Args>(args)...) {}
+
+  // 20.5.4.2, Destructor
+  ~optional() = default;
+
+  // 20.5.4.3, assignment
+  optional& operator=(nullopt_t) noexcept
+  {
+    clear();
+    return *this;
+  }
+
+  optional& operator=(const optional& rhs)
+  {
+    if      (initialized() == true  && rhs.initialized() == false) clear();
+    else if (initialized() == false && rhs.initialized() == true)  initialize(*rhs);
+    else if (initialized() == true  && rhs.initialized() == true)  contained_val() = *rhs;
+    return *this;
+  }
+
+  optional& operator=(optional&& rhs)
+  noexcept(is_nothrow_move_assignable<T>::value && is_nothrow_move_constructible<T>::value)
+  {
+    if      (initialized() == true  && rhs.initialized() == false) clear();
+    else if (initialized() == false && rhs.initialized() == true)  initialize(std::move(*rhs));
+    else if (initialized() == true  && rhs.initialized() == true)  contained_val() = std::move(*rhs);
+    return *this;
+  }
+
+  template <class U>
+  auto operator=(U&& v)
+  -> typename enable_if
+  <
+    is_same<typename decay<U>::type, T>::value,
+    optional&
+  >::type
+  {
+    if (initialized()) { contained_val() = std::forward<U>(v); }
+    else               { initialize(std::forward<U>(v));  }
+    return *this;
+  }
+
+
+  template <class... Args>
+  void emplace(Args&&... args)
+  {
+    clear();
+    initialize(std::forward<Args>(args)...);
+  }
+
+  template <class U, class... Args>
+  void emplace(initializer_list<U> il, Args&&... args)
+  {
+    clear();
+    initialize<U, Args...>(il, std::forward<Args>(args)...);
+  }
+
+  // 20.5.4.4, Swap
+  void swap(optional<T>& rhs) noexcept(is_nothrow_move_constructible<T>::value
+                                       && noexcept(detail_::swap_ns::adl_swap(declval<T&>(), declval<T&>())))
+  {
+    if      (initialized() == true  && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); }
+    else if (initialized() == false && rhs.initialized() == true)  { initialize(std::move(*rhs)); rhs.clear(); }
+    else if (initialized() == true  && rhs.initialized() == true)  { using std::swap; swap(**this, *rhs); }
+  }
+
+  // 20.5.4.5, Observers
+
+  explicit constexpr operator bool() const noexcept { return initialized(); }
+  constexpr bool has_value() const noexcept { return initialized(); }
+
+  constexpr T const* operator ->() const {
+    return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
+  }
+
+# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
+
+  OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() {
+    assert (initialized());
+    return dataptr();
+  }
+
+  constexpr T const& operator *() const& {
+    return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
+  }
+
+  OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & {
+    assert (initialized());
+    return contained_val();
+  }
+
+  OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && {
+    assert (initialized());
+    return constexpr_move(contained_val());
+  }
+
+  constexpr T const& value() const& {
+    return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
+  }
+
+  OPTIONAL_MUTABLE_CONSTEXPR T& value() & {
+    return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
+  }
+
+  OPTIONAL_MUTABLE_CONSTEXPR T&& value() && {
+    if (!initialized()) throw bad_optional_access("bad optional access");
+	return std::move(contained_val());
+  }
+
+# else
+
+  T* operator ->() {
+    assert (initialized());
+    return dataptr();
+  }
+
+  constexpr T const& operator *() const {
+    return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
+  }
+
+  T& operator *() {
+    assert (initialized());
+    return contained_val();
+  }
+
+  constexpr T const& value() const {
+    return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
+  }
+
+  T& value() {
+    return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
+  }
+
+# endif
+
+# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
+
+  template <class V>
+  constexpr T value_or(V&& v) const&
+  {
+    return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
+  }
+
+#   if OPTIONAL_HAS_MOVE_ACCESSORS == 1
+
+  template <class V>
+  OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) &&
+  {
+    return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
+  }
+
+#   else
+
+  template <class V>
+  T value_or(V&& v) &&
+  {
+    return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
+  }
+
+#   endif
+
+# else
+
+  template <class V>
+  constexpr T value_or(V&& v) const
+  {
+    return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
+  }
+
+# endif
+
+  // 20.6.3.6, modifiers
+  void reset() noexcept { clear(); }
+};
+
+
+template <class T>
+class optional<T&>
+{
+  static_assert( !std::is_same<T, nullopt_t>::value, "bad T" );
+  static_assert( !std::is_same<T, in_place_t>::value, "bad T" );
+  T* ref;
+
+public:
+
+  // 20.5.5.1, construction/destruction
+  constexpr optional() noexcept : ref(nullptr) {}
+
+  constexpr optional(nullopt_t) noexcept : ref(nullptr) {}
+
+  constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {}
+
+  optional(T&&) = delete;
+
+  constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {}
+
+  explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {}
+
+  explicit optional(in_place_t, T&&) = delete;
+
+  ~optional() = default;
+
+  // 20.5.5.2, mutation
+  optional& operator=(nullopt_t) noexcept {
+    ref = nullptr;
+    return *this;
+  }
+
+  // optional& operator=(const optional& rhs) noexcept {
+    // ref = rhs.ref;
+    // return *this;
+  // }
+
+  // optional& operator=(optional&& rhs) noexcept {
+    // ref = rhs.ref;
+    // return *this;
+  // }
+
+  template <typename U>
+  auto operator=(U&& rhs) noexcept
+  -> typename enable_if
+  <
+    is_same<typename decay<U>::type, optional<T&>>::value,
+    optional&
+  >::type
+  {
+    ref = rhs.ref;
+    return *this;
+  }
+
+  template <typename U>
+  auto operator=(U&& rhs) noexcept
+  -> typename enable_if
+  <
+    !is_same<typename decay<U>::type, optional<T&>>::value,
+    optional&
+  >::type
+  = delete;
+
+  void emplace(T& v) noexcept {
+    ref = detail_::static_addressof(v);
+  }
+
+  void emplace(T&&) = delete;
+
+
+  void swap(optional<T&>& rhs) noexcept
+  {
+    std::swap(ref, rhs.ref);
+  }
+
+  // 20.5.5.3, observers
+  constexpr T* operator->() const {
+    return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
+  }
+
+  constexpr T& operator*() const {
+    return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
+  }
+
+  constexpr T& value() const {
+    return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref);
+  }
+
+  explicit constexpr operator bool() const noexcept {
+    return ref != nullptr;
+  }
+
+  constexpr bool has_value() const noexcept {
+    return ref != nullptr;
+  }
+
+  template <class V>
+  constexpr typename decay<T>::type value_or(V&& v) const
+  {
+    return *this ? **this : detail_::convert<typename decay<T>::type>(constexpr_forward<V>(v));
+  }
+
+  // x.x.x.x, modifiers
+  void reset() noexcept { ref = nullptr; }
+};
+
+
+template <class T>
+class optional<T&&>
+{
+  static_assert( sizeof(T) == 0, "optional rvalue references disallowed" );
+};
+
+
+// 20.5.8, Relational operators
+template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y)
+{
+  return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
+}
+
+template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y)
+{
+  return !(x == y);
+}
+
+template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y)
+{
+  return (!y) ? false : (!x) ? true : *x < *y;
+}
+
+template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y)
+{
+  return (y < x);
+}
+
+template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y)
+{
+  return !(y < x);
+}
+
+template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y)
+{
+  return !(x < y);
+}
+
+
+// 20.5.9, Comparison with nullopt
+template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept
+{
+  return (!x);
+}
+
+template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept
+{
+  return (!x);
+}
+
+template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept
+{
+  return bool(x);
+}
+
+template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept
+{
+  return bool(x);
+}
+
+template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept
+{
+  return false;
+}
+
+template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept
+{
+  return bool(x);
+}
+
+template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept
+{
+  return (!x);
+}
+
+template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept
+{
+  return true;
+}
+
+template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept
+{
+  return bool(x);
+}
+
+template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept
+{
+  return false;
+}
+
+template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept
+{
+  return true;
+}
+
+template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept
+{
+  return (!x);
+}
+
+
+
+// 20.5.10, Comparison with T
+template <class T> constexpr bool operator==(const optional<T>& x, const T& v)
+{
+  return bool(x) ? *x == v : false;
+}
+
+template <class T> constexpr bool operator==(const T& v, const optional<T>& x)
+{
+  return bool(x) ? v == *x : false;
+}
+
+template <class T> constexpr bool operator!=(const optional<T>& x, const T& v)
+{
+  return bool(x) ? *x != v : true;
+}
+
+template <class T> constexpr bool operator!=(const T& v, const optional<T>& x)
+{
+  return bool(x) ? v != *x : true;
+}
+
+template <class T> constexpr bool operator<(const optional<T>& x, const T& v)
+{
+  return bool(x) ? *x < v : true;
+}
+
+template <class T> constexpr bool operator>(const T& v, const optional<T>& x)
+{
+  return bool(x) ? v > *x : true;
+}
+
+template <class T> constexpr bool operator>(const optional<T>& x, const T& v)
+{
+  return bool(x) ? *x > v : false;
+}
+
+template <class T> constexpr bool operator<(const T& v, const optional<T>& x)
+{
+  return bool(x) ? v < *x : false;
+}
+
+template <class T> constexpr bool operator>=(const optional<T>& x, const T& v)
+{
+  return bool(x) ? *x >= v : false;
+}
+
+template <class T> constexpr bool operator<=(const T& v, const optional<T>& x)
+{
+  return bool(x) ? v <= *x : false;
+}
+
+template <class T> constexpr bool operator<=(const optional<T>& x, const T& v)
+{
+  return bool(x) ? *x <= v : true;
+}
+
+template <class T> constexpr bool operator>=(const T& v, const optional<T>& x)
+{
+  return bool(x) ? v >= *x : true;
+}
+
+
+// Comparison of optional<T&> with T
+template <class T> constexpr bool operator==(const optional<T&>& x, const T& v)
+{
+  return bool(x) ? *x == v : false;
+}
+
+template <class T> constexpr bool operator==(const T& v, const optional<T&>& x)
+{
+  return bool(x) ? v == *x : false;
+}
+
+template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v)
+{
+  return bool(x) ? *x != v : true;
+}
+
+template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x)
+{
+  return bool(x) ? v != *x : true;
+}
+
+template <class T> constexpr bool operator<(const optional<T&>& x, const T& v)
+{
+  return bool(x) ? *x < v : true;
+}
+
+template <class T> constexpr bool operator>(const T& v, const optional<T&>& x)
+{
+  return bool(x) ? v > *x : true;
+}
+
+template <class T> constexpr bool operator>(const optional<T&>& x, const T& v)
+{
+  return bool(x) ? *x > v : false;
+}
+
+template <class T> constexpr bool operator<(const T& v, const optional<T&>& x)
+{
+  return bool(x) ? v < *x : false;
+}
+
+template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v)
+{
+  return bool(x) ? *x >= v : false;
+}
+
+template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x)
+{
+  return bool(x) ? v <= *x : false;
+}
+
+template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v)
+{
+  return bool(x) ? *x <= v : true;
+}
+
+template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x)
+{
+  return bool(x) ? v >= *x : true;
+}
+
+// Comparison of optional<T const&> with T
+template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v)
+{
+  return bool(x) ? *x == v : false;
+}
+
+template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x)
+{
+  return bool(x) ? v == *x : false;
+}
+
+template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v)
+{
+  return bool(x) ? *x != v : true;
+}
+
+template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x)
+{
+  return bool(x) ? v != *x : true;
+}
+
+template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v)
+{
+  return bool(x) ? *x < v : true;
+}
+
+template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x)
+{
+  return bool(x) ? v > *x : true;
+}
+
+template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v)
+{
+  return bool(x) ? *x > v : false;
+}
+
+template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x)
+{
+  return bool(x) ? v < *x : false;
+}
+
+template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v)
+{
+  return bool(x) ? *x >= v : false;
+}
+
+template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x)
+{
+  return bool(x) ? v <= *x : false;
+}
+
+template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v)
+{
+  return bool(x) ? *x <= v : true;
+}
+
+template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x)
+{
+  return bool(x) ? v >= *x : true;
+}
+
+
+// 20.5.12, Specialized algorithms
+template <class T>
+void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)))
+{
+  x.swap(y);
+}
+
+
+template <class T>
+constexpr optional<typename decay<T>::type> make_optional(T&& v)
+{
+  return optional<typename decay<T>::type>(constexpr_forward<T>(v));
+}
+
+template <class X>
+constexpr optional<X&> make_optional(reference_wrapper<X> v)
+{
+  return optional<X&>(v.get());
+}
+
+
+} // namespace experimental
+} // namespace std
+
+namespace std
+{
+  template <typename T>
+  struct hash<std::experimental::optional<T>>
+  {
+    typedef typename hash<T>::result_type result_type;
+    typedef std::experimental::optional<T> argument_type;
+
+    constexpr result_type operator()(argument_type const& arg) const {
+      return arg ? std::hash<T>{}(*arg) : result_type{};
+    }
+  };
+
+  template <typename T>
+  struct hash<std::experimental::optional<T&>>
+  {
+    typedef typename hash<T>::result_type result_type;
+    typedef std::experimental::optional<T&> argument_type;
+
+    constexpr result_type operator()(argument_type const& arg) const {
+      return arg ? std::hash<T>{}(*arg) : result_type{};
+    }
+  };
+}
+
+# undef TR2_OPTIONAL_REQUIRES
+# undef TR2_OPTIONAL_ASSERTED_EXPRESSION
+
+# endif //___OPTIONAL_HPP___
diff --git a/launchers/macosx/include/portcheck.h b/launchers/macosx/include/portcheck.h
index fd7838c952..39487369cb 100644
--- a/launchers/macosx/include/portcheck.h
+++ b/launchers/macosx/include/portcheck.h
@@ -9,51 +9,52 @@
 
 typedef struct sockaddr *sad; /* A necesary dummy typedef */
 
-
-int port_check(int portNum=7657)
+int port_check(int portNum)
 {
-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 );
+  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 );
   }
-
-  else
-  /* If the error were other than EADDRINUSE, we print it */
-  perror( "bind" );
-
-  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;
 }
 
-/* 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;
-}
diff --git a/launchers/macosx/include/strutil.hpp b/launchers/macosx/include/strutil.hpp
index b27d4f70ed..2703315431 100644
--- a/launchers/macosx/include/strutil.hpp
+++ b/launchers/macosx/include/strutil.hpp
@@ -8,7 +8,7 @@
 #include <iostream>
 #include <cctype>
 #include <locale>
-#include "optional.hpp"
+#include "optional.h"
 
 #include <CoreFoundation/CoreFoundation.h>
 #include <CoreFoundation/CFArray.h>
diff --git a/launchers/macosx/main.mm b/launchers/macosx/main.mm
index 9a64c4796e..2bbf5de468 100644
--- a/launchers/macosx/main.mm
+++ b/launchers/macosx/main.mm
@@ -11,6 +11,7 @@
 
 #import <Foundation/Foundation.h>
 
+
 #include <CoreFoundation/CoreFoundation.h>
 #include <CoreFoundation/CFStream.h>
 #include <CoreFoundation/CFPropertyList.h>
@@ -24,40 +25,39 @@
 #import <AppKit/AppKit.h>
 #import <AppKit/NSApplication.h>
 
+#import "I2PLauncher-Swift.h"
+
 #include "AppDelegate.h"
-#include "StatusItemButton.h"
 #include "RouterTask.h"
 #include "JavaHelper.h"
-#include "fn.h"
-#include "optional.hpp"
-#include "portcheck.h"
+#include "include/fn.h"
+#include "include/portcheck.h"
 
 #define debug(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]);
 
-JvmListSharedPtr gRawJvmList = nullptr;
+@interface AppDelegate () <NSUserNotificationCenterDelegate, NSApplicationDelegate>
+@end
 
+#ifdef __cplusplus
+#import "SBridge.h"
+JvmListSharedPtr gRawJvmList = nullptr;
+#endif
 
-@interface MenuBarCtrl () <StatusItemButtonDelegate, NSMenuDelegate>
-@end
 
 @interface AppDelegate () <NSUserNotificationCenterDelegate, NSApplicationDelegate>
 @end
 
-std::vector<std::string> buildClassPath(std::string basePath)
-{
-    return globVector(basePath+std::string("/lib/*.jar"));
-}
-
+#ifdef __cplusplus
 maybeAnRouterRunner getGlobalRouterObject()
 {
     std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
-    return globalRouterStatus;
+    return globalRouterStatus; // Remember this might be nullptr now.
 }
 
 void setGlobalRouterObject(I2PRouterTask* newRouter)
 {
     std::lock_guard<std::mutex> lock(globalRouterStatusMutex);
-    globalRouterStatus.emplace(newRouter);
+    globalRouterStatus = newRouter;
 }
 
 
@@ -77,214 +77,25 @@ void setGlobalRouterIsRunning(bool 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 = [[[I2PRouterTask alloc] initWithOptions: options] autorelease];
-        setGlobalRouterObject(instance);
-        //NSThread *thr = [[NSThread alloc] initWithTarget:instance selector:@selector(execute) object:nil];
-        [instance execute];
-        sendUserNotification(APP_IDSTR, @"The I2P router is starting up.");
-        auto pid = [instance getPID];
-        return std::async(std::launch::async, [&pid]{
-          return pid;
-        });
-    }
-    @catch (NSException *e)
-	{
-        auto errStr = [NSString stringWithFormat:@"Expection occurred %@",[e reason]];
-		NSLog(@"%@", errStr);
-        sendUserNotification(APP_IDSTR, errStr);
-        return std::async(std::launch::async, [&]{
-          return 0;
-        });
-	}
-}
+#endif
 
-void openUrl(NSString* url)
-{
-    [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString: url]];
-}
-
-@implementation I2PStatusMenu
-
-- (BOOL)validateMenuItem:(NSMenuItem *)item
-{
-  NSLog(@"item is: %@",item);
-  return YES;
-}
 
+@implementation ExtractMetaInfo : NSObject
 @end
 
-@implementation MenuBarCtrl
-
-- (void) statusItemButtonLeftClick: (StatusItemButton *) button
-{
-  CFShow(CFSTR("Left button clicked!"));
-  NSEvent *event = [NSApp currentEvent];
-}
-
-- (void) statusItemButtonRightClick: (StatusItemButton *) button
-{
-  CFShow(CFSTR("Right button clicked!"));
-  NSEvent *event = [NSApp currentEvent];
-  [self.statusItem popUpStatusItemMenu: self.menu];
-}
-
-- (void)statusBarImageBtnClicked
-{
-  [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(btnPressedAction) userInfo:nil repeats:NO];
-}
-
-- (void)btnPressedAction:(id)sender
-{
-  NSLog(@"Button presseeeeeeed");
-  NSEvent *event = [NSApp currentEvent];
-}
-
-- (void) openRouterConsoleBtnHandler: (NSMenuItem *) menuItem
-{
-  NSLog(@"Clicked openRouterConsoleBtnHandler");
-  openUrl(@"http://127.0.0.1:7657");
-}
-
-- (void) startJavaRouterBtnHandler: (NSMenuItem *) menuItem
-{
-  NSLog(@"Clicked startJavaRouterBtnHandler");
-  AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
-  [appDelegate startupI2PRouter];
-}
-
-- (void) restartJavaRouterBtnHandler: (NSMenuItem *) menuItem
-{
-  NSLog(@"Clicked restartJavaRouterBtnHandler");
-  if (getGlobalRouterObject().has_value())
-  {
-      sendUserNotification(APP_IDSTR, @"Requesting the I2P router to restart.");
-      [getGlobalRouterObject().value() requestRestart];
-      NSLog(@"Requested restart");
-  }
-}
-
-- (void) stopJavaRouterBtnHandler: (NSMenuItem *) menuItem
-{
-  NSLog(@"Clicked stopJavaRouterBtnHandler");
-  if (getGlobalRouterObject().has_value())
-  {
-      sendUserNotification(APP_IDSTR, @"Requesting the I2P router to shutdown.");
-      [getGlobalRouterObject().value() requestShutdown];
-      NSLog(@"Requested shutdown");
-  }
-}
-
-- (void) quitWrapperBtnHandler: (NSMenuItem *) menuItem
-{
-  NSLog(@"quitWrapper event handler called!");
-  [[NSApplication sharedApplication] terminate:self];
-}
-
-- (MenuBarCtrl *) init
-{
-  self.menu = [self createStatusBarMenu];
-  self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
-
-  self.image = [NSImage imageNamed:@"ItoopieTransparent.png"];
-  [self.image setTemplate:YES];
-  self.statusItem.image = self.image;
-
-  self.statusItem.highlightMode = NO;
-  self.statusItem.toolTip = @"I2P Router Controller";
-
-  self.statusBarButton = [[StatusItemButton alloc] initWithImage:self.image];
-  self.statusBarButton.menu = self.menu;
-
-  // Selecting action
-  //[self.statusBarButton setAction:@selector(statusBarImageBtnClicked)];
-  //[self.statusBarButton setTarget:self];
-  self.statusBarButton.delegate = self;
-  [self.statusItem popUpStatusItemMenu: self.menu];
-
-  [self.statusItem setView: self.statusBarButton];
-  NSLog(@"Initialized statusbar and such");
-  return self;
-}
-
--(void) dealloc
-{
-  [self.image release];
-  [self.menu release];
-}
-
-- (I2PStatusMenu *)createStatusBarMenu
-{
-  I2PStatusMenu *menu = [[I2PStatusMenu alloc] init];
-  [menu setAutoenablesItems:NO];
-
-  NSMenuItem *openConsoleI2Pbtn =
-    [[NSMenuItem alloc] initWithTitle:@"Open Console"
-                        action:@selector(openRouterConsoleBtnHandler:)
-                        keyEquivalent:@""];
-  [openConsoleI2Pbtn setTarget:self];
-  [openConsoleI2Pbtn setEnabled:YES];
-
-  NSMenuItem *startI2Pbtn =
-    [[NSMenuItem alloc] initWithTitle:@"Start I2P"
-                        action:@selector(startJavaRouterBtnHandler:)
-                        keyEquivalent:@""];
-  [startI2Pbtn setTarget:self];
-  if ([self.userPreferences boolForKey:@"autoStartRouter"])
-  {
-    [startI2Pbtn setEnabled:NO];
-  } else {
-    [startI2Pbtn setEnabled:YES];
-  }
+@implementation AppDelegate
 
-  NSMenuItem *restartI2Pbtn =
-    [[NSMenuItem alloc] initWithTitle:@"Restart I2P"
-                        action:@selector(restartJavaRouterBtnHandler:)
-                        keyEquivalent:@""];
-  [restartI2Pbtn setTarget:self];
-  [restartI2Pbtn setEnabled:YES];
-
-  NSMenuItem *stopI2Pbtn =
-    [[NSMenuItem alloc] initWithTitle:@"Stop I2P"
-                        action:@selector(stopJavaRouterBtnHandler:)
-                        keyEquivalent:@""];
-  [stopI2Pbtn setTarget:self];
-  [stopI2Pbtn setEnabled:YES];
-
-  NSMenuItem *quitWrapperBtn =
-    [[NSMenuItem alloc] initWithTitle:@"Quit I2P Wrapper"
-                        action:@selector(quitWrapperBtnHandler:)
-                        keyEquivalent:@""];
-  [quitWrapperBtn setTarget:self];
-  [quitWrapperBtn setEnabled:YES];
-
-
-  [menu addItem:openConsoleI2Pbtn];
-  [menu addItem:startI2Pbtn];
-  [menu addItem:stopI2Pbtn];
-  [menu addItem:restartI2Pbtn];
-  [menu addItem:quitWrapperBtn];
-  return menu;
+- (void) awakeFromNib {
 }
 
-@end
-
-@implementation ExtractMetaInfo
-@end
-
-@implementation AppDelegate
+#ifdef __cplusplus
 
 - (void)extractI2PBaseDir:(void(^)(BOOL success, NSError *error))completion
 {
   std::string basePath([self.metaInfo.i2pBase UTF8String]);
   NSParameterAssert(self.metaInfo.i2pBase);
   NSError *error = NULL;
-  BOOL success;
+  BOOL success = NO;
   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
 
     // Get paths
@@ -312,7 +123,7 @@ void openUrl(NSString* url)
     cli.push_back(jarfile);
     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 = [self.metaInfo.javaBinary UTF8String];
     for_each(cli, [&execStr](std::string str){ execStr += std::string(" ") + str; });
 
@@ -337,7 +148,7 @@ void openUrl(NSString* url)
 
     // All done. Assume success and error are already set.
     dispatch_async(dispatch_get_main_queue(), ^{
-      sendUserNotification(APP_IDSTR, @"Extraction complete!", self.contentImage);
+      //sendUserNotification(APP_IDSTR, @"Extraction complete!", self.contentImage);
       if (completion) {
         completion(success, error);
       }
@@ -345,57 +156,27 @@ void openUrl(NSString* url)
   });
 }
 
-- (void)startupI2PRouter
-{
-  std::string basePath([self.metaInfo.i2pBase UTF8String]);
-
-  // Get paths
-  NSBundle *launcherBundle = [NSBundle mainBundle];
-  auto jarList = buildClassPath(basePath);
-  std::string classpathStrHead = "-classpath";
-  std::string classpathStr = "";
-  classpathStr += [[launcherBundle pathForResource:@"launcher" ofType:@"jar"] UTF8String];
-  std::string prefix(basePath);
-  prefix += "/lib/";
-  for_each(jarList, [&classpathStr](std::string str){ classpathStr += std::string(":") + str; });
-  //if (self.enableVerboseLogging) NSLog(@"Classpath: %@\n",[NSString stringWithUTF8String:classpathStr.c_str()]);
-
-  try {
-    auto argList = JavaRunner::defaultStartupFlags;
-
-    std::string baseDirArg("-Di2p.dir.base=");
-    baseDirArg += basePath;
-    std::string javaLibArg("-Djava.library.path=");
-    javaLibArg += basePath;
-    // TODO: pass this to JVM
-    auto java_opts = getenv("JAVA_OPTS");
-
-    argList.push_back([NSString stringWithUTF8String:baseDirArg.c_str()]);
-    argList.push_back([NSString stringWithUTF8String:javaLibArg.c_str()]);
-    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([self.metaInfo.javaBinary UTF8String]);
-
-
-    sendUserNotification(APP_IDSTR, @"I2P Router is starting up!", self.contentImage);
-    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]);
-  } catch (std::exception &err) {
-    auto errMsg = [NSString stringWithUTF8String:err.what()];
-    NSLog(@"Exception: %@", errMsg);
-    sendUserNotification(APP_IDSTR, [NSString stringWithFormat:@"Error: %@", errMsg], self.contentImage);
-  }
-}
+#endif
 
 - (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
                                shouldPresentNotification:(NSUserNotification *)notification {
     return YES;
 }
 
+
+#ifdef __cplusplus
+
+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;
+}
+
 - (NSString *)userSelectJavaHome:(JvmListPtr)rawJvmList
 {
   NSString *appleScriptString = @"set jvmlist to {\"Newest\"";
@@ -428,19 +209,21 @@ void openUrl(NSString* url)
   // TODO: Add logic so user can set preferred JVM
 }
 
+#endif
+
 - (void)setApplicationDefaultPreferences {
   auto defaultJVMHome = check_output({"/usr/libexec/java_home","-v",DEF_MIN_JVM_VER});
   auto tmpStdStr = std::string(defaultJVMHome.buf.data());
   trim(tmpStdStr);
   auto cfDefaultHome  = CFStringCreateWithCString(NULL, const_cast<const char *>(tmpStdStr.c_str()), kCFStringEncodingUTF8);
-  [self.userPreferences registerDefaults:@{
+  /*[self.userPreferences registerDefaults:@{
     @"javaHome" : (NSString *)cfDefaultHome,
     @"lastI2PVersion" : (NSString *)CFSTR(DEF_I2P_VERSION),
-    @"enableLogging": @true,
-    @"enableVerboseLogging": @true,
-    @"autoStartRouter": @true,
+    @"enableLogging": @YES,
+    @"enableVerboseLogging": @YES,
+    @"autoStartRouter": @YES,
     @"i2pBaseDirectory": (NSString *)CFStringCreateWithCString(NULL, const_cast<const char *>(getDefaultBaseDir().c_str()), kCFStringEncodingUTF8)
-  }];
+  }];*/
   if (self.enableVerboseLogging) NSLog(@"Default JVM home preference set to: %@", (NSString *)cfDefaultHome);
 
   auto dict = [self.userPreferences dictionaryRepresentation];
@@ -456,6 +239,10 @@ void openUrl(NSString* url)
 
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
   // Init application here
+  
+  SwiftMainDelegate *swiftRuntime = [[SwiftMainDelegate alloc] init];
+  swiftRuntime.applicationDidFinishLaunching;
+  
   [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];
   // Start with user preferences
   self.userPreferences = [NSUserDefaults standardUserDefaults];
@@ -464,44 +251,54 @@ void openUrl(NSString* url)
   self.enableVerboseLogging = [self.userPreferences boolForKey:@"enableVerboseLogging"];
 
 
-  // Get paths
-  NSBundle *launcherBundle = [NSBundle mainBundle];
-  auto iconImage = [launcherBundle pathForResource:@"ItoopieTransparent" ofType:@"png"];
-  self.contentImage = [NSImage imageNamed:iconImage];
+    // Get paths
+    NSBundle *launcherBundle = [NSBundle mainBundle];
+    //auto iconImage = [launcherBundle pathForResource:@"ItoopieTransparent" ofType:@"png"];
+  
+    // This is the only GUI the user experience on a regular basis.
+    //self.menuBarCtrl = [[MenuBarCtrl alloc] init];
 
+#ifdef __cplusplus
   gRawJvmList = std::make_shared<std::list<JvmVersionPtr> >(std::list<JvmVersionPtr>());
+#endif
   // In case we are unbundled, make us a proper UI application
   [NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
   [NSApp activateIgnoringOtherApps:YES];
-  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];
+  // TODO: Also check for new installations from time to time.
+  
+#ifdef __cplusplus
+  auto javaHomePref = [self.userPreferences stringForKey:@"javaHome"];
+  if (self.enableVerboseLogging)
+  {
+    NSLog(@"Java home from preferences: %@", javaHomePref);
+  }
 
-  NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
-  if (self.enableVerboseLogging) NSLog(@"Appdomain is: %@", appDomain);
+  if (self.enableVerboseLogging)
+  {
+    NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
+    NSLog(@"Appdomain is: %@", appDomain);
+  }
 
   NSLog(@"We should have started the statusbar object by now...");
+  RouterProcessStatus* routerStatus = [[RouterProcessStatus alloc] init];
 
   std::string i2pBaseDir(getDefaultBaseDir());
-  //if (self.enableVerboseLogging) printf("Home directory is: %s\n", buffer);
-
 
-  //[statusBarButton setAction:@selector(itemClicked:)];
-  //dispatch_async(dispatch_get_main_queue(), ^{
-  //});
   auto pref = self.userPreferences;
-  self.menuBarCtrl.userPreferences = self.userPreferences;
-  self.menuBarCtrl.enableLogging = self.enableLogging;
-  self.menuBarCtrl.enableVerboseLogging = self.enableVerboseLogging;
+  
+  bool shouldAutoStartRouter = false;
 
-
-
-  if (port_check() != 0)
+  if (port_check(7657) != 0)
   {
     NSLog(@"Seems i2p is already running - I will not start the router (port 7657 is in use..)");
+    sendUserNotification(@"Found already running router", @"TCP port 7657 seem to be used by another i2p instance.");
+    
+    [routerStatus setRouterStatus: true];
+    [routerStatus setRouterRanByUs: false];
     return;
+  } else {
+    shouldAutoStartRouter = true;
   }
 
   if (self.enableVerboseLogging) NSLog(@"processinfo %@", [[NSProcessInfo processInfo] arguments]);
@@ -513,21 +310,23 @@ void openUrl(NSString* url)
     if (val == NULL) val = @"";
     if (self.enableVerboseLogging) NSLog(@"Javahome: %@", val);
     auto javaHome = std::string([val UTF8String]);
-    trim(javaHome); // Trim to remove endline
+    //trim(javaHome); // Trim to remove endline
     auto javaBin = std::string(javaHome);
     javaBin += "/bin/java"; // Append java binary to path.
     return javaBin;
   };
 
 
+  //NSBundle *launcherBundle = [NSBundle mainBundle];
+    
   self.metaInfo = [[ExtractMetaInfo alloc] init];
-  self.metaInfo.i2pBase = [NSString stringWithUTF8String:i2pBaseDir.c_str()];
+  //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;
+  //basearg += i2pBaseDir;
 
   std::string jarfile("-cp ");
   jarfile += [self.metaInfo.zipFile UTF8String];
@@ -539,16 +338,16 @@ void openUrl(NSString* url)
     if (self.enableVerboseLogging) NSLog(@"I2P Directory don't exists!");
 
     [self extractI2PBaseDir:^(BOOL success, NSError *error) {
-        //__typeof__(self) strongSelf = weakSelf;
-        //if (strongSelf == nil) return;
-        [self startupI2PRouter];
+      sendUserNotification(@"I2P is done extracting", @"I2P is now installed and ready to run!");
+      NSLog(@"Done extracting I2P");
+      if (shouldAutoStartRouter) [self startupI2PRouter];
     }];
 
   } else {
-      if (self.enableVerboseLogging) NSLog(@"I2P directory found!");
-      [self startupI2PRouter];
+    if (self.enableVerboseLogging) NSLog(@"I2P directory found!");
+    if (shouldAutoStartRouter) [self startupI2PRouter];
   }
-
+#endif
 }
 
 
@@ -579,15 +378,11 @@ int main(int argc, const char **argv)
   NSApplication *app = [NSApplication sharedApplication];
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
 
-
-
   app.delegate = [[AppDelegate alloc] initWithArgc:argc argv:argv];
   [NSBundle loadNibNamed:@"I2Launcher" owner:NSApp];
 
   [NSApp run];
   // Handle any errors
-  //CFRelease(javaHomes);
-  //CFRelease(err);
   [pool drain];
   return 0;
 }
diff --git a/launchers/macosx/requirements.txt b/launchers/macosx/requirements.txt
new file mode 100644
index 0000000000..58c95be88f
--- /dev/null
+++ b/launchers/macosx/requirements.txt
@@ -0,0 +1 @@
+builddmg
-- 
GitLab