forked from shibukawa/tobubus
-
Notifications
You must be signed in to change notification settings - Fork 1
/
message.go
96 lines (87 loc) · 2.33 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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package tobubus
import (
"encoding/binary"
"github.com/ugorji/go/codec"
"io"
"net"
)
type MessageType uint32
const (
ResultOK MessageType = 0x1
ResultNG = 0x2
ResultObjectNotFound = 0x3
ResultMethodNotFound = 0x4
ResultMethodError = 0x5
ConnectClient = 0x10
CloseClient = 0x11
ConfirmPath = 0x20
Publish = 0x21
Unpublish = 0x22
CallMethod = 0x30
ReturnMethod = 0x31
)
type message struct {
Type MessageType
ID uint32
body []byte
}
type methodCall struct {
Path string `codec:"path,omitempty"`
Method string `codec:"method,omitempty"`
Params []interface{} `codec:"params"`
}
func archiveMessage(msg MessageType, sessionID uint32, body []byte) []byte {
result := make([]byte, 12+len(body))
binary.LittleEndian.PutUint32(result, uint32(msg))
binary.LittleEndian.PutUint32(result[4:], sessionID)
binary.LittleEndian.PutUint32(result[8:], uint32(len(body)))
copy(result[12:], body)
return result
}
func parseMessage(conn net.Conn) (*message, error) {
header := make([]byte, 12)
_, err := io.ReadAtLeast(conn, header, 12)
if err != nil {
return nil, err
}
messageType := binary.LittleEndian.Uint32(header)
sessionID := binary.LittleEndian.Uint32(header[4:])
bodySize := binary.LittleEndian.Uint32(header[8:])
var body []byte
if bodySize > 0 {
body = make([]byte, bodySize)
_, err = io.ReadAtLeast(conn, body, int(bodySize))
if err != nil {
return nil, err
}
}
return &message{
Type: MessageType(messageType),
ID: sessionID,
body: body,
}, nil
}
func archiveMethodCallMessage(msg MessageType, msgID uint32, path, methodName string, params []interface{}) ([]byte, error) {
var ch codec.CborHandle
src := methodCall{
Path: path,
Method: methodName,
Params: params,
}
var data []byte
ch.SignedInteger = true
enc := codec.NewEncoderBytes(&data, &ch)
err := enc.Encode(src)
if err != nil {
return nil, err
}
return archiveMessage(msg, msgID, data), nil
}
func parseMethodCallMessage(data []byte) *methodCall {
var ch codec.CborHandle
ch.SignedInteger = true
result := &methodCall{}
dec := codec.NewDecoderBytes(data, &ch)
dec.Decode(result)
return result
}