From 948e9a67e1f8cdd72a4f3e353ca27a02ef4ea33e Mon Sep 17 00:00:00 2001 From: Saxon Date: Wed, 17 Apr 2019 09:05:34 +0930 Subject: [PATCH] protocol/rtsp/rtsp.go: simplified RTSP method functions wrap a single writeRequest func --- protocol/rtsp/rtsp.go | 221 +++++++++++++++++------------------------- 1 file changed, 90 insertions(+), 131 deletions(-) diff --git a/protocol/rtsp/rtsp.go b/protocol/rtsp/rtsp.go index 596fcec3..37b0e6e3 100644 --- a/protocol/rtsp/rtsp.go +++ b/protocol/rtsp/rtsp.go @@ -23,18 +23,98 @@ const ( setup = "SETUP" ) -type Request struct { - Method string - URL *url.URL - Proto string - ProtoMajor int - ProtoMinor int - Header http.Header - ContentLength int - Body io.ReadCloser +type Session struct { + cSeq int + conn net.Conn + session string } -func (r Request) String() string { +func NewSession() *Session { + return &Session{} +} + +func (s *Session) Describe(urlStr string) (*Response, error) { + return s.writeRequest(describe, urlStr, func(req *request) { req.Header.Add("Accept", "application/sdp") }, nil) +} + +func (s *Session) Options(urlStr string) (*Response, error) { + return s.writeRequest(options, urlStr, nil, nil) +} + +func (s *Session) Setup(urlStr, transport string) (*Response, error) { + return s.writeRequest( + setup, + urlStr, + func(req *request) { + req.Header.Add("Transport", transport) + }, + func(resp *Response) { + s.session = resp.Header.Get("Session") + }, + ) +} + +func (s *Session) Play(urlStr, sessionId string) (*Response, error) { + return s.writeRequest(play, urlStr, func(req *request) { req.Header.Add("Session", s.session) }, nil) +} +func (s *Session) writeRequest(method, url string, headerOp func(*request), respOp func(*Response)) (*Response, error) { + req, err := newRequest(describe, url, s.nextCSeq(), nil) + if err != nil { + panic(err) + } + + if headerOp != nil { + headerOp(req) + } + + if s.conn == nil { + s.conn, err = net.Dial("tcp", req.URL.Host) + if err != nil { + return nil, err + } + } + + _, err = io.WriteString(s.conn, req.String()) + if err != nil { + return nil, err + } + res, err := ReadResponse(s.conn) + if err != nil { + return nil, err + } + + if respOp != nil { + respOp(res) + } + return res, nil +} + +func (s *Session) nextCSeq() string { + s.cSeq++ + return strconv.Itoa(s.cSeq) +} + +type request http.Request + +func newRequest(method, urlStr, cSeq string, body io.ReadCloser) (*request, error) { + u, err := url.Parse(urlStr) + if err != nil { + return nil, err + } + + req := &http.Request{ + Method: method, + URL: u, + Proto: "RTSP", + ProtoMajor: 1, + ProtoMinor: 0, + Header: map[string][]string{"CSeq": []string{cSeq}}, + Body: body, + } + return (*request)(req), nil +} + +func (r *request) String() string { s := fmt.Sprintf("%s %s %s/%d.%d\r\n", r.Method, r.URL, r.Proto, r.ProtoMajor, r.ProtoMinor) for k, v := range r.Header { for _, v := range v { @@ -49,127 +129,6 @@ func (r Request) String() string { return s } -func NewRequest(method, urlStr, cSeq string, body io.ReadCloser) (*Request, error) { - u, err := url.Parse(urlStr) - if err != nil { - return nil, err - } - - req := &Request{ - Method: method, - URL: u, - Proto: "RTSP", - ProtoMajor: 1, - ProtoMinor: 0, - Header: map[string][]string{"CSeq": []string{cSeq}}, - Body: body, - } - return req, nil -} - -type Session struct { - cSeq int - conn net.Conn - session string -} - -func NewSession() *Session { - return &Session{} -} - -func (s *Session) nextCSeq() string { - s.cSeq++ - return strconv.Itoa(s.cSeq) -} - -func (s *Session) Describe(urlStr string) (*Response, error) { - req, err := NewRequest(describe, urlStr, s.nextCSeq(), nil) - if err != nil { - panic(err) - } - - req.Header.Add("Accept", "application/sdp") - - if s.conn == nil { - s.conn, err = net.Dial("tcp", req.URL.Host) - if err != nil { - return nil, err - } - } - - _, err = io.WriteString(s.conn, req.String()) - if err != nil { - return nil, err - } - return ReadResponse(s.conn) -} - -func (s *Session) Options(urlStr string) (*Response, error) { - req, err := NewRequest(options, urlStr, s.nextCSeq(), nil) - if err != nil { - panic(err) - } - - if s.conn == nil { - s.conn, err = net.Dial("tcp", req.URL.Host) - if err != nil { - return nil, err - } - } - - _, err = io.WriteString(s.conn, req.String()) - if err != nil { - return nil, err - } - return ReadResponse(s.conn) -} - -func (s *Session) Setup(urlStr, transport string) (*Response, error) { - req, err := NewRequest(setup, urlStr, s.nextCSeq(), nil) - if err != nil { - panic(err) - } - - req.Header.Add("Transport", transport) - - if s.conn == nil { - s.conn, err = net.Dial("tcp", req.URL.Host) - if err != nil { - return nil, err - } - } - - _, err = io.WriteString(s.conn, req.String()) - if err != nil { - return nil, err - } - resp, err := ReadResponse(s.conn) - s.session = resp.Header.Get("Session") - return resp, err -} - -func (s *Session) Play(urlStr, sessionId string) (*Response, error) { - req, err := NewRequest(play, urlStr+"/", s.nextCSeq(), nil) - if err != nil { - panic(err) - } - - req.Header.Add("Session", sessionId) - - if s.conn == nil { - s.conn, err = net.Dial("tcp", req.URL.Host) - if err != nil { - return nil, err - } - } - - _, err = io.WriteString(s.conn, req.String()) - if err != nil { - return nil, err - } - return ReadResponse(s.conn) -} - type closer struct { *bufio.Reader r io.Reader