source: launchers/macosx/obj-cpp/RouterTask.mm @ f9fbc76

Last change on this file since f9fbc76 was f9fbc76, checked in by meeh <meeh@…>, 2 years ago

Code changes:

  • Port check to see if i2p is already running.
  • All buttons in the menu should work now.
  • Rewrote some C++ to Objective-C, which fits better with the integration.
  • Misc cleanup.
  • Made the launch of router repeatable.
  • Property mode set to 100644
File size: 4.5 KB
Line 
1#include "RouterTask.h"
2
3#include <dispatch/dispatch.h>
4#include <future>
5#include <stdlib.h>
6
7#include "optional.hpp"
8#include "subprocess.hpp"
9#include "PidWatcher.h"
10
11#import <AppKit/AppKit.h>
12
13@implementation RTaskOptions
14@end
15
16@implementation I2PRouterTask
17
18
19- (void)routerStdoutData:(NSNotification *)notification
20{
21    NSLog(@"%@", [[NSString alloc] initWithData:[notification.object availableData] encoding:NSUTF8StringEncoding]);
22    [notification.object waitForDataInBackgroundAndNotify];
23}
24
25- (instancetype) initWithOptions : (RTaskOptions*) options
26{
27    self.userRequestedRestart = NO;
28    self.isRouterRunning = NO;
29    self.input = [NSFileHandle fileHandleWithStandardInput];
30    self.routerTask = [NSTask new];
31    self.processPipe = [NSPipe new];
32    [self.routerTask setLaunchPath:options.binPath];
33    [self.routerTask setArguments:options.arguments];
34    NSDictionary *envDict = @{
35        @"I2PBASE": options.i2pBaseDir
36    };
37    [self.routerTask setEnvironment: envDict];
38    [self.routerTask setStandardOutput:self.processPipe];
39        [self.routerTask setStandardError:self.processPipe];
40
41    NSFileHandle *stdoutFileHandle = [self.processPipe fileHandleForReading];
42    [[NSNotificationCenter defaultCenter] addObserver:self
43        selector:@selector(routerStdoutData:)
44        name:NSFileHandleDataAvailableNotification
45        object:stdoutFileHandle];
46
47    [stdoutFileHandle waitForDataInBackgroundAndNotify];
48
49    [self.routerTask setTerminationHandler:^(NSTask* task) {
50        NSLog(@"termHandler triggered!");
51        NSBundle *launcherBundle = [NSBundle mainBundle];
52        auto iconImage = [launcherBundle pathForResource:@"ItoopieTransparent" ofType:@"png"];
53        sendUserNotification(APP_IDSTR, @"I2P Router has stopped", [NSImage imageNamed:iconImage]);
54        // Cleanup
55        self.isRouterRunning = NO;
56    }];
57/*
58    self.readLogHandle = [self.processPipe fileHandleForReading];
59    NSData *inData = nil;
60    self.totalLogData = [[[NSMutableData alloc] init] autorelease];
61
62    while ((inData = [self.readLogHandle availableData]) &&
63        [inData length]) {
64        [self.totalLogData appendData:inData];
65    }
66*/
67    return self;
68}
69
70- (void) requestShutdown
71{
72    [self.routerTask interrupt];
73}
74
75- (void) requestRestart
76{
77    self.userRequestedRestart = YES;
78    kill([self.routerTask processIdentifier], SIGHUP);
79}
80
81- (BOOL) isRunning
82{
83    return self.routerTask.running;
84}
85
86- (int) execute
87{
88    @try {
89        [self.routerTask launch];
90        watchPid([self.routerTask processIdentifier]);
91        self.isRouterRunning = YES;
92        return 1;
93    }
94    @catch (NSException *e)
95        {
96                NSLog(@"Expection occurred %@", [e reason]);
97        return 0;
98        }
99}
100
101- (int) getPID
102{
103    return [self.routerTask processIdentifier];
104}
105
106@end
107
108
109
110
111using namespace subprocess;
112
113const std::vector<NSString*> JavaRunner::defaultStartupFlags {
114    @"-Xmx512M",
115    @"-Xms128m",
116    @"-Djava.awt.headless=true",
117    @"-Dwrapper.logfile=/tmp/router.log",
118    @"-Dwrapper.logfile.loglevel=DEBUG",
119    @"-Dwrapper.java.pidfile=/tmp/routerjvm.pid",
120    @"-Dwrapper.console.loglevel=DEBUG"
121};
122
123const std::vector<std::string> JavaRunner::defaultFlagsForExtractorJob {
124    "-Xmx512M",
125    "-Xms128m",
126    "-Djava.awt.headless=true"
127};
128
129JavaRunner::JavaRunner(std::string& javaBin, std::string& arguments, std::string& i2pBaseDir, const fp_proc_t& execFn, const fp_t& cb)
130  : javaBinaryPath(javaBin), javaRouterArgs(arguments), _i2pBaseDir(i2pBaseDir), executingFn(execFn), exitCallbackFn(cb)
131{
132  execLine = javaBinaryPath;
133  execLine += " " + std::string(javaRouterArgs.c_str());
134  printf("CLI: %s\n",execLine.c_str());
135  javaProcess = std::shared_ptr<Popen>(new Popen(execLine, environment{{
136            {"I2PBASE", _i2pBaseDir},
137            {"JAVA_OPTS", getenv("JAVA_OPTS")}
138        }}, defer_spawn{true}));
139}
140
141void JavaRunner::requestRouterShutdown()
142{
143    // SIGHUP
144    javaProcess->kill(1);
145}
146
147std::experimental::optional<std::future<int> > JavaRunner::execute()
148{
149  try {
150    auto executingFn = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, ^{
151      this->executingFn(this);
152    });
153    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), executingFn);
154    dispatch_block_wait(executingFn, DISPATCH_TIME_FOREVER);
155
156    // Here, the process is done executing.
157
158    printf("Finished executingFn - Runs callbackFn\n");
159    this->exitCallbackFn();
160    return std::async(std::launch::async, []{ return 0; });
161  } catch (std::exception* ex) {
162    printf("ERROR: %s\n", ex->what());
163    return std::experimental::nullopt;
164  }
165}
Note: See TracBrowser for help on using the repository browser.