packet_buffer.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package rtcp
  4. import (
  5. "encoding/binary"
  6. "reflect"
  7. "unsafe"
  8. )
  9. // These functions implement an introspective structure
  10. // serializer/deserializer, designed to allow RTCP packet
  11. // Structs to be self-describing. They currently work with
  12. // fields of type uint8, uint16, uint32, and uint64 (and
  13. // types derived from them).
  14. //
  15. // - Unexported fields will take up space in the encoded
  16. // array, but wil be set to zero when written, and ignore
  17. // when read.
  18. //
  19. // - Fields that are marked with the tag `encoding:"omit"`
  20. // will be ignored when reading and writing data.
  21. //
  22. // For example:
  23. //
  24. // type Example struct {
  25. // A uint32
  26. // B bool `encoding:"omit"`
  27. // _ uint64
  28. // C uint16
  29. // }
  30. //
  31. // "A" will be encoded as four bytes, in network order. "B"
  32. // will not be encoded at all. The anonymous uint64 will
  33. // encode as 8 bytes of value "0", followed by two bytes
  34. // encoding "C" in network order.
  35. type packetBuffer struct {
  36. bytes []byte
  37. }
  38. const omit = "omit"
  39. // Writes the structure passed to into the buffer that
  40. // PacketBuffer is initialized with. This function will
  41. // modify the PacketBuffer.bytes slice to exclude those
  42. // bytes that have been written into.
  43. func (b *packetBuffer) write(v interface{}) error { //nolint:gocognit
  44. value := reflect.ValueOf(v)
  45. // Indirect is safe to call on non-pointers, and
  46. // will simply return the same value in such cases
  47. value = reflect.Indirect(value)
  48. switch value.Kind() {
  49. case reflect.Uint8:
  50. if len(b.bytes) < 1 {
  51. return errWrongMarshalSize
  52. }
  53. if value.CanInterface() {
  54. b.bytes[0] = byte(value.Uint())
  55. }
  56. b.bytes = b.bytes[1:]
  57. case reflect.Uint16:
  58. if len(b.bytes) < 2 {
  59. return errWrongMarshalSize
  60. }
  61. if value.CanInterface() {
  62. binary.BigEndian.PutUint16(b.bytes, uint16(value.Uint()))
  63. }
  64. b.bytes = b.bytes[2:]
  65. case reflect.Uint32:
  66. if len(b.bytes) < 4 {
  67. return errWrongMarshalSize
  68. }
  69. if value.CanInterface() {
  70. binary.BigEndian.PutUint32(b.bytes, uint32(value.Uint()))
  71. }
  72. b.bytes = b.bytes[4:]
  73. case reflect.Uint64:
  74. if len(b.bytes) < 8 {
  75. return errWrongMarshalSize
  76. }
  77. if value.CanInterface() {
  78. binary.BigEndian.PutUint64(b.bytes, value.Uint())
  79. }
  80. b.bytes = b.bytes[8:]
  81. case reflect.Slice:
  82. for i := 0; i < value.Len(); i++ {
  83. if value.Index(i).CanInterface() {
  84. if err := b.write(value.Index(i).Interface()); err != nil {
  85. return err
  86. }
  87. } else {
  88. b.bytes = b.bytes[value.Index(i).Type().Size():]
  89. }
  90. }
  91. case reflect.Struct:
  92. for i := 0; i < value.NumField(); i++ {
  93. encoding := value.Type().Field(i).Tag.Get("encoding")
  94. if encoding == omit {
  95. continue
  96. }
  97. if value.Field(i).CanInterface() {
  98. if err := b.write(value.Field(i).Interface()); err != nil {
  99. return err
  100. }
  101. } else {
  102. advance := int(value.Field(i).Type().Size())
  103. if len(b.bytes) < advance {
  104. return errWrongMarshalSize
  105. }
  106. b.bytes = b.bytes[advance:]
  107. }
  108. }
  109. default:
  110. return errBadStructMemberType
  111. }
  112. return nil
  113. }
  114. // Reads bytes from the buffer as necessary to populate
  115. // the structure passed as a parameter. This function will
  116. // modify the PacketBuffer.bytes slice to exclude those
  117. // bytes that have already been read.
  118. func (b *packetBuffer) read(v interface{}) error { //nolint:gocognit
  119. ptr := reflect.ValueOf(v)
  120. if ptr.Kind() != reflect.Ptr {
  121. return errBadReadParameter
  122. }
  123. value := reflect.Indirect(ptr)
  124. // If this is an interface, we need to make it concrete before using it
  125. if value.Kind() == reflect.Interface {
  126. value = reflect.ValueOf(value.Interface())
  127. }
  128. value = reflect.Indirect(value)
  129. switch value.Kind() {
  130. case reflect.Uint8:
  131. if len(b.bytes) < 1 {
  132. return errWrongMarshalSize
  133. }
  134. value.SetUint(uint64(b.bytes[0]))
  135. b.bytes = b.bytes[1:]
  136. case reflect.Uint16:
  137. if len(b.bytes) < 2 {
  138. return errWrongMarshalSize
  139. }
  140. value.SetUint(uint64(binary.BigEndian.Uint16(b.bytes)))
  141. b.bytes = b.bytes[2:]
  142. case reflect.Uint32:
  143. if len(b.bytes) < 4 {
  144. return errWrongMarshalSize
  145. }
  146. value.SetUint(uint64(binary.BigEndian.Uint32(b.bytes)))
  147. b.bytes = b.bytes[4:]
  148. case reflect.Uint64:
  149. if len(b.bytes) < 8 {
  150. return errWrongMarshalSize
  151. }
  152. value.SetUint(binary.BigEndian.Uint64(b.bytes))
  153. b.bytes = b.bytes[8:]
  154. case reflect.Slice:
  155. // If we encounter a slice, we consume the rest of the data
  156. // in the buffer and load it into the slice.
  157. for len(b.bytes) > 0 {
  158. newElementPtr := reflect.New(value.Type().Elem())
  159. if err := b.read(newElementPtr.Interface()); err != nil {
  160. return err
  161. }
  162. if value.CanSet() {
  163. value.Set(reflect.Append(value, reflect.Indirect(newElementPtr)))
  164. }
  165. }
  166. case reflect.Struct:
  167. for i := 0; i < value.NumField(); i++ {
  168. encoding := value.Type().Field(i).Tag.Get("encoding")
  169. if encoding == omit {
  170. continue
  171. }
  172. if value.Field(i).CanInterface() {
  173. field := value.Field(i)
  174. newFieldPtr := reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())) //nolint:gosec // This is the only way to get a typed pointer to a structure's field
  175. if err := b.read(newFieldPtr.Interface()); err != nil {
  176. return err
  177. }
  178. } else {
  179. advance := int(value.Field(i).Type().Size())
  180. if len(b.bytes) < advance {
  181. return errWrongMarshalSize
  182. }
  183. b.bytes = b.bytes[advance:]
  184. }
  185. }
  186. default:
  187. return errBadStructMemberType
  188. }
  189. return nil
  190. }
  191. // Consumes `size` bytes and returns them as an
  192. // independent PacketBuffer
  193. func (b *packetBuffer) split(size int) packetBuffer {
  194. if size > len(b.bytes) {
  195. size = len(b.bytes)
  196. }
  197. newBuffer := packetBuffer{bytes: b.bytes[:size]}
  198. b.bytes = b.bytes[size:]
  199. return newBuffer
  200. }
  201. // Returns the size that a structure will encode into.
  202. // This fuction doesn't check that Write() will succeed,
  203. // and may return unexpectedly large results for those
  204. // structures that Write() will fail on
  205. func wireSize(v interface{}) int {
  206. value := reflect.ValueOf(v)
  207. // Indirect is safe to call on non-pointers, and
  208. // will simply return the same value in such cases
  209. value = reflect.Indirect(value)
  210. size := int(0)
  211. switch value.Kind() {
  212. case reflect.Slice:
  213. for i := 0; i < value.Len(); i++ {
  214. if value.Index(i).CanInterface() {
  215. size += wireSize(value.Index(i).Interface())
  216. } else {
  217. size += int(value.Index(i).Type().Size())
  218. }
  219. }
  220. case reflect.Struct:
  221. for i := 0; i < value.NumField(); i++ {
  222. encoding := value.Type().Field(i).Tag.Get("encoding")
  223. if encoding == omit {
  224. continue
  225. }
  226. if value.Field(i).CanInterface() {
  227. size += wireSize(value.Field(i).Interface())
  228. } else {
  229. size += int(value.Field(i).Type().Size())
  230. }
  231. }
  232. default:
  233. size = int(value.Type().Size())
  234. }
  235. return size
  236. }