The API design identifies three major components. There is a library of functions that can be called from the client application, a server process that accepts requests from the client library, and a client-supplied callback function for handling requests.
The client application first initializes its interface by calling an initialization function, and providing it with the address of a callback function. This starts a second thread of control (in the same memory space) that opens a port on which to receive network information, then receive-blocks on it until data arrives from the server. When the server sends a message to this port, the information is passed on to the callback function.
Having initialized the interface, the client application can register interest in network variables (current throughput, packet loss probability, etc.) by specifying a variable, a value (or range of values), and an operator (inside, outside, equal, etc.) to the API (e.g., loss probability > 2%). The client side then adds to this information the port number on which the callback thread is blocked, and sends it to the server.
The server is implemented as a separate heavyweight process. It waits for registrations from clients, specifying the conditions under which they would like to be alerted to changing network parameters. Whenever it receives a request, it updates its database of client requests, then checks all parameters that any client has interest in, compares them to the conditions under which each client has asked to be informed, and informs the appropriate clients. The network statistics are also checked periodically, should no requests arrive during that time.
Consider a ``chat'' program, i.e. a program that allows two users to establish a connection, and have keystrokes from both ends displayed promptly on both screens. Under favorable network conditions, this would generate one data packet for each keystroke or two, but during periods of poor network quality, the program might choose to send bundles of keystrokes whenever a ``transmission period'' expires.
When this application calls the initialization function, a child thread will be started that will open a port, communicate the port number back to the parent thread, then read-block on that port. The parent thread will note the port that its child has blocked on, then return to the user program. When the user application then calls the registration function, this port number will be combined with a condition (e.g., ``throughput < 10Mbps'') to generate a message that will be sent to the registration service at the server.
When the throughput is less than 10Mbps, the server will send a message to the blocked thread at the client, which will then call the user's callback function. In this way, the main part of the program is never required to explicitly check the network conditions, it just uses the transmission period variable set in the callback. In an actual application, the client program also specifies whether it wants to be informed upon crossing the specified threshold (in which case it would be notified when the throughput dropped below 10Mbps, and again when the throughput was no longer below 10Mbps), or it wants to be informed more often (in which case it would be notified when the throughput dropped below 10Mbps, and periodically reminded until it got better again).
This architecture has been implemented twice. One implementation runs on laptops under OS/2, the second implementation was done for Unix workstations. This allows us to design and implement ``mobile-enhanced'' applications in a wide variety of network scenarios, using the same API. The Unix workstations emulate cellular networks such as CDPD via a modified network device driver, with a throughput of 19.6 kbps. The laptops are equipped with WaveLan cards, roaming in one of three indoor cells at a nominal throughput of 2 Mbps. And the Unix workstations are connected to a 10 Mbps Ethernet as well as to a 100 Mbps FDDI ring. A number of applications are currently under development or modification, utilizing the API to adapt to these radically different wireless environments. The overview will discuss some of these applications (an e-mail reader, a groupware editor, an audio player), how they adapt to the changing network conditions, and what lessons we learned from these experiences.