On Monday, February 24, 2003, at 03:01 AM, Nathan Torkington wrote:

My friend Rael was wondering where the Perl implementation of
Rendezvous (zeroconf) is.  How do I register my service?  How do I
browse for local machines and services?

I don't have X.II to test this with, but nothing in the NSNetService or NSNetServiceBrowser Cocoa classes looks like it would be unusable from Perl. If you're using CamelBones to build your app - a big "if," of course, if it's a server app - all you'd need to do is add wrappers for those classes, like this:


@NSNetService::ISA = qw(Exporter NSObject);
@NSNetServiceBrowser::ISA = qw(Exporter NSObject);

(The above won't be necessary in 0.3 - it queries the Objective-C runtime, and automatically generates wrappers for all registered classes.)

After that, you'd publish your service like this:

# Assume that $svcDomain, $svcType, $svcName, and $svcPort have
# already been figured out

my $service = NSNetService->alloc()->initWithDomain_type_name_port(
        $svcDomain, $svcType, $svcName, $svcPort);
if ($service) {
        $service->setDelegate($self); # Or some other delegate object
        $service->publish();
}

There are various delegate methods you may wish to implement, none of them critical.

Browsing for services would look something like this:

my $serviceBrowser = NSNetServiceBrowser->alloc()->init();
$serviceBrowser->setDelegate($self); # Or some other...
$serviceBrowser->searchForServicesOfType_inDomain("_type._tcp", "");

There are definitely delegate methods you'll want to implement in this case. Searching is done asynchronously, and delegate methods are called with the results. Suppose, for example, that you're keeping a list of services in an instance variable '_services'. You could add discovered services to this list with this delegate method:

$OBJC_EXPORT{'netServiceBrowser:didFindService:moreComing:'} =
        {'args'=>'@@c', 'return'=>'v'};

sub netServiceBrowser_didFindService_moreComing {
        my ($self, $browser, $aService, $more) = @_;
        push @{$self->{'_services'}}, $aService;
}

Once you have a list of services, you need to resolve the address(es) of the service you're interested in. Assign the service object a delegate, and then call its resolve() method. The service object resolves the address(es) asynchronously, and then informs the delegate when it's done. Once the addresses have been resolved, you can get a list of them from the services object with the addresses() method.

The addresses are the only potential snag I see in the entire process - they're returned as an NSArray of NSData objects, each of which contains a sockaddr structure. Unfortunately, CB doesn't yet deal well with pointers to arbitrary data. So, you'll need to use description(), which returns a hex representation of the data, or one of the deserializeInt... methods to get at the structure data.

As I said - I don't have X.II, and I haven't tested any of this. It's all based on my ObjC/Perl translation of Apple's online docs for the NSNetService and NSNetServiceBrowser classes. If you decide to give it a try, I'd be interested in hearing about how it works out.

sherm--

Welcome to Rivendell, Mr. Anderson.



Reply via email to