|
@@ -39,6 +39,7 @@ type Server struct {
|
39
|
39
|
channels ChannelNameMap
|
40
|
40
|
clients *ClientLookupSet
|
41
|
41
|
commands chan Command
|
|
42
|
+ configFilename string
|
42
|
43
|
ctime time.Time
|
43
|
44
|
store buntdb.DB
|
44
|
45
|
idle chan *Client
|
|
@@ -47,6 +48,7 @@ type Server struct {
|
47
|
48
|
motdLines []string
|
48
|
49
|
name string
|
49
|
50
|
nameCasefolded string
|
|
51
|
+ networkName string
|
50
|
52
|
newConns chan clientConn
|
51
|
53
|
operators map[string][]byte
|
52
|
54
|
password []byte
|
|
@@ -72,7 +74,8 @@ type clientConn struct {
|
72
|
74
|
IsTLS bool
|
73
|
75
|
}
|
74
|
76
|
|
75
|
|
-func NewServer(config *Config) *Server {
|
|
77
|
+// NewServer returns a new Oragono server.
|
|
78
|
+func NewServer(configFilename string, config *Config) *Server {
|
76
|
79
|
casefoldedName, err := Casefold(config.Server.Name)
|
77
|
80
|
if err != nil {
|
78
|
81
|
log.Println(fmt.Sprintf("Server name isn't valid: [%s]", config.Server.Name), err.Error())
|
|
@@ -80,12 +83,13 @@ func NewServer(config *Config) *Server {
|
80
|
83
|
}
|
81
|
84
|
|
82
|
85
|
server := &Server{
|
83
|
|
- accounts: make(map[string]*ClientAccount),
|
84
|
|
- channels: make(ChannelNameMap),
|
85
|
|
- clients: NewClientLookupSet(),
|
86
|
|
- commands: make(chan Command),
|
87
|
|
- ctime: time.Now(),
|
88
|
|
- idle: make(chan *Client),
|
|
86
|
+ accounts: make(map[string]*ClientAccount),
|
|
87
|
+ channels: make(ChannelNameMap),
|
|
88
|
+ clients: NewClientLookupSet(),
|
|
89
|
+ commands: make(chan Command),
|
|
90
|
+ configFilename: configFilename,
|
|
91
|
+ ctime: time.Now(),
|
|
92
|
+ idle: make(chan *Client),
|
89
|
93
|
limits: Limits{
|
90
|
94
|
AwayLen: int(config.Limits.AwayLen),
|
91
|
95
|
ChannelLen: int(config.Limits.ChannelLen),
|
|
@@ -97,6 +101,7 @@ func NewServer(config *Config) *Server {
|
97
|
101
|
monitoring: make(map[string][]Client),
|
98
|
102
|
name: config.Server.Name,
|
99
|
103
|
nameCasefolded: casefoldedName,
|
|
104
|
+ networkName: config.Network.Name,
|
100
|
105
|
newConns: make(chan clientConn),
|
101
|
106
|
operators: config.Operators(),
|
102
|
107
|
signals: make(chan os.Signal, len(SERVER_SIGNALS)),
|
|
@@ -171,6 +176,13 @@ func NewServer(config *Config) *Server {
|
171
|
176
|
// Attempt to clean up when receiving these signals.
|
172
|
177
|
signal.Notify(server.signals, SERVER_SIGNALS...)
|
173
|
178
|
|
|
179
|
+ server.setISupport()
|
|
180
|
+
|
|
181
|
+ return server
|
|
182
|
+}
|
|
183
|
+
|
|
184
|
+// setISupport sets up our RPL_ISUPPORT reply.
|
|
185
|
+func (server *Server) setISupport() {
|
174
|
186
|
// add RPL_ISUPPORT tokens
|
175
|
187
|
server.isupport = NewISupportList()
|
176
|
188
|
server.isupport.Add("AWAYLEN", strconv.Itoa(server.limits.AwayLen))
|
|
@@ -184,7 +196,7 @@ func NewServer(config *Config) *Server {
|
184
|
196
|
// server.isupport.Add("MAXLIST", "") //TODO(dan): Support max list length?
|
185
|
197
|
// server.isupport.Add("MODES", "") //TODO(dan): Support max modes?
|
186
|
198
|
server.isupport.Add("MONITOR", strconv.Itoa(server.limits.MonitorEntries))
|
187
|
|
- server.isupport.Add("NETWORK", config.Network.Name)
|
|
199
|
+ server.isupport.Add("NETWORK", server.networkName)
|
188
|
200
|
server.isupport.Add("NICKLEN", strconv.Itoa(server.limits.NickLen))
|
189
|
201
|
server.isupport.Add("PREFIX", "(qaohv)~&@%+")
|
190
|
202
|
// server.isupport.Add("STATUSMSG", "@+") //TODO(dan): Support STATUSMSG
|
|
@@ -207,8 +219,6 @@ func NewServer(config *Config) *Server {
|
207
|
219
|
}
|
208
|
220
|
|
209
|
221
|
server.isupport.RegenerateCachedReply()
|
210
|
|
-
|
211
|
|
- return server
|
212
|
222
|
}
|
213
|
223
|
|
214
|
224
|
func loadChannelList(channel *Channel, list string, maskMode ChannelMode) {
|
|
@@ -220,7 +230,7 @@ func loadChannelList(channel *Channel, list string, maskMode ChannelMode) {
|
220
|
230
|
|
221
|
231
|
func (server *Server) Shutdown() {
|
222
|
232
|
//TODO(dan): Make sure we disallow new nicks
|
223
|
|
- for _, client := range server.clients.byNick {
|
|
233
|
+ for _, client := range server.clients.ByNick {
|
224
|
234
|
client.Notice("Server is shutting down")
|
225
|
235
|
}
|
226
|
236
|
|
|
@@ -511,13 +521,16 @@ func joinHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
511
|
521
|
for i, name := range channels {
|
512
|
522
|
casefoldedName, err := CasefoldChannel(name)
|
513
|
523
|
if err != nil {
|
514
|
|
- log.Println("ISN'T CHANNEL NAME:", name)
|
515
|
524
|
client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, name, "No such channel")
|
516
|
525
|
continue
|
517
|
526
|
}
|
518
|
527
|
|
519
|
528
|
channel := server.channels.Get(casefoldedName)
|
520
|
529
|
if channel == nil {
|
|
530
|
+ if len(casefoldedName) > server.limits.ChannelLen {
|
|
531
|
+ client.Send(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, name, "No such channel")
|
|
532
|
+ continue
|
|
533
|
+ }
|
521
|
534
|
channel = NewChannel(server, name, true)
|
522
|
535
|
}
|
523
|
536
|
|
|
@@ -780,6 +793,50 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
780
|
793
|
return false
|
781
|
794
|
}
|
782
|
795
|
|
|
796
|
+// REHASH
|
|
797
|
+func rehashHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
|
798
|
+ config, err := LoadConfig(server.configFilename)
|
|
799
|
+
|
|
800
|
+ if err != nil {
|
|
801
|
+ client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, "REHASH", fmt.Sprintf("Error rehashing config file: %s", err.Error()))
|
|
802
|
+ return false
|
|
803
|
+ }
|
|
804
|
+
|
|
805
|
+ //TODO(dan): burst CAP DEL for sasl
|
|
806
|
+
|
|
807
|
+ // set server options
|
|
808
|
+ server.limits = Limits{
|
|
809
|
+ AwayLen: int(config.Limits.AwayLen),
|
|
810
|
+ ChannelLen: int(config.Limits.ChannelLen),
|
|
811
|
+ KickLen: int(config.Limits.KickLen),
|
|
812
|
+ MonitorEntries: int(config.Limits.MonitorEntries),
|
|
813
|
+ NickLen: int(config.Limits.NickLen),
|
|
814
|
+ TopicLen: int(config.Limits.TopicLen),
|
|
815
|
+ }
|
|
816
|
+ server.operators = config.Operators()
|
|
817
|
+ server.checkIdent = config.Server.CheckIdent
|
|
818
|
+
|
|
819
|
+ // registration
|
|
820
|
+ accountReg := NewAccountRegistration(config.Registration.Accounts)
|
|
821
|
+ server.accountRegistration = &accountReg
|
|
822
|
+
|
|
823
|
+ // set RPL_ISUPPORT
|
|
824
|
+ oldISupportList := server.isupport
|
|
825
|
+ server.setISupport()
|
|
826
|
+ newISupportReplies := oldISupportList.GetDifference(server.isupport)
|
|
827
|
+
|
|
828
|
+ // push new info to all of our clients
|
|
829
|
+ for _, sClient := range server.clients.ByNick {
|
|
830
|
+ for _, tokenline := range newISupportReplies {
|
|
831
|
+ // ugly trickery ahead
|
|
832
|
+ sClient.Send(nil, client.server.name, RPL_ISUPPORT, append([]string{sClient.nick}, tokenline...)...)
|
|
833
|
+ }
|
|
834
|
+ }
|
|
835
|
+
|
|
836
|
+ client.Send(nil, server.name, RPL_REHASHING, client.nick, "ircd.yaml", "Rehashing")
|
|
837
|
+ return false
|
|
838
|
+}
|
|
839
|
+
|
783
|
840
|
// AWAY [<message>]
|
784
|
841
|
func awayHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
785
|
842
|
var isAway bool
|