Преглед изворни кода

refactor monitor and /oper implementations

tags/v0.9.2-beta
Shivaram Lingamneni пре 6 година
родитељ
комит
26686d7e86
5 измењених фајлова са 184 додато и 172 уклоњено
  1. 28
    31
      irc/client.go
  2. 18
    0
      irc/getters.go
  3. 119
    115
      irc/monitor.go
  4. 1
    1
      irc/nickname.go
  5. 18
    25
      irc/server.go

+ 28
- 31
irc/client.go Прегледај датотеку

@@ -61,8 +61,6 @@ type Client struct {
61 61
 	idleTimer          *time.Timer
62 62
 	isDestroyed        bool
63 63
 	isQuitting         bool
64
-	monitoring         map[string]bool
65
-	monitoringMutex    sync.RWMutex
66 64
 	nick               string
67 65
 	nickCasefolded     string
68 66
 	nickMaskCasefolded string
@@ -81,6 +79,7 @@ type Client struct {
81 79
 	saslValue          string
82 80
 	server             *Server
83 81
 	socket             *Socket
82
+	stateMutex         sync.RWMutex // generic protection for mutable state
84 83
 	timerMutex         sync.Mutex
85 84
 	username           string
86 85
 	vhost              string
@@ -101,7 +100,6 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) *Client {
101 100
 		channels:       make(ChannelSet),
102 101
 		ctime:          now,
103 102
 		flags:          make(map[Mode]bool),
104
-		monitoring:     make(map[string]bool),
105 103
 		server:         server,
106 104
 		socket:         &socket,
107 105
 		account:        &NoAccount,
@@ -302,8 +300,8 @@ func (client *Client) Register() {
302 300
 	client.registered = true
303 301
 	client.Touch()
304 302
 
305
-	client.updateNickMask()
306
-	client.alertMonitors()
303
+	client.updateNickMask("")
304
+	client.server.monitorManager.alertMonitors(client, true)
307 305
 }
308 306
 
309 307
 // IdleTime returns how long this client's been idle.
@@ -393,19 +391,28 @@ func (client *Client) Friends(capabs ...caps.Capability) ClientSet {
393 391
 	return friends
394 392
 }
395 393
 
396
-// updateNick updates the casefolded nickname.
397
-func (client *Client) updateNick() {
398
-	casefoldedName, err := CasefoldName(client.nick)
394
+// updateNick updates `nick` and `nickCasefolded`.
395
+func (client *Client) updateNick(nick string) {
396
+	casefoldedName, err := CasefoldName(nick)
399 397
 	if err != nil {
400 398
 		log.Println(fmt.Sprintf("ERROR: Nick [%s] couldn't be casefolded... this should never happen. Printing stacktrace.", client.nick))
401 399
 		debug.PrintStack()
402 400
 	}
401
+	client.stateMutex.Lock()
402
+	client.nick = nick
403 403
 	client.nickCasefolded = casefoldedName
404
+	client.stateMutex.Unlock()
404 405
 }
405 406
 
406 407
 // updateNickMask updates the casefolded nickname and nickmask.
407
-func (client *Client) updateNickMask() {
408
-	client.updateNick()
408
+func (client *Client) updateNickMask(nick string) {
409
+	// on "", just regenerate the nickmask etc.
410
+	// otherwise, update the actual nick
411
+	if nick != "" {
412
+		client.updateNick(nick)
413
+	}
414
+
415
+	client.stateMutex.Lock()
409 416
 
410 417
 	if len(client.vhost) > 0 {
411 418
 		client.hostname = client.vhost
@@ -413,14 +420,17 @@ func (client *Client) updateNickMask() {
413 420
 		client.hostname = client.rawHostname
414 421
 	}
415 422
 
416
-	client.nickMaskString = fmt.Sprintf("%s!%s@%s", client.nick, client.username, client.hostname)
417
-
418
-	nickMaskCasefolded, err := Casefold(client.nickMaskString)
423
+	nickMaskString := fmt.Sprintf("%s!%s@%s", client.nick, client.username, client.hostname)
424
+	nickMaskCasefolded, err := Casefold(nickMaskString)
419 425
 	if err != nil {
420 426
 		log.Println(fmt.Sprintf("ERROR: Nickmask [%s] couldn't be casefolded... this should never happen. Printing stacktrace.", client.nickMaskString))
421 427
 		debug.PrintStack()
422 428
 	}
429
+
430
+	client.nickMaskString = nickMaskString
423 431
 	client.nickMaskCasefolded = nickMaskCasefolded
432
+
433
+	client.stateMutex.Unlock()
424 434
 }
425 435
 
426 436
 // AllNickmasks returns all the possible nickmasks for the client.
@@ -458,8 +468,7 @@ func (client *Client) SetNickname(nickname string) error {
458 468
 
459 469
 	err := client.server.clients.Add(client, nickname)
460 470
 	if err == nil {
461
-		client.nick = nickname
462
-		client.updateNick()
471
+		client.updateNick(nickname)
463 472
 	}
464 473
 	return err
465 474
 }
@@ -472,8 +481,7 @@ func (client *Client) ChangeNickname(nickname string) error {
472 481
 		client.server.logger.Debug("nick", fmt.Sprintf("%s changed nickname to %s", client.nick, nickname))
473 482
 		client.server.snomasks.Send(sno.LocalNicks, fmt.Sprintf(ircfmt.Unescape("$%s$r changed nickname to %s"), client.nick, nickname))
474 483
 		client.server.whoWas.Append(client)
475
-		client.nick = nickname
476
-		client.updateNickMask()
484
+		client.updateNickMask(nickname)
477 485
 		for friend := range client.Friends() {
478 486
 			friend.Send(nil, origNickMask, "NICK", nickname)
479 487
 		}
@@ -530,21 +538,10 @@ func (client *Client) destroy() {
530 538
 		client.server.connectionLimitsMutex.Unlock()
531 539
 	}
532 540
 
533
-	// remove from opers list
534
-	_, exists := client.server.currentOpers[client]
535
-	if exists {
536
-		delete(client.server.currentOpers, client)
537
-	}
538
-
539 541
 	// alert monitors
540
-	client.server.monitoringMutex.RLock()
541
-	for _, mClient := range client.server.monitoring[client.nickCasefolded] {
542
-		mClient.Send(nil, client.server.name, RPL_MONOFFLINE, mClient.nick, client.nick)
543
-	}
544
-	client.server.monitoringMutex.RUnlock()
545
-
546
-	// remove my monitors
547
-	client.clearMonitorList()
542
+	client.server.monitorManager.alertMonitors(client, false)
543
+	// clean up monitor state
544
+	client.server.monitorManager.clearMonitorList(client)
548 545
 
549 546
 	// clean up channels
550 547
 	client.server.channelJoinPartMutex.Lock()

+ 18
- 0
irc/getters.go Прегледај датотеку

@@ -20,3 +20,21 @@ func (server *Server) getPassword() []byte {
20 20
 	defer server.configurableStateMutex.RUnlock()
21 21
 	return server.password
22 22
 }
23
+
24
+func (client *Client) getNick() string {
25
+	client.stateMutex.RLock()
26
+	defer client.stateMutex.RUnlock()
27
+	return client.nick
28
+}
29
+
30
+func (client *Client) getNickMaskString() string {
31
+	client.stateMutex.RLock()
32
+	defer client.stateMutex.RUnlock()
33
+	return client.nickMaskString
34
+}
35
+
36
+func (client *Client) getNickCasefolded() string {
37
+	client.stateMutex.RLock()
38
+	defer client.stateMutex.RUnlock()
39
+	return client.nickCasefolded
40
+}

+ 119
- 115
irc/monitor.go Прегледај датотеку

@@ -4,50 +4,108 @@
4 4
 package irc
5 5
 
6 6
 import (
7
+	"errors"
7 8
 	"strconv"
8 9
 	"strings"
10
+	"sync"
9 11
 
10 12
 	"github.com/goshuirc/irc-go/ircmsg"
11 13
 )
12 14
 
13
-// alertMonitors alerts everyone monitoring us that we're online.
14
-func (client *Client) alertMonitors() {
15
-	// get monitors
16
-	client.server.monitoringMutex.RLock()
17
-	monitors := client.server.monitoring[client.nickCasefolded]
18
-	client.server.monitoringMutex.RUnlock()
19
-
20
-	// alert monitors
21
-	for _, mClient := range monitors {
22
-		// don't have to notify ourselves
23
-		if mClient != client {
24
-			mClient.SendFromClient("", client, nil, RPL_MONONLINE, mClient.nick, client.nickMaskString)
25
-		}
15
+type MonitorManager struct {
16
+	sync.RWMutex
17
+	// client -> nicks it's watching
18
+	watching map[*Client]map[string]bool
19
+	// nick -> clients watching it
20
+	watchedby map[string]map[*Client]bool
21
+	// (all nicks must be normalized externally by casefolding)
22
+}
23
+
24
+func NewMonitorManager() *MonitorManager {
25
+	mm := MonitorManager{
26
+		watching:  make(map[*Client]map[string]bool),
27
+		watchedby: make(map[string]map[*Client]bool),
26 28
 	}
29
+	return &mm
27 30
 }
28 31
 
29
-// clearMonitorList clears our MONITOR list.
30
-func (client *Client) clearMonitorList() {
31
-	// lockin' everything
32
-	client.monitoringMutex.Lock()
33
-	defer client.monitoringMutex.Unlock()
34
-	client.server.monitoringMutex.Lock()
35
-	defer client.server.monitoringMutex.Unlock()
36
-
37
-	for name := range client.monitoring {
38
-		// just removes current client from the list
39
-		orig := client.server.monitoring[name]
40
-		var index int
41
-		for i, cli := range orig {
42
-			if cli == client {
43
-				index = i
44
-				break
32
+var MonitorLimitExceeded = errors.New("Monitor limit exceeded")
33
+
34
+// alertMonitors alerts everyone monitoring us that we're online.
35
+func (manager *MonitorManager) alertMonitors(client *Client, online bool) {
36
+	cfnick := client.getNickCasefolded()
37
+	nick := client.getNick()
38
+	var watchers []*Client
39
+	// safely copy the list of clients watching our nick
40
+	manager.RLock()
41
+	for client := range manager.watchedby[cfnick] {
42
+		watchers = append(watchers, client)
43
+	}
44
+	manager.RUnlock()
45
+
46
+	command := RPL_MONOFFLINE
47
+	if online {
48
+		command = RPL_MONONLINE
49
+	}
50
+
51
+	// asynchronously send all the notifications
52
+	go func() {
53
+		for _, mClient := range watchers {
54
+			// don't have to notify ourselves
55
+			if mClient != client {
56
+				mClient.SendFromClient("", client, nil, command, mClient.getNick(), nick)
45 57
 			}
46 58
 		}
47
-		client.server.monitoring[name] = append(orig[:index], orig[index+1:]...)
59
+	}()
60
+}
61
+
62
+// clearMonitorList clears our MONITOR list.
63
+func (manager *MonitorManager) clearMonitorList(client *Client) {
64
+	manager.Lock()
65
+	defer manager.Unlock()
66
+
67
+	for nick, _ := range manager.watching[client] {
68
+		delete(manager.watchedby[nick], client)
69
+	}
70
+	delete(manager.watching, client)
71
+}
72
+
73
+func (manager *MonitorManager) addMonitor(client *Client, nick string, limit int) error {
74
+	manager.Lock()
75
+	defer manager.Unlock()
76
+
77
+	if manager.watching[client] == nil {
78
+		manager.watching[client] = make(map[string]bool)
79
+	}
80
+	if manager.watchedby[nick] == nil {
81
+		manager.watchedby[nick] = make(map[*Client]bool)
48 82
 	}
49 83
 
50
-	client.monitoring = make(map[string]bool)
84
+	if len(manager.watching[client]) >= limit {
85
+		return MonitorLimitExceeded
86
+	}
87
+
88
+	manager.watching[client][nick] = true
89
+	manager.watchedby[nick][client] = true
90
+	return nil
91
+}
92
+
93
+func (manager *MonitorManager) removeMonitor(client *Client, nick string) error {
94
+	manager.Lock()
95
+	defer manager.Unlock()
96
+	// deleting from nil maps is fine
97
+	delete(manager.watching[client], nick)
98
+	delete(manager.watchedby[nick], client)
99
+	return nil
100
+}
101
+
102
+func (manager *MonitorManager) listMonitors(client *Client) (nicks []string) {
103
+	manager.RLock()
104
+	defer manager.RUnlock()
105
+	for nick := range manager.watching[client] {
106
+		nicks = append(nicks, nick)
107
+	}
108
+	return nicks
51 109
 }
52 110
 
53 111
 var (
@@ -64,7 +122,7 @@ func monitorHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool
64 122
 	handler, exists := metadataSubcommands[strings.ToLower(msg.Params[0])]
65 123
 
66 124
 	if !exists {
67
-		client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, "MONITOR", msg.Params[0], "Unknown subcommand")
125
+		client.Send(nil, server.name, ERR_UNKNOWNERROR, client.getNick(), "MONITOR", msg.Params[0], "Unknown subcommand")
68 126
 		return false
69 127
 	}
70 128
 
@@ -73,49 +131,17 @@ func monitorHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool
73 131
 
74 132
 func monitorRemoveHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
75 133
 	if len(msg.Params) < 2 {
76
-		client.Send(nil, server.name, ERR_NEEDMOREPARAMS, client.nick, msg.Command, "Not enough parameters")
134
+		client.Send(nil, server.name, ERR_NEEDMOREPARAMS, client.getNick(), msg.Command, "Not enough parameters")
77 135
 		return false
78 136
 	}
79 137
 
80 138
 	targets := strings.Split(msg.Params[1], ",")
81
-	for len(targets) > 0 {
82
-		// check name length
83
-		if len(targets[0]) < 1 {
84
-			targets = targets[1:]
85
-			continue
86
-		}
87
-
88
-		// remove target
89
-		casefoldedTarget, err := CasefoldName(targets[0])
139
+	for _, target := range targets {
140
+		cfnick, err := CasefoldName(target)
90 141
 		if err != nil {
91
-			// skip silently I guess
92
-			targets = targets[1:]
93 142
 			continue
94 143
 		}
95
-
96
-		client.monitoringMutex.Lock()
97
-		client.server.monitoringMutex.Lock()
98
-
99
-		if client.monitoring[casefoldedTarget] {
100
-			// just removes current client from the list
101
-			orig := server.monitoring[casefoldedTarget]
102
-			var index int
103
-			for i, cli := range orig {
104
-				if cli == client {
105
-					index = i
106
-					break
107
-				}
108
-			}
109
-			server.monitoring[casefoldedTarget] = append(orig[:index], orig[index+1:]...)
110
-
111
-			delete(client.monitoring, casefoldedTarget)
112
-		}
113
-
114
-		client.monitoringMutex.Unlock()
115
-		client.server.monitoringMutex.Unlock()
116
-
117
-		// remove first element of targets list
118
-		targets = targets[1:]
144
+		server.monitorManager.removeMonitor(client, cfnick)
119 145
 	}
120 146
 
121 147
 	return false
@@ -123,88 +149,68 @@ func monitorRemoveHandler(server *Server, client *Client, msg ircmsg.IrcMessage)
123 149
 
124 150
 func monitorAddHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
125 151
 	if len(msg.Params) < 2 {
126
-		client.Send(nil, server.name, ERR_NEEDMOREPARAMS, client.nick, msg.Command, "Not enough parameters")
152
+		client.Send(nil, server.name, ERR_NEEDMOREPARAMS, client.getNick(), msg.Command, "Not enough parameters")
127 153
 		return false
128 154
 	}
129 155
 
130 156
 	var online []string
131 157
 	var offline []string
132 158
 
159
+	limit := server.getLimits().MonitorEntries
160
+
133 161
 	targets := strings.Split(msg.Params[1], ",")
134
-	for len(targets) > 0 {
162
+	for _, target := range targets {
135 163
 		// check name length
136
-		if len(targets[0]) < 1 || len(targets[0]) > server.limits.NickLen {
137
-			targets = targets[1:]
164
+		if len(target) < 1 || len(targets) > server.limits.NickLen {
138 165
 			continue
139 166
 		}
140 167
 
141
-		// check the monitor list length
142
-		if len(client.monitoring) >= server.limits.MonitorEntries {
143
-			client.Send(nil, server.name, ERR_MONLISTFULL, client.nick, strconv.Itoa(server.limits.MonitorEntries), strings.Join(targets, ","))
144
-			break
145
-		}
146
-
147 168
 		// add target
148 169
 		casefoldedTarget, err := CasefoldName(targets[0])
149 170
 		if err != nil {
150
-			// skip silently I guess
151
-			targets = targets[1:]
152 171
 			continue
153 172
 		}
154 173
 
155
-		client.monitoringMutex.Lock()
156
-		client.server.monitoringMutex.Lock()
157
-
158
-		if !client.monitoring[casefoldedTarget] {
159
-			client.monitoring[casefoldedTarget] = true
160
-
161
-			orig := server.monitoring[casefoldedTarget]
162
-			server.monitoring[casefoldedTarget] = append(orig, client)
174
+		err = server.monitorManager.addMonitor(client, casefoldedTarget, limit)
175
+		if err == MonitorLimitExceeded {
176
+			client.Send(nil, server.name, ERR_MONLISTFULL, client.getNick(), strconv.Itoa(server.limits.MonitorEntries), strings.Join(targets, ","))
177
+			break
178
+		} else if err != nil {
179
+			continue
163 180
 		}
164 181
 
165
-		client.monitoringMutex.Unlock()
166
-		client.server.monitoringMutex.Unlock()
167
-
168 182
 		// add to online / offline lists
169
-		target := server.clients.Get(casefoldedTarget)
170
-		if target == nil {
183
+		if target := server.clients.Get(casefoldedTarget); target == nil {
171 184
 			offline = append(offline, targets[0])
172 185
 		} else {
173
-			online = append(online, target.nickMaskString)
186
+			online = append(online, target.getNick())
174 187
 		}
175
-
176
-		// remove first element of targets list
177
-		targets = targets[1:]
178 188
 	}
179 189
 
180 190
 	if len(online) > 0 {
181
-		client.Send(nil, server.name, RPL_MONONLINE, client.nick, strings.Join(online, ","))
191
+		client.Send(nil, server.name, RPL_MONONLINE, client.getNick(), strings.Join(online, ","))
182 192
 	}
183 193
 	if len(offline) > 0 {
184
-		client.Send(nil, server.name, RPL_MONOFFLINE, client.nick, strings.Join(offline, ","))
194
+		client.Send(nil, server.name, RPL_MONOFFLINE, client.getNick(), strings.Join(offline, ","))
185 195
 	}
186 196
 
187 197
 	return false
188 198
 }
189 199
 
190 200
 func monitorClearHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
191
-	client.clearMonitorList()
192
-
201
+	server.monitorManager.clearMonitorList(client)
193 202
 	return false
194 203
 }
195 204
 
196 205
 func monitorListHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
197
-	var monitorList []string
198
-	client.monitoringMutex.RLock()
199
-	for name := range client.monitoring {
200
-		monitorList = append(monitorList, name)
201
-	}
202
-	client.monitoringMutex.RUnlock()
206
+	monitorList := server.monitorManager.listMonitors(client)
203 207
 
204 208
 	for _, line := range argsToStrings(maxLastArgLength, monitorList, ",") {
205
-		client.Send(nil, server.name, RPL_MONLIST, client.nick, line)
209
+		client.Send(nil, server.name, RPL_MONLIST, client.getNick(), line)
206 210
 	}
207 211
 
212
+	client.Send(nil, server.name, RPL_ENDOFMONLIST, "End of MONITOR list")
213
+
208 214
 	return false
209 215
 }
210 216
 
@@ -212,27 +218,25 @@ func monitorStatusHandler(server *Server, client *Client, msg ircmsg.IrcMessage)
212 218
 	var online []string
213 219
 	var offline []string
214 220
 
215
-	client.monitoringMutex.RLock()
216
-	monitoring := client.monitoring
217
-	client.monitoringMutex.RUnlock()
221
+	monitorList := server.monitorManager.listMonitors(client)
218 222
 
219
-	for name := range monitoring {
223
+	for _, name := range monitorList {
220 224
 		target := server.clients.Get(name)
221 225
 		if target == nil {
222 226
 			offline = append(offline, name)
223 227
 		} else {
224
-			online = append(online, target.nickMaskString)
228
+			online = append(online, target.getNick())
225 229
 		}
226 230
 	}
227 231
 
228 232
 	if len(online) > 0 {
229 233
 		for _, line := range argsToStrings(maxLastArgLength, online, ",") {
230
-			client.Send(nil, server.name, RPL_MONONLINE, client.nick, line)
234
+			client.Send(nil, server.name, RPL_MONONLINE, client.getNick(), line)
231 235
 		}
232 236
 	}
233 237
 	if len(offline) > 0 {
234 238
 		for _, line := range argsToStrings(maxLastArgLength, offline, ",") {
235
-			client.Send(nil, server.name, RPL_MONOFFLINE, client.nick, line)
239
+			client.Send(nil, server.name, RPL_MONOFFLINE, client.getNick(), line)
236 240
 		}
237 241
 	}
238 242
 

+ 1
- 1
irc/nickname.go Прегледај датотеку

@@ -57,7 +57,7 @@ func nickHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
57 57
 		return false
58 58
 	}
59 59
 	if client.registered {
60
-		client.alertMonitors()
60
+		client.server.monitorManager.alertMonitors(client, true)
61 61
 	}
62 62
 	server.tryRegister(client)
63 63
 	return false

+ 18
- 25
irc/server.go Прегледај датотеку

@@ -94,7 +94,6 @@ type Server struct {
94 94
 	connectionThrottle           *ConnectionThrottle
95 95
 	connectionThrottleMutex      sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
96 96
 	ctime                        time.Time
97
-	currentOpers                 map[*Client]bool
98 97
 	defaultChannelModes          Modes
99 98
 	dlines                       *DLineManager
100 99
 	isupport                     *ISupportList
@@ -103,8 +102,7 @@ type Server struct {
103 102
 	listeners                    map[string]*ListenerWrapper
104 103
 	logger                       *logger.Manager
105 104
 	MaxSendQBytes                uint64
106
-	monitoring                   map[string][]*Client
107
-	monitoringMutex              sync.RWMutex
105
+	monitorManager               *MonitorManager
108 106
 	motdLines                    []string
109 107
 	name                         string
110 108
 	nameCasefolded               string
@@ -155,10 +153,9 @@ func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
155 153
 		channels:           *NewChannelNameMap(),
156 154
 		clients:            NewClientLookupSet(),
157 155
 		commands:           make(chan Command),
158
-		currentOpers:       make(map[*Client]bool),
159 156
 		listeners:          make(map[string]*ListenerWrapper),
160 157
 		logger:             logger,
161
-		monitoring:         make(map[string][]*Client),
158
+		monitorManager:     NewMonitorManager(),
162 159
 		newConns:           make(chan clientConn),
163 160
 		registeredChannels: make(map[string]*RegisteredChannel),
164 161
 		rehashSignal:       make(chan os.Signal, 1),
@@ -1143,36 +1140,36 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
1143 1140
 		client.Send(nil, server.name, ERR_UNKNOWNERROR, "OPER", "You're already opered-up!")
1144 1141
 		return false
1145 1142
 	}
1146
-	hash := server.operators[name].Pass
1147
-	password := []byte(msg.Params[1])
1148
-
1149
-	err = ComparePassword(hash, password)
1143
+	server.configurableStateMutex.RLock()
1144
+	oper := server.operators[name]
1145
+	server.configurableStateMutex.RUnlock()
1150 1146
 
1151
-	if (hash == nil) || (err != nil) {
1147
+	password := []byte(msg.Params[1])
1148
+	err = ComparePassword(oper.Pass, password)
1149
+	if (oper.Pass == nil) || (err != nil) {
1152 1150
 		client.Send(nil, server.name, ERR_PASSWDMISMATCH, client.nick, "Password incorrect")
1153 1151
 		return true
1154 1152
 	}
1155 1153
 
1156 1154
 	client.flags[Operator] = true
1157 1155
 	client.operName = name
1158
-	client.class = server.operators[name].Class
1159
-	server.currentOpers[client] = true
1160
-	client.whoisLine = server.operators[name].WhoisLine
1156
+	client.class = oper.Class
1157
+	client.whoisLine = oper.WhoisLine
1161 1158
 
1162 1159
 	// push new vhost if one is set
1163
-	if len(server.operators[name].Vhost) > 0 {
1160
+	if len(oper.Vhost) > 0 {
1164 1161
 		for fClient := range client.Friends(caps.ChgHost) {
1165
-			fClient.SendFromClient("", client, nil, "CHGHOST", client.username, server.operators[name].Vhost)
1162
+			fClient.SendFromClient("", client, nil, "CHGHOST", client.username, oper.Vhost)
1166 1163
 		}
1167 1164
 		// CHGHOST requires prefix nickmask to have original hostname, so do that before updating nickmask
1168
-		client.vhost = server.operators[name].Vhost
1169
-		client.updateNickMask()
1165
+		client.vhost = oper.Vhost
1166
+		client.updateNickMask("")
1170 1167
 	}
1171 1168
 
1172 1169
 	// set new modes
1173 1170
 	var applied ModeChanges
1174
-	if 0 < len(server.operators[name].Modes) {
1175
-		modeChanges, unknownChanges := ParseUserModeChanges(strings.Split(server.operators[name].Modes, " ")...)
1171
+	if 0 < len(oper.Modes) {
1172
+		modeChanges, unknownChanges := ParseUserModeChanges(strings.Split(oper.Modes, " ")...)
1176 1173
 		applied = client.applyUserModeChanges(true, modeChanges)
1177 1174
 		if 0 < len(unknownChanges) {
1178 1175
 			var runes string
@@ -1257,12 +1254,8 @@ func (server *Server) applyConfig(config *Config, initial bool) error {
1257 1254
 	if err != nil {
1258 1255
 		return fmt.Errorf("Error rehashing config file opers: %s", err.Error())
1259 1256
 	}
1260
-	for client := range server.currentOpers {
1261
-		_, exists := opers[client.operName]
1262
-		if !exists {
1263
-			return fmt.Errorf("Oper [%s] no longer exists (used by client [%s])", client.operName, client.nickMaskString)
1264
-		}
1265
-	}
1257
+
1258
+	// TODO: support rehash of existing operator perms?
1266 1259
 
1267 1260
 	// sanity checks complete, start modifying server state
1268 1261
 

Loading…
Откажи
Сачувај