Article Title : xremote_protocol Creation Date : unknown Author : unknown Last Update : 6-1-93 Last Update By : NCD Technical Support Expiration Rules : ============================================================================= The XRemote Serial-Line Protocol Jim Fulton 11 December 1991 1. What is XRemote? XRemote is the name of a transport protocol developed by NCD for combining X request/reply streams over a serial line. Unlike SLIP, which routes TCP/IP packets directly from the application to the display, XRemote uses a "pseudo-server" (similar in concept to xscope) which multiplexes the client streams together and reduces by as much as a factor of 10 the amount of data that has to be transmitted over the wire. The X display demultiplexes the incoming data to recreate the individual streams. 2. How XRemote is Currently Used To start an XRemote session, a user currently invokes a builtin terminal emulator that uses a serial port from the X display to connect to a host (either through a modem or a direct connection) and login. Then, a program called "xinitremote" is run on the host which: o finds an unused X display number, o starts the host-side pseudo-server "helper" as host:number, o sets the client's DISPLAY variable to point to the pseudo-server, and o sends a special escape sequence which the serial line driver in the receiver recognizes as an instruction to treat all further data as XRemote protocol. At this point, applications connect to the pseudo-server as if it were a normal X display. When the first client started exits, the pseudo-server disconnects all of its X clients, instructs the X display to treat further data as normal terminal emulator data, and exits (in retrospect, the designer of XRemote says that the pseudo-server should have just waited for the X server to tell it to shut down). 3. What does the Pseudo-Server Do? The host-side pseudo-server is responsible for combining the X application streams together, removing X-specific redundancies, compressing the resulting data, and transmitting it over the serial line. 3.1. The Muxer The first task of the pseudo-server is to manage the network connections to the X clients and to multiplex their request streams. Instead of using a separate framing or encapsulation protocol, the individual request streams are merged on request boundaries and are delimited by special X-style extension requests that instruct the receiving end to either: o create a new client stream, o kill a given client stream, or o direct subsequent requests to a given client stream. In determining how to merge the request streams, the muxer watches for any GrabServer requests. When one is encountered, all other client streams are blocked (no further data are read and existing data are not transmitted) until a corresponding UngrabServer is found or the grabbing client is shut down. This reduces the amount of data that has to be buffered within the display and conveniently helps to expedite transmission of the grabbing client's requests. Note that the grab and ungrab requests are still transmitted to the X server so that any already buffered requests and local client streams are dealt with correctly. X X X \ | / +---------------+ | pseudo-server | | muxer | +---------------+ | ... Switch to Client A DrawSegment QueryPointer Switch to Client B CreateWindow ... | Several operations are performed on the resulting stream of requests. When the X display finally receives the data, the XRemote instructions are stripped out and the remaining requests are routed to the appropriate client streams. 3.2 The Delta Compactor One of the advantages of using X-style delimiters is that the resulting stream is still a flat sequence of small packets (instead of nesting the X packets inside separate framing packets). This simplifies the decoding of packets so that redundancies can be removed. The pseudo-server keeps a cache of the 16 most-recently sent requests. Each packet is then compared to any packets in the cache that are of the same length. If the packet can be represented as a difference of fewer than 8 bytes against a preceding packet, the delta is sent in place of the original packet. | +-----------------+ | delta compactor | +-----------------+ | ... delta from packet #622 DrawArc delta from packet #591 ... | The receiving side also keeps the same cache and applies the deltas to obtain the original packet. 3.3 The General Compressor The sequence of deltas and packets is then run through an LZW filter which balances the conflicting needs of delaying long enough to coalesce data efficiently without interfering with timely delivery. | +----------------+ | LZW compressor | +----------------+ | chunk chunk ... | The size of the chunks are chosen to match the capabilities of the transport layer to avoid fragmentation and reassembly. If the compressed chunk is larger than the plaintext from which it was generated, the plaintext is transmitted instead. 3.4 Transport The sequence of compressed chunks is transmitted over the serial line using a simple sliding-window, reliable (i.e. checksummed) datagram mechanism. At the time that XRemote was developed, neither PPP nor CSLIP were (or are yet truly) widely available. In addition to the increased throughput that such a tightly focused transport (which did not require any routing since the receiver was guaranteed to be the destination) provides, it also obviates the need to have separate network addresses for each display. | +------------------+ | Simple, Reliable | | Datagram | +------------------+ | framed packet ... This scheme does have the limitation that the XRemote data monopolizes the serial line, preventing other services from being used. A more general point-to-point mechanism (even a non-routing one) will allow the remote display to be a full participant on the application network. We anticipate that the Low-Bandwidth X standard will have to encompass both styles of transport. 3.5 Other Services As mentioned above, one of the problems with not having an actual network address is that services that are normally taken for granted on a network are not available. In particular, this forces the protocol to provide support for obtaining fonts and the color database. Furthermore, depending on how access control is implemented, means of determining hostnames and authentication must be provided. 3.6 X server to Pseudo-Server Communication Just as the pseudo-server inserts request-style messages into the request stream being sent to the display, the X server inserts event-style messages into the return stream whenever it needs to obtain data from the host-side. The pseudo-server intercepts these special events, performs the requested action, and returns that necessary information by way of another special request. 4. XRemote Protocol The XRemote protocol merges the client streams and adds several special packets of its own. 4.1 Pseudo-Server to X Server The following packets are injected into the stream sent from the pseudo-server to the X display. Instead of allocating an X extension to use as the major opcode for its request, XRemote uses opcode values 250-255 and "escapes" any X requests with those opcodes (which typically are only generated by test suites since XRemote products allocate X extension major opcodes up from 128). EscapeRequest This request is emitted before any X requests that collide with opcodes used by XRemote (250-255). FileReadData transaction_id CARD8 error INT32 offset CARD32 data_length CARD32 (m) data LISTofBYTE This request provides file data that was requested by an earlier FileRead operation sent from the X server. The TRANSACTION_ID corresponds to the value given in the initiating FileRead and identifies the read operation to which the DATA belongs. The ERROR value is 0 if the read was successful else it is set to the UNIX error code (e.g. ENOMEM) or the value EOF that generated the error condition. The OFFSET value and DATA_LENGTH specifies from where in the file the data was obtained. NewRequestClient client_id CARD8 client_setup_data LISTofBYTE => server_setup_data LISTofBYTE This request instructs the X server to create a new virtual client connection associated with the value CLIENT_ID and then perform an implicit ChangeRequestClient to the new client. The normal X connection setup protocol is then passed through. CloseRequestClient client_id CARD8 This request instructs the X server to destroy the virtual client connection associated with the value CLIENT_ID. The X server responds as if the client had closed its connection. The pseudo-server must not reuse this identifier until it has received an acknowledging CloseReplyClient from the X server. ChangeRequestClient client_id CARD8 This request specifies which virtual client connection within the X server should receive all subsequent X requests (until the next ChangeClient). RequestDelta whichmask CARD8 deltas LISTofDELTA where DELTA: [ byte: CARD8, data: CARD8 ] This request specifies a given X request in terms of byte differences against a preceding request. The most-significant four bits of WHICHMASK specify the number of bytes that are different; the least-significant four bits specify the index of the request cache entry against which the DELTAS should be applied. 4.2 X server to Pseudo-Server The following X event-like packets are injected into the stream sent from the X display to the pseudo-server. EscapeReply This "event" is emitted before any X replies, events, or errors that would have a type field that collides with an of the XRemote reply types (numbers 249-255), should this ever happen. ReadFile transaction_id CARD8 offset CARD32 bytestoread CARD32 filename_length CARD32 filename LISTofCHAR This "event" instructs the pseudo-server to read data from the file specified by FILENAME. The data is returned using the FileReadData request. Multiple file reads may be performed at once by issuing separate TRANSACTION_ID values (which may be thought of loosely as file descriptors). The OFFSET and BYTESTOREAD specify which data in FILENAME are to be sent (equivalent to a UNIX seek() and read()). The pseudo-server may keep any file descriptors it opens to satisfy the event until a ReadFileDone event for the TRANSACTION_ID is sent. ReadFileDone transaction_id CARD8 This "event" notifies the pseudo-server that TRANSACTION_ID should no longer be associated with any open file. The pseudo-server must close any associated file descriptors. CloseReplyClient client_id CARD8 This "event" notifies the pseudo-server that the connection associated with CLIENT_ID has been broken, typically by an X KillClient operation. The pseudo-server should break the network connection and release any storage it has allocated on behalf of that client. ChangeReplyClient client_id CARD8 This "event" notifies the pseudo-server that subsequent X reply, event, and error packets should be delivered to the client associated to CLIENT_ID. ReplyDelta whichmask CARD8 deltas LISTofDELTA where DELTA: [ byte: CARD8, data: CARD8 ] This "event" specifies a given X reply, event, or error in terms of byte differences against a preceding request. The most-significant four bits of WHICHMASK specify the number of bytes that are different; the least-significant four bits specify the reply cache entry against which the DELTAS should be applied. 5. Experiences with XRemote XRemote is used extensively within NCD, primarily within Engineering and the field sales offices, as well as by a number of customers. The delta compression is particularly well suited to reducing the amount of data sent for events such key strokes in which the only changing fields are the timestamp and keycode (typically 2+1 = 3 bytes different). As one might expect, pixmap transfers do take a noticeable amount of time. The LZW compression helps on some images, but future work may wish to investigate whether or not image-specific compression techniques (e.g. G4, run-length encoding, lossless JPEG, etc.) would be more efficient than general compression algorithms like LZW. Font downloading also requires transferring large amounts of data. Similar image-specific compression techniques may be useful here as would the dynamic glyph loading being spurred on by the growing popularity of the font server. The pseudo-server should also be made to cache font metrics so that they do not have to be sent over the wire from the X display. Such caching would also be beneficial to keymap tables, window properties, color allocation and the connection setup information. This would dramatically reduce the startup time for new applications; experience has shown that delays in this area and in window management operations are one of the most common causes of user frustration. This is why having a local window manager running on the X server side of the wire is so important to building a usable system. 6. Where Do We Go From Here Hopefully this document will help everyone understand the concepts of how XRemote works. There are a number of areas that NCD would like to see changed (we will elaborate on the wishlist sent out recently), and we expect that others will to. Ideally, it would be nice to begin debating some of the high-level issues in January.