retransmission_queue.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package quic
  2. import (
  3. "fmt"
  4. "github.com/Psiphon-Labs/quic-go/internal/ackhandler"
  5. "github.com/Psiphon-Labs/quic-go/internal/protocol"
  6. "github.com/Psiphon-Labs/quic-go/internal/wire"
  7. )
  8. type retransmissionQueue struct {
  9. initial []wire.Frame
  10. initialCryptoData []*wire.CryptoFrame
  11. handshake []wire.Frame
  12. handshakeCryptoData []*wire.CryptoFrame
  13. appData []wire.Frame
  14. }
  15. func newRetransmissionQueue() *retransmissionQueue {
  16. return &retransmissionQueue{}
  17. }
  18. // AddPing queues a ping.
  19. // It is used when a probe packet needs to be sent
  20. func (q *retransmissionQueue) AddPing(encLevel protocol.EncryptionLevel) {
  21. //nolint:exhaustive // Cannot send probe packets for 0-RTT.
  22. switch encLevel {
  23. case protocol.EncryptionInitial:
  24. q.addInitial(&wire.PingFrame{})
  25. case protocol.EncryptionHandshake:
  26. q.addHandshake(&wire.PingFrame{})
  27. case protocol.Encryption1RTT:
  28. q.addAppData(&wire.PingFrame{})
  29. default:
  30. panic("unexpected encryption level")
  31. }
  32. }
  33. func (q *retransmissionQueue) addInitial(f wire.Frame) {
  34. if cf, ok := f.(*wire.CryptoFrame); ok {
  35. q.initialCryptoData = append(q.initialCryptoData, cf)
  36. return
  37. }
  38. q.initial = append(q.initial, f)
  39. }
  40. func (q *retransmissionQueue) addHandshake(f wire.Frame) {
  41. if cf, ok := f.(*wire.CryptoFrame); ok {
  42. q.handshakeCryptoData = append(q.handshakeCryptoData, cf)
  43. return
  44. }
  45. q.handshake = append(q.handshake, f)
  46. }
  47. func (q *retransmissionQueue) HasInitialData() bool {
  48. return len(q.initialCryptoData) > 0 || len(q.initial) > 0
  49. }
  50. func (q *retransmissionQueue) HasHandshakeData() bool {
  51. return len(q.handshakeCryptoData) > 0 || len(q.handshake) > 0
  52. }
  53. func (q *retransmissionQueue) HasAppData() bool {
  54. return len(q.appData) > 0
  55. }
  56. func (q *retransmissionQueue) addAppData(f wire.Frame) {
  57. if _, ok := f.(*wire.StreamFrame); ok {
  58. panic("STREAM frames are handled with their respective streams.")
  59. }
  60. q.appData = append(q.appData, f)
  61. }
  62. func (q *retransmissionQueue) GetInitialFrame(maxLen protocol.ByteCount, v protocol.VersionNumber) wire.Frame {
  63. if len(q.initialCryptoData) > 0 {
  64. f := q.initialCryptoData[0]
  65. newFrame, needsSplit := f.MaybeSplitOffFrame(maxLen, v)
  66. if newFrame == nil && !needsSplit { // the whole frame fits
  67. q.initialCryptoData = q.initialCryptoData[1:]
  68. return f
  69. }
  70. if newFrame != nil { // frame was split. Leave the original frame in the queue.
  71. return newFrame
  72. }
  73. }
  74. if len(q.initial) == 0 {
  75. return nil
  76. }
  77. f := q.initial[0]
  78. if f.Length(v) > maxLen {
  79. return nil
  80. }
  81. q.initial = q.initial[1:]
  82. return f
  83. }
  84. func (q *retransmissionQueue) GetHandshakeFrame(maxLen protocol.ByteCount, v protocol.VersionNumber) wire.Frame {
  85. if len(q.handshakeCryptoData) > 0 {
  86. f := q.handshakeCryptoData[0]
  87. newFrame, needsSplit := f.MaybeSplitOffFrame(maxLen, v)
  88. if newFrame == nil && !needsSplit { // the whole frame fits
  89. q.handshakeCryptoData = q.handshakeCryptoData[1:]
  90. return f
  91. }
  92. if newFrame != nil { // frame was split. Leave the original frame in the queue.
  93. return newFrame
  94. }
  95. }
  96. if len(q.handshake) == 0 {
  97. return nil
  98. }
  99. f := q.handshake[0]
  100. if f.Length(v) > maxLen {
  101. return nil
  102. }
  103. q.handshake = q.handshake[1:]
  104. return f
  105. }
  106. func (q *retransmissionQueue) GetAppDataFrame(maxLen protocol.ByteCount, v protocol.VersionNumber) wire.Frame {
  107. if len(q.appData) == 0 {
  108. return nil
  109. }
  110. f := q.appData[0]
  111. if f.Length(v) > maxLen {
  112. return nil
  113. }
  114. q.appData = q.appData[1:]
  115. return f
  116. }
  117. func (q *retransmissionQueue) DropPackets(encLevel protocol.EncryptionLevel) {
  118. //nolint:exhaustive // Can only drop Initial and Handshake packet number space.
  119. switch encLevel {
  120. case protocol.EncryptionInitial:
  121. q.initial = nil
  122. q.initialCryptoData = nil
  123. case protocol.EncryptionHandshake:
  124. q.handshake = nil
  125. q.handshakeCryptoData = nil
  126. default:
  127. panic(fmt.Sprintf("unexpected encryption level: %s", encLevel))
  128. }
  129. }
  130. func (q *retransmissionQueue) InitialAckHandler() ackhandler.FrameHandler {
  131. return (*retransmissionQueueInitialAckHandler)(q)
  132. }
  133. func (q *retransmissionQueue) HandshakeAckHandler() ackhandler.FrameHandler {
  134. return (*retransmissionQueueHandshakeAckHandler)(q)
  135. }
  136. func (q *retransmissionQueue) AppDataAckHandler() ackhandler.FrameHandler {
  137. return (*retransmissionQueueAppDataAckHandler)(q)
  138. }
  139. type retransmissionQueueInitialAckHandler retransmissionQueue
  140. func (q *retransmissionQueueInitialAckHandler) OnAcked(wire.Frame) {}
  141. func (q *retransmissionQueueInitialAckHandler) OnLost(f wire.Frame) {
  142. (*retransmissionQueue)(q).addInitial(f)
  143. }
  144. type retransmissionQueueHandshakeAckHandler retransmissionQueue
  145. func (q *retransmissionQueueHandshakeAckHandler) OnAcked(wire.Frame) {}
  146. func (q *retransmissionQueueHandshakeAckHandler) OnLost(f wire.Frame) {
  147. (*retransmissionQueue)(q).addHandshake(f)
  148. }
  149. type retransmissionQueueAppDataAckHandler retransmissionQueue
  150. func (q *retransmissionQueueAppDataAckHandler) OnAcked(wire.Frame) {}
  151. func (q *retransmissionQueueAppDataAckHandler) OnLost(f wire.Frame) {
  152. (*retransmissionQueue)(q).addAppData(f)
  153. }