forked from PretendoNetwork/nex-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrmc.go
165 lines (129 loc) · 3.87 KB
/
rmc.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package nex
import (
"errors"
)
// RMCRequest represets a RMC request
type RMCRequest struct {
protocolID uint8
callID uint32
methodID uint32
parameters []byte
}
// ProtocolID sets the RMC request protocolID
func (request *RMCRequest) ProtocolID() uint8 {
return request.protocolID
}
// CallID sets the RMC request callID
func (request *RMCRequest) CallID() uint32 {
return request.callID
}
// MethodID sets the RMC request methodID
func (request *RMCRequest) MethodID() uint32 {
return request.methodID
}
// Parameters sets the RMC request parameters
func (request *RMCRequest) Parameters() []byte {
return request.parameters
}
// NewRMCRequest returns a new parsed RMCRequest
func NewRMCRequest(data []byte) (RMCRequest, error) {
if len(data) < 13 {
return RMCRequest{}, errors.New("[RMC] Data size less than minimum")
}
stream := NewStreamIn(data, nil)
// TODO: Re-enable this once we can properly detect that the packet was fragmented. Right now it just causes a lot of log spew
//size := int(stream.ReadUInt32LE())
stream.ReadUInt32LE()
/*if size != (len(data) - 4) {
log.Println(errors.New("[RMC] Data size does not match; ignore this error"))
}*/
protocolID := stream.ReadUInt8() ^ 0x80
callID := stream.ReadUInt32LE()
methodID := stream.ReadUInt32LE()
parameters := data[13:]
request := RMCRequest{
protocolID: protocolID,
callID: callID,
methodID: methodID,
parameters: parameters,
}
return request, nil
}
// RMCResponse represents a RMC response
type RMCResponse struct {
protocolID uint8
success uint8
callID uint32
methodID uint32
data []byte
errorCode uint32
}
// SetSuccess sets the RMCResponse payload to an instance of RMCSuccess
func (response *RMCResponse) SetSuccess(methodID uint32, data []byte) {
response.success = 1
response.methodID = methodID
response.data = data
}
// SetError sets the RMCResponse payload to an instance of RMCError
func (response *RMCResponse) SetError(errorCode uint32) {
response.success = 0
response.errorCode = errorCode
}
// SetProtocolID sets the RMC request protocol ID
func (request *RMCRequest) SetProtocolID(protocolID uint8) {
request.protocolID = protocolID
}
// SetCallID sets the RMC request call ID
func (request *RMCRequest) SetCallID(callID uint32) {
request.callID = callID
}
// SetMethodID sets the RMC request method ID
func (request *RMCRequest) SetMethodID(methodID uint32) {
request.methodID = methodID
}
// SetParameters sets the RMC request parameters
func (request *RMCRequest) SetParameters(parameters []byte) {
request.parameters = parameters
}
// Bytes converts a RMCRequest struct into a usable byte array
func (request *RMCRequest) Bytes() []byte {
body := NewStreamOut(nil)
body.WriteUInt8(request.protocolID ^ 0x80)
body.WriteUInt32LE(request.callID)
body.WriteUInt32LE(request.methodID)
if request.parameters != nil && len(request.parameters) > 0 {
body.Grow(int64(len(request.parameters)))
body.WriteBytesNext(request.parameters)
}
data := NewStreamOut(nil)
data.WriteBuffer(body.Bytes())
return data.Bytes()
}
// Bytes converts a RMCResponse struct into a usable byte array
func (response *RMCResponse) Bytes() []byte {
body := NewStreamOut(nil)
body.WriteUInt8(response.protocolID)
body.WriteUInt8(response.success)
if response.success == 1 {
body.WriteUInt32LE(response.callID)
body.WriteUInt32LE(response.methodID | 0x8000)
if response.data != nil && len(response.data) > 0 {
body.Grow(int64(len(response.data)))
body.WriteBytesNext(response.data)
}
} else {
body.WriteUInt32LE(response.errorCode)
body.WriteUInt32LE(response.callID)
}
data := NewStreamOut(nil)
data.WriteBuffer(body.Bytes())
return data.Bytes()
}
// NewRMCResponse returns a new RMCResponse
func NewRMCResponse(protocolID uint8, callID uint32) RMCResponse {
response := RMCResponse{
protocolID: protocolID,
callID: callID,
}
return response
}