Closed CMCDragonkai closed 1 year ago
I recall something in the quic
RFC about ping frames being sent if a timeout were to happen soon. So I think keep alive is built into quic? It's something I'll have to check.
If we do need to implement keep alive logic here are a few ideas,
Quic
has ping frames, if it's not automatic then there may be a way to manually trigger them?No it isn't automatic. There is a specific function you have to call to initiate a ping frame in case of idleness.
5 May 2023 12:15:18 Brian Botha @.***>:
I recall something in the quic RFC about ping frames being sent if a timeout were to happen soon. So I think keep alive is built into quic? It's something I'll have to check.
If we do need to implement keep alive logic here are a few ideas,
- Quic has ping frames, if it's not automatic then there may be a way to manually trigger them?
- If we had to implement something then we can create a single stream to send our own ping/pong messages.
— Reply to this email directly, view it on GitHub[https://github.com/MatrixAI/js-quic/issues/6#issuecomment-1535613076], or unsubscribe[https://github.com/notifications/unsubscribe-auth/AAE4OHOGEDUUSBUN3SNKQC3XERPDHANCNFSM6AAAAAAWZXMLRA]. You are receiving this because you authored the thread.[Tracking image][https://github.com/notifications/beacon/AAE4OHMGV2D742ZGH5D3PADXERPDHA5CNFSM6AAAAAAWZXMLRCWGG33NNVSW45C7OR4XAZNMJFZXG5LFINXW23LFNZ2KUY3PNVWWK3TUL5UWJTS3Q6MJI.gif]
Looking over the quiche docs, the only mention of the ping frame is for the send_ack_eliciting
method https://docs.rs/quiche/latest/quiche/struct.Connection.html#method.send_ack_eliciting.
If I understand it correctly, After calling send_ack_eliciting
the next connection.send()
attempt will generate a ping frame packet if no other packets will be generated. If a packet was already waiting to be sent then it will do nothing. If it is called twice, only 1 new packet would be generated.
So to implement the keep-alive we just need to call send_ack_eliciting
on an interval. We could get fancy and check if x delay since a packet has been sent, but I don't think we need that.
So changes that need to be made.
send_ack_eliciting
and send
. Instead of a keepaliveIntervalTime
parameter for construction, I'm adding a setKeepAlive
method so we can set the keep alive at any time. Client and server will use this to set the keep alive after establishment.
Both sides doing timeouts looks something like this.
1 0.000000000 CLIENT Initial, PKN: 0, CRYPTO
2 0.003445980 SERVER Retry
3 0.004450904 CLIENT Initial, PKN: 1, CRYPTO
4 0.007895284 SERVER Handshake, PKN: 0, CRYPTO
5 0.008070888 SERVER Handshake, PKN: 1, CRYPTO
6 0.009016510 CLIENT Handshake, PKN: 0, ACK
7 0.010089535 CLIENT Handshake, PKN: 1, ACK, CRYPTO
8 0.011349064 SERVER Protected Payload (KP0), PKN: 0, DONE, CRYPTO
9 0.012237485 CLIENT Protected Payload (KP0), PKN: 0, ACK
10 1.007485100 SERVER Protected Payload (KP0), PKN: 1, PING, PADDING
11 1.008462923 CLIENT Protected Payload (KP0), PKN: 1, ACK
12 1.011268288 CLIENT Protected Payload (KP0), PKN: 2, PING, PADDING
13 1.012332313 SERVER Protected Payload (KP0), PKN: 2, ACK
14 2.008451188 SERVER Protected Payload (KP0), PKN: 3, PING, PADDING
15 2.009454311 CLIENT Protected Payload (KP0), PKN: 3, ACK
16 2.011583460 CLIENT Protected Payload (KP0), PKN: 4, PING, PADDING
17 2.012327978 SERVER Protected Payload (KP0), PKN: 4, ACK
18 3.009607920 SERVER Protected Payload (KP0), PKN: 5, PING, PADDING
19 3.010677245 CLIENT Protected Payload (KP0), PKN: 5, ACK
20 3.012587189 CLIENT Protected Payload (KP0), PKN: 6, PING, PADDING
21 3.013224903 SERVER Protected Payload (KP0), PKN: 6, ACK
22 4.011331505 SERVER Protected Payload (KP0), PKN: 7, PING, PADDING
23 4.012639335 CLIENT Protected Payload (KP0), PKN: 7, ACK
24 4.012986143 CLIENT Protected Payload (KP0), PKN: 8, PING, PADDING
25 4.014197071 SERVER Protected Payload (KP0), PKN: 8, ACK
26 5.012244510 SERVER Protected Payload (KP0), PKN: 9, PING, PADDING
27 5.012907725 CLIENT Protected Payload (KP0), PKN: 9, PING, PADDING
28 5.013517739 CLIENT Protected Payload (KP0), PKN: 10, ACK
29 5.014344358 SERVER Protected Payload (KP0), PKN: 10, ACK
30 6.012996752 SERVER Protected Payload (KP0), PKN: 11, PING, PADDING
31 6.013341960 CLIENT Protected Payload (KP0), PKN: 11, PING, PADDING
32 6.014423184 CLIENT Protected Payload (KP0), PKN: 12, ACK
33 6.014943796 SERVER Protected Payload (KP0), PKN: 12, ACK
34 6.312145693 CLIENT Protected Payload (KP0), PKN: 13, CC
This was fixed by d542dcb6a70e189c8234440bf30ab160b0369e9f but I put the wrong issue id in the commit message,
Resolving this.
Specification
After the QUIC connection is established, there's a max idle timeout. Nothing actually keeps the connection alive. If there's no activity on the connection either by stream data or datagram data, then the connection will timeout and be destroyed. Once destroyed, the
QUICClient
is destroyed, or theQUICServer
removes it from the connection map.We should have a interval loop that keeps the connection alive. This will be important for any connection that we need to maintain the NAT mappings. Which usually activity under 20 seconds.
One way to do this is with the send_ack_eliciting method. This method will queue up a PING frame if it detects there's nothing in the send queue that will keep the connection alive (and by nothing we mean something that will trigger an acknowledgement from the remote end).
I imagine that this can be done from both ends, the client and server. So both sides are capable of sending a PING frame and elicit an acknowledgement.
The function call is a noop if there's stuff ihttps://github.com/MatrixAI/js-quic/issues/1#issuecomment-1501236254n the queue that will keep the connection alive anyway.
We should add in a
keepaliveIntervalTime
that maintains the connection liveness toQUICConnection
. This can be added to theconfig
, although it's not actually used by thebuildQuicheConfig
.Alternatively it can be an extra parameter to the
QUICConnection
itself.I think this loop will be rather easy. It can be a
setTimeout
loop that just calls that function repeatedly. However this loop can only start once the connection is established, and the loop must not be running when the connection is closing or draining.Additional context
send_ack_eliciting
Tasks
keepAliveTime
option toQUICConnection
, propagate from bothQUICClient
andQUICServer
.