mirror of
https://github.com/aler9/gortsplib
synced 2025-10-05 15:16:51 +08:00
new server structure
This commit is contained in:
@@ -16,18 +16,10 @@ const (
|
||||
serverWriteBufferSize = 4096
|
||||
)
|
||||
|
||||
// ServerConnHandler is the interface that must be implemented to use a ServerConn.
|
||||
type ServerConnHandler interface {
|
||||
OnClose(err error)
|
||||
OnRequest(req *base.Request) (*base.Response, error)
|
||||
OnFrame(rackID int, streamType StreamType, content []byte)
|
||||
}
|
||||
|
||||
// ServerConn is a server-side RTSP connection.
|
||||
type ServerConn struct {
|
||||
s *Server
|
||||
nconn net.Conn
|
||||
connHandler ServerConnHandler
|
||||
br *bufio.Reader
|
||||
bw *bufio.Writer
|
||||
mutex sync.Mutex
|
||||
@@ -35,7 +27,7 @@ type ServerConn struct {
|
||||
readTimeout bool
|
||||
}
|
||||
|
||||
// Close closes all the ServerConn resources.
|
||||
// Close closes all the connection resources.
|
||||
func (sc *ServerConn) Close() error {
|
||||
return sc.nconn.Close()
|
||||
}
|
||||
@@ -55,8 +47,36 @@ func (sc *ServerConn) EnableReadTimeout(v bool) {
|
||||
sc.readTimeout = v
|
||||
}
|
||||
|
||||
func (sc *ServerConn) run() {
|
||||
defer sc.s.wg.Done()
|
||||
func (sc *ServerConn) backgroundRead(
|
||||
onRequest func(req *base.Request) (*base.Response, error),
|
||||
onFrame func(trackID int, streamType StreamType, content []byte),
|
||||
done chan error,
|
||||
) {
|
||||
handleRequest := func(req *base.Request) error {
|
||||
sc.mutex.Lock()
|
||||
defer sc.mutex.Unlock()
|
||||
|
||||
// check cseq
|
||||
cseq, ok := req.Header["CSeq"]
|
||||
if !ok || len(cseq) != 1 {
|
||||
sc.nconn.SetWriteDeadline(time.Now().Add(sc.s.conf.WriteTimeout))
|
||||
base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
Header: base.Header{},
|
||||
}.Write(sc.bw)
|
||||
return fmt.Errorf("cseq is missing")
|
||||
}
|
||||
|
||||
res, err := onRequest(req)
|
||||
|
||||
// add cseq to response
|
||||
res.Header["CSeq"] = cseq
|
||||
|
||||
sc.nconn.SetWriteDeadline(time.Now().Add(sc.s.conf.WriteTimeout))
|
||||
res.Write(sc.bw)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
var req base.Request
|
||||
var frame base.InterleavedFrame
|
||||
@@ -81,10 +101,10 @@ outer:
|
||||
|
||||
switch what.(type) {
|
||||
case *base.InterleavedFrame:
|
||||
sc.connHandler.OnFrame(frame.TrackID, frame.StreamType, frame.Content)
|
||||
onFrame(frame.TrackID, frame.StreamType, frame.Content)
|
||||
|
||||
case *base.Request:
|
||||
err := sc.handleRequest(&req)
|
||||
err := handleRequest(&req)
|
||||
if err != nil {
|
||||
errRet = err
|
||||
break outer
|
||||
@@ -98,7 +118,7 @@ outer:
|
||||
break outer
|
||||
}
|
||||
|
||||
err = sc.handleRequest(&req)
|
||||
err = handleRequest(&req)
|
||||
if err != nil {
|
||||
errRet = err
|
||||
break outer
|
||||
@@ -107,33 +127,21 @@ outer:
|
||||
}
|
||||
|
||||
sc.nconn.Close()
|
||||
sc.connHandler.OnClose(errRet)
|
||||
done <- errRet
|
||||
}
|
||||
|
||||
func (sc *ServerConn) handleRequest(req *base.Request) error {
|
||||
sc.mutex.Lock()
|
||||
defer sc.mutex.Unlock()
|
||||
// Read starts reading requests and frames from the connection.
|
||||
// it returns a channel that is written when the reading stops.
|
||||
func (sc *ServerConn) Read(
|
||||
onRequest func(req *base.Request) (*base.Response, error),
|
||||
onFrame func(trackID int, streamType StreamType, content []byte),
|
||||
) chan error {
|
||||
// channel is buffered, since listening to it is not mandatory
|
||||
done := make(chan error, 1)
|
||||
|
||||
// check cseq
|
||||
cseq, ok := req.Header["CSeq"]
|
||||
if !ok || len(cseq) != 1 {
|
||||
sc.nconn.SetWriteDeadline(time.Now().Add(sc.s.conf.WriteTimeout))
|
||||
base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
Header: base.Header{},
|
||||
}.Write(sc.bw)
|
||||
return fmt.Errorf("cseq is missing")
|
||||
}
|
||||
go sc.backgroundRead(onRequest, onFrame, done)
|
||||
|
||||
res, err := sc.connHandler.OnRequest(req)
|
||||
|
||||
// add cseq to response
|
||||
res.Header["CSeq"] = cseq
|
||||
|
||||
sc.nconn.SetWriteDeadline(time.Now().Add(sc.s.conf.WriteTimeout))
|
||||
res.Write(sc.bw)
|
||||
|
||||
return err
|
||||
return done
|
||||
}
|
||||
|
||||
// WriteFrame writes a frame.
|
||||
|
Reference in New Issue
Block a user