mirror of
https://github.com/aler9/gortsplib
synced 2025-10-05 15:16:51 +08:00
141 lines
2.7 KiB
Go
141 lines
2.7 KiB
Go
// Package base contains the base elements of the RTSP protocol.
|
|
package base
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"strconv"
|
|
)
|
|
|
|
const (
|
|
rtspProtocol10 = "RTSP/1.0"
|
|
requestMaxLethodLength = 128
|
|
requestMaxPathLength = 1024
|
|
requestMaxProtocolLength = 128
|
|
)
|
|
|
|
// Method is the method of a RTSP request.
|
|
type Method string
|
|
|
|
// standard methods
|
|
const (
|
|
Announce Method = "ANNOUNCE"
|
|
Describe Method = "DESCRIBE"
|
|
GetParameter Method = "GET_PARAMETER"
|
|
Options Method = "OPTIONS"
|
|
Pause Method = "PAUSE"
|
|
Play Method = "PLAY"
|
|
Record Method = "RECORD"
|
|
Setup Method = "SETUP"
|
|
SetParameter Method = "SET_PARAMETER"
|
|
Teardown Method = "TEARDOWN"
|
|
)
|
|
|
|
// Request is a RTSP request.
|
|
type Request struct {
|
|
// request method
|
|
Method Method
|
|
|
|
// request url
|
|
URL *URL
|
|
|
|
// map of header values
|
|
Header Header
|
|
|
|
// optional content
|
|
Content []byte
|
|
|
|
// whether to wait for a response or not
|
|
// used only by ClientConn.Do()
|
|
SkipResponse bool
|
|
}
|
|
|
|
// Read reads a request.
|
|
func (req *Request) Read(rb *bufio.Reader) error {
|
|
byts, err := readBytesLimited(rb, ' ', requestMaxLethodLength)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req.Method = Method(byts[:len(byts)-1])
|
|
|
|
if req.Method == "" {
|
|
return fmt.Errorf("empty method")
|
|
}
|
|
|
|
byts, err = readBytesLimited(rb, ' ', requestMaxPathLength)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
rawURL := string(byts[:len(byts)-1])
|
|
|
|
if rawURL == "" {
|
|
return fmt.Errorf("empty url")
|
|
}
|
|
|
|
ur, err := ParseURL(rawURL)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to parse url (%v)", rawURL)
|
|
}
|
|
req.URL = ur
|
|
|
|
byts, err = readBytesLimited(rb, '\r', requestMaxProtocolLength)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
proto := string(byts[:len(byts)-1])
|
|
|
|
if proto != rtspProtocol10 {
|
|
return fmt.Errorf("expected '%s', got '%s'", rtspProtocol10, proto)
|
|
}
|
|
|
|
err = readByteEqual(rb, '\n')
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = req.Header.read(rb)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = (*content)(&req.Content).read(rb, req.Header)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Write writes a request.
|
|
func (req Request) Write(bw *bufio.Writer) error {
|
|
urStr := req.URL.CloneWithoutCredentials().String()
|
|
_, err := bw.Write([]byte(string(req.Method) + " " + urStr + " " + rtspProtocol10 + "\r\n"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(req.Content) != 0 {
|
|
req.Header["Content-Length"] = HeaderValue{strconv.FormatInt(int64(len(req.Content)), 10)}
|
|
}
|
|
|
|
err = req.Header.write(bw)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = content(req.Content).write(bw)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return bw.Flush()
|
|
}
|
|
|
|
// String implements fmt.Stringer.
|
|
func (req Request) String() string {
|
|
buf := bytes.NewBuffer(nil)
|
|
req.Write(bufio.NewWriter(buf))
|
|
return buf.String()
|
|
}
|