More: hellfire

This commit is contained in:
kayos@tcp.direct 2021-10-17 17:16:59 -07:00
parent 410e8686ab
commit 7f101f3656
5 changed files with 31 additions and 13 deletions

View File

@ -484,13 +484,15 @@ func handleISUPPORT(c *Client, e Event) {
j := strings.IndexByte(e.Params[i], '=')
if j < 1 || (j+1) == len(e.Params[i]) {
c.state.serverOptions[e.Params[i]] = ""
opt := c.state.serverOptions[e.Params[i]]
opt.Store("")
continue
}
name := e.Params[i][0:j]
val := e.Params[i][j+1:]
c.state.serverOptions[name] = val
opt := c.state.serverOptions[name]
opt.Store(val)
}
c.state.Unlock()

View File

@ -19,6 +19,7 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
)
@ -678,10 +679,12 @@ func (c *Client) IsInChannel(channel string) (in bool) {
//
func (c *Client) GetServerOption(key string) (result string, ok bool) {
c.panicIfNotTracking()
var opt atomic.Value
if opt, ok = c.state.serverOptions[key]; ok {
result = opt.Load().(string)
}
c.state.RLock()
result, ok = c.state.serverOptions[key]
c.state.RUnlock()
return result, ok
}
@ -693,7 +696,13 @@ func (c *Client) GetAllServerOption() (map[string]string, error) {
c.state.RLock()
defer c.state.RUnlock()
if len(c.state.serverOptions) > 0 {
return c.state.serverOptions, nil
copied := make(map[string]string)
for k, av := range c.state.serverOptions {
if v := av.Load(); v != nil {
copied[k] = av.Load().(string)
}
}
return copied, nil
} else {
return nil, errors.New("server options is empty")
}

View File

@ -428,13 +428,14 @@ func (c *Client) readLoop(ctx context.Context, errs chan error, wg *sync.WaitGro
func (c *Client) Send(event *Event) {
var delay time.Duration
event.Network = c.NetworkName()
for atomic.CompareAndSwapUint32(&c.atom, stateUnlocked, stateLocked) {
randSleep()
}
defer atomic.StoreUint32(&c.atom, stateUnlocked)
if !c.Config.AllowFlood {
// Drop the event early as we're disconnected, this way we don't have to wait
// the (potentially long) rate limit delay before dropping.
if c.conn == nil {

View File

@ -370,8 +370,11 @@ func handleMODE(c *Client, e Event) {
// chanModes returns the ISUPPORT list of server-supported channel modes,
// alternatively falling back to ModeDefaults.
func (s *state) chanModes() string {
if modes, ok := s.serverOptions["CHANMODES"]; ok && IsValidChannelMode(modes) {
return modes
if validmodes, ok := s.serverOptions["CHANMODES"]; ok {
modes := validmodes.Load().(string)
if IsValidChannelMode(modes) {
return modes
}
}
return ModeDefaults
@ -381,8 +384,11 @@ func (s *state) chanModes() string {
// This includes mode characters, as well as user prefix symbols. Falls back
// to DefaultPrefixes if not server-supported.
func (s *state) userPrefixes() string {
if prefix, ok := s.serverOptions["PREFIX"]; ok && isValidUserPrefix(prefix) {
return prefix
if atomicprefix, ok := s.serverOptions["PREFIX"]; ok {
prefix := atomicprefix.Load().(string)
if isValidUserPrefix(prefix) {
return prefix
}
}
return DefaultPrefixes

View File

@ -32,7 +32,7 @@ type state struct {
// serverOptions are the standard capabilities and configurations
// supported by the server at connection time. This also includes
// RPL_ISUPPORT entries.
serverOptions map[string]string
serverOptions map[string]atomic.Value
// motd is the servers message of the day.
motd string
@ -52,7 +52,7 @@ func (s *state) reset(initial bool) {
s.host.Store("")
s.channels = make(map[string]*Channel)
s.users = make(map[string]*User)
s.serverOptions = make(map[string]string)
s.serverOptions = make(map[string]atomic.Value)
s.enabledCap = make(map[string]map[string]string)
s.tmpCap = make(map[string]map[string]string)
s.motd = ""