mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
optimized implementation of Channel.Names()
This commit is contained in:
parent
ef35c587fc
commit
6533893863
@ -6,6 +6,7 @@
|
|||||||
package irc
|
package irc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -24,7 +25,7 @@ type Channel struct {
|
|||||||
lists map[modes.Mode]*UserMaskSet
|
lists map[modes.Mode]*UserMaskSet
|
||||||
key string
|
key string
|
||||||
members MemberSet
|
members MemberSet
|
||||||
membersCache []*Client // allow iteration over channel members without holding the lock
|
membersCache []*Client // allow iteration over channel members without holding the lock
|
||||||
name string
|
name string
|
||||||
nameCasefolded string
|
nameCasefolded string
|
||||||
server *Server
|
server *Server
|
||||||
@ -180,27 +181,47 @@ func (channel *Channel) regenerateMembersCache() {
|
|||||||
|
|
||||||
// Names sends the list of users joined to the channel to the given client.
|
// Names sends the list of users joined to the channel to the given client.
|
||||||
func (channel *Channel) Names(client *Client, rb *ResponseBuffer) {
|
func (channel *Channel) Names(client *Client, rb *ResponseBuffer) {
|
||||||
currentNicks := channel.nicks(client)
|
isMultiPrefix := client.capabilities.Has(caps.MultiPrefix)
|
||||||
// assemble and send replies
|
isUserhostInNames := client.capabilities.Has(caps.UserhostInNames)
|
||||||
maxNamLen := 480 - len(client.server.name) - len(client.nick)
|
|
||||||
var buffer string
|
maxNamLen := 480 - len(client.server.name) - len(client.Nick())
|
||||||
for _, nick := range currentNicks {
|
var namesLines []string
|
||||||
if buffer == "" {
|
var buffer bytes.Buffer
|
||||||
buffer += nick
|
for _, target := range channel.Members() {
|
||||||
|
var nick string
|
||||||
|
if isUserhostInNames {
|
||||||
|
nick = target.NickMaskString()
|
||||||
|
} else {
|
||||||
|
nick = target.Nick()
|
||||||
|
}
|
||||||
|
channel.stateMutex.RLock()
|
||||||
|
modes := channel.members[target]
|
||||||
|
channel.stateMutex.RUnlock()
|
||||||
|
if modes == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
prefix := modes.Prefixes(isMultiPrefix)
|
||||||
if len(buffer)+1+len(nick) > maxNamLen {
|
if buffer.Len()+len(nick)+len(prefix)+1 > maxNamLen {
|
||||||
rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, buffer)
|
namesLines = append(namesLines, buffer.String())
|
||||||
buffer = nick
|
// memset(&buffer, 0, sizeof(bytes.Buffer));
|
||||||
continue
|
var newBuffer bytes.Buffer
|
||||||
|
buffer = newBuffer
|
||||||
}
|
}
|
||||||
|
if buffer.Len() > 0 {
|
||||||
buffer += " "
|
buffer.WriteString(" ")
|
||||||
buffer += nick
|
}
|
||||||
|
buffer.WriteString(prefix)
|
||||||
|
buffer.WriteString(nick)
|
||||||
|
}
|
||||||
|
if buffer.Len() > 0 {
|
||||||
|
namesLines = append(namesLines, buffer.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, buffer)
|
for _, line := range namesLines {
|
||||||
|
if buffer.Len() > 0 {
|
||||||
|
rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
rb.Add(nil, client.server.name, RPL_ENDOFNAMES, client.nick, channel.name, client.t("End of NAMES list"))
|
rb.Add(nil, client.server.name, RPL_ENDOFNAMES, client.nick, channel.name, client.t("End of NAMES list"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,37 +284,6 @@ func (channel *Channel) ClientHasPrivsOver(client *Client, target *Client) bool
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (channel *Channel) nicks(target *Client) []string {
|
|
||||||
isMultiPrefix := (target != nil) && target.capabilities.Has(caps.MultiPrefix)
|
|
||||||
isUserhostInNames := (target != nil) && target.capabilities.Has(caps.UserhostInNames)
|
|
||||||
|
|
||||||
// slightly cumbersome: get the mutex and copy both the client pointers and
|
|
||||||
// the mode prefixes
|
|
||||||
channel.stateMutex.RLock()
|
|
||||||
length := len(channel.members)
|
|
||||||
clients := make([]*Client, length)
|
|
||||||
result := make([]string, length)
|
|
||||||
i := 0
|
|
||||||
for client, modes := range channel.members {
|
|
||||||
clients[i] = client
|
|
||||||
result[i] = modes.Prefixes(isMultiPrefix)
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
channel.stateMutex.RUnlock()
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
for i < length {
|
|
||||||
if isUserhostInNames {
|
|
||||||
result[i] += clients[i].NickMaskString()
|
|
||||||
} else {
|
|
||||||
result[i] += clients[i].Nick()
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (channel *Channel) hasClient(client *Client) bool {
|
func (channel *Channel) hasClient(client *Client) bool {
|
||||||
channel.stateMutex.RLock()
|
channel.stateMutex.RLock()
|
||||||
defer channel.stateMutex.RUnlock()
|
defer channel.stateMutex.RUnlock()
|
||||||
|
Loading…
Reference in New Issue
Block a user