RTMP packet marshaling
This commit is contained in:
parent
3001499cae
commit
261ad84d23
4 changed files with 63 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
||||||
package rtmp
|
package rtmp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
@ -10,6 +11,7 @@ import (
|
||||||
// DataPacket represents an RTMP Data packet.
|
// DataPacket represents an RTMP Data packet.
|
||||||
type DataPacket struct {
|
type DataPacket struct {
|
||||||
RouterAddr ddp.Addr
|
RouterAddr ddp.Addr
|
||||||
|
Extended bool
|
||||||
NetworkTuples []NetworkTuple
|
NetworkTuples []NetworkTuple
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +23,29 @@ type NetworkTuple struct {
|
||||||
Distance uint8
|
Distance uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marshal marshals an RTMP Data packet.
|
||||||
|
func (dp *DataPacket) Marshal() ([]byte, error) {
|
||||||
|
b := bytes.NewBuffer(nil)
|
||||||
|
write16(b, dp.RouterAddr.Network)
|
||||||
|
b.WriteByte(8)
|
||||||
|
b.WriteByte(byte(dp.RouterAddr.Node))
|
||||||
|
if !dp.Extended {
|
||||||
|
write16(b, uint16(0))
|
||||||
|
b.WriteByte(0x82)
|
||||||
|
}
|
||||||
|
for _, nt := range dp.NetworkTuples {
|
||||||
|
write16(b, nt.RangeStart)
|
||||||
|
if !nt.Extended {
|
||||||
|
b.WriteByte(nt.Distance)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b.WriteByte(nt.Distance | 0x80)
|
||||||
|
write16(b, nt.RangeEnd)
|
||||||
|
b.WriteByte(0x82)
|
||||||
|
}
|
||||||
|
return b.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalDataPacket unmarshals a DataPacket.
|
// UnmarshalDataPacket unmarshals a DataPacket.
|
||||||
func UnmarshalDataPacket(data []byte) (*DataPacket, error) {
|
func UnmarshalDataPacket(data []byte) (*DataPacket, error) {
|
||||||
if len(data) < 7 || (len(data)-4)%3 != 0 {
|
if len(data) < 7 || (len(data)-4)%3 != 0 {
|
||||||
|
@ -34,6 +59,7 @@ func UnmarshalDataPacket(data []byte) (*DataPacket, error) {
|
||||||
Network: ddp.Network(binary.BigEndian.Uint16(data[:2])),
|
Network: ddp.Network(binary.BigEndian.Uint16(data[:2])),
|
||||||
Node: ddp.Node(data[3]),
|
Node: ddp.Node(data[3]),
|
||||||
},
|
},
|
||||||
|
Extended: true,
|
||||||
}
|
}
|
||||||
data = data[4:]
|
data = data[4:]
|
||||||
|
|
||||||
|
@ -56,6 +82,7 @@ func UnmarshalDataPacket(data []byte) (*DataPacket, error) {
|
||||||
if nt.Distance != 0x82 {
|
if nt.Distance != 0x82 {
|
||||||
return nil, fmt.Errorf("unsupported RTMP version %x", nt.Distance)
|
return nil, fmt.Errorf("unsupported RTMP version %x", nt.Distance)
|
||||||
}
|
}
|
||||||
|
dp.Extended = false
|
||||||
first = false
|
first = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
7
atalk/rtmp/misc.go
Normal file
7
atalk/rtmp/misc.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package rtmp
|
||||||
|
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
func write16[I ~uint16](b *bytes.Buffer, n I) {
|
||||||
|
b.Write([]byte{byte(n >> 8), byte(n & 0xff)})
|
||||||
|
}
|
|
@ -7,6 +7,15 @@ type RequestPacket struct {
|
||||||
Function uint8
|
Function uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marshal marshals an RTMP Request or RTMP RDR packet.
|
||||||
|
func (rp *RequestPacket) Marshal() ([]byte, error) {
|
||||||
|
if rp.Function < 1 || rp.Function > 3 {
|
||||||
|
return nil, fmt.Errorf("invalid RTMP request function %d", rp.Function)
|
||||||
|
}
|
||||||
|
return []byte{rp.Function}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalRequestPacket unmarshals an RTMP Request or RTMP RDR packet.
|
||||||
func UnmarshalRequestPacket(data []byte) (*RequestPacket, error) {
|
func UnmarshalRequestPacket(data []byte) (*RequestPacket, error) {
|
||||||
if len(data) != 1 {
|
if len(data) != 1 {
|
||||||
return nil, fmt.Errorf("invalid data length %d for RTMP Request or RTMP RDR packet", len(data))
|
return nil, fmt.Errorf("invalid data length %d for RTMP Request or RTMP RDR packet", len(data))
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package rtmp
|
package rtmp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/sfiera/multitalk/pkg/ddp"
|
"github.com/sfiera/multitalk/pkg/ddp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ResponsePacket represents an RTMP Response packet.
|
||||||
type ResponsePacket struct {
|
type ResponsePacket struct {
|
||||||
SenderAddr ddp.Addr
|
SenderAddr ddp.Addr
|
||||||
Extended bool
|
Extended bool
|
||||||
|
@ -14,6 +16,24 @@ type ResponsePacket struct {
|
||||||
RangeEnd ddp.Network
|
RangeEnd ddp.Network
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marshal marshals an RTMP Response packet.
|
||||||
|
func (rp *ResponsePacket) Marshal() ([]byte, error) {
|
||||||
|
b := bytes.NewBuffer(nil)
|
||||||
|
b.Grow(10)
|
||||||
|
write16(b, rp.SenderAddr.Network)
|
||||||
|
b.WriteByte(8)
|
||||||
|
b.WriteByte(byte(rp.SenderAddr.Node))
|
||||||
|
if !rp.Extended {
|
||||||
|
return b.Bytes(), nil
|
||||||
|
}
|
||||||
|
write16(b, rp.RangeStart)
|
||||||
|
b.WriteByte(0x80)
|
||||||
|
write16(b, rp.RangeEnd)
|
||||||
|
b.WriteByte(0x82)
|
||||||
|
return b.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalResponsePacket unmarshals an RTMP Response packet.
|
||||||
func UnmarshalResponsePacket(data []byte) (*ResponsePacket, error) {
|
func UnmarshalResponsePacket(data []byte) (*ResponsePacket, error) {
|
||||||
if len(data) != 4 && len(data) != 10 {
|
if len(data) != 4 && len(data) != 10 {
|
||||||
return nil, fmt.Errorf("invalid input length %d for RTMP Response packet", len(data))
|
return nil, fmt.Errorf("invalid input length %d for RTMP Response packet", len(data))
|
||||||
|
|
Loading…
Reference in a new issue