[comp.unix.programmer] Out of band data

A.J.Rasiah@massey.ac.nz (Ajit Rasiah ) (01/31/91)

Hello!

I am trying to use the out-of-band (OOB) facility of UNIX sockets. I tried a


	send(s, "out of band data", 16, MSG_OOB);       /* 1 */
	write(s, "string 2", 8);         		/* 2 */

When I perform a read() I get the string "out of band dat".

It appears that the string "out of band dat" (note the missing last character)
is considered low-priority, and the logical mark identifying the start of the
urgent data is in fact the missing last character (the 'a'). This implies
that the string "string 2" is actually the urgent data!

Why is this? What I want, is to be able to read the urgent data separately
from the low-priority without mixing them up. What is the best approach I
should use?

Please reply to A.J.Rasiah@massey.ac.nz

Thanks in advance.

sean@ms.uky.edu (Sean Casey) (02/01/91)

To receive out-of-band data, don't do a read(). Do a recv() with the
OOB flag set. Things will work properly then.

Sean

-- 
** Sean Casey  <sean@s.ms.uky.edu>

enag@ifi.uio.no (Erik Naggum) (02/01/91)

In article <483sis-d@massey.ac.nz>, Ajit Rasiah  writes:

   I am trying to use the out-of-band (OOB) facility of UNIX sockets.
   I tried a

	   send(s, "out of band data", 16, MSG_OOB);			[1]
	   write(s, "string 2", 8);					[2]

   When I perform a read() I get the string "out of band dat".

   It appears that the string "out of band dat" (note the missing last
   character) is considered low-priority, and the logical mark
   identifying the start of the urgent data is in fact the missing
   last character (the 'a'). This implies that the string "string 2"
   is actually the urgent data!

   Why is this? What I want, is to be able to read the urgent data
   separately from the low-priority without mixing them up. What is
   the best approach I should use?

I'm posting this to the group to air a suggestion.

The out of band facility was not intended to be used as a separate
data channel.  If you wish to multiplex two channels on one
connection, I suggest that you do something like this:

	#include <sys/types.h>
	#include <netinet/in.h>

	struct mux {
		u_short channel;
		u_short datalen;
	};								[1]

	int muxwrite (int fd, u_short channel, void *data, u_short count)
	{
		struct mux xmit;
		xmit.channel = htons (channel);
		xmit.datalen = htons (count);
		write (fd, &xmit, sizeof xmit);				[2]
		return write (fd, data, count);				[3]
	}

	int muxread (int fd, u_short *channel, void *data, u_short *count, u_short max_count)
	{
		struct mux recv;
		read (fd, &recv, sizeof recv);				[4]
		*channel = ntohs (recv.channel);
		*count = ntohs (recv.datalen);
		if (*count > maxcount)	{ }				[5]
		return read (fd, data, *count);				[6]
	}

NOTE: This is not anywhere near finished, polished code.  You need to
figure out how to deal with a failure of the write in [3] when the
write in [2] succeeded, because the read in [4] will expect a block of
data following the "protocol portion".  You would definitely do some
sanity checking on the received channel and datalen elements, etc.
There are problems to be solved in what you want to do when the test
in [5] succeeds.  There are also a few problems to be solved in what
to do if the return value of the read in [6] is less than what is
reported by *count.  It should probably loop, slurping up bytes until
the prescribed number of bytes are received.  A checksum could be
provided with [1].

You should probably devise a scheme by which these protocol portions
are introduced so that you can detect when or if screw-ups occur in
the protocol, e.g. by using a special magic value in [1] which is
allowed only at the head of the protocol data unit ("packet"), and
escaped when found in the data, much like SLIP does.

I think I have made an excellent argument against using only one
stream, and thus an equally excellent argument for two or more
streams, which you alternate between via the select(2) system call.
In fact, I suggest you do just that, instead of relying on long
strings of out of band data.

--
[Erik Naggum]	Snail: Naggum Software / BOX 1570 VIKA / 0118 OSLO / NORWAY
		Mail: <erik@naggum.uu.no>, <enag@ifi.uio.no>
My opinions.	Wail: +47-2-836-863	Another int'l standards dude.

mouse@thunder.mcrcim.mcgill.edu (der Mouse) (03/01/91)

In article <483sis-d@massey.ac.nz>, ...!cc-server4.massey.ac.nz!A.J.Rasiah writes:

> I am trying to use the out-of-band (OOB) facility of UNIX sockets.  I
> tried a

> 	send(s, "out of band data", 16, MSG_OOB);       /* 1 */
> 	write(s, "string 2", 8);         		/* 2 */

You don't say what flavor of UNIX, though with sockets and MSG_OOB it
clearly has Berkeley blood in its veins.

You also don't say what sort of socket.  It's clearly a stream socket,
but is it AF_UNIX or AF_INET?

I don't know what AF_UNIX does with MSG_OOB.  I've neither tried it nor
looked at the code.

But AF_INET, now, that's a different story.

You see, TCP doesn't have out-of-band data.  It has an urgent pointer,
which marks a point in the data stream, *not* a subsequence of the data
stream.  Berkeley took this notion and managed to turn it into a
sort-of OOB mechanism.  But the underlying mechanism is really not
suited to sending OOB data, so it's hardly surprising that it breaks.
And then various vendors ship code that isn't quite the Berkeley code
any longer, so it's broken in subtle ways....

If the sender and receiver use different implementations of TCP, this
is even less surprising.  The Berkeley code contains a comment that
seems to indicate that they violate the TCP spec slightly, in a way
that seems to me likely to cause interoperability problems with this
pseudo-OOB mechanism, and in fact I've observed problems that I can
pretty much justify as being caused by this.

If you really want a second data channel, I would recommend creating a
second connection.  If you want something else, it depends on just what
it is you want.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu