ソースを参照

refactor [dk]linemanagers

* Synchronize map accesses
* Be more aggressive about cleaning up expired lines
* CIDR dlines did not work (nil dereference)
tags/v0.9.2-alpha
Shivaram Lingamneni 6年前
コミット
ae441d22d3
2個のファイルの変更72行の追加41行の削除
  1. 38
    21
      irc/dline.go
  2. 34
    20
      irc/kline.go

+ 38
- 21
irc/dline.go ファイルの表示

@@ -8,6 +8,7 @@ import (
8 8
 	"fmt"
9 9
 	"net"
10 10
 	"sort"
11
+	"sync"
11 12
 	"time"
12 13
 
13 14
 	"strings"
@@ -79,6 +80,7 @@ type dLineNet struct {
79 80
 
80 81
 // DLineManager manages and dlines.
81 82
 type DLineManager struct {
83
+	sync.RWMutex
82 84
 	// addresses that are dlined
83 85
 	addresses map[string]*dLineAddr
84 86
 	// networks that are dlined
@@ -97,6 +99,9 @@ func NewDLineManager() *DLineManager {
97 99
 func (dm *DLineManager) AllBans() map[string]IPBanInfo {
98 100
 	allb := make(map[string]IPBanInfo)
99 101
 
102
+	dm.RLock()
103
+	defer dm.RUnlock()
104
+
100 105
 	for name, info := range dm.addresses {
101 106
 		allb[name] = info.Info
102 107
 	}
@@ -118,13 +123,17 @@ func (dm *DLineManager) AddNetwork(network net.IPNet, length *IPRestrictTime, re
118 123
 			OperReason: operReason,
119 124
 		},
120 125
 	}
126
+	dm.Lock()
121 127
 	dm.networks[netString] = &dln
128
+	dm.Unlock()
122 129
 }
123 130
 
124 131
 // RemoveNetwork removes a network from the blocked list.
125 132
 func (dm *DLineManager) RemoveNetwork(network net.IPNet) {
126 133
 	netString := network.String()
134
+	dm.Lock()
127 135
 	delete(dm.networks, netString)
136
+	dm.Unlock()
128 137
 }
129 138
 
130 139
 // AddIP adds an IP address to the blocked list.
@@ -138,21 +147,27 @@ func (dm *DLineManager) AddIP(addr net.IP, length *IPRestrictTime, reason string
138 147
 			OperReason: operReason,
139 148
 		},
140 149
 	}
150
+	dm.Lock()
141 151
 	dm.addresses[addrString] = &dla
152
+	dm.Unlock()
142 153
 }
143 154
 
144 155
 // RemoveIP removes an IP from the blocked list.
145 156
 func (dm *DLineManager) RemoveIP(addr net.IP) {
146 157
 	addrString := addr.String()
158
+	dm.Lock()
147 159
 	delete(dm.addresses, addrString)
160
+	dm.Unlock()
148 161
 }
149 162
 
150 163
 // CheckIP returns whether or not an IP address was banned, and how long it is banned for.
151 164
 func (dm *DLineManager) CheckIP(addr net.IP) (isBanned bool, info *IPBanInfo) {
152 165
 	// check IP addr
153 166
 	addrString := addr.String()
154
-
167
+	dm.RLock()
155 168
 	addrInfo := dm.addresses[addrString]
169
+	dm.RUnlock()
170
+
156 171
 	if addrInfo != nil {
157 172
 		if addrInfo.Info.Time != nil {
158 173
 			if addrInfo.Info.Time.IsExpired() {
@@ -167,30 +182,32 @@ func (dm *DLineManager) CheckIP(addr net.IP) (isBanned bool, info *IPBanInfo) {
167 182
 	}
168 183
 
169 184
 	// check networks
170
-	var netsToRemove []net.IPNet
171
-
172
-	for _, netInfo := range dm.networks {
173
-		if !netInfo.Network.Contains(addr) {
174
-			continue
185
+	doCleanup := false
186
+	defer func() {
187
+		if doCleanup {
188
+			go func() {
189
+				dm.Lock()
190
+				defer dm.Unlock()
191
+				for key, netInfo := range dm.networks {
192
+					if netInfo.Info.Time.IsExpired() {
193
+						delete(dm.networks, key)
194
+					}
195
+				}
196
+			}()
175 197
 		}
198
+	}()
176 199
 
177
-		if netInfo.Info.Time != nil {
178
-			if netInfo.Info.Time.IsExpired() {
179
-				// ban on network has expired, remove it from our blocked list
180
-				netsToRemove = append(netsToRemove, netInfo.Network)
181
-			} else {
182
-				return true, &addrInfo.Info
183
-			}
184
-		} else {
185
-			return true, &addrInfo.Info
186
-		}
187
-	}
200
+	dm.RLock()
201
+	defer dm.RUnlock()
188 202
 
189
-	// remove expired networks
190
-	for _, expiredNet := range netsToRemove {
191
-		dm.RemoveNetwork(expiredNet)
203
+	for _, netInfo := range dm.networks {
204
+		if netInfo.Info.Time != nil && netInfo.Info.Time.IsExpired() {
205
+			// expired ban, ignore and clean up later
206
+			doCleanup = true
207
+		} else if netInfo.Network.Contains(addr) {
208
+			return true, &netInfo.Info
209
+		}
192 210
 	}
193
-
194 211
 	// no matches!
195 212
 	return false, nil
196 213
 }

+ 34
- 20
irc/kline.go ファイルの表示

@@ -8,6 +8,7 @@ import (
8 8
 	"fmt"
9 9
 	"sort"
10 10
 	"strings"
11
+	"sync"
11 12
 	"time"
12 13
 
13 14
 	"github.com/goshuirc/irc-go/ircfmt"
@@ -34,6 +35,7 @@ type KLineInfo struct {
34 35
 
35 36
 // KLineManager manages and klines.
36 37
 type KLineManager struct {
38
+	sync.RWMutex
37 39
 	// kline'd entries
38 40
 	entries map[string]*KLineInfo
39 41
 }
@@ -49,6 +51,8 @@ func NewKLineManager() *KLineManager {
49 51
 func (km *KLineManager) AllBans() map[string]IPBanInfo {
50 52
 	allb := make(map[string]IPBanInfo)
51 53
 
54
+	km.RLock()
55
+	defer km.RUnlock()
52 56
 	for name, info := range km.entries {
53 57
 		allb[name] = info.Info
54 58
 	}
@@ -67,48 +71,58 @@ func (km *KLineManager) AddMask(mask string, length *IPRestrictTime, reason stri
67 71
 			OperReason: operReason,
68 72
 		},
69 73
 	}
74
+	km.Lock()
70 75
 	km.entries[mask] = &kln
76
+	km.Unlock()
71 77
 }
72 78
 
73 79
 // RemoveMask removes a mask from the blocked list.
74 80
 func (km *KLineManager) RemoveMask(mask string) {
81
+	km.Lock()
75 82
 	delete(km.entries, mask)
83
+	km.Unlock()
76 84
 }
77 85
 
78 86
 // CheckMasks returns whether or not the hostmask(s) are banned, and how long they are banned for.
79 87
 func (km *KLineManager) CheckMasks(masks ...string) (isBanned bool, info *IPBanInfo) {
80
-	// check networks
81
-	var masksToRemove []string
88
+	doCleanup := false
89
+	defer func() {
90
+		// asynchronously remove expired bans
91
+		if doCleanup {
92
+			go func() {
93
+				km.Lock()
94
+				defer km.Unlock()
95
+				for key, entry := range km.entries {
96
+					if entry.Info.Time.IsExpired() {
97
+						delete(km.entries, key)
98
+					}
99
+				}
100
+			}()
101
+		}
102
+	}()
103
+
104
+
105
+	km.RLock()
106
+	defer km.RUnlock()
82 107
 
83 108
 	for _, entryInfo := range km.entries {
84
-		var matches bool
109
+		if entryInfo.Info.Time != nil && entryInfo.Info.Time.IsExpired() {
110
+			doCleanup = true
111
+			continue
112
+		}
113
+
114
+		matches := false
85 115
 		for _, mask := range masks {
86 116
 			if entryInfo.Matcher.Match(mask) {
87 117
 				matches = true
88 118
 				break
89 119
 			}
90 120
 		}
91
-		if !matches {
92
-			continue
93
-		}
94
-
95
-		if entryInfo.Info.Time != nil {
96
-			if entryInfo.Info.Time.IsExpired() {
97
-				// ban on network has expired, remove it from our blocked list
98
-				masksToRemove = append(masksToRemove, entryInfo.Mask)
99
-			} else {
100
-				return true, &entryInfo.Info
101
-			}
102
-		} else {
121
+		if matches {
103 122
 			return true, &entryInfo.Info
104 123
 		}
105 124
 	}
106 125
 
107
-	// remove expired networks
108
-	for _, expiredMask := range masksToRemove {
109
-		km.RemoveMask(expiredMask)
110
-	}
111
-
112 126
 	// no matches!
113 127
 	return false, nil
114 128
 }

読み込み中…
キャンセル
保存