Stream States Part 1
Streams can be modelled as an FSM by determining the different states a stream can be in and all valid state transistions. Initially, a stream is in the created
state.
This state signifies that the stream has been created. This is possible in two different ways: a) The stream was created by the session, added to the stream map, and a SYN
packet with the stream’s ID was sent to the remote session, or b) A SYN packet was received from the remote session and a new stream was created and added to the stream map.
In case of (a) the stream waits for an ACK packet from the remote session and as soon as the ACK packet arrives, it transistions to the accepted
state. In case of (b) the
session sends an ACK packet, and the the stream transitions to the accepted
state.
Once in the accepted
state the stream can read and write from the stream. When a DAT packet arrives, the data is push to the stream’s buffer. When data is read out of the
buffer using a Read()
call, an ACK packet is sent to the remote stream with the number of bytes read. When an ACK packet is received in the accepted state, the number of
bytes unblocked (the number of bytes the remote session is willing to accept), is updated. If the stream is closed by a call to Close()
, then the stream transitions to the
closed
state and sends a FIN packet to the remote stream. When a FIN packet is received, the stream transitions to the remoteClosed
state.
In the closed
state, the stream can not write any data to the remote connection. All Write()
calls return an ErrBrokenPipe error. The stream can still receive data, and canread data from the buffer.
The remoteClosed
state signifies that the remote stream will not send any more data to the stream. Read()
calls can still read data from the buffer. If the buffer is empty
then the Read()
calls return EOF. The stream can write data to the remote session.
If a FIN packet is received when in the closed
state, or Close()
is called in the remoteClosed
state, the stream transitions to the dead
state. All Write()
calls fail
in the dead
state, but Read()
can retreive data from the buffer. If the stream is in the dead
state, and the buffer is empty, then the stream is removed by its Session.
The state transitions can be summed up in the following diagram: