reader.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package rtpdump
  4. import (
  5. "bufio"
  6. "errors"
  7. "io"
  8. "regexp"
  9. "sync"
  10. )
  11. // Reader reads the RTPDump file format
  12. type Reader struct {
  13. readerMu sync.Mutex
  14. reader io.Reader
  15. }
  16. // NewReader opens a new Reader and immediately reads the Header from the start
  17. // of the input stream.
  18. func NewReader(r io.Reader) (*Reader, Header, error) {
  19. var hdr Header
  20. bio := bufio.NewReader(r)
  21. // Look ahead to see if there's a valid preamble
  22. peek, err := bio.Peek(preambleLen)
  23. if errors.Is(err, io.EOF) {
  24. return nil, hdr, errMalformed
  25. }
  26. if err != nil {
  27. return nil, hdr, err
  28. }
  29. // The file starts with #!rtpplay1.0 address/port\n
  30. preambleRegexp := regexp.MustCompile(`#\!rtpplay1\.0 \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,5}\n`)
  31. if !preambleRegexp.Match(peek) {
  32. return nil, hdr, errMalformed
  33. }
  34. // consume the preamble
  35. _, _, err = bio.ReadLine()
  36. if errors.Is(err, io.EOF) {
  37. return nil, hdr, errMalformed
  38. }
  39. if err != nil {
  40. return nil, hdr, err
  41. }
  42. hBuf := make([]byte, headerLen)
  43. _, err = io.ReadFull(bio, hBuf)
  44. if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) {
  45. return nil, hdr, errMalformed
  46. }
  47. if err != nil {
  48. return nil, hdr, err
  49. }
  50. if err := hdr.Unmarshal(hBuf); err != nil {
  51. return nil, hdr, err
  52. }
  53. return &Reader{
  54. reader: bio,
  55. }, hdr, nil
  56. }
  57. // Next returns the next Packet in the Reader input stream
  58. func (r *Reader) Next() (Packet, error) {
  59. r.readerMu.Lock()
  60. defer r.readerMu.Unlock()
  61. hBuf := make([]byte, pktHeaderLen)
  62. _, err := io.ReadFull(r.reader, hBuf)
  63. if errors.Is(err, io.ErrUnexpectedEOF) {
  64. return Packet{}, errMalformed
  65. }
  66. if err != nil {
  67. return Packet{}, err
  68. }
  69. var h packetHeader
  70. if err = h.Unmarshal(hBuf); err != nil {
  71. return Packet{}, err
  72. }
  73. if h.Length == 0 {
  74. return Packet{}, errMalformed
  75. }
  76. payload := make([]byte, h.Length-pktHeaderLen)
  77. _, err = io.ReadFull(r.reader, payload)
  78. if errors.Is(err, io.ErrUnexpectedEOF) {
  79. return Packet{}, errMalformed
  80. }
  81. if err != nil {
  82. return Packet{}, err
  83. }
  84. return Packet{
  85. Offset: h.offset(),
  86. IsRTCP: h.PacketLength == 0,
  87. Payload: payload,
  88. }, nil
  89. }