github.com/TeaOSLab/EdgeNode@v1.3.8/internal/iplibrary/ip_list.go (about) 1 package iplibrary 2 3 import ( 4 "github.com/TeaOSLab/EdgeCommon/pkg/iputils" 5 "github.com/TeaOSLab/EdgeNode/internal/utils/expires" 6 "github.com/TeaOSLab/EdgeNode/internal/utils/fasttime" 7 "sort" 8 "sync" 9 ) 10 11 var GlobalBlackIPList = NewIPList() 12 var GlobalWhiteIPList = NewIPList() 13 14 // IPList IP名单 15 // TODO 对ipMap进行分区 16 type IPList struct { 17 isDeleted bool 18 19 itemsMap map[uint64]*IPItem // id => item 20 21 sortedRangeItems []*IPItem 22 ipMap map[string]*IPItem // ipFrom => IPItem 23 bufferItemsMap map[uint64]*IPItem // id => IPItem 24 25 allItemsMap map[uint64]*IPItem // id => item 26 27 expireList *expires.List 28 29 mu sync.RWMutex 30 } 31 32 func NewIPList() *IPList { 33 var list = &IPList{ 34 itemsMap: map[uint64]*IPItem{}, 35 bufferItemsMap: map[uint64]*IPItem{}, 36 allItemsMap: map[uint64]*IPItem{}, 37 ipMap: map[string]*IPItem{}, 38 } 39 40 var expireList = expires.NewList() 41 expireList.OnGC(func(itemId uint64) { 42 list.Delete(itemId) 43 }) 44 list.expireList = expireList 45 return list 46 } 47 48 func (this *IPList) Add(item *IPItem) { 49 if this.isDeleted { 50 return 51 } 52 53 this.addItem(item, true, true) 54 } 55 56 func (this *IPList) AddDelay(item *IPItem) { 57 if this.isDeleted || item == nil { 58 return 59 } 60 61 if !IsZero(item.IPTo) { 62 this.mu.Lock() 63 this.bufferItemsMap[item.Id] = item 64 this.mu.Unlock() 65 } else { 66 this.addItem(item, true, true) 67 } 68 } 69 70 func (this *IPList) Sort() { 71 this.mu.Lock() 72 this.sortRangeItems(false) 73 this.mu.Unlock() 74 } 75 76 func (this *IPList) Delete(itemId uint64) { 77 this.mu.Lock() 78 this.deleteItem(itemId) 79 this.mu.Unlock() 80 } 81 82 // Contains 判断是否包含某个IP 83 func (this *IPList) Contains(ipBytes []byte) bool { 84 if this.isDeleted { 85 return false 86 } 87 88 this.mu.RLock() 89 defer this.mu.RUnlock() 90 91 if len(this.allItemsMap) > 0 { 92 return true 93 } 94 95 var item = this.lookupIP(ipBytes) 96 return item != nil 97 } 98 99 // ContainsExpires 判断是否包含某个IP 100 func (this *IPList) ContainsExpires(ipBytes []byte) (expiresAt int64, ok bool) { 101 if this.isDeleted { 102 return 103 } 104 105 this.mu.RLock() 106 defer this.mu.RUnlock() 107 108 if len(this.allItemsMap) > 0 { 109 return 0, true 110 } 111 112 var item = this.lookupIP(ipBytes) 113 114 if item == nil { 115 return 116 } 117 118 return item.ExpiredAt, true 119 } 120 121 // ContainsIPStrings 是否包含一组IP中的任意一个,并返回匹配的第一个Item 122 func (this *IPList) ContainsIPStrings(ipStrings []string) (item *IPItem, found bool) { 123 if this.isDeleted { 124 return 125 } 126 127 if len(ipStrings) == 0 { 128 return 129 } 130 131 this.mu.RLock() 132 defer this.mu.RUnlock() 133 134 if len(this.allItemsMap) > 0 { 135 for _, allItem := range this.allItemsMap { 136 item = allItem 137 break 138 } 139 140 if item != nil { 141 found = true 142 return 143 } 144 } 145 for _, ipString := range ipStrings { 146 if len(ipString) == 0 { 147 continue 148 } 149 item = this.lookupIP(iputils.ToBytes(ipString)) 150 if item != nil { 151 found = true 152 return 153 } 154 } 155 return 156 } 157 158 func (this *IPList) SetDeleted() { 159 this.isDeleted = true 160 } 161 162 func (this *IPList) SortedRangeItems() []*IPItem { 163 return this.sortedRangeItems 164 } 165 166 func (this *IPList) IPMap() map[string]*IPItem { 167 return this.ipMap 168 } 169 170 func (this *IPList) ItemsMap() map[uint64]*IPItem { 171 return this.itemsMap 172 } 173 174 func (this *IPList) AllItemsMap() map[uint64]*IPItem { 175 return this.allItemsMap 176 } 177 178 func (this *IPList) BufferItemsMap() map[uint64]*IPItem { 179 return this.bufferItemsMap 180 } 181 182 func (this *IPList) addItem(item *IPItem, lock bool, sortable bool) { 183 if item == nil { 184 return 185 } 186 187 if item.ExpiredAt > 0 && item.ExpiredAt < fasttime.Now().Unix() { 188 return 189 } 190 191 var shouldSort bool 192 193 if iputils.CompareBytes(item.IPFrom, item.IPTo) == 0 { 194 item.IPTo = nil 195 } 196 197 if IsZero(item.IPFrom) && IsZero(item.IPTo) { 198 if item.Type != IPItemTypeAll { 199 return 200 } 201 } else if !IsZero(item.IPTo) { 202 if iputils.CompareBytes(item.IPFrom, item.IPTo) > 0 { 203 item.IPFrom, item.IPTo = item.IPTo, item.IPFrom 204 } else if IsZero(item.IPFrom) { 205 item.IPFrom = item.IPTo 206 item.IPTo = nil 207 } 208 } 209 210 if lock { 211 this.mu.Lock() 212 defer this.mu.Unlock() 213 } 214 215 // 是否已经存在 216 _, ok := this.itemsMap[item.Id] 217 if ok { 218 this.deleteItem(item.Id) 219 } 220 221 this.itemsMap[item.Id] = item 222 223 // 展开 224 if item.Type == IPItemTypeAll { 225 this.allItemsMap[item.Id] = item 226 } else if !IsZero(item.IPFrom) { 227 if !IsZero(item.IPTo) { 228 this.sortedRangeItems = append(this.sortedRangeItems, item) 229 shouldSort = true 230 } else { 231 this.ipMap[ToHex(item.IPFrom)] = item 232 } 233 } 234 235 if item.ExpiredAt > 0 { 236 this.expireList.Add(item.Id, item.ExpiredAt) 237 } 238 239 if shouldSort && sortable { 240 this.sortRangeItems(true) 241 } 242 } 243 244 // 对列表进行排序 245 func (this *IPList) sortRangeItems(force bool) { 246 if len(this.bufferItemsMap) > 0 { 247 for _, item := range this.bufferItemsMap { 248 this.addItem(item, false, false) 249 } 250 this.bufferItemsMap = map[uint64]*IPItem{} 251 force = true 252 } 253 254 if force { 255 sort.Slice(this.sortedRangeItems, func(i, j int) bool { 256 var item1 = this.sortedRangeItems[i] 257 var item2 = this.sortedRangeItems[j] 258 if iputils.CompareBytes(item1.IPFrom, item2.IPFrom) == 0 { 259 return iputils.CompareBytes(item1.IPTo, item2.IPTo) < 0 260 } 261 return iputils.CompareBytes(item1.IPFrom, item2.IPFrom) < 0 262 }) 263 } 264 } 265 266 // 不加锁的情况下查找Item 267 func (this *IPList) lookupIP(ipBytes []byte) *IPItem { 268 { 269 item, ok := this.ipMap[ToHex(ipBytes)] 270 if ok && (item.ExpiredAt == 0 || item.ExpiredAt > fasttime.Now().Unix()) { 271 return item 272 } 273 } 274 275 if len(this.sortedRangeItems) == 0 { 276 return nil 277 } 278 279 var count = len(this.sortedRangeItems) 280 var resultIndex = -1 281 sort.Search(count, func(i int) bool { 282 var item = this.sortedRangeItems[i] 283 var cmp = iputils.CompareBytes(item.IPFrom, ipBytes) 284 if cmp < 0 { 285 if iputils.CompareBytes(item.IPTo, ipBytes) >= 0 { 286 resultIndex = i 287 } 288 return false 289 } else if cmp == 0 { 290 resultIndex = i 291 return false 292 } 293 return true 294 }) 295 296 if resultIndex < 0 || resultIndex >= count { 297 return nil 298 } 299 300 var item = this.sortedRangeItems[resultIndex] 301 if item.ExpiredAt == 0 || item.ExpiredAt > fasttime.Now().Unix() { 302 return item 303 } 304 return nil 305 } 306 307 // 在不加锁的情况下删除某个Item 308 // 将会被别的方法引用,切记不能加锁 309 func (this *IPList) deleteItem(itemId uint64) { 310 // 从buffer中删除 311 delete(this.bufferItemsMap, itemId) 312 313 // 从all items中删除 314 _, ok := this.allItemsMap[itemId] 315 if ok { 316 delete(this.allItemsMap, itemId) 317 } 318 319 // 检查是否存在 320 oldItem, existsOld := this.itemsMap[itemId] 321 if !existsOld { 322 return 323 } 324 325 // 从ipMap中删除 326 if IsZero(oldItem.IPTo) { 327 var ipHex = ToHex(oldItem.IPFrom) 328 ipItem, ok := this.ipMap[ipHex] 329 if ok && ipItem.Id == itemId { 330 delete(this.ipMap, ipHex) 331 } 332 } 333 334 delete(this.itemsMap, itemId) 335 336 // 删除排序中的Item 337 if !IsZero(oldItem.IPTo) { 338 var index = -1 339 for itemIndex, item := range this.sortedRangeItems { 340 if item.Id == itemId { 341 index = itemIndex 342 break 343 } 344 } 345 if index >= 0 { 346 copy(this.sortedRangeItems[index:], this.sortedRangeItems[index+1:]) 347 this.sortedRangeItems = this.sortedRangeItems[:len(this.sortedRangeItems)-1] 348 } 349 } 350 }