Changeset 108 in code for trunk/downstream.go


Ignore:
Timestamp:
Mar 16, 2020, 2:05:24 PM (5 years ago)
Author:
contact
Message:

Add CAP support for downstream connections

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/downstream.go

    r107 r108  
    66        "io"
    77        "net"
     8        "strconv"
    89        "strings"
    910        "sync"
     
    7273        network     *network // can be nil
    7374
     75        negociatingCaps bool
     76        capVersion      int
     77        caps            map[string]bool
     78
    7479        lock        sync.Mutex
    7580        ourMessages map[*irc.Message]struct{}
     
    8590                ringMessages: make(chan ringMessage),
    8691                closed:       make(chan struct{}),
     92                caps:         make(map[string]bool),
    8793                ourMessages:  make(map[*irc.Message]struct{}),
    8894        }
     
    329335                        return err
    330336                }
     337        case "CAP":
     338                var subCmd string
     339                if err := parseMessageParams(msg, &subCmd); err != nil {
     340                        return err
     341                }
     342                subCmd = strings.ToUpper(subCmd)
     343                if err := dc.handleCapCommand(subCmd, msg.Params[1:]); err != nil {
     344                        return err
     345                }
    331346        default:
    332347                dc.logger.Printf("unhandled message: %v", msg)
    333348                return newUnknownCommandError(msg.Command)
    334349        }
    335         if dc.rawUsername != "" && dc.nick != "" {
     350        if dc.rawUsername != "" && dc.nick != "" && !dc.negociatingCaps {
    336351                return dc.register()
     352        }
     353        return nil
     354}
     355
     356func (dc *downstreamConn) handleCapCommand(cmd string, args []string) error {
     357        replyTo := dc.nick
     358        if !dc.registered {
     359                replyTo = "*"
     360        }
     361
     362        switch cmd {
     363        case "LS":
     364                if len(args) > 0 {
     365                        var err error
     366                        if dc.capVersion, err = strconv.Atoi(args[0]); err != nil {
     367                                return err
     368                        }
     369                }
     370
     371                var caps []string
     372                /*if dc.capVersion >= 302 {
     373                        caps = append(caps, "sasl=PLAIN")
     374                } else {
     375                        caps = append(caps, "sasl")
     376                }*/
     377
     378                // TODO: multi-line replies
     379                dc.SendMessage(&irc.Message{
     380                        Prefix:  dc.srv.prefix(),
     381                        Command: "CAP",
     382                        Params:  []string{replyTo, "LS", strings.Join(caps, " ")},
     383                })
     384
     385                if !dc.registered {
     386                        dc.negociatingCaps = true
     387                }
     388        case "LIST":
     389                var caps []string
     390                for name := range dc.caps {
     391                        caps = append(caps, name)
     392                }
     393
     394                // TODO: multi-line replies
     395                dc.SendMessage(&irc.Message{
     396                        Prefix:  dc.srv.prefix(),
     397                        Command: "CAP",
     398                        Params:  []string{replyTo, "LIST", strings.Join(caps, " ")},
     399                })
     400        case "REQ":
     401                if len(args) == 0 {
     402                        return ircError{&irc.Message{
     403                                Command: err_invalidcapcmd,
     404                                Params:  []string{replyTo, cmd, "Missing argument in CAP REQ command"},
     405                        }}
     406                }
     407
     408                caps := strings.Fields(args[0])
     409                ack := true
     410                for _, name := range caps {
     411                        name = strings.ToLower(name)
     412                        enable := !strings.HasPrefix(name, "-")
     413                        if !enable {
     414                                name = strings.TrimPrefix(name, "-")
     415                        }
     416
     417                        enabled := dc.caps[name]
     418                        if enable == enabled {
     419                                continue
     420                        }
     421
     422                        switch name {
     423                        /*case "sasl":
     424                                dc.caps[name] = enable*/
     425                        default:
     426                                ack = false
     427                        }
     428                }
     429
     430                reply := "NAK"
     431                if ack {
     432                        reply = "ACK"
     433                }
     434                dc.SendMessage(&irc.Message{
     435                        Prefix:  dc.srv.prefix(),
     436                        Command: "CAP",
     437                        Params:  []string{replyTo, reply, args[0]},
     438                })
     439        case "END":
     440                dc.negociatingCaps = false
     441        default:
     442                return ircError{&irc.Message{
     443                        Command: err_invalidcapcmd,
     444                        Params:  []string{replyTo, cmd, "Unknown CAP command"},
     445                }}
    337446        }
    338447        return nil
Note: See TracChangeset for help on using the changeset viewer.