Files
go-rtmp/message/decoder.go
T

268 lines
5.9 KiB
Go
Raw Normal View History

//
// Copyright (c) 2018- yutopp (yutopp@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
//
package message
import (
"encoding/binary"
"fmt"
2018-07-28 17:40:33 +09:00
"github.com/pkg/errors"
"io"
2018-05-28 17:51:42 +09:00
"github.com/yutopp/go-amf0"
)
type Decoder struct {
r io.Reader
}
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{
r: r,
}
}
func (dec *Decoder) Reset(r io.Reader) {
dec.r = r
}
func (dec *Decoder) Decode(typeID TypeID, msg *Message) error {
switch typeID {
case TypeIDSetChunkSize:
return dec.decodeSetChunkSize(msg)
case TypeIDAbortMessage:
return dec.decodeAbortMessage(msg)
case TypeIDAck:
return dec.decodeAck(msg)
case TypeIDUserCtrl:
return dec.decodeUserCtrl(msg)
case TypeIDWinAckSize:
return dec.decodeWinAckSize(msg)
case TypeIDSetPeerBandwidth:
return dec.decodeSetPeerBandwidth(msg)
case TypeIDAudioMessage:
return dec.decodeAudioMessage(msg)
case TypeIDVideoMessage:
return dec.decodeVideoMessage(msg)
case TypeIDDataMessageAMF3:
return dec.decodeDataMessageAMF3(msg)
case TypeIDSharedObjectMessageAMF3:
return dec.decodeSharedObjectMessageAMF3(msg)
case TypeIDCommandMessageAMF3:
return dec.decodeCommandMessageAMF3(msg)
case TypeIDDataMessageAMF0:
return dec.decodeDataMessageAMF0(msg)
case TypeIDSharedObjectMessageAMF0:
return dec.decodeSharedObjectMessageAMF0(msg)
case TypeIDCommandMessageAMF0:
return dec.decodeCommandMessageAMF0(msg)
case TypeIDAggregateMessage:
return dec.decodeAggregateMessage(msg)
default:
return fmt.Errorf("Unexpected message type(decode): ID = %d", typeID)
}
}
func (dec *Decoder) decodeSetChunkSize(msg *Message) error {
2018-06-19 21:16:11 +09:00
buf := make([]byte, 4)
if _, err := io.ReadAtLeast(dec.r, buf, 4); err != nil {
return err
}
total := binary.BigEndian.Uint32(buf)
bit := (total & 0x80000000) >> 31 // 0b1000,0000... >> 31
chunkSize := total & 0x7fffffff // 0b0111,1111...
if bit != 0 {
return fmt.Errorf("Invalid format: bit must be 0")
}
if chunkSize == 0 {
return fmt.Errorf("Invalid format: chunk size is 0")
}
*msg = &SetChunkSize{
ChunkSize: chunkSize,
}
return nil
}
func (dec *Decoder) decodeAbortMessage(msg *Message) error {
2018-06-21 18:52:19 +09:00
buf := make([]byte, 4)
if _, err := io.ReadAtLeast(dec.r, buf, 4); err != nil {
return err
}
chunkStreamID := binary.BigEndian.Uint32(buf)
*msg = &AbortMessage{
ChunkStreamID: chunkStreamID,
}
return nil
}
func (dec *Decoder) decodeAck(msg *Message) error {
buf := make([]byte, 4)
if _, err := io.ReadAtLeast(dec.r, buf, 4); err != nil {
return err
}
sequenceNumber := binary.BigEndian.Uint32(buf)
*msg = &Ack{
SequenceNumber: sequenceNumber,
}
return nil
}
func (dec *Decoder) decodeUserCtrl(msg *Message) error {
2018-07-28 17:40:33 +09:00
ucmDec := NewUserControlEventDecoder(dec.r)
var event UserCtrlEvent
if err := ucmDec.Decode(&event); err != nil {
return errors.Wrapf(err, "Failed to decode UserCtrl")
}
*msg = &UserCtrl{
Event: event,
}
return nil
}
func (dec *Decoder) decodeWinAckSize(msg *Message) error {
2018-06-21 18:56:41 +09:00
buf := make([]byte, 4)
if _, err := io.ReadAtLeast(dec.r, buf, 4); err != nil {
return err
}
2018-07-14 21:08:04 +09:00
size := int32(binary.BigEndian.Uint32(buf))
2018-06-21 18:56:41 +09:00
*msg = &WinAckSize{
Size: size,
}
return nil
}
func (dec *Decoder) decodeSetPeerBandwidth(msg *Message) error {
2018-06-21 19:00:33 +09:00
buf := make([]byte, 5)
if _, err := io.ReadAtLeast(dec.r, buf, 5); err != nil {
return err
}
2018-07-09 19:01:33 +09:00
size := int32(binary.BigEndian.Uint32(buf[0:4]))
2018-06-21 19:00:33 +09:00
limit := LimitType(buf[4])
*msg = &SetPeerBandwidth{
Size: size,
Limit: limit,
}
return nil
}
func (dec *Decoder) decodeAudioMessage(msg *Message) error {
*msg = &AudioMessage{
Payload: dec.r, // Share an ownership of the reader
}
return nil
}
func (dec *Decoder) decodeVideoMessage(msg *Message) error {
*msg = &VideoMessage{
Payload: dec.r, // Share an ownership of the reader
}
return nil
}
func (dec *Decoder) decodeDataMessageAMF3(msg *Message) error {
return fmt.Errorf("Not implemented: DataMessageAMF3")
}
func (dec *Decoder) decodeSharedObjectMessageAMF3(msg *Message) error {
return fmt.Errorf("Not implemented: SharedObjectMessageAMF3")
}
func (dec *Decoder) decodeCommandMessageAMF3(msg *Message) error {
return fmt.Errorf("Not implemented: CommandMessageAMF3")
}
func (dec *Decoder) decodeDataMessageAMF0(msg *Message) error {
if err := dec.decodeDataMessage(msg, func(r io.Reader) (AMFDecoder, EncodingType) {
return amf0.NewDecoder(r), EncodingTypeAMF0
}); err != nil {
return err
}
return nil
}
func (dec *Decoder) decodeSharedObjectMessageAMF0(msg *Message) error {
return fmt.Errorf("Not implemented: SharedObjectMessageAMF0")
}
func (dec *Decoder) decodeCommandMessageAMF0(msg *Message) error {
if err := dec.decodeCommandMessage(msg, func(r io.Reader) (AMFDecoder, EncodingType) {
return amf0.NewDecoder(r), EncodingTypeAMF0
}); err != nil {
return err
}
return nil
}
func (dec *Decoder) decodeAggregateMessage(msg *Message) error {
return fmt.Errorf("Not implemented: AggregateMessage")
}
func (dec *Decoder) decodeDataMessage(msg *Message, f func(r io.Reader) (AMFDecoder, EncodingType)) error {
d, encTy := f(dec.r)
var name string
if err := d.Decode(&name); err != nil {
return errors.Wrap(err, "Failed to decode name")
}
*msg = &DataMessage{
Name: name,
Encoding: encTy,
Body: dec.r, // Share an ownership of the reader
}
return nil
}
func (dec *Decoder) decodeCommandMessage(msg *Message, f func(r io.Reader) (AMFDecoder, EncodingType)) error {
d, encTy := f(dec.r)
var name string
if err := d.Decode(&name); err != nil {
return errors.Wrap(err, "Failed to decode name")
}
var transactionID int64
if err := d.Decode(&transactionID); err != nil {
return errors.Wrap(err, "Failed to decode transactionID")
}
*msg = &CommandMessage{
CommandName: name,
TransactionID: transactionID,
Encoding: encTy,
Body: dec.r, // Share an ownership of the reader
}
return nil
}