-
Notifications
You must be signed in to change notification settings - Fork 7
/
common.go
executable file
·349 lines (314 loc) · 8.85 KB
/
common.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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
package wkproto
import "fmt"
// Framer 包的基础framer
type Framer struct {
FrameType FrameType
RemainingLength uint32 // 控制报文总长度等于固定报头的长度加上剩余长度
NoPersist bool // 是否不持久化
RedDot bool // 是否显示红点
SyncOnce bool // 此消息只被同步或被消费一次
DUP bool // 是否是重发消息
HasServerVersion bool // 是否有服务端版本 connack包用到
FrameSize int64
}
// ToFixHeaderUint8 ToFixHeaderUint8
func ToFixHeaderUint8(f Frame) uint8 {
typeAndFlags := encodeBool(f.GetDUP())<<3 | encodeBool(f.GetsyncOnce())<<2 | encodeBool(f.GetRedDot())<<1 | encodeBool(f.GetNoPersist())
if f.GetFrameType() == CONNACK {
typeAndFlags = encodeBool(f.GetHasServerVersion())
}
return byte(int(f.GetFrameType()<<4) | typeAndFlags)
}
// FramerFromUint8 FramerFromUint8
func FramerFromUint8(v uint8) Framer {
p := Framer{}
p.NoPersist = (v & 0x01) > 0
p.RedDot = (v >> 1 & 0x01) > 0
p.SyncOnce = (v >> 2 & 0x01) > 0
p.DUP = (v >> 3 & 0x01) > 0
p.FrameType = FrameType(v >> 4)
if p.FrameType == CONNACK {
p.HasServerVersion = (v & 0x01) > 0
}
return p
}
// GetFrameType GetFrameType
func (f Framer) GetFrameType() FrameType {
return f.FrameType
}
func (f Framer) GetFrameSize() int64 {
return f.FrameSize
}
// GetRemainingLength 包剩余长度
func (f Framer) GetRemainingLength() uint32 {
return f.RemainingLength
}
// GetNoPersist 是否不持久化
func (f Framer) GetNoPersist() bool {
return f.NoPersist
}
// GetRedDot 是否显示红点
func (f Framer) GetRedDot() bool {
return f.RedDot
}
// GetsyncOnce 是否只被同步一次
func (f Framer) GetsyncOnce() bool {
return f.SyncOnce
}
// GetDUP 是否是重发消息
func (f Framer) GetDUP() bool {
return f.DUP
}
func (f Framer) GetHasServerVersion() bool {
return f.HasServerVersion
}
func (f Framer) String() string {
return fmt.Sprintf("packetType: %s remainingLength:%d NoPersist:%v redDot:%v syncOnce:%v DUP:%v", f.GetFrameType().String(), f.RemainingLength, f.NoPersist, f.RedDot, f.SyncOnce, f.DUP)
}
// type Setting struct {
// Receipt bool // 消息已读回执,此标记表示,此消息需要已读回执
// Signal bool // 是否采用signal加密
// }
// func (s Setting) ToUint8() uint8 {
// return uint8(encodeBool(s.Receipt) << 7)
// }
// func SettingFromUint8(v uint8) Setting {
// s := Setting{}
// s.Receipt = (v >> 7 & 0x01) > 0
// return s
// }
//
// FrameType 包类型
type FrameType uint8
// 包类型
const (
UNKNOWN FrameType = iota // 保留位
CONNECT // 客户端请求连接到服务器(c2s)
CONNACK // 服务端收到连接请求后确认的报文(s2c)
SEND // 发送消息(c2s)
SENDACK // 收到消息确认的报文(s2c)
RECV // 收取消息(s2c)
RECVACK // 收取消息确认(c2s)
PING //ping请求
PONG // 对ping请求的相应
DISCONNECT // 请求断开连接
SUB // 订阅
SUBACK // 订阅确认
)
func (p FrameType) String() string {
switch p {
case CONNECT:
return "CONNECT"
case CONNACK:
return "CONNACK"
case SEND:
return "SEND"
case SENDACK:
return "SENDACK"
case RECV:
return "RECV"
case RECVACK:
return "RECVACK"
case PING:
return "PING"
case PONG:
return "PONG"
case DISCONNECT:
return "DISCONNECT"
case SUB:
return "SUB"
case SUBACK:
return "SUBACK"
}
return fmt.Sprintf("UNKNOWN[%d]", p)
}
// ReasonCode 原因码
type ReasonCode uint8
const (
// ReasonUnknown 未知错误
ReasonUnknown ReasonCode = iota
// ReasonSuccess 成功
ReasonSuccess
// ReasonAuthFail 认证失败
ReasonAuthFail
// ReasonSubscriberNotExist 订阅者在频道内不存在
ReasonSubscriberNotExist
// ReasonInBlacklist 在黑名单列表里
ReasonInBlacklist
// ReasonChannelNotExist 频道不存在
ReasonChannelNotExist
// ReasonUserNotOnNode 用户没在节点上
ReasonUserNotOnNode
// ReasonSenderOffline // 发送者离线了,这条消息将发不成功
ReasonSenderOffline
// ReasonMsgKeyError 消息key错误 说明消息不合法
ReasonMsgKeyError
// ReasonPayloadDecodeError payload解码失败
ReasonPayloadDecodeError
// ReasonForwardSendPacketError 转发发送包失败
ReasonForwardSendPacketError
// ReasonNotAllowSend 不允许发送消息
ReasonNotAllowSend
// ReasonConnectKick 连接被踢
ReasonConnectKick
// ReasonNotInWhitelist 没在白名单内
ReasonNotInWhitelist
// 查询用户token错误
ReasonQueryTokenError
// 系统错误
ReasonSystemError
// 错误的频道ID
ReasonChannelIDError
// ReasonNodeMatchError 节点匹配错误
ReasonNodeMatchError
// ReasonNodeNotMatch 节点不匹配
ReasonNodeNotMatch
ReasonBan // 频道被封禁
ReasonNotSupportHeader // 不支持的header
ReasonClientKeyIsEmpty // clientKey 是空的
ReasonRateLimit // 速率限制
ReasonNotSupportChannelType // 不支持的频道类型
ReasonDisband // 频道已解散
)
func (r ReasonCode) String() string {
switch r {
case ReasonUnknown:
return "ReasonUnknown"
case ReasonSuccess:
return "ReasonSuccess"
case ReasonAuthFail:
return "ReasonAuthFail"
case ReasonSubscriberNotExist:
return "ReasonSubscriberNotExist"
case ReasonNotAllowSend:
return "ReasonNotAllowSend"
case ReasonInBlacklist:
return "ReasonInBlacklist"
case ReasonChannelNotExist:
return "ReasonChannelNotExist"
case ReasonUserNotOnNode:
return "ReasonUserNotOnNode"
case ReasonSenderOffline:
return "ReasonSenderOffline"
case ReasonMsgKeyError:
return "ReasonMsgKeyError"
case ReasonPayloadDecodeError:
return "ReasonPayloadDecodeError"
case ReasonForwardSendPacketError:
return "ReasonForwardSendPacketError"
case ReasonConnectKick:
return "ReasonConnectKick"
case ReasonNotInWhitelist:
return "ReasonNotInWhitelist"
case ReasonQueryTokenError:
return "ReasonQueryTokenError"
case ReasonSystemError:
return "ReasonSystemError"
case ReasonChannelIDError:
return "ReasonChannelIDError"
case ReasonClientKeyIsEmpty:
return "ReasonClientKeyIsEmpty"
case ReasonRateLimit:
return "ReasonRateLimit"
case ReasonDisband:
return "ReasonDisband"
}
return fmt.Sprintf("UNKNOWN[%d]", r)
}
// Byte 转换为byte
func (r ReasonCode) Byte() byte {
return byte(r)
}
// DeviceFlag 设备类型
type DeviceFlag uint8
const (
// APP APP
APP DeviceFlag = iota
// WEB WEB
WEB = 1
// PC PC
PC = 2
// SYSTEM 系统
SYSTEM = 99
)
// DeviceLevel 设备等级
type DeviceLevel uint8
const (
// DeviceLevelSlave 从设备
DeviceLevelSlave DeviceLevel = 0
// DeviceLevelMaster 主设备
DeviceLevelMaster DeviceLevel = 1
)
func (r DeviceLevel) String() string {
switch r {
case DeviceLevelMaster:
return "Master"
case DeviceLevelSlave:
return "Slave"
}
return fmt.Sprintf("Unknown[%d]", r)
}
// ToUint8 转换为uint8
func (r DeviceFlag) ToUint8() uint8 {
return uint8(r)
}
func (r DeviceFlag) String() string {
switch r {
case APP:
return "APP"
case WEB:
return "WEB"
case SYSTEM:
return "SYSTEM"
}
return fmt.Sprintf("%d", r)
}
// Frame 接口
type Frame interface {
GetFrameType() FrameType
GetRemainingLength() uint32
// GetPersist 是否存储
GetNoPersist() bool
// GetRedDot 是否显示红点
GetRedDot() bool
// GetsyncOnce 是否只被同步一次
GetsyncOnce() bool
// 是否是重发的消息
GetDUP() bool
GetFrameSize() int64 // 总个frame的大小(不参与编码解码)
GetHasServerVersion() bool // 是否有服务端版本 connack包用到
}
type Channel struct {
ChannelID string `json:"channel_id"`
ChannelType uint8 `json:"channel_type"`
}
const (
SettingByteSize = 1 // setting固定大小
StringFixLenByteSize = 2 // 字符串可变大小
ClientSeqByteSize = 4 // clientSeq的大小
ChannelTypeByteSize = 1 // channelType的大小
VersionByteSize = 1 // version的大小
DeviceFlagByteSize = 1
ClientTimestampByteSize = 8
TimeDiffByteSize = 8
ReasonCodeByteSize = 1
MessageIDByteSize = 8
MessageSeqByteSize = 4
TimestampByteSize = 4
ActionByteSize = 1
StreamSeqByteSize = 4
StreamFlagByteSize = 1
ExpireByteSize = 4
NodeIdByteSize = 8
)
const (
// ChannelTypePerson 个人频道
ChannelTypePerson uint8 = 1
// ChannelTypeGroup 群频道
ChannelTypeGroup uint8 = 2 // 群组频道
ChannelTypeCustomerService uint8 = 3 // 客服频道
ChannelTypeCommunity uint8 = 4 // 社区频道
ChannelTypeCommunityTopic uint8 = 5 // 社区话题频道
ChannelTypeInfo uint8 = 6 // 资讯频道(有临时订阅者的概念,查看资讯的时候加入临时订阅,退出资讯的时候退出临时订阅)
ChannelTypeData uint8 = 7 // 数据频道
)