Merge pull request #124 from irccloud/cap-timeout

Add an overall timeout on CAP negotiation
diff --git a/irc.go b/irc.go
index de8f6a5..3c41873 100644
--- a/irc.go
+++ b/irc.go
@@ -36,6 +36,8 @@
 	VERSION = "go-ircevent v2.1"
 )
 
+const CAP_TIMEOUT = time.Second * 15
+
 var ErrDisconnected = errors.New("Disconnect Called")
 
 // Read data from a connection. To be used as a goroutine.
@@ -554,16 +556,29 @@
 				close(saslResChan)
 				return res.Err
 			}
-		case <-time.After(time.Second * 15):
+		case <-time.After(CAP_TIMEOUT):
 			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
-	for i := 0; i < len(irc.RequestCaps); i++ {
-		<-cap_chan
+	remaining_caps := len(irc.RequestCaps)
+
+	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")
 
 	return nil