Transport Interfaces Programming Guide

Out-of-Band Data

The stream socket abstraction includes out-of-band data. Out-of-band data is a logically independent transmission channel between a pair of connected stream sockets. Out-of-band data is delivered independent of normal data. The out-of-band data facilities must support the reliable delivery of at least one out-of-band message at a time. This message can contain at least one byte of data, and at least one message can be pending delivery at any time.

For communications protocols that support only in-band signaling (that is, urgent data is delivered in sequence with normal data), the message is extracted from the normal data stream and stored separately. This lets users choose between receiving the urgent data in order and receiving it out of sequence, without having to buffer the intervening data.

You can peek (with 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 SIGURG with the appropriate fcntl() call, as described in "Interrupt-Driven Socket I/O" for SIGIO. If multiple sockets have out-of-band data waiting delivery, a select() call for exceptional conditions can be used to determine the sockets with such data pending.

A logical mark is placed in the data stream at 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 is received, all data up to the mark in the data stream is discarded.

To send an out-of-band message, the MSG_OOB flag is applied to send() or sendto(). To receive out-of-band data, specify MSG_OOB to recvfrom() or recv() (unless out-of-band data is taken in line, in which case the MSG_OOB flag is not needed). The SIOCATMARK ioctl tells whether the read pointer currently points at the mark in the data stream:


int yes;
ioctl(s, SIOCATMARK, &yes);

If yes is 1 on return, the next read returns data after the mark. Otherwise, assuming out-of-band data has arrived, the next read provides data sent by the client before sending the out-of-band signal. The routine in the remote login process that flushes output on receipt of an interrupt or quit signal is shown in Example 2-13. This code reads the normal data up to the mark (to discard it), then reads the out-of-band byte.

A process can 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, TCP, the protocol used to provide socket streams in the Internet domain). With such protocols, the out-of-band byte might not yet have arrived when a recv() is done with the MSG_OOB flag. In that case, the call returns the error of EWOULDBLOCK. Also, there might 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 can be delivered.


Example 2-13 Flushing Terminal I/O on Receipt of Out-of-Band Data


#include <sys/ioctl.h>
#include <sys/file.h>
...
oob()
{
		int out = FWRITE;
		char waste[BUFSIZ];
		int mark = 0;
 
		/* flush local terminal output */
		ioctl(1, TIOCFLUSH, (char *) &out);
		while(1) {
			if (ioctl(rem, SIOCATMARK, &mark) == -1) {
				perror("ioctl");
				break;
			}
			if (mark)
				break;
			(void) read(rem, waste, sizeof waste);
		}
		if (recv(rem, &mark, 1, MSG_OOB) == -1) {
			perror("recv");
			...
		}
		...
}

There is also a facility to retain the position of urgent in-line data in the socket stream. This is available as a socket-level option, SO_OOBINLINE. See the getsockopt(3N) manpage for usage. With this option, the position of urgent data (the mark) is retained, but the urgent data immediately follows the mark in 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 are lost.