On Aug 2, 2009, at 2:37 PM, Christiaan Hofman wrote: > I tried that but this also fails, slightly differently though. > > One point seems to be that -isValid does not seem to be correct. > When I check this in BibDesk, it also returns NO, but we know it > works. BTW, the port in your code is not nil. > > When I try my proposal, the it seems to work, including an > NSConnection. However when I try to send a DO message I get a log > (not an exception) saying > > *** NSDistantObject initWithCoder: 0x2 not given away for conn > 0x113140 > > Christiaan >
I have been able to get it to work with a single port. In fact in two ways. One is to both name and retrieve the port using NSSocketPortNameServer, this will still give two bonjour services to turn up in browsers. However, I can also get it to work /without/ NSSocketPortNameServer, so only one service shows up. Of course this won't be compatible with BibDesk's current code, so I don't think we should be using that, but it may be just nice to know. The crucial difference with what I tried before is that the sendPort is created using -initRemoteWithTCPPort:host:, getting the port from one of the netServices addresses. The code is below (slightly redacted to remove some unnecessary stuff). Christiaan #import <Foundation/Foundation.h> #import <sys/socket.h> #include <netinet/in.h> #include <unistd.h> @interface Server : NSObject { NSNetService *service; NSConnection *connection; } - (oneway void)connectClient:(byref id)client; @end @interface Browser : NSObject { NSNetServiceBrowser *browser; NSMutableArray *services; NSMutableArray *clients; } @end @interface Client : NSObject { NSNetService *service; NSConnection *connection; } - (id)initWithService:(NSNetService *)aNetService; @end static BOOL _getFamilyAndPort(NSData *addressData, uint16_t *family, uint16_t *port) { struct sockaddr *address = (struct sockaddr *)[addressData bytes]; if (address->sa_family == AF_INET) { NSLog(@"family is AF_INET"); if (family) *family = AF_INET; if (port) *port = ntohs(((struct sockaddr_in *)address)- >sin_port); return YES; } else if(address->sa_family == AF_INET6) { NSLog(@"family is AF_INET6"); if (family) *family = AF_INET6; if (port) *port = ntohs(((struct sockaddr_in6 *)address)- >sin6_port); return YES; } else { NSLog(@"unknown family"); return NO; } } @implementation Server - (id)init { if (self = [super init]) { NSString *sharingName = @"DO test name"; NSPort *receivePort = [NSSocketPort port]; connection = [[NSConnection alloc] initWithReceivePort:receivePort sendPort:nil]; [connection setRootObject:self]; uint16_t port = 0; _getFamilyAndPort([(NSSocketPort *)receivePort address], NULL, &port); NSLog(@"port = %d", port); service = [[NSNetService alloc] initWithDomain:@"" type:@"_mytest._tcp." name:sharingName port:port]; [service publishWithOptions:0]; } return self; } - (oneway void)connectClient:(byref id)client { NSLog(@"connectClient: %@", client); } @end @implementation Browser - (id)init { if (self = [super init]) { services = [NSMutableArray new]; clients = [NSMutableArray new; browser = [NSNetServiceBrowser new]; [browser setDelegate:self]; [browser searchForServicesOfType:@"_mytest._tcp." inDomain:@""]; } return self; } - (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser didFindService:(NSNetService *)aNetService moreComing:(BOOL)moreComing { NSLog(@"found service %@", aNetService); [services addObject:aNetService]; [aNetService setDelegate:self]; [aNetService resolveWithTimeout:5.0]; } - (void)netServiceDidResolveAddress:(NSNetService *)aNetService { NSLog(@"Did resolve %@", aNetService); [aNetService setDelegate:nil]; Client *client = [[[Client alloc] initWithService:aNetService] autorelease]; [clients addObject:client]; [services removeObject:aNetService]; } - (void)netService:(NSNetService *)aNetService didNotResolve:(NSDictionary *)errorDict { NSLog(@"Did not resolve %@", aNetService); [aNetService setDelegate:nil]; [services removeObject:aNetService]; } @end @implementation Client - (id)initWithService:(NSNetService *)aNetService { if (self = [super init]) { service = [aNetService retain]; NSData *addressData = [[service addresses] lastObject]; uint16_t family = 0, port = 0; _getFamilyAndPort(addressData, &family, &port); NSLog(@"port is %d", port); // this works only for AF_INET, but a remote connection only gets AF_INET6 //NSPort *sendPort = [[[NSSocketPort alloc] initRemoteWithProtocolFamily:family socketType:SOCK_STREAM protocol:IPPROTO_TCP address:addressData] autorelease]; NSPort *sendPort = [[[NSSocketPort alloc] initRemoteWithTCPPort:port host:[service hostName]] autorelease]; // isValid here always returns NO, even when things work NSLog(@"%d %@", [sendPort isValid], sendPort); connection = [[NSConnection alloc] initWithReceivePort:nil sendPort:sendPort]; [connection setRequestTimeout:60]; @try { [(Server *)[connection rootProxy] connectClient:self]; } @catch(id e) { NSLog(@"Caught exception %@", e); } } return self; } @end int main (int argc, char const *argv[]) { NSAutoreleasePool *pool = [NSAutoreleasePool new]; [Server new]; [Browser new]; [[NSRunLoop currentRunLoop] run]; [pool drain]; return 0; } ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Bibdesk-develop mailing list Bibdesk-develop@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/bibdesk-develop