I got a Cocoa command-line program in which I try to run NSTask
program (tshark
to monitor network) and get data from it in real-time. So I make a
NSFileHandle
, call waitForDataInBackgroundAndNotify
to send notifications and then register my help class to Notification center to process the data, but not a single notification is sent to my help class.
Does anybody have an idea of what could be wrong?
Thanks in advance
Here is my code:
#import <Foundation/Foundation.h>
#import <string>
#import <iostream>
@interface toff : NSObject {}
-(void) process:(NSNotification*)notification;
@end
@implementation toff
-(void) process:(NSNotification*)notification{
printf("Packet caught!\n");
}
@end
int main (int argc, const char * argv[]){
@autoreleasepool {
NSTask* tshark = [[NSTask alloc] init];
NSPipe* p = [NSPipe pipe];
NSFileHandle* read = [p fileHandleForReading];
toff* t1 = [[toff alloc] init];
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[read waitForDataInBackgroundAndNotify];
[nc addObserver:t1 selector:@selector(process:) name:nil object:nil];
printf("Type 'stop' to stop monitoring network traffic.\n");
[tshark setLaunchPath:@"/usr/local/bin/tshark"];
[tshark setStandardOutput:p];
[tshark launch];
while(1){
std::string buffer;
getline(std::cin, buffer);
if(buffer.empty()) continue;
else if(buffer.compare("stop") == 0){
[tshark interrupt];
break;
}
}
//NSData* dataRead = [read readDataToEndOfFile];
//NSLog(@"Data: %@", dataRead);
//NSString* stringRead = [[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding];
//NSLog(@"Output: %@", stringRead);
}
return 0;
}
EDIT: When I uncomment commented section of code and delete all that notification stuff, all desired data are extracted from file handle after task finish.
I was also wondering, if problem can't be in fact, that my program is 'Command line tool' so I am not sure if it has run loop - as Apple documentation says is needed (in waitForDataInBackgroundAndNotify message of NSFileHandle):
You must call this method from a thread that has an active run loop.
Your program finishes immediately after launching the task. You need to tell the task to wait until exit. That will run the run loop, waiting for the child process to exit and coincidentally enabling the file handle to monitor the pipe. When the task does exit, the method will return and you can proceed to the end of
main
.