The API for libopendaap seemed reasonable enough that I thought I could put together a simple crawler for iTunes shares in a few hours. Although this didn't quite happen, the situation still seems promising; with there being two possible approaches that I could take.
The first step is to build the library. The release notes claim that as of version 0.1.3 it should compile fine for Mac OS X. This it does, with the caveat that there must be no spaces in the path to the build directory (otherwise the
ar fails, and although I'm sure some makefile tweaking would fix this, the build process looked convoluted enough that I didn't want to deal with it). Once this is done, the result is
libopendaap.a in the
.libs directory (haven't quite figured out why it's a hidden directory, but it doesn't matter).
libopendaap is very self-contained, in that is also handles the Rendezvous/mDNS discovery of hosts. As a result, using it should be a simple matter of creating a new client with
DAAP_Client_Create, getting a list of machines with
DAAP_Client_EnumerateHosts, connecting to each one and then using
DAAP_ClientHost_GetDatabases to actually do the crawling. An initial run of code like this did nothing, in that no hosts were returned. A bit of skimming through the library codebase revealed that the host discovery is done asynchronously on a different thread. As a temporary hack, I added a
sleep(10) call between the client creation and host enumeration steps. This seemed to work, in that machines were being found, but as a whole the program was behaving very crappily (i.e. non-deterministically, suggesting threading issues, something I wasn't too thrilled to deal with).
After trying for a bit to trace the execution path and figure out what was going on, I decided to punt the issue and not use libopendaap's discovery at all. For now I could add hosts by hand (using the thoughtfully provided, if hack-labeled
DAAP_Client_AddHost) and eventually use the
CFNetServiceBrowser API built into Mac OS X's Core Foundation. This got me slightly further, but now the process failed in the connection stage, with it being returned an 403 (forbidden) HTTP status code when requesting the
/update?session-id=id&revision-number=1 URL (although the
/login requests were completed successfully). This seemed awfully familiar, i.e. it was at this point that iLeech and other DAAP libraries failed as well.
At this point, I began to doubt that libopendaap worked at all. To validate this, I dug up a VMware VM running Fedora and built the library there. I couldn't get tunesbrowser (a GTK app that uses the library) to build since I didn't have gstreamer installed, so I was reduced to running my own code. Discovery still didn't appear to work (there were no threading issues, but it didn't find any hosts either, despite my using bridged networking for the VM). However, if I specified a host by hand, it would connect successfully. Now that I have this known working case, it should be a matter of getting a few traces with tcpflow from both the Mac OS X and Linux builds, and seeing where the former goes wrong (it may be something as simple as an endian issue - I don't have a LinuxPPC install to verify this).
Alternatively, I can drop the libopendaap approach entirely, and try to base my crawler on another daap library. I'm not a big fan of the Hungarian notation that it uses in its codebase, and generally, although the API may be simple-looking, the insides seem grotty (and undocumented enough) that hacking on it to get it running on Mac OS X may be painful. As for what else I'd use, One2OhMyGod is a Java-based DAAP client that is new enough to work with iTunes 4.1 shares (not 4.5 ones, but apparently there is only a 1-byte difference in the hashing that the two use). However, I still haven't looked at its codebase to see whether it'd be any better, and from a "not reinventing the wheel" point of view, using a library that was meant for this (as opposed to hacking some functionality out of an app) is the better way to go.