Browse Source

RTMP source: apply read and write timeouts to connection initialization

pull/372/head
aler9 5 years ago
parent
commit
faf8d24dff
  1. 1
      internal/path/path.go
  2. 32
      internal/rtmp/client.go
  3. 78
      internal/sourcertmp/source.go
  4. 2
      internal/sourcertsp/source.go

1
internal/path/path.go

@ -420,6 +420,7 @@ func (pa *Path) startExternalSource() { @@ -420,6 +420,7 @@ func (pa *Path) startExternalSource() {
pa.source = sourcertmp.New(
pa.conf.Source,
pa.readTimeout,
pa.writeTimeout,
&pa.sourceWg,
pa.stats,
pa)

32
internal/rtmp/client.go

@ -1,18 +1,44 @@ @@ -1,18 +1,44 @@
package rtmp
import (
"bufio"
"context"
"net"
"net/url"
"github.com/notedit/rtmp/format/rtmp"
)
// Dial connects to a server in reading mode.
func Dial(address string) (*Conn, error) {
rconn, nconn, err := rtmp.NewClient().Dial(address, rtmp.PrepareReading)
// DialContext connects to a server in reading mode.
func DialContext(ctx context.Context, address string) (*Conn, error) {
// https://github.com/aler9/rtmp/blob/master/format/rtmp/client.go#L74
u, err := url.Parse(address)
if err != nil {
return nil, err
}
host := rtmp.UrlGetHost(u)
var d net.Dialer
nconn, err := d.DialContext(ctx, "tcp", host)
if err != nil {
return nil, err
}
rw := &bufio.ReadWriter{
Reader: bufio.NewReaderSize(nconn, 4096),
Writer: bufio.NewWriterSize(nconn, 4096),
}
rconn := rtmp.NewConn(rw)
rconn.URL = u
return &Conn{
rconn: rconn,
nconn: nconn,
}, nil
}
// ClientHandshake performs the handshake of a client-side connection.
func (c *Conn) ClientHandshake() error {
return c.rconn.Prepare(rtmp.StageGotPublishOrPlayCommand, rtmp.PrepareReading)
}

78
internal/sourcertmp/source.go

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
package sourcertmp
import (
"context"
"fmt"
"sync"
"sync/atomic"
@ -34,6 +35,7 @@ type Parent interface { @@ -34,6 +35,7 @@ type Parent interface {
type Source struct {
ur string
readTimeout time.Duration
writeTimeout time.Duration
wg *sync.WaitGroup
stats *stats.Stats
parent Parent
@ -45,12 +47,14 @@ type Source struct { @@ -45,12 +47,14 @@ type Source struct {
// New allocates a Source.
func New(ur string,
readTimeout time.Duration,
writeTimeout time.Duration,
wg *sync.WaitGroup,
stats *stats.Stats,
parent Parent) *Source {
s := &Source{
ur: ur,
readTimeout: readTimeout,
writeTimeout: writeTimeout,
wg: wg,
stats: stats,
parent: parent,
@ -106,47 +110,37 @@ func (s *Source) run() { @@ -106,47 +110,37 @@ func (s *Source) run() {
}
func (s *Source) runInner() bool {
s.log(logger.Info, "connecting")
ctx, cancel := context.WithCancel(context.Background())
var conn *rtmp.Conn
var err error
dialDone := make(chan struct{}, 1)
done := make(chan error)
go func() {
defer close(dialDone)
conn, err = rtmp.Dial(s.ur)
}()
done <- func() error {
s.log(logger.Debug, "connecting")
select {
case <-dialDone:
case <-s.terminate:
return false
}
ctx2, cancel2 := context.WithTimeout(ctx, s.readTimeout)
defer cancel2()
conn, err := rtmp.DialContext(ctx2, s.ur)
if err != nil {
s.log(logger.Info, "ERR: %s", err)
return true
return err
}
var videoTrack *gortsplib.Track
var audioTrack *gortsplib.Track
metadataDone := make(chan struct{})
readDone := make(chan error)
go func() {
defer close(metadataDone)
readDone <- func() error {
conn.NetConn().SetReadDeadline(time.Now().Add(s.readTimeout))
videoTrack, audioTrack, err = conn.ReadMetadata()
}()
select {
case <-metadataDone:
case <-s.terminate:
conn.NetConn().Close()
<-metadataDone
return false
conn.NetConn().SetWriteDeadline(time.Now().Add(s.writeTimeout))
err = conn.ClientHandshake()
if err != nil {
return err
}
conn.NetConn().SetWriteDeadline(time.Time{})
conn.NetConn().SetReadDeadline(time.Now().Add(s.readTimeout))
videoTrack, audioTrack, err := conn.ReadMetadata()
if err != nil {
s.log(logger.Info, "ERR: %s", err)
return true
return err
}
var tracks gortsplib.Tracks
@ -185,9 +179,6 @@ func (s *Source) runInner() bool { @@ -185,9 +179,6 @@ func (s *Source) runInner() bool {
<-res
}()
readerDone := make(chan error)
go func() {
readerDone <- func() error {
rtcpSenders := rtcpsenderset.New(tracks, res.SP.OnFrame)
defer rtcpSenders.Close()
@ -257,14 +248,27 @@ func (s *Source) runInner() bool { @@ -257,14 +248,27 @@ func (s *Source) runInner() bool {
}()
select {
case <-s.terminate:
case err := <-readDone:
conn.NetConn().Close()
<-readerDone
return false
return err
case err := <-readerDone:
s.log(logger.Info, "ERR: %s", err)
case <-ctx.Done():
conn.NetConn().Close()
<-readDone
return nil
}
}()
}()
select {
case err := <-done:
cancel()
s.log(logger.Info, "ERR: %s", err)
return true
case <-s.terminate:
cancel()
<-done
return false
}
}

2
internal/sourcertsp/source.go

@ -121,7 +121,7 @@ func (s *Source) run() { @@ -121,7 +121,7 @@ func (s *Source) run() {
}
func (s *Source) runInner() bool {
s.log(logger.Info, "connecting")
s.log(logger.Debug, "connecting")
var conn *gortsplib.ClientConn
var err error

Loading…
Cancel
Save