轮询机制对比
原版轮询策略(延迟恢复模式)
核心设计
// 轮询搜索结构
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]++;
}
}
}
1542

被折叠的 条评论
为什么被折叠?



