reader_test.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package rtpdump
  4. import (
  5. "bytes"
  6. "errors"
  7. "io"
  8. "net"
  9. "reflect"
  10. "testing"
  11. "time"
  12. )
  13. func TestReader(t *testing.T) {
  14. validPreamble := []byte("#!rtpplay1.0 224.2.0.1/3456\n")
  15. for _, test := range []struct {
  16. Name string
  17. Data []byte
  18. WantHeader Header
  19. WantPackets []Packet
  20. WantErr error
  21. }{
  22. {
  23. Name: "empty",
  24. Data: nil,
  25. WantErr: errMalformed,
  26. },
  27. {
  28. Name: "hashbang missing ip/port",
  29. Data: append(
  30. []byte("#!rtpplay1.0 \n"),
  31. 0x00, 0x00, 0x00, 0x00,
  32. 0x00, 0x00, 0x00, 0x00,
  33. 0x00, 0x00, 0x00, 0x00,
  34. 0x00, 0x00, 0x00, 0x00,
  35. ),
  36. WantErr: errMalformed,
  37. },
  38. {
  39. Name: "hashbang missing port",
  40. Data: append(
  41. []byte("#!rtpplay1.0 0.0.0.0\n"),
  42. 0x00, 0x00, 0x00, 0x00,
  43. 0x00, 0x00, 0x00, 0x00,
  44. 0x00, 0x00, 0x00, 0x00,
  45. 0x00, 0x00, 0x00, 0x00,
  46. ),
  47. WantErr: errMalformed,
  48. },
  49. {
  50. Name: "valid empty file",
  51. Data: append(
  52. validPreamble,
  53. 0x00, 0x00, 0x00, 0x01,
  54. 0x00, 0x00, 0x00, 0x00,
  55. 0x01, 0x01, 0x01, 0x01,
  56. 0x22, 0xB8, 0x00, 0x00,
  57. ),
  58. WantHeader: Header{
  59. Start: time.Unix(1, 0).UTC(),
  60. Source: net.IPv4(1, 1, 1, 1),
  61. Port: 8888,
  62. },
  63. },
  64. {
  65. Name: "malformed packet header",
  66. Data: append(
  67. validPreamble,
  68. // header
  69. 0x00, 0x00, 0x00, 0x00,
  70. 0x00, 0x00, 0x00, 0x00,
  71. 0x00, 0x00, 0x00, 0x00,
  72. 0x00, 0x00, 0x00, 0x00,
  73. // packet header
  74. 0x00,
  75. ),
  76. WantHeader: Header{
  77. Start: time.Unix(0, 0).UTC(),
  78. Source: net.IPv4(0, 0, 0, 0),
  79. Port: 0,
  80. },
  81. WantErr: errMalformed,
  82. },
  83. {
  84. Name: "short packet payload",
  85. Data: append(
  86. validPreamble,
  87. // header
  88. 0x00, 0x00, 0x00, 0x00,
  89. 0x00, 0x00, 0x00, 0x00,
  90. 0x00, 0x00, 0x00, 0x00,
  91. 0x00, 0x00, 0x00, 0x00,
  92. // packet header len=1048575
  93. 0xFF, 0xFF, 0x00, 0x00,
  94. 0x00, 0x00, 0x00, 0x00,
  95. // packet payload
  96. 0x00,
  97. ),
  98. WantHeader: Header{
  99. Start: time.Unix(0, 0).UTC(),
  100. Source: net.IPv4(0, 0, 0, 0),
  101. Port: 0,
  102. },
  103. WantErr: errMalformed,
  104. },
  105. {
  106. Name: "empty packet payload",
  107. Data: append(
  108. validPreamble,
  109. // header
  110. 0x00, 0x00, 0x00, 0x00,
  111. 0x00, 0x00, 0x00, 0x00,
  112. 0x00, 0x00, 0x00, 0x00,
  113. 0x00, 0x00, 0x00, 0x00,
  114. // packet header len=0
  115. 0x00, 0x00, 0x00, 0x00,
  116. 0x00, 0x00, 0x00, 0x00,
  117. ),
  118. WantHeader: Header{
  119. Start: time.Unix(0, 0).UTC(),
  120. Source: net.IPv4(0, 0, 0, 0),
  121. Port: 0,
  122. },
  123. WantErr: errMalformed,
  124. },
  125. {
  126. Name: "valid rtcp packet",
  127. Data: append(
  128. validPreamble,
  129. // header
  130. 0x00, 0x00, 0x00, 0x00,
  131. 0x00, 0x00, 0x00, 0x00,
  132. 0x00, 0x00, 0x00, 0x00,
  133. 0x00, 0x00, 0x00, 0x00,
  134. // packet header len=20, pLen=0, off=1
  135. 0x00, 0x14, 0x00, 0x00,
  136. 0x00, 0x00, 0x00, 0x01,
  137. // packet payload (BYE)
  138. 0x81, 0xcb, 0x00, 0x0c,
  139. 0x90, 0x2f, 0x9e, 0x2e,
  140. 0x03, 0x46, 0x4f, 0x4f,
  141. ),
  142. WantHeader: Header{
  143. Start: time.Unix(0, 0).UTC(),
  144. Source: net.IPv4(0, 0, 0, 0),
  145. Port: 0,
  146. },
  147. WantPackets: []Packet{
  148. {
  149. Offset: time.Millisecond,
  150. IsRTCP: true,
  151. Payload: []byte{
  152. 0x81, 0xcb, 0x00, 0x0c,
  153. 0x90, 0x2f, 0x9e, 0x2e,
  154. 0x03, 0x46, 0x4f, 0x4f,
  155. },
  156. },
  157. },
  158. WantErr: nil,
  159. },
  160. {
  161. Name: "truncated rtcp packet",
  162. Data: append(
  163. validPreamble,
  164. // header
  165. 0x00, 0x00, 0x00, 0x00,
  166. 0x00, 0x00, 0x00, 0x00,
  167. 0x00, 0x00, 0x00, 0x00,
  168. 0x00, 0x00, 0x00, 0x00,
  169. // packet header len=9, pLen=0, off=1
  170. 0x00, 0x09, 0x00, 0x00,
  171. 0x00, 0x00, 0x00, 0x01,
  172. // invalid payload
  173. 0x81,
  174. ),
  175. WantHeader: Header{
  176. Start: time.Unix(0, 0).UTC(),
  177. Source: net.IPv4(0, 0, 0, 0),
  178. Port: 0,
  179. },
  180. WantPackets: []Packet{
  181. {
  182. Offset: time.Millisecond,
  183. IsRTCP: true,
  184. Payload: []byte{0x81},
  185. },
  186. },
  187. },
  188. {
  189. Name: "two valid packets",
  190. Data: append(
  191. validPreamble,
  192. // header
  193. 0x00, 0x00, 0x00, 0x00,
  194. 0x00, 0x00, 0x00, 0x00,
  195. 0x00, 0x00, 0x00, 0x00,
  196. 0x00, 0x00, 0x00, 0x00,
  197. // packet header len=20, pLen=0, off=1
  198. 0x00, 0x14, 0x00, 0x00,
  199. 0x00, 0x00, 0x00, 0x01,
  200. // packet payload (BYE)
  201. 0x81, 0xcb, 0x00, 0x0c,
  202. 0x90, 0x2f, 0x9e, 0x2e,
  203. 0x03, 0x46, 0x4f, 0x4f,
  204. // packet header len=33, pLen=0, off=2
  205. 0x00, 0x21, 0x00, 0x19,
  206. 0x00, 0x00, 0x00, 0x02,
  207. // packet payload (RTP)
  208. 0x90, 0x60, 0x69, 0x8f,
  209. 0xd9, 0xc2, 0x93, 0xda,
  210. 0x1c, 0x64, 0x27, 0x82,
  211. 0x00, 0x01, 0x00, 0x01,
  212. 0xFF, 0xFF, 0xFF, 0xFF,
  213. 0x98, 0x36, 0xbe, 0x88,
  214. 0x9e,
  215. ),
  216. WantHeader: Header{
  217. Start: time.Unix(0, 0).UTC(),
  218. Source: net.IPv4(0, 0, 0, 0),
  219. Port: 0,
  220. },
  221. WantPackets: []Packet{
  222. {
  223. Offset: time.Millisecond,
  224. IsRTCP: true,
  225. Payload: []byte{
  226. 0x81, 0xcb, 0x00, 0x0c,
  227. 0x90, 0x2f, 0x9e, 0x2e,
  228. 0x03, 0x46, 0x4f, 0x4f,
  229. },
  230. },
  231. {
  232. Offset: 2 * time.Millisecond,
  233. IsRTCP: false,
  234. Payload: []byte{
  235. 0x90, 0x60, 0x69, 0x8f,
  236. 0xd9, 0xc2, 0x93, 0xda,
  237. 0x1c, 0x64, 0x27, 0x82,
  238. 0x00, 0x01, 0x00, 0x01,
  239. 0xFF, 0xFF, 0xFF, 0xFF,
  240. 0x98, 0x36, 0xbe, 0x88,
  241. 0x9e,
  242. },
  243. },
  244. },
  245. WantErr: nil,
  246. },
  247. } {
  248. r, hdr, err := NewReader(bytes.NewReader(test.Data))
  249. if err != nil {
  250. if got, want := err, test.WantErr; !errors.Is(got, want) {
  251. t.Fatalf("NewReader(%s) err=%v want %v", test.Name, got, want)
  252. }
  253. continue
  254. }
  255. if got, want := hdr, test.WantHeader; !reflect.DeepEqual(got, want) {
  256. t.Fatalf("%q Header = %#v, want %#v", test.Name, got, want)
  257. }
  258. var nextErr error
  259. var packets []Packet
  260. for {
  261. pkt, err := r.Next()
  262. if errors.Is(err, io.EOF) {
  263. break
  264. }
  265. if err != nil {
  266. nextErr = err
  267. break
  268. }
  269. packets = append(packets, pkt)
  270. }
  271. if got, want := nextErr, test.WantErr; !errors.Is(got, want) {
  272. t.Fatalf("%s err=%v want %v", test.Name, got, want)
  273. }
  274. if got, want := packets, test.WantPackets; !reflect.DeepEqual(got, want) {
  275. t.Fatalf("%q packets=%#v, want %#v", test.Name, got, want)
  276. }
  277. }
  278. }