Each reconnection would add redundant callbacks for CAP and the SASL numerics. This would result in `AUTHENTICATE PLAIN` being sent multiple times (once for each callback), which would confuse the server.
		
			
				
	
	
		
			77 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package irc
 | |
| 
 | |
| import (
 | |
| 	"encoding/base64"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| type SASLResult struct {
 | |
| 	Failed bool
 | |
| 	Err    error
 | |
| }
 | |
| 
 | |
| // Check if a space-separated list of arguments contains a value.
 | |
| func listContains(list string, value string) bool {
 | |
| 	for _, arg_name := range strings.Split(strings.TrimSpace(list), " ") {
 | |
| 		if arg_name == value {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func (irc *Connection) setupSASLCallbacks(result chan<- *SASLResult) (callbacks []CallbackID) {
 | |
| 	id := irc.AddCallback("CAP", func(e *Event) {
 | |
| 		if len(e.Arguments) == 3 {
 | |
| 			if e.Arguments[1] == "LS" {
 | |
| 				if !listContains(e.Arguments[2], "sasl") {
 | |
| 					result <- &SASLResult{true, errors.New("no SASL capability " + e.Arguments[2])}
 | |
| 				}
 | |
| 			}
 | |
| 			if e.Arguments[1] == "ACK" && listContains(e.Arguments[2], "sasl") {
 | |
| 				if irc.SASLMech != "PLAIN" {
 | |
| 					result <- &SASLResult{true, errors.New("only PLAIN is supported")}
 | |
| 				}
 | |
| 				irc.SendRaw("AUTHENTICATE " + irc.SASLMech)
 | |
| 			}
 | |
| 		}
 | |
| 	})
 | |
| 	callbacks = append(callbacks, CallbackID{"CAP", id})
 | |
| 
 | |
| 	id = irc.AddCallback("AUTHENTICATE", func(e *Event) {
 | |
| 		str := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s\x00%s\x00%s", irc.SASLLogin, irc.SASLLogin, irc.SASLPassword)))
 | |
| 		irc.SendRaw("AUTHENTICATE " + str)
 | |
| 	})
 | |
| 	callbacks = append(callbacks, CallbackID{"AUTHENTICATE", id})
 | |
| 
 | |
| 	id = irc.AddCallback("901", func(e *Event) {
 | |
| 		irc.SendRaw("CAP END")
 | |
| 		irc.SendRaw("QUIT")
 | |
| 		result <- &SASLResult{true, errors.New(e.Arguments[1])}
 | |
| 	})
 | |
| 	callbacks = append(callbacks, CallbackID{"901", id})
 | |
| 
 | |
| 	id = irc.AddCallback("902", func(e *Event) {
 | |
| 		irc.SendRaw("CAP END")
 | |
| 		irc.SendRaw("QUIT")
 | |
| 		result <- &SASLResult{true, errors.New(e.Arguments[1])}
 | |
| 	})
 | |
| 	callbacks = append(callbacks, CallbackID{"902", id})
 | |
| 
 | |
| 	id = irc.AddCallback("903", func(e *Event) {
 | |
| 		result <- &SASLResult{false, nil}
 | |
| 	})
 | |
| 	callbacks = append(callbacks, CallbackID{"903", id})
 | |
| 
 | |
| 	id = irc.AddCallback("904", func(e *Event) {
 | |
| 		irc.SendRaw("CAP END")
 | |
| 		irc.SendRaw("QUIT")
 | |
| 		result <- &SASLResult{true, errors.New(e.Arguments[1])}
 | |
| 	})
 | |
| 	callbacks = append(callbacks, CallbackID{"904", id})
 | |
| 
 | |
| 	return
 | |
| }
 |