号码池轮询策略分析以及优化

轮询机制对比

原版轮询策略(延迟恢复模式)

核心设计

// 轮询搜索结构
for(int i=CallerInfo->nCurrentPos+1; i<CallerInfo->dwCount; i++) {
    // 从当前位置向后搜索
}
for(int i=0; i<CallerInfo->nCurrentPos+1; i++) {
    // 从开头到当前位置搜索
}

// 恢复机制
if (bReSearch == FALSE) {
    // 恢复目的组的资源
    for(int i=0; i<CallerInfo->dwCount; i++) {
        if(CallerInfo->dwCurrentResource[i] <= 0) {
            CallerInfo->dwCurrentResource[i] = CallerInfo->dwMaxResource[i];
        }
    }
    goto SERACH_1; // 重新搜索
}

轮询特点

  • 延迟资源恢复:资源耗尽时才批量恢复,减少恢复频率
  • 按组恢复:只恢复特定PCM组的资源
  • 强制重新搜索:恢复后使用goto重新开始搜索
  • 保持状态持续性:已分配的号码保持占用状态直到恢复
修改版轮询策略(立即释放模式)

核心设计

// 轮询搜索结构(简化版)
for (int i = CallerInfo->nCurrentPos + 1; i < CallerInfo->dwCount; i++) {
    // 第一次搜索:从当前位置开始
}
for (int i = 0; i < CallerInfo->nCurrentPos + 1; i++) {
    // 第二次搜索:从头开始到当前位置
}

// 立即释放机制
void ReleaseCallerIDResource(...) {
    if (nPos >= 0 && nPos < CallerInfo->dwCount) {
        CallerInfo->bInUse[nPos] = FALSE;
        if (CallerInfo->dwCurrentResource[nPos] < CallerInfo->dwMaxResource[nPos]) {
            CallerInfo->dwCurrentResource[nPos]++;
        }
    }
}

轮询特点

  • 立即资源释放:每次呼叫结束立即释放资源
  • 添加使用状态标记:通过bInUse数组跟踪号码使用状态
  • 移除恢复重试机制:删除goto和资源恢复逻辑
  • 增强匹配条件:增加主叫/被叫前缀匹配

轮询算法差异分析

搜索算法对比
特性原版算法修改版算法
搜索范围两次线性搜索两次线性搜索
重试机制有(goto恢复重试)
恢复时机搜索失败时批量恢复呼叫结束时立即释放
状态跟踪仅资源计数资源计数 + 使用状态
循环方式当前位置指针轮询当前位置指针轮询
轮询公平性实现

原版公平性策略

  • 搜索起点轮换:每次从上次成功位置的下一个开始
  • 分段搜索:先搜索后半段,再搜索前半段,形成循环
  • 恢复后重置:资源恢复后重新搜索,可能改变轮询顺序

修改版公平性策略

  • 搜索起点轮换:同原版
  • 分段搜索:同原版
  • 即时资源可用:释放后立即可用,增加分配机会
算法复杂度
场景原版复杂度修改版复杂度
最佳情况O(1) - 第一个号码可用O(1)
平均情况O(n/2) - 需要搜索一半O(n/2)
最坏情况O(3n) - 两次搜索+恢复O(n)
资源管理批量恢复O(n)立即释放O(1)

轮询场景适应性分析

呼叫模式适应性

连续呼叫场景

// 场景:多个连续呼叫使用同一PCM组
呼叫序列:C1 -> C2 -> C3 -> C4 -> C5

原版行为:
C1: 使用号码A,标记为占用
C2: 跳过A,使用号码B
C3: 跳过A、B,使用号码C
C4: 如果A、B、C都占用,触发恢复
C5: 恢复后重新从A开始

修改版行为:
C1: 使用号码A,立即减少资源
C2: A可能已释放,也可能使用B
C3: 根据资源可用性选择
C4: 继续轮询
C5: 继续轮询

并发呼叫场景

// 场景:多个并发呼叫同时分配号码
并发呼叫:C1、C2、C3同时请求

原版潜在问题:
- 资源恢复可能被多次触发
- 并发访问nCurrentPos可能导致指针错乱

修改版改进:
- bInUse标志可以帮助避免重复分配
- 但仍需考虑线程安全问题
资源利用率对比
指标原版修改版
资源周转率低(批量恢复)高(立即释放)
号码多样性高(避免重复使用)中(可能重复使用)
分配延迟可能高(需要恢复)低(立即分配)
管理开销高(维护恢复逻辑)低(简单释放)

code

int SetCallerIDFromList(char *szCallerId,PCallerPool CallerInfo,int nFirstRule,int nDstGroup,int nDir)
{
	int nResult = -1;
	BOOL bAppoint = FALSE;
	BOOL bReSearch = FALSE;
	BOOL bHaveResource = FALSE;
	//主叫号码变换池不符合IP->PSTN指定主叫前缀的呼叫,只要不变换主叫号码就好不用挂断 170 bug112
	if(strncmp(szCallerId,CallerInfo->szPrefix,strlen(CallerInfo->szPrefix)) && strcmp(CallerInfo->szPrefix,"*"))
	{
		return nResult;
	}

	if(CallerInfo->dwCount > 0)
	{//在有主叫号码池情况下,寻找符合条件的外呼通道

		//查询该PCM(组)是否被指定,指定需要单独查找170 bug119
		for(int i=0; i<CallerInfo->dwCount; i++)
		{
			if (CALL_IPTOPSTN==nDir)
			{
				if (CallerInfo->nDstGroup[i]==nDstGroup)
				{
					bAppoint = TRUE;
					break;
				}	
			}
			else
			{
				if (CallerInfo->nSrcGroup[i]==nDstGroup)
				{
					bAppoint = TRUE;
					break;
				}
			}
		}

		if (bAppoint == TRUE)
		{

		SERACH_1:

			for(int i=CallerInfo->nCurrentPos+1; i<CallerInfo->dwCount; i++)
			{
				if(CallerInfo->dwCurrentResource[i] > 0 	//有呼出资源
				&& (!strncmp(szCallerId,CallerInfo->szPrefix,strlen(CallerInfo->szPrefix)) || !strcmp(CallerInfo->szPrefix,"*"))
				&& ((CALL_IPTOPSTN==nDir && CallerInfo->nDstGroup[i]==nDstGroup) || (CALL_PSTNTOIP==nDir && CallerInfo->nSrcGroup[i]==nDstGroup)) //如果是IP->PSTN则符合目的PCM,如果是PSTN->IP则符合源PCM(-1表示任意)
				&& ((CALL_IPTOPSTN==nDir && ((CallerInfo->dwCurCallOutcnt[i]<CallerInfo->dwAllowCallOutcnt) || (CallerInfo->dwAllowCallOutcnt<=0))) || (CALL_PSTNTOIP==nDir))) //如果是IP->PSTN则需要外呼次数小于配置值,  如果是PSTN->IP则没有限制
				{
					strcpy(szCallerId,CallerInfo->szCallerid[i]);
					if(nFirstRule == ROUTE_FIRST)
						CallerInfo->dwCurrentResource[i]--;
					if (CALL_IPTOPSTN == nDir)
					{
						CallerInfo->dwCurCallOutcnt[i]++;
					}
					CallerInfo->nCurrentPos = i;
					nResult = i;
					return nResult;
				}
			}
			for(int i=0; i<CallerInfo->nCurrentPos+1; i++)
			{
				if(CallerInfo->dwCurrentResource[i] > 0 	//有呼出资源
				&& (!strncmp(szCallerId,CallerInfo->szPrefix,strlen(CallerInfo->szPrefix)) || !strcmp(CallerInfo->szPrefix,"*"))
				&& ((CALL_IPTOPSTN==nDir && CallerInfo->nDstGroup[i]==nDstGroup) || (CALL_PSTNTOIP==nDir && CallerInfo->nSrcGroup[i]==nDstGroup)) //如果是IP->PSTN则符合目的PCM,如果是PSTN->IP则符合源PCM(-1表示任意)
				&& ((CALL_IPTOPSTN==nDir && ((CallerInfo->dwCurCallOutcnt[i]<CallerInfo->dwAllowCallOutcnt) || (CallerInfo->dwAllowCallOutcnt<=0))) || (CALL_PSTNTOIP==nDir))) //如果是IP->PSTN则需要外呼次数小于配置值,  如果是PSTN->IP则没有限制
				{
					strcpy(szCallerId,CallerInfo->szCallerid[i]);
					if(nFirstRule == ROUTE_FIRST)
						CallerInfo->dwCurrentResource[i]--;
					if (CALL_IPTOPSTN == nDir)
					{
						CallerInfo->dwCurCallOutcnt[i]++;
					}
					CallerInfo->nCurrentPos = i;
					nResult = i;
					return nResult;
				}
			}

			if (bReSearch == FALSE)
			{
				bReSearch = TRUE;

				//可能是没有资源了,恢复目的组的资源,再去重新找一遍吧
				for(int i=0; i<CallerInfo->dwCount; i++)
				{
					if ((CALL_IPTOPSTN==nDir && CallerInfo->nDstGroup[i]==nDstGroup) || (CALL_PSTNTOIP==nDir && CallerInfo->nSrcGroup[i]==nDstGroup))
					{
						if(CallerInfo->dwCurrentResource[i] <= 0)
						{
							CallerInfo->dwCurrentResource[i] = CallerInfo->dwMaxResource[i];
						}	
					}	
				}

				goto SERACH_1;
			}
		}
		else
		{

		SERACH_2:

			for(int i=CallerInfo->nCurrentPos+1; i<CallerInfo->dwCount; i++)
			{
				//如果中继组对应的PCM中继没有设置号码池,也会走进来,在有资源的情况下无需再去恢复资源
				if (bHaveResource == FALSE && CallerInfo->dwCurrentResource[i] > 0)
				{
					bHaveResource = TRUE;
				}

				if(CallerInfo->dwCurrentResource[i] > 0 	//有呼出资源
				&& (!strncmp(szCallerId,CallerInfo->szPrefix,strlen(CallerInfo->szPrefix)) || !strcmp(CallerInfo->szPrefix,"*"))
				&& ((CALL_IPTOPSTN==nDir && -1==CallerInfo->nDstGroup[i]) || (CALL_PSTNTOIP==nDir && -1==CallerInfo->nSrcGroup[i])) //如果是IP->PSTN则符合目的PCM,如果是PSTN->IP则符合源PCM(-1表示任意)
				&& ((CALL_IPTOPSTN==nDir && ((CallerInfo->dwCurCallOutcnt[i]<CallerInfo->dwAllowCallOutcnt) || (CallerInfo->dwAllowCallOutcnt<=0))) || (CALL_PSTNTOIP==nDir))) //如果是IP->PSTN则需要外呼次数小于配置值,  如果是PSTN->IP则没有限制
				{
					strcpy(szCallerId,CallerInfo->szCallerid[i]);
					if(nFirstRule == ROUTE_FIRST)
						CallerInfo->dwCurrentResource[i]--;
					if (CALL_IPTOPSTN == nDir)
					{
						CallerInfo->dwCurCallOutcnt[i]++;
					}
					CallerInfo->nCurrentPos = i;
					nResult = i;
					return nResult;
				}
			}
			for(int i=0; i<CallerInfo->nCurrentPos+1; i++)
			{
				//如果中继组对应的PCM中继没有设置号码池,也会走进来,在有资源的情况下无需再去恢复资源
				if (bHaveResource == FALSE && CallerInfo->dwCurrentResource[i] > 0)
				{
					bHaveResource = TRUE;
				}

				if(CallerInfo->dwCurrentResource[i] > 0 	//有呼出资源
				&& (!strncmp(szCallerId,CallerInfo->szPrefix,strlen(CallerInfo->szPrefix)) || !strcmp(CallerInfo->szPrefix,"*"))
				&& ((CALL_IPTOPSTN==nDir && -1==CallerInfo->nDstGroup[i]) || (CALL_PSTNTOIP==nDir && -1==CallerInfo->nSrcGroup[i])) //如果是IP->PSTN则符合目的PCM,如果是PSTN->IP则符合源PCM(-1表示任意)
				&& ((CALL_IPTOPSTN==nDir && ((CallerInfo->dwCurCallOutcnt[i]<CallerInfo->dwAllowCallOutcnt) || (CallerInfo->dwAllowCallOutcnt<=0))) || (CALL_PSTNTOIP==nDir))) //如果是IP->PSTN则需要外呼次数小于配置值,  如果是PSTN->IP则没有限制
				{
					strcpy(szCallerId,CallerInfo->szCallerid[i]);
					if(nFirstRule == ROUTE_FIRST)
						CallerInfo->dwCurrentResource[i]--;
					if (CALL_IPTOPSTN == nDir)
					{
						CallerInfo->dwCurCallOutcnt[i]++;
					}
					CallerInfo->nCurrentPos = i;
					nResult = i;
					return nResult;
				}
			}

			if (bReSearch == FALSE && bHaveResource == FALSE)
			{
				bReSearch = TRUE;
				bHaveResource = TRUE;

				//没有资源了,恢复资源,再去重新找一遍吧
				for(int i=0; i<CallerInfo->dwCount; i++)
				{
					if(CallerInfo->dwCurrentResource[i] <= 0)
					{
						CallerInfo->dwCurrentResource[i] = CallerInfo->dwMaxResource[i];
					}	
				}

				goto SERACH_2;
			}
		}
	}
	
	if(CALL_IPTOPSTN==nDir && CallerInfo->dwAllowCallOutcnt>0)
	{
		if (CallerInfo->nType == 0)
		{
			//如果是IP->PSTN方向,则判断IP->PSTN的指定模式,如果是 SIP侧直接拒绝 模式
			nResult = -3;
		} 
		else
		{
			//如果是IP->PSTN方向,则判断IP->PSTN的指定模式,如果是 指定号码呼叫 模式,则使用备用号码外呼
			strcpy(szCallerId, CallerInfo->szCallerTmp);
			nResult = -2;
		}
		
		return nResult;
	}

	return nResult;
}

//释放主叫号码资源
void ReleaseCallerIDResource(char *szCallerId,PCallerPool CallerInfo,int nDstGroup,int nPos)
{
	//挂机时释放资源,会导致pcm中继组中存在多条中继循环递增方式呼叫时主叫号码不变的问题 DS-79454
	//修改为:查找不到资源再去释放资源,然后重新找一遍
	//if(nPos < CallerInfo->dwCount && CallerInfo->dwCurrentResource[nPos] < CallerInfo->dwMaxResource[nPos])
	//	CallerInfo->dwCurrentResource[nPos]++;

	return;
}

--------------------------------------------
int SetCallerIDFromList(char *szCallerId, PCallerPool CallerInfo, int nFirstRule, int nDstGroup, int nDir, char *callerPrefix, char * calledPrefix)
{
	int nResult = -1;
	BOOL bAppoint = FALSE;
	
	//主叫号码变换池不符合IP->PSTN指定主叫前缀的呼叫,只要不变换主叫号码就好不用挂断 170 bug112
	if(strncmp(szCallerId, CallerInfo->szPrefix, strlen(CallerInfo->szPrefix)) && strcmp(CallerInfo->szPrefix,"*"))
	{
		return nResult;
	}

	if (CallerInfo->dwCount > 0)
	{
		// 查询该PCM(组)是否被指定,指定需要单独查找170 bug119
		for (int i = 0; i < CallerInfo->dwCount; i++)
		{
			if (CALL_IPTOPSTN == nDir)
			{
				if (CallerInfo->nDstGroup[i] == nDstGroup)
				{
					bAppoint = TRUE;
					break;
				}
			}
			else
			{
				if (CallerInfo->nSrcGroup[i] == nDstGroup)
				{
					bAppoint = TRUE;
					break;
				}
			}
		}

		if (bAppoint == TRUE)
		{
			// 第一次查找:从当前位置开始
			for (int i = CallerInfo->nCurrentPos + 1; i < CallerInfo->dwCount; i++)
			{
				// 检查当前号码池的前缀匹配
				BOOL prefixMatch = TRUE;
				
				// 检查主叫前缀匹配
				if (strcmp(CallerInfo->szCallerPrefix[i], "*") != 0)
				{
					if (callerPrefix == NULL || strlen(callerPrefix) == 0)
					{
						prefixMatch = FALSE;
					}
					else if (strlen(callerPrefix) < strlen(CallerInfo->szCallerPrefix[i]))
					{
						prefixMatch = FALSE;
					}
					else if (strncmp(callerPrefix, CallerInfo->szCallerPrefix[i], strlen(CallerInfo->szCallerPrefix[i])) != 0)
					{
						prefixMatch = FALSE;
					}
				}
				
				// 检查被叫前缀匹配
				if (prefixMatch && strcmp(CallerInfo->szCalledPrefix[i], "*") != 0)
				{
					if (calledPrefix == NULL || strlen(calledPrefix) == 0)
					{
						prefixMatch = FALSE;
					}
					else if (strlen(calledPrefix) < strlen(CallerInfo->szCalledPrefix[i]))
					{
						prefixMatch = FALSE;
					}
					else if (strncmp(calledPrefix, CallerInfo->szCalledPrefix[i], strlen(CallerInfo->szCalledPrefix[i])) != 0)
					{
						prefixMatch = FALSE;
					}
				}
				
				if (prefixMatch && 
					CallerInfo->dwCurrentResource[i] > 0 && 	// 有呼出资源
					(!strncmp(szCallerId, CallerInfo->szPrefix, strlen(CallerInfo->szPrefix)) || !strcmp(CallerInfo->szPrefix, "*")) &&
					// 修改关键条件:允许指定PCM组或任意PCM组(-1)
					((CALL_IPTOPSTN == nDir && (CallerInfo->nDstGroup[i] == nDstGroup || CallerInfo->nDstGroup[i] == -1)) || 
					 (CALL_PSTNTOIP == nDir && (CallerInfo->nSrcGroup[i] == nDstGroup || CallerInfo->nSrcGroup[i] == -1))) && 
					((CALL_IPTOPSTN == nDir && ((CallerInfo->dwCurCallOutcnt[i] < CallerInfo->dwAllowCallOutcnt) || (CallerInfo->dwAllowCallOutcnt <= 0))) || (CALL_PSTNTOIP == nDir))) // 如果是IP->PSTN则需要外呼次数小于配置值,如果是PSTN->IP则没有限制
				{
					strcpy(szCallerId, CallerInfo->szCallerid[i]);
					if (nFirstRule == ROUTE_FIRST)
						CallerInfo->dwCurrentResource[i]--;
					if (CALL_IPTOPSTN == nDir)
					{
						CallerInfo->dwCurCallOutcnt[i]++;
					}
					CallerInfo->nCurrentPos = i;
					nResult = i;
					
					// 标记这个号码正在使用
					CallerInfo->bInUse[i] = TRUE;
					return nResult;
				}
			}
			
			// 第二次查找:从头开始到当前位置
			for (int i = 0; i < CallerInfo->nCurrentPos + 1; i++)
			{
				// 检查当前号码池的前缀匹配
				BOOL prefixMatch = TRUE;
				
				// 检查主叫前缀匹配
				if (strcmp(CallerInfo->szCallerPrefix[i], "*") != 0)
				{
					if (callerPrefix == NULL || strlen(callerPrefix) == 0)
					{
						prefixMatch = FALSE;
					}
					else if (strlen(callerPrefix) < strlen(CallerInfo->szCallerPrefix[i]))
					{
						prefixMatch = FALSE;
					}
					else if (strncmp(callerPrefix, CallerInfo->szCallerPrefix[i], strlen(CallerInfo->szCallerPrefix[i])) != 0)
					{
						prefixMatch = FALSE;
					}
				}
				
				// 检查被叫前缀匹配
				if (prefixMatch && strcmp(CallerInfo->szCalledPrefix[i], "*") != 0)
				{
					if (calledPrefix == NULL || strlen(calledPrefix) == 0)
					{
						prefixMatch = FALSE;
					}
					else if (strlen(calledPrefix) < strlen(CallerInfo->szCalledPrefix[i]))
					{
						prefixMatch = FALSE;
					}
					else if (strncmp(calledPrefix, CallerInfo->szCalledPrefix[i], strlen(CallerInfo->szCalledPrefix[i])) != 0)
					{
						prefixMatch = FALSE;
					}
				}
				
				if (prefixMatch && 
					CallerInfo->dwCurrentResource[i] > 0 && 	// 有呼出资源
					(!strncmp(szCallerId, CallerInfo->szPrefix, strlen(CallerInfo->szPrefix)) || !strcmp(CallerInfo->szPrefix, "*")) &&
					// 修改关键条件:允许指定PCM组或任意PCM组(-1)
					((CALL_IPTOPSTN == nDir && (CallerInfo->nDstGroup[i] == nDstGroup || CallerInfo->nDstGroup[i] == -1)) || 
					 (CALL_PSTNTOIP == nDir && (CallerInfo->nSrcGroup[i] == nDstGroup || CallerInfo->nSrcGroup[i] == -1))) && 
					((CALL_IPTOPSTN == nDir && ((CallerInfo->dwCurCallOutcnt[i] < CallerInfo->dwAllowCallOutcnt) || (CallerInfo->dwAllowCallOutcnt <= 0))) || (CALL_PSTNTOIP == nDir))) // 如果是IP->PSTN则需要外呼次数小于配置值,如果是PSTN->IP则没有限制
				{
					strcpy(szCallerId, CallerInfo->szCallerid[i]);
					if (nFirstRule == ROUTE_FIRST)
						CallerInfo->dwCurrentResource[i]--;
					if (CALL_IPTOPSTN == nDir)
					{
						CallerInfo->dwCurCallOutcnt[i]++;
					}
					CallerInfo->nCurrentPos = i;
					nResult = i;
					
					// 标记这个号码正在使用
					CallerInfo->bInUse[i] = TRUE;
					return nResult;
				}
			}
		}
		else
		{
			// 第一次查找:从当前位置开始
			for (int i = CallerInfo->nCurrentPos + 1; i < CallerInfo->dwCount; i++)
			{
				// 检查当前号码池的前缀匹配
				BOOL prefixMatch = TRUE;
				
				// 检查主叫前缀匹配
				if (strcmp(CallerInfo->szCallerPrefix[i], "*") != 0)
				{
					if (callerPrefix == NULL || strlen(callerPrefix) == 0)
					{
						prefixMatch = FALSE;
					}
					else if (strlen(callerPrefix) < strlen(CallerInfo->szCallerPrefix[i]))
					{
						prefixMatch = FALSE;
					}
					else if (strncmp(callerPrefix, CallerInfo->szCallerPrefix[i], strlen(CallerInfo->szCallerPrefix[i])) != 0)
					{
						prefixMatch = FALSE;
					}
				}
				
				// 检查被叫前缀匹配
				if (prefixMatch && strcmp(CallerInfo->szCalledPrefix[i], "*") != 0)
				{
					if (calledPrefix == NULL || strlen(calledPrefix) == 0)
					{
						prefixMatch = FALSE;
					}
					else if (strlen(calledPrefix) < strlen(CallerInfo->szCalledPrefix[i]))
					{
						prefixMatch = FALSE;
					}
					else if (strncmp(calledPrefix, CallerInfo->szCalledPrefix[i], strlen(CallerInfo->szCalledPrefix[i])) != 0)
					{
						prefixMatch = FALSE;
					}
				}
				
				if (prefixMatch && 
					CallerInfo->dwCurrentResource[i] > 0 && 	// 有呼出资源
					(!strncmp(szCallerId, CallerInfo->szPrefix, strlen(CallerInfo->szPrefix)) || !strcmp(CallerInfo->szPrefix, "*")) &&
					((CALL_IPTOPSTN == nDir && -1 == CallerInfo->nDstGroup[i]) || (CALL_PSTNTOIP == nDir && -1 == CallerInfo->nSrcGroup[i])) && // 如果是IP->PSTN则符合目的PCM,如果是PSTN->IP则符合源PCM(-1表示任意)
					((CALL_IPTOPSTN == nDir && ((CallerInfo->dwCurCallOutcnt[i] < CallerInfo->dwAllowCallOutcnt) || (CallerInfo->dwAllowCallOutcnt <= 0))) || (CALL_PSTNTOIP == nDir))) // 如果是IP->PSTN则需要外呼次数小于配置值,如果是PSTN->IP则没有限制
				{
					strcpy(szCallerId, CallerInfo->szCallerid[i]);
					if (nFirstRule == ROUTE_FIRST)
						CallerInfo->dwCurrentResource[i]--;
					if (CALL_IPTOPSTN == nDir)
					{
						CallerInfo->dwCurCallOutcnt[i]++;
					}
					CallerInfo->nCurrentPos = i;
					nResult = i;
					
					// 标记这个号码正在使用
					CallerInfo->bInUse[i] = TRUE;
					return nResult;
				}
			}
			
			// 第二次查找:从头开始到当前位置
			for (int i = 0; i < CallerInfo->nCurrentPos + 1; i++)
			{
				// 检查当前号码池的前缀匹配
				BOOL prefixMatch = TRUE;
				
				// 检查主叫前缀匹配
				if (strcmp(CallerInfo->szCallerPrefix[i], "*") != 0)
				{
					if (callerPrefix == NULL || strlen(callerPrefix) == 0)
					{
						prefixMatch = FALSE;
					}
					else if (strlen(callerPrefix) < strlen(CallerInfo->szCallerPrefix[i]))
					{
						prefixMatch = FALSE;
					}
					else if (strncmp(callerPrefix, CallerInfo->szCallerPrefix[i], strlen(CallerInfo->szCallerPrefix[i])) != 0)
					{
						prefixMatch = FALSE;
					}
				}
				
				// 检查被叫前缀匹配
				if (prefixMatch && strcmp(CallerInfo->szCalledPrefix[i], "*") != 0)
				{
					if (calledPrefix == NULL || strlen(calledPrefix) == 0)
					{
						prefixMatch = FALSE;
					}
					else if (strlen(calledPrefix) < strlen(CallerInfo->szCalledPrefix[i]))
					{
						prefixMatch = FALSE;
					}
					else if (strncmp(calledPrefix, CallerInfo->szCalledPrefix[i], strlen(CallerInfo->szCalledPrefix[i])) != 0)
					{
						prefixMatch = FALSE;
					}
				}
				
				if (prefixMatch && 
					CallerInfo->dwCurrentResource[i] > 0 && 	// 有呼出资源
					(!strncmp(szCallerId, CallerInfo->szPrefix, strlen(CallerInfo->szPrefix)) || !strcmp(CallerInfo->szPrefix, "*")) &&
					((CALL_IPTOPSTN == nDir && -1 == CallerInfo->nDstGroup[i]) || (CALL_PSTNTOIP == nDir && -1 == CallerInfo->nSrcGroup[i])) && // 如果是IP->PSTN则符合目的PCM,如果是PSTN->IP则符合源PCM(-1表示任意)
					((CALL_IPTOPSTN == nDir && ((CallerInfo->dwCurCallOutcnt[i] < CallerInfo->dwAllowCallOutcnt) || (CallerInfo->dwAllowCallOutcnt <= 0))) || (CALL_PSTNTOIP == nDir))) // 如果是IP->PSTN则需要外呼次数小于配置值,如果是PSTN->IP则没有限制
				{
					strcpy(szCallerId, CallerInfo->szCallerid[i]);
					if (nFirstRule == ROUTE_FIRST)
						CallerInfo->dwCurrentResource[i]--;
					if (CALL_IPTOPSTN == nDir)
					{
						CallerInfo->dwCurCallOutcnt[i]++;
					}
					CallerInfo->nCurrentPos = i;
					nResult = i;
					
					// 标记这个号码正在使用
					CallerInfo->bInUse[i] = TRUE;
					return nResult;
				}
			}
		}
	}
	
	if (CALL_IPTOPSTN == nDir && CallerInfo->dwAllowCallOutcnt > 0)
	{
		if (CallerInfo->nType == 0)
		{
			// 如果是IP->PSTN方向,则判断IP->PSTN的指定模式,如果是 SIP侧直接拒绝 模式
			nResult = -3;
		}
		else
		{
			// 如果是IP->PSTN方向,则判断IP->PSTN的指定模式,如果是 指定号码呼叫 模式,则使用备用号码外呼
			strcpy(szCallerId, CallerInfo->szCallerTmp);
			nResult = -2;
		}
		
		return nResult;
	}

	return nResult;   
}

//释放主叫号码资源
void ReleaseCallerIDResource(char *szCallerId,PCallerPool CallerInfo,int nDstGroup,int nPos)
{
	if (nPos >= 0 && nPos < CallerInfo->dwCount)
	{
		// 标记这个号码已挂机
		CallerInfo->bInUse[nPos] = FALSE;
		if (CallerInfo->dwCurrentResource[nPos] < CallerInfo->dwMaxResource[nPos])
		{
			CallerInfo->dwCurrentResource[nPos]++;
		}
	}
}

















评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

八月的雨季997

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值