chunk_forward_tsn.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package sctp
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "fmt"
  6. )
  7. // This chunk shall be used by the data sender to inform the data
  8. // receiver to adjust its cumulative received TSN point forward because
  9. // some missing TSNs are associated with data chunks that SHOULD NOT be
  10. // transmitted or retransmitted by the sender.
  11. //
  12. // 0 1 2 3
  13. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  14. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  15. // | Type = 192 | Flags = 0x00 | Length = Variable |
  16. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  17. // | New Cumulative TSN |
  18. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  19. // | Stream-1 | Stream Sequence-1 |
  20. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  21. // \ /
  22. // / \
  23. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  24. // | Stream-N | Stream Sequence-N |
  25. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  26. type chunkForwardTSN struct {
  27. chunkHeader
  28. // This indicates the new cumulative TSN to the data receiver. Upon
  29. // the reception of this value, the data receiver MUST consider
  30. // any missing TSNs earlier than or equal to this value as received,
  31. // and stop reporting them as gaps in any subsequent SACKs.
  32. newCumulativeTSN uint32
  33. streams []chunkForwardTSNStream
  34. }
  35. const (
  36. newCumulativeTSNLength = 4
  37. forwardTSNStreamLength = 4
  38. )
  39. var (
  40. errMarshalStreamFailed = errors.New("failed to marshal stream")
  41. errChunkTooShort = errors.New("chunk too short")
  42. )
  43. func (c *chunkForwardTSN) unmarshal(raw []byte) error {
  44. if err := c.chunkHeader.unmarshal(raw); err != nil {
  45. return err
  46. }
  47. if len(c.raw) < newCumulativeTSNLength {
  48. return errChunkTooShort
  49. }
  50. c.newCumulativeTSN = binary.BigEndian.Uint32(c.raw[0:])
  51. offset := newCumulativeTSNLength
  52. remaining := len(c.raw) - offset
  53. for remaining > 0 {
  54. s := chunkForwardTSNStream{}
  55. if err := s.unmarshal(c.raw[offset:]); err != nil {
  56. return fmt.Errorf("%w: %v", errMarshalStreamFailed, err)
  57. }
  58. c.streams = append(c.streams, s)
  59. offset += s.length()
  60. remaining -= s.length()
  61. }
  62. return nil
  63. }
  64. func (c *chunkForwardTSN) marshal() ([]byte, error) {
  65. out := make([]byte, newCumulativeTSNLength)
  66. binary.BigEndian.PutUint32(out[0:], c.newCumulativeTSN)
  67. for _, s := range c.streams {
  68. b, err := s.marshal()
  69. if err != nil {
  70. return nil, fmt.Errorf("%w: %v", errMarshalStreamFailed, err)
  71. }
  72. out = append(out, b...)
  73. }
  74. c.typ = ctForwardTSN
  75. c.raw = out
  76. return c.chunkHeader.marshal()
  77. }
  78. func (c *chunkForwardTSN) check() (abort bool, err error) {
  79. return true, nil
  80. }
  81. // String makes chunkForwardTSN printable
  82. func (c *chunkForwardTSN) String() string {
  83. res := fmt.Sprintf("New Cumulative TSN: %d\n", c.newCumulativeTSN)
  84. for _, s := range c.streams {
  85. res += fmt.Sprintf(" - si=%d, ssn=%d\n", s.identifier, s.sequence)
  86. }
  87. return res
  88. }
  89. type chunkForwardTSNStream struct {
  90. // This field holds a stream number that was skipped by this
  91. // FWD-TSN.
  92. identifier uint16
  93. // This field holds the sequence number associated with the stream
  94. // that was skipped. The stream sequence field holds the largest
  95. // stream sequence number in this stream being skipped. The receiver
  96. // of the FWD-TSN's can use the Stream-N and Stream Sequence-N fields
  97. // to enable delivery of any stranded TSN's that remain on the stream
  98. // re-ordering queues. This field MUST NOT report TSN's corresponding
  99. // to DATA chunks that are marked as unordered. For ordered DATA
  100. // chunks this field MUST be filled in.
  101. sequence uint16
  102. }
  103. func (s *chunkForwardTSNStream) length() int {
  104. return forwardTSNStreamLength
  105. }
  106. func (s *chunkForwardTSNStream) unmarshal(raw []byte) error {
  107. if len(raw) < forwardTSNStreamLength {
  108. return errChunkTooShort
  109. }
  110. s.identifier = binary.BigEndian.Uint16(raw[0:])
  111. s.sequence = binary.BigEndian.Uint16(raw[2:])
  112. return nil
  113. }
  114. func (s *chunkForwardTSNStream) marshal() ([]byte, error) { // nolint:unparam
  115. out := make([]byte, forwardTSNStreamLength)
  116. binary.BigEndian.PutUint16(out[0:], s.identifier)
  117. binary.BigEndian.PutUint16(out[2:], s.sequence)
  118. return out, nil
  119. }