-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtypes.go
158 lines (132 loc) · 3.62 KB
/
types.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
package ws
import (
"bytes"
"encoding/json"
"net"
"net/url"
"sync"
"time"
"github.com/gorilla/websocket"
log "github.com/sirupsen/logrus"
)
const (
// Time allowed to write a message to the peer.
writeWait = 5 * time.Second
readTimeout = 5 * time.Second
// Maximum message size allowed from peer.
maxMessageSize = 8192
// Time to wait before force close on connection.
closeGracePeriod = 1 * time.Second
// Reserved msg types & sequence
msgNoResponse = 0
msgSuccess = 1
msgAuthentication = 2
msgReserved = 15
MsgClient = 16
// First bit is used indicate response msg
msgSeqNew = 0x00
msgSeqResponse = 0x80
)
var (
NoResponse = WSMsg{0x00, msgNoResponse}
AutoRedial bool = true
)
type common interface {
}
type WSServer interface {
Accept(wsConn *WSConn) error
// Process(msg *WSMsg) error
WSClient
}
type WSClient interface {
BeforeRedial()
AfterRedial(wsConn *WSConn)
Process(clientId string, msg WSMsg) (response WSMsg, err error)
Closed(wsConn *WSConn)
}
type WSConn struct {
c *websocket.Conn
url url.URL // connection url; used for restablishing connection
RemoteIP net.IP // store the client public IP on the server side
ClientId string // store the device id on the server side
writeMutex sync.Mutex
readMutex sync.Mutex
readChannel chan WSMsg
callback WSClient
msgSeq uint8
closing bool
lastUpdated time.Time
}
// WSMsg is a slice, so pass it by value to all
type WSMsg []byte
func (w WSMsg) Sequence() uint8 { return uint8(w[0]) & 0x7f }
func (w WSMsg) Type() uint8 { return uint8(w[1]) }
func (w WSMsg) Data() []byte { return w[2:] }
func (w WSMsg) setSequence(seq uint8) { w[0] = seq }
func (w WSMsg) IsResponse() bool {
if w[0]&msgSeqResponse == msgSeqResponse {
return true
} else {
return false
}
}
//Encode will add the data struct to the msg; It uses json encoding
func Encode(msgType uint8, token *string, data interface{}) (msg WSMsg, err error) {
var buf bytes.Buffer
return encode(false, buf, msgSeqNew, msgType, token, data)
}
// EncodeBytes will add the raw []byte to the msg
func EncodeBytes(msgType uint8, token *string, data []byte) (msg WSMsg, err error) {
var buf bytes.Buffer
return encode(true, buf, msgSeqNew, msgType, token, data)
}
//EncodeResponse will reuse previous message
func EncodeResponse(old WSMsg, data interface{}) (msg WSMsg, err error) {
buf := bytes.NewBuffer(old)
buf.Reset()
return encode(false, *buf, old.Sequence()|msgSeqResponse, old.Type(), nil, data)
}
func encode(raw bool, buf bytes.Buffer, seq uint8, msgType uint8, token *string, data interface{}) (msg WSMsg, err error) {
if token == nil {
var noToken = ""
token = &noToken
}
buf.WriteByte(seq)
buf.WriteByte(msgType)
enc := json.NewEncoder(&buf)
if err = enc.Encode(token); err != nil {
log.Error("WS encode token error:", err)
return nil, err
}
if data != nil {
if raw {
buf.Write(data.([]byte))
// log.Info("using []byte with no encoding", buf.Bytes())
} else {
if err = enc.Encode(data); err != nil {
log.Error("WS json encode error:", err)
return nil, err
}
}
}
msg = WSMsg(buf.Bytes())
return
}
func (w WSMsg) Decode(token *string, data interface{}) error {
empty := ""
dec := json.NewDecoder(bytes.NewBuffer(w[2:]))
if token == nil { // caller is not interested in token
token = &empty
}
if err := dec.Decode(&token); err != nil {
log.Error("WS decode token error: ", err)
return err
}
if data != nil {
if err := dec.Decode(data); err != nil && err.Error() != "EOF" {
log.Error("WS data decode error: ", err, w)
return err
}
}
return nil
}