chandata.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package proto
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "errors"
  6. "io"
  7. )
  8. // ChannelData represents The ChannelData Message.
  9. //
  10. // See RFC 5766 Section 11.4
  11. type ChannelData struct {
  12. Data []byte // can be subslice of Raw
  13. Length int // ignored while encoding, len(Data) is used
  14. Number ChannelNumber
  15. Raw []byte
  16. }
  17. // Equal returns true if b == c.
  18. func (c *ChannelData) Equal(b *ChannelData) bool {
  19. if c == nil && b == nil {
  20. return true
  21. }
  22. if c == nil || b == nil {
  23. return false
  24. }
  25. if c.Number != b.Number {
  26. return false
  27. }
  28. if len(c.Data) != len(b.Data) {
  29. return false
  30. }
  31. return bytes.Equal(c.Data, b.Data)
  32. }
  33. // grow ensures that internal buffer will fit v more bytes and
  34. // increases it capacity if necessary.
  35. //
  36. // Similar to stun.Message.grow method.
  37. func (c *ChannelData) grow(v int) {
  38. n := len(c.Raw) + v
  39. for cap(c.Raw) < n {
  40. c.Raw = append(c.Raw, 0)
  41. }
  42. c.Raw = c.Raw[:n]
  43. }
  44. // Reset resets Length, Data and Raw length.
  45. func (c *ChannelData) Reset() {
  46. c.Raw = c.Raw[:0]
  47. c.Length = 0
  48. c.Data = c.Data[:0]
  49. }
  50. // Encode encodes ChannelData Message to Raw.
  51. func (c *ChannelData) Encode() {
  52. c.Raw = c.Raw[:0]
  53. c.WriteHeader()
  54. c.Raw = append(c.Raw, c.Data...)
  55. padded := nearestPaddedValueLength(len(c.Raw))
  56. if bytesToAdd := padded - len(c.Raw); bytesToAdd > 0 {
  57. for i := 0; i < bytesToAdd; i++ {
  58. c.Raw = append(c.Raw, 0)
  59. }
  60. }
  61. }
  62. const padding = 4
  63. func nearestPaddedValueLength(l int) int {
  64. n := padding * (l / padding)
  65. if n < l {
  66. n += padding
  67. }
  68. return n
  69. }
  70. // WriteHeader writes channel number and length.
  71. func (c *ChannelData) WriteHeader() {
  72. if len(c.Raw) < channelDataHeaderSize {
  73. // Making WriteHeader call valid even when c.Raw
  74. // is nil or len(c.Raw) is less than needed for header.
  75. c.grow(channelDataHeaderSize)
  76. }
  77. // Early bounds check to guarantee safety of writes below.
  78. _ = c.Raw[:channelDataHeaderSize]
  79. binary.BigEndian.PutUint16(c.Raw[:channelDataNumberSize], uint16(c.Number))
  80. binary.BigEndian.PutUint16(c.Raw[channelDataNumberSize:channelDataHeaderSize],
  81. uint16(len(c.Data)),
  82. )
  83. }
  84. // ErrBadChannelDataLength means that channel data length is not equal
  85. // to actual data length.
  86. var ErrBadChannelDataLength = errors.New("channelData length != len(Data)")
  87. // Decode decodes The ChannelData Message from Raw.
  88. func (c *ChannelData) Decode() error {
  89. buf := c.Raw
  90. if len(buf) < channelDataHeaderSize {
  91. return io.ErrUnexpectedEOF
  92. }
  93. num := binary.BigEndian.Uint16(buf[:channelDataNumberSize])
  94. c.Number = ChannelNumber(num)
  95. l := binary.BigEndian.Uint16(buf[channelDataNumberSize:channelDataHeaderSize])
  96. c.Data = buf[channelDataHeaderSize:]
  97. c.Length = int(l)
  98. if !c.Number.Valid() {
  99. return ErrInvalidChannelNumber
  100. }
  101. if int(l) < len(c.Data) {
  102. c.Data = c.Data[:int(l)]
  103. }
  104. if int(l) > len(buf[channelDataHeaderSize:]) {
  105. return ErrBadChannelDataLength
  106. }
  107. return nil
  108. }
  109. const (
  110. channelDataLengthSize = 2
  111. channelDataNumberSize = channelDataLengthSize
  112. channelDataHeaderSize = channelDataLengthSize + channelDataNumberSize
  113. )
  114. // IsChannelData returns true if buf looks like the ChannelData Message.
  115. func IsChannelData(buf []byte) bool {
  116. if len(buf) < channelDataHeaderSize {
  117. return false
  118. }
  119. if int(binary.BigEndian.Uint16(buf[channelDataNumberSize:channelDataHeaderSize])) > len(buf[channelDataHeaderSize:]) {
  120. return false
  121. }
  122. // Quick check for channel number.
  123. num := binary.BigEndian.Uint16(buf[0:channelNumberSize])
  124. return isChannelNumberValid(num)
  125. }