diff --git a/downstream.go b/downstream.go index 7eedaff..5c05290 100644 --- a/downstream.go +++ b/downstream.go @@ -423,25 +423,6 @@ func isOurNick(net *network, nick string) bool { return net.casemap(nick) == net.casemap(database.GetNick(&net.user.User, &net.Network)) } -// marshalEntity converts an upstream entity name (ie. channel or nick) into a -// downstream entity name. -// -// This involves adding a "/" suffix if the entity isn't the current -// user. -func (dc *downstreamConn) marshalEntity(net *network, name string) string { - if isOurNick(net, name) { - return dc.nick - } - name = partialCasemap(net.casemap, name) - if dc.network != nil { - if dc.network != net { - panic("soju: tried to marshal an entity for another network") - } - return name - } - return name + "/" + net.GetName() -} - // unmarshalEntityNetwork converts a downstream entity name (ie. channel or // nick) into an upstream entity name. // @@ -1524,7 +1505,7 @@ func (dc *downstreamConn) welcome(ctx context.Context) error { dc.SendMessage(&irc.Message{ Prefix: dc.prefix(), Command: "JOIN", - Params: []string{dc.marshalEntity(ch.conn.network, ch.Name)}, + Params: []string{ch.Name}, }) forwardChannel(ctx, dc, ch) @@ -1603,7 +1584,7 @@ func (dc *downstreamConn) sendTargetBacklog(ctx context.Context, net *network, t return } - dc.SendBatch("chathistory", []string{dc.marshalEntity(net, target)}, nil, func(batchRef irc.TagValue) { + dc.SendBatch("chathistory", []string{target}, nil, func(batchRef irc.TagValue) { for _, msg := range history { if ch != nil && ch.Detached { if net.detachedMessageNeedsRelay(ch, msg) { @@ -1625,9 +1606,9 @@ func (dc *downstreamConn) relayDetachedMessage(net *network, msg *irc.Message) { sender := msg.Prefix.Name target, text := msg.Params[0], msg.Params[1] if net.isHighlight(msg) { - sendServiceNOTICE(dc, fmt.Sprintf("highlight in %v: <%v> %v", dc.marshalEntity(net, target), sender, text)) + sendServiceNOTICE(dc, fmt.Sprintf("highlight in %v: <%v> %v", target, sender, text)) } else { - sendServiceNOTICE(dc, fmt.Sprintf("message in %v: <%v> %v", dc.marshalEntity(net, target), sender, text)) + sendServiceNOTICE(dc, fmt.Sprintf("message in %v: <%v> %v", target, sender, text)) } } @@ -2957,7 +2938,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc. d.SendMessage(&irc.Message{ Prefix: d.prefix(), Command: cmd, - Params: []string{d.marshalEntity(network, entity), timestampStr}, + Params: []string{entity, timestampStr}, }) } }) @@ -3437,7 +3418,7 @@ func forwardChannel(ctx context.Context, dc *downstreamConn, ch *upstreamChannel dc.SendMessage(&irc.Message{ Prefix: dc.prefix(), Command: markReadCmd, - Params: []string{dc.marshalEntity(ch.conn.network, ch.Name), timestampStr}, + Params: []string{ch.Name, timestampStr}, }) } } @@ -3448,41 +3429,37 @@ func forwardChannel(ctx context.Context, dc *downstreamConn, ch *upstreamChannel } func sendTopic(dc *downstreamConn, ch *upstreamChannel) { - downstreamName := dc.marshalEntity(ch.conn.network, ch.Name) - if ch.Topic != "" { dc.SendMessage(&irc.Message{ Prefix: dc.srv.prefix(), Command: irc.RPL_TOPIC, - Params: []string{dc.nick, downstreamName, ch.Topic}, + Params: []string{dc.nick, ch.Name, ch.Topic}, }) if ch.TopicWho != nil { topicTime := strconv.FormatInt(ch.TopicTime.Unix(), 10) dc.SendMessage(&irc.Message{ Prefix: dc.srv.prefix(), Command: xirc.RPL_TOPICWHOTIME, - Params: []string{dc.nick, downstreamName, ch.TopicWho.String(), topicTime}, + Params: []string{dc.nick, ch.Name, ch.TopicWho.String(), topicTime}, }) } } else { dc.SendMessage(&irc.Message{ Prefix: dc.srv.prefix(), Command: irc.RPL_NOTOPIC, - Params: []string{dc.nick, downstreamName, "No topic is set"}, + Params: []string{dc.nick, ch.Name, "No topic is set"}, }) } } func sendNames(dc *downstreamConn, ch *upstreamChannel) { - downstreamName := dc.marshalEntity(ch.conn.network, ch.Name) - var members []string ch.Members.ForEach(func(nick string, memberships *xirc.MembershipSet) { - s := formatMemberPrefix(*memberships, dc) + dc.marshalEntity(ch.conn.network, nick) + s := formatMemberPrefix(*memberships, dc) + nick members = append(members, s) }) - msgs := xirc.GenerateNamesReply(dc.srv.prefix(), dc.nick, downstreamName, ch.Status, members) + msgs := xirc.GenerateNamesReply(dc.srv.prefix(), dc.nick, ch.Name, ch.Status, members) for _, msg := range msgs { dc.SendMessage(msg) } diff --git a/upstream.go b/upstream.go index 32e7d88..09fd28f 100644 --- a/upstream.go +++ b/upstream.go @@ -1175,7 +1175,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err return err } - needMarshaling, err := applyChannelModes(ch, modeStr, msg.Params[2:]) + _, err = applyChannelModes(ch, modeStr, msg.Params[2:]) if err != nil { return err } @@ -1185,22 +1185,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err c := uc.network.channels.Get(name) if c == nil || !c.Detached { uc.forEachDownstream(func(dc *downstreamConn) { - params := make([]string, len(msg.Params)) - params[0] = dc.marshalEntity(uc.network, name) - params[1] = modeStr - - copy(params[2:], msg.Params[2:]) - for i, modeParam := range params[2:] { - if _, ok := needMarshaling[i]; ok { - params[2+i] = dc.marshalEntity(uc.network, modeParam) - } - } - - dc.SendMessage(&irc.Message{ - Prefix: msg.Prefix, - Command: "MODE", - Params: params, - }) + dc.SendMessage(msg) }) } } @@ -1248,17 +1233,8 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err c := uc.network.channels.Get(channel) if firstMode && (c == nil || !c.Detached) { - modeStr, modeParams := ch.modes.Format() - uc.forEachDownstream(func(dc *downstreamConn) { - params := []string{dc.nick, dc.marshalEntity(uc.network, channel), modeStr} - params = append(params, modeParams...) - - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: irc.RPL_CHANNELMODEIS, - Params: params, - }) + dc.SendMessage(msg) }) } case xirc.RPL_CREATIONTIME: @@ -1278,11 +1254,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err c := uc.network.channels.Get(channel) if firstCreationTime && (c == nil || !c.Detached) { uc.forEachDownstream(func(dc *downstreamConn) { - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: xirc.RPL_CREATIONTIME, - Params: []string{dc.nick, dc.marshalEntity(uc.network, ch.Name), creationTime}, - }) + dc.SendMessage(msg) }) } case xirc.RPL_TOPICWHOTIME: @@ -1307,24 +1279,10 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err c := uc.network.channels.Get(channel) if firstTopicWhoTime && (c == nil || !c.Detached) { uc.forEachDownstream(func(dc *downstreamConn) { - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: xirc.RPL_TOPICWHOTIME, - Params: []string{ - dc.nick, - dc.marshalEntity(uc.network, ch.Name), - ch.TopicWho.String(), - timeStr, - }, - }) + dc.SendMessage(msg) }) } case irc.RPL_LIST: - var channel, clients, topic string - if err := parseMessageParams(msg, nil, &channel, &clients, &topic); err != nil { - return err - } - dc, cmd := uc.currentPendingCommand("LIST") if cmd == nil { return fmt.Errorf("unexpected RPL_LIST: no matching pending LIST") @@ -1332,11 +1290,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err return nil } - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: irc.RPL_LIST, - Params: []string{dc.nick, dc.marshalEntity(uc.network, channel), clients, topic}, - }) + dc.SendMessage(msg) case irc.RPL_LISTEND: dc, cmd := uc.dequeueCommand("LIST") if cmd == nil { @@ -1345,11 +1299,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err return nil } - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: irc.RPL_LISTEND, - Params: []string{dc.nick, "End of /LIST"}, - }) + dc.SendMessage(msg) case irc.RPL_NAMREPLY: var name, statusStr, members string if err := parseMessageParams(msg, nil, &statusStr, &name, &members); err != nil { @@ -1360,19 +1310,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err if ch == nil { // NAMES on a channel we have not joined, forward to downstream uc.forEachDownstreamByID(downstreamID, func(dc *downstreamConn) { - channel := dc.marshalEntity(uc.network, name) - members := splitSpace(members) - for i, member := range members { - memberships, nick := uc.parseMembershipPrefix(member) - members[i] = formatMemberPrefix(memberships, dc) + dc.marshalEntity(uc.network, nick) - } - memberStr := strings.Join(members, " ") - - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: irc.RPL_NAMREPLY, - Params: []string{dc.nick, statusStr, channel, memberStr}, - }) + dc.SendMessage(msg) }) return nil } @@ -1397,13 +1335,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err if ch == nil { // NAMES on a channel we have not joined, forward to downstream uc.forEachDownstreamByID(downstreamID, func(dc *downstreamConn) { - channel := dc.marshalEntity(uc.network, name) - - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: irc.RPL_ENDOFNAMES, - Params: []string{dc.nick, channel, "End of /NAMES list"}, - }) + dc.SendMessage(msg) }) return nil } @@ -1419,44 +1351,16 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err forwardChannel(ctx, dc, ch) }) } - case irc.RPL_WHOREPLY: - var channel, username, host, server, nick, flags, trailing string - if err := parseMessageParams(msg, nil, &channel, &username, &host, &server, &nick, &flags, &trailing); err != nil { - return err - } - + case irc.RPL_WHOREPLY, xirc.RPL_WHOSPCRPL: dc, cmd := uc.currentPendingCommand("WHO") if cmd == nil { - return fmt.Errorf("unexpected RPL_WHOREPLY: no matching pending WHO") + return fmt.Errorf("unexpected WHO reply %v: no matching pending WHO", msg.Command) } else if dc == nil { return nil } - if channel != "*" { - channel = dc.marshalEntity(uc.network, channel) - } - nick = dc.marshalEntity(uc.network, nick) - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: irc.RPL_WHOREPLY, - Params: []string{dc.nick, channel, username, host, server, nick, flags, trailing}, - }) - case xirc.RPL_WHOSPCRPL: - dc, cmd := uc.currentPendingCommand("WHO") - if cmd == nil { - return fmt.Errorf("unexpected RPL_WHOSPCRPL: no matching pending WHO") - } else if dc == nil { - return nil - } - - // Only supported in single-upstream mode, so forward as-is dc.SendMessage(msg) case irc.RPL_ENDOFWHO: - var name string - if err := parseMessageParams(msg, nil, &name); err != nil { - return err - } - dc, cmd := uc.dequeueCommand("WHO") if cmd == nil { // Some servers send RPL_TRYAGAIN followed by RPL_ENDOFWHO @@ -1466,21 +1370,8 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err return nil } - mask := "*" - if len(cmd.Params) > 0 { - mask = cmd.Params[0] - } - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: irc.RPL_ENDOFWHO, - Params: []string{dc.nick, mask, "End of /WHO list"}, - }) - case xirc.RPL_WHOISCERTFP, xirc.RPL_WHOISREGNICK, irc.RPL_WHOISUSER, irc.RPL_WHOISSERVER, irc.RPL_WHOISOPERATOR, irc.RPL_WHOISIDLE, xirc.RPL_WHOISSPECIAL, xirc.RPL_WHOISACCOUNT, xirc.RPL_WHOISACTUALLY, xirc.RPL_WHOISHOST, xirc.RPL_WHOISMODES, xirc.RPL_WHOISSECURE: - var nick string - if err := parseMessageParams(msg, nil, &nick); err != nil { - return err - } - + dc.SendMessage(msg) + case xirc.RPL_WHOISCERTFP, xirc.RPL_WHOISREGNICK, irc.RPL_WHOISUSER, irc.RPL_WHOISSERVER, irc.RPL_WHOISCHANNELS, irc.RPL_WHOISOPERATOR, irc.RPL_WHOISIDLE, xirc.RPL_WHOISSPECIAL, xirc.RPL_WHOISACCOUNT, xirc.RPL_WHOISACTUALLY, xirc.RPL_WHOISHOST, xirc.RPL_WHOISMODES, xirc.RPL_WHOISSECURE: dc, cmd := uc.currentPendingCommand("WHOIS") if cmd == nil { return fmt.Errorf("unexpected WHOIS reply %q: no matching pending WHOIS", msg.Command) @@ -1488,42 +1379,8 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err return nil } - msg := msg.Copy() - msg.Params[1] = dc.marshalEntity(uc.network, nick) dc.SendMessage(msg) - case irc.RPL_WHOISCHANNELS: - var nick, channelList string - if err := parseMessageParams(msg, nil, &nick, &channelList); err != nil { - return err - } - channels := splitSpace(channelList) - - dc, cmd := uc.currentPendingCommand("WHOIS") - if cmd == nil { - return fmt.Errorf("unexpected RPL_WHOISCHANNELS: no matching pending WHOIS") - } else if dc == nil { - return nil - } - - nick = dc.marshalEntity(uc.network, nick) - l := make([]string, len(channels)) - for i, channel := range channels { - prefix, channel := uc.parseMembershipPrefix(channel) - channel = dc.marshalEntity(uc.network, channel) - l[i] = formatMemberPrefix(prefix, dc) + channel - } - channelList = strings.Join(l, " ") - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: irc.RPL_WHOISCHANNELS, - Params: []string{dc.nick, nick, channelList}, - }) case irc.RPL_ENDOFWHOIS: - var nick string - if err := parseMessageParams(msg, nil, &nick); err != nil { - return err - } - dc, cmd := uc.dequeueCommand("WHOIS") if cmd == nil { return fmt.Errorf("unexpected RPL_ENDOFWHOIS: no matching pending WHOIS") @@ -1531,12 +1388,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err return nil } - nick = dc.marshalEntity(uc.network, nick) - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: irc.RPL_ENDOFWHOIS, - Params: []string{dc.nick, nick, "End of /WHOIS list"}, - }) + dc.SendMessage(msg) case "INVITE": var nick, channel string if err := parseMessageParams(msg, &nick, &channel); err != nil { @@ -1549,11 +1401,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err if !weAreInvited && !dc.caps.IsEnabled("invite-notify") { return } - dc.SendMessage(&irc.Message{ - Prefix: msg.Prefix, - Command: "INVITE", - Params: []string{dc.marshalEntity(uc.network, nick), dc.marshalEntity(uc.network, channel)}, - }) + dc.SendMessage(msg) }) if weAreInvited { @@ -1566,11 +1414,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err } uc.forEachDownstreamByID(downstreamID, func(dc *downstreamConn) { - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: irc.RPL_INVITING, - Params: []string{dc.nick, dc.marshalEntity(uc.network, nick), dc.marshalEntity(uc.network, channel)}, - }) + dc.SendMessage(msg) }) case irc.RPL_MONONLINE, irc.RPL_MONOFFLINE: var targetsStr string @@ -1636,63 +1480,16 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err } }) case irc.RPL_AWAY: - var nick, reason string - if err := parseMessageParams(msg, nil, &nick, &reason); err != nil { - return err - } - uc.forEachDownstream(func(dc *downstreamConn) { - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: irc.RPL_AWAY, - Params: []string{dc.nick, dc.marshalEntity(uc.network, nick), reason}, - }) + dc.SendMessage(msg) }) case "AWAY", "ACCOUNT": uc.forEachDownstream(func(dc *downstreamConn) { dc.SendMessage(msg) }) - case irc.RPL_BANLIST, irc.RPL_INVITELIST, irc.RPL_EXCEPTLIST: - var channel, mask string - if err := parseMessageParams(msg, nil, &channel, &mask); err != nil { - return err - } - var addNick, addTime string - if len(msg.Params) >= 5 { - addNick = msg.Params[3] - addTime = msg.Params[4] - } - + case irc.RPL_BANLIST, irc.RPL_INVITELIST, irc.RPL_EXCEPTLIST, irc.RPL_ENDOFBANLIST, irc.RPL_ENDOFINVITELIST, irc.RPL_ENDOFEXCEPTLIST: uc.forEachDownstreamByID(downstreamID, func(dc *downstreamConn) { - channel := dc.marshalEntity(uc.network, channel) - - var params []string - if addNick != "" && addTime != "" { - addNick := dc.marshalEntity(uc.network, addNick) - params = []string{dc.nick, channel, mask, addNick, addTime} - } else { - params = []string{dc.nick, channel, mask} - } - - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: msg.Command, - Params: params, - }) - }) - case irc.RPL_ENDOFBANLIST, irc.RPL_ENDOFINVITELIST, irc.RPL_ENDOFEXCEPTLIST: - var channel, trailing string - if err := parseMessageParams(msg, nil, &channel, &trailing); err != nil { - return err - } - - uc.forEachDownstreamByID(downstreamID, func(dc *downstreamConn) { - upstreamChannel := dc.marshalEntity(uc.network, channel) - dc.SendMessage(&irc.Message{ - Prefix: dc.srv.prefix(), - Command: msg.Command, - Params: []string{dc.nick, upstreamChannel, trailing}, - }) + dc.SendMessage(msg) }) case irc.ERR_NOSUCHNICK: var nick, reason string @@ -1705,12 +1502,7 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err if cmd != nil && cm(cmd.Params[len(cmd.Params)-1]) == cm(nick) { uc.dequeueCommand("WHOIS") if dc != nil { - nick = dc.marshalEntity(uc.network, nick) - dc.SendMessage(&irc.Message{ - Prefix: uc.srv.prefix(), - Command: msg.Command, - Params: []string{dc.nick, nick, reason}, - }) + dc.SendMessage(msg) } } case xirc.ERR_UNKNOWNERROR, irc.ERR_UNKNOWNCOMMAND, irc.ERR_NEEDMOREPARAMS, irc.RPL_TRYAGAIN: diff --git a/user.go b/user.go index 7b9294f..7468483 100644 --- a/user.go +++ b/user.go @@ -318,7 +318,7 @@ func (net *network) detach(ch *database.Channel) { dc.SendMessage(&irc.Message{ Prefix: dc.prefix(), Command: "PART", - Params: []string{dc.marshalEntity(net, ch.Name), "Detach"}, + Params: []string{ch.Name, "Detach"}, }) }) } @@ -345,7 +345,7 @@ func (net *network) attach(ctx context.Context, ch *database.Channel) { dc.SendMessage(&irc.Message{ Prefix: dc.prefix(), Command: "JOIN", - Params: []string{dc.marshalEntity(net, ch.Name)}, + Params: []string{ch.Name}, }) if uch != nil {