1 Star 1 Fork 0

raininfall/RTSP

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
request.go 4.23 KB
一键复制 编辑 原始数据 按行查看 历史
Songrq 提交于 2019-08-23 04:10 +08:00 . v0.0.1
package rtsp
import (
"bufio"
"bytes"
"fmt"
"io"
"net/textproto"
"net/url"
"strconv"
"strings"
"gitee.com/raininfall/header"
)
// RTSP request method
const (
MethodOptions = "OPTIONS"
MethodAnnounce = "ANNOUNCE"
MethodDescribe = "DESCRIBE"
MethodSetup = "SETUP"
MethodPlay = "PLAY"
MethodPause = "PAUSE"
MethodGetParameter = "GET_PARAMETER"
MethodSetParameter = "SET_PARAMETER"
MethodTeardown = "TEARDOWN"
MethodRecord = "RECORD"
)
var (
validMethods = []string{
MethodOptions,
MethodDescribe,
MethodSetup,
MethodPlay,
MethodTeardown,
MethodGetParameter,
MethodSetParameter,
}
)
// Request of RTSP
type Request struct {
Method string
URL *url.URL // non-nil in server
RawURL string // Manufactor like DaHua ONVIF RTSP URL is invalid
Control string // uri of Authorization is without control
ProtoMajor int
ProtoMinor int
CSeq uint64 // for other arch system, use 32 bit integer
Header header.Header
Body []byte
}
// NewRequest returns
func NewRequest(method string, rawurl string) *Request {
return &Request{
Method: method,
RawURL: rawurl,
ProtoMajor: 1,
ProtoMinor: 2,
Header: make(map[string][]string),
}
}
// Bytes of request
func (r *Request) Bytes() []byte {
b := make([]byte, 1024)
buf := bytes.NewBuffer(b[:0])
buf.WriteString(fmt.Sprintf("%s %s%s RTSP/%d.%d\r\n",
r.Method, r.RawURL, r.Control, r.ProtoMajor, r.ProtoMinor))
if len(r.Body) > 0 {
r.Header.Set("Content-Length", fmt.Sprintf("%d", len(r.Body)))
}
buf.Write(r.Header.Bytes(nil))
buf.WriteString("\r\n")
if len(r.Body) > 0 {
buf.Write(r.Body)
}
return buf.Bytes()
}
// parseRequestLine parses "GET /foo HTTP/1.1" into its three parts.
func parseRequestLine(line string) (method, requestURI, proto string, ok bool) {
s1 := strings.Index(line, " ")
s2 := strings.Index(line[s1+1:], " ")
if s1 < 0 || s2 < 0 {
return
}
s2 += s1 + 1
return line[:s1], line[s1+1 : s2], line[s2+1:], true
}
// ParseRTSPVersion parses a RTSP version string.
// "RTSP/1.0" returns (1, 0, true).
func ParseRTSPVersion(vers string) (major, minor int, ok bool) {
const Big = 1000000 // arbitrary upper bound
switch vers {
case "RTSP/1.0":
return 1, 0, true
case "RTSP/2.0":
return 2, 0, true
}
if !strings.HasPrefix(vers, "RTSP/") {
return 0, 0, false
}
dot := strings.Index(vers, ".")
if dot < 0 {
return 0, 0, false
}
major, err := strconv.Atoi(vers[5:dot])
if err != nil || major < 0 || major > Big {
return 0, 0, false
}
minor, err = strconv.Atoi(vers[dot+1:])
if err != nil || minor < 0 || minor > Big {
return 0, 0, false
}
return major, minor, true
}
// ReadRequest from reader
func ReadRequest(r *bufio.Reader) (request *Request, err error) {
request = new(Request)
reader := textproto.NewReader(r)
// Change normal error
defer func() {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
}()
// head line
var ok bool
{
headline, err := reader.ReadLine()
if err != nil {
return nil, err
}
var proto string
request.Method, request.RawURL, proto, ok = parseRequestLine(headline)
if !ok {
return nil, &badStringError{"malformed HTTP request", headline}
}
if request.URL, err = url.ParseRequestURI(request.RawURL); nil != err {
return nil, err
}
if request.ProtoMajor, request.ProtoMinor, ok = ParseRTSPVersion(proto); !ok {
return nil, &badStringError{"malformed RTSP version", proto}
}
}
// header
{
mimeHeader, err := reader.ReadMIMEHeader()
if err != nil {
return nil, err
}
request.Header = header.FromMIMEHeader(mimeHeader)
// All request must have CSeq
if !request.Header.Has("CSeq") {
return nil, &missingError{Part: "CSeq"}
}
request.CSeq, err = strconv.ParseUint(request.Header.Get("CSeq"), 10, 64)
if nil != err {
return nil, &badStringError{"invalid cseq", request.Header.Get("CSeq")}
}
}
// body
{
if request.Header.Has("Content-Length") {
l, err := strconv.ParseUint(request.Header.Get("Content-Length"), 10, 31)
if nil != err {
return nil, &badStringError{"invalid content-length", request.Header.Get("Content-Length")}
}
request.Body = make([]byte, l)
_, err = io.ReadFull(r, request.Body)
if nil != err {
return nil, err
}
}
}
return
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/raininfall/rtsp.git
git@gitee.com:raininfall/rtsp.git
raininfall
rtsp
RTSP
v0.0.1

搜索帮助