Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Display Control Manager
The Display Control Manager (KCM) is a piece of software used to abstract service discovery across many different connection types. For instance, when used on a machine that has Ethernet, WiFi, USB and Bluetooth networking, an application could signal a KCM process to look for services named "foo", and the KCM would perform service discovery across all connection types. This vastly reduces the complexity of applications by reducing service discovery implementations in applications to a single interface with the KCM. The KCM also operates in both publishing and discovery modes simultaneously, as long as the underlying service discovery mechanisms support it.
The syntax for the KCM command is:
kcm <private-SSL-key> <public-SSL-certificate>
The Kimberley Control Manager executes as a standalone process, receiving requests to publish or browse services over the D-Bus interprocess communication mechanism. The use of D-Bus both simplifies implementation by allowing KCM method calls to be defined in XML files. Here is the XML representation of the KCM's method calls:
<?xml version="1.0" encoding="UTF-8" ?> <node name="/edu/cmu/cs/kimberley/kcm"> <interface name="edu.cmu.cs.kimberley.kcm"> <method name="publish"> <arg type="s" name="service_name" direction="in" /> <arg type="u" name="port" direction="in" /> </method> <method name="browse"> <arg type="s" name="service_name" direction="in" /> <arg type="u" name="port" direction="out" /> </method> </interface> </node>
D-Bus applications translate XML files into C bindings using the rpcgen-like tool "dbus-binding-tool". Then, an application simply creates a D-Bus message following the above naming conventions to signal the KCM, rather than worrying about opening unix or network connections to the process. An additional advantage of using D-Bus is that the daemon can launch the destination applications of messages if they are not currently running, if a D-Bus service file is registered for the application. Since this occurs during KCM installation, applications are not required to execute the KCM on their own. Further, since many service discovery applications support D-Bus interfaces, the KCM may discover the service discovery applications available at runtime rather than requiring their installation and linking against them.
The KCM supports two types of messages, roughly corresponding to these C prototypes:
int publish(char *service_name, unsigned int port); int browse(char *service_name);
publish() is the server-side call which accepts a service name and a port on which the service can be connected to using TCP/IP. It takes the service name and registers it with as many different service discovery mechanisms as are installed on the system. It then spawns a thread which listens for incoming connections across each connection type. When this thread accepts a new connection, it unregisters the service name from each of the service discovery mechanisms and makes a local TCP connection to the service on the port provided. If the application would like to allow additional connections to this service, it can re-register the service whenever it sees that a new connection has been made. The thread then acts as a tunnel between the local connection to the service and the remote connection. The call handling thread in parallel returns an integer error message indicating if any part of the publishing process failed. If at any point either the local connection or remote connection is closed, the tunneling thread closes both of its sockets and destroys itself.
browse() accepts only the service name to search for. It spawns a browsing thread that immediately opens a locally listening socket to which the application can connect. The call handling thread returns as an integer value the port to which the socket is bound, so the application may continue while service discovery progresses. In parallel, the browsing thread searches using as many service discovery mechanisms as are installed on the system. Upon finding one or more matching services, the browsing thread uses an internal heuristic to choose the most desirable connection type, which is to choose Internet-based over Bluetooth-based connections. The browsing thread then creates the remote connection, accepts the local connection and acts as a tunnel between these two. If no matching services are found, the browsing thread accepts a local connection if one is pending, immediately closes it to indicate failure, and destroys itself.
Service Discovery Mechanisms
A different service discovery mechanism is used for each connection type. For Internet connections such as Ethernet and WiFi interfaces, Avahi is a popular open-source package for service discovery on local Internet subnets. Avahi is an implementation of Apple's version of the Zeroconf protocol, called Bonjour. Bonjour allows a local network of machines to publish and discover services without requiring any prior network configuration, using DNS SRV records to publish service types. This is opposed to Microsoft's version of Zeroconf which uses Universal Plug-And-Play (uPNP) combined with messages sent over HTTP. For Bluetooth connections, the standard Bluetooth Service Discovery Protocol (SDP) is used through the open-source BlueZ implementation. The KCM may also support other connection types in the future, but the applications using KCM do not need additional knowledge of these types, since it exports a generic service discovery interface.
Private Connections through Encryption
The publishing and browsing threads also take an additional step before beginning tunneling to encrypt the remote connection using the OpenSSL library. The private key and public certificate of the host machine are passed as parameters to the KCM command and are loaded at runtime. It is important to note that certificates are only used because they contain the public keys of the hosts used for encryption, and do not correspond to any form of authentication. Thus, they may be self-signed without worry and may be generated at any point in time before executing KCM.
When a publishing thread successfully establishes a connection, it calls
SSL_accept() passing the connected socket into the OpenSSL library. Likewise, the browsing thread calls
SSL_connect(), passing its connected socket in. These calls are performed before any application data is transferred on this link. Both SSL calls return an opaque data structure that serves as a handle to the SSL connection. If the calls succeed, future writes to the socket are performed using SSL_write on the returned data structure, and reads performed using SSL_read.
Thus, the KCM creates a thread per connection pair both in browsing and publishing services and provides a private communication channel between devices.