Files
upstream-pion-webrtc/pkg/media/rtpdump/reader.go
upstream-mirror 8acb1a3a29
Some checks failed
REUSE Compliance Check / lint (push) Failing after 0s
Browser E2E / Test (push) Failing after 3s
Test / test (1.24) (push) Failing after 0s
Test / test-i386 (1.25) (push) Failing after 0s
Test / test-i386 (1.24) (push) Failing after 0s
Test / test-windows (1.25) (push) Failing after 0s
Test / test-windows (1.24) (push) Failing after 0s
Test / test (1.25) (push) Failing after 0s
Examples Tests / Test (push) Failing after 3s
Test / test-macos (1.25) (push) Failing after 0s
Test / test-macos (1.24) (push) Failing after 0s
Go mod tidy / tidy (push) Failing after 0s
Test / test-wasm (push) Failing after 0s
CodeQL / analyze (push) Failing after 1s
Fuzz / fuzz (push) Failing after 0s
snapshot of https://github.com/pion/webrtc.git (main, 2026-09-15; blobs > 131072B omitted)
2026-09-15 20:06:07 +05:00

108 lines
2.2 KiB
Go

// SPDX-FileCopyrightText: 2026 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
package rtpdump
import (
"bufio"
"errors"
"io"
"regexp"
"sync"
)
// Reader reads the RTPDump file format.
type Reader struct {
readerMu sync.Mutex
reader io.Reader
}
// NewReader opens a new Reader and immediately reads the Header from the start
// of the input stream.
func NewReader(r io.Reader) (*Reader, Header, error) {
var hdr Header
bio := bufio.NewReader(r)
// Look ahead to see if there's a valid preamble
peek, err := bio.Peek(preambleLen)
if errors.Is(err, io.EOF) {
return nil, hdr, errMalformed
}
if err != nil {
return nil, hdr, err
}
// The file starts with #!rtpplay1.0 address/port\n
preambleRegexp := regexp.MustCompile(`#\!rtpplay1\.0 \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,5}\n`)
if !preambleRegexp.Match(peek) {
return nil, hdr, errMalformed
}
// consume the preamble
_, _, err = bio.ReadLine()
if errors.Is(err, io.EOF) {
return nil, hdr, errMalformed
}
if err != nil {
return nil, hdr, err
}
hBuf := make([]byte, headerLen)
_, err = io.ReadFull(bio, hBuf)
if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) {
return nil, hdr, errMalformed
}
if err != nil {
return nil, hdr, err
}
if err := hdr.Unmarshal(hBuf); err != nil {
return nil, hdr, err
}
return &Reader{
reader: bio,
}, hdr, nil
}
// Next returns the next Packet in the Reader input stream.
func (r *Reader) Next() (Packet, error) {
r.readerMu.Lock()
defer r.readerMu.Unlock()
hBuf := make([]byte, pktHeaderLen)
_, err := io.ReadFull(r.reader, hBuf)
if errors.Is(err, io.ErrUnexpectedEOF) {
return Packet{}, errMalformed
}
if err != nil {
return Packet{}, err
}
var header packetHeader
if err = header.Unmarshal(hBuf); err != nil {
return Packet{}, err
}
if header.Length == 0 {
return Packet{}, errMalformed
}
payload := make([]byte, header.Length-pktHeaderLen)
_, err = io.ReadFull(r.reader, payload)
if errors.Is(err, io.ErrUnexpectedEOF) {
return Packet{}, errMalformed
}
if err != nil {
return Packet{}, err
}
return Packet{
Offset: header.offset(),
IsRTCP: header.PacketLength == 0,
Payload: payload,
}, nil
}