mirror of
https://github.com/AlexxIT/go2rtc.git
synced 2025-09-26 20:31:11 +08:00
151 lines
2.6 KiB
Go
151 lines
2.6 KiB
Go
package tcp
|
|
|
|
import (
|
|
"bufio"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/textproto"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
const EndLine = "\r\n"
|
|
|
|
// Response like http.Response, but with any proto
|
|
type Response struct {
|
|
Status string
|
|
StatusCode int
|
|
Proto string
|
|
Header textproto.MIMEHeader
|
|
Body []byte
|
|
Request *Request
|
|
}
|
|
|
|
func (r Response) String() string {
|
|
s := r.Proto + " " + r.Status + EndLine
|
|
for k, v := range r.Header {
|
|
s += k + ": " + v[0] + EndLine
|
|
}
|
|
s += EndLine
|
|
if r.Body != nil {
|
|
s += string(r.Body)
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (r *Response) Write(w io.Writer) (err error) {
|
|
_, err = w.Write([]byte(r.String()))
|
|
return
|
|
}
|
|
|
|
func ReadResponse(r *bufio.Reader) (*Response, error) {
|
|
tp := textproto.NewReader(r)
|
|
|
|
line, err := tp.ReadLine()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if line == "" {
|
|
return nil, errors.New("empty response on RTSP request")
|
|
}
|
|
|
|
ss := strings.SplitN(line, " ", 3)
|
|
if len(ss) != 3 {
|
|
return nil, fmt.Errorf("malformed response: %s", line)
|
|
}
|
|
|
|
res := &Response{
|
|
Status: ss[1] + " " + ss[2],
|
|
Proto: ss[0],
|
|
}
|
|
|
|
res.StatusCode, err = strconv.Atoi(ss[1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
res.Header, err = tp.ReadMIMEHeader()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if val := res.Header.Get("Content-Length"); val != "" {
|
|
var i int
|
|
i, err = strconv.Atoi(val)
|
|
res.Body = make([]byte, i)
|
|
if _, err = io.ReadAtLeast(r, res.Body, i); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
// Request like http.Request, but with any proto
|
|
type Request struct {
|
|
Method string
|
|
URL *url.URL
|
|
Proto string
|
|
Header textproto.MIMEHeader
|
|
Body []byte
|
|
}
|
|
|
|
func (r *Request) String() string {
|
|
s := r.Method + " " + r.URL.String() + " " + r.Proto + EndLine
|
|
for k, v := range r.Header {
|
|
s += k + ": " + v[0] + EndLine
|
|
}
|
|
s += EndLine
|
|
if r.Body != nil {
|
|
s += string(r.Body)
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (r *Request) Write(w io.Writer) (err error) {
|
|
_, err = w.Write([]byte(r.String()))
|
|
return
|
|
}
|
|
|
|
func ReadRequest(r *bufio.Reader) (*Request, error) {
|
|
tp := textproto.NewReader(r)
|
|
|
|
line, err := tp.ReadLine()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ss := strings.SplitN(line, " ", 3)
|
|
if len(ss) != 3 {
|
|
return nil, fmt.Errorf("wrong request: %s", line)
|
|
}
|
|
|
|
req := &Request{
|
|
Method: ss[0],
|
|
Proto: ss[2],
|
|
}
|
|
|
|
req.URL, err = url.Parse(ss[1])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
req.Header, err = tp.ReadMIMEHeader()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if val := req.Header.Get("Content-Length"); val != "" {
|
|
var i int
|
|
i, err = strconv.Atoi(val)
|
|
req.Body = make([]byte, i)
|
|
if _, err = io.ReadAtLeast(r, req.Body, i); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return req, nil
|
|
}
|