reliability improvements

die on mumble disconnect
drop packets if channel is full
This commit is contained in:
Tyler Stiene 2020-11-04 01:12:43 -05:00
parent 8d9df9e95b
commit 33e3ea70a4
6 changed files with 84 additions and 57 deletions

View File

@ -4,7 +4,7 @@ mumble-discord-bridge: $(GOFILES)
go build -o $@ $(GOFILES) go build -o $@ $(GOFILES)
docker-latest: docker-latest:
docker build . docker build -t stieneee/mumble-discord-bridge:latest .
docker push stieneee/mumble-bridge-latest docker push stieneee/mumble-bridge-latest
clean: clean:

View File

@ -2,7 +2,7 @@ package main
import ( import (
"fmt" "fmt"
"os" "log"
"sync" "sync"
"time" "time"
@ -28,9 +28,9 @@ var OnError = func(str string, err error) {
prefix := "dgVoice: " + str prefix := "dgVoice: " + str
if err != nil { if err != nil {
os.Stderr.WriteString(prefix + ": " + err.Error()) log.Println(prefix + ": " + err.Error())
} else { } else {
os.Stderr.WriteString(prefix) log.Println(prefix)
} }
} }
@ -47,7 +47,7 @@ func discordSendPCM(v *discordgo.VoiceConnection, pcm <-chan []int16) {
opusEncoder, err := gopus.NewEncoder(frameRate, channels, gopus.Audio) opusEncoder, err := gopus.NewEncoder(frameRate, channels, gopus.Audio)
if err != nil { if err != nil {
OnError("NewEncoder Error", err) OnError("NewEncoder Error", err)
return panic(err)
} }
ticker := time.NewTicker(20 * time.Millisecond) ticker := time.NewTicker(20 * time.Millisecond)
@ -68,12 +68,12 @@ func discordSendPCM(v *discordgo.VoiceConnection, pcm <-chan []int16) {
opus, err := opusEncoder.Encode(append(r1, r2...), frameSize, maxBytes) opus, err := opusEncoder.Encode(append(r1, r2...), frameSize, maxBytes)
if err != nil { if err != nil {
OnError("Encoding Error", err) OnError("Encoding Error", err)
return continue
} }
if v.Ready == false || v.OpusSend == nil { if v.Ready == false || v.OpusSend == nil {
OnError(fmt.Sprintf("Discordgo not ready for opus packets. %+v : %+v", v.Ready, v.OpusSend), nil) OnError(fmt.Sprintf("Discordgo not ready for opus packets. %+v : %+v", v.Ready, v.OpusSend), nil)
return continue
} }
v.OpusSend <- opus v.OpusSend <- opus
@ -94,13 +94,13 @@ func discordReceivePCM(v *discordgo.VoiceConnection) {
for { for {
if v.Ready == false || v.OpusRecv == nil { if v.Ready == false || v.OpusRecv == nil {
OnError(fmt.Sprintf("Discordgo not to receive opus packets. %+v : %+v", v.Ready, v.OpusSend), nil) OnError(fmt.Sprintf("Discordgo not to receive opus packets. %+v : %+v", v.Ready, v.OpusSend), nil)
return continue
} }
p, ok := <-v.OpusRecv p, ok := <-v.OpusRecv
if !ok { if !ok {
fmt.Println("Opus not ok") log.Println("Opus not ok")
return continue
} }
discordMutex.Lock() discordMutex.Lock()
@ -178,7 +178,12 @@ func fromDiscordMixer(toMumble chan<- gumble.AudioBuffer) {
} }
if sendAudio { if sendAudio {
toMumble <- outBuf select {
case toMumble <- outBuf:
default:
log.Println("toMumble buffer full. Dropping packet")
}
} }
} }
} }

View File

@ -0,0 +1,13 @@
version: "3"
services:
mumble-discord-bridge:
image: stieneee/mumble-discord-bridge
restart: unless-stopped
environment:
- MUMBLE_ADDRESS=example.com"
- MUMBLE_USERNAME=discord-bridge
- MUMBLE_PASSWORD=password
- DISCORD_TOKEN=token
- DISCORD_GID=gid
- DISCORD_CID=cid

View File

@ -1,13 +0,0 @@
version: "3.8"
services:
mumble-discord-bridge:
image: stieneee/mumble-discord-bridge
restart: always
environment:
- MUMBLE_ADDRESS=
- MUMBLE_USERNAME=
- MUMBLE_PASSWORD=
- DISCORD_TOKEN=
- DISCORD_GID=
- DISCORD_CID=

82
main.go
View File

@ -86,6 +86,35 @@ func main() {
log.Fatalln("missing discord cid") log.Fatalln("missing discord cid")
} }
// DISCORD Setup
discord, err := discordgo.New("Bot " + *discordToken)
if err != nil {
log.Println(err)
return
}
// Open Websocket
discord.LogLevel = 2
err = discord.Open()
if err != nil {
log.Println(err)
return
}
defer discord.Close()
log.Println("Discord Bot Connected")
dgv, err := discord.ChannelVoiceJoin(*discordGID, *discordCID, false, false)
if err != nil {
log.Println(err)
return
}
defer dgv.Speaking(false)
defer dgv.Close()
discord.ShouldReconnectOnError = true
// MUMBLE Setup // MUMBLE Setup
config := gumble.NewConfig() config := gumble.NewConfig()
@ -100,41 +129,21 @@ func main() {
log.Println(err) log.Println(err)
return return
} }
defer mumble.Disconnect()
// Shared Channels // Shared Channels
// Shared channels pass PCM information in 10ms chunks [480]int16 // Shared channels pass PCM information in 10ms chunks [480]int16
var toMumble = mumble.AudioOutgoing() var toMumble = mumble.AudioOutgoing()
var toDiscord = make(chan []int16, 100) var toDiscord = make(chan []int16, 100)
var die = make(chan bool)
go m.fromMumbleMixer(toDiscord)
config.AudioListeners.Attach(m)
log.Println("Mumble Connected") log.Println("Mumble Connected")
// DISCORD Setup // Start Passing Between
// Mumble
discord, err := discordgo.New("Bot " + *discordToken) go m.fromMumbleMixer(toDiscord)
if err != nil { config.AudioListeners.Attach(m)
log.Println(err) //Discord
return
}
// Open Websocket
err = discord.Open()
if err != nil {
log.Println(err)
return
}
log.Println("Discord Bot Connected")
dgv, err := discord.ChannelVoiceJoin(*discordGID, *discordCID, false, false)
if err != nil {
log.Println(err)
return
}
go discordReceivePCM(dgv) go discordReceivePCM(dgv)
go fromDiscordMixer(toMumble) go fromDiscordMixer(toMumble)
go discordSendPCM(dgv, toDiscord) go discordSendPCM(dgv, toDiscord)
@ -143,12 +152,21 @@ func main() {
c := make(chan os.Signal) c := make(chan os.Signal)
signal.Notify(c, os.Interrupt) signal.Notify(c, os.Interrupt)
go func() {
ticker := time.NewTicker(500 * time.Millisecond)
for {
<-ticker.C
if mumble.State() != 2 {
log.Println("Lost mumble connection " + strconv.Itoa(int(mumble.State())))
die <- true
}
}
}()
select { select {
case sig := <-c: case sig := <-c:
log.Printf("\nGot %s signal. Ending Mumble-Bridge\n", sig) log.Printf("\nGot %s signal. Terminating Mumble-Bridge\n", sig)
mumble.Disconnect() case <-die:
dgv.Speaking(false) log.Println("\nGot internal die request. Terminating Mumble-Bridge")
dgv.Close()
discord.Close()
} }
} }

View File

@ -86,7 +86,11 @@ func (m MumbleDuplex) fromMumbleMixer(toDiscord chan []int16) {
} }
if sendAudio { if sendAudio {
toDiscord <- outBuf select {
case toDiscord <- outBuf:
default:
log.Println("toDiscord buffer full. Dropping packet")
}
} }
} }
} }