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  }