// Package conn contains a RTSP connection implementation. package conn import ( "bufio" "io" "github.com/bluenviron/gortsplib/v5/pkg/base" ) // Conn is a RTSP connection. type Conn struct { br *bufio.Reader w io.Writer // reuse interleaved frames. they should never be passed to secondary routines fr base.InterleavedFrame } // NewConn allocates a Conn. func NewConn(br *bufio.Reader, w io.Writer) *Conn { return &Conn{ br: br, w: w, } } // Read reads a Request, a Response or an Interleaved frame. func (c *Conn) Read() (interface{}, error) { for { byts, err := c.br.Peek(2) if err != nil { return nil, err } if byts[0] == base.InterleavedFrameMagicByte { return c.ReadInterleavedFrame() } if byts[0] == 'R' && byts[1] == 'T' { return c.ReadResponse() } if (byts[0] == 'A' && byts[1] == 'N') || (byts[0] == 'D' && byts[1] == 'E') || (byts[0] == 'G' && byts[1] == 'E') || (byts[0] == 'O' && byts[1] == 'P') || (byts[0] == 'P' && byts[1] == 'A') || (byts[0] == 'P' && byts[1] == 'L') || (byts[0] == 'R' && byts[1] == 'E') || (byts[0] == 'S' && byts[1] == 'E') || (byts[0] == 'T' && byts[1] == 'E') { return c.ReadRequest() } if _, err = c.br.Discard(1); err != nil { return nil, err } } } // ReadRequest reads a Request. func (c *Conn) ReadRequest() (*base.Request, error) { var req base.Request err := req.Unmarshal(c.br) return &req, err } // ReadResponse reads a Response. func (c *Conn) ReadResponse() (*base.Response, error) { var res base.Response err := res.Unmarshal(c.br) return &res, err } // ReadInterleavedFrame reads a InterleavedFrame. func (c *Conn) ReadInterleavedFrame() (*base.InterleavedFrame, error) { err := c.fr.Unmarshal(c.br) return &c.fr, err } // WriteRequest writes a request. func (c *Conn) WriteRequest(req *base.Request) error { buf, _ := req.Marshal() _, err := c.w.Write(buf) return err } // WriteResponse writes a response. func (c *Conn) WriteResponse(res *base.Response) error { buf, _ := res.Marshal() _, err := c.w.Write(buf) return err } // WriteInterleavedFrame writes an interleaved frame. func (c *Conn) WriteInterleavedFrame(fr *base.InterleavedFrame, buf []byte) error { n, _ := fr.MarshalTo(buf) _, err := c.w.Write(buf[:n]) return err }