packet_buffer.go 6.5 KB

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