The ServiceAccess Class and Zeroconf Discovery


A common feature of many of the Data Abstract for Cocoa samples is that they make use of Zeroconf to discover any instances of Relativity Server that are running on the local network. However as this is not directly related to demonstrating a particular feature of the Data Abstract SDK, the sample documentation doesn't cover what the ServiceAccess class is doing. The purpose of this document is to give you an overview of how the ServiceAccess class works so that you can potentially take advantage of this feature in your own or a customers environment.

If you haven't come across Zero Configuration Networking (Zeroconf) before, you may know it under the name that Apple uses for it; Bonjour. The purpose of Zeroconf is to automatically create a usable computer network where computers and other network capable devices are connected together without the user of the machine or devices having to do any manual configuration. Zeroconf is available out of the box on Mac OS X, on Linux/Unix you can use Avahi and on Windows you need to install iTunes1 or Bonjour Print Services2.

The Remoting SDK, that Data Abstract is built upon, provides built-in support for Zeroconf on all the platforms the SDK is available for and a Zeroconf service is installed on. The Remoting SDK implementation of Zeroconf is known as ROZeroConf and is based on the available open standards for Zeroconf.

ROZeroConf provides two major features: * Automated discovery of services running on the local network, without the need for any central infrastructure or discovery service. Simply be running ROZeroConf enabled services, they will be discoverable by clients. * registration and discovery of services globally across the internet with minimal configuration and a properly set up DNS server.

Using the ROZeroConfBrowser class all that is required is a few short lines to discover services running on the network that match a particular identifier. Enabling discoverability in your custom Data Abstract servers is even easier though its beyond the scope of this article.

You see an example of ROZeroConf in action any time you manage an instance of Relativity Server with the Server Explorer (Mac) or Relativity Admin Tool (Win) tools. When Relativity Server is run it automatically broadcasts to the network that it is available for discovery with the service name relativity_adminservice. The admin tools search for that service identifier and automatically display any server that is discovered on the local network.

Exploring the ServiceAccess class

The ServiceAccess class works in conjunction with the DataAccess and the AppDelegate classes to provide effortless discovery of instances of the Relativity Server running on the local network, so that when you are running one of the samples you can focus on understanding what the sample is doing rather than concerning yourself with establishing a link to a running server. Although if needed, the samples also provide a means of supplying an address manually if you need to use an instance of Relativity Server that is running on a machine that doesn't have the Zeroconf service available.

When sample starts the applicationDidFinishLaunching method of AppDelegate creates an singleton instance of the DataAccess class which in turn creates an instance of the ServiceAccess class. The AppDelegate registers itself as a delegate for the DataAccess class and then registers itself as handling the three notifications related to the discovery of a service (NOTIFICATION_FOUND_SERVICE), the disappearance of a service (NOTIFICATION_LOST_SERVICE) and that a connection to a service is established (NOTIFICATION_SERVICE_CONNECTED). Finally it calls the startBrowsing method of ServiceAccess which tells ROZeroConfBrowser] to start browsing the network for a particular service identifier.

Discovering a Server with Zeroconf

Looking a little more closely at ServiceAccess, the first time the zcBrowser property is accessed it creates an instance of the ROZeroConfBrowser class and assigns itself as the delegate for the ROZeroConfBrowser object (ROZeroConfBrowserDelegate). The init method (initWithServiceType) of ROZeroConfBrowser takes a string identifier of the service that is to be sought on the network. Here we pass RELATIVITY_SERVICE_NAME which in reality is simply relativity_adminservice.

To be a delegate of the ROZeroConfBrowser class, the ServiceAccess class needs to implement the following methods zeroConfBrowser:didFindService:moreComing and zeroConfBrowser:didRemoveService:moreComing. Those are called when a server is discovered on or disappears from the network.

Once a service is discovered the zeroConfBrowser:didFindService:moreComing method is called which posts a notification (NOTIFICATION_FOUND_SERVICE) that generally the AppDelegate class listens for and it is used to populate a UI element with the service name. (If there is only one discovered server and AUTO_CONFIGURE_FOR_FIRST_SERVICE is set to true, then it calls the ServiceAccess delegate's setupConnectionByIdentifier: method. However this isn't typically used)

Likewise when a service disappears the zeroConfBrowser:didRemoveService:moreComing method is called which posts the NOTIFICATION_LOST_SERVICE notification that generally the AppDelegate class listens for, so that particular service can be removed from the UI element's list of available servers.

When a service is selected from the UI, the ServiceAccess method setupConnectionByIdentifier is called passing in the name of the selected service. This name is converted into an identifier (either pulled from the list that ROZeroConfBrowser holds internally, or from those added manually by the user) that is passed to the setupConnectionWithService method of DataAccess which creates both a login and data service (using RORemoteService) and passes them to the DataAccess class's DARemoteDataAdapter. Control is then returned to setupConnectionByIdentifier which posts a NOTIFICATION_SERVICE_CONNECTED notification that (typically) the AppDelegate listens and uses to highlight the connected service in some way (like in a popup).

At this point the Sample has a DARemoteDataAdapter that is fully configured to work with an instance of Relativity Server.

NOTE: If you change AUTO_CONFIGURE_FOR_FIRST_SERVICE (defined at the top of ServiceAccess.m) to YES rather than NO, then the zeroConfBrowser:didFindService:moreComing method will call setupConnectionWithService on the first discovered service to immediately establish a connection to that service.

Manually registering a Server

The samples also provide a means for the user to manually specify an address for the server. The UI for this is not the same in the samples, but internally once the user has entered an address it is passed to the registerServerName method of the ServiceAccess class. This method ensures that the address adheres to the correct URL format and passes this url to the registerServer: method.

registerServer then creates an RORemoteService object which is stored in an internal dictionary of custom servers kept by ServiceAccess. The NOTIFICATION_SERVICE_CONNECTED notification is then posted and the connection to the server is immediately created by calling setupConnectionByIdentifier. (The assumption being that if the user is adding a url manually that they wish to connect to it now)

Some samples (those for iOS) use the unRegisterServer method of ServiceAccess to remove a manual address, that has been removed from a table of available servers.

NOTE: While the ServiceAccess class in the provided samples contains a serviceWithURL class method, it is not used by any samples. It demonstrates an alternative means of creating a RORemoteService class.

See Also

  1. This article on Adafruit mentions another method for installing the latest version of Bonjour/Zeroconf on your Windows machines. 

  2. Note that is you want/need version 3 of Bonjour that is only available via iTunes. The Bonjour Print Services is only version 2.0.2