pending_queue.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package sctp
  4. import (
  5. "errors"
  6. )
  7. // pendingBaseQueue
  8. type pendingBaseQueue struct {
  9. queue []*chunkPayloadData
  10. }
  11. func newPendingBaseQueue() *pendingBaseQueue {
  12. return &pendingBaseQueue{queue: []*chunkPayloadData{}}
  13. }
  14. func (q *pendingBaseQueue) push(c *chunkPayloadData) {
  15. q.queue = append(q.queue, c)
  16. }
  17. func (q *pendingBaseQueue) pop() *chunkPayloadData {
  18. if len(q.queue) == 0 {
  19. return nil
  20. }
  21. c := q.queue[0]
  22. q.queue = q.queue[1:]
  23. return c
  24. }
  25. func (q *pendingBaseQueue) get(i int) *chunkPayloadData {
  26. if len(q.queue) == 0 || i < 0 || i >= len(q.queue) {
  27. return nil
  28. }
  29. return q.queue[i]
  30. }
  31. func (q *pendingBaseQueue) size() int {
  32. return len(q.queue)
  33. }
  34. // pendingQueue
  35. type pendingQueue struct {
  36. unorderedQueue *pendingBaseQueue
  37. orderedQueue *pendingBaseQueue
  38. nBytes int
  39. selected bool
  40. unorderedIsSelected bool
  41. }
  42. // Pending queue errors
  43. var (
  44. ErrUnexpectedChuckPoppedUnordered = errors.New("unexpected chunk popped (unordered)")
  45. ErrUnexpectedChuckPoppedOrdered = errors.New("unexpected chunk popped (ordered)")
  46. ErrUnexpectedQState = errors.New("unexpected q state (should've been selected)")
  47. )
  48. func newPendingQueue() *pendingQueue {
  49. return &pendingQueue{
  50. unorderedQueue: newPendingBaseQueue(),
  51. orderedQueue: newPendingBaseQueue(),
  52. }
  53. }
  54. func (q *pendingQueue) push(c *chunkPayloadData) {
  55. if c.unordered {
  56. q.unorderedQueue.push(c)
  57. } else {
  58. q.orderedQueue.push(c)
  59. }
  60. q.nBytes += len(c.userData)
  61. }
  62. func (q *pendingQueue) peek() *chunkPayloadData {
  63. if q.selected {
  64. if q.unorderedIsSelected {
  65. return q.unorderedQueue.get(0)
  66. }
  67. return q.orderedQueue.get(0)
  68. }
  69. if c := q.unorderedQueue.get(0); c != nil {
  70. return c
  71. }
  72. return q.orderedQueue.get(0)
  73. }
  74. func (q *pendingQueue) pop(c *chunkPayloadData) error {
  75. if q.selected {
  76. var popped *chunkPayloadData
  77. if q.unorderedIsSelected {
  78. popped = q.unorderedQueue.pop()
  79. if popped != c {
  80. return ErrUnexpectedChuckPoppedUnordered
  81. }
  82. } else {
  83. popped = q.orderedQueue.pop()
  84. if popped != c {
  85. return ErrUnexpectedChuckPoppedOrdered
  86. }
  87. }
  88. if popped.endingFragment {
  89. q.selected = false
  90. }
  91. } else {
  92. if !c.beginningFragment {
  93. return ErrUnexpectedQState
  94. }
  95. if c.unordered {
  96. popped := q.unorderedQueue.pop()
  97. if popped != c {
  98. return ErrUnexpectedChuckPoppedUnordered
  99. }
  100. if !popped.endingFragment {
  101. q.selected = true
  102. q.unorderedIsSelected = true
  103. }
  104. } else {
  105. popped := q.orderedQueue.pop()
  106. if popped != c {
  107. return ErrUnexpectedChuckPoppedOrdered
  108. }
  109. if !popped.endingFragment {
  110. q.selected = true
  111. q.unorderedIsSelected = false
  112. }
  113. }
  114. }
  115. q.nBytes -= len(c.userData)
  116. return nil
  117. }
  118. func (q *pendingQueue) getNumBytes() int {
  119. return q.nBytes
  120. }
  121. func (q *pendingQueue) size() int {
  122. return q.unorderedQueue.size() + q.orderedQueue.size()
  123. }