improve write performance by

* buffering packets before sending them
* removing mutexes
This commit is contained in:
aler9
2021-12-08 17:46:56 +01:00
parent a1de5ffdf9
commit f3096ec102
20 changed files with 969 additions and 952 deletions

View File

@@ -9,6 +9,7 @@ package gortsplib
import (
"bufio"
"bytes"
"context"
"crypto/tls"
"fmt"
@@ -34,7 +35,6 @@ import (
const (
clientReadBufferSize = 4096
clientWriteBufferSize = 4096
clientUDPKernelReadBufferSize = 0x80000 // same size as gstreamer's rtspsrc
)
@@ -200,9 +200,8 @@ type Client struct {
ctx context.Context
ctxCancel func()
state clientState
nconn net.Conn
conn net.Conn
br *bufio.Reader
bw *bufio.Writer
session string
sender *auth.Sender
cseq int
@@ -213,7 +212,6 @@ type Client struct {
tracksByChannel map[int]int
lastRange *headers.Range
tcpReadBuffer *multibuffer.MultiBuffer
tcpWriteMutex sync.Mutex
writeMutex sync.RWMutex // publish
writeFrameAllowed bool // publish
udpReportTimer *time.Timer
@@ -609,10 +607,10 @@ func (c *Client) doClose(isClosing bool) {
}
}
if c.nconn != nil {
if c.conn != nil {
c.connCloserStop()
c.nconn.Close()
c.nconn = nil
c.conn.Close()
c.conn = nil
}
}
@@ -727,7 +725,7 @@ func (c *Client) playRecordStart() {
// for some reason, SetReadDeadline() must always be called in the same
// goroutine, otherwise Read() freezes.
// therefore, we disable the deadline and perform a check with a ticker.
c.nconn.SetReadDeadline(time.Time{})
c.conn.SetReadDeadline(time.Time{})
// start reader
c.readerErr = make(chan error)
@@ -768,8 +766,8 @@ func (c *Client) runReader() {
}
}
frame := base.InterleavedFrame{}
res := base.Response{}
var frame base.InterleavedFrame
var res base.Response
for {
frame.Payload = c.tcpReadBuffer.Next()
@@ -801,7 +799,7 @@ func (c *Client) runReader() {
func (c *Client) playRecordStop(isClosing bool) {
// stop reader
if c.readerErr != nil {
c.nconn.SetReadDeadline(time.Now())
c.conn.SetReadDeadline(time.Now())
<-c.readerErr
}
@@ -847,7 +845,7 @@ func (c *Client) connOpen() error {
return err
}
conn := func() net.Conn {
c.conn = func() net.Conn {
if c.scheme == "rtsps" {
tlsConfig := c.TLSConfig
@@ -863,9 +861,7 @@ func (c *Client) connOpen() error {
return nconn
}()
c.nconn = nconn
c.br = bufio.NewReaderSize(conn, clientReadBufferSize)
c.bw = bufio.NewWriterSize(conn, clientWriteBufferSize)
c.br = bufio.NewReaderSize(c.conn, clientReadBufferSize)
c.connCloserStart()
return nil
}
@@ -877,7 +873,7 @@ func (c *Client) connCloserStart() {
defer close(c.connCloserDone)
select {
case <-c.ctx.Done():
c.nconn.Close()
c.conn.Close()
case <-c.connCloserTerminate:
}
@@ -893,7 +889,7 @@ func (c *Client) connCloserStop() {
}
func (c *Client) do(req *base.Request, skipResponse bool) (*base.Response, error) {
if c.nconn == nil {
if c.conn == nil {
err := c.connOpen()
if err != nil {
return nil, err
@@ -924,8 +920,11 @@ func (c *Client) do(req *base.Request, skipResponse bool) (*base.Response, error
var res base.Response
err := func() error {
c.nconn.SetWriteDeadline(time.Now().Add(c.WriteTimeout))
err := req.Write(c.bw)
var buf bytes.Buffer
req.Write(&buf)
c.conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout))
_, err := c.conn.Write(buf.Bytes())
if err != nil {
return err
}
@@ -934,7 +933,7 @@ func (c *Client) do(req *base.Request, skipResponse bool) (*base.Response, error
return nil
}
c.nconn.SetReadDeadline(time.Now().Add(c.ReadTimeout))
c.conn.SetReadDeadline(time.Now().Add(c.ReadTimeout))
if c.tcpReadBuffer != nil {
// read the response and ignore interleaved frames in between;
@@ -1449,8 +1448,8 @@ func (c *Client) doSetup(
switch proto {
case TransportUDP:
rtpListener.remoteReadIP = c.nconn.RemoteAddr().(*net.TCPAddr).IP
rtpListener.remoteZone = c.nconn.RemoteAddr().(*net.TCPAddr).Zone
rtpListener.remoteReadIP = c.conn.RemoteAddr().(*net.TCPAddr).IP
rtpListener.remoteZone = c.conn.RemoteAddr().(*net.TCPAddr).Zone
if thRes.ServerPorts != nil {
rtpListener.remotePort = thRes.ServerPorts[0]
}
@@ -1459,13 +1458,13 @@ func (c *Client) doSetup(
cct.udpRTPListener = rtpListener
rtpListener.remoteWriteAddr = &net.UDPAddr{
IP: c.nconn.RemoteAddr().(*net.TCPAddr).IP,
IP: c.conn.RemoteAddr().(*net.TCPAddr).IP,
Zone: rtpListener.remoteZone,
Port: rtpListener.remotePort,
}
rtcpListener.remoteReadIP = c.nconn.RemoteAddr().(*net.TCPAddr).IP
rtcpListener.remoteZone = c.nconn.RemoteAddr().(*net.TCPAddr).Zone
rtcpListener.remoteReadIP = c.conn.RemoteAddr().(*net.TCPAddr).IP
rtcpListener.remoteZone = c.conn.RemoteAddr().(*net.TCPAddr).Zone
if thRes.ServerPorts != nil {
rtcpListener.remotePort = thRes.ServerPorts[1]
}
@@ -1474,13 +1473,13 @@ func (c *Client) doSetup(
cct.udpRTCPListener = rtcpListener
rtcpListener.remoteWriteAddr = &net.UDPAddr{
IP: c.nconn.RemoteAddr().(*net.TCPAddr).IP,
IP: c.conn.RemoteAddr().(*net.TCPAddr).IP,
Zone: rtcpListener.remoteZone,
Port: rtcpListener.remotePort,
}
case TransportUDPMulticast:
rtpListener.remoteReadIP = c.nconn.RemoteAddr().(*net.TCPAddr).IP
rtpListener.remoteReadIP = c.conn.RemoteAddr().(*net.TCPAddr).IP
rtpListener.remoteZone = ""
rtpListener.remotePort = thRes.Ports[0]
rtpListener.trackID = trackID
@@ -1493,7 +1492,7 @@ func (c *Client) doSetup(
Port: rtpListener.remotePort,
}
rtcpListener.remoteReadIP = c.nconn.RemoteAddr().(*net.TCPAddr).IP
rtcpListener.remoteReadIP = c.conn.RemoteAddr().(*net.TCPAddr).IP
rtcpListener.remoteZone = ""
rtcpListener.remotePort = thRes.Ports[1]
rtcpListener.trackID = trackID
@@ -1812,6 +1811,8 @@ func (c *Client) runWriter() {
}
default: // TCP
var buf bytes.Buffer
writeFunc = func(trackID int, isRTP bool, payload []byte) {
if isRTP {
if c.tracks[trackID].rtcpSender != nil {
@@ -1820,19 +1821,17 @@ func (c *Client) runWriter() {
f := c.tracks[trackID].tcpRTPFrame
f.Payload = payload
f.Write(&buf)
c.tcpWriteMutex.Lock()
c.nconn.SetWriteDeadline(time.Now().Add(c.WriteTimeout))
f.Write(c.bw)
c.tcpWriteMutex.Unlock()
c.conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout))
c.conn.Write(buf.Bytes())
} else {
f := c.tracks[trackID].tcpRTCPFrame
f.Payload = payload
f.Write(&buf)
c.tcpWriteMutex.Lock()
c.nconn.SetWriteDeadline(time.Now().Add(c.WriteTimeout))
f.Write(c.bw)
c.tcpWriteMutex.Unlock()
c.conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout))
c.conn.Write(buf.Bytes())
}
}
}

View File

@@ -2,6 +2,7 @@ package gortsplib
import (
"bufio"
"bytes"
"crypto/tls"
"net"
"strings"
@@ -48,14 +49,15 @@ func TestClientPublishSerial(t *testing.T) {
conn, err := l.Accept()
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
req, err := readRequest(bconn.Reader)
req, err := readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Options, req.Method)
require.Equal(t, mustParseURL(scheme+"://localhost:8554/teststream"), req.URL)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Public": base.HeaderValue{strings.Join([]string{
@@ -64,20 +66,22 @@ func TestClientPublishSerial(t *testing.T) {
string(base.Record),
}, ", ")},
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Announce, req.Method)
require.Equal(t, mustParseURL(scheme+"://localhost:8554/teststream"), req.URL)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Setup, req.Method)
require.Equal(t, mustParseURL(scheme+"://localhost:8554/teststream/trackID=0"), req.URL)
@@ -114,22 +118,24 @@ func TestClientPublishSerial(t *testing.T) {
th.InterleavedIDs = inTH.InterleavedIDs
}
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Transport": th.Write(),
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Record, req.Method)
require.Equal(t, mustParseURL(scheme+"://localhost:8554/teststream"), req.URL)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
// client -> server
@@ -141,7 +147,7 @@ func TestClientPublishSerial(t *testing.T) {
} else {
var f base.InterleavedFrame
f.Payload = make([]byte, 2048)
err = f.Read(bconn.Reader)
err = f.Read(br)
require.NoError(t, err)
require.Equal(t, 0, f.Channel)
require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, f.Payload)
@@ -154,21 +160,23 @@ func TestClientPublishSerial(t *testing.T) {
Port: th.ClientPorts[1],
})
} else {
err = base.InterleavedFrame{
base.InterleavedFrame{
Channel: 1,
Payload: []byte{0x05, 0x06, 0x07, 0x08},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Teardown, req.Method)
require.Equal(t, mustParseURL(scheme+"://localhost:8554/teststream"), req.URL)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}()
@@ -254,13 +262,14 @@ func TestClientPublishParallel(t *testing.T) {
conn, err := l.Accept()
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
req, err := readRequest(bconn.Reader)
req, err := readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Options, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Public": base.HeaderValue{strings.Join([]string{
@@ -269,19 +278,21 @@ func TestClientPublishParallel(t *testing.T) {
string(base.Record),
}, ", ")},
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Announce, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Setup, req.Method)
@@ -305,30 +316,33 @@ func TestClientPublishParallel(t *testing.T) {
th.InterleavedIDs = inTH.InterleavedIDs
}
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Transport": th.Write(),
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Record, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequestIgnoreFrames(bconn.Reader)
req, err = readRequestIgnoreFrames(br)
require.NoError(t, err)
require.Equal(t, base.Teardown, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}()
@@ -397,13 +411,14 @@ func TestClientPublishPauseSerial(t *testing.T) {
conn, err := l.Accept()
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
req, err := readRequest(bconn.Reader)
req, err := readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Options, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Public": base.HeaderValue{strings.Join([]string{
@@ -413,19 +428,21 @@ func TestClientPublishPauseSerial(t *testing.T) {
string(base.Pause),
}, ", ")},
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Announce, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Setup, req.Method)
@@ -449,48 +466,53 @@ func TestClientPublishPauseSerial(t *testing.T) {
th.InterleavedIDs = inTH.InterleavedIDs
}
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Transport": th.Write(),
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Record, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequestIgnoreFrames(bconn.Reader)
req, err = readRequestIgnoreFrames(br)
require.NoError(t, err)
require.Equal(t, base.Pause, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Record, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequestIgnoreFrames(bconn.Reader)
req, err = readRequestIgnoreFrames(br)
require.NoError(t, err)
require.Equal(t, base.Teardown, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}()
@@ -550,13 +572,14 @@ func TestClientPublishPauseParallel(t *testing.T) {
conn, err := l.Accept()
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
req, err := readRequest(bconn.Reader)
req, err := readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Options, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Public": base.HeaderValue{strings.Join([]string{
@@ -566,19 +589,21 @@ func TestClientPublishPauseParallel(t *testing.T) {
string(base.Pause),
}, ", ")},
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Announce, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Setup, req.Method)
@@ -602,30 +627,33 @@ func TestClientPublishPauseParallel(t *testing.T) {
th.InterleavedIDs = inTH.InterleavedIDs
}
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Transport": th.Write(),
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Record, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequestIgnoreFrames(bconn.Reader)
req, err = readRequestIgnoreFrames(br)
require.NoError(t, err)
require.Equal(t, base.Pause, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}()
@@ -689,14 +717,15 @@ func TestClientPublishAutomaticProtocol(t *testing.T) {
conn, err := l.Accept()
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
req, err := readRequest(bconn.Reader)
req, err := readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Options, req.Method)
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Public": base.HeaderValue{strings.Join([]string{
@@ -705,29 +734,32 @@ func TestClientPublishAutomaticProtocol(t *testing.T) {
string(base.Record),
}, ", ")},
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Announce, req.Method)
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Setup, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusUnsupportedTransport,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Setup, req.Method)
@@ -745,38 +777,41 @@ func TestClientPublishAutomaticProtocol(t *testing.T) {
InterleavedIDs: &[2]int{0, 1},
}
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Transport": th.Write(),
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Record, req.Method)
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
var f base.InterleavedFrame
f.Payload = make([]byte, 2048)
err = f.Read(bconn.Reader)
err = f.Read(br)
require.NoError(t, err)
require.Equal(t, 0, f.Channel)
require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, f.Payload)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Teardown, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}()
@@ -812,13 +847,14 @@ func TestClientPublishRTCPReport(t *testing.T) {
conn, err := l.Accept()
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
req, err := readRequest(bconn.Reader)
req, err := readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Options, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Public": base.HeaderValue{strings.Join([]string{
@@ -827,19 +863,21 @@ func TestClientPublishRTCPReport(t *testing.T) {
string(base.Record),
}, ", ")},
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Announce, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Setup, req.Method)
@@ -855,7 +893,7 @@ func TestClientPublishRTCPReport(t *testing.T) {
require.NoError(t, err)
defer l2.Close()
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Transport": headers.Transport{
@@ -868,16 +906,18 @@ func TestClientPublishRTCPReport(t *testing.T) {
ServerPorts: &[2]int{34556, 34557},
}.Write(),
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Record, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
rr := rtcpreceiver.New(nil, 90000)
@@ -905,13 +945,15 @@ func TestClientPublishRTCPReport(t *testing.T) {
close(reportReceived)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Teardown, req.Method)
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}()
c := &Client{
@@ -958,13 +1000,14 @@ func TestClientPublishIgnoreTCPRTPPackets(t *testing.T) {
conn, err := l.Accept()
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
req, err := readRequest(bconn.Reader)
req, err := readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Options, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Public": base.HeaderValue{strings.Join([]string{
@@ -973,19 +1016,21 @@ func TestClientPublishIgnoreTCPRTPPackets(t *testing.T) {
string(base.Record),
}, ", ")},
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Announce, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Setup, req.Method)
@@ -1002,42 +1047,48 @@ func TestClientPublishIgnoreTCPRTPPackets(t *testing.T) {
InterleavedIDs: inTH.InterleavedIDs,
}
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Transport": th.Write(),
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Record, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
err = base.InterleavedFrame{
base.InterleavedFrame{
Channel: 0,
Payload: []byte{0x01, 0x02, 0x03, 0x04},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
err = base.InterleavedFrame{
base.InterleavedFrame{
Channel: 1,
Payload: []byte{0x05, 0x06, 0x07, 0x08},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Teardown, req.Method)
base.Response{
StatusCode: base.StatusOK,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}()
rtcpReceived := make(chan struct{})

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,7 @@ package gortsplib
import (
"bufio"
"bytes"
"crypto/tls"
"net"
"strings"
@@ -93,14 +94,15 @@ func TestClientSession(t *testing.T) {
conn, err := l.Accept()
require.NoError(t, err)
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
defer conn.Close()
req, err := readRequest(bconn.Reader)
req, err := readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Options, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Public": base.HeaderValue{strings.Join([]string{
@@ -108,10 +110,11 @@ func TestClientSession(t *testing.T) {
}, ", ")},
"Session": base.HeaderValue{"123456"},
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Describe, req.Method)
@@ -124,14 +127,15 @@ func TestClientSession(t *testing.T) {
tracks := cloneAndClearTracks(Tracks{track})
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Content-Type": base.HeaderValue{"application/sdp"},
"Session": base.HeaderValue{"123456"},
},
Body: tracks.Write(false),
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}()
@@ -163,38 +167,41 @@ func TestClientAuth(t *testing.T) {
conn, err := l.Accept()
require.NoError(t, err)
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
defer conn.Close()
req, err := readRequest(bconn.Reader)
req, err := readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Options, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Public": base.HeaderValue{strings.Join([]string{
string(base.Describe),
}, ", ")},
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Describe, req.Method)
v := auth.NewValidator("myuser", "mypass", nil)
err = base.Response{
base.Response{
StatusCode: base.StatusUnauthorized,
Header: base.Header{
"WWW-Authenticate": v.Header(),
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Describe, req.Method)
@@ -208,13 +215,14 @@ func TestClientAuth(t *testing.T) {
tracks := cloneAndClearTracks(Tracks{track})
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Content-Type": base.HeaderValue{"application/sdp"},
},
Body: tracks.Write(false),
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}()
@@ -247,23 +255,25 @@ func TestClientDescribeCharset(t *testing.T) {
conn, err := l.Accept()
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
req, err := readRequest(bconn.Reader)
req, err := readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Options, req.Method)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Public": base.HeaderValue{strings.Join([]string{
string(base.Describe),
}, ", ")},
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
req, err = readRequest(bconn.Reader)
req, err = readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Describe, req.Method)
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
@@ -273,14 +283,15 @@ func TestClientDescribeCharset(t *testing.T) {
})
require.NoError(t, err)
err = base.Response{
base.Response{
StatusCode: base.StatusOK,
Header: base.Header{
"Content-Type": base.HeaderValue{"application/sdp; charset=utf-8"},
"Content-Base": base.HeaderValue{"rtsp://localhost:8554/teststream/"},
},
Body: Tracks{track1}.Write(false),
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}()
@@ -349,9 +360,9 @@ func TestClientCloseDuringRequest(t *testing.T) {
conn, err := l.Accept()
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
req, err := readRequest(bconn.Reader)
req, err := readRequest(br)
require.NoError(t, err)
require.Equal(t, base.Options, req.Method)

View File

@@ -2,6 +2,7 @@ package base
import (
"bufio"
"bytes"
"fmt"
"io"
"strconv"
@@ -35,15 +36,10 @@ func (b *body) read(header Header, rb *bufio.Reader) error {
return nil
}
func (b body) write(bw *bufio.Writer) error {
func (b body) write(bb *bytes.Buffer) {
if len(b) == 0 {
return nil
return
}
_, err := bw.Write(b)
if err != nil {
return err
}
return nil
bb.Write(b)
}

View File

@@ -3,25 +3,11 @@ package base
import (
"bufio"
"bytes"
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
type limitedBuffer struct {
cap int
n int
}
func (b *limitedBuffer) Write(p []byte) (int, error) {
b.n += len(p)
if b.n > b.cap {
return 0, fmt.Errorf("capacity reached")
}
return len(p), nil
}
var casesBody = []struct {
name string
h Header
@@ -52,19 +38,6 @@ func TestBodyRead(t *testing.T) {
}
}
func TestBodyWrite(t *testing.T) {
for _, ca := range casesBody {
t.Run(ca.name, func(t *testing.T) {
var buf bytes.Buffer
bw := bufio.NewWriter(&buf)
err := body(ca.byts).write(bw)
require.NoError(t, err)
bw.Flush()
require.Equal(t, ca.byts, buf.Bytes())
})
}
}
func TestBodyReadErrors(t *testing.T) {
for _, ca := range []struct {
name string
@@ -105,8 +78,12 @@ func TestBodyReadErrors(t *testing.T) {
}
}
func TestBodyWriteErrors(t *testing.T) {
bw := bufio.NewWriterSize(&limitedBuffer{cap: 3}, 1)
err := body([]byte("1234")).write(bw)
require.EqualError(t, err, "capacity reached")
func TestBodyWrite(t *testing.T) {
for _, ca := range casesBody {
t.Run(ca.name, func(t *testing.T) {
var buf bytes.Buffer
body(ca.byts).write(&buf)
require.Equal(t, ca.byts, buf.Bytes())
})
}
}

View File

@@ -2,6 +2,7 @@ package base
import (
"bufio"
"bytes"
"fmt"
"net/http"
"sort"
@@ -97,7 +98,7 @@ func (h *Header) read(rb *bufio.Reader) error {
return nil
}
func (h Header) write(wb *bufio.Writer) error {
func (h Header) write(bb *bytes.Buffer) {
// sort headers by key
// in order to obtain deterministic results
keys := make([]string, len(h))
@@ -108,17 +109,9 @@ func (h Header) write(wb *bufio.Writer) error {
for _, key := range keys {
for _, val := range h[key] {
_, err := wb.Write([]byte(key + ": " + val + "\r\n"))
if err != nil {
return err
}
bb.Write([]byte(key + ": " + val + "\r\n"))
}
}
_, err := wb.Write([]byte("\r\n"))
if err != nil {
return err
}
return nil
bb.Write([]byte("\r\n"))
}

View File

@@ -116,19 +116,6 @@ func TestHeaderRead(t *testing.T) {
}
}
func TestHeaderWrite(t *testing.T) {
for _, ca := range casesHeader {
t.Run(ca.name, func(t *testing.T) {
var buf bytes.Buffer
bw := bufio.NewWriter(&buf)
err := ca.header.write(bw)
require.NoError(t, err)
bw.Flush()
require.Equal(t, ca.enc, buf.Bytes())
})
}
}
func TestHeaderReadErrors(t *testing.T) {
for _, ca := range []struct {
name string
@@ -186,26 +173,12 @@ func TestHeaderReadErrors(t *testing.T) {
}
}
func TestHeaderWriteErrors(t *testing.T) {
for _, ca := range []struct {
name string
cap int
}{
{
"values",
3,
},
{
"final newline",
12,
},
} {
func TestHeaderWrite(t *testing.T) {
for _, ca := range casesHeader {
t.Run(ca.name, func(t *testing.T) {
bw := bufio.NewWriterSize(&limitedBuffer{cap: ca.cap}, 1)
err := Header{
"Value": HeaderValue{"key"},
}.write(bw)
require.EqualError(t, err, "capacity reached")
var buf bytes.Buffer
ca.header.write(&buf)
require.Equal(t, ca.enc, buf.Bytes())
})
}
}

View File

@@ -2,6 +2,7 @@ package base
import (
"bufio"
"bytes"
"encoding/binary"
"fmt"
"io"
@@ -96,19 +97,13 @@ func (f *InterleavedFrame) Read(br *bufio.Reader) error {
}
// Write writes an InterleavedFrame into a buffered writer.
func (f InterleavedFrame) Write(bw *bufio.Writer) error {
func (f InterleavedFrame) Write(bb *bytes.Buffer) {
bb.Reset()
buf := []byte{0x24, byte(f.Channel), 0x00, 0x00}
binary.BigEndian.PutUint16(buf[2:], uint16(len(f.Payload)))
_, err := bw.Write(buf)
if err != nil {
return err
}
bb.Write(buf)
_, err = bw.Write(f.Payload)
if err != nil {
return err
}
return bw.Flush()
bb.Write(f.Payload)
}

View File

@@ -45,19 +45,6 @@ func TestInterleavedFrameRead(t *testing.T) {
}
}
func TestInterleavedFrameWrite(t *testing.T) {
for _, ca := range casesInterleavedFrame {
t.Run(ca.name, func(t *testing.T) {
var buf bytes.Buffer
bw := bufio.NewWriter(&buf)
err := ca.dec.Write(bw)
require.NoError(t, err)
bw.Flush()
require.Equal(t, ca.enc, buf.Bytes())
})
}
}
func TestInterleavedFrameReadErrors(t *testing.T) {
for _, ca := range []struct {
name string
@@ -94,27 +81,12 @@ func TestInterleavedFrameReadErrors(t *testing.T) {
}
}
func TestInterleavedFrameWriteErrors(t *testing.T) {
for _, ca := range []struct {
name string
cap int
}{
{
"header",
3,
},
{
"content",
6,
},
} {
func TestInterleavedFrameWrite(t *testing.T) {
for _, ca := range casesInterleavedFrame {
t.Run(ca.name, func(t *testing.T) {
bw := bufio.NewWriterSize(&limitedBuffer{cap: ca.cap}, 1)
err := InterleavedFrame{
Channel: 3,
Payload: []byte{0x01, 0x02, 0x03, 0x04},
}.Write(bw)
require.EqualError(t, err, "capacity reached")
var buf bytes.Buffer
ca.dec.Write(&buf)
require.Equal(t, ca.enc, buf.Bytes())
})
}
}

View File

@@ -121,33 +121,24 @@ func (req *Request) ReadIgnoreFrames(rb *bufio.Reader, buf []byte) error {
}
// Write writes a request.
func (req Request) Write(bw *bufio.Writer) error {
func (req Request) Write(bb *bytes.Buffer) {
bb.Reset()
urStr := req.URL.CloneWithoutCredentials().String()
_, err := bw.Write([]byte(string(req.Method) + " " + urStr + " " + rtspProtocol10 + "\r\n"))
if err != nil {
return err
}
bb.Write([]byte(string(req.Method) + " " + urStr + " " + rtspProtocol10 + "\r\n"))
if len(req.Body) != 0 {
req.Header["Content-Length"] = HeaderValue{strconv.FormatInt(int64(len(req.Body)), 10)}
}
err = req.Header.write(bw)
if err != nil {
return err
}
req.Header.write(bb)
err = body(req.Body).write(bw)
if err != nil {
return err
}
return bw.Flush()
body(req.Body).write(bb)
}
// String implements fmt.Stringer.
func (req Request) String() string {
buf := bytes.NewBuffer(nil)
req.Write(bufio.NewWriter(buf))
var buf bytes.Buffer
req.Write(&buf)
return buf.String()
}

View File

@@ -143,19 +143,6 @@ func TestRequestRead(t *testing.T) {
}
}
func TestRequestWrite(t *testing.T) {
for _, ca := range casesRequest {
t.Run(ca.name, func(t *testing.T) {
var buf bytes.Buffer
bw := bufio.NewWriter(&buf)
err := ca.req.Write(bw)
require.NoError(t, err)
// do NOT call flush(), write() must have already done it
require.Equal(t, ca.byts, buf.Bytes())
})
}
}
func TestRequestReadErrors(t *testing.T) {
for _, ca := range []struct {
name string
@@ -231,35 +218,12 @@ func TestRequestReadErrors(t *testing.T) {
}
}
func TestRequestWriteErrors(t *testing.T) {
for _, ca := range []struct {
name string
cap int
}{
{
"first line",
3,
},
{
"header",
53,
},
{
"body",
80,
},
} {
func TestRequestWrite(t *testing.T) {
for _, ca := range casesRequest {
t.Run(ca.name, func(t *testing.T) {
bw := bufio.NewWriterSize(&limitedBuffer{cap: ca.cap}, 1)
err := Request{
Method: "ANNOUNCE",
URL: mustParseURL("rtsp://example.com/media.mp4"),
Header: Header{
"CSeq": HeaderValue{"7"},
},
Body: []byte("abc"),
}.Write(bw)
require.EqualError(t, err, "capacity reached")
var buf bytes.Buffer
ca.req.Write(&buf)
require.Equal(t, ca.byts, buf.Bytes())
})
}
}

View File

@@ -207,40 +207,31 @@ func (res *Response) ReadIgnoreFrames(rb *bufio.Reader, buf []byte) error {
}
// Write writes a Response.
func (res Response) Write(bw *bufio.Writer) error {
func (res Response) Write(bb *bytes.Buffer) {
bb.Reset()
if res.StatusMessage == "" {
if status, ok := statusMessages[res.StatusCode]; ok {
res.StatusMessage = status
}
}
_, err := bw.Write([]byte(rtspProtocol10 + " " +
bb.Write([]byte(rtspProtocol10 + " " +
strconv.FormatInt(int64(res.StatusCode), 10) + " " +
res.StatusMessage + "\r\n"))
if err != nil {
return err
}
if len(res.Body) != 0 {
res.Header["Content-Length"] = HeaderValue{strconv.FormatInt(int64(len(res.Body)), 10)}
}
err = res.Header.write(bw)
if err != nil {
return err
}
res.Header.write(bb)
err = body(res.Body).write(bw)
if err != nil {
return err
}
return bw.Flush()
body(res.Body).write(bb)
}
// String implements fmt.Stringer.
func (res Response) String() string {
buf := bytes.NewBuffer(nil)
res.Write(bufio.NewWriter(buf))
var buf bytes.Buffer
res.Write(&buf)
return buf.String()
}

View File

@@ -105,19 +105,6 @@ func TestResponseRead(t *testing.T) {
}
}
func TestResponseWrite(t *testing.T) {
for _, c := range casesResponse {
t.Run(c.name, func(t *testing.T) {
var buf bytes.Buffer
bw := bufio.NewWriter(&buf)
err := c.res.Write(bw)
require.NoError(t, err)
// do NOT call flush(), write() must have already done it
require.Equal(t, c.byts, buf.Bytes())
})
}
}
func TestResponseReadErrors(t *testing.T) {
for _, ca := range []struct {
name string
@@ -188,35 +175,12 @@ func TestResponseReadErrors(t *testing.T) {
}
}
func TestResponseWriteErrors(t *testing.T) {
for _, ca := range []struct {
name string
cap int
}{
{
"first line",
14,
},
{
"header",
21,
},
{
"body",
49,
},
} {
t.Run(ca.name, func(t *testing.T) {
bw := bufio.NewWriterSize(&limitedBuffer{cap: ca.cap}, 1)
err := Response{
StatusCode: 200,
StatusMessage: "OK",
Header: Header{
"CSeq": HeaderValue{"2"},
},
Body: []byte("abc"),
}.Write(bw)
require.EqualError(t, err, "capacity reached")
func TestResponseWrite(t *testing.T) {
for _, c := range casesResponse {
t.Run(c.name, func(t *testing.T) {
var buf bytes.Buffer
c.res.Write(&buf)
require.Equal(t, c.byts, buf.Bytes())
})
}
}
@@ -244,9 +208,7 @@ func TestResponseWriteAutoFillStatus(t *testing.T) {
)
var buf bytes.Buffer
bw := bufio.NewWriter(&buf)
err := res.Write(bw)
require.NoError(t, err)
res.Write(&buf)
require.Equal(t, byts, buf.Bytes())
}

View File

@@ -17,7 +17,6 @@ import (
const (
serverReadBufferSize = 4096
serverWriteBufferSize = 4096
serverUDPKernelReadBufferSize = 0x80000 // same as gstreamer's rtspsrc
)

View File

@@ -171,9 +171,9 @@ func TestServerPublishErrorAnnounce(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
_, err = writeReqReadRes(bconn, ca.req)
_, err = writeReqReadRes(conn, br, ca.req)
require.NoError(t, err)
<-connClosed
@@ -258,7 +258,7 @@ func TestServerPublishSetupPath(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
track, err := NewTrackH264(96, &TrackConfigH264{
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04},
@@ -287,7 +287,7 @@ func TestServerPublishSetupPath(t *testing.T) {
byts, _ := sout.Marshal()
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Announce,
URL: mustParseURL("rtsp://localhost:8554/" + ca.path),
Header: base.Header{
@@ -312,7 +312,7 @@ func TestServerPublishSetupPath(t *testing.T) {
InterleavedIDs: &[2]int{0, 1},
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL(ca.url),
Header: base.Header{
@@ -356,7 +356,7 @@ func TestServerPublishErrorSetupDifferentPaths(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
track, err := NewTrackH264(96, &TrackConfigH264{
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04},
@@ -371,7 +371,7 @@ func TestServerPublishErrorSetupDifferentPaths(t *testing.T) {
})
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Announce,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -396,7 +396,7 @@ func TestServerPublishErrorSetupDifferentPaths(t *testing.T) {
InterleavedIDs: &[2]int{0, 1},
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/test2stream/trackID=0"),
Header: base.Header{
@@ -441,7 +441,7 @@ func TestServerPublishErrorSetupTrackTwice(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
track, err := NewTrackH264(96, &TrackConfigH264{
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04},
@@ -456,7 +456,7 @@ func TestServerPublishErrorSetupTrackTwice(t *testing.T) {
})
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Announce,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -481,7 +481,7 @@ func TestServerPublishErrorSetupTrackTwice(t *testing.T) {
InterleavedIDs: &[2]int{0, 1},
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -493,7 +493,7 @@ func TestServerPublishErrorSetupTrackTwice(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -543,7 +543,7 @@ func TestServerPublishErrorRecordPartialTracks(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
track1, err := NewTrackH264(96, &TrackConfigH264{
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04},
@@ -563,7 +563,7 @@ func TestServerPublishErrorRecordPartialTracks(t *testing.T) {
})
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Announce,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -588,7 +588,7 @@ func TestServerPublishErrorRecordPartialTracks(t *testing.T) {
InterleavedIDs: &[2]int{0, 1},
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -600,7 +600,7 @@ func TestServerPublishErrorRecordPartialTracks(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Record,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -684,17 +684,18 @@ func TestServerPublish(t *testing.T) {
require.NoError(t, err)
defer s.Close()
nconn, err := net.Dial("tcp", "localhost:8554")
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer nconn.Close()
defer conn.Close()
conn := func() net.Conn {
conn = func() net.Conn {
if transport == "tls" {
return tls.Client(nconn, &tls.Config{InsecureSkipVerify: true})
return tls.Client(conn, &tls.Config{InsecureSkipVerify: true})
}
return nconn
return conn
}()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
<-connOpened
@@ -711,7 +712,7 @@ func TestServerPublish(t *testing.T) {
})
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Announce,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -755,7 +756,7 @@ func TestServerPublish(t *testing.T) {
inTH.InterleavedIDs = &[2]int{0, 1}
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -771,7 +772,7 @@ func TestServerPublish(t *testing.T) {
err = th.Read(res.Header["Transport"])
require.NoError(t, err)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Record,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -798,16 +799,18 @@ func TestServerPublish(t *testing.T) {
Port: th.ServerPorts[1],
})
} else {
err = base.InterleavedFrame{
base.InterleavedFrame{
Channel: 0,
Payload: []byte{0x01, 0x02, 0x03, 0x04},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
err = base.InterleavedFrame{
base.InterleavedFrame{
Channel: 1,
Payload: []byte{0x05, 0x06, 0x07, 0x08},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}
@@ -825,13 +828,13 @@ func TestServerPublish(t *testing.T) {
} else {
var f base.InterleavedFrame
f.Payload = make([]byte, 2048)
err := f.Read(bconn.Reader)
err := f.Read(br)
require.NoError(t, err)
require.Equal(t, 1, f.Channel)
require.Equal(t, []byte{0x09, 0x0A, 0x0B, 0x0C}, f.Payload)
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Teardown,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -885,10 +888,11 @@ func TestServerPublishNonStandardFrameSize(t *testing.T) {
require.NoError(t, err)
defer s.Close()
nconn, err := net.Dial("tcp", "localhost:8554")
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer nconn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(nconn), bufio.NewWriter(nconn))
defer conn.Close()
br := bufio.NewReader(conn)
var bb bytes.Buffer
track, err := NewTrackH264(96, &TrackConfigH264{
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04},
@@ -900,7 +904,7 @@ func TestServerPublishNonStandardFrameSize(t *testing.T) {
Value: "trackID=0",
})
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Announce,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -925,7 +929,7 @@ func TestServerPublishNonStandardFrameSize(t *testing.T) {
InterleavedIDs: &[2]int{0, 1},
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -937,7 +941,7 @@ func TestServerPublishNonStandardFrameSize(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Record,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -948,10 +952,11 @@ func TestServerPublishNonStandardFrameSize(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
err = base.InterleavedFrame{
base.InterleavedFrame{
Channel: 0,
Payload: payload,
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
<-frameReceived
@@ -991,7 +996,8 @@ func TestServerPublishErrorInvalidProtocol(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
track, err := NewTrackH264(96, &TrackConfigH264{
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04},
@@ -1006,7 +1012,7 @@ func TestServerPublishErrorInvalidProtocol(t *testing.T) {
})
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Announce,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1031,7 +1037,7 @@ func TestServerPublishErrorInvalidProtocol(t *testing.T) {
ClientPorts: &[2]int{35466, 35467},
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1047,7 +1053,7 @@ func TestServerPublishErrorInvalidProtocol(t *testing.T) {
err = th.Read(res.Header["Transport"])
require.NoError(t, err)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Record,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1058,10 +1064,11 @@ func TestServerPublishErrorInvalidProtocol(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
err = base.InterleavedFrame{
base.InterleavedFrame{
Channel: 0,
Payload: []byte{0x01, 0x02, 0x03, 0x04},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
}
@@ -1097,7 +1104,7 @@ func TestServerPublishRTCPReport(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
track, err := NewTrackH264(96, &TrackConfigH264{
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04},
@@ -1112,7 +1119,7 @@ func TestServerPublishRTCPReport(t *testing.T) {
})
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Announce,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1132,7 +1139,7 @@ func TestServerPublishRTCPReport(t *testing.T) {
require.NoError(t, err)
defer l2.Close()
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1159,7 +1166,7 @@ func TestServerPublishRTCPReport(t *testing.T) {
err = th.Read(res.Header["Transport"])
require.NoError(t, err)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Record,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1272,10 +1279,10 @@ func TestServerPublishTimeout(t *testing.T) {
require.NoError(t, err)
defer s.Close()
nconn, err := net.Dial("tcp", "localhost:8554")
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer nconn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(nconn), bufio.NewWriter(nconn))
defer conn.Close()
br := bufio.NewReader(conn)
track, err := NewTrackH264(96, &TrackConfigH264{
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04},
@@ -1290,7 +1297,7 @@ func TestServerPublishTimeout(t *testing.T) {
})
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Announce,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1321,7 +1328,7 @@ func TestServerPublishTimeout(t *testing.T) {
inTH.InterleavedIDs = &[2]int{0, 1}
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1337,7 +1344,7 @@ func TestServerPublishTimeout(t *testing.T) {
err = th.Read(res.Header["Transport"])
require.NoError(t, err)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Record,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1403,9 +1410,9 @@ func TestServerPublishWithoutTeardown(t *testing.T) {
require.NoError(t, err)
defer s.Close()
nconn, err := net.Dial("tcp", "localhost:8554")
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
bconn := bufio.NewReadWriter(bufio.NewReader(nconn), bufio.NewWriter(nconn))
br := bufio.NewReader(conn)
track, err := NewTrackH264(96, &TrackConfigH264{
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04},
@@ -1420,7 +1427,7 @@ func TestServerPublishWithoutTeardown(t *testing.T) {
})
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Announce,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1451,7 +1458,7 @@ func TestServerPublishWithoutTeardown(t *testing.T) {
inTH.InterleavedIDs = &[2]int{0, 1}
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1467,7 +1474,7 @@ func TestServerPublishWithoutTeardown(t *testing.T) {
err = th.Read(res.Header["Transport"])
require.NoError(t, err)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Record,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1478,7 +1485,7 @@ func TestServerPublishWithoutTeardown(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
nconn.Close()
conn.Close()
<-sessionClosed
<-connClosed
@@ -1527,7 +1534,7 @@ func TestServerPublishUDPChangeConn(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
track, err := NewTrackH264(96, &TrackConfigH264{
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04},
@@ -1542,7 +1549,7 @@ func TestServerPublishUDPChangeConn(t *testing.T) {
})
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Announce,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1567,7 +1574,7 @@ func TestServerPublishUDPChangeConn(t *testing.T) {
ClientPorts: &[2]int{35466, 35467},
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1579,7 +1586,7 @@ func TestServerPublishUDPChangeConn(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Record,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1596,9 +1603,9 @@ func TestServerPublishUDPChangeConn(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.GetParameter,
URL: mustParseURL("rtsp://localhost:8554/teststream/"),
Header: base.Header{

View File

@@ -118,7 +118,7 @@ func TestServerReadSetupPath(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
th := &headers.Transport{
Protocol: headers.TransportProtocolTCP,
@@ -133,7 +133,7 @@ func TestServerReadSetupPath(t *testing.T) {
InterleavedIDs: &[2]int{ca.trackID * 2, (ca.trackID * 2) + 1},
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL(ca.url),
Header: base.Header{
@@ -185,7 +185,7 @@ func TestServerReadSetupErrors(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
th := &headers.Transport{
Protocol: headers.TransportProtocolTCP,
@@ -201,7 +201,7 @@ func TestServerReadSetupErrors(t *testing.T) {
}
if ca == "different paths" {
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -214,7 +214,7 @@ func TestServerReadSetupErrors(t *testing.T) {
th.InterleavedIDs = &[2]int{2, 3}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/test12stream/trackID=1"),
Header: base.Header{
@@ -226,7 +226,7 @@ func TestServerReadSetupErrors(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusBadRequest, res.StatusCode)
} else {
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -239,7 +239,7 @@ func TestServerReadSetupErrors(t *testing.T) {
th.InterleavedIDs = &[2]int{2, 3}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -351,16 +351,17 @@ func TestServerRead(t *testing.T) {
require.NoError(t, err)
defer s.Close()
nconn, err := net.Dial("tcp", listenIP+":8554")
conn, err := net.Dial("tcp", listenIP+":8554")
require.NoError(t, err)
conn := func() net.Conn {
conn = func() net.Conn {
if transport == "tls" {
return tls.Client(nconn, &tls.Config{InsecureSkipVerify: true})
return tls.Client(conn, &tls.Config{InsecureSkipVerify: true})
}
return nconn
return conn
}()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
<-connOpened
@@ -390,7 +391,7 @@ func TestServerRead(t *testing.T) {
inTH.InterleavedIDs = &[2]int{4, 5}
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://" + listenIP + ":8554/teststream/trackID=0"),
Header: base.Header{
@@ -460,7 +461,7 @@ func TestServerRead(t *testing.T) {
<-sessionOpened
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://" + listenIP + ":8554/teststream"),
Header: base.Header{
@@ -492,13 +493,13 @@ func TestServerRead(t *testing.T) {
} else {
var f base.InterleavedFrame
f.Payload = make([]byte, 2048)
err := f.Read(bconn.Reader)
err := f.Read(br)
require.NoError(t, err)
require.Equal(t, 4, f.Channel)
require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, f.Payload)
f.Payload = make([]byte, 2048)
err = f.Read(bconn.Reader)
err = f.Read(br)
require.NoError(t, err)
require.Equal(t, 5, f.Channel)
require.Equal(t, []byte{0x05, 0x06, 0x07, 0x08}, f.Payload)
@@ -521,17 +522,18 @@ func TestServerRead(t *testing.T) {
<-framesReceived
default:
err = base.InterleavedFrame{
base.InterleavedFrame{
Channel: 5,
Payload: []byte{0x01, 0x02, 0x03, 0x04},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
<-framesReceived
}
if transport == "udp" || transport == "multicast" {
// ping with OPTIONS
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Options,
URL: mustParseURL("rtsp://" + listenIP + ":8554/teststream"),
Header: base.Header{
@@ -543,7 +545,7 @@ func TestServerRead(t *testing.T) {
require.Equal(t, base.StatusOK, res.StatusCode)
// ping with GET_PARAMETER
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.GetParameter,
URL: mustParseURL("rtsp://" + listenIP + ":8554/teststream"),
Header: base.Header{
@@ -555,7 +557,7 @@ func TestServerRead(t *testing.T) {
require.Equal(t, base.StatusOK, res.StatusCode)
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Teardown,
URL: mustParseURL("rtsp://" + listenIP + ":8554/teststream"),
Header: base.Header{
@@ -568,7 +570,7 @@ func TestServerRead(t *testing.T) {
<-sessionClosed
nconn.Close()
conn.Close()
<-connClosed
})
}
@@ -602,12 +604,12 @@ func TestServerReadVLCMulticast(t *testing.T) {
require.NoError(t, err)
defer s.Close()
nconn, err := net.Dial("tcp", listenIP+":8554")
conn, err := net.Dial("tcp", listenIP+":8554")
require.NoError(t, err)
bconn := bufio.NewReadWriter(bufio.NewReader(nconn), bufio.NewWriter(nconn))
defer nconn.Close()
br := bufio.NewReader(conn)
defer conn.Close()
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Describe,
URL: mustParseURL("rtsp://" + listenIP + ":8554/teststream?vlcmulticast"),
Header: base.Header{
@@ -659,9 +661,9 @@ func TestServerReadNonStandardFrameSize(t *testing.T) {
require.NoError(t, err)
defer s.Close()
nconn, err := net.Dial("tcp", "localhost:8554")
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
bconn := bufio.NewReadWriter(bufio.NewReader(nconn), bufio.NewWriter(nconn))
br := bufio.NewReader(conn)
inTH := &headers.Transport{
Mode: func() *headers.TransportMode {
@@ -676,7 +678,7 @@ func TestServerReadNonStandardFrameSize(t *testing.T) {
InterleavedIDs: &[2]int{0, 1},
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -687,7 +689,7 @@ func TestServerReadNonStandardFrameSize(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -700,7 +702,7 @@ func TestServerReadNonStandardFrameSize(t *testing.T) {
var f base.InterleavedFrame
f.Payload = make([]byte, 4500)
err = f.Read(bconn.Reader)
err = f.Read(br)
require.NoError(t, err)
require.Equal(t, 0, f.Channel)
require.Equal(t, payload, f.Payload)
@@ -764,9 +766,9 @@ func TestServerReadTCPResponseBeforeFrames(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -788,7 +790,7 @@ func TestServerReadTCPResponseBeforeFrames(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -801,7 +803,7 @@ func TestServerReadTCPResponseBeforeFrames(t *testing.T) {
var fr base.InterleavedFrame
fr.Payload = make([]byte, 2048)
err = fr.Read(bconn.Reader)
err = fr.Read(br)
require.NoError(t, err)
}
@@ -838,9 +840,9 @@ func TestServerReadPlayPlay(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -862,7 +864,7 @@ func TestServerReadPlayPlay(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -873,7 +875,7 @@ func TestServerReadPlayPlay(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -948,9 +950,9 @@ func TestServerReadPlayPausePlay(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -972,7 +974,7 @@ func TestServerReadPlayPausePlay(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -983,7 +985,7 @@ func TestServerReadPlayPausePlay(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Pause,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -994,7 +996,7 @@ func TestServerReadPlayPausePlay(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1065,9 +1067,10 @@ func TestServerReadPlayPausePause(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
var bb bytes.Buffer
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1089,7 +1092,7 @@ func TestServerReadPlayPausePause(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1100,31 +1103,33 @@ func TestServerReadPlayPausePause(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
err = base.Request{
base.Request{
Method: base.Pause,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
"CSeq": base.HeaderValue{"2"},
"Session": res.Header["Session"],
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
res, err = readResIgnoreFrames(bconn.Reader)
res, err = readResIgnoreFrames(br)
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
err = base.Request{
base.Request{
Method: base.Pause,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
"CSeq": base.HeaderValue{"2"},
"Session": res.Header["Session"],
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
res, err = readResIgnoreFrames(bconn.Reader)
res, err = readResIgnoreFrames(br)
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
}
@@ -1176,10 +1181,10 @@ func TestServerReadTimeout(t *testing.T) {
require.NoError(t, err)
defer s.Close()
nconn, err := net.Dial("tcp", "localhost:8554")
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer nconn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(nconn), bufio.NewWriter(nconn))
defer conn.Close()
br := bufio.NewReader(conn)
inTH := &headers.Transport{
Delivery: func() *headers.TransportDelivery {
@@ -1195,7 +1200,7 @@ func TestServerReadTimeout(t *testing.T) {
inTH.Protocol = headers.TransportProtocolUDP
inTH.ClientPorts = &[2]int{35466, 35467}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1206,7 +1211,7 @@ func TestServerReadTimeout(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1276,10 +1281,10 @@ func TestServerReadWithoutTeardown(t *testing.T) {
require.NoError(t, err)
defer s.Close()
nconn, err := net.Dial("tcp", "localhost:8554")
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer nconn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(nconn), bufio.NewWriter(nconn))
defer conn.Close()
br := bufio.NewReader(conn)
inTH := &headers.Transport{
Delivery: func() *headers.TransportDelivery {
@@ -1300,7 +1305,7 @@ func TestServerReadWithoutTeardown(t *testing.T) {
inTH.InterleavedIDs = &[2]int{0, 1}
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1311,7 +1316,7 @@ func TestServerReadWithoutTeardown(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1322,7 +1327,7 @@ func TestServerReadWithoutTeardown(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
nconn.Close()
conn.Close()
<-sessionClosed
<-connClosed
@@ -1371,7 +1376,7 @@ func TestServerReadUDPChangeConn(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
inTH := &headers.Transport{
Delivery: func() *headers.TransportDelivery {
@@ -1386,7 +1391,7 @@ func TestServerReadUDPChangeConn(t *testing.T) {
ClientPorts: &[2]int{35466, 35467},
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1397,7 +1402,7 @@ func TestServerReadUDPChangeConn(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1414,9 +1419,9 @@ func TestServerReadUDPChangeConn(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.GetParameter,
URL: mustParseURL("rtsp://localhost:8554/teststream/"),
Header: base.Header{
@@ -1471,7 +1476,7 @@ func TestServerReadPartialTracks(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
inTH := &headers.Transport{
Delivery: func() *headers.TransportDelivery {
@@ -1486,7 +1491,7 @@ func TestServerReadPartialTracks(t *testing.T) {
InterleavedIDs: &[2]int{4, 5},
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=1"),
Header: base.Header{
@@ -1497,7 +1502,7 @@ func TestServerReadPartialTracks(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1510,7 +1515,7 @@ func TestServerReadPartialTracks(t *testing.T) {
var f base.InterleavedFrame
f.Payload = make([]byte, 2048)
err = f.Read(bconn.Reader)
err = f.Read(br)
require.NoError(t, err)
require.Equal(t, 4, f.Channel)
require.Equal(t, []byte{0x05, 0x06, 0x07, 0x08}, f.Payload)
@@ -1521,7 +1526,7 @@ func TestServerReadAdditionalInfos(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
ssrcs := make([]*uint32, 2)
@@ -1538,7 +1543,7 @@ func TestServerReadAdditionalInfos(t *testing.T) {
InterleavedIDs: &[2]int{0, 1},
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1567,7 +1572,7 @@ func TestServerReadAdditionalInfos(t *testing.T) {
InterleavedIDs: &[2]int{2, 3},
}
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=1"),
Header: base.Header{
@@ -1584,7 +1589,7 @@ func TestServerReadAdditionalInfos(t *testing.T) {
require.NoError(t, err)
ssrcs[1] = th.SSRC
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1757,7 +1762,7 @@ func TestServerReadErrorUDPSamePorts(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
inTH := &headers.Transport{
Delivery: func() *headers.TransportDelivery {
@@ -1772,7 +1777,7 @@ func TestServerReadErrorUDPSamePorts(t *testing.T) {
ClientPorts: &[2]int{35466, 35467},
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1783,7 +1788,7 @@ func TestServerReadErrorUDPSamePorts(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1799,7 +1804,7 @@ func TestServerReadErrorUDPSamePorts(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
inTH := &headers.Transport{
Delivery: func() *headers.TransportDelivery {
@@ -1814,7 +1819,7 @@ func TestServerReadErrorUDPSamePorts(t *testing.T) {
ClientPorts: &[2]int{35466, 35467},
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{

View File

@@ -2,6 +2,7 @@ package gortsplib
import (
"bufio"
"bytes"
"crypto/tls"
"fmt"
"net"
@@ -19,14 +20,18 @@ import (
"github.com/aler9/gortsplib/pkg/headers"
)
func writeReqReadRes(bconn *bufio.ReadWriter, req base.Request) (*base.Response, error) {
err := req.Write(bconn.Writer)
func writeReqReadRes(conn net.Conn,
br *bufio.Reader,
req base.Request) (*base.Response, error) {
var bb bytes.Buffer
req.Write(&bb)
_, err := conn.Write(bb.Bytes())
if err != nil {
return nil, err
}
var res base.Response
err = res.Read(bconn.Reader)
err = res.Read(br)
return &res, err
}
@@ -603,9 +608,9 @@ func TestServerCSeq(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Options,
URL: mustParseURL("rtsp://localhost:8554/"),
Header: base.Header{
@@ -637,9 +642,9 @@ func TestServerErrorCSeqMissing(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Options,
URL: mustParseURL("rtsp://localhost:8554/"),
Header: base.Header{},
@@ -669,9 +674,9 @@ func TestServerErrorInvalidMethod(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: "INVALID",
URL: mustParseURL("rtsp://localhost:8554/"),
Header: base.Header{
@@ -720,9 +725,9 @@ func TestServerErrorTCPTwoConnOneSession(t *testing.T) {
conn1, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn1.Close()
bconn1 := bufio.NewReadWriter(bufio.NewReader(conn1), bufio.NewWriter(conn1))
br1 := bufio.NewReader(conn1)
res, err := writeReqReadRes(bconn1, base.Request{
res, err := writeReqReadRes(conn1, br1, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -744,7 +749,7 @@ func TestServerErrorTCPTwoConnOneSession(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn1, base.Request{
res, err = writeReqReadRes(conn1, br1, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -758,9 +763,9 @@ func TestServerErrorTCPTwoConnOneSession(t *testing.T) {
conn2, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn2.Close()
bconn2 := bufio.NewReadWriter(bufio.NewReader(conn2), bufio.NewWriter(conn2))
br2 := bufio.NewReader(conn2)
res, err = writeReqReadRes(bconn2, base.Request{
res, err = writeReqReadRes(conn2, br2, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -820,9 +825,9 @@ func TestServerErrorTCPOneConnTwoSessions(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -844,7 +849,7 @@ func TestServerErrorTCPOneConnTwoSessions(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -855,7 +860,7 @@ func TestServerErrorTCPOneConnTwoSessions(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -906,9 +911,9 @@ func TestServerGetSetParameter(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Options,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -918,7 +923,7 @@ func TestServerGetSetParameter(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.SetParameter,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -929,7 +934,7 @@ func TestServerGetSetParameter(t *testing.T) {
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
res, err = writeReqReadRes(bconn, base.Request{
res, err = writeReqReadRes(conn, br, base.Request{
Method: base.GetParameter,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -978,9 +983,9 @@ func TestServerErrorInvalidSession(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: method,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1021,9 +1026,9 @@ func TestServerSessionClose(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
var bb bytes.Buffer
err = base.Request{
base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1041,7 +1046,8 @@ func TestServerSessionClose(t *testing.T) {
InterleavedIDs: &[2]int{0, 1},
}.Write(),
},
}.Write(bconn.Writer)
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
<-sessionClosed
@@ -1077,9 +1083,9 @@ func TestServerSessionAutoClose(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1158,7 +1164,7 @@ func TestServerErrorInvalidPath(t *testing.T) {
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer conn.Close()
bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
br := bufio.NewReader(conn)
sxID := ""
@@ -1176,7 +1182,7 @@ func TestServerErrorInvalidPath(t *testing.T) {
})
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Announce,
URL: mustParseURL("rtsp://localhost:8554/teststream"),
Header: base.Header{
@@ -1191,7 +1197,7 @@ func TestServerErrorInvalidPath(t *testing.T) {
}
if method == base.Play || method == base.Record || method == base.Pause {
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Setup,
URL: mustParseURL("rtsp://localhost:8554/teststream/trackID=0"),
Header: base.Header{
@@ -1221,7 +1227,7 @@ func TestServerErrorInvalidPath(t *testing.T) {
}
if method == base.Pause {
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: base.Play,
URL: mustParseURL("rtsp://localhost:8554/teststream/"),
Header: base.Header{
@@ -1233,7 +1239,7 @@ func TestServerErrorInvalidPath(t *testing.T) {
require.Equal(t, base.StatusOK, res.StatusCode)
}
res, err := writeReqReadRes(bconn, base.Request{
res, err := writeReqReadRes(conn, br, base.Request{
Method: method,
URL: mustParseURL("rtsp://localhost:8554"),
Header: base.Header{

View File

@@ -2,12 +2,12 @@ package gortsplib
import (
"bufio"
"bytes"
"context"
"crypto/tls"
"net"
"net/url"
"strings"
"sync"
"time"
"github.com/aler9/gortsplib/pkg/base"
@@ -29,21 +29,20 @@ type readReq struct {
// ServerConn is a server-side RTSP connection.
type ServerConn struct {
s *Server
nconn net.Conn
s *Server
conn net.Conn
ctx context.Context
ctxCancel func()
remoteAddr *net.TCPAddr // to improve speed
br *bufio.Reader
bw *bufio.Writer
sessions map[string]*ServerSession
tcpFrameEnabled bool
tcpSession *ServerSession
tcpFrameTimeout bool
tcpReadBuffer *multibuffer.MultiBuffer
tcpProcessFunc func(int, bool, []byte)
tcpWriteMutex sync.Mutex
ctx context.Context
ctxCancel func()
remoteAddr *net.TCPAddr
br *bufio.Reader
sessions map[string]*ServerSession
tcpFrameEnabled bool
tcpSession *ServerSession
tcpFrameTimeout bool
tcpReadBuffer *multibuffer.MultiBuffer
tcpProcessFunc func(int, bool, []byte)
tcpWriterRunning bool
// in
sessionRemove chan *ServerSession
@@ -57,12 +56,19 @@ func newServerConn(
nconn net.Conn) *ServerConn {
ctx, ctxCancel := context.WithCancel(s.ctx)
conn := func() net.Conn {
if s.TLSConfig != nil {
return tls.Server(nconn, s.TLSConfig)
}
return nconn
}()
sc := &ServerConn{
s: s,
nconn: nconn,
conn: conn,
ctx: ctx,
ctxCancel: ctxCancel,
remoteAddr: nconn.RemoteAddr().(*net.TCPAddr),
remoteAddr: conn.RemoteAddr().(*net.TCPAddr),
sessionRemove: make(chan *ServerSession),
done: make(chan struct{}),
}
@@ -81,7 +87,7 @@ func (sc *ServerConn) Close() error {
// NetConn returns the underlying net.Conn.
func (sc *ServerConn) NetConn() net.Conn {
return sc.nconn
return sc.conn
}
func (sc *ServerConn) ip() net.IP {
@@ -102,15 +108,7 @@ func (sc *ServerConn) run() {
})
}
conn := func() net.Conn {
if sc.s.TLSConfig != nil {
return tls.Server(sc.nconn, sc.s.TLSConfig)
}
return sc.nconn
}()
sc.br = bufio.NewReaderSize(conn, serverReadBufferSize)
sc.bw = bufio.NewWriterSize(conn, serverWriteBufferSize)
sc.br = bufio.NewReaderSize(sc.conn, serverReadBufferSize)
sc.sessions = make(map[string]*ServerSession)
readRequest := make(chan readReq)
@@ -125,7 +123,7 @@ func (sc *ServerConn) run() {
for {
if sc.tcpFrameEnabled {
if sc.tcpFrameTimeout {
sc.nconn.SetReadDeadline(time.Now().Add(sc.s.ReadTimeout))
sc.conn.SetReadDeadline(time.Now().Add(sc.s.ReadTimeout))
}
frame.Payload = sc.tcpReadBuffer.Next()
@@ -215,7 +213,7 @@ func (sc *ServerConn) run() {
sc.ctxCancel()
sc.nconn.Close()
sc.conn.Close()
<-readDone
for _, ss := range sc.sessions {
@@ -458,8 +456,6 @@ func (sc *ServerConn) handleRequestOuter(req *base.Request) error {
h.OnRequest(sc, req)
}
sc.tcpWriteMutex.Lock()
res, err := sc.handleRequest(req)
if res.Header == nil {
@@ -478,10 +474,20 @@ func (sc *ServerConn) handleRequestOuter(req *base.Request) error {
h.OnResponse(sc, res)
}
sc.nconn.SetWriteDeadline(time.Now().Add(sc.s.WriteTimeout))
res.Write(sc.bw)
var buf bytes.Buffer
res.Write(&buf)
sc.tcpWriteMutex.Unlock()
sc.conn.SetWriteDeadline(time.Now().Add(sc.s.WriteTimeout))
sc.conn.Write(buf.Bytes())
// start writer after sending the response
if sc.tcpFrameEnabled && !sc.tcpWriterRunning {
sc.tcpWriterRunning = true
select {
case sc.tcpSession.startWriter <- struct{}{}:
case <-sc.tcpSession.ctx.Done():
}
}
return err
}

View File

@@ -1,6 +1,7 @@
package gortsplib
import (
"bytes"
"context"
"fmt"
"net"
@@ -183,8 +184,9 @@ type ServerSession struct {
writerDone chan struct{}
// in
request chan sessionRequestReq
connRemove chan *ServerConn
request chan sessionRequestReq
connRemove chan *ServerConn
startWriter chan struct{}
}
func newServerSession(
@@ -206,6 +208,7 @@ func newServerSession(
udpReceiverReportTimer: emptyTimer(),
request: make(chan sessionRequestReq),
connRemove: make(chan *ServerConn),
startWriter: make(chan struct{}),
}
s.wg.Add(1)
@@ -314,6 +317,15 @@ func (ss *ServerSession) run() {
}
}
case <-ss.startWriter:
if !ss.writerRunning && (ss.state == ServerSessionStatePublish ||
ss.state == ServerSessionStateRead) &&
*ss.setuppedTransport == TransportTCP {
ss.writerRunning = true
ss.writerDone = make(chan struct{})
go ss.runWriter()
}
case <-ss.udpCheckStreamTimer.C:
now := time.Now()
@@ -876,9 +888,8 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
ss.tcpConn.tcpProcessFunc = sc.tcpProcessPlay
ss.writeBuffer = ringbuffer.New(uint64(ss.s.ReadBufferCount))
ss.writerRunning = true
ss.writerDone = make(chan struct{})
go ss.runWriter()
// run writer after sending the response
ss.tcpConn.tcpWriterRunning = false
}
// add RTP-Info
@@ -1010,9 +1021,8 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
// that are much smaller than RTP packets and are sent at a fixed interval.
// decrease RAM consumption by allocating less buffers.
ss.writeBuffer = ringbuffer.New(uint64(8))
ss.writerRunning = true
ss.writerDone = make(chan struct{})
go ss.runWriter()
// run writer after sending the response
ss.tcpConn.tcpWriterRunning = false
}
return res, err
@@ -1096,7 +1106,7 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
ss.tcpConn.tcpSession = nil
ss.tcpConn.tcpFrameEnabled = false
ss.tcpConn.tcpReadBuffer = nil
ss.tcpConn.nconn.SetReadDeadline(time.Time{})
ss.tcpConn.conn.SetReadDeadline(time.Time{})
ss.tcpConn = nil
}
}
@@ -1158,23 +1168,23 @@ func (ss *ServerSession) runWriter() {
}
}
} else {
var buf bytes.Buffer
writeFunc = func(trackID int, isRTP bool, payload []byte) {
if isRTP {
f := ss.setuppedTracks[trackID].tcpRTPFrame
f.Payload = payload
f.Write(&buf)
ss.tcpConn.tcpWriteMutex.Lock()
ss.tcpConn.nconn.SetWriteDeadline(time.Now().Add(ss.s.WriteTimeout))
f.Write(ss.tcpConn.bw)
ss.tcpConn.tcpWriteMutex.Unlock()
ss.tcpConn.conn.SetWriteDeadline(time.Now().Add(ss.s.WriteTimeout))
ss.tcpConn.conn.Write(buf.Bytes())
} else {
f := ss.setuppedTracks[trackID].tcpRTCPFrame
f.Payload = payload
f.Write(&buf)
ss.tcpConn.tcpWriteMutex.Lock()
ss.tcpConn.nconn.SetWriteDeadline(time.Now().Add(ss.s.WriteTimeout))
f.Write(ss.tcpConn.bw)
ss.tcpConn.tcpWriteMutex.Unlock()
ss.tcpConn.conn.SetWriteDeadline(time.Now().Add(ss.s.WriteTimeout))
ss.tcpConn.conn.Write(buf.Bytes())
}
}
}