Beispiel #1
0
        public bool RemoveIpEntry(string ip, bool condition)
        {
            if (condition)
            {
                IpEntry entry = FindIpEntry(ip);
                if (entry == null)
                {
                    return(false);
                }

                if (entry.CanRemove() == false)
                {
                    return(false);
                }
            }

            // 然后用写锁定尝试
            _lock.EnterWriteLock();
            try
            {
                return(_ipTable.Remove(ip));
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }
Beispiel #2
0
        // 检查 IP。
        // exception:
        //      可能会抛出异常
        // return:
        //      null    许可 IP 被使用
        //      其他   禁止 IP 使用。字符串内容为禁止理由
        public string CheckIp(string ip)
        {
            // exception:
            //      可能会抛出异常
            IpEntry entry = GetIpEntry(ip);

            if (entry.IsInBlackList() == true)
            {
                return("IP [" + ip + "] 在黑名单之中");
            }

            // return:
            //      false   总量超过 max
            //      true    总量没有超过 max
            if (entry.CheckTotal(_maxTotalConnectRequest, _period) == false)
            {
                // TODO: 何时从黑名单中自动清除?
                entry.SetInBlackList();
                return("IP [" + ip + "] 短时间 (" + _period.TotalSeconds.ToString() + "秒) 内连接请求数超过极限 (" + _maxTotalConnectRequest + "),已被加入黑名单");
            }

            long value = entry.IncOnline();

            if (MaxClientsPerIp != -1 && value > MaxClientsPerIp)
            {
                entry.DecOnline();
                return("IP 地址为 '" + ip + "' 的前端数量超过配额 " + MaxClientsPerIp);
            }

            return(null);
        }
Beispiel #3
0
        // 把一个 IP 加入黑名单
        // exception:
        //      可能会抛出异常
        // return:
        //      false   调用前已经在黑名单之中
        //      true    成功
        public bool SetInBlackList(string ip, TimeSpan lockLength)
        {
            // exception:
            //      可能会抛出异常
            IpEntry entry = GetIpEntry(ip);

            if (entry.IsInBlackList() == true)
            {
                return(false);   // 已经在黑名单之中
            }
            entry.SetInBlackList(lockLength);
            return(true);
        }
Beispiel #4
0
        // 释放 IpEntry
        public void FinishIp(string ip)
        {
            IpEntry entry = FindIpEntry(ip);

            if (entry == null)
            {
                return;
            }
            long value = entry.DecOnline();

            if (value == 0)
            {
                // 发出清除 0 值条目的请求。不过也许不该清除,因为后面还要判断 Total。可以改为清除 Total 值小于某个阈值的条目
                RemoveIpEntry(ip, true);
            }
        }
Beispiel #5
0
        // 确保获得一个 IpEntry
        // exception:
        //      可能会抛出异常
        public IpEntry GetIpEntry(string ip)
        {
            // TODO: localhost 注意做归一化处理
            // 先用读锁定尝试一次
            _lock.EnterReadLock();
            try
            {
                if (_ipTable.TryGetValue(ip, out IpEntry value) == false)
                {
                    goto NEXT;
                }
                return(value);
            }
            finally
            {
                _lock.ExitReadLock();
            }

NEXT:
            // 然后用写锁定尝试
            _lock.EnterWriteLock();
            try
            {
                if (_ipTable.TryGetValue(ip, out IpEntry value) == false)
                {
                    if (this._ipTable.Count > _nMaxEntryCount)
                    {
                        throw new Exception("IP 表超过条目配额 " + _nMaxEntryCount);
                    }

                    IpEntry entry = new IpEntry();
                    _ipTable.Add(ip, entry);
                    return(entry);
                }
                return(value);
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }
Beispiel #6
0
        // 增量 IP 统计数字
        // 如果 IP 事项总数超过限额,会抛出异常
        // parameters:
        //      strIP   前端机器的 IP 地址。还用于辅助判断是否超过 MaxClients。localhost 是不计算在内的
        long _incIpCount(string strIP, int nDelta)
        {
            // this.MaxClients = 0;    // test
            if (nDelta != 0 && nDelta != 1 && nDelta != -1)
            {
                throw new ArgumentException("nDelta 参数值应为 0 -1 1 之一");
            }

            IpEntry entry = GetIpEntry(strIP);

            long oldOnline = 0;

            if (nDelta == 1)
            {
                oldOnline = entry.IncOnline();
                if (oldOnline >= MaxClientsPerIp)
                {
                    entry.DecOnline();
                    throw new Exception("IP 地址为 '" + strIP + "' 的前端数量超过配额 " + MaxClientsPerIp);
                }

                return(oldOnline);
            }
            else if (nDelta == -1)
            {
                oldOnline = entry.DecOnline();
                if (oldOnline == 1)
                {
                    // 发出清除 0 值条目的请求。不过也许不该清除,因为后面还要判断 Total。可以改为清除 Total 值小于某个阈值的条目
                    RemoveIpEntry(strIP);
                }

                return(oldOnline);
            }
            else
            {
                Debug.Assert(nDelta == 0, "");
            }

            return(entry.OnlineCount);

#if NO
            long v = 0;
            if (this._ipTable.ContainsKey(strIP) == true)
            {
                v = (long)this._ipTable[strIP];
            }
            else
            {
                if (this.Count > _nMaxCount &&
                    v + nDelta != 0)
                {
                    throw new OutofSessionException("IP 条目数量超过 " + _nMaxCount.ToString());
                }

                // 判断前端机器台数是否超过限制数额 2014/8/23
                if (this.MaxClients != -1 &&
                    IsLocalhost(strIP) == false &&
                    this.GetClientIpAmount() >= this.MaxClients &&
                    v + nDelta != 0)
                {
                    throw new OutofClientsException("前端机器数量已经达到 " + this.GetClientIpAmount().ToString() + " 个 ( 现有IP: " + StringUtil.MakePathList(GetIpList(), ", ") + " 试图申请的IP: " + strIP + ")。请先释放出通道然后重新访问");
                }
            }

            if (v + nDelta == 0)
            {
                this._ipTable.Remove(strIP); // 及时移走计数器为 0 的条目,避免 hashtable 尺寸太大
            }
            else
            {
                this._ipTable[strIP] = v + nDelta;
            }

            return(v);   // 返回增量前的数字
#endif
        }