-
Notifications
You must be signed in to change notification settings - Fork 82
/
tcp_connector.go
130 lines (110 loc) · 2.9 KB
/
tcp_connector.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
package cherryConnector
import (
"github.com/cherry-game/cherry/error"
"github.com/cherry-game/cherry/facade"
"github.com/cherry-game/cherry/logger"
"github.com/cherry-game/cherry/net/packet"
"io"
"io/ioutil"
"net"
)
type (
TCPConnector struct {
address string
listener net.Listener
running bool
certFile string
keyFile string
onConnectListener []cherryFacade.OnConnectListener
}
tcpConn struct {
net.Conn
}
)
func NewTCP(address string) *TCPConnector {
if address == "" {
cherryLogger.Warn("create tcp socket fail. address is null.")
return nil
}
return &TCPConnector{
address: address,
}
}
func NewTCPLTS(address, certFile, keyFile string) *TCPConnector {
if address == "" {
cherryLogger.Warn("create tcp socket fail. address is null.")
return nil
}
if certFile == "" || keyFile == "" {
cherryLogger.Warn("create tcp socket fail. certFile or keyFile is null.")
return nil
}
return &TCPConnector{
address: address,
certFile: certFile,
keyFile: keyFile,
}
}
func (t *TCPConnector) OnStart() {
if len(t.onConnectListener) < 1 {
panic("onConnectListener() not set.")
}
var err error
t.listener, err = GetNetListener(t.address, t.certFile, t.keyFile)
if err != nil {
cherryLogger.Fatalf("failed to listen: %s", err.Error())
}
cherryLogger.Infof("tcp connector listening at address %s", t.address)
if t.certFile != "" || t.keyFile != "" {
cherryLogger.Infof("certFile = %s", t.certFile)
cherryLogger.Infof("keyFile = %s", t.keyFile)
}
t.running = true
for t.running {
conn, err := t.listener.Accept()
if err != nil {
cherryLogger.Errorf("failed to accept TCP connection: %s", err.Error())
continue
}
// open goroutine for new connection
go t.processNewConn(&tcpConn{Conn: conn})
}
}
func (t *TCPConnector) processNewConn(conn cherryFacade.INetConn) {
for _, listener := range t.onConnectListener {
listener(conn)
}
}
// OnStop stops the connector
func (t *TCPConnector) OnStop() {
t.running = false
err := t.listener.Close()
if err != nil {
cherryLogger.Errorf("failed to stop: %s", err.Error())
}
}
func (t *TCPConnector) OnConnect(listener ...cherryFacade.OnConnectListener) {
t.onConnectListener = append(t.onConnectListener, listener...)
}
func (t *tcpConn) GetNextMessage() (b []byte, err error) {
header, err := ioutil.ReadAll(io.LimitReader(t.Conn, int64(cherryPacket.HeadLength)))
if err != nil {
return nil, err
}
// if the header has no data, we can consider it as a closed connection
if len(header) == 0 {
return nil, cherryError.PacketConnectClosed
}
msgSize, _, err := cherryPacket.ParseHeader(header)
if err != nil {
return nil, err
}
msgData, err := ioutil.ReadAll(io.LimitReader(t.Conn, int64(msgSize)))
if err != nil {
return nil, err
}
if len(msgData) < msgSize {
return nil, cherryError.PacketMsgSmallerThanExpected
}
return append(header, msgData...), nil
}