        @(#) $Id: thrulay-protocol.txt,v 1.2 2005/10/02 17:01:16 shalunov Exp $

			   THRULAY PROTOCOL

The purpose of thrulay is to inject test streams into the network.  To
accomplish this, a simple protocol is used.  The protocol consists of
an interaction between a client and a server.  The bulk of the data is
always sent by the client; the server merely sends back control
messages and small records that help the client measure the round-trip
time.

The server typically listens on TCP port number 5003.  The simple
protocol is binary (most characters are actually printable, but
newlines are not used as record separators).  Literals in double
quotes are represented in ASCII (which coincides with their UTF-8
representations).  Once a connection is established, the server MUST
send the greeting: "thrulay/2" (no quotes are actually sent; the
character after the slash designates version number; the only version
number currently defined is 2, with 1 being an old deprecated
version).  Then, the server MUST send a single character, either "+"
or "-".  If the "-" character is sent, it MUST be followed by a
(possibly empty) string of UTF-8 characters that give the reason for
rejecting the connection; the connection MUST be closed by the server
once the string is sent.  If the "+" character is sent, the server
then expects to read a response from the client.  The response will
tell the server the parameters of the session.

If the first 10 characters sent by the server are not "thrulay/2+", then
the client MUST close the connection.  (All matches in thrulay protocol
are case-sensitive.)  If the first 10 characters sent by the server are
"thrulay/2-", then the client MAY display subsequent characters
(possibly processed in some way) to the user if there is one or record
them somewhere as a reason for session failure.

If the first 10 characters sent by the server are "thrulay/2+", then the
client MUST send a session proposal.  A session proposal is described
as follows: 

  <digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
  <number> ::= <digit> | <number> <digit>
  <indicator> ::= "thrulay"
  <version> ::= "2"
  <start> ::= <indicator> "/" <version>
  <requested TCP window> ::= <number>
  <requested TCP block size> ::= <number>
  <TCP proposal> ::= "t:" <requested TCP window> ":" <requested TCP block size>
  <client port> ::= <number>
  <packet size> ::= <number>
  <rate> ::= <number>
  <packets> ::= <number>
  <UDP proposal> ::= "u:" <client port> ":" <packet size> ":" <rate>
                     ":" <packets>
  <protocol proposal> ::= <TCP proposal> | <UDP proposal>
  <session proposal> ::= <start> ":" <protocol proposal> "+"

In a TCP proposal, the server is asked to use the requested TCP window
size.  Requested TCP block size is the requested size of the read
blocks; it MUST be at least 16.

In a UDP proposal, the client port (an unsigned integer less than
65536) is the port that the client intends to use to send the data
from.  The packet size is the length, in octets, of UDP test packets;
the complete IP packet is accounted for, but link-layer headers and
trailers are not included within the packet size.  The rate is the
average rate, in packets per 1000 seconds, that the client wants to
use in the test.  Finally, the number of packets to be sent is
specified.

The server reads the session proposal, always terminated by the "+"
character.

			     TCP proposal

The server MUST respond to a session proposal that contains a TCP
proposal with a TCP session response:

  <window> ::= <number>
  <block size> ::= <number>
  <TCP session response> ::= <window> ":" <block size> "+"

Here, window is the actual window size that the server will use.  If
resources and policies allow, window SHOULD be equal to the requested
window.  Block size is similar; it MUST be at least 16.

Once this exchange is over, the client MUST send zero or more blocks
of test data.

Upon receipt of each block, server MUST send back the first 16 bytes
of the block.  The client MAY use the 16-byte `block headers'
arbitrarily; one possibility is to measure the round-trip time by
embedding timestamps in them.

Once the client is finished testing, it MUST close the connection.
The server MUST then close the connection as well.

			     UDP proposal

In the case when a session proposal that contains a UDP proposal is
sent by the client, the server MUST respond with a UDP session
response:

  <server port> ::= <number>
  <nonce> ::= <octet> <octet> <octet> <octet> <octet> <octet> <octet> <octet>
  <positive UDP session response> ::= <server port> ":"
				      <packet size> ":" <rate> ":"
				      <packets> ":" <nonce> "+"
  <negative UDP session response> ::= "u:-"
  <UDP session response> ::= <positive UDP session response> |
			     <negative UDP session response>

An octet above is defined as an arbitrary octet, with values from 0 to
255.

If a negative UDP session response is received by the client, the test
fails and the client MUST close the connection.  The server MUST also
close the connection after sending a negative UDP session response.

If a positive UDP session response is used, the server port is the UDP
port number that the server will use to receive the test packets from
the client; it has no relationship to the client port.  The server
port SHOULD be 5003, if that port is unused; if that port is used, it
SHOULD be 5004, and so forth.  The packet size and the rate specified
by the server SHOULD be the same as those specified by the client, if
policy considerations and network configuration allow that.
Regardless of whether they are the same as those specified by the
client, the client MUST use the server-specified values.  The nonce is
a pseudo-random eight-octet quantity used for security purposes.

The UDP test consists of a stream of UDP packets sent from the client
(using the client port as the source) to the server (with the server
port as the destination port).  Each packet has the length specified
in UDP session response.  The negotiated average rate needs to be
approached with the best practical approximation of a Poisson stream;
whatever are the deviations from a true Poisson stream, there MUST be
no long-term bias.

The TCP connection is not closed while the UDP test is going.  Both
the client and the server MUST refrain from sending any data over the
TCP connection (and SHOULD refrain from sending TCP keep-alive probes)
while the UDP test is active.  When the client is done with the test,
it sends a single character over the TCP connection; this character
can be "+" to indicate successful end of session and "-" to indicate
that the session is aborted (no other values are legal).  In the case
the "+" character is used, it is followed by a number (decimal) that
represents that total number of packets sent, followed by a colon
(":").  In both cases ("+" or "-"), the server stops listening to
further UDP traffic; in the case when a "+" was sent, the server
transmits arbitrary UTF-8 characters that constitute the results of
the session.  Then, the server closes the TCP connection.

The format of test packet payload (the normal IP and UDP headers are,
of course, also present) is as follows: 8 octets of nonce are followed
by 8 octets of sequence number are followed by 8 octets of timestamp
are followed by zero or more octets of padding to bring the packet
size to the negotiated value.  The value of nonce is the value
specified by the server in UDP session response.  Sequence number is
an unsigned binary integer in network byte order; it starts at 0 and
is incremented by 1 with each packet.  The timestamp has the same
format as the NTP timestamp in RFC 1305.  Padding contains arbitrary
data.
