A shutdown is a graceful closure of a connection. Each side wants to maximize the chances that outstanding requests complete successfully.
Shutdown steps
A client or a server follows these steps when it wants to shutdown an icerpc connection:
Stop sending new requests (creating new streams) to the peer, and stop accepting new requests (accepting new streams) from the peer.
Send a
GoAway
frame to the peer over its outbound control stream.The
GoAway
frame carries two stream IDs, thebidirectionalStreamId
and theunidirectionalStreamId
. Any stream ID greater than or equal to these IDs will not be accepted by theGoAway
sender.This way, the peer can identify the outstanding requests it has sent (or is sending) and cancel these requests: they won't be accepted so it's pointless to let them continue. It's also safe to resend these requests over another connection, if possible.
Outstanding requests with lower stream IDs were accepted and the connection shutdown lets them proceed unimpeded.
The
GoAway
frame is all about the requests (streams) that theGoAway
sender accepts. It says nothing about the requests sent or being sent by theGoAway
sender.Wait to receive the peer's
GoAway
frame over the inbound control stream, and then cancel any outstanding requests that the peer won't accept.Wait for all local stream activity to complete (control streams aside).
Close its outbound control stream. This tells the peer: "all done on my side, you can close the connection".
Wait for the peer to close the inbound control stream, which means it's done (see above).
Close the multiplexed connection with the 0 error code (0 means no error). This step can fail because the peer closed the multiplexed connection first with error code 0. This remains a successful shutdown.
The following sequence diagram shows the interactions between the client and server on connection shutdown:
GoAway frame
The GoAway
frame is specified in Slice:
enum ControlFrameType : uint8 { Settings = 0 GoAway = 1}
compact struct GoAwayFrame { type: ControlFrameType // value is ControlFrameType::GoAway bodySize: varuint62 // the number of bytes in the remainder of the frame (between 2 and 16) bidirectionalStreamId: varuint62 unidirectionalStreamId: varuint62}