-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathclient_conn.go
169 lines (129 loc) · 3.19 KB
/
client_conn.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
package proxy
import (
"errors"
"log"
"net"
"sync"
"time"
"github.com/HimbeerserverDE/mt"
"github.com/HimbeerserverDE/mt/rudp"
)
type clientState uint8
const (
csCreated clientState = iota
csInit
csActive
csSudo
)
// A ClientConn is a connection to a minetest client.
type ClientConn struct {
mt.Peer
created time.Time
srv *ServerConn
mu sync.RWMutex
logger *log.Logger
cstate clientState
cstateMu sync.RWMutex
name string
initCh chan struct{}
hopMu sync.Mutex
auth struct {
method mt.AuthMethods
salt, srpA, srpB, srpM, srpK []byte
}
new bool
fallbackFrom string
whyKicked *mt.ToCltKick
lang string
major, minor, patch uint8
reservedVer uint8
versionStr string
formspecVer uint16
denyPools map[string]struct{}
itemDefs []mt.ItemDef
aliases []struct{ Alias, Orig string }
nodeDefs []mt.NodeDef
p0Map param0Map
p0SrvMap param0SrvMap
media []mediaFile
playerCAO, currentCAO mt.AOID
playerListInit bool
modChs map[string]struct{}
modChsMu sync.RWMutex
cltInfo *mt.ToSrvCltInfo
FormspecPrepend string
}
// Name returns the player name of the ClientConn.
func (cc *ClientConn) Name() string { return cc.name }
// IsNew reports whether a new account was registered for the ClientConn.
func (cc *ClientConn) IsNew() bool { return cc.new }
func (cc *ClientConn) hasPlayerCAO() bool { return cc.playerCAO != 0 }
func (cc *ClientConn) server() *ServerConn {
cc.mu.RLock()
defer cc.mu.RUnlock()
return cc.srv
}
// ServerName returns the name of the current upstream server
// of the ClientConn. It is empty if there is no upstream connection.
func (cc *ClientConn) ServerName() string {
srv := cc.server()
if srv != nil {
return srv.name
}
return ""
}
func (cc *ClientConn) state() clientState {
cc.cstateMu.RLock()
defer cc.cstateMu.RUnlock()
return cc.cstate
}
func (cc *ClientConn) setState(state clientState) {
cc.cstateMu.Lock()
defer cc.cstateMu.Unlock()
cc.cstate = state
}
// Init returns a channel that is closed
// when the ClientConn enters the csActive state.
func (cc *ClientConn) Init() <-chan struct{} { return cc.initCh }
// Log logs an interaction with the ClientConn.
// dir indicates the direction of the interaction.
func (cc *ClientConn) Log(dir string, v ...interface{}) {
cc.logger.Println(append([]interface{}{dir}, v...)...)
}
// CltInfo returns the ToSrvCltInfo known about the client.
func (cc *ClientConn) ToSrvCltInfo() *mt.ToSrvCltInfo { return cc.cltInfo }
func handleClt(cc *ClientConn) {
for {
pkt, err := cc.Recv()
if err != nil {
if errors.Is(err, net.ErrClosed) {
if cc.state() == csActive {
handleLeave(cc)
}
if errors.Is(cc.WhyClosed(), rudp.ErrTimedOut) {
cc.Log("<->", "timeout")
} else {
cc.Log("<->", "disconnect")
}
if cc.Name() != "" {
playersMu.Lock()
delete(players, cc.Name())
playersMu.Unlock()
}
if cc.server() != nil {
cc.server().Close()
cc.server().mu.Lock()
cc.server().clt = nil
cc.server().mu.Unlock()
cc.mu.Lock()
cc.srv = nil
cc.mu.Unlock()
}
break
}
cc.Log("->", err)
continue
}
cc.process(pkt)
}
}