- Timestamp:
- Mar 24, 2021, 5:15:52 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/bridge.go
r405 r478 55 55 56 56 var buf strings.Builder 57 for nick, memberships := range ch.Members { 57 for _, entry := range ch.Members.innerMap { 58 nick := entry.originalKey 59 memberships := entry.value.(*memberships) 58 60 s := memberships.Format(dc) + dc.marshalEntity(ch.conn.network, nick) 59 61 -
trunk/downstream.go
r464 r478 117 117 user *user 118 118 nick string 119 nickCM string 119 120 rawUsername string 120 121 networkName string … … 193 194 // TODO: this doesn't account for nick changes 194 195 if net.conn != nil { 195 return n ick == net.conn.nick196 return net.casemap(nick) == net.conn.nickCM 196 197 } 197 198 // We're not currently connected to the upstream connection, so we don't … … 199 200 // configured nickname and hope it was the one being used when we were 200 201 // connected. 201 return n ick == net.Nick202 return net.casemap(nick) == net.casemap(net.Nick) 202 203 } 203 204 … … 211 212 return dc.nick 212 213 } 214 name = partialCasemap(net.casemap, name) 213 215 if dc.network != nil { 214 216 if dc.network != net { … … 224 226 return dc.prefix() 225 227 } 228 prefix.Name = partialCasemap(net.casemap, prefix.Name) 226 229 if dc.network != nil { 227 230 if dc.network != net { … … 359 362 } 360 363 361 delivered , ok := network.delivered[entity]362 if !ok{364 delivered := network.delivered.Value(entity) 365 if delivered == nil { 363 366 return 364 367 } … … 446 449 }} 447 450 } 448 if nick == serviceNick { 451 nickCM := casemapASCII(nick) 452 if nickCM == serviceNickCM { 449 453 return ircError{&irc.Message{ 450 454 Command: irc.ERR_NICKNAMEINUSE, … … 453 457 } 454 458 dc.nick = nick 459 dc.nickCM = nickCM 455 460 case "USER": 456 461 if err := parseMessageParams(msg, &dc.rawUsername, nil, nil, &dc.realname); err != nil { … … 767 772 }) 768 773 dc.nick = uc.nick 774 dc.nickCM = casemapASCII(dc.nick) 769 775 } 770 776 } … … 912 918 isupport := []string{ 913 919 fmt.Sprintf("CHATHISTORY=%v", dc.srv.HistoryLimit), 920 "CASEMAPPING=ascii", 914 921 } 915 922 … … 961 968 962 969 dc.forEachUpstream(func(uc *upstreamConn) { 963 for _, ch := range uc.channels { 970 for _, entry := range uc.channels.innerMap { 971 ch := entry.value.(*upstreamChannel) 964 972 if !ch.complete { 965 973 continue 966 974 } 967 if record, ok := uc.network.channels[ch.Name]; ok && record.Detached { 975 record := uc.network.channels.Value(ch.Name) 976 if record != nil && record.Detached { 968 977 continue 969 978 } … … 988 997 989 998 // Fast-forward history to last message 990 for target, delivered := range net.delivered { 991 if ch, ok := net.channels[target]; ok && ch.Detached { 999 for target, entry := range net.delivered.innerMap { 1000 delivered := entry.value.(map[string]string) 1001 ch := net.channels.Value(target) 1002 if ch != nil && ch.Detached { 992 1003 continue 993 1004 } … … 1020 1031 1021 1032 func (dc *downstreamConn) sendNetworkBacklog(net *network) { 1022 for target := range net.delivered { 1033 for _, entry := range net.delivered.innerMap { 1034 target := entry.originalKey 1023 1035 dc.sendTargetBacklog(net, target) 1024 1036 } … … 1029 1041 return 1030 1042 } 1031 if ch , ok := net.channels[target]; ok&& ch.Detached {1043 if ch := net.channels.Value(target); ch != nil && ch.Detached { 1032 1044 return 1033 1045 } 1034 delivered , ok := net.delivered[target]1035 if !ok{1046 delivered := net.delivered.Value(target) 1047 if delivered == nil { 1036 1048 return 1037 1049 } … … 1159 1171 }} 1160 1172 } 1161 if nick == serviceNick{1173 if casemapASCII(nick) == serviceNickCM { 1162 1174 return ircError{&irc.Message{ 1163 1175 Command: irc.ERR_NICKNAMEINUSE, … … 1195 1207 }) 1196 1208 dc.nick = nick 1209 dc.nickCM = casemapASCII(dc.nick) 1197 1210 } 1198 1211 case "JOIN": … … 1227 1240 }) 1228 1241 1229 var ch *Channel 1230 var ok bool 1231 if ch, ok = uc.network.channels[upstreamName]; ok { 1242 ch := uc.network.channels.Value(upstreamName) 1243 if ch != nil { 1232 1244 // Don't clear the channel key if there's one set 1233 1245 // TODO: add a way to unset the channel key … … 1241 1253 Key: key, 1242 1254 } 1243 uc.network.channels [upstreamName] = ch1255 uc.network.channels.SetValue(upstreamName, ch) 1244 1256 } 1245 1257 if err := dc.srv.db.StoreChannel(uc.network.ID, ch); err != nil { … … 1265 1277 1266 1278 if strings.EqualFold(reason, "detach") { 1267 var ch *Channel 1268 var ok bool 1269 if ch, ok = uc.network.channels[upstreamName]; ok { 1279 ch := uc.network.channels.Value(upstreamName) 1280 if ch != nil { 1270 1281 uc.network.detach(ch) 1271 1282 } else { … … 1274 1285 Detached: true, 1275 1286 } 1276 uc.network.channels [upstreamName] = ch1287 uc.network.channels.SetValue(upstreamName, ch) 1277 1288 } 1278 1289 if err := dc.srv.db.StoreChannel(uc.network.ID, ch); err != nil { … … 1361 1372 } 1362 1373 1363 if name == dc.nick{1374 if casemapASCII(name) == dc.nickCM { 1364 1375 if modeStr != "" { 1365 1376 dc.forEachUpstream(func(uc *upstreamConn) { … … 1399 1410 }) 1400 1411 } else { 1401 ch , ok := uc.channels[upstreamName]1402 if !ok{1412 ch := uc.channels.Value(upstreamName) 1413 if ch == nil { 1403 1414 return ircError{&irc.Message{ 1404 1415 Command: irc.ERR_NOSUCHCHANNEL, … … 1436 1447 } 1437 1448 1438 uc, upstream Channel, err := dc.unmarshalEntity(channel)1449 uc, upstreamName, err := dc.unmarshalEntity(channel) 1439 1450 if err != nil { 1440 1451 return err … … 1445 1456 uc.SendMessageLabeled(dc.id, &irc.Message{ 1446 1457 Command: "TOPIC", 1447 Params: []string{upstream Channel, topic},1458 Params: []string{upstreamName, topic}, 1448 1459 }) 1449 1460 } else { // getting topic 1450 ch , ok := uc.channels[upstreamChannel]1451 if !ok{1461 ch := uc.channels.Value(upstreamName) 1462 if ch == nil { 1452 1463 return ircError{&irc.Message{ 1453 1464 Command: irc.ERR_NOSUCHCHANNEL, 1454 Params: []string{dc.nick, upstream Channel, "No such channel"},1465 Params: []string{dc.nick, upstreamName, "No such channel"}, 1455 1466 }} 1456 1467 } … … 1514 1525 channels := strings.Split(msg.Params[0], ",") 1515 1526 for _, channel := range channels { 1516 uc, upstream Channel, err := dc.unmarshalEntity(channel)1527 uc, upstreamName, err := dc.unmarshalEntity(channel) 1517 1528 if err != nil { 1518 1529 return err 1519 1530 } 1520 1531 1521 ch , ok := uc.channels[upstreamChannel]1522 if ok{1532 ch := uc.channels.Value(upstreamName) 1533 if ch != nil { 1523 1534 sendNames(dc, ch) 1524 1535 } else { … … 1526 1537 uc.SendMessageLabeled(dc.id, &irc.Message{ 1527 1538 Command: "NAMES", 1528 Params: []string{upstream Channel},1539 Params: []string{upstreamName}, 1529 1540 }) 1530 1541 } … … 1543 1554 // TODO: support WHO masks 1544 1555 entity := msg.Params[0] 1545 1546 if entity == dc.nick { 1556 entityCM := casemapASCII(entity) 1557 1558 if entityCM == dc.nickCM { 1547 1559 // TODO: support AWAY (H/G) in self WHO reply 1548 1560 dc.SendMessage(&irc.Message{ … … 1558 1570 return nil 1559 1571 } 1560 if entity == serviceNick{1572 if entityCM == serviceNickCM { 1561 1573 dc.SendMessage(&irc.Message{ 1562 1574 Prefix: dc.srv.prefix(), … … 1609 1621 } 1610 1622 1611 if mask == dc.nick{1623 if casemapASCII(mask) == dc.nickCM { 1612 1624 dc.SendMessage(&irc.Message{ 1613 1625 Prefix: dc.srv.prefix(), -
trunk/irc.go
r463 r478 122 122 } 123 123 member := arguments[nextArgument] 124 if _, ok := ch.Members[member]; ok { 124 m := ch.Members.Value(member) 125 if m != nil { 125 126 if plusMinus == '+' { 126 ch.Members[member].Add(ch.conn.availableMemberships, membership)127 m.Add(ch.conn.availableMemberships, membership) 127 128 } else { 128 129 // TODO: for upstreams without multi-prefix, query the user modes again 129 ch.Members[member].Remove(membership)130 m.Remove(membership) 130 131 } 131 132 } … … 419 420 return cmd, params, true 420 421 } 422 423 type casemapping func(string) string 424 425 func casemapNone(name string) string { 426 return name 427 } 428 429 // CasemapASCII of name is the canonical representation of name according to the 430 // ascii casemapping. 431 func casemapASCII(name string) string { 432 var sb strings.Builder 433 sb.Grow(len(name)) 434 for _, r := range name { 435 if 'A' <= r && r <= 'Z' { 436 r += 'a' - 'A' 437 } 438 sb.WriteRune(r) 439 } 440 return sb.String() 441 } 442 443 // casemapRFC1459 of name is the canonical representation of name according to the 444 // rfc1459 casemapping. 445 func casemapRFC1459(name string) string { 446 var sb strings.Builder 447 sb.Grow(len(name)) 448 for _, r := range name { 449 if 'A' <= r && r <= 'Z' { 450 r += 'a' - 'A' 451 } else if r == '{' { 452 r = '[' 453 } else if r == '}' { 454 r = ']' 455 } else if r == '\\' { 456 r = '|' 457 } else if r == '~' { 458 r = '^' 459 } 460 sb.WriteRune(r) 461 } 462 return sb.String() 463 } 464 465 // casemapRFC1459Strict of name is the canonical representation of name 466 // according to the rfc1459-strict casemapping. 467 func casemapRFC1459Strict(name string) string { 468 var sb strings.Builder 469 sb.Grow(len(name)) 470 for _, r := range name { 471 if 'A' <= r && r <= 'Z' { 472 r += 'a' - 'A' 473 } else if r == '{' { 474 r = '[' 475 } else if r == '}' { 476 r = ']' 477 } else if r == '\\' { 478 r = '|' 479 } 480 sb.WriteRune(r) 481 } 482 return sb.String() 483 } 484 485 func parseCasemappingToken(tokenValue string) (casemap casemapping, ok bool) { 486 switch tokenValue { 487 case "ascii": 488 casemap = casemapASCII 489 case "rfc1459": 490 casemap = casemapRFC1459 491 case "rfc1459-strict": 492 casemap = casemapRFC1459Strict 493 default: 494 return nil, false 495 } 496 return casemap, true 497 } 498 499 func partialCasemap(higher casemapping, name string) string { 500 nameFullyCM := higher(name) 501 var sb strings.Builder 502 sb.Grow(len(name)) 503 for i, r := range nameFullyCM { 504 if 'a' <= r && r <= 'z' { 505 r = rune(name[i]) 506 } 507 sb.WriteRune(r) 508 } 509 return sb.String() 510 } 511 512 type casemapMap struct { 513 innerMap map[string]casemapEntry 514 casemap casemapping 515 } 516 517 type casemapEntry struct { 518 originalKey string 519 value interface{} 520 } 521 522 func newCasemapMap(size int) casemapMap { 523 return casemapMap{ 524 innerMap: make(map[string]casemapEntry, size), 525 casemap: casemapNone, 526 } 527 } 528 529 func (cm *casemapMap) OriginalKey(name string) (key string, ok bool) { 530 entry, ok := cm.innerMap[cm.casemap(name)] 531 if !ok { 532 return "", false 533 } 534 return entry.originalKey, true 535 } 536 537 func (cm *casemapMap) Has(name string) bool { 538 _, ok := cm.innerMap[cm.casemap(name)] 539 return ok 540 } 541 542 func (cm *casemapMap) Len() int { 543 return len(cm.innerMap) 544 } 545 546 func (cm *casemapMap) SetValue(name string, value interface{}) { 547 nameCM := cm.casemap(name) 548 entry, ok := cm.innerMap[nameCM] 549 if !ok { 550 cm.innerMap[nameCM] = casemapEntry{ 551 originalKey: name, 552 value: value, 553 } 554 return 555 } 556 entry.value = value 557 cm.innerMap[nameCM] = entry 558 } 559 560 func (cm *casemapMap) Delete(name string) { 561 delete(cm.innerMap, cm.casemap(name)) 562 } 563 564 func (cm *casemapMap) SetCasemapping(newCasemap casemapping) { 565 cm.casemap = newCasemap 566 newInnerMap := make(map[string]casemapEntry, len(cm.innerMap)) 567 for _, entry := range cm.innerMap { 568 newInnerMap[cm.casemap(entry.originalKey)] = entry 569 } 570 cm.innerMap = newInnerMap 571 } 572 573 type upstreamChannelCasemapMap struct{ casemapMap } 574 575 func (cm *upstreamChannelCasemapMap) Value(name string) *upstreamChannel { 576 entry, ok := cm.innerMap[cm.casemap(name)] 577 if !ok { 578 return nil 579 } 580 return entry.value.(*upstreamChannel) 581 } 582 583 type channelCasemapMap struct{ casemapMap } 584 585 func (cm *channelCasemapMap) Value(name string) *Channel { 586 entry, ok := cm.innerMap[cm.casemap(name)] 587 if !ok { 588 return nil 589 } 590 return entry.value.(*Channel) 591 } 592 593 type membershipsCasemapMap struct{ casemapMap } 594 595 func (cm *membershipsCasemapMap) Value(name string) *memberships { 596 entry, ok := cm.innerMap[cm.casemap(name)] 597 if !ok { 598 return nil 599 } 600 return entry.value.(*memberships) 601 } 602 603 type mapStringStringCasemapMap struct{ casemapMap } 604 605 func (cm *mapStringStringCasemapMap) Value(name string) map[string]string { 606 entry, ok := cm.innerMap[cm.casemap(name)] 607 if !ok { 608 return nil 609 } 610 return entry.value.(map[string]string) 611 } -
trunk/service.go
r436 r478 28 28 29 29 const serviceNick = "BouncerServ" 30 const serviceNickCM = "bouncerserv" 30 31 const serviceRealname = "soju bouncer service" 31 32 … … 409 410 statuses = append(statuses, "connected") 410 411 } 411 details = fmt.Sprintf("%v channels", len(uc.channels))412 details = fmt.Sprintf("%v channels", uc.channels.Len()) 412 413 } else { 413 414 statuses = append(statuses, "disconnected") … … 769 770 } 770 771 771 ch , ok := uc.network.channels[upstreamName]772 if !ok{772 ch := uc.network.channels.Value(upstreamName) 773 if ch == nil { 773 774 return fmt.Errorf("unknown channel %q", name) 774 775 } -
trunk/upstream.go
r469 r478 49 49 modes channelModes 50 50 creationTime string 51 Members m ap[string]*memberships51 Members membershipsCasemapMap 52 52 complete bool 53 53 detachTimer *time.Timer … … 87 87 registered bool 88 88 nick string 89 nickCM string 89 90 username string 90 91 realname string 91 92 modes userModes 92 channels map[string]*upstreamChannel93 channels upstreamChannelCasemapMap 93 94 supportedCaps map[string]string 94 95 caps map[string]bool … … 99 100 saslClient sasl.Client 100 101 saslStarted bool 102 103 casemapIsSet bool 101 104 102 105 // set of LIST commands in progress, per downstream … … 187 190 network: network, 188 191 user: network.user, 189 channels: make(map[string]*upstreamChannel),192 channels: upstreamChannelCasemapMap{newCasemapMap(0)}, 190 193 supportedCaps: make(map[string]string), 191 194 caps: make(map[string]bool), … … 214 217 215 218 func (uc *upstreamConn) getChannel(name string) (*upstreamChannel, error) { 216 ch , ok := uc.channels[name]217 if !ok{219 ch := uc.channels.Value(name) 220 if ch == nil { 218 221 return nil, fmt.Errorf("unknown channel %q", name) 219 222 } … … 223 226 func (uc *upstreamConn) isChannel(entity string) bool { 224 227 return strings.ContainsRune(uc.availableChannelTypes, rune(entity[0])) 228 } 229 230 func (uc *upstreamConn) isOurNick(nick string) bool { 231 return uc.nickCM == uc.network.casemap(nick) 225 232 } 226 233 … … 414 421 } else { // regular user message 415 422 target := entity 416 if target == uc.nick{423 if uc.isOurNick(target) { 417 424 target = msg.Prefix.Name 418 425 } 419 426 420 if ch, ok := uc.network.channels[target]; ok { 427 ch := uc.network.channels.Value(target) 428 if ch != nil { 421 429 if ch.Detached { 422 430 uc.handleDetachedMessage(msg.Prefix.Name, text, ch) … … 591 599 uc.logger.Printf("connection registered") 592 600 593 if len(uc.network.channels) > 0 {601 if uc.network.channels.Len() > 0 { 594 602 var channels, keys []string 595 for _, ch := range uc.network.channels { 603 for _, entry := range uc.network.channels.innerMap { 604 ch := entry.value.(*Channel) 596 605 channels = append(channels, ch.Name) 597 606 keys = append(keys, ch.Key) … … 635 644 var err error 636 645 switch parameter { 646 case "CASEMAPPING": 647 casemap, ok := parseCasemappingToken(value) 648 if !ok { 649 casemap = casemapRFC1459 650 } 651 uc.network.updateCasemapping(casemap) 652 uc.nickCM = uc.network.casemap(uc.nick) 653 uc.casemapIsSet = true 637 654 case "CHANMODES": 638 655 if !negate { … … 672 689 } 673 690 }) 691 case irc.ERR_NOMOTD, irc.RPL_ENDOFMOTD: 692 if !uc.casemapIsSet { 693 // upstream did not send any CASEMAPPING token, thus 694 // we assume it implements the old RFCs with rfc1459. 695 uc.casemapIsSet = true 696 uc.network.updateCasemapping(casemapRFC1459) 697 uc.nickCM = uc.network.casemap(uc.nick) 698 } 674 699 case "BATCH": 675 700 var tag string … … 717 742 718 743 me := false 719 if msg.Prefix.Name == uc.nick{744 if uc.isOurNick(msg.Prefix.Name) { 720 745 uc.logger.Printf("changed nick from %q to %q", uc.nick, newNick) 721 746 me = true 722 747 uc.nick = newNick 723 } 724 725 for _, ch := range uc.channels { 726 if memberships, ok := ch.Members[msg.Prefix.Name]; ok { 727 delete(ch.Members, msg.Prefix.Name) 728 ch.Members[newNick] = memberships 748 uc.nickCM = uc.network.casemap(uc.nick) 749 } 750 751 for _, entry := range uc.channels.innerMap { 752 ch := entry.value.(*upstreamChannel) 753 memberships := ch.Members.Value(msg.Prefix.Name) 754 if memberships != nil { 755 ch.Members.Delete(msg.Prefix.Name) 756 ch.Members.SetValue(newNick, memberships) 729 757 uc.appendLog(ch.Name, msg) 730 758 } … … 751 779 752 780 for _, ch := range strings.Split(channels, ",") { 753 if msg.Prefix.Name == uc.nick{781 if uc.isOurNick(msg.Prefix.Name) { 754 782 uc.logger.Printf("joined channel %q", ch) 755 uc.channels[ch] = &upstreamChannel{ 783 members := membershipsCasemapMap{newCasemapMap(0)} 784 members.casemap = uc.network.casemap 785 uc.channels.SetValue(ch, &upstreamChannel{ 756 786 Name: ch, 757 787 conn: uc, 758 Members: m ake(map[string]*memberships),759 } 788 Members: members, 789 }) 760 790 uc.updateChannelAutoDetach(ch) 761 791 … … 769 799 return err 770 800 } 771 ch.Members [msg.Prefix.Name] = &memberships{}801 ch.Members.SetValue(msg.Prefix.Name, &memberships{}) 772 802 } 773 803 … … 787 817 788 818 for _, ch := range strings.Split(channels, ",") { 789 if msg.Prefix.Name == uc.nick{819 if uc.isOurNick(msg.Prefix.Name) { 790 820 uc.logger.Printf("parted channel %q", ch) 791 if uch, ok := uc.channels[ch]; ok { 792 delete(uc.channels, ch) 821 uch := uc.channels.Value(ch) 822 if uch != nil { 823 uc.channels.Delete(ch) 793 824 uch.updateAutoDetach(0) 794 825 } … … 798 829 return err 799 830 } 800 delete(ch.Members,msg.Prefix.Name)831 ch.Members.Delete(msg.Prefix.Name) 801 832 } 802 833 … … 815 846 } 816 847 817 if u ser == uc.nick{848 if uc.isOurNick(user) { 818 849 uc.logger.Printf("kicked from channel %q by %s", channel, msg.Prefix.Name) 819 delete(uc.channels,channel)850 uc.channels.Delete(channel) 820 851 } else { 821 852 ch, err := uc.getChannel(channel) … … 823 854 return err 824 855 } 825 delete(ch.Members,user)856 ch.Members.Delete(user) 826 857 } 827 858 … … 832 863 } 833 864 834 if msg.Prefix.Name == uc.nick{865 if uc.isOurNick(msg.Prefix.Name) { 835 866 uc.logger.Printf("quit") 836 867 } 837 868 838 for _, ch := range uc.channels { 839 if _, ok := ch.Members[msg.Prefix.Name]; ok { 840 delete(ch.Members, msg.Prefix.Name) 869 for _, entry := range uc.channels.innerMap { 870 ch := entry.value.(*upstreamChannel) 871 if ch.Members.Has(msg.Prefix.Name) { 872 ch.Members.Delete(msg.Prefix.Name) 841 873 842 874 uc.appendLog(ch.Name, msg) … … 909 941 uc.appendLog(ch.Name, msg) 910 942 911 if ch, ok := uc.network.channels[name]; !ok || !ch.Detached { 943 c := uc.network.channels.Value(name) 944 if c == nil || !c.Detached { 912 945 uc.forEachDownstream(func(dc *downstreamConn) { 913 946 params := make([]string, len(msg.Params)) … … 965 998 } 966 999 if firstMode { 967 if c, ok := uc.network.channels[channel]; !ok || !c.Detached { 1000 c := uc.network.channels.Value(channel) 1001 if c == nil || !c.Detached { 968 1002 modeStr, modeParams := ch.modes.Format() 969 1003 … … 1062 1096 } 1063 1097 1064 ch , ok := uc.channels[name]1065 if !ok{1098 ch := uc.channels.Value(name) 1099 if ch == nil { 1066 1100 // NAMES on a channel we have not joined, forward to downstream 1067 1101 uc.forEachDownstreamByID(downstreamID, func(dc *downstreamConn) { … … 1091 1125 for _, s := range splitSpace(members) { 1092 1126 memberships, nick := uc.parseMembershipPrefix(s) 1093 ch.Members [nick] = memberships1127 ch.Members.SetValue(nick, memberships) 1094 1128 } 1095 1129 case irc.RPL_ENDOFNAMES: … … 1099 1133 } 1100 1134 1101 ch , ok := uc.channels[name]1102 if !ok{1135 ch := uc.channels.Value(name) 1136 if ch == nil { 1103 1137 // NAMES on a channel we have not joined, forward to downstream 1104 1138 uc.forEachDownstreamByID(downstreamID, func(dc *downstreamConn) { … … 1119 1153 ch.complete = true 1120 1154 1121 if c, ok := uc.network.channels[name]; !ok || !c.Detached { 1155 c := uc.network.channels.Value(name) 1156 if c == nil || !c.Detached { 1122 1157 uc.forEachDownstream(func(dc *downstreamConn) { 1123 1158 forwardChannel(dc, ch) … … 1273 1308 } 1274 1309 1275 weAreInvited := nick == uc.nick1310 weAreInvited := uc.isOurNick(nick) 1276 1311 1277 1312 uc.forEachDownstream(func(dc *downstreamConn) { … … 1396 1431 case irc.RPL_LUSERCLIENT, irc.RPL_LUSEROP, irc.RPL_LUSERUNKNOWN, irc.RPL_LUSERCHANNELS, irc.RPL_LUSERME: 1397 1432 // Ignore 1398 case irc.RPL_MOTDSTART, irc.RPL_MOTD , irc.RPL_ENDOFMOTD:1433 case irc.RPL_MOTDSTART, irc.RPL_MOTD: 1399 1434 // Ignore 1400 1435 case irc.RPL_LISTSTART: … … 1602 1637 func (uc *upstreamConn) register() { 1603 1638 uc.nick = uc.network.Nick 1639 uc.nickCM = uc.network.casemap(uc.nick) 1604 1640 uc.username = uc.network.GetUsername() 1605 1641 uc.realname = uc.network.GetRealname() … … 1706 1742 1707 1743 detached := false 1708 if ch , ok := uc.network.channels[entity]; ok{1744 if ch := uc.network.channels.Value(entity); ch != nil { 1709 1745 detached = ch.Detached 1710 1746 } 1711 1747 1712 delivered, ok := uc.network.delivered[entity] 1713 if !ok { 1714 lastID, err := uc.user.msgStore.LastMsgID(uc.network, entity, time.Now()) 1748 delivered := uc.network.delivered.Value(entity) 1749 entityCM := uc.network.casemap(entity) 1750 if delivered == nil { 1751 lastID, err := uc.user.msgStore.LastMsgID(uc.network, entityCM, time.Now()) 1715 1752 if err != nil { 1716 1753 uc.logger.Printf("failed to log message: failed to get last message ID: %v", err) … … 1719 1756 1720 1757 delivered = make(map[string]string) 1721 uc.network.delivered [entity] = delivered1758 uc.network.delivered.SetValue(entity, delivered) 1722 1759 1723 1760 for clientName, _ := range uc.network.offlineClients { … … 1734 1771 } 1735 1772 1736 msgID, err := uc.user.msgStore.Append(uc.network, entity , msg)1773 msgID, err := uc.user.msgStore.Append(uc.network, entityCM, msg) 1737 1774 if err != nil { 1738 1775 uc.logger.Printf("failed to log message: %v", err) … … 1755 1792 1756 1793 // Don't forward messages if it's a detached channel 1757 if ch, ok := uc.network.channels[target]; ok && ch.Detached { 1794 ch := uc.network.channels.Value(target) 1795 if ch != nil && ch.Detached { 1758 1796 return 1759 1797 } … … 1790 1828 1791 1829 func (uc *upstreamConn) updateChannelAutoDetach(name string) { 1792 if uch, ok := uc.channels[name]; ok { 1793 if ch, ok := uc.network.channels[name]; ok && !ch.Detached { 1794 uch.updateAutoDetach(ch.DetachAfter) 1795 } 1796 } 1797 } 1830 uch := uc.channels.Value(name) 1831 if uch == nil { 1832 return 1833 } 1834 ch := uc.network.channels.Value(name) 1835 if ch == nil || ch.Detached { 1836 return 1837 } 1838 uch.updateAutoDetach(ch.DetachAfter) 1839 } -
trunk/user.go
r467 r478 62 62 63 63 conn *upstreamConn 64 channels map[string]*Channel65 delivered map [string]map[string]string// entity -> client name -> msg ID66 offlineClients map[string]struct{} 64 channels channelCasemapMap 65 delivered mapStringStringCasemapMap // entity -> client name -> msg ID 66 offlineClients map[string]struct{} // indexed by client name 67 67 lastError error 68 casemap casemapping 68 69 } 69 70 70 71 func newNetwork(user *user, record *Network, channels []Channel) *network { 71 m := make(map[string]*Channel, len(channels))72 m := channelCasemapMap{newCasemapMap(0)} 72 73 for _, ch := range channels { 73 74 ch := ch 74 m [ch.Name] = &ch75 m.SetValue(ch.Name, &ch) 75 76 } 76 77 … … 80 81 stopped: make(chan struct{}), 81 82 channels: m, 82 delivered: ma ke(map[string]map[string]string),83 delivered: mapStringStringCasemapMap{newCasemapMap(0)}, 83 84 offlineClients: make(map[string]struct{}), 85 casemap: casemapRFC1459, 84 86 } 85 87 } … … 186 188 187 189 if net.conn != nil { 188 if uch, ok := net.conn.channels[ch.Name]; ok { 190 uch := net.conn.channels.Value(ch.Name) 191 if uch != nil { 189 192 uch.updateAutoDetach(0) 190 193 } … … 211 214 var uch *upstreamChannel 212 215 if net.conn != nil { 213 uch = net.conn.channels [ch.Name]216 uch = net.conn.channels.Value(ch.Name) 214 217 215 218 net.conn.updateChannelAutoDetach(ch.Name) … … 232 235 233 236 func (net *network) deleteChannel(name string) error { 234 ch , ok := net.channels[name]235 if !ok{237 ch := net.channels.Value(name) 238 if ch == nil { 236 239 return fmt.Errorf("unknown channel %q", name) 237 240 } 238 241 if net.conn != nil { 239 if uch, ok := net.conn.channels[ch.Name]; ok { 242 uch := net.conn.channels.Value(ch.Name) 243 if uch != nil { 240 244 uch.updateAutoDetach(0) 241 245 } … … 245 249 return err 246 250 } 247 delete(net.channels,name)251 net.channels.Delete(name) 248 252 return nil 253 } 254 255 func (net *network) updateCasemapping(newCasemap casemapping) { 256 net.casemap = newCasemap 257 net.channels.SetCasemapping(newCasemap) 258 net.delivered.SetCasemapping(newCasemap) 259 if net.conn != nil { 260 net.conn.channels.SetCasemapping(newCasemap) 261 for _, entry := range net.conn.channels.innerMap { 262 uch := entry.value.(*upstreamChannel) 263 uch.Members.SetCasemapping(newCasemap) 264 } 265 } 249 266 } 250 267 … … 411 428 case eventChannelDetach: 412 429 uc, name := e.uc, e.name 413 c , ok := uc.network.channels[name]414 if !ok|| c.Detached {430 c := uc.network.channels.Value(name) 431 if c == nil || c.Detached { 415 432 continue 416 433 } … … 500 517 uc.endPendingLISTs(true) 501 518 502 for _, uch := range uc.channels { 519 for _, entry := range uc.channels.innerMap { 520 uch := entry.value.(*upstreamChannel) 503 521 uch.updateAutoDetach(0) 504 522 } … … 571 589 // Most network changes require us to re-connect to the upstream server 572 590 573 channels := make([]Channel, 0, len(network.channels)) 574 for _, ch := range network.channels { 591 channels := make([]Channel, 0, network.channels.Len()) 592 for _, entry := range network.channels.innerMap { 593 ch := entry.value.(*Channel) 575 594 channels = append(channels, *ch) 576 595 }
Note:
See TracChangeset
for help on using the changeset viewer.