Browse Source

refactor rehash to rely more on server.config

tags/v0.12.0
Shivaram Lingamneni 5 years ago
parent
commit
1383190249
11 changed files with 134 additions and 232 deletions
  1. 3
    2
      irc/channel.go
  2. 4
    4
      irc/client.go
  3. 56
    33
      irc/config.go
  4. 1
    1
      irc/database.go
  5. 16
    41
      irc/getters.go
  6. 7
    6
      irc/handlers.go
  7. 3
    3
      irc/modes.go
  8. 1
    3
      irc/modes_test.go
  9. 39
    133
      irc/server.go
  10. 3
    5
      irc/utils/bitset.go
  11. 1
    1
      irc/whowas.go

+ 3
- 2
irc/channel.go View File

@@ -515,8 +515,9 @@ func (channel *Channel) SetTopic(client *Client, topic string, rb *ResponseBuffe
515 515
 		return
516 516
 	}
517 517
 
518
-	if len(topic) > client.server.limits.TopicLen {
519
-		topic = topic[:client.server.limits.TopicLen]
518
+	topicLimit := client.server.Limits().TopicLen
519
+	if len(topic) > topicLimit {
520
+		topic = topic[:topicLimit]
520 521
 	}
521 522
 
522 523
 	channel.stateMutex.Lock()

+ 4
- 4
irc/client.go View File

@@ -85,9 +85,9 @@ type Client struct {
85 85
 // NewClient returns a client with all the appropriate info setup.
86 86
 func NewClient(server *Server, conn net.Conn, isTLS bool) *Client {
87 87
 	now := time.Now()
88
-	limits := server.Limits()
89
-	fullLineLenLimit := limits.LineLen.Tags + limits.LineLen.Rest
90
-	socket := NewSocket(conn, fullLineLenLimit*2, server.MaxSendQBytes())
88
+	config := server.Config()
89
+	fullLineLenLimit := config.Limits.LineLen.Tags + config.Limits.LineLen.Rest
90
+	socket := NewSocket(conn, fullLineLenLimit*2, config.Server.MaxSendQBytes)
91 91
 	client := &Client{
92 92
 		atime:          now,
93 93
 		authorized:     server.Password() == nil,
@@ -112,7 +112,7 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) *Client {
112 112
 		// error is not useful to us here anyways so we can ignore it
113 113
 		client.certfp, _ = client.socket.CertFP()
114 114
 	}
115
-	if server.checkIdent && !utils.AddrIsUnix(conn.RemoteAddr()) {
115
+	if config.Server.CheckIdent && !utils.AddrIsUnix(conn.RemoteAddr()) {
116 116
 		_, serverPortString, err := net.SplitHostPort(conn.LocalAddr().String())
117 117
 		serverPort, _ := strconv.Atoi(serverPortString)
118 118
 		if err != nil {

+ 56
- 33
irc/config.go View File

@@ -28,10 +28,10 @@ import (
28 28
 	"gopkg.in/yaml.v2"
29 29
 )
30 30
 
31
-// PassConfig holds the connection password.
32
-type PassConfig struct {
33
-	Password string
34
-}
31
+// here's how this works: exported (capitalized) members of the config structs
32
+// are defined in the YAML file and deserialized directly from there. They may
33
+// be postprocessed and overwritten by LoadConfig. Unexported (lowercase) members
34
+// are derived from the exported members in LoadConfig.
35 35
 
36 36
 // TLSListenConfig defines configuration options for listening on TLS.
37 37
 type TLSListenConfig struct {
@@ -51,15 +51,6 @@ func (conf *TLSListenConfig) Config() (*tls.Config, error) {
51 51
 	}, err
52 52
 }
53 53
 
54
-// PasswordBytes returns the bytes represented by the password hash.
55
-func (conf *PassConfig) PasswordBytes() []byte {
56
-	bytes, err := passwd.DecodePasswordHash(conf.Password)
57
-	if err != nil {
58
-		log.Fatal("decode password error: ", err)
59
-	}
60
-	return bytes
61
-}
62
-
63 54
 type AccountConfig struct {
64 55
 	Registration          AccountRegistrationConfig
65 56
 	AuthenticationEnabled bool                  `yaml:"authentication-enabled"`
@@ -171,11 +162,24 @@ func (conf *OperConfig) PasswordBytes() []byte {
171 162
 }
172 163
 
173 164
 // LineLenConfig controls line lengths.
174
-type LineLenConfig struct {
165
+type LineLenLimits struct {
175 166
 	Tags int
176 167
 	Rest int
177 168
 }
178 169
 
170
+// Various server-enforced limits on data size.
171
+type Limits struct {
172
+	AwayLen        int           `yaml:"awaylen"`
173
+	ChanListModes  int           `yaml:"chan-list-modes"`
174
+	ChannelLen     int           `yaml:"channellen"`
175
+	KickLen        int           `yaml:"kicklen"`
176
+	MonitorEntries int           `yaml:"monitor-entries"`
177
+	NickLen        int           `yaml:"nicklen"`
178
+	TopicLen       int           `yaml:"topiclen"`
179
+	WhowasEntries  int           `yaml:"whowas-entries"`
180
+	LineLen        LineLenLimits `yaml:"linelen"`
181
+}
182
+
179 183
 // STSConfig controls the STS configuration/
180 184
 type STSConfig struct {
181 185
 	Enabled        bool
@@ -219,9 +223,10 @@ type Config struct {
219 223
 	}
220 224
 
221 225
 	Server struct {
222
-		PassConfig
223 226
 		Password            string
227
+		passwordBytes       []byte
224 228
 		Name                string
229
+		nameCasefolded      string
225 230
 		Listen              []string
226 231
 		TLSListeners        map[string]*TLSListenConfig `yaml:"tls-listeners"`
227 232
 		STS                 STSConfig
@@ -251,14 +256,19 @@ type Config struct {
251 256
 	Accounts AccountConfig
252 257
 
253 258
 	Channels struct {
254
-		DefaultModes *string `yaml:"default-modes"`
255
-		Registration ChannelRegistrationConfig
259
+		RawDefaultModes *string `yaml:"default-modes"`
260
+		defaultModes    modes.Modes
261
+		Registration    ChannelRegistrationConfig
256 262
 	}
257 263
 
258 264
 	OperClasses map[string]*OperClassConfig `yaml:"oper-classes"`
259 265
 
260 266
 	Opers map[string]*OperConfig
261 267
 
268
+	// parsed operator definitions, unexported so they can't be defined
269
+	// directly in YAML:
270
+	operators map[string]*Oper
271
+
262 272
 	Logging []logger.LoggingConfig
263 273
 
264 274
 	Debug struct {
@@ -267,17 +277,7 @@ type Config struct {
267 277
 		StackImpact       StackImpactConfig
268 278
 	}
269 279
 
270
-	Limits struct {
271
-		AwayLen        uint          `yaml:"awaylen"`
272
-		ChanListModes  uint          `yaml:"chan-list-modes"`
273
-		ChannelLen     uint          `yaml:"channellen"`
274
-		KickLen        uint          `yaml:"kicklen"`
275
-		MonitorEntries uint          `yaml:"monitor-entries"`
276
-		NickLen        uint          `yaml:"nicklen"`
277
-		TopicLen       uint          `yaml:"topiclen"`
278
-		WhowasEntries  uint          `yaml:"whowas-entries"`
279
-		LineLen        LineLenConfig `yaml:"linelen"`
280
-	}
280
+	Limits Limits
281 281
 
282 282
 	Fakelag FakelagConfig
283 283
 
@@ -437,11 +437,6 @@ func LoadConfig(filename string) (config *Config, err error) {
437 437
 
438 438
 	config.Filename = filename
439 439
 
440
-	// we need this so PasswordBytes returns the correct info
441
-	if config.Server.Password != "" {
442
-		config.Server.PassConfig.Password = config.Server.Password
443
-	}
444
-
445 440
 	if config.Network.Name == "" {
446 441
 		return nil, ErrNetworkNameMissing
447 442
 	}
@@ -691,5 +686,33 @@ func LoadConfig(filename string) (config *Config, err error) {
691 686
 		}
692 687
 	}
693 688
 
689
+	// casefold/validate server name
690
+	config.Server.nameCasefolded, err = Casefold(config.Server.Name)
691
+	if err != nil {
692
+		return nil, fmt.Errorf("Server name isn't valid [%s]: %s", config.Server.Name, err.Error())
693
+	}
694
+
695
+	// process operator definitions, store them to config.operators
696
+	operclasses, err := config.OperatorClasses()
697
+	if err != nil {
698
+		return nil, err
699
+	}
700
+	opers, err := config.Operators(operclasses)
701
+	if err != nil {
702
+		return nil, err
703
+	}
704
+	config.operators = opers
705
+
706
+	// parse default channel modes
707
+	config.Channels.defaultModes = ParseDefaultChannelModes(config.Channels.RawDefaultModes)
708
+
709
+	if config.Server.Password != "" {
710
+		bytes, err := passwd.DecodePasswordHash(config.Server.Password)
711
+		if err != nil {
712
+			return nil, err
713
+		}
714
+		config.Server.passwordBytes = bytes
715
+	}
716
+
694 717
 	return config, nil
695 718
 }

+ 1
- 1
irc/database.go View File

@@ -267,7 +267,7 @@ func schemaChangeV2ToV3(config *Config, tx *buntdb.Tx) error {
267 267
 	}
268 268
 
269 269
 	// explicitly store the channel modes
270
-	defaultModes := ParseDefaultChannelModes(config)
270
+	defaultModes := ParseDefaultChannelModes(config.Channels.RawDefaultModes)
271 271
 	modeStrings := make([]string, len(defaultModes))
272 272
 	for i, mode := range defaultModes {
273 273
 		modeStrings[i] = string(mode)

+ 16
- 41
irc/getters.go View File

@@ -6,15 +6,12 @@ package irc
6 6
 import (
7 7
 	"github.com/oragono/oragono/irc/isupport"
8 8
 	"github.com/oragono/oragono/irc/modes"
9
-	"sync/atomic"
10 9
 )
11 10
 
12
-func (server *Server) MaxSendQBytes() int {
13
-	return int(atomic.LoadUint32(&server.maxSendQBytes))
14
-}
15
-
16
-func (server *Server) SetMaxSendQBytes(m int) {
17
-	atomic.StoreUint32(&server.maxSendQBytes, uint32(m))
11
+func (server *Server) Config() *Config {
12
+	server.configurableStateMutex.RLock()
13
+	defer server.configurableStateMutex.RUnlock()
14
+	return server.config
18 15
 }
19 16
 
20 17
 func (server *Server) ISupport() *isupport.List {
@@ -24,63 +21,41 @@ func (server *Server) ISupport() *isupport.List {
24 21
 }
25 22
 
26 23
 func (server *Server) Limits() Limits {
27
-	server.configurableStateMutex.RLock()
28
-	defer server.configurableStateMutex.RUnlock()
29
-	return server.limits
24
+	return server.Config().Limits
30 25
 }
31 26
 
32 27
 func (server *Server) Password() []byte {
33
-	server.configurableStateMutex.RLock()
34
-	defer server.configurableStateMutex.RUnlock()
35
-	return server.password
28
+	return server.Config().Server.passwordBytes
36 29
 }
37 30
 
38 31
 func (server *Server) RecoverFromErrors() bool {
39
-	server.configurableStateMutex.RLock()
40
-	defer server.configurableStateMutex.RUnlock()
41
-	return server.recoverFromErrors
32
+	// default to true if unset
33
+	rfe := server.Config().Debug.RecoverFromErrors
34
+	return rfe == nil || *rfe
42 35
 }
43 36
 
44 37
 func (server *Server) ProxyAllowedFrom() []string {
45
-	server.configurableStateMutex.RLock()
46
-	defer server.configurableStateMutex.RUnlock()
47
-	return server.proxyAllowedFrom
38
+	return server.Config().Server.ProxyAllowedFrom
48 39
 }
49 40
 
50 41
 func (server *Server) WebIRCConfig() []webircConfig {
51
-	server.configurableStateMutex.RLock()
52
-	defer server.configurableStateMutex.RUnlock()
53
-	return server.webirc
42
+	return server.Config().Server.WebIRC
54 43
 }
55 44
 
56 45
 func (server *Server) DefaultChannelModes() modes.Modes {
57
-	server.configurableStateMutex.RLock()
58
-	defer server.configurableStateMutex.RUnlock()
59
-	return server.defaultChannelModes
46
+	return server.Config().Channels.defaultModes
60 47
 }
61 48
 
62 49
 func (server *Server) ChannelRegistrationEnabled() bool {
63
-	server.configurableStateMutex.RLock()
64
-	defer server.configurableStateMutex.RUnlock()
65
-	return server.config.Channels.Registration.Enabled
50
+	return server.Config().Channels.Registration.Enabled
66 51
 }
67 52
 
68 53
 func (server *Server) AccountConfig() *AccountConfig {
69
-	server.configurableStateMutex.RLock()
70
-	defer server.configurableStateMutex.RUnlock()
71
-	if server.config == nil {
72
-		return nil
73
-	}
74
-	return &server.config.Accounts
54
+	return &server.Config().Accounts
75 55
 }
76 56
 
77 57
 func (server *Server) FakelagConfig() *FakelagConfig {
78
-	server.configurableStateMutex.RLock()
79
-	defer server.configurableStateMutex.RUnlock()
80
-	if server.config == nil {
81
-		return nil
82
-	}
83
-	return &server.config.Fakelag
58
+	return &server.Config().Fakelag
84 59
 }
85 60
 
86 61
 func (server *Server) GetOperator(name string) (oper *Oper) {
@@ -90,7 +65,7 @@ func (server *Server) GetOperator(name string) (oper *Oper) {
90 65
 	}
91 66
 	server.configurableStateMutex.RLock()
92 67
 	defer server.configurableStateMutex.RUnlock()
93
-	return server.operators[name]
68
+	return server.config.operators[name]
94 69
 }
95 70
 
96 71
 func (client *Client) Nick() string {

+ 7
- 6
irc/handlers.go View File

@@ -1501,12 +1501,12 @@ func monitorAddHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb
1501 1501
 	var online []string
1502 1502
 	var offline []string
1503 1503
 
1504
-	limit := server.Limits().MonitorEntries
1504
+	limits := server.Limits()
1505 1505
 
1506 1506
 	targets := strings.Split(msg.Params[1], ",")
1507 1507
 	for _, target := range targets {
1508 1508
 		// check name length
1509
-		if len(target) < 1 || len(targets) > server.limits.NickLen {
1509
+		if len(target) < 1 || len(targets) > limits.NickLen {
1510 1510
 			continue
1511 1511
 		}
1512 1512
 
@@ -1516,9 +1516,9 @@ func monitorAddHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb
1516 1516
 			continue
1517 1517
 		}
1518 1518
 
1519
-		err = server.monitorManager.Add(client, casefoldedTarget, limit)
1519
+		err = server.monitorManager.Add(client, casefoldedTarget, limits.MonitorEntries)
1520 1520
 		if err == errMonitorLimitExceeded {
1521
-			rb.Add(nil, server.name, ERR_MONLISTFULL, client.Nick(), strconv.Itoa(server.limits.MonitorEntries), strings.Join(targets, ","))
1521
+			rb.Add(nil, server.name, ERR_MONLISTFULL, client.Nick(), strconv.Itoa(limits.MonitorEntries), strings.Join(targets, ","))
1522 1522
 			break
1523 1523
 		} else if err != nil {
1524 1524
 			continue
@@ -1814,14 +1814,15 @@ func passHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
1814 1814
 	}
1815 1815
 
1816 1816
 	// if no password exists, skip checking
1817
-	if len(server.password) == 0 {
1817
+	serverPassword := server.Password()
1818
+	if serverPassword == nil {
1818 1819
 		client.SetAuthorized(true)
1819 1820
 		return false
1820 1821
 	}
1821 1822
 
1822 1823
 	// check the provided password
1823 1824
 	password := []byte(msg.Params[0])
1824
-	if passwd.ComparePassword(server.password, password) != nil {
1825
+	if passwd.ComparePassword(serverPassword, password) != nil {
1825 1826
 		rb.Add(nil, server.name, ERR_PASSWDMISMATCH, client.nick, client.t("Password incorrect"))
1826 1827
 		rb.Add(nil, server.name, "ERROR", client.t("Password incorrect"))
1827 1828
 		return true

+ 3
- 3
irc/modes.go View File

@@ -87,12 +87,12 @@ func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool)
87 87
 }
88 88
 
89 89
 // ParseDefaultChannelModes parses the `default-modes` line of the config
90
-func ParseDefaultChannelModes(config *Config) modes.Modes {
91
-	if config.Channels.DefaultModes == nil {
90
+func ParseDefaultChannelModes(rawModes *string) modes.Modes {
91
+	if rawModes == nil {
92 92
 		// not present in config, fall back to compile-time default
93 93
 		return DefaultChannelModes
94 94
 	}
95
-	modeChangeStrings := strings.Split(strings.TrimSpace(*config.Channels.DefaultModes), " ")
95
+	modeChangeStrings := strings.Fields(*rawModes)
96 96
 	modeChanges, _ := modes.ParseChannelModeChanges(modeChangeStrings...)
97 97
 	defaultChannelModes := make(modes.Modes, 0)
98 98
 	for _, modeChange := range modeChanges {

+ 1
- 3
irc/modes_test.go View File

@@ -27,10 +27,8 @@ func TestParseDefaultChannelModes(t *testing.T) {
27 27
 		{nil, modes.Modes{modes.NoOutside, modes.OpOnlyTopic}},
28 28
 	}
29 29
 
30
-	var config Config
31 30
 	for _, testcase := range parseTests {
32
-		config.Channels.DefaultModes = testcase.raw
33
-		result := ParseDefaultChannelModes(&config)
31
+		result := ParseDefaultChannelModes(testcase.raw)
34 32
 		if !reflect.DeepEqual(result, testcase.expected) {
35 33
 			t.Errorf("expected modes %s, got %s", testcase.expected, result)
36 34
 		}

+ 39
- 133
irc/server.go View File

@@ -58,24 +58,6 @@ var (
58 58
 	CapValues = caps.NewValues()
59 59
 )
60 60
 
61
-// Limits holds the maximum limits for various things such as topic lengths.
62
-type Limits struct {
63
-	AwayLen        int
64
-	ChannelLen     int
65
-	KickLen        int
66
-	MonitorEntries int
67
-	NickLen        int
68
-	TopicLen       int
69
-	ChanListModes  int
70
-	LineLen        LineLenLimits
71
-}
72
-
73
-// LineLenLimits holds the maximum limits for IRC lines.
74
-type LineLenLimits struct {
75
-	Tags int
76
-	Rest int
77
-}
78
-
79 61
 // ListenerWrapper wraps a listener so it can be safely reconfigured or stopped
80 62
 type ListenerWrapper struct {
81 63
 	listener   net.Listener
@@ -91,7 +73,6 @@ type Server struct {
91 73
 	batches                *BatchManager
92 74
 	channels               *ChannelManager
93 75
 	channelRegistry        *ChannelRegistry
94
-	checkIdent             bool
95 76
 	clients                *ClientManager
96 77
 	config                 *Config
97 78
 	configFilename         string
@@ -99,35 +80,23 @@ type Server struct {
99 80
 	connectionLimiter      *connection_limits.Limiter
100 81
 	connectionThrottler    *connection_limits.Throttler
101 82
 	ctime                  time.Time
102
-	defaultChannelModes    modes.Modes
103 83
 	dlines                 *DLineManager
104
-	loggingRawIO           bool
105 84
 	isupport               *isupport.List
106 85
 	klines                 *KLineManager
107 86
 	languages              *languages.Manager
108
-	limits                 Limits
109 87
 	listeners              map[string]*ListenerWrapper
110 88
 	logger                 *logger.Manager
111
-	maxSendQBytes          uint32
112 89
 	monitorManager         *MonitorManager
113 90
 	motdLines              []string
114 91
 	name                   string
115 92
 	nameCasefolded         string
116
-	networkName            string
117
-	operators              map[string]*Oper
118
-	operclasses            map[string]*OperClass
119
-	password               []byte
120 93
 	passwords              *passwd.SaltedManager
121
-	recoverFromErrors      bool
122 94
 	rehashMutex            sync.Mutex // tier 4
123 95
 	rehashSignal           chan os.Signal
124 96
 	pprofServer            *http.Server
125
-	proxyAllowedFrom       []string
126 97
 	signals                chan os.Signal
127 98
 	snomasks               *SnoManager
128 99
 	store                  *buntdb.DB
129
-	stsEnabled             bool
130
-	webirc                 []webircConfig
131 100
 	whoWas                 *WhoWasList
132 101
 	stats                  *Stats
133 102
 	semaphores             *ServerSemaphores
@@ -204,35 +173,35 @@ func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
204 173
 func (server *Server) setISupport() {
205 174
 	maxTargetsString := strconv.Itoa(maxTargets)
206 175
 
207
-	server.configurableStateMutex.RLock()
176
+	config := server.Config()
208 177
 
209 178
 	// add RPL_ISUPPORT tokens
210 179
 	isupport := isupport.NewList()
211
-	isupport.Add("AWAYLEN", strconv.Itoa(server.limits.AwayLen))
180
+	isupport.Add("AWAYLEN", strconv.Itoa(config.Limits.AwayLen))
212 181
 	isupport.Add("CASEMAPPING", "ascii")
213 182
 	isupport.Add("CHANMODES", strings.Join([]string{modes.Modes{modes.BanMask, modes.ExceptMask, modes.InviteMask}.String(), "", modes.Modes{modes.UserLimit, modes.Key}.String(), modes.Modes{modes.InviteOnly, modes.Moderated, modes.NoOutside, modes.OpOnlyTopic, modes.ChanRoleplaying, modes.Secret}.String()}, ","))
214
-	isupport.Add("CHANNELLEN", strconv.Itoa(server.limits.ChannelLen))
183
+	isupport.Add("CHANNELLEN", strconv.Itoa(config.Limits.ChannelLen))
215 184
 	isupport.Add("CHANTYPES", "#")
216 185
 	isupport.Add("ELIST", "U")
217 186
 	isupport.Add("EXCEPTS", "")
218 187
 	isupport.Add("INVEX", "")
219
-	isupport.Add("KICKLEN", strconv.Itoa(server.limits.KickLen))
220
-	isupport.Add("MAXLIST", fmt.Sprintf("beI:%s", strconv.Itoa(server.limits.ChanListModes)))
188
+	isupport.Add("KICKLEN", strconv.Itoa(config.Limits.KickLen))
189
+	isupport.Add("MAXLIST", fmt.Sprintf("beI:%s", strconv.Itoa(config.Limits.ChanListModes)))
221 190
 	isupport.Add("MAXTARGETS", maxTargetsString)
222 191
 	isupport.Add("MODES", "")
223
-	isupport.Add("MONITOR", strconv.Itoa(server.limits.MonitorEntries))
224
-	isupport.Add("NETWORK", server.networkName)
225
-	isupport.Add("NICKLEN", strconv.Itoa(server.limits.NickLen))
192
+	isupport.Add("MONITOR", strconv.Itoa(config.Limits.MonitorEntries))
193
+	isupport.Add("NETWORK", config.Network.Name)
194
+	isupport.Add("NICKLEN", strconv.Itoa(config.Limits.NickLen))
226 195
 	isupport.Add("PREFIX", "(qaohv)~&@%+")
227 196
 	isupport.Add("RPCHAN", "E")
228 197
 	isupport.Add("RPUSER", "E")
229 198
 	isupport.Add("STATUSMSG", "~&@%+")
230 199
 	isupport.Add("TARGMAX", fmt.Sprintf("NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:%s,TAGMSG:%s,NOTICE:%s,MONITOR:", maxTargetsString, maxTargetsString, maxTargetsString))
231
-	isupport.Add("TOPICLEN", strconv.Itoa(server.limits.TopicLen))
200
+	isupport.Add("TOPICLEN", strconv.Itoa(config.Limits.TopicLen))
232 201
 	isupport.Add("UTF8MAPPING", casemappingName)
233 202
 
234 203
 	// account registration
235
-	if server.config.Accounts.Registration.Enabled {
204
+	if config.Accounts.Registration.Enabled {
236 205
 		// 'none' isn't shown in the REGCALLBACKS vars
237 206
 		var enabledCallbacks []string
238 207
 		for _, name := range server.config.Accounts.Registration.EnabledCallbacks {
@@ -246,8 +215,6 @@ func (server *Server) setISupport() {
246 215
 		isupport.Add("REGCREDTYPES", "passphrase,certfp")
247 216
 	}
248 217
 
249
-	server.configurableStateMutex.RUnlock()
250
-
251 218
 	isupport.RegenerateCachedReply()
252 219
 
253 220
 	server.configurableStateMutex.Lock()
@@ -672,7 +639,7 @@ func (client *Client) getWhoisOf(target *Client, rb *ResponseBuffer) {
672 639
 		rb.Add(nil, client.server.name, RPL_WHOISACCOUNT, client.nick, target.AccountName(), client.t("is logged in as"))
673 640
 	}
674 641
 	if target.HasMode(modes.Bot) {
675
-		rb.Add(nil, client.server.name, RPL_WHOISBOT, client.nick, target.nick, ircfmt.Unescape(fmt.Sprintf(client.t("is a $bBot$b on %s"), client.server.networkName)))
642
+		rb.Add(nil, client.server.name, RPL_WHOISBOT, client.nick, target.nick, ircfmt.Unescape(fmt.Sprintf(client.t("is a $bBot$b on %s"), client.server.Config().Network.Name)))
676 643
 	}
677 644
 
678 645
 	if 0 < len(target.languages) {
@@ -744,13 +711,16 @@ func (server *Server) rehash() error {
744 711
 	return nil
745 712
 }
746 713
 
747
-func (server *Server) applyConfig(config *Config, initial bool) error {
714
+func (server *Server) applyConfig(config *Config, initial bool) (err error) {
748 715
 	if initial {
749 716
 		server.ctime = time.Now()
750 717
 		server.configFilename = config.Filename
718
+		server.name = config.Server.Name
719
+		server.nameCasefolded = config.Server.nameCasefolded
751 720
 	} else {
752 721
 		// enforce configs that can't be changed after launch:
753
-		if server.limits.LineLen.Tags != config.Limits.LineLen.Tags || server.limits.LineLen.Rest != config.Limits.LineLen.Rest {
722
+		currentLimits := server.Limits()
723
+		if currentLimits.LineLen.Tags != config.Limits.LineLen.Tags || currentLimits.LineLen.Rest != config.Limits.LineLen.Rest {
754 724
 			return fmt.Errorf("Maximum line length (linelen) cannot be changed after launching the server, rehash aborted")
755 725
 		} else if server.name != config.Server.Name {
756 726
 			return fmt.Errorf("Server name cannot be changed after launching the server, rehash aborted")
@@ -759,58 +729,31 @@ func (server *Server) applyConfig(config *Config, initial bool) error {
759 729
 		}
760 730
 	}
761 731
 
732
+	// sanity checks complete, start modifying server state
762 733
 	server.logger.Info("rehash", "Using config file", server.configFilename)
734
+	oldConfig := server.Config()
763 735
 
764
-	casefoldedName, err := Casefold(config.Server.Name)
765
-	if err != nil {
766
-		return fmt.Errorf("Server name isn't valid [%s]: %s", config.Server.Name, err.Error())
767
-	}
736
+	// first, reload config sections for functionality implemented in subpackages:
768 737
 
769
-	// confirm operator stuff all exists and is fine
770
-	operclasses, err := config.OperatorClasses()
771
-	if err != nil {
772
-		return fmt.Errorf("Error rehashing config file operclasses: %s", err.Error())
773
-	}
774
-	opers, err := config.Operators(operclasses)
738
+	err = server.connectionLimiter.ApplyConfig(config.Server.ConnectionLimiter)
775 739
 	if err != nil {
776
-		return fmt.Errorf("Error rehashing config file opers: %s", err.Error())
777
-	}
778
-
779
-	// TODO: support rehash of existing operator perms?
780
-
781
-	// sanity checks complete, start modifying server state
782
-
783
-	if initial {
784
-		server.name = config.Server.Name
785
-		server.nameCasefolded = casefoldedName
786
-	}
787
-
788
-	server.configurableStateMutex.Lock()
789
-	server.networkName = config.Network.Name
790
-	if config.Server.Password != "" {
791
-		server.password = config.Server.PasswordBytes()
792
-	} else {
793
-		server.password = nil
794
-	}
795
-	// apply new WebIRC command restrictions
796
-	server.webirc = config.Server.WebIRC
797
-	// apply new PROXY command restrictions
798
-	server.proxyAllowedFrom = config.Server.ProxyAllowedFrom
799
-	server.recoverFromErrors = true
800
-	if config.Debug.RecoverFromErrors != nil {
801
-		server.recoverFromErrors = *config.Debug.RecoverFromErrors
740
+		return err
802 741
 	}
803
-	server.configurableStateMutex.Unlock()
804 742
 
805
-	err = server.connectionLimiter.ApplyConfig(config.Server.ConnectionLimiter)
743
+	err = server.connectionThrottler.ApplyConfig(config.Server.ConnectionThrottler)
806 744
 	if err != nil {
807 745
 		return err
808 746
 	}
809 747
 
810
-	err = server.connectionThrottler.ApplyConfig(config.Server.ConnectionThrottler)
748
+	// reload logging config
749
+	wasLoggingRawIO := !initial && server.logger.IsLoggingRawIO()
750
+	err = server.logger.ApplyConfig(config.Logging)
811 751
 	if err != nil {
812 752
 		return err
813 753
 	}
754
+	nowLoggingRawIO := server.logger.IsLoggingRawIO()
755
+	// notify existing clients if raw i/o logging was enabled by a rehash
756
+	sendRawOutputNotice := !wasLoggingRawIO && nowLoggingRawIO
814 757
 
815 758
 	// setup new and removed caps
816 759
 	addedCaps := caps.NewSet()
@@ -844,8 +787,7 @@ func (server *Server) applyConfig(config *Config, initial bool) error {
844 787
 	server.languages = lm
845 788
 
846 789
 	// SASL
847
-	oldAccountConfig := server.AccountConfig()
848
-	authPreviouslyEnabled := oldAccountConfig != nil && oldAccountConfig.AuthenticationEnabled
790
+	authPreviouslyEnabled := oldConfig != nil && oldConfig.Accounts.AuthenticationEnabled
849 791
 	if config.Accounts.AuthenticationEnabled && !authPreviouslyEnabled {
850 792
 		// enabling SASL
851 793
 		SupportedCapabilities.Enable(caps.SASL)
@@ -857,39 +799,39 @@ func (server *Server) applyConfig(config *Config, initial bool) error {
857 799
 		removedCaps.Add(caps.SASL)
858 800
 	}
859 801
 
860
-	nickReservationPreviouslyDisabled := oldAccountConfig != nil && !oldAccountConfig.NickReservation.Enabled
802
+	nickReservationPreviouslyDisabled := oldConfig != nil && !oldConfig.Accounts.NickReservation.Enabled
861 803
 	nickReservationNowEnabled := config.Accounts.NickReservation.Enabled
862 804
 	if nickReservationPreviouslyDisabled && nickReservationNowEnabled {
863 805
 		server.accounts.buildNickToAccountIndex()
864 806
 	}
865 807
 
866
-	hsPreviouslyDisabled := oldAccountConfig != nil && !oldAccountConfig.VHosts.Enabled
808
+	hsPreviouslyDisabled := oldConfig != nil && !oldConfig.Accounts.VHosts.Enabled
867 809
 	hsNowEnabled := config.Accounts.VHosts.Enabled
868 810
 	if hsPreviouslyDisabled && hsNowEnabled {
869 811
 		server.accounts.initVHostRequestQueue()
870 812
 	}
871 813
 
872 814
 	// STS
815
+	stsPreviouslyEnabled := oldConfig != nil && oldConfig.Server.STS.Enabled
873 816
 	stsValue := config.Server.STS.Value()
874
-	var stsDisabled bool
817
+	stsDisabledByRehash := false
875 818
 	stsCurrentCapValue, _ := CapValues.Get(caps.STS)
876
-	server.logger.Debug("rehash", "STS Vals", stsCurrentCapValue, stsValue, fmt.Sprintf("server[%v] config[%v]", server.stsEnabled, config.Server.STS.Enabled))
877
-	if config.Server.STS.Enabled && !server.stsEnabled {
819
+	server.logger.Debug("rehash", "STS Vals", stsCurrentCapValue, stsValue, fmt.Sprintf("server[%v] config[%v]", stsPreviouslyEnabled, config.Server.STS.Enabled))
820
+	if config.Server.STS.Enabled && !stsPreviouslyEnabled {
878 821
 		// enabling STS
879 822
 		SupportedCapabilities.Enable(caps.STS)
880 823
 		addedCaps.Add(caps.STS)
881 824
 		CapValues.Set(caps.STS, stsValue)
882
-	} else if !config.Server.STS.Enabled && server.stsEnabled {
825
+	} else if !config.Server.STS.Enabled && stsPreviouslyEnabled {
883 826
 		// disabling STS
884 827
 		SupportedCapabilities.Disable(caps.STS)
885 828
 		removedCaps.Add(caps.STS)
886
-		stsDisabled = true
887
-	} else if config.Server.STS.Enabled && server.stsEnabled && stsValue != stsCurrentCapValue {
829
+		stsDisabledByRehash = true
830
+	} else if config.Server.STS.Enabled && stsPreviouslyEnabled && stsValue != stsCurrentCapValue {
888 831
 		// STS policy updated
889 832
 		CapValues.Set(caps.STS, stsValue)
890 833
 		updatedCaps.Add(caps.STS)
891 834
 	}
892
-	server.stsEnabled = config.Server.STS.Enabled
893 835
 
894 836
 	// burst new and removed caps
895 837
 	var capBurstClients ClientSet
@@ -912,7 +854,7 @@ func (server *Server) applyConfig(config *Config, initial bool) error {
912 854
 	}
913 855
 
914 856
 	for sClient := range capBurstClients {
915
-		if stsDisabled {
857
+		if stsDisabledByRehash {
916 858
 			// remove STS policy
917 859
 			//TODO(dan): this is an ugly hack. we can write this better.
918 860
 			stsPolicy := "sts=duration=0"
@@ -932,44 +874,8 @@ func (server *Server) applyConfig(config *Config, initial bool) error {
932 874
 		}
933 875
 	}
934 876
 
935
-	// set server options
936
-	server.configurableStateMutex.Lock()
937
-	lineLenConfig := LineLenLimits{
938
-		Tags: config.Limits.LineLen.Tags,
939
-		Rest: config.Limits.LineLen.Rest,
940
-	}
941
-	server.limits = Limits{
942
-		AwayLen:        int(config.Limits.AwayLen),
943
-		ChannelLen:     int(config.Limits.ChannelLen),
944
-		KickLen:        int(config.Limits.KickLen),
945
-		MonitorEntries: int(config.Limits.MonitorEntries),
946
-		NickLen:        int(config.Limits.NickLen),
947
-		TopicLen:       int(config.Limits.TopicLen),
948
-		ChanListModes:  int(config.Limits.ChanListModes),
949
-		LineLen:        lineLenConfig,
950
-	}
951
-	server.operclasses = operclasses
952
-	server.operators = opers
953
-	server.checkIdent = config.Server.CheckIdent
954
-
955
-	server.defaultChannelModes = ParseDefaultChannelModes(config)
956
-	server.configurableStateMutex.Unlock()
957
-
958
-	// set new sendqueue size
959
-	server.SetMaxSendQBytes(config.Server.MaxSendQBytes)
960
-
961 877
 	server.loadMOTD(config.Server.MOTD, config.Server.MOTDFormatting)
962 878
 
963
-	// reload logging config
964
-	err = server.logger.ApplyConfig(config.Logging)
965
-	if err != nil {
966
-		return err
967
-	}
968
-	nowLoggingRawIO := server.logger.IsLoggingRawIO()
969
-	// notify clients if raw i/o logging was enabled by a rehash
970
-	sendRawOutputNotice := !initial && !server.loggingRawIO && nowLoggingRawIO
971
-	server.loggingRawIO = nowLoggingRawIO
972
-
973 879
 	// save a pointer to the new config
974 880
 	server.configurableStateMutex.Lock()
975 881
 	server.config = config

+ 3
- 5
irc/utils/bitset.go View File

@@ -52,11 +52,9 @@ func BitsetSet(set []uint64, position uint, on bool) (changed bool) {
52 52
 }
53 53
 
54 54
 // BitsetEmpty returns whether the bitset is empty.
55
-// Right now, this is technically free of race conditions because we don't
56
-// have a method that can simultaneously modify two bits separated by a word boundary
57
-// such that one of those modifications is an unset. If we did, there would be a race
58
-// that could produce false positives. It's probably better to assume that they are
59
-// already possible under concurrent modification (which is not how we're using this).
55
+// This has false positives under concurrent modification (i.e., it can return true
56
+// even though w.r.t. the sequence of atomic modifications, there was no point at
57
+// which the bitset was completely empty), but that's not how we're using this method.
60 58
 func BitsetEmpty(set []uint64) (empty bool) {
61 59
 	for i := 0; i < len(set); i++ {
62 60
 		if atomic.LoadUint64(&set[i]) != 0 {

+ 1
- 1
irc/whowas.go View File

@@ -32,7 +32,7 @@ type WhoWas struct {
32 32
 }
33 33
 
34 34
 // NewWhoWasList returns a new WhoWasList
35
-func NewWhoWasList(size uint) *WhoWasList {
35
+func NewWhoWasList(size int) *WhoWasList {
36 36
 	return &WhoWasList{
37 37
 		buffer: make([]WhoWas, size),
38 38
 		start:  -1,

Loading…
Cancel
Save