aboutsummaryrefslogtreecommitdiff
path: root/plugin_join_leave.go
blob: baa4ba3cd12e5015a68b5fe46d8fe64bdc5f8d03 (plain) (blame)
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
package proxy

import "sync"

var (
	onJoin     []func(*ClientConn) string
	onJoinMu   sync.Mutex
	onJoinOnce sync.Once
)

var (
	onLeave     []func(*ClientConn)
	onLeaveMu   sync.Mutex
	onLeaveOnce sync.Once
)

// RegisterOnJoin registers a handler that is called
// when a client finishes connecting to the proxy (TOSERVER_CLIENT_READY packet)
// but before it is connected to an upstream server.
// If any handler returns a non-empty string, the client is kicked
// with that message.
// Handlers are run sequentially and block the client's connection
// and packet handling procedure.
func RegisterOnJoin(handler func(*ClientConn) string) {
	initOnJoin()

	onJoinMu.Lock()
	defer onJoinMu.Unlock()

	onJoin = append(onJoin, handler)
}

// RegisterOnLeave registers a handler that is called
// when a client disconnects for any reason after reaching the ready stage.
// Handlers are run sequentially.
func RegisterOnLeave(handler func(*ClientConn)) {
	initOnLeave()

	onLeaveMu.Lock()
	defer onLeaveMu.Unlock()

	onLeave = append(onLeave, handler)
}

func handleJoin(cc *ClientConn) {
	onJoinMu.Lock()
	defer onJoinMu.Unlock()

	for _, handler := range onJoin {
		if msg := handler(cc); msg != "" {
			cc.Kick(msg)
			break
		}
	}
}

func handleLeave(cc *ClientConn) {
	onLeaveMu.Lock()
	defer onLeaveMu.Unlock()

	for _, handler := range onLeave {
		handler(cc)
	}
}

func initOnJoin() {
	onJoinOnce.Do(func() {
		onJoinMu.Lock()
		defer onJoinMu.Unlock()

		onJoin = make([]func(*ClientConn) string, 0)
	})
}

func initOnLeave() {
	onLeaveOnce.Do(func() {
		onLeaveMu.Lock()
		defer onLeaveMu.Unlock()

		onLeave = make([]func(*ClientConn), 0)
	})
}