Version 1.1 of acs/ac-00059.txt

Unformatted version of acs/ac-00059.txt version 1.1
Other versions for file acs/ac-00059.txt

!standard 13.13.1(08)          03-07-24 AC95-00059/01
!class confirmation 03-06-23
!status received no action 03-06-23
!subject discriminant_association grammar rule found misleading
!summary
!appendix

!topic Streaming over a datagram protocol
!reference RM95-13.13.1(8)
!from Simon Wright 2003-02-09
!discussion

At least one vendor uses streams to support network socket operations
for both streaming (TCP) and datagram (UDP) protocols.

The question is, the standard says "The index of the last stream
element transferred is returned in Last. Last is less than Item'Last
only if the end of the stream is reached.", so what should happen if
the user says

  declare
     Res : Stream_Element_Array (1 .. 1592);
     Last : Stream_Element_Offset;
  begin
     Read (UDP_Stream, Res, Last);

and the next datagram is of size 42 bytes?

Clearly (a) users would choose UDP because datagrams are important to
them, and (b) UDP doesn't guarantee order of arrival or even arrival
at all. So it is not sensible to just read more packets until the 1592
bytes are read.

(The intended use is less than clear, I suppose: it was
   read the next packet into a Stream_Element_Array inside an in-memory stream
   use 'Class'Input to handle the data from the in-memory stream )

At first sight there are two possibilities: first, don't implement
streams over media that don't guarantee reliable delivery, or second,
reword the standard to allow vendors to implement streams in a
sensible way over unreliable media.

The extension of "implement streams in a sensible way over unreliable
media" might be "implement streams in a way appropriate to the
underlying medium".

So, what about

For standard streams (including those specified in
Ada.Streams.Stream_IO), Last is less than Item'Last only if the end of
the stream is reached. Different behaviour may be appropriate for
particular types of stream.

****************************************************************

From: Nick Roberts
Sent: Tuesday, March 4, 2003  4:21 PM

...
> and the next datagram is of size 42 bytes?

The most sensible behaviour, to my mind, would be to treat each datagram as
a mini stream in its own right. This way, the end of the stream is indeed
the end of the datagram, and in this example Last would contain 42 (and
Res(1..42) would contain the datagram), assuming Stream_Element'Size=8.

> Clearly (a) users would choose UDP because datagrams are important to
> them, and (b) UDP doesn't guarantee order of arrival or even arrival
> at all. So it is not sensible to just read more packets until the 1592
> bytes are read.

I agree. In the above example, the datagram read into Res would be sure to
contain a 'header' which would contain serialisation and validation
information. This would have to be checked, and the appropriate action
taken.

> (The intended use is less than clear, I suppose: it was
>   read the next packet into a Stream_Element_Array inside an in-memory stream
>   use 'Class'Input to handle the data from the in-memory stream )

A typical action would presumably be to use T'Read (or T'Class'Input) on
some part of the 'payload' part of Res, to extract a value for a variable of
type T (or to get a value in T'Class).

> At first sight there are two possibilities: first, don't implement
> streams over media that don't guarantee reliable delivery, or second,
> reword the standard to allow vendors to implement streams in a
> sensible way over unreliable media.

I'm not sure the standard needs rewording. Possibly some implementation
advice regarding datagram-oriented I/O might be worthwhile.

> The extension of "implement streams in a sensible way over unreliable
> media" might be "implement streams in a way appropriate to the
> underlying medium".

But I fancy this would be appropriate as implementation advice.

> So, what about
>
> For standard streams (including those specified in
> Ada.Streams.Stream_IO), Last is less than Item'Last only if the end of
> the stream is reached. Different behaviour may be appropriate for
> particular types of stream.

Ditto.

I must say, I'd be inclined to implement datagram I/O at the lowest level
not as a stream, but simply as a type (derived from a type) named
Datagram_Transceiver.

Datagram_Transceiver would provide a pair of procedures, Read and Write,
which would both take an access to a Stream_Element_Array parameter (and
possibly others, such as node addresses). The likelihood is that these
procedures would program a DMA to perform the actual data transfer into or
out of memory (so needing the address of the array). Datagram_Transceiver
would also provide such operations as obtaining (or setting) the maximum
datagram length, setting various timeout values, and so on.

I might build a stream type on top of Datagram_Transceiver, but then I would
hide away the datagram details from this type (rather like TCP does).

****************************************************************

Questions? Ask the ACAA Technical Agent