source: launchers/macosx/RouterTask.mm @ 5ed701d

Last change on this file since 5ed701d was 2233f7f, checked in by meeh <meeh@…>, 23 months ago

Mac OSX Launcher:

  • Update readme about event manager
  • RouterTask? can now detect a running router by scanning processes&arguments for i2p.jar
  • The logger will log to OSX's default: ~/Library/Logs?/I2P/[whatever].log
  • Property mode set to 100644
File size: 5.5 KB
Line 
1#include "RouterTask.h"
2
3#include <dispatch/dispatch.h>
4#include <future>
5#include <stdlib.h>
6
7#ifdef __cplusplus
8#include "include/subprocess.hpp"
9#import "I2PLauncher-Swift.h"
10#include "AppDelegate.h"
11
12#include <assert.h>
13#include <errno.h>
14#include <stdbool.h>
15#include <sys/sysctl.h>
16#endif
17
18#include "include/PidWatcher.h"
19
20#import <AppKit/AppKit.h>
21#import <Foundation/Foundation.h>
22
23@implementation RTaskOptions
24@end
25
26@implementation I2PRouterTask
27
28- (void)routerStdoutData:(NSNotification *)notification
29{
30    NSLog(@"%@", [[NSString alloc] initWithData:[notification.object availableData] encoding:NSUTF8StringEncoding]);
31    [notification.object waitForDataInBackgroundAndNotify];
32}
33
34- (instancetype) initWithOptions : (RTaskOptions*) options
35{
36  self.userRequestedRestart = NO;
37  self.isRouterRunning = NO;
38  self.routerTask = [NSTask new];
39  self.processPipe = [NSPipe new];
40  [self.routerTask setLaunchPath:options.binPath];
41  [self.routerTask setArguments:options.arguments];
42  NSDictionary *envDict = @{
43    @"I2PBASE": options.i2pBaseDir
44  };
45  [self.routerTask setEnvironment: envDict];
46  NSLog(@"Using environment variables: %@", envDict);
47  [self.routerTask setStandardOutput:self.processPipe];
48        [self.routerTask setStandardError:self.processPipe];
49
50  [self.routerTask setTerminationHandler:^(NSTask* task) {
51    // Cleanup
52    NSLog(@"termHandler triggered!");
53    [[[RouterProcessStatus alloc] init] triggerEventWithEn:@"router_stop" details:@"normal shutdown"];
54    [[SBridge sharedInstance] setCurrentRouterInstance:nil];
55    sendUserNotification(APP_IDSTR, @"I2P Router has stopped");
56  }];
57  return self;
58}
59
60- (void) requestShutdown
61{
62    [self.routerTask interrupt];
63}
64
65- (void) requestRestart
66{
67    self.userRequestedRestart = YES;
68    kill([self.routerTask processIdentifier], SIGHUP);
69}
70
71- (BOOL) isRunning
72{
73    return self.routerTask.running;
74}
75
76- (int) execute
77{
78    @try {
79      [self.routerTask launch];
80      self.isRouterRunning = YES;
81      return 1;
82    }
83    @catch (NSException *e)
84        {
85                NSLog(@"Expection occurred %@", [e reason]);
86    self.isRouterRunning = NO;
87    [[[RouterProcessStatus alloc] init] triggerEventWithEn:@"router_exception" details:[e reason]];
88    [[SBridge sharedInstance] setCurrentRouterInstance:nil];
89    sendUserNotification(@"An error occured, can't start the I2P Router", [e reason]);
90    return 0;
91        }
92}
93
94- (int) getPID
95{
96  return [self.routerTask processIdentifier];
97}
98
99@end
100
101typedef struct kinfo_proc kinfo_proc;
102
103@implementation IIProcessInfo
104- (id) init
105{
106  self = [super init];
107  if (self != nil)
108  {
109    numberOfProcesses = -1; // means "not initialized"
110    processList = NULL;
111  }
112  return self;
113}
114
115- (int)numberOfProcesses
116{
117  return numberOfProcesses;
118}
119
120- (void)setNumberOfProcesses:(int)num
121{
122  numberOfProcesses = num;
123}
124
125- (int)getBSDProcessList:(kinfo_proc **)procList
126   withNumberOfProcesses:(size_t *)procCount
127{
128#ifdef __cplusplus
129  int             err;
130  kinfo_proc *    result;
131  bool            done;
132  static const int    name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
133  size_t          length;
134 
135  // a valid pointer procList holder should be passed
136  assert( procList != NULL );
137  // But it should not be pre-allocated
138  assert( *procList == NULL );
139  // a valid pointer to procCount should be passed
140  assert( procCount != NULL );
141 
142  *procCount = 0;
143  result = NULL;
144  done = false;
145 
146  do
147  {
148    assert( result == NULL );
149   
150    // Call sysctl with a NULL buffer to get proper length
151    length = 0;
152    err = sysctl((int *)name,(sizeof(name)/sizeof(*name))-1,NULL,&length,NULL,0);
153    if( err == -1 )
154      err = errno;
155   
156    // Now, proper length is optained
157    if( err == 0 )
158    {
159      result = (kinfo_proc *)malloc(length);
160      if( result == NULL )
161        err = ENOMEM;   // not allocated
162    }
163   
164    if( err == 0 )
165    {
166      err = sysctl( (int *)name, (sizeof(name)/sizeof(*name))-1, result, &length, NULL, 0);
167      if( err == -1 )
168        err = errno;
169     
170      if( err == 0 )
171        done = true;
172      else if( err == ENOMEM )
173      {
174        assert( result != NULL );
175        free( result );
176        result = NULL;
177        err = 0;
178      }
179    }
180  }while ( err == 0 && !done );
181 
182  // Clean up and establish post condition
183  if( err != 0 && result != NULL )
184  {
185    free(result);
186    result = NULL;
187  }
188 
189  *procList = result; // will return the result as procList
190  if( err == 0 )
191    *procCount = length / sizeof( kinfo_proc );
192  assert( (err == 0) == (*procList != NULL ) );
193  return err;
194}
195
196- (void)obtainFreshProcessList
197{
198  int i;
199  kinfo_proc *allProcs = 0;
200  size_t numProcs;
201  NSString *procName;
202 
203  int err =  [self getBSDProcessList:&allProcs withNumberOfProcesses:&numProcs];
204  if( err )
205  {
206    numberOfProcesses = -1;
207    processList = NULL;
208   
209    return;
210  }
211 
212  // Construct an array for ( process name, pid, arguments concat'ed )
213  processList = [NSMutableArray arrayWithCapacity:numProcs];
214  for( i = 0; i < numProcs; i++ )
215  {
216    int pid = (int)allProcs[i].kp_proc.p_pid;
217    procName = [NSString stringWithFormat:@"%s, pid %d, args: %s", allProcs[i].kp_proc.p_comm, pid, getArgvOfPid(pid).c_str()];
218    [processList addObject:procName];
219  }
220 
221  [self setNumberOfProcesses:(int)numProcs];
222  free( allProcs );
223#endif
224}
225
226
227- (BOOL)findProcessWithStringInNameOrArguments:(NSString *)procNameToSearch
228{
229  BOOL seenProcessThatMatch = NO;
230  for (NSString* processInfoStr in processList) {
231    if ([processInfoStr containsString:procNameToSearch]) {
232      seenProcessThatMatch = YES;
233      break;
234    }
235  }
236  return seenProcessThatMatch;
237}
238@end
Note: See TracBrowser for help on using the repository browser.