XUDP is currently implemented as a UNIX daemon, as shown in Figure 4. Utilizing a separate process for the protocol implementation allows the protocol flow control to function asynchronously from the connected multimedia application and preserves the layered programming paradigm; only those functions related to the application programmers interface (API) are implemented in the user's process. However, this separation comes at the cost of an additional connection to move the data between the protocol's daemon process and the user's application. Fortunately, the connection exists only between two processes on the same machine, so it has been implemented with UNIX streams - yielding much lower system load than a TCP/IP implementation.
Figure 4 also depicts XUDP's positioning in the protocol stack. Implemented in user space, XUDP rests on top of the User Datagram Protocol (UDP), making use of UDP's highly refined payload checksum and port multiplexer. Future implementations of XUDP may choose to use raw IP, skipping UDP and removing a layer of complexity from the protocol.
From the application programmer's perspective, XUDP is accessed through a series of high-level Berkeley sockets-like functions: xudpSocket, xudpBind, xudpListen, xudpAccept, xudpConnect, xudpSend, xudpRecv and xudpClose. It effectively preserves the conceptual protocol layering scheme found in the TCP/IP protocol suite. Figure 5 illustrates the similarity of this interface to the existing Berkeley sockets API (the diagram is purposely similar to Stevens' Figure 6.2[7, p.261,]).
Shown below is an excerpt of a simple client application, showing the usage of xudpSocket, xudpConnect, xudpSend and xudpClose typically exhibited by clients. Important parameters are as follows: argv[1] contains the hostname of the remote application, buffer is a character buffer of length 10240 bytes and timed_ob is equal to the time until obsolescence in milliseconds for this parcel of data.
xudphost=xudpSocket(); xudpConnect(xudphost, argv[1], 0); if (xudpSend(xudphost, buffer, 10240, timed_ob)<=0) printf("Error!"); sleep(2); xudpClose(xudphost);
Excerpt from a simple client application.
Much of XUDP's functionality lies in the adoption of a new unit of internetworking data transfer named the parcel. A parcel is a single unit of inseparable data that is defined by the user's application, such as a frame in a video, a one second burst of audio or any number of imaginable constructs that require delivery as a whole. The size of each parcel is not fixed, and is set at the time that the parcel is sent from the application.
XUDP is capable of sending the parcel in one of three modes:
Unlike TCP, which transmits segments of a stream, parcels are not necessarily part of a continuous stream of data, and thus preserve record boundaries. A single parcel, comprising some indivisible cell of data such as a video frame, may be fragmented by XUDP; if this is the case, the receiver guarantees complete, in-order reassembly of data comprising a single parcel, or no delivery due to activation of the timed obsolescence mechanism. In addition, preservation of the timed obsolescence concept through the entire protocol stack necessitates selective acknowledgment and retransmission at the packet level. Although XUDP operates with a sliding window scheme, windowing is based on the typically MTU-sized packet as the fundamental unit of transmission, rather than the byte. XUDP can fill the network with as many packets as the window allows, waiting until the retransmission time out timer expires or an acknowledgment is received for either a packet or an entire parcel. Parcels are never delivered incomplete.
Many of XUDP's flow control algorithms have been modeled after enhancements to TCP implementations, documented in [1][4] and [5]. These flow control mechanisms include:
To manage selective acknowledgment and retransmission, as well as the timed obsolescence mechanism, XUDP organizes data as doubly-linked lists at various points in the transmission process. The queues are presented graphically in figure 6.
As data isn't presented in a stream, and parcel boundaries need to be preserved, intermediate buffers (fragmented parcels waiting for acknowledgment and fragmented, incompletely received parcels) are required to hold incomplete parcels. Upon activation of the timed obsolescence mechanism, the data comprising the obsolete parcel(s) is removed from these queues.