Class StreamsState
The application side (open(io.github.mahmoudimus.quic.connection.Dir), accept(io.github.mahmoudimus.quic.connection.Dir), write(io.github.mahmoudimus.quic.connection.StreamId, java.nio.ByteBuffer, io.github.mahmoudimus.quic.connection.Retransmits), finish(io.github.mahmoudimus.quic.connection.StreamId), reset(io.github.mahmoudimus.quic.connection.StreamId, long, io.github.mahmoudimus.quic.connection.Retransmits), read(io.github.mahmoudimus.quic.connection.StreamId, boolean, io.github.mahmoudimus.quic.connection.Retransmits), stop(io.github.mahmoudimus.quic.connection.StreamId, long, io.github.mahmoudimus.quic.connection.Retransmits)) never blocks: it reports StreamException.Kind.BLOCKED
and later a StreamEvent from poll() says when to retry. That is what a blocking
stream layer waits on.
Frames the operations need go into a Retransmits the caller passes, normally the
application data space's pending frames; writeControlFrames(java.nio.ByteBuffer, io.github.mahmoudimus.quic.connection.Retransmits, io.github.mahmoudimus.quic.connection.Retransmits, int) and writeStreamFrames(java.nio.ByteBuffer, int, boolean) put them into packets.
Flow control. Credit is issued as quinn does: a stream's MAX_STREAM_DATA moves with
what the application reads, to bytes read + stream receive window, and is sent once it
has moved by an eighth of the window; MAX_DATA likewise with the connection receive window;
MAX_STREAMS keeps the configured number of remote streams open and is sent once an eighth of
them have closed. The windows can be changed at run time; quinn does not auto-tune them, and
neither does this port. Writes are limited by the peer's credit and by a local send window of
buffered, unacknowledged data.
Threads. Not thread-safe and takes no locks: one connection owns it and serializes every call, including the blocking stream layer's.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final record -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final longThe largest stream count MAX_STREAMS may carry, 260. -
Constructor Summary
ConstructorsConstructorDescriptionStreamsState(Side side, long maxRemoteUni, long maxRemoteBi, long sendWindow, long receiveWindow, long streamReceiveWindow) The stream state of a new connection. -
Method Summary
Modifier and TypeMethodDescriptionAccepts a stream the peer opened.booleanWhether a queued DATA_BLOCKED is still accurate.booleanWhether a MAX_STREAM_DATA for a stream would still be useful.booleanWhether any stream has data to send, ignoring control frames.voidFinishes a stream: no more data will be written, and a FIN is queued.booleanWhether a local stream has never been opened.longmaxConcurrent(Dir dir) How many remote streams of a directionality are allowed and not fully closed.voidMarks the connection closed: writes are refused from now on.Opens a local stream.poll()The next stream event.intA stream's priority.booleanqueueMaxStreamId(Retransmits retransmits) Queues MAX_STREAMS if enough remote streams closed: more than an eighth of the concurrency limit.read(StreamId id, boolean ordered, Retransmits retransmits) Starts reading a stream.booleanreceived(Frame.Stream frame, int payloadLength) Processes a STREAM frame.voidreceivedAckOf(StreamMeta frame) Records that a STREAM frame was acknowledged; may release the stream and reportStreamEvent.Finished.voidreceivedMaxData(long n) Processes a MAX_DATA frame; smaller limits than the current one are ignored.voidreceivedMaxStreamData(StreamId id, long offset) Processes a MAX_STREAM_DATA frame.voidreceivedMaxStreams(Dir dir, long count) Processes a MAX_STREAMS frame.booleanreceivedReset(Frame.ResetStream frame) Processes a RESET_STREAM frame.voidProcesses a STOP_SENDING frame.voidProcesses a STREAM_DATA_BLOCKED frame, which needs no response.voidProcesses a STREAMS_BLOCKED frame, which needs no response.The state of a stream's receiving part.longremoteOpenStreams(Dir dir) The number of open remote streams, accepted or not, which count against the concurrency limit.voidreset(StreamId id, long errorCode, Retransmits retransmits) Abandons sending on a stream (RESET_STREAM).voidresetAcked(StreamId id) Releases a stream whose RESET_STREAM was acknowledged.voidretransmit(StreamMeta frame) Queues a lost STREAM frame's data to be sent again.booleanAfter the server rejected 0-RTT: if what the local streams used fits the server's actual limits, takes those limits and queues everything written to be sent again in 1-RTT packets, so the streams carry on as if the early data had been lost; otherwise forgets the local streams, as quinn does (zeroRttRejected()).voidQueues everything written on local streams to be sent again after 0-RTT was rejected.The state of a stream's sending part.intThe number of streams that may have unacknowledged outgoing data.voidsetMaxConcurrent(Dir dir, long count) Changes how many remote streams of a directionality may be open at once.voidsetParams(TransportParameters params) Applies the peer's transport parameters: initial stream and connection limits.voidsetPriority(StreamId id, int priority) Sets a stream's priority; streams with a higher priority send first.booleansetReceiveWindow(long receiveWindow) Changes the connection receive window.voidsetSendWindow(long sendWindow) Changes the send window, the most outgoing data to buffer.voidstop(StreamId id, long errorCode, Retransmits retransmits) Stops receiving a stream (STOP_SENDING).longWhether the peer stopped a stream.longThe limit to put in a STREAM_DATA_BLOCKED for a stream.longtakeReset(StreamId id, Retransmits retransmits) Whether the peer reset a stream.intwrite(StreamId id, ByteBuffer data, Retransmits pending) Writes data, copying as much as flow control and the send window accept.writeChunks(StreamId id, ByteBuffer[] chunks, Retransmits pending) Writes buffers without copying them: the stream keeps views until the data is acknowledged, so their contents must not change.voidwriteControlFrames(ByteBuffer buf, Retransmits retransmits, Retransmits sent, int maxSize) Writes pending stream control frames: RESET_STREAM, STOP_SENDING, MAX_DATA, MAX_STREAM_DATA, MAX_STREAMS, STREAMS_BLOCKED, DATA_BLOCKED and STREAM_DATA_BLOCKED, as many as fit.longHow much the application may write now: the peer's remaining connection credit, limited by the send window.writeStreamFrames(ByteBuffer buf, int maxBufSize, boolean fair) Writes STREAM frames from the pending streams, highest priority first, as many as fit.voidForgets every local stream after the server rejected 0-RTT.
-
Field Details
-
MAX_STREAM_COUNT
public static final long MAX_STREAM_COUNTThe largest stream count MAX_STREAMS may carry, 260.- See Also:
-
-
Constructor Details
-
StreamsState
public StreamsState(Side side, long maxRemoteUni, long maxRemoteBi, long sendWindow, long receiveWindow, long streamReceiveWindow) The stream state of a new connection.- Parameters:
side- this endpoint's rolemaxRemoteUni- how many unidirectional streams the peer may have openmaxRemoteBi- how many bidirectional streams the peer may have opensendWindow- the most outgoing data to buffer, in bytesreceiveWindow- the connection receive window, in bytesstreamReceiveWindow- the per-stream receive window, in bytes
-
-
Method Details
-
setParams
Applies the peer's transport parameters: initial stream and connection limits.- Parameters:
params- the peer's parameters
-
onConnectionClosed
public void onConnectionClosed()Marks the connection closed: writes are refused from now on. -
zeroRttRejected
public void zeroRttRejected()Forgets every local stream after the server rejected 0-RTT. -
setMaxConcurrent
Changes how many remote streams of a directionality may be open at once.- Parameters:
dir- the directionalitycount- the number of concurrent streams
-
maxConcurrent
How many remote streams of a directionality are allowed and not fully closed.- Parameters:
dir- the directionality- Returns:
- the count
-
setSendWindow
public void setSendWindow(long sendWindow) Changes the send window, the most outgoing data to buffer.- Parameters:
sendWindow- bytes; may be below what is already buffered
-
setReceiveWindow
public boolean setReceiveWindow(long receiveWindow) Changes the connection receive window. A larger window raises the limit at once; a smaller one is absorbed from credit as data is read.- Parameters:
receiveWindow- bytes- Returns:
- true if the window grew, so a MAX_DATA is worth sending
-
open
Opens a local stream.- Parameters:
dir- the directionality- Returns:
- the new stream, or null if the peer's limit is reached (a STREAMS_BLOCKED is then queued) or the connection is closed
-
accept
Accepts a stream the peer opened. Does not change flow control or stream limits.- Parameters:
dir- the directionality- Returns:
- the next stream not yet accepted, or null if there is none
-
sendStreams
public int sendStreams()The number of streams that may have unacknowledged outgoing data.- Returns:
- the count
-
remoteOpenStreams
The number of open remote streams, accepted or not, which count against the concurrency limit.- Parameters:
dir- the directionality- Returns:
- the count
-
write
Writes data, copying as much as flow control and the send window accept.- Parameters:
id- the streamdata- the bytes between the position and limit; the position advances past the bytes takenpending- where to queue DATA_BLOCKED and STREAM_DATA_BLOCKED- Returns:
- the number of bytes taken, at least 1 unless
datais empty - Throws:
StreamException-BLOCKEDif no byte could be taken,STOPPEDafter STOP_SENDING,CLOSED_STREAMif the stream is not writable
-
writeChunks
public StreamsState.Written writeChunks(StreamId id, ByteBuffer[] chunks, Retransmits pending) throws StreamException Writes buffers without copying them: the stream keeps views until the data is acknowledged, so their contents must not change. A buffer only partly taken has its position advanced.- Parameters:
id- the streamchunks- the datapending- where to queue DATA_BLOCKED and STREAM_DATA_BLOCKED- Returns:
- the bytes and whole chunks taken
- Throws:
StreamException- as forwrite(io.github.mahmoudimus.quic.connection.StreamId, java.nio.ByteBuffer, io.github.mahmoudimus.quic.connection.Retransmits)
-
stopped
Whether the peer stopped a stream.- Parameters:
id- the stream- Returns:
- the STOP_SENDING error code, or -1 if not stopped
- Throws:
StreamException-CLOSED_STREAMif the stream's send side is gone
-
finish
Finishes a stream: no more data will be written, and a FIN is queued.StreamEvent.Finishedfollows once everything is acknowledged.- Parameters:
id- the stream- Throws:
StreamException-STOPPEDafter STOP_SENDING,CLOSED_STREAMif already finished or reset
-
reset
Abandons sending on a stream (RESET_STREAM). Unsent and unacknowledged data is discarded.- Parameters:
id- the streamerrorCode- the application error coderetransmits- where to queue the RESET_STREAM- Throws:
StreamException-CLOSED_STREAMif the stream was already reset or is gone
-
setPriority
Sets a stream's priority; streams with a higher priority send first.- Parameters:
id- the streampriority- the priority, 0 by default- Throws:
StreamException-CLOSED_STREAMif the stream's send side is gone
-
priority
A stream's priority.- Parameters:
id- the stream- Returns:
- the priority
- Throws:
StreamException-CLOSED_STREAMif the stream's send side is gone
-
sendState
The state of a stream's sending part.- Parameters:
id- the stream- Returns:
- the state, or null if the stream has no sending part or it was released
-
read
Starts reading a stream. CallChunks.next(int)for data, thenChunks.close()(or use try-with-resources) to issue the flow control credit for what was read.- Parameters:
id- the streamordered- true to read bytes in order; false for chunks in any order, after which ordered reads are refusedretransmits- where to queue MAX_DATA, MAX_STREAM_DATA and MAX_STREAMS- Returns:
- the reader
- Throws:
StreamException-CLOSED_STREAMif the stream is gone or stopped,ILLEGAL_ORDERED_READfor an ordered read after an unordered one
-
stop
Stops receiving a stream (STOP_SENDING). Unread data is discarded and its connection credit returned.- Parameters:
id- the streamerrorCode- the application error coderetransmits- where to queue STOP_SENDING and MAX_DATA- Throws:
StreamException-CLOSED_STREAMif the stream is gone or already stopped
-
takeReset
Whether the peer reset a stream. Once a reset is returned the stream is released, and later calls fail withCLOSED_STREAM.- Parameters:
id- the streamretransmits- where to queue MAX_STREAMS- Returns:
- the RESET_STREAM error code, or -1 if the stream was not reset
- Throws:
StreamException-CLOSED_STREAMif the stream is gone or stopped
-
recvState
The state of a stream's receiving part.- Parameters:
id- the stream- Returns:
- the state, or null if the stream has no receiving part or it was released
-
received
Processes a STREAM frame. The stream keeps a view of the frame's data until it is read, so copy the data out of a reusable packet buffer first.- Parameters:
frame- the framepayloadLength- the size of the buffer behind the frame's data, for memory accounting- Returns:
- true if a MAX_DATA should be queued
- Throws:
QuicException-STREAM_STATE_ERRORfor a send-only or unopened stream,STREAM_LIMIT_ERRORbeyond the stream limit,FLOW_CONTROL_ERRORbeyond a credit limit,FINAL_SIZE_ERRORfor a changed or exceeded final size
-
receivedReset
Processes a RESET_STREAM frame.- Parameters:
frame- the frame- Returns:
- true if a MAX_DATA should be queued
- Throws:
QuicException- as forreceived(io.github.mahmoudimus.quic.frame.Frame.Stream, int)
-
receivedStopSending
Processes a STOP_SENDING frame.- Parameters:
frame- the frame- Throws:
QuicException-STREAM_STATE_ERRORfor a receive-only or unopened stream,STREAM_LIMIT_ERRORbeyond the stream limit
-
receivedStreamDataBlocked
Processes a STREAM_DATA_BLOCKED frame, which needs no response.- Parameters:
frame- the frame- Throws:
QuicException-STREAM_STATE_ERRORfor a stream this endpoint only sends on
-
receivedStreamsBlocked
Processes a STREAMS_BLOCKED frame, which needs no response.- Parameters:
frame- the frame- Throws:
QuicException-FRAME_ENCODING_ERRORfor a limit above 260
-
receivedMaxStreams
Processes a MAX_STREAMS frame.- Parameters:
dir- the directionalitycount- the new limit- Throws:
QuicException-FRAME_ENCODING_ERRORfor a limit above 260
-
receivedMaxData
public void receivedMaxData(long n) Processes a MAX_DATA frame; smaller limits than the current one are ignored.- Parameters:
n- the new connection-level limit
-
receivedMaxStreamData
Processes a MAX_STREAM_DATA frame.- Parameters:
id- the streamoffset- the new limit- Throws:
QuicException-STREAM_STATE_ERRORfor a receive-only or unopened stream,STREAM_LIMIT_ERRORbeyond the stream limit
-
resetAcked
Releases a stream whose RESET_STREAM was acknowledged.- Parameters:
id- the stream
-
receivedAckOf
Records that a STREAM frame was acknowledged; may release the stream and reportStreamEvent.Finished.- Parameters:
frame- what the frame carried
-
retransmit
Queues a lost STREAM frame's data to be sent again.- Parameters:
frame- what the frame carried
-
retransmitAfterZeroRttRejected
After the server rejected 0-RTT: if what the local streams used fits the server's actual limits, takes those limits and queues everything written to be sent again in 1-RTT packets, so the streams carry on as if the early data had been lost; otherwise forgets the local streams, as quinn does (zeroRttRejected()).- Parameters:
params- the server's transport parameters from this handshake- Returns:
- true if the streams carry on, false if they were forgotten
-
retransmitAllForZeroRtt
public void retransmitAllForZeroRtt()Queues everything written on local streams to be sent again after 0-RTT was rejected. -
writeLimit
public long writeLimit()How much the application may write now: the peer's remaining connection credit, limited by the send window.- Returns:
- bytes
-
poll
The next stream event.- Returns:
- the event, or null if there is none
-
queueMaxStreamId
Queues MAX_STREAMS if enough remote streams closed: more than an eighth of the concurrency limit.- Parameters:
retransmits- where to queue the frames- Returns:
- true if any were queued
-
canSendStreamData
public boolean canSendStreamData()Whether any stream has data to send, ignoring control frames.- Returns:
- true if
writeStreamFrames(java.nio.ByteBuffer, int, boolean)would write a frame
-
canSendFlowControl
Whether a MAX_STREAM_DATA for a stream would still be useful.- Parameters:
id- the stream- Returns:
- true if the stream is still receiving with an unknown final size
-
canSendDataBlocked
public boolean canSendDataBlocked()Whether a queued DATA_BLOCKED is still accurate.- Returns:
- true if the peer has not raised MAX_DATA since it was queued
-
streamDataBlockedLimit
The limit to put in a STREAM_DATA_BLOCKED for a stream.- Parameters:
id- the stream- Returns:
- the limit, or -1 if the frame is no longer accurate: the stream is not writable, was stopped, or the peer raised its limit
-
isLocalUnopened
Whether a local stream has never been opened.- Parameters:
id- a locally initiated stream- Returns:
- true if its index is beyond those opened
-
writeControlFrames
public void writeControlFrames(ByteBuffer buf, Retransmits retransmits, Retransmits sent, int maxSize) Writes pending stream control frames: RESET_STREAM, STOP_SENDING, MAX_DATA, MAX_STREAM_DATA, MAX_STREAMS, STREAMS_BLOCKED, DATA_BLOCKED and STREAM_DATA_BLOCKED, as many as fit. Each one written is recorded insent, to be queued again if the packet is lost.- Parameters:
buf- the packet payload, written at its positionretransmits- the pending frames; written ones are removedsent- the frames this packet carriesmaxSize- the position the frames must stay below
-
writeStreamFrames
Writes STREAM frames from the pending streams, highest priority first, as many as fit.- Parameters:
buf- the packet payload, written at its positionmaxBufSize- the position the frames must stay belowfair- true to requeue a partly written stream behind others of its priority, false to finish it first- Returns:
- what each frame carried, to keep with the sent packet
-