Add an overall timeout on CAP negotiation

At the moment it just hangs if the server doesn't support CAP. This adds
a 15 second timeout to the CAP negotiation process, after which the
connection continues.

The timeout and error on failed SASL negotiation is preserved.
This commit is contained in:
Russ Garrett 2019-05-12 10:29:21 +01:00
parent 0b3c53b324
commit 2d0ed40435
No known key found for this signature in database
GPG Key ID: 68880BB652AB0570

25
irc.go
View File

@ -36,6 +36,8 @@ const (
VERSION = "go-ircevent v2.1" VERSION = "go-ircevent v2.1"
) )
const CAP_TIMEOUT = time.Second * 15
var ErrDisconnected = errors.New("Disconnect Called") var ErrDisconnected = errors.New("Disconnect Called")
// Read data from a connection. To be used as a goroutine. // Read data from a connection. To be used as a goroutine.
@ -554,16 +556,29 @@ func (irc *Connection) negotiateCaps() error {
close(saslResChan) close(saslResChan)
return res.Err return res.Err
} }
case <-time.After(time.Second * 15): case <-time.After(CAP_TIMEOUT):
close(saslResChan) close(saslResChan)
return errors.New("SASL setup timed out. This shouldn't happen.") // Raise an error if we can't authenticate with SASL.
return errors.New("SASL setup timed out. Does the server support SASL?")
} }
} }
// Wait for all capabilities to be ACKed or NAKed before ending negotiation remaining_caps := len(irc.RequestCaps)
for i := 0; i < len(irc.RequestCaps); i++ {
<-cap_chan select {
case <-cap_chan:
remaining_caps--
case <-time.After(CAP_TIMEOUT):
// The server probably doesn't implement CAP LS, which is "normal".
return nil
} }
// Wait for all capabilities to be ACKed or NAKed before ending negotiation
for remaining_caps > 0 {
<-cap_chan
remaining_caps--
}
irc.pwrite <- fmt.Sprintf("CAP END\r\n") irc.pwrite <- fmt.Sprintf("CAP END\r\n")
return nil return nil