/* NAME client.go DESCRIPTION client.go provides a Client type providing functionality to send RTSP requests of methods DESCRIBE, OPTIONS, SETUP and PLAY to an RTSP server. AUTHORS Saxon A. Nelson-Milton LICENSE This is Copyright (C) 2019 the Australian Ocean Lab (AusOcean). It is free software: you can redistribute it and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License in gpl.txt. If not, see http://www.gnu.org/licenses. */ package rtsp import ( "bufio" "net" "net/url" "strconv" ) // Client describes an RTSP Client. type Client struct { cSeq int addr string url *url.URL conn net.Conn sessionID string } // NewClient returns a pointer to a new Client. The URL u will be parsed and // a connection to the RTSP server will be made. func NewClient(addr string) (*Client, error) { c := &Client{addr: addr} var err error c.url, err = url.Parse(addr) if err != nil { return nil, err } c.conn, err = net.Dial("tcp", c.url.Host) if err != nil { return nil, err } return c, nil } // Describe forms and sends an RTSP request of method DESCRIBE to the RTSP server. func (c *Client) Describe() (*Response, error) { req, err := NewRequest("DESCRIBE", c.nextCSeq(), c.url, nil) if err != nil { return nil, err } req.Header.Add("Accept", "application/sdp") return c.Do(req) } // Options forms and sends an RTSP request of method OPTIONS to the RTSP server. func (c *Client) Options() (*Response, error) { req, err := NewRequest("OPTIONS", c.nextCSeq(), c.url, nil) if err != nil { return nil, err } return c.Do(req) } // Setup forms and sends an RTSP request of method SETUP to the RTSP server. func (c *Client) Setup(track, transport string) (*Response, error) { url, err := url.Parse(c.addr + "/" + track) if err != nil { return nil, err } req, err := NewRequest("SETUP", c.nextCSeq(), url, nil) if err != nil { return nil, err } req.Header.Add("Transport", transport) resp, err := c.Do(req) if err != nil { return nil, err } c.sessionID = resp.Header.Get("Session") return resp, err } // Play forms and sends an RTSP request of method PLAY to the RTSP server func (c *Client) Play() (*Response, error) { req, err := NewRequest("PLAY", c.nextCSeq(), c.url, nil) if err != nil { return nil, err } req.Header.Add("Session", c.sessionID) return c.Do(req) } // Do sends the given RTSP request r and reads any responses, return the response // and any errors. func (c *Client) Do(req *Request) (*Response, error) { err := req.Write(c.conn) if err != nil { return nil, err } res, err := ReadResponse(bufio.NewReader(c.conn)) if err != nil { return nil, err } return res, nil } func (c *Client) nextCSeq() string { c.cSeq++ return strconv.Itoa(c.cSeq) }