aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-12-06 20:39:47 +0100
committerHimbeer <himbeer@disroot.org>2024-12-07 11:22:54 +0100
commit162faad9f636263cc27413358af18de725db66d9 (patch)
treeb8de1a5559fee82ba93edb37898a3edfcff4b1ed
parentfed47e8f13cf051c2f09b08112c513deb08b47a1 (diff)
Implement modchannel plugin API between clients and proxy
-rw-r--r--plugin_modchan.go96
-rw-r--r--process.go16
2 files changed, 112 insertions, 0 deletions
diff --git a/plugin_modchan.go b/plugin_modchan.go
new file mode 100644
index 0000000..446a37f
--- /dev/null
+++ b/plugin_modchan.go
@@ -0,0 +1,96 @@
+package proxy
+
+import (
+ "sync"
+
+ "github.com/HimbeerserverDE/mt"
+)
+
+var (
+ modChanSubscribers map[string][]*ClientConn
+ modChanSubscriberMu sync.RWMutex
+)
+
+var (
+ onCltModChanMsg []func(string, *ClientConn, string) bool
+ onCltModChanMsgMu sync.RWMutex
+ onCltModChanMsgOnce sync.Once
+)
+
+// SendModChanMsg sends a message to all subscribed clients on a modchannel.
+func SendModChanMsg(channel, msg string) {
+ modChanSubscriberMu.RLock()
+ defer modChanSubscriberMu.RUnlock()
+
+ subs, _ := modChanSubscribers[channel]
+ for _, cc := range subs {
+ cc.SendCmd(&mt.ToCltModChanMsg{
+ Channel: channel,
+ Msg: msg,
+ })
+ }
+}
+
+// RegisterOnCltModChanMsg registers a handler that is called
+// when a client sends a message on a modchannel.
+// If any handler returns true, the message is not forwarded
+// to the upstream server.
+func RegisterOnCltModChanMsg(handler func(string, *ClientConn, string) bool) {
+ onCltModChanMsgMu.Lock()
+ defer onCltModChanMsgMu.Unlock()
+
+ onCltModChanMsg = append(onCltModChanMsg, handler)
+}
+
+func cltLeaveModChan(cc *ClientConn, channel string) {
+ modChanSubscriberMu.Lock()
+ defer modChanSubscriberMu.Unlock()
+
+ for i, sub := range modChanSubscribers[channel] {
+ if sub == cc {
+ modChanSubscribers[channel] = append(modChanSubscribers[channel][:i], modChanSubscribers[channel][i+1:]...)
+ break
+ }
+ }
+}
+
+func cltLeaveModChans(cc *ClientConn) {
+ modChanSubscriberMu.Lock()
+ defer modChanSubscriberMu.Unlock()
+
+ for ch := range modChanSubscribers {
+ for i, sub := range modChanSubscribers[ch] {
+ if sub == cc {
+ modChanSubscribers[ch] = append(modChanSubscribers[ch][:i], modChanSubscribers[ch][i+1:]...)
+ break
+ }
+ }
+ }
+}
+
+func handleCltModChanMsg(cc *ClientConn, cmd *mt.ToSrvMsgModChan) bool {
+ onCltModChanMsgMu.RLock()
+ defer onCltModChanMsgMu.RUnlock()
+
+ subs, _ := modChanSubscribers[cmd.Channel]
+ for _, sub := range subs {
+ sub.SendCmd(&mt.ToCltModChanMsg{
+ Channel: cmd.Channel,
+ Sender: cc.Name(),
+ Msg: cmd.Msg,
+ })
+ }
+
+ drop := false
+ for _, handler := range onCltModChanMsg {
+ if handler(cmd.Channel, cc, cmd.Msg) {
+ drop = true
+ }
+ }
+
+ return drop
+}
+
+func init() {
+ modChanSubscribers = make(map[string][]*ClientConn)
+}
diff --git a/process.go b/process.go
index a68238c..05b16fe 100644
--- a/process.go
+++ b/process.go
@@ -12,6 +12,10 @@ import (
)
func (cc *ClientConn) process(pkt mt.Pkt) {
+ defer func() {
+ cltLeaveModChans(cc)
+ }()
+
srv := cc.server()
forward := func(pkt mt.Pkt) {
@@ -484,6 +488,18 @@ func (cc *ClientConn) process(pkt mt.Pkt) {
if handleOnPlayerReceiveFields(cc, cmd) {
return
}
+ case *mt.ToSrvJoinModChan:
+ modChanSubscriberMu.Lock()
+ defer modChanSubscriberMu.Unlock()
+
+ subs, _ := modChanSubscribers[cmd.Channel]
+ modChanSubscribers[cmd.Channel] = append(subs, cc)
+ case *mt.ToSrvLeaveModChan:
+ cltLeaveModChan(cc, cmd.Channel)
+ case *mt.ToSrvMsgModChan:
+ if handleCltModChanMsg(cc, cmd) {
+ return
+ }
}
forward(pkt)