-
Notifications
You must be signed in to change notification settings - Fork 19
/
wprotov1.go
153 lines (130 loc) · 2.99 KB
/
wprotov1.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
package cocaine12
import (
"fmt"
)
const (
v1Handshake = 0
v1Heartbeat = 0
v1Invoke = 0
v1Write = 0
v1Error = 1
v1Close = 2
v1Terminate = 1
v1UtilitySession = 1
)
type v1Protocol struct {
maxSession uint64
}
func newV1Protocol() protocolDispather {
return &v1Protocol{
maxSession: 1,
}
}
func (v *v1Protocol) onMessage(p protocolHandler, msg *Message) error {
if msg.Session == v1UtilitySession {
return v.dispatchUtilityMessage(p, msg)
}
if v.maxSession < msg.Session {
// It must be Invkoke
if msg.MsgType != v1Invoke {
return fmt.Errorf("new session %d must start from invoke type %d, not %d\n",
msg.Session, v1Invoke, msg.MsgType)
}
v.maxSession = msg.Session
return p.onInvoke(msg)
}
switch msg.MsgType {
case v1Write:
p.onChunk(msg)
case v1Close:
p.onChoke(msg)
case v1Error:
p.onError(msg)
default:
return fmt.Errorf("an invalid message type: %d, message %v", msg.MsgType, msg)
}
return nil
}
func (v *v1Protocol) isChunk(msg *Message) bool {
return msg.MsgType == v1Write
}
func (v *v1Protocol) dispatchUtilityMessage(p protocolHandler, msg *Message) error {
switch msg.MsgType {
case v1Heartbeat:
p.onHeartbeat(msg)
case v1Terminate:
p.onTerminate(msg)
default:
return fmt.Errorf("an invalid utility message type %d", msg.MsgType)
}
return nil
}
func (v *v1Protocol) newHandshake(id string) *Message {
return newHandshakeV1(id)
}
func (v *v1Protocol) newHeartbeat() *Message {
return newHeartbeatV1()
}
func (v *v1Protocol) newChoke(session uint64) *Message {
return newChokeV1(session)
}
func (v *v1Protocol) newChunk(session uint64, data []byte) *Message {
return newChunkV1(session, data)
}
func (v *v1Protocol) newError(session uint64, category, code int, message string) *Message {
return newErrorV1(session, category, code, message)
}
func newHandshakeV1(id string) *Message {
return &Message{
CommonMessageInfo: CommonMessageInfo{
Session: v1UtilitySession,
MsgType: v1Handshake,
},
Payload: []interface{}{id},
}
}
func newHeartbeatV1() *Message {
return &Message{
CommonMessageInfo: CommonMessageInfo{
Session: v1UtilitySession,
MsgType: v1Heartbeat,
},
Payload: []interface{}{},
}
}
func newInvokeV1(session uint64, event string) *Message {
return &Message{
CommonMessageInfo: CommonMessageInfo{
Session: session,
MsgType: v1Invoke,
},
Payload: []interface{}{event},
}
}
func newChunkV1(session uint64, data []byte) *Message {
return &Message{
CommonMessageInfo: CommonMessageInfo{
Session: session,
MsgType: v1Write,
},
Payload: []interface{}{data},
}
}
func newErrorV1(session uint64, category, code int, message string) *Message {
return &Message{
CommonMessageInfo: CommonMessageInfo{
Session: session,
MsgType: v1Error,
},
Payload: []interface{}{[2]int{category, code}, message},
}
}
func newChokeV1(session uint64) *Message {
return &Message{
CommonMessageInfo: CommonMessageInfo{
Session: session,
MsgType: v1Close,
},
Payload: []interface{}{},
}
}