- Timestamp:
- Nov 15, 2021, 1:34:04 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/downstream.go
r683 r684 229 229 "MAXTARGETS": true, 230 230 "MODES": true, 231 "MONITOR": true, 231 232 "NAMELEN": true, 232 233 "NETWORK": true, … … 265 266 lastBatchRef uint64 266 267 268 monitored casemapMap 269 267 270 saslServer sasl.Server 268 271 } … … 277 280 supportedCaps: make(map[string]string), 278 281 caps: make(map[string]bool), 282 monitored: newCasemapMap(0), 279 283 } 280 284 dc.hostname = remoteAddr … … 2254 2258 Params: []string{upstreamUser, upstreamChannel}, 2255 2259 }) 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 } 2256 2343 case "CHATHISTORY": 2257 2344 var subcommand string -
trunk/irc.go
r673 r684 409 409 } 410 410 411 func generateMonitor(subcmd string, targets []string) []*irc.Message { 412 maxLength := maxMessageLength - len("MONITOR "+subcmd+" ") 413 414 var msgs []*irc.Message 415 var buf []string 416 n := 0 417 for _, target := range targets { 418 if n+len(target)+1 > maxLength { 419 msgs = append(msgs, &irc.Message{ 420 Command: "MONITOR", 421 Params: []string{subcmd, strings.Join(buf, ",")}, 422 }) 423 buf = buf[:0] 424 n = 0 425 } 426 427 buf = append(buf, target) 428 n += len(target) + 1 429 } 430 431 if len(buf) > 0 { 432 msgs = append(msgs, &irc.Message{ 433 Command: "MONITOR", 434 Params: []string{subcmd, strings.Join(buf, ",")}, 435 }) 436 } 437 438 return msgs 439 } 440 411 441 type joinSorter struct { 412 442 channels []string … … 635 665 } 636 666 667 type monitorCasemapMap struct{ casemapMap } 668 669 func (cm *monitorCasemapMap) Value(name string) (online bool) { 670 entry, ok := cm.innerMap[cm.casemap(name)] 671 if !ok { 672 return false 673 } 674 return entry.value.(bool) 675 } 676 637 677 func isWordBoundary(r rune) bool { 638 678 switch r { -
trunk/upstream.go
r682 r684 104 104 account string 105 105 nextLabelID uint64 106 monitored monitorCasemapMap 106 107 107 108 saslClient sasl.Client … … 210 211 isupport: make(map[string]*string), 211 212 pendingCmds: make(map[string][]pendingUpstreamCommand), 213 monitored: monitorCasemapMap{newCasemapMap(0)}, 212 214 } 213 215 return uc, nil … … 1414 1416 }) 1415 1417 }) 1418 case irc.RPL_MONONLINE, irc.RPL_MONOFFLINE: 1419 var targetsStr string 1420 if err := parseMessageParams(msg, nil, &targetsStr); err != nil { 1421 return err 1422 } 1423 targets := strings.Split(targetsStr, ",") 1424 1425 online := msg.Command == irc.RPL_MONONLINE 1426 for _, target := range targets { 1427 prefix := irc.ParsePrefix(target) 1428 uc.monitored.SetValue(prefix.Name, online) 1429 } 1430 1431 uc.forEachDownstream(func(dc *downstreamConn) { 1432 for _, target := range targets { 1433 prefix := irc.ParsePrefix(target) 1434 if dc.monitored.Has(prefix.Name) { 1435 dc.SendMessage(&irc.Message{ 1436 Prefix: dc.srv.prefix(), 1437 Command: msg.Command, 1438 Params: []string{dc.nick, target}, 1439 }) 1440 } 1441 } 1442 }) 1443 case irc.ERR_MONLISTFULL: 1444 var limit, targetsStr string 1445 if err := parseMessageParams(msg, nil, &limit, &targetsStr); err != nil { 1446 return err 1447 } 1448 1449 targets := strings.Split(targetsStr, ",") 1450 uc.forEachDownstream(func(dc *downstreamConn) { 1451 for _, target := range targets { 1452 if dc.monitored.Has(target) { 1453 dc.SendMessage(&irc.Message{ 1454 Prefix: dc.srv.prefix(), 1455 Command: msg.Command, 1456 Params: []string{dc.nick, limit, target}, 1457 }) 1458 } 1459 } 1460 }) 1416 1461 case irc.RPL_AWAY: 1417 1462 var nick, reason string … … 1913 1958 uch.updateAutoDetach(ch.DetachAfter) 1914 1959 } 1960 1961 func (uc *upstreamConn) updateMonitor() { 1962 add := make(map[string]struct{}) 1963 var addList []string 1964 seen := make(map[string]struct{}) 1965 uc.forEachDownstream(func(dc *downstreamConn) { 1966 for targetCM := range dc.monitored.innerMap { 1967 if !uc.monitored.Has(targetCM) { 1968 if _, ok := add[targetCM]; !ok { 1969 addList = append(addList, targetCM) 1970 } 1971 add[targetCM] = struct{}{} 1972 } else { 1973 seen[targetCM] = struct{}{} 1974 } 1975 } 1976 }) 1977 1978 removeAll := true 1979 var removeList []string 1980 for targetCM, entry := range uc.monitored.innerMap { 1981 if _, ok := seen[targetCM]; ok { 1982 removeAll = false 1983 } else { 1984 removeList = append(removeList, entry.originalKey) 1985 } 1986 } 1987 1988 // TODO: better handle the case where len(uc.monitored) + len(addList) 1989 // exceeds the limit, probably by immediately sending ERR_MONLISTFULL? 1990 1991 if removeAll && len(addList) == 0 && len(removeList) > 0 { 1992 // Optimization when the last MONITOR-aware downstream disconnects 1993 uc.SendMessage(&irc.Message{ 1994 Command: "MONITOR", 1995 Params: []string{"C"}, 1996 }) 1997 } else { 1998 msgs := generateMonitor("-", removeList) 1999 msgs = append(msgs, generateMonitor("+", addList)...) 2000 for _, msg := range msgs { 2001 uc.SendMessage(msg) 2002 } 2003 } 2004 2005 for _, target := range removeList { 2006 uc.monitored.Delete(target) 2007 } 2008 } -
trunk/user.go
r682 r684 343 343 net.channels.SetCasemapping(newCasemap) 344 344 net.delivered.m.SetCasemapping(newCasemap) 345 if net.conn!= nil {346 net.conn.channels.SetCasemapping(newCasemap)347 for _, entry := range net.conn.channels.innerMap {345 if uc := net.conn; uc != nil { 346 uc.channels.SetCasemapping(newCasemap) 347 for _, entry := range uc.channels.innerMap { 348 348 uch := entry.value.(*upstreamChannel) 349 349 uch.Members.SetCasemapping(newCasemap) 350 350 } 351 } 351 uc.monitored.SetCasemapping(newCasemap) 352 } 353 net.forEachDownstream(func(dc *downstreamConn) { 354 dc.monitored.SetCasemapping(newCasemap) 355 }) 352 356 } 353 357 … … 520 524 521 525 uc.updateAway() 526 uc.updateMonitor() 522 527 523 528 netIDStr := fmt.Sprintf("%v", uc.network.ID) … … 589 594 dc := e.dc 590 595 596 if dc.network != nil { 597 dc.monitored.SetCasemapping(dc.network.casemap) 598 } 599 591 600 if err := dc.welcome(); err != nil { 592 601 dc.logger.Printf("failed to handle new registered connection: %v", err) … … 621 630 u.forEachUpstream(func(uc *upstreamConn) { 622 631 uc.updateAway() 632 uc.updateMonitor() 623 633 }) 624 634 case eventDownstreamMessage:
Note:
See TracChangeset
for help on using the changeset viewer.