move interleaved frames into dedicated struct

This commit is contained in:
aler9
2020-01-26 11:45:32 +01:00
parent da431f1c89
commit 9d2081e29c
5 changed files with 189 additions and 122 deletions

View File

@@ -12,15 +12,15 @@ func md5Hex(in string) string {
return hex.EncodeToString(h.Sum(nil)) return hex.EncodeToString(h.Sum(nil))
} }
type AuthClientProvider struct { type authClientProvider struct {
user string user string
pass string pass string
realm string realm string
nonce string nonce string
} }
func NewAuthClientProvider(user string, pass string, realm string, nonce string) *AuthClientProvider { func newAuthClientProvider(user string, pass string, realm string, nonce string) *authClientProvider {
return &AuthClientProvider{ return &authClientProvider{
user: user, user: user,
pass: pass, pass: pass,
realm: realm, realm: realm,
@@ -28,7 +28,7 @@ func NewAuthClientProvider(user string, pass string, realm string, nonce string)
} }
} }
func (ap *AuthClientProvider) generateHeader(method string, path string) string { func (ap *authClientProvider) generateHeader(method string, path string) string {
ha1 := md5Hex(ap.user + ":" + ap.realm + ":" + ap.pass) ha1 := md5Hex(ap.user + ":" + ap.realm + ":" + ap.pass)
ha2 := md5Hex(method + ":" + path) ha2 := md5Hex(method + ":" + path)
response := md5Hex(ha1 + ":" + ap.nonce + ":" + ha2) response := md5Hex(ha1 + ":" + ap.nonce + ":" + ha2)

118
conn.go
View File

@@ -1,118 +0,0 @@
package gortsplib
import (
"encoding/binary"
"fmt"
"io"
"net"
"strconv"
)
type Conn struct {
nconn net.Conn
writeBuf []byte
session string
clientCseqEnabled bool
clientCseq int
clientAuthProv *AuthClientProvider
}
func NewConn(nconn net.Conn) *Conn {
return &Conn{
nconn: nconn,
writeBuf: make([]byte, 2048),
}
}
func (c *Conn) NetConn() net.Conn {
return c.nconn
}
func (c *Conn) SetSession(v string) {
c.session = v
}
func (c *Conn) ClientEnableCseq() {
c.clientCseqEnabled = true
}
func (c *Conn) ClientSetCredentials(user string, pass string, realm string, nonce string) {
c.clientAuthProv = NewAuthClientProvider(user, pass, realm, nonce)
}
func (c *Conn) ReadRequest() (*Request, error) {
return readRequest(c.nconn)
}
func (c *Conn) WriteRequest(req *Request) error {
if c.session != "" {
if req.Header == nil {
req.Header = make(Header)
}
req.Header["Session"] = []string{c.session}
}
if c.clientCseqEnabled {
if req.Header == nil {
req.Header = make(Header)
}
c.clientCseq += 1
req.Header["CSeq"] = []string{strconv.FormatInt(int64(c.clientCseq), 10)}
}
if c.clientAuthProv != nil {
if req.Header == nil {
req.Header = make(Header)
}
req.Header["Authorization"] = []string{c.clientAuthProv.generateHeader(req.Method, req.Url)}
}
return req.write(c.nconn)
}
func (c *Conn) ReadResponse() (*Response, error) {
return readResponse(c.nconn)
}
func (c *Conn) WriteResponse(res *Response) error {
return res.write(c.nconn)
}
func (c *Conn) ReadInterleavedFrame(buf []byte) (int, int, error) {
var header [4]byte
_, err := io.ReadFull(c.nconn, header[:])
if err != nil {
return 0, 0, err
}
// connection terminated
if header[0] == 0x54 {
return 0, 0, io.EOF
}
if header[0] != 0x24 {
return 0, 0, fmt.Errorf("wrong magic byte (0x%.2x)", header[0])
}
framelen := binary.BigEndian.Uint16(header[2:])
if int(framelen) > len(buf) {
return 0, 0, fmt.Errorf("frame length greater than buffer length")
}
_, err = io.ReadFull(c.nconn, buf[:framelen])
if err != nil {
return 0, 0, err
}
return int(header[1]), int(framelen), nil
}
func (c *Conn) WriteInterleavedFrame(channel int, frame []byte) error {
c.writeBuf[0] = 0x24
c.writeBuf[1] = byte(channel)
binary.BigEndian.PutUint16(c.writeBuf[2:], uint16(len(frame)))
n := copy(c.writeBuf[4:], frame)
_, err := c.nconn.Write(c.writeBuf[:4+n])
if err != nil {
return err
}
return nil
}

74
connclient.go Normal file
View File

@@ -0,0 +1,74 @@
package gortsplib
import (
"bufio"
"net"
"strconv"
)
type ConnClient struct {
nconn net.Conn
bw *bufio.Writer
session string
cseqEnabled bool
cseq int
authProv *authClientProvider
}
func NewConnClient(nconn net.Conn) *ConnClient {
return &ConnClient{
nconn: nconn,
bw: bufio.NewWriterSize(nconn, _INTERLEAVED_FRAME_MAX_SIZE),
}
}
func (c *ConnClient) NetConn() net.Conn {
return c.nconn
}
func (c *ConnClient) SetSession(v string) {
c.session = v
}
func (c *ConnClient) EnableCseq() {
c.cseqEnabled = true
}
func (c *ConnClient) SetCredentials(user string, pass string, realm string, nonce string) {
c.authProv = newAuthClientProvider(user, pass, realm, nonce)
}
func (c *ConnClient) WriteRequest(req *Request) error {
if c.session != "" {
if req.Header == nil {
req.Header = make(Header)
}
req.Header["Session"] = []string{c.session}
}
if c.cseqEnabled {
if req.Header == nil {
req.Header = make(Header)
}
c.cseq += 1
req.Header["CSeq"] = []string{strconv.FormatInt(int64(c.cseq), 10)}
}
if c.authProv != nil {
if req.Header == nil {
req.Header = make(Header)
}
req.Header["Authorization"] = []string{c.authProv.generateHeader(req.Method, req.Url)}
}
return req.write(c.nconn)
}
func (c *ConnClient) ReadResponse() (*Response, error) {
return readResponse(c.nconn)
}
func (c *ConnClient) ReadInterleavedFrame() (*InterleavedFrame, error) {
return readInterleavedFrame(c.nconn)
}
func (c *ConnClient) WriteInterleavedFrame(frame *InterleavedFrame) error {
return frame.write(c.bw)
}

38
connserver.go Normal file
View File

@@ -0,0 +1,38 @@
package gortsplib
import (
"bufio"
"net"
)
type ConnServer struct {
nconn net.Conn
bw *bufio.Writer
}
func NewConnServer(nconn net.Conn) *ConnServer {
return &ConnServer{
nconn: nconn,
bw: bufio.NewWriterSize(nconn, _INTERLEAVED_FRAME_MAX_SIZE),
}
}
func (s *ConnServer) NetConn() net.Conn {
return s.nconn
}
func (s *ConnServer) ReadRequest() (*Request, error) {
return readRequest(s.nconn)
}
func (s *ConnServer) WriteResponse(res *Response) error {
return res.write(s.nconn)
}
func (s *ConnServer) ReadInterleavedFrame() (*InterleavedFrame, error) {
return readInterleavedFrame(s.nconn)
}
func (s *ConnServer) WriteInterleavedFrame(frame *InterleavedFrame) error {
return frame.write(s.bw)
}

73
interleavedframe.go Normal file
View File

@@ -0,0 +1,73 @@
package gortsplib
import (
"bufio"
"encoding/binary"
"fmt"
"io"
)
const (
_INTERLEAVED_FRAME_MAX_SIZE = 2048
_INTERLEAVED_FRAME_MAX_CONTENT_SIZE = (_INTERLEAVED_FRAME_MAX_SIZE - 4)
)
type InterleavedFrame struct {
Channel uint8
Content []byte
}
func readInterleavedFrame(r io.Reader) (*InterleavedFrame, error) {
var header [4]byte
_, err := io.ReadFull(r, header[:])
if err != nil {
return nil, err
}
// connection terminated
if header[0] == 0x54 {
return nil, io.EOF
}
if header[0] != 0x24 {
return nil, fmt.Errorf("wrong magic byte (0x%.2x)", header[0])
}
framelen := binary.BigEndian.Uint16(header[2:])
if int(framelen) > _INTERLEAVED_FRAME_MAX_SIZE {
return nil, fmt.Errorf("frame length greater than maximum allowed")
}
f := &InterleavedFrame{
Channel: header[1],
Content: make([]byte, framelen),
}
_, err = io.ReadFull(r, f.Content)
if err != nil {
return nil, err
}
return f, nil
}
func (f *InterleavedFrame) write(bw *bufio.Writer) error {
_, err := bw.Write([]byte{0x24, f.Channel})
if err != nil {
return err
}
buf := make([]byte, 2)
binary.BigEndian.PutUint16(buf, uint16(len(f.Content)))
_, err = bw.Write(buf)
if err != nil {
return err
}
_, err = bw.Write(f.Content)
if err != nil {
return err
}
return bw.Flush()
}