forked from External/grumble
import changes
This commit is contained in:
parent
3e7af1e0fe
commit
384ae29dd8
7 changed files with 159 additions and 68 deletions
|
|
@ -90,6 +90,9 @@ type Client struct {
|
||||||
Recording bool
|
Recording bool
|
||||||
PluginContext []byte
|
PluginContext []byte
|
||||||
PluginIdentity string
|
PluginIdentity string
|
||||||
|
|
||||||
|
// CEF
|
||||||
|
ircChannel string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugf implements debug-level printing for Clients.
|
// Debugf implements debug-level printing for Clients.
|
||||||
|
|
@ -187,7 +190,7 @@ func (client *Client) disconnect(kicked bool) {
|
||||||
//
|
//
|
||||||
// In case of a premature disconnect, close the channel so the
|
// In case of a premature disconnect, close the channel so the
|
||||||
// receiver routine can exit correctly.
|
// receiver routine can exit correctly.
|
||||||
if client.state == StateClientSentVersion || client.state == StateClientAuthenticated {
|
if (client.state == StateClientSentVersion || client.state == StateClientAuthenticated) && client.clientReady != nil {
|
||||||
close(client.clientReady)
|
close(client.clientReady)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -588,6 +591,20 @@ func (client *Client) sendChannelList() {
|
||||||
client.sendChannelTree(client.server.RootChannel())
|
client.sendChannelTree(client.server.RootChannel())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *Client) sendWindowedChannel() *Channel {
|
||||||
|
channel, exists := client.server.WindowedChannels[client.ircChannel]
|
||||||
|
if !exists {
|
||||||
|
channel = NewChannel(client.server.nextChanId, client.ircChannel)
|
||||||
|
channel.temporary = true
|
||||||
|
|
||||||
|
client.server.nextChanId++
|
||||||
|
client.server.WindowedChannels[client.ircChannel] = channel
|
||||||
|
log.Print("Made new channel")
|
||||||
|
}
|
||||||
|
client.sendChannelTree(channel)
|
||||||
|
return channel
|
||||||
|
}
|
||||||
|
|
||||||
func (client *Client) sendChannelTree(channel *Channel) {
|
func (client *Client) sendChannelTree(channel *Channel) {
|
||||||
chanstate := &mumbleproto.ChannelState{
|
chanstate := &mumbleproto.ChannelState{
|
||||||
ChannelId: proto.Uint32(uint32(channel.Id)),
|
ChannelId: proto.Uint32(uint32(channel.Id)),
|
||||||
|
|
@ -597,18 +614,6 @@ func (client *Client) sendChannelTree(channel *Channel) {
|
||||||
chanstate.Parent = proto.Uint32(uint32(channel.parent.Id))
|
chanstate.Parent = proto.Uint32(uint32(channel.parent.Id))
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.HasDescription() {
|
|
||||||
if client.Version >= 0x10202 {
|
|
||||||
chanstate.DescriptionHash = channel.DescriptionBlobHashBytes()
|
|
||||||
} else {
|
|
||||||
buf, err := blobStore.Get(channel.DescriptionBlob)
|
|
||||||
if err != nil {
|
|
||||||
panic("Blobstore error.")
|
|
||||||
}
|
|
||||||
chanstate.Description = proto.String(string(buf))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if channel.IsTemporary() {
|
if channel.IsTemporary() {
|
||||||
chanstate.Temporary = proto.Bool(true)
|
chanstate.Temporary = proto.Bool(true)
|
||||||
}
|
}
|
||||||
|
|
@ -626,9 +631,6 @@ func (client *Client) sendChannelTree(channel *Channel) {
|
||||||
client.Panicf("%v", err)
|
client.Panicf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, subchannel := range channel.children {
|
|
||||||
client.sendChannelTree(subchannel)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to do a crypto resync
|
// Try to do a crypto resync
|
||||||
|
|
|
||||||
|
|
@ -313,7 +313,7 @@ func (server *Server) handleChannelStateMessage(client *Client, msg *Message) {
|
||||||
userstate.Session = proto.Uint32(client.Session())
|
userstate.Session = proto.Uint32(client.Session())
|
||||||
userstate.ChannelId = proto.Uint32(uint32(channel.Id))
|
userstate.ChannelId = proto.Uint32(uint32(channel.Id))
|
||||||
server.userEnterChannel(client, channel, userstate)
|
server.userEnterChannel(client, channel, userstate)
|
||||||
server.broadcastProtoMessage(userstate)
|
server.broadcastProtoMessageWithPredicate(userstate, func(cli *Client) bool { return cli.ircChannel == client.ircChannel })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Edit existing channel.
|
// Edit existing channel.
|
||||||
|
|
@ -531,7 +531,7 @@ func (server *Server) handleUserRemoveMessage(client *Client, msg *Message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
userremove.Actor = proto.Uint32(uint32(client.Session()))
|
userremove.Actor = proto.Uint32(uint32(client.Session()))
|
||||||
if err = server.broadcastProtoMessage(userremove); err != nil {
|
if err = server.broadcastProtoMessageWithPredicate(userremove, func(cli *Client) bool { return cli.ircChannel == client.ircChannel }); err != nil {
|
||||||
server.Panicf("Unable to broadcast UserRemove message")
|
server.Panicf("Unable to broadcast UserRemove message")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -874,6 +874,7 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
|
||||||
server.ClearCaches()
|
server.ClearCaches()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server.ergoStateBroadcast(target)
|
||||||
err := server.broadcastProtoMessageWithPredicate(userstate, func(client *Client) bool {
|
err := server.broadcastProtoMessageWithPredicate(userstate, func(client *Client) bool {
|
||||||
return client.Version >= 0x10203
|
return client.Version >= 0x10203
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,15 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"hash"
|
"hash"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -38,7 +42,7 @@ import (
|
||||||
|
|
||||||
// The default port a Murmur server listens on
|
// The default port a Murmur server listens on
|
||||||
const DefaultPort = 64738
|
const DefaultPort = 64738
|
||||||
const DefaultWebPort = 443
|
const DefaultWebPort = 8443
|
||||||
const UDPPacketSize = 1024
|
const UDPPacketSize = 1024
|
||||||
|
|
||||||
const LogOpsBeforeSync = 100
|
const LogOpsBeforeSync = 100
|
||||||
|
|
@ -101,6 +105,7 @@ type Server struct {
|
||||||
|
|
||||||
// Channels
|
// Channels
|
||||||
Channels map[int]*Channel
|
Channels map[int]*Channel
|
||||||
|
WindowedChannels map[string]*Channel
|
||||||
nextChanId int
|
nextChanId int
|
||||||
|
|
||||||
// Users
|
// Users
|
||||||
|
|
@ -122,6 +127,9 @@ type Server struct {
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
*log.Logger
|
*log.Logger
|
||||||
|
|
||||||
|
// CEF
|
||||||
|
ergo net.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
type clientLogForwarder struct {
|
type clientLogForwarder struct {
|
||||||
|
|
@ -137,6 +145,62 @@ func (lf clientLogForwarder) Write(incoming []byte) (int, error) {
|
||||||
return len(incoming), nil
|
return len(incoming), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (server *Server) ergoMessage(action string, ircChannel string, user string, extra ...string) {
|
||||||
|
if server.ergo == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
str := fmt.Sprintf("%s %s %s %s\n", action, ircChannel, user, strings.Join(extra, " "))
|
||||||
|
server.ergo.Write([]byte(str))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) ergoStateBroadcast(client *Client) {
|
||||||
|
// Gooooooooo
|
||||||
|
muteState := b2i(client.SelfMute)
|
||||||
|
muteState |= b2i(client.Mute) << 1
|
||||||
|
deafState := b2i(client.SelfDeaf)
|
||||||
|
deafState |= b2i(client.Deaf) << 1
|
||||||
|
server.ergoMessage("VOICESTATE", client.ircChannel, client.Username, strconv.Itoa(muteState), strconv.Itoa(deafState))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) ergoConnection() {
|
||||||
|
conn, _ := net.Dial("tcp", "127.0.0.1:22843")
|
||||||
|
server.ergo = conn
|
||||||
|
reader := bufio.NewReader(conn)
|
||||||
|
println("Connection established with ergo")
|
||||||
|
for {
|
||||||
|
// read client request data
|
||||||
|
data, err := reader.ReadBytes(byte('\n'))
|
||||||
|
if err != nil {
|
||||||
|
if err != io.EOF {
|
||||||
|
fmt.Println("failed to read data, err:", err)
|
||||||
|
}
|
||||||
|
println("Reconnecting to ergo in 5s")
|
||||||
|
time.Sleep(5000)
|
||||||
|
go server.ergoConnection()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
line := strings.Split(string(data[:len(data)-1]), " ")
|
||||||
|
fmt.Printf("ergo: %+q\n", line)
|
||||||
|
switch line[0] {
|
||||||
|
case "KICK":
|
||||||
|
for _, client := range server.clients {
|
||||||
|
if client.ircChannel == line[1] && client.Username == line[2] {
|
||||||
|
server.RemoveClient(client, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "POLL":
|
||||||
|
channel, ok := server.WindowedChannels[line[1]]
|
||||||
|
if ok {
|
||||||
|
for _, client := range channel.clients {
|
||||||
|
server.ergoStateBroadcast(client)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Allocate a new Murmur instance
|
// Allocate a new Murmur instance
|
||||||
func NewServer(id int64) (s *Server, err error) {
|
func NewServer(id int64) (s *Server, err error) {
|
||||||
s = new(Server)
|
s = new(Server)
|
||||||
|
|
@ -153,11 +217,13 @@ func NewServer(id int64) (s *Server, err error) {
|
||||||
s.nextUserId = 1
|
s.nextUserId = 1
|
||||||
|
|
||||||
s.Channels = make(map[int]*Channel)
|
s.Channels = make(map[int]*Channel)
|
||||||
|
s.WindowedChannels = make(map[string]*Channel)
|
||||||
s.Channels[0] = NewChannel(0, "Root")
|
s.Channels[0] = NewChannel(0, "Root")
|
||||||
s.nextChanId = 1
|
s.nextChanId = 1
|
||||||
|
|
||||||
s.Logger = log.New(logtarget.Default, fmt.Sprintf("[%v] ", s.Id), log.LstdFlags|log.Lmicroseconds)
|
s.Logger = log.New(logtarget.Default, fmt.Sprintf("[%v] ", s.Id), log.LstdFlags|log.Lmicroseconds)
|
||||||
|
|
||||||
|
go s.ergoConnection()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,14 +413,15 @@ func (server *Server) RemoveClient(client *Client, kicked bool) {
|
||||||
if channel != nil {
|
if channel != nil {
|
||||||
channel.RemoveClient(client)
|
channel.RemoveClient(client)
|
||||||
}
|
}
|
||||||
|
server.ergoMessage("PART", client.ircChannel, client.Username)
|
||||||
|
|
||||||
// If the user was not kicked, broadcast a UserRemove message.
|
// If the user was not kicked, broadcast a UserRemove message.
|
||||||
// If the user is disconnect via a kick, the UserRemove message has already been sent
|
// If the user is disconnect via a kick, the UserRemove message has already been sent
|
||||||
// at this point.
|
// at this point.
|
||||||
if !kicked && client.state > StateClientAuthenticated {
|
if !kicked && client.state > StateClientAuthenticated {
|
||||||
err := server.broadcastProtoMessage(&mumbleproto.UserRemove{
|
err := server.broadcastProtoMessageWithPredicate(&mumbleproto.UserRemove{
|
||||||
Session: proto.Uint32(client.Session()),
|
Session: proto.Uint32(client.Session()),
|
||||||
})
|
}, func(cli *Client) bool { return cli.ircChannel == client.ircChannel })
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.Panic("Unable to broadcast UserRemove message for disconnected client.")
|
server.Panic("Unable to broadcast UserRemove message for disconnected client.")
|
||||||
}
|
}
|
||||||
|
|
@ -539,11 +606,33 @@ func (server *Server) handleAuthenticate(client *Client, msg *Message) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if client.user == nil && server.hasServerPassword() {
|
if auth.Password == nil {
|
||||||
if auth.Password == nil || !server.CheckServerPassword(*auth.Password) {
|
|
||||||
client.RejectAuth(mumbleproto.Reject_WrongServerPW, "Invalid server password")
|
client.RejectAuth(mumbleproto.Reject_WrongServerPW, "Invalid server password")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
token, err := jwt.Parse(*auth.Password, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
// Don't forget to validate the alg is what you expect:
|
||||||
|
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
|
||||||
|
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||||
|
}
|
||||||
|
keyData, _ := os.ReadFile(filepath.Join(Args.DataDir, "jwtpub.pem"))
|
||||||
|
key, _ := jwt.ParseRSAPublicKeyFromPEM(keyData)
|
||||||
|
return key, nil
|
||||||
|
})
|
||||||
|
log.Printf("Auth failed: %s", err)
|
||||||
|
if err != nil {
|
||||||
|
client.RejectAuth(mumbleproto.Reject_WrongServerPW, "Invalid server password")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if claims, ok := token.Claims.(jwt.MapClaims); ok {
|
||||||
|
client.ircChannel = claims["channel"].(string)
|
||||||
|
if client.Username != claims["account"].(string) {
|
||||||
|
client.RejectAuth(mumbleproto.Reject_InvalidUsername, "Username doesn't match")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
client.RejectAuth(mumbleproto.Reject_WrongServerPW, "Something was wrong with your JWT")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the cryptstate for the client.
|
// Setup the cryptstate for the client.
|
||||||
|
|
@ -567,7 +656,7 @@ func (server *Server) handleAuthenticate(client *Client, msg *Message) {
|
||||||
|
|
||||||
// Add codecs
|
// Add codecs
|
||||||
client.codecs = auth.CeltVersions
|
client.codecs = auth.CeltVersions
|
||||||
client.opus = auth.GetOpus()
|
client.opus = true // You get Opus. Too bad.
|
||||||
|
|
||||||
client.state = StateClientAuthenticated
|
client.state = StateClientAuthenticated
|
||||||
server.clientAuthenticated <- client
|
server.clientAuthenticated <- client
|
||||||
|
|
@ -615,11 +704,10 @@ func (server *Server) finishAuthenticate(client *Client) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, check whether we need to tell the other connected
|
// Opus gang only.
|
||||||
// clients to switch to a codec so the new guy can actually speak.
|
// server.updateCodecVersions(client)
|
||||||
server.updateCodecVersions(client)
|
|
||||||
|
|
||||||
client.sendChannelList()
|
channel := client.sendWindowedChannel()
|
||||||
|
|
||||||
// Add the client to the host slice for its host address.
|
// Add the client to the host slice for its host address.
|
||||||
host := client.tcpaddr.IP.String()
|
host := client.tcpaddr.IP.String()
|
||||||
|
|
@ -627,14 +715,6 @@ func (server *Server) finishAuthenticate(client *Client) {
|
||||||
server.hclients[host] = append(server.hclients[host], client)
|
server.hclients[host] = append(server.hclients[host], client)
|
||||||
server.hmutex.Unlock()
|
server.hmutex.Unlock()
|
||||||
|
|
||||||
channel := server.RootChannel()
|
|
||||||
if client.IsRegistered() {
|
|
||||||
lastChannel := server.Channels[client.user.LastChannelId]
|
|
||||||
if lastChannel != nil {
|
|
||||||
channel = lastChannel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
userstate := &mumbleproto.UserState{
|
userstate := &mumbleproto.UserState{
|
||||||
Session: proto.Uint32(client.Session()),
|
Session: proto.Uint32(client.Session()),
|
||||||
Name: proto.String(client.ShownName()),
|
Name: proto.String(client.ShownName()),
|
||||||
|
|
@ -676,7 +756,7 @@ func (server *Server) finishAuthenticate(client *Client) {
|
||||||
}
|
}
|
||||||
|
|
||||||
server.userEnterChannel(client, channel, userstate)
|
server.userEnterChannel(client, channel, userstate)
|
||||||
if err := server.broadcastProtoMessage(userstate); err != nil {
|
if err := server.broadcastProtoMessageWithPredicate(userstate, func(cli *Client) bool { return cli.ircChannel == client.ircChannel }); err != nil {
|
||||||
// Server panic?
|
// Server panic?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -702,7 +782,7 @@ func (server *Server) finishAuthenticate(client *Client) {
|
||||||
}
|
}
|
||||||
|
|
||||||
err := client.sendMessage(&mumbleproto.ServerConfig{
|
err := client.sendMessage(&mumbleproto.ServerConfig{
|
||||||
AllowHtml: proto.Bool(server.cfg.BoolValue("AllowHTML")),
|
AllowHtml: proto.Bool(false),
|
||||||
MessageLength: proto.Uint32(server.cfg.Uint32Value("MaxTextMessageLength")),
|
MessageLength: proto.Uint32(server.cfg.Uint32Value("MaxTextMessageLength")),
|
||||||
ImageMessageLength: proto.Uint32(server.cfg.Uint32Value("MaxImageMessageLength")),
|
ImageMessageLength: proto.Uint32(server.cfg.Uint32Value("MaxImageMessageLength")),
|
||||||
})
|
})
|
||||||
|
|
@ -812,6 +892,10 @@ func (server *Server) updateCodecVersions(connecting *Client) {
|
||||||
|
|
||||||
func (server *Server) sendUserList(client *Client) {
|
func (server *Server) sendUserList(client *Client) {
|
||||||
for _, connectedClient := range server.clients {
|
for _, connectedClient := range server.clients {
|
||||||
|
if client.ircChannel != connectedClient.ircChannel {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if connectedClient.state != StateClientReady {
|
if connectedClient.state != StateClientReady {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -1115,6 +1199,8 @@ func (server *Server) userEnterChannel(client *Client, channel *Channel, usersta
|
||||||
if channel.parent != nil {
|
if channel.parent != nil {
|
||||||
server.sendClientPermissions(client, channel.parent)
|
server.sendClientPermissions(client, channel.parent)
|
||||||
}
|
}
|
||||||
|
server.Printf("Broadcasting join: %s %s\n", client.ircChannel, client.Username)
|
||||||
|
server.ergoStateBroadcast(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register a client on the server.
|
// Register a client on the server.
|
||||||
|
|
@ -1231,12 +1317,10 @@ func (server *Server) RemoveChannel(channel *Channel) {
|
||||||
parent := channel.parent
|
parent := channel.parent
|
||||||
delete(parent.children, channel.Id)
|
delete(parent.children, channel.Id)
|
||||||
delete(server.Channels, channel.Id)
|
delete(server.Channels, channel.Id)
|
||||||
chanremove := &mumbleproto.ChannelRemove{
|
// Don't leak this
|
||||||
ChannelId: proto.Uint32(uint32(channel.Id)),
|
// if err := server.broadcastProtoMessage(chanremove); err != nil {
|
||||||
}
|
// server.Panicf("%v", err)
|
||||||
if err := server.broadcastProtoMessage(chanremove); err != nil {
|
//}
|
||||||
server.Panicf("%v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveExpiredBans removes expired bans
|
// RemoveExpiredBans removes expired bans
|
||||||
|
|
@ -1475,18 +1559,18 @@ func (server *Server) Start() (err error) {
|
||||||
if shouldListenWeb {
|
if shouldListenWeb {
|
||||||
// Create HTTP server and WebSocket "listener"
|
// Create HTTP server and WebSocket "listener"
|
||||||
webaddr := &net.TCPAddr{IP: net.ParseIP(host), Port: webport}
|
webaddr := &net.TCPAddr{IP: net.ParseIP(host), Port: webport}
|
||||||
server.webtlscfg = &tls.Config{
|
//server.webtlscfg = &tls.Config{
|
||||||
Certificates: []tls.Certificate{cert},
|
// Certificates: []tls.Certificate{cert},
|
||||||
ClientAuth: tls.NoClientCert,
|
// ClientAuth: tls.NoClientCert,
|
||||||
NextProtos: []string{"http/1.1"},
|
// NextProtos: []string{"http/1.1"},
|
||||||
}
|
//}
|
||||||
server.webwsl = web.NewListener(webaddr, server.Logger)
|
server.webwsl = web.NewListener(webaddr, server.Logger)
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.Handle("/", server.webwsl)
|
mux.Handle("/", server.webwsl)
|
||||||
server.webhttp = &http.Server{
|
server.webhttp = &http.Server{
|
||||||
Addr: webaddr.String(),
|
Addr: webaddr.String(),
|
||||||
Handler: mux,
|
Handler: mux,
|
||||||
TLSConfig: server.webtlscfg,
|
//TLSConfig: server.webtlscfg,
|
||||||
ErrorLog: server.Logger,
|
ErrorLog: server.Logger,
|
||||||
|
|
||||||
// Set sensible timeouts, in case no reverse proxy is in front of Grumble.
|
// Set sensible timeouts, in case no reverse proxy is in front of Grumble.
|
||||||
|
|
@ -1497,7 +1581,7 @@ func (server *Server) Start() (err error) {
|
||||||
IdleTimeout: 2 * time.Minute,
|
IdleTimeout: 2 * time.Minute,
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
err := server.webhttp.ListenAndServeTLS("", "")
|
err := server.webhttp.ListenAndServe()
|
||||||
if err != http.ErrServerClosed {
|
if err != http.ErrServerClosed {
|
||||||
server.Fatalf("Fatal HTTP server error: %v", err)
|
server.Fatalf("Fatal HTTP server error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
8
cmd/grumble/util.go
Normal file
8
cmd/grumble/util.go
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// Stolen from https://dev.to/chigbeef_77/bool-int-but-stupid-in-go-3jb3
|
||||||
|
func b2i(b bool) int {
|
||||||
|
return int(*(*byte)(unsafe.Pointer(&b)))
|
||||||
|
}
|
||||||
|
|
@ -126,7 +126,7 @@ func (vt *VoiceTarget) SendVoiceBroadcast(vb *VoiceBroadcast) {
|
||||||
vt.fromChannelsCache = fromChannels
|
vt.fromChannelsCache = fromChannels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: prevent cross-channel whispering
|
||||||
kind := buf[0] & 0xe0
|
kind := buf[0] & 0xe0
|
||||||
|
|
||||||
if len(fromChannels) > 0 {
|
if len(fromChannels) > 0 {
|
||||||
|
|
|
||||||
1
go.mod
1
go.mod
|
|
@ -3,6 +3,7 @@ module mumble.info/grumble
|
||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||||
github.com/golang/protobuf v1.5.4
|
github.com/golang/protobuf v1.5.4
|
||||||
github.com/gorilla/websocket v1.5.1
|
github.com/gorilla/websocket v1.5.1
|
||||||
golang.org/x/crypto v0.21.0
|
golang.org/x/crypto v0.21.0
|
||||||
|
|
|
||||||
13
go.sum
13
go.sum
|
|
@ -1,17 +1,14 @@
|
||||||
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
|
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
|
||||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+UgTgQZ4pMLzXxi1pSt+/Y=
|
|
||||||
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
|
|
@ -19,7 +16,6 @@ golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
|
@ -33,8 +29,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|
@ -64,6 +58,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue