protocol/rtsp/rtsp.go: simplified RTSP method functions wrap a single writeRequest func

This commit is contained in:
Saxon 2019-04-17 09:05:34 +09:30
parent 6f4738a04c
commit 948e9a67e1
1 changed files with 90 additions and 131 deletions

View File

@ -23,18 +23,98 @@ const (
setup = "SETUP" setup = "SETUP"
) )
type Request struct { type Session struct {
Method string cSeq int
URL *url.URL conn net.Conn
Proto string session string
ProtoMajor int
ProtoMinor int
Header http.Header
ContentLength int
Body io.ReadCloser
} }
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) 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 k, v := range r.Header {
for _, v := range v { for _, v := range v {
@ -49,127 +129,6 @@ func (r Request) String() string {
return s 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 { type closer struct {
*bufio.Reader *bufio.Reader
r io.Reader r io.Reader