Changeset 684 in code for trunk/downstream.go


Ignore:
Timestamp:
Nov 15, 2021, 1:34:04 PM (4 years ago)
Author:
contact
Message:

Add support for MONITOR

Add support for MONITOR in single-upstream mode.

Each downstream has its own set of monitored targets. These sets
are merged together to compute the MONITOR commands to send to
upstream.

Each upstream has a set of monitored targets accepted by the server
alongside with their status (online/offline). This is used to
directly send replies to downstreams adding a target another
downstream has already added, and send MONITOR S[TATUS] replies.

Co-authored-by: delthas <delthas@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/downstream.go

    r683 r684  
    229229        "MAXTARGETS":    true,
    230230        "MODES":         true,
     231        "MONITOR":       true,
    231232        "NAMELEN":       true,
    232233        "NETWORK":       true,
     
    265266        lastBatchRef uint64
    266267
     268        monitored casemapMap
     269
    267270        saslServer sasl.Server
    268271}
     
    277280                supportedCaps: make(map[string]string),
    278281                caps:          make(map[string]bool),
     282                monitored:     newCasemapMap(0),
    279283        }
    280284        dc.hostname = remoteAddr
     
    22542258                        Params:  []string{upstreamUser, upstreamChannel},
    22552259                })
     2260        case "MONITOR":
     2261                // MONITOR is unsupported in multi-upstream mode
     2262                uc := dc.upstream()
     2263                if uc == nil {
     2264                        return newUnknownCommandError(msg.Command)
     2265                }
     2266
     2267                var subcommand string
     2268                if err := parseMessageParams(msg, &subcommand); err != nil {
     2269                        return err
     2270                }
     2271
     2272                switch strings.ToUpper(subcommand) {
     2273                case "+", "-":
     2274                        var targets string
     2275                        if err := parseMessageParams(msg, nil, &targets); err != nil {
     2276                                return err
     2277                        }
     2278                        for _, target := range strings.Split(targets, ",") {
     2279                                if subcommand == "+" {
     2280                                        // Hard limit, just to avoid having downstreams fill our map
     2281                                        if len(dc.monitored.innerMap) >= 1000 {
     2282                                                dc.SendMessage(&irc.Message{
     2283                                                        Prefix:  dc.srv.prefix(),
     2284                                                        Command: irc.ERR_MONLISTFULL,
     2285                                                        Params:  []string{dc.nick, "1000", target, "Bouncer monitor list is full"},
     2286                                                })
     2287                                                continue
     2288                                        }
     2289
     2290                                        dc.monitored.SetValue(target, nil)
     2291
     2292                                        if uc.monitored.Has(target) {
     2293                                                cmd := irc.RPL_MONOFFLINE
     2294                                                if online := uc.monitored.Value(target); online {
     2295                                                        cmd = irc.RPL_MONONLINE
     2296                                                }
     2297
     2298                                                dc.SendMessage(&irc.Message{
     2299                                                        Prefix:  dc.srv.prefix(),
     2300                                                        Command: cmd,
     2301                                                        Params:  []string{dc.nick, target},
     2302                                                })
     2303                                        }
     2304                                } else {
     2305                                        dc.monitored.Delete(target)
     2306                                }
     2307                        }
     2308                        uc.updateMonitor()
     2309                case "C": // clear
     2310                        dc.monitored = newCasemapMap(0)
     2311                        uc.updateMonitor()
     2312                case "L": // list
     2313                        // TODO: be less lazy and pack the list
     2314                        for _, entry := range dc.monitored.innerMap {
     2315                                dc.SendMessage(&irc.Message{
     2316                                        Prefix:  dc.srv.prefix(),
     2317                                        Command: irc.RPL_MONLIST,
     2318                                        Params:  []string{dc.nick, entry.originalKey},
     2319                                })
     2320                        }
     2321                        dc.SendMessage(&irc.Message{
     2322                                Prefix:  dc.srv.prefix(),
     2323                                Command: irc.RPL_ENDOFMONLIST,
     2324                                Params:  []string{dc.nick, "End of MONITOR list"},
     2325                        })
     2326                case "S": // status
     2327                        // TODO: be less lazy and pack the lists
     2328                        for _, entry := range dc.monitored.innerMap {
     2329                                target := entry.originalKey
     2330
     2331                                cmd := irc.RPL_MONOFFLINE
     2332                                if online := uc.monitored.Value(target); online {
     2333                                        cmd = irc.RPL_MONONLINE
     2334                                }
     2335
     2336                                dc.SendMessage(&irc.Message{
     2337                                        Prefix:  dc.srv.prefix(),
     2338                                        Command: cmd,
     2339                                        Params:  []string{dc.nick, target},
     2340                                })
     2341                        }
     2342                }
    22562343        case "CHATHISTORY":
    22572344                var subcommand string
Note: See TracChangeset for help on using the changeset viewer.