|
@@ -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
|