// Server/Client for vending an object either through a NSMessagePort or NSSocketPort #import #import "Protocol.h" // configure ------ /* use command line arguments * -NSLoopback * -NSSendback * -NSSocket YES = use SocketPort NO = use MessagePort * -NSConnection YES = use NSConnection NO = use port directly * -NSClient */ BOOL loopback=NO; // use a single socket for sending and receiving, otherwise compile as Zaurus-Server and Mac/Zaurus-Client BOOL sendback=NO; // send the received portmessage back BOOL useSocket=NO; // if YES, use NSSocketPort, if NO, use NSMessagePort BOOL useConnectionForClient=NO; // connect to the server through an NSConnection #ifdef __mySTEP__ BOOL client=NO; /* make Zaurus a Server by default */ #else BOOL client=YES; /* make Mac a Client by default */ #endif // end configure ------ @interface MyClass : NSObject @end @implementation MyClass - (NSString *) method; { NSLog(@"client calls -[MyClass method]"); return @"this is the instance of MyClass"; } - (bycopy NSString *) method2:(byref NSString *) arg; { NSLog(@"client calls -[MyClass method2:%@]", arg); NSLog(@"Arg class:%@", NSStringFromClass([arg class])); // should be a distant object NSLog(@"Arg connection:%@", [(NSDistantObject *) arg connectionForProxy]); // should be a distant object NSLog(@"All connections:%@", [NSConnection allConnections]); NSLog(@"Conversation:%@", [NSConnection currentConversation]); return @"result bycopy"; } @end @interface PortDelegate : NSObject // - (void)handlePortMessage:(NSPortMessage *)portMessage; @end @implementation PortDelegate - (void) invalidated:(NSNotification *) n { NSLog(@"invalidated NSPort: %@", [n object]); } #if 0 - (void) handleMachMessage:(void *) msg; { NSLog(@"received MachMessage: %@", [NSData dataWithBytes:msg length:64]); } #else - (void) handlePortMessage:(NSPortMessage *)portMessage; { static int cnt; BOOL b; NSSocketPort *s; // NSLog(@"runloop: %@", [NSRunLoop currentRunLoop]); NSLog(@"received NSPortMessage: %@", portMessage); NSLog(@" runloop mode: %@", [[NSRunLoop currentRunLoop] currentMode]); NSLog(@" msgid: %u", [portMessage msgid]); s=[portMessage sendPort]; NSLog(@" send: %p, %@, %@", s, s, NSStringFromClass([s class])); // is the port we should send the response to - this is DIFFERENT from the port created in main() if([s respondsToSelector:@selector(address)]) { NSLog(@" address=%@", [s address]); NSLog(@" protocol=%d", [s protocol]); NSLog(@" protocolFamily=%d", [s protocolFamily]); NSLog(@" socket=%d", [s socket]); NSLog(@" socketType=%d", [s socketType]); } NSLog(@" delegate=%@", [s delegate]); NSLog(@" reservedSpaceLength=%d", [s reservedSpaceLength]); s=[portMessage receivePort]; NSLog(@" recv: %p, %@", s, s); // is the originating port if([s respondsToSelector:@selector(address)]) { NSLog(@" address=%@", [s address]); NSLog(@" protocol=%d", [s protocol]); NSLog(@" protocolFamily=%d", [s protocolFamily]); NSLog(@" socket=%d", [s socket]); NSLog(@" socketType=%d", [s socketType]); } NSLog(@" delegate=%@", [s delegate]); NSLog(@" reservedSpaceLength=%d", [s reservedSpaceLength]); NSLog(@" comp: %@", [portMessage components]); [(NSMutableArray *) [portMessage components] addObject:[@"3" dataUsingEncoding:NSUTF8StringEncoding]]; // mutable - yes if(sendback && cnt++ < 3) { b=[portMessage sendBeforeDate:[NSDate dateWithTimeIntervalSinceNow:10.0]]; // send back if(!b) NSLog(@"send failed"); } else NSLog(@"no more replys"); } #endif @end int main(int argc, const char *argv[]) { NSAutoreleasePool *arp=[NSAutoreleasePool new]; NSPort *send; NSPort *recv; NSLog(@"config=%@", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]); loopback=[[NSUserDefaults standardUserDefaults] boolForKey:@"NSLoopback"]; // set by -NSLoopback sendback=[[NSUserDefaults standardUserDefaults] boolForKey:@"NSSendback"]; // send the received portmessage back useSocket=[[NSUserDefaults standardUserDefaults] boolForKey:@"NSSocket"]; // if YES, use NSSocketPort, if NO, use NSMessagePort useConnectionForClient=[[NSUserDefaults standardUserDefaults] boolForKey:@"NSConnection"]; // connect to the server through an NSConnection client=[[NSUserDefaults standardUserDefaults] boolForKey:@"NSClient"]; // server otherwise #if 0 { PortClass *p=[[PortClass new] autorelease]; // create new port NSConnection *c=[NSConnection connectionWithReceivePort:p sendPort:p]; NSLog(@"started"); NSLog(@"connection %@", c); [c setRootObject:[MyClass new]]; // vend some object NSLog(@"root object: %@", [c rootObject]); [c registerName:@"fexpserver" withNameServer:[NameServerClass sharedInstance]]; NSLog(@"registered as fexpserver"); NSLog(@"connections %@", [NSConnection allConnections]); } #endif if(useSocket) { if(loopback) { recv=send=[[NSSocketPort alloc] initWithTCPPort:4550]; // connect to self } else if(client) { send=[[NSSocketPort alloc] initRemoteWithTCPPort:4550 host:@"192.168.129.201"]; // run as client connecting the server recv=[[NSSocketPort alloc] initWithTCPPort:4551]; // use a second port to receive from } else { // server recv=send=[[NSSocketPort alloc] initWithTCPPort:4550]; // run as a server and publish #ifdef __mySTEP__ // [[NSPortNameServer systemDefaultPortNameServer] registerPort:recv name:@"port"]; // this blocks for 1.0 seconds for socketports (due to ZeroConf publishing) #endif } } else { if(loopback) { recv=send=[[NSMessagePort alloc] init]; } else if(client) { send=[[NSMessagePortNameServer sharedInstance] portForName:@"port"]; // recv=nil - > NSConnection would alloc a second port... recv=[[NSMessagePort alloc] init]; // use a second port to receive on } else { // server recv=send=[[NSMessagePort alloc] init]; #ifdef __mySTEP__ [[NSPortNameServer systemDefaultPortNameServer] registerPort:recv name:@"port"]; // this blocks for 1.0 seconds for socketports (due to ZeroConf publishing) #endif } } if(!useConnectionForClient) { // otherwise, the NSConnection should do all setups [send setDelegate:[PortDelegate new]]; if(recv != send) [recv setDelegate:[send delegate]]; // make same [[NSNotificationCenter defaultCenter] addObserver:[send delegate] selector:@selector(invalidated:) name:NSPortDidBecomeInvalidNotification object:nil]; } [recv scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; // listen on otherport for incoming connection and data NSLog(@"send=%@ %p", send, send); if([send respondsToSelector:@selector(address)]) { NSLog(@" address=%@", [send address]); NSLog(@" protocol=%d", [send protocol]); NSLog(@" protocolFamily=%d", [send protocolFamily]); NSLog(@" socket=%d", [send socket]); NSLog(@" socketType=%d", [send socketType]); } NSLog(@" delegate=%@", [send delegate]); NSLog(@" reservedSpaceLength=%d", [send reservedSpaceLength]); NSLog(@"recv=%@ %p", recv, recv); if([recv respondsToSelector:@selector(address)]) { NSLog(@" address=%@", [recv address]); NSLog(@" protocol=%d", [recv protocol]); NSLog(@" protocolFamily=%d", [recv protocolFamily]); NSLog(@" socket=%d", [recv socket]); NSLog(@" socketType=%d", [recv socketType]); } NSLog(@" delegate=%@", [recv delegate]); NSLog(@" reservedSpaceLength=%d", [send reservedSpaceLength]); NSLog(@" *** end of initialization *** \n\n\n"); #if 0 // to test how arguments are passed to NSInvocation NS_DURING [send method2:@"with arg"]; // an NSPort does not understand, so this calls forwardInvocation which raises an exception NS_HANDLER NS_ENDHANDLER #endif if(useConnectionForClient) { // connect through an NSConnection NSConnection *c=[NSConnection connectionWithReceivePort:recv sendPort:send]; // create a new connection if(client || loopback) { NSDistantObject *proxy; NSString *res; proxy=[c rootProxy]; // this should block until connected and response received NSLog(@"proxy=%@", proxy); [proxy setProtocolForProxy:@protocol(MyServer)]; NSLog(@"calling proxy's method=%@", [proxy method]); NSLog(@"calling proxy's method2=%@", [proxy method2:@"some string"]); NSLog(@"calling proxy's method2 again=%@", res=[proxy method2:@"some other string"]); NSLog(@"calling proxy's method2 again returning server's copy=%@", [proxy method2:res]); } else { // server [c setRootObject:[MyClass new]]; // object to vend } } else { if(client || loopback) { BOOL b=[send sendBeforeDate:[NSDate dateWithTimeIntervalSinceNow:10.0] msgid:12 components:[NSMutableArray arrayWithObjects: [@"123" dataUsingEncoding:NSUTF8StringEncoding], [NSData data], // empty component [@"987654321" dataUsingEncoding:NSUTF8StringEncoding], // send, // recv, // [[NSMessagePort alloc] init], // sending a NSMessagePort through an NSSocketPort doesn't work on MacOS X nil] from:recv // must not be nil or it fails! reserved:100]; if(!b) NSLog(@"send failed"); else NSLog(@"did send"); } } NSLog(@"running loop in default mode"); [[NSRunLoop currentRunLoop] run]; NSLog(@"loop done"); [arp release]; exit(0); }