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

Reply via email to