Skip to content

Commit

Permalink
Merge pull request #62 from kmille/development
Browse files Browse the repository at this point in the history
Improve error handling if we are disconnected from the IRC server. Fixes #47
  • Loading branch information
fleaz committed Mar 11, 2021
2 parents 8fca0bc + fe23e4e commit 50cdd97
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 22 deletions.
28 changes: 8 additions & 20 deletions irc.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"io/ioutil"
"strings"
"sync"
"time"

"github.com/sirupsen/logrus"
Expand All @@ -16,10 +15,7 @@ import (
"github.com/spf13/viper"
)

var (
client *girc.Client
clientLock = &sync.RWMutex{}
)
var client *girc.Client

func ircConnection(config *viper.Viper, channelList []string) {
clientConfig := girc.Config{
Expand Down Expand Up @@ -89,12 +85,10 @@ func ircConnection(config *viper.Viper, channelList []string) {
}
}

clientLock.Lock()
client = girc.New(clientConfig)

client.Handlers.Add(girc.CONNECTED, func(c *girc.Client, e girc.Event) {
log.Info("Sucessfully connected to the IRC server. Starting to join channel.")
clientLock.Unlock()
for _, name := range removeDuplicates(channelList) {
joinChannel(name)
}
Expand All @@ -105,7 +99,7 @@ func ircConnection(config *viper.Viper, channelList []string) {
log.WithFields(log.Fields{
"Event": e.String(),
}).Debug("Received a PRIMSG")
message := "Hi. I'm a CptHook bot. Visit https://github.com/fleaz/CptHook to learn more"
message := "Hi. I'm a CptHook bot. Visit https://github.com/fleaz/CptHook to learn more."
if version == "dev" {
message += fmt.Sprintf(" I was compiled by hand at %v", date)
} else {
Expand All @@ -120,16 +114,13 @@ func ircConnection(config *viper.Viper, channelList []string) {

log.Info("Connecting to IRC server")
for {
// client.Connect() blocks. It returns nil if we call a client.Close() which we never do.
// client.Connect() blocks while we are connected.
// If the the connection is dropped/broken (recognized if we don't get a PONG 60 seconds
// after we sent a PING) an error is returned.
err := client.Connect()
// FIXME: if client.Connect() fails twice without going in state connected our handler is
// not called. This means that the lock is still acquired and we will hang here forever.
clientLock.Lock()
log.Warnf("Connection terminated: %s", err)
log.Warn("Reconnecting in 30 seconds...")
time.Sleep(30 * time.Second)
log.Warnf("Connection terminated. Reason: %s\n", err)
log.Warn("Reconnecting in 10 seconds...")
time.Sleep(10 * time.Second)
}

}
Expand Down Expand Up @@ -164,9 +155,8 @@ func channelReceiver() {
}).Debug("IRC handler received a message")
joinChannel(elem.Channel)
for _, message := range elem.Messages {
clientLock.RLock()
client.Cmd.Message(elem.Channel, message)
clientLock.RUnlock()

}
}
}
Expand All @@ -181,8 +171,6 @@ func joinChannel(newChannel string) {
log.WithFields(log.Fields{
"channel": newChannel,
}).Info("Need to join a new channel")

clientLock.RLock()
client.Cmd.Join(newChannel)
clientLock.RUnlock()

}
20 changes: 18 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
)

var (
inputChannel = make(chan input.IRCMessage, 10)
inputChannel = make(chan input.IRCMessage, 30)
version = "dev"
commit = "none"
date = time.Now().Format(time.RFC3339)
Expand Down Expand Up @@ -100,6 +100,22 @@ func loggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
"host": r.Host,
"uri": r.URL,
}).Debug("Received HTTP request")

next.ServeHTTP(w, r)
})
}

func ircCheckMiddleware(next http.HandlerFunc) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !client.IsConnected() {
log.WithFields(log.Fields{
"remote": r.RemoteAddr,
"uri": r.URL,
}).Warn("IRC server is disconnected. Dropping incoming HTTP request")
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("IRC server disconnected"))
return
}
next.ServeHTTP(w, r)
})
}
Expand Down Expand Up @@ -142,7 +158,7 @@ func main() {
configPath := fmt.Sprintf("modules.%s", blockName)
module.Init(viper.Sub(configPath), &inputChannel)
channelList = append(channelList, module.GetChannelList()...)
http.HandleFunc(blockConfig.Endpoint, loggingMiddleware(module.GetHandler()))
http.HandleFunc(blockConfig.Endpoint, loggingMiddleware(ircCheckMiddleware(module.GetHandler())))
}

// Start IRC connection
Expand Down

0 comments on commit 50cdd97

Please sign in to comment.