|
|
The stream socket abstraction includes the notion of out-of-band data. Out-of-band data is a logically independent transmission channel associated with each pair of connected stream sockets. Out-of-band data is delivered to the user independently of normal data. The abstraction defines that the out-of-band data facilities must support the reliable delivery of at least one out-of-band message at a time. This message may contain at least one byte of data, and at least one message may be pending delivery to the user at any one time. For communications protocols (such as TCP) that support only in-band signaling (that is, the urgent data is delivered in sequence with the normal data), the system normally extracts the data from the normal data stream and stores it separately. This allows users to choose between receiving the urgent data in order and receiving it out of sequence without having to buffer all the intervening data. It is possible to ``peek'' (via MSG_PEEK) at out-of-band data. If the socket has a process group, a SIGURG signal is generated when the protocol is notified of its existence. A process can set the process group or process id to be informed by the SIGURG signal via the appropriate fcntl(S) call, as described below for SIGIO. If multiple sockets may have out-of-band data awaiting delivery, a select call for exceptional conditions may be used to determine those sockets with such data pending. Neither the signal nor the select show the arrival of the out-of-band data, but only notification that it is pending.
In addition to the information passed, a logical mark is placed in the data stream to specify the point at which the out-of-band data was sent. The remote login and remote shell applications use this facility to propagate signals between client and server processes. When a signal flushes any pending output from the remote process(es), all data up to the mark in the data stream is discarded.
To send an out-of-band message the MSG_OOB flag is supplied to a send or sendto calls, while to receive out-of-band data MSG_OOB should be specified when doing a recvfrom or recv call (unless out-of-band data is taken in line, in which case the MSG_OOB flag is not needed).
To find out if the read pointer is currently pointing at the mark in the data stream, the SIOCATMARK ioctl is provided:
ioctl(s, SIOCATMARK, &yes);If yes is 1 on return, the next read will return data after the mark. Otherwise (assuming out-of-band data has arrived), the next read will provide data sent by the client before transmission of the out-of-band signal. The routine used in the remote login process to flush output on receipt of an interrupt or quit signal is shown in the following example. This code reads the normal data up to the mark (to discard it), then reads the out-of-band byte.
#include <sys/ioctl.h> #include <sys/file.h> ... oob() { int out = FWRITE; char waste[BUFSIZ]; int mark;A process may also read or peek at the out-of-band data without first reading up to the mark. This is more difficult when the underlying protocol delivers the urgent data in-band with the normal data, and only sends notification of its presence ahead of time (for example, the TCP protocol used to provide socket streams in the Internet domain). With such protocols, the out-of-band byte may not yet have arrived when a recv is done with the MSG_OOB flag. In that case, the call will return an error of EWOULDBLOCK. Worse, there may be enough in-band data in the input buffer that normal flow control prevents the peer from sending the urgent data until the buffer is cleared. The process must then read enough of the queued data before the urgent data may be delivered./* flush local terminal output */ ioctl(1, TIOCFLUSH, (char *)&out); for (;;) { if (ioctl(rem, SIOCATMARK, &mark) < 0) { perror("ioctl"); break; } if (mark) break; (void) read(rem, waste, sizeof(waste)); } if (recv(rem, &mark, 1, MSG_OOB) < 0) { perror("recv"); ... } ... }
Certain programs that use multiple bytes of urgent data and must handle multiple urgent signals (for example, telnet(C)) need to retain the position of urgent data within the socket stream. This treatment is available as a socket-level option, SO_OOBINLINE; see setsockopt(S). With this option, the position of urgent data (the ``mark'') is retained, but the urgent data immediately follows the mark within the normal data stream returned without the MSG_OOB flag. Reception of multiple urgent indications causes the mark to move, but no out-of-band data is lost.