Changeset 139 in code for trunk/upstream.go
- Timestamp:
- Mar 25, 2020, 8:40:08 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/upstream.go
r131 r139 22 22 TopicTime time.Time 23 23 Status channelStatus 24 modes modeSet25 Members map[string] membership24 modes channelModes 25 Members map[string]*membership 26 26 complete bool 27 27 } … … 39 39 serverName string 40 40 availableUserModes string 41 availableChannelModes string 42 channelModesWithParam string 41 availableChannelModes map[byte]channelModeType 42 availableChannelTypes string 43 availableMemberships []membership 43 44 44 45 registered bool … … 47 48 realname string 48 49 closed bool 49 modes modeSet50 modes userModes 50 51 channels map[string]*upstreamChannel 51 52 caps map[string]string … … 73 74 outgoing := make(chan *irc.Message, 64) 74 75 uc := &upstreamConn{ 75 network: network, 76 logger: logger, 77 net: netConn, 78 irc: irc.NewConn(netConn), 79 srv: network.user.srv, 80 user: network.user, 81 outgoing: outgoing, 82 ring: NewRing(network.user.srv.RingCap), 83 channels: make(map[string]*upstreamChannel), 84 caps: make(map[string]string), 76 network: network, 77 logger: logger, 78 net: netConn, 79 irc: irc.NewConn(netConn), 80 srv: network.user.srv, 81 user: network.user, 82 outgoing: outgoing, 83 ring: NewRing(network.user.srv.RingCap), 84 channels: make(map[string]*upstreamChannel), 85 caps: make(map[string]string), 86 availableChannelTypes: stdChannelTypes, 87 availableChannelModes: stdChannelModes, 88 availableMemberships: stdMemberships, 85 89 } 86 90 … … 131 135 132 136 func (uc *upstreamConn) isChannel(entity string) bool { 133 for _, r := range entity { 134 switch r { 135 // TODO: support upstream ISUPPORT channel prefixes 136 case '#', '&', '+', '!': 137 return true 138 } 139 break 137 if i := strings.IndexByte(uc.availableChannelTypes, entity[0]); i >= 0 { 138 return true 140 139 } 141 140 return false 141 } 142 143 func (uc *upstreamConn) parseMembershipPrefix(s string) (membership *membership, nick string) { 144 for _, m := range uc.availableMemberships { 145 if m.Prefix == s[0] { 146 return &m, s[1:] 147 } 148 } 149 return nil, s 142 150 } 143 151 … … 150 158 }) 151 159 return nil 152 case "MODE":153 var name, modeStr string154 if err := parseMessageParams(msg, &name, &modeStr); err != nil {155 return err156 }157 158 if !uc.isChannel(name) { // user mode change159 if name != uc.nick {160 return fmt.Errorf("received MODE message for unknown nick %q", name)161 }162 return uc.modes.Apply(modeStr)163 } else { // channel mode change164 // TODO: handle MODE channel mode arguments165 ch, err := uc.getChannel(name)166 if err != nil {167 return err168 }169 if err := ch.modes.Apply(modeStr); err != nil {170 return err171 }172 173 uc.forEachDownstream(func(dc *downstreamConn) {174 dc.SendMessage(&irc.Message{175 Prefix: dc.marshalUserPrefix(uc, msg.Prefix),176 Command: "MODE",177 Params: []string{dc.marshalChannel(uc, name), modeStr},178 })179 })180 }181 160 case "NOTICE": 182 161 uc.logger.Print(msg) … … 347 326 } 348 327 case irc.RPL_MYINFO: 349 if err := parseMessageParams(msg, nil, &uc.serverName, nil, &uc.availableUserModes, &uc.availableChannelModes); err != nil { 350 return err 351 } 352 if len(msg.Params) > 5 { 353 uc.channelModesWithParam = msg.Params[5] 328 if err := parseMessageParams(msg, nil, &uc.serverName, nil, &uc.availableUserModes, nil); err != nil { 329 return err 330 } 331 case irc.RPL_ISUPPORT: 332 if err := parseMessageParams(msg, nil, nil); err != nil { 333 return err 334 } 335 for _, token := range msg.Params[1 : len(msg.Params)-1] { 336 negate := false 337 parameter := token 338 value := "" 339 if strings.HasPrefix(token, "-") { 340 negate = true 341 token = token[1:] 342 } else { 343 if i := strings.IndexByte(token, '='); i >= 0 { 344 parameter = token[:i] 345 value = token[i+1:] 346 } 347 } 348 if !negate { 349 switch parameter { 350 case "CHANMODES": 351 parts := strings.SplitN(value, ",", 5) 352 if len(parts) < 4 { 353 return fmt.Errorf("malformed ISUPPORT CHANMODES value: %v", value) 354 } 355 modes := make(map[byte]channelModeType) 356 for i, mt := range []channelModeType{modeTypeA, modeTypeB, modeTypeC, modeTypeD} { 357 for j := 0; j < len(parts[i]); j++ { 358 mode := parts[i][j] 359 modes[mode] = mt 360 } 361 } 362 uc.availableChannelModes = modes 363 case "CHANTYPES": 364 uc.availableChannelTypes = value 365 case "PREFIX": 366 if value == "" { 367 uc.availableMemberships = nil 368 } else { 369 if value[0] != '(' { 370 return fmt.Errorf("malformed ISUPPORT PREFIX value: %v", value) 371 } 372 sep := strings.IndexByte(value, ')') 373 if sep < 0 || len(value) != sep*2 { 374 return fmt.Errorf("malformed ISUPPORT PREFIX value: %v", value) 375 } 376 memberships := make([]membership, len(value)/2-1) 377 for i := range memberships { 378 memberships[i] = membership{ 379 Mode: value[i+1], 380 Prefix: value[sep+i+1], 381 } 382 } 383 uc.availableMemberships = memberships 384 } 385 } 386 } else { 387 // TODO: handle ISUPPORT negations 388 } 354 389 } 355 390 case "NICK": … … 400 435 Name: ch, 401 436 conn: uc, 402 Members: make(map[string] membership),437 Members: make(map[string]*membership), 403 438 } 439 440 uc.SendMessage(&irc.Message{ 441 Command: "MODE", 442 Params: []string{ch}, 443 }) 404 444 } else { 405 445 ch, err := uc.getChannel(ch) … … 407 447 return err 408 448 } 409 ch.Members[msg.Prefix.Name] = 0449 ch.Members[msg.Prefix.Name] = nil 410 450 } 411 451 … … 509 549 }) 510 550 }) 551 case "MODE": 552 var name, modeStr string 553 if err := parseMessageParams(msg, &name, &modeStr); err != nil { 554 return err 555 } 556 557 if !uc.isChannel(name) { // user mode change 558 if name != uc.nick { 559 return fmt.Errorf("received MODE message for unknown nick %q", name) 560 } 561 return uc.modes.Apply(modeStr) 562 // TODO: notify downstreams about user mode change? 563 } else { // channel mode change 564 ch, err := uc.getChannel(name) 565 if err != nil { 566 return err 567 } 568 569 if ch.modes != nil { 570 if err := ch.modes.Apply(uc.availableChannelModes, modeStr, msg.Params[2:]...); err != nil { 571 return err 572 } 573 } 574 575 uc.forEachDownstream(func(dc *downstreamConn) { 576 params := []string{dc.marshalChannel(uc, name), modeStr} 577 params = append(params, msg.Params[2:]...) 578 579 dc.SendMessage(&irc.Message{ 580 Prefix: dc.marshalUserPrefix(uc, msg.Prefix), 581 Command: "MODE", 582 Params: params, 583 }) 584 }) 585 } 586 case irc.RPL_UMODEIS: 587 if err := parseMessageParams(msg, nil); err != nil { 588 return err 589 } 590 modeStr := "" 591 if len(msg.Params) > 1 { 592 modeStr = msg.Params[1] 593 } 594 595 uc.modes = "" 596 if err := uc.modes.Apply(modeStr); err != nil { 597 return err 598 } 599 // TODO: send RPL_UMODEIS to downstream connections when applicable 600 case irc.RPL_CHANNELMODEIS: 601 var channel string 602 if err := parseMessageParams(msg, nil, &channel); err != nil { 603 return err 604 } 605 modeStr := "" 606 if len(msg.Params) > 2 { 607 modeStr = msg.Params[2] 608 } 609 610 ch, err := uc.getChannel(channel) 611 if err != nil { 612 return err 613 } 614 615 firstMode := ch.modes == nil 616 ch.modes = make(map[byte]string) 617 if err := ch.modes.Apply(uc.availableChannelModes, modeStr, msg.Params[3:]...); err != nil { 618 return err 619 } 620 if firstMode { 621 modeStr, modeParams := ch.modes.Format() 622 623 uc.forEachDownstream(func(dc *downstreamConn) { 624 params := []string{dc.nick, dc.marshalChannel(uc, channel), modeStr} 625 params = append(params, modeParams...) 626 627 dc.SendMessage(&irc.Message{ 628 Prefix: dc.srv.prefix(), 629 Command: irc.RPL_CHANNELMODEIS, 630 Params: params, 631 }) 632 }) 633 } 511 634 case rpl_topicwhotime: 512 635 var name, who, timeStr string … … 541 664 542 665 for _, s := range strings.Split(members, " ") { 543 membership, nick := parseMembershipPrefix(s)666 membership, nick := uc.parseMembershipPrefix(s) 544 667 ch.Members[nick] = membership 545 668 } … … 680 803 channelList := make([]string, len(channels)) 681 804 for i, channel := range channels { 682 prefix, channel := parseMembershipPrefix(channel)805 prefix, channel := uc.parseMembershipPrefix(channel) 683 806 channel = dc.marshalChannel(uc, channel) 684 807 channelList[i] = prefix.String() + channel
Note:
See TracChangeset
for help on using the changeset viewer.