HP OpenVMS Systems Documentation
VMS DECwindows Transport Manual
2.3 Transporting the Protocol Request
Once the transport layer receives the output request buffer from Xlib, it arranges to have the data transmitted to the server. The transport layer on the server side of the connection receives the data and notifies the server that data is available.
The connection could be across the network to the display, or within a workstation in the case where the client and server have established a local connection. The networking service is assumed to be reliable; Xlib, the transport layer, and the server assume that the data arrives intact and error-free.
The transport layer notifies the scheduler at user-AST level that it
has data available for a connection. The dispatcher calls the transport
layer to get the data.
Input to clients comes in three forms: input events, errors, and replies. An event packet is the X11 protocol message sent from a server to a client that gives information about some event in the server, such as a windowing operation, a keyboard key transition, or a mouse movement. Clients can also use request packets (XSendEvent) to send events to another client by way of the server. An event packet consists of exactly 32 bytes.
An error packet is the X11 protocol message sent from a server to a client that indicates an error state in the server. An error packet consists of exactly 32 bytes.
A reply packet is the X11 protocol message sent from a server to a
client in response to a client protocol request that generates data
(for example, GetImage). A reply can be any length with a maximum size
of some 16 gigabytes.
Most input events are reported to clients relative to windows. Events are usually sent to the smallest enclosing window in which the pointer is located that is interested in the type of event being sent. It is also possible to assign the keyboard input focus to a specific window. When the input focus is attached to a window, keyboard events go to the client that has selected input on that window, rather than to the window in which the pointer is located.
The input component of the server services the XEvent queue and interacts with the window manager to determine which window is associated with the position recorded in the input queue entry. The window ID to which the event is to be delivered is then recorded in the event packet. The input component calls the events component to send the input events to clients that want to know about input in this window ID.
Client programs can use the event_mask argument of the XSelectInput routine to select the events for which they want to receive notification. The server does not send events to a client unless the client has specifically asked to be informed of that type of event. One exception to this rule is that one client can use the XSendEvent routine to force events to be sent to other clients.
An interest list is attached to the window ID data structure. Each entry on the interest list describes filtering parameters defined by the client's event masks. If there are multiple windows interested in the event, the event is sent to multiple windows.
The events component calls the transport layer to transmit the processed input event packets to the Xlib input queue. The transport layer buffers the events packets on a per-connection basis and delivers them to the Xlib input queues. As in the case for output, the transport layer does not interpret the data. Input normally arrives at the client as an I/O completion. Typically, the client processes the input event and generates output requests.
The input event is retained by Xlib until a client requests the next, or the next matching, event. It is the responsibility of the client to request the event; if the client does not request the event, the event remains in the queue.
Xlib provides routines, such as XPeekIfEvent and XCheckIfEvent, that client programs can call to check for particular types of events on their respective input queues. These routines require client programs to supply a procedure that determines if the next event in the queue matches the one that the client wants.
|EventWorkQueue||Queue of XTCBs containing events, errors, and replies to be sent to Xlib|
(large and small)
|Return queue for processed XTCBs from the EventWorkQueue|
|RequestWorkQueue||Queue of XTCBs containing requests to be sent to a server|
(large and small)
|Return queue for processed XTCBs from the RequestWorkQueue|
The transport layer communication queues are shown in Figure 3-1. For the purpose of simplicity, Figure 3-1 combines the free queues; there are actually separate free queues for large and small XTCBs.
Figure 3-1 Transport Layer Communication Queues
You can consider the buffers in the transport layer communication queues to be in an infinite loop similar to a ski lift; once a buffer is received at one end of the connection it is emptied and added to the returning loop.
The transport layer further distinguishes between the queues so that terminology is consistent on both sides of the client/server connection; when the term "input" is used in the context of a client, it means "event." Conversely, "input" in the context of the server means "request." Table 3-2 shows the delineation of the queues.
|General Queue Name||Client View||Server View|
Figure 3-2 Client/Server Communication Queue Views
The transport layer seems to be a single entity that somehow moves data across the wire, but there are actually two transport layers involved: a transport layer on the client side and a transport layer on the server side. Each side of the client/server connection initializes the common transport and attaches one or more specific transports. Each transport layer builds and maintains its own set of connection queues; the queues are private to each side of the wire and are not actually shared across a network connection. The local transport is an exception; the queues are built in shared global sections.
General discussions of the relationship between the transport layer and other DECwindows components commonly treat the transport layer as a single entity that exists on both sides of the client/server connection. However, the transport layer consists of the transport-common and transport-specific components.
The transport-common and transport-specific components pass data to each other by means of a queue implementation that is similar to the queues employed between Xlib and the transport-common code. This intratransport queuing implementation is shown in Figure 3-3.
Figure 3-3 Transport Common/Specific Connection
The server and Xlib call transport-common routines such as DECW$XPORT_READ, DECW$XPORT_FREE_INPUT_BUFFER, GET_OUTPUT_BUFFER, and DECW$XPORT_CHAINED_WRITE to remove or add buffers from the queues, as described in Section 126.96.36.199 and Section 188.8.131.52.
Some of the transport-common routines may call transport-specific routines such as XTFT$A_WRITE to actually get the buffer from the queue. Other transport-common routines, such as DECW$XPORT_READ, operate only in the common layer and communicate with the specific transport only by manipulating data structures.
The following is an example of the transport-common/transport-specific queue process:
Figure 3-4 Transport Common/Specific Queues
On the server side of the connection, the underlying transport notifies the transport-specific layer that data is available. For example, DECnet delivers this notification in the form of a $QIO read completion for the connection; that is, the specific transport receives a read-completion AST in response to a $QIO read for a given connection.
When the specific transport receives a read completion, it calls the transport-common DECW$XPORT_READ_COMPLETE routine to perform the following steps:
The server calls DECW$XPORT_READ to remove (REMQHI) the XTCB from the InputWorkQueue. When the dispatcher is finished with the XTCB, it calls DECW$XPORT_FREE_INPUT_BUFFER to insert the XTCB on the InputFreeQueue, and the queue cycle is complete.
If the InputFreeQueue is empty and input for the connection is enabled
when DECW$XPORT_FREE_INPUT_BUFFER inserts the XTCB,
DECW$XPORT_FREE_INPUT_BUFFER calls XTFT$A_EXECUTE_FREE to remove
(REMQHI) the XTCB it just placed on the InputFreeQueue. In the case of
DECnet or TCP/IP, the XTCB is then used to store the result of the next
QIO read operation for the connection.
3.1.3 Communication Queue Notification Flags
It is possible that at any given time all of a connection's input or output XTCBs will be in use. To provide for this possibility, there is a flag associated with each queue that tracks the state of the queue. When a queue has been exhausted, the component that is removing XTCBs from the queue (the consumer) sets the state flag to indicate that it wants to be notified when an XTCB becomes available.
If the component that is adding XTCBs to the queue (the producer) notices that the queue was empty, it tests the state flag and, if set, notifies the consumer that an XTCB is available.
The notification is context dependent. When the consumer is a transport-specific layer, as described in Section 3.1.1, the notification causes I/O to be initiated using the recently inserted queue element.
When the consumer is the transport-common layer, notification consists of delivering an AST or setting an event flag. For example, the transport-specific code on the server side of the connection sends the transport-common layer an AST to say that input is available for a connection.
The notification flags are shown in Table 3-3.
|EventWorkQueueFlag||Event consumer awaits event XTCBs|
|EventFreeQueueFlag||Event producer awaits returned event XTCBs|
|RequestWorkQueueFlag||Request consumer awaits request XTCBs|
|RequestFreeQueueFlag||Request producer awaits returned request XTCBs|
As in the case of the local communication queues, each interest flag in a local connection has two meanings depending upon whether a server or a client is looking at the queue: the EventWorkQueue is the client's InputWorkQueue and the server's OutputWorkQueue; the RequestFreeQueueInterest bit is the client's OutputFreeQueueInterest bit and the server's InputFreeQueueInterest bit.
A queue element consumer functions as follows:
A queue element producer functions as follows:
The transport layer uses interlocked queues to synchronize access between the queue producer and consumer. Server or Xlib attempts to remove and insert buffers result in the interlocked instructions being used in user mode, possibly at AST level.
The queues are also accessed by inner-mode routines by using the following transport common routines:
Executive-mode code cannot use the REMQxI and INSQxI built-ins to access a relative queue that is modifiable by user-mode code because of the possibility of incorrectly accessing user-write-protected memory.
The REMQxI and INSQxI routines use the VAX PROBEW instruction to probe the memory occupied by a queue entry to determine if the memory has user-mode write access and return an ACCVIO status if it is not accessible.
The REMQxI and INSQxI emulations also perform a spin-and-wait to see if
the queue is locked by another transport user.
184.108.40.206 Special-Case Queue Conditions
There are two special-case queue conditions:
The transport layer data structures maintain the state of the transport and each of the established connections. The transport layer data structures are created in stages as the transport-common code is initialized, a transport-specific mechanism is attached, and connections are established.
The XTPB, IXTCC, and XTDB data structures are allocated from memory pages that have user-mode read access/executive-mode write access (UREW) to prevent modification by less privileged access levels, including the transport-specific code that runs in user mode. The transport-common code depends on the accuracy of the contents of the XTPB, IXTCC, and XTDB data structures.
The transport layer data structures are described in Table 3-4.
|Name||When Created||Write Access Mode||Description|
|exec||Transport parameter block (XTPB) contains default transport parameters. There is a three-level hierarchy of XTPB data structures.|
|IXTCC||Connection open||exec||Internal transport communications context (IXTCC) describes an established connection for executive-mode routines within the transport layer. The IXTCC is used by executive-mode routines to store protected data.|
|Transport communications context (XTCC) describes an established connection. The XTCC is used to pass user-mode data to executive-mode routines. The XTCC may be modified by user-mode code and is visible to either the server or Xlib.|
|XTDB||Transport attach||exec||Transport descriptor block (XTDB) describes each attached transport.|
|Transport communication queue (XTCQ) contains six per-connection communication queues and their states.|
|Transport communication buffers (XTCB) pass data in the transport layer.|
|XTFT||Transport attach||exec||Transport function table (XTFT) contains the addresses of the transport-specific routines. The XTFT is the transport-common code's link to the transport-specific code.|
The transport-common code creates the global XTPB structure at initialization time. The transport-common DECW$XPORT_ATTACH_TRANSPORT routine creates XTDB and XTPB data structures, as shown in Figure 3-5. The XTCC, XTCQ, and XTCB data structures are allocated from memory pages that are user-writable so that routines running in either user or executive mode can modify them.
Figure 3-5 Transport Attach Data Structures
The transport-common open routine creates IXTCC and XTPB data structures. The transport-specific connection open routine creates XTCC, XTCQ, and XTCB data structures, as shown in Figure 3-6.
Figure 3-6 Transport Connection Open Data Structures
The transport-specific connection open routine also creates XTCB data structures, as shown in Figure 3-7.
Figure 3-7 Transport Connection Open XTCB Data Structures
The shaded areas of Figure 3-8 show the transport layer data structures that have user-mode read access/executive-mode write access.
Figure 3-8 Transport Data Structures