-
Notifications
You must be signed in to change notification settings - Fork 3
/
message.go
80 lines (65 loc) · 1.73 KB
/
message.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package rtmp
import (
"bytes"
"github.com/elobuff/goamf"
)
type Message struct {
Type uint8
ChunkStreamId uint32
StreamId uint32
Timestamp uint32
AbsoluteTimestamp uint32
TransactionId uint32
Length uint32
Buffer *bytes.Buffer
}
type Response struct {
Name string
TransactionId float64
Objects []interface{}
}
func (m *Message) RemainingBytes() uint32 {
if m.Buffer == nil {
return m.Length
}
return m.Length - uint32(m.Buffer.Len())
}
func (m *Message) DecodeResponse(c *Client) (response *Response, err error) {
dec := amf.NewDecoder()
response = new(Response)
for nam, fn := range c.amfExternalHandlers {
dec.RegisterExternalHandler(nam, fn)
}
if m.ChunkStreamId != CHUNK_STREAM_ID_COMMAND {
return response, Error("message is not a command message")
}
switch m.Type {
case MESSAGE_TYPE_AMF3:
_, err = m.Buffer.ReadByte()
if err != nil {
return response, Error("unable to read first byte of amf3 message")
}
fallthrough
case MESSAGE_TYPE_AMF0:
response.Name, err = dec.DecodeAmf0String(m.Buffer, true)
if err != nil {
return response, Error("unable to read command from amf message")
}
response.TransactionId, err = dec.DecodeAmf0Number(m.Buffer, true)
if err != nil {
return response, Error("unable to read tid from amf message")
}
var obj interface{}
for m.Buffer.Len() > 0 {
obj, err = dec.Decode(m.Buffer, 0)
if err != nil {
return response, Error("unable to read object from amf message: %s", err)
}
response.Objects = append(response.Objects, obj)
}
default:
return response, Error("unable to decode message: %+v", m)
}
log.Trace("command decoded: %+v", response)
return response, err
}