Quellcode durchsuchen

Z991239-3401 #comment 远程连线去分行化改造

陈礼鹏80274480 vor 3 Jahren
Ursprung
Commit
a8c8e51204

+ 2 - 0
Module/include/EventCode.h

@@ -592,6 +592,8 @@ ERROR_ACCESSAUTH_CONNECT_ACS}
 #define LOG_WARN_COUNTERCONNECT_CALL_CONNECT_TIME					0x30460008	 //call connect time
 #define LOG_WARN_COUNTERCONNECT_ASSIST_CONNECT_FAILED				0x30460009	 //assist channel connect failed
 #define LOG_WARN_COUNTERCONNECT_SIP_CONNECT_FAILED					0x3046000A	 //sip channel connect failed
+#define LOG_WARN_COUNTERCONNECT_CALL_STATE_TRANS					0x3046000B	 //call state trans
+#define LOG_WARN_COUNTERCONNECT_BROADCAST_CALL_STATE				0x3046000C	 //broadcast call state trans
 /*----End--CounterConnector------------------------------*/  
 
 

+ 148 - 40
Module/mod_counterconnector/ConnectorFSM.cpp

@@ -2,7 +2,8 @@
 #include "ConnectorFSM.h"
 #include "../include/ModuleMix.h"
 #include "../include/EventCode.h"
-
+#include "json/json.h"
+#include <regex>
 
 #define RELEASEING_TIMER_INTERVAL	1200
 #define RELEASEING_SIP_TIMER		20000
@@ -26,6 +27,46 @@ unsigned long GetTickCount()
 }
 #endif
 
+static int iHttpLogCount = 0; 
+
+struct GrayLaunchReq : CHTTPReq{
+	GrayLaunchReq(){m_timeOut = 5;}
+	CSimpleStringA m_terminal_no;
+	CSimpleStringA m_branch_no;
+    CSimpleStringA m_modular;
+	virtual string ToJson(){
+		char reqcontent[512];
+		//string reqcontent = "{\"terminal_no\":\"" + m_terminal_no.GetData() + "\",\"branch_no\":\"" + m_branch_no.GetData() + 
+		//	"\",\"m_modular\":\"" + m_modular.GetData() + "\"}";
+		sprintf(reqcontent, "{\"terminal_no\":\"%s\",\"branch_no\":\"%s\",\"modular\":\"%s\"}", m_terminal_no.GetData(), 
+			m_branch_no.GetData(), m_modular.GetData());
+		return reqcontent;
+	}
+};
+
+
+struct GrayLaunchResponse : CHTTPRet{
+	GrayLaunchResponse():m_result(false){}
+	bool m_result;
+	virtual bool Parse(string strData){
+		Dbg("GrayLaunchResponse: data = %s", strData.c_str());
+		Json::Value root;
+		Json::Reader reader;
+		reader.parse(strData, root, false);
+		if (root["data"].isBool()) {
+			m_result = root["data"].asBool();
+		}
+		return m_result;
+	}
+};
+
+static void HTTPLogCallback(const char* msg){
+	if (0 == iHttpLogCount){
+		LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_COUNTERCONNECT_GRAY_FAILED, msg);
+		iHttpLogCount++;
+	}	
+}
+
 class  SyncServiceClient:public SyncService_ClientBase
 {
 public:
@@ -135,6 +176,14 @@ ErrorCodeEnum ACMCallFSM::OnInit()
 	memset(m_strChanCallNum,0,sizeof(m_strChanCallNum));
 	memset(m_strChanProxyIP,0,sizeof(m_strChanProxyIP));
 	memset(m_iSIPProxyPort,0,sizeof(m_iSIPProxyPort));
+	m_strCallRouteIP = NULL;
+	m_iCallRoutePort = 0;
+	m_strCallRouteBranchNo = NULL;
+	m_strCallRouteAccessNo = NULL;
+	m_pCallRouteList = NULL;
+	m_pHttpFunc = create_http(HTTPLogCallback);
+	m_bGrayLaunch = FALSE;
+	m_strDirectCenterPattern = NULL;
 	ErrorCodeEnum Error = LoadConfig();
 	if (Error != Error_Succeed)
 		goto on_error;
@@ -145,7 +194,10 @@ ErrorCodeEnum ACMCallFSM::OnInit()
 		goto on_error;
 	Dbg("sip proxy ip1:%s,num1:%s,port1:%d;ip2:%s,num2:%s,port2:%d", (LPCSTR)m_strSIPProxyIP[0],(LPCSTR)m_strSIPCallNum[0], m_iSIPProxyPort[0],(LPCSTR)m_strSIPProxyIP[1],(LPCSTR)m_strSIPCallNum[1], m_iSIPProxyPort[1]);
 	Dbg("chan proxy ip1:%s,num1:%s,port1:%d;ip2:%s,num2:%s,port2:%d", (LPCSTR)m_strChanProxyIP[0],(LPCSTR)m_strChanCallNum[0], m_iChanProxyPort[0],(LPCSTR)m_strChanProxyIP[1],(LPCSTR)m_strChanCallNum[1], m_iChanProxyPort[1]);
+	Dbg("CallRouteIP:%s,port:%d", (LPCSTR)m_strCallRouteIP,m_iCallRoutePort);
 	Dbg("TerminalId: %s", (LPCSTR)m_strTerminalId);
+	Dbg("DirectCenterPattern: %s", (LPCSTR)m_strDirectCenterPattern);
+	Dbg("GrayLaunchUrl: %s", (LPCSTR)m_strGrayLaunchUrl);
 	m_bHangup = FALSE;
 	m_bHandFree = TRUE;
 	m_bAgentHandFree = TRUE;
@@ -337,8 +389,11 @@ void ACMCallFSM::OnStateTrans(int iSrcState, int iDstState)
 			if (!((st2 == eState_Fail)&&(m_nCurChanServer != Error_Server)&&(m_nCurSipServer != Error_Server))||m_bHangup)
 			{
 				if (eState_Fail != st1 || eState_Connecting != st2){
-					Dbg("Broadcast state from %d to %d", st1, st2);
+					char strmsg[MAX_PATH] = {0};
+					_snprintf(strmsg, MAX_PATH,"Broadcast state from %d to %d", st1, st2);
+					Dbg(strmsg);
 					SpSendBroadcast(GetEntityBase()->GetFunction(), SP_MSG_OF(PhoneState), SP_MSG_SIG_OF(PhoneState), evt);
+					LogWarn(Severity_Middle, Error_Debug, LOG_WARN_COUNTERCONNECT_BROADCAST_CALL_STATE, strmsg);
 				} 
 				else{
 					char strinfo[MAX_PATH] = {0};
@@ -392,11 +447,16 @@ void ACMCallFSM::s0_on_entry()
 	memset(&m_CallingParam,0,sizeof(m_CallingParam));
 	GetEntityBase()->GetFunction()->SetSysVar("CallType", "N"); //进入初始状态时设置呼叫模式为常规呼叫
 	m_nSysCallType = 0;
+	if(m_pCallRouteList != NULL){
+		free_node_list(m_pCallRouteList);	
+		m_pCallRouteList = NULL;
+	}
 }
 void ACMCallFSM::s0_on_exit() 
 {
 	m_bHangup = FALSE;
 	m_nStarttime = GetTickCount();
+	m_bGrayLaunch = FALSE;
 }
 
 unsigned int ACMCallFSM::s0_on_event(FSMEvent* event)
@@ -532,6 +592,31 @@ unsigned int ACMCallFSM::s9_on_event(FSMEvent* event)
 
 void ACMCallFSM::s8_on_entry() 
 {
+	//get call route,采用直接总行方式
+	if ((m_strDirectCenterPattern.GetLength() != 0) && (m_strGrayLaunchUrl.GetLength() != 0)){
+		if (std::regex_match(m_strTerminalId.GetData(), std::regex(m_strDirectCenterPattern.GetData()))) {
+			GrayLaunchReq req;
+			req.m_url = m_strGrayLaunchUrl.GetData();
+			req.m_terminal_no = m_strTerminalId;
+			req.m_branch_no = m_strCallRouteBranchNo;
+			req.m_modular = "counterconnector";
+			GrayLaunchResponse response;
+			bool ret = m_pHttpFunc->Get(req, response);
+			if (ret) {
+				m_bGrayLaunch = response.m_result;
+			}
+			if (m_bGrayLaunch && (m_strCallRouteIP.GetLength() != 0)) {
+				call_info_t call_info;
+				call_info.callroute_server_ip = m_strCallRouteIP;
+				call_info.callroute_server_port = m_iCallRoutePort;
+				call_info.szbranchno = m_strCallRouteBranchNo;
+				call_info.szcaller_num = m_strTerminalId;
+				call_info.szdest_num = m_strCallRouteAccessNo;
+				m_pCallRouteList = get_callroute_list(&call_info);
+			}
+		}
+	}
+
 	int time = GetDelayTime();
 	Dbg("get Delay time = %d",time);
 	if (time > 0)
@@ -596,50 +681,73 @@ void ACMCallFSM::s11_on_entry()
 	if (m_nCurSipServer == Error_Server){
 		Error = Error_NetBroken;
 	}
-	if (Error == Error_Succeed)
-	{
-		if (m_CallingParam.nCallType != NORMAL_CALLTYPE && m_CallingParam.nCallType != DOUBLERECORD_CALLTYPE)
-		{
-			Dbg("Begin Make Distribute Call!");
-			Error = MakeCall(m_nCurSipServer,m_CallingParam);
-			if (Error!=Error_Succeed)
-			{
-				m_nCurSipServer?(m_nCurSipServer=Error_Server):(m_nCurSipServer=BACK_SERVER);
-			}
-			Dbg("make call result:0x%08x", Error);
-		}
-		else
-		{	
-			if (NORMAL_CALLTYPE == m_CallingParam.nCallType){
-				Dbg("Begin Make Normal Call!");
-			}
+
+	if (Error == Error_Succeed){
+		bool center_connect = FALSE;
+		//get call route,采用直接总行方式
+		if (m_bGrayLaunch && (m_strCallRouteIP.GetLength() != 0)) {
+			callurl_node_t *node = get_no_used_node(m_pCallRouteList);
+			if (node != NULL){
+				Dbg("Begin Head Office Make Call!");
+				char ipstr[256] = {0};
+				char callid_str[64] = { 0 };
+				GetLocalIP(ipstr);
+				get_format_uuid(callid_str, 64);
+				Error = MakeCall(node->strcallurl, CSimpleStringA::Format("sip:%s@%s;transport=UDP", node->strnewcallernum, ipstr), 
+					callid_str, m_CallingParam);
+				m_iChanProxyPort[0] = node->uassistport;
+				m_iChanProxyPort[1] = node->uassistport;
+				m_strChanProxyIP[0] = node->strassistip;
+				m_strChanProxyIP[1] = node->strassistip;
+				if (Error!=Error_Succeed){
+					m_nCurSipServer?(m_nCurSipServer=Error_Server):(m_nCurSipServer=BACK_SERVER);
+				}
+				m_nCurChanServer = BACK_SERVER;
+				node->bused = TRUE;
+				Dbg("head office make call result:0x%08x", Error);
+				center_connect = TRUE;
+			}	
 			else{
-				Dbg("Begin Make Record Call!");
-			}
-			
-			Error = MakeCall(m_strHintCallNum.GetLength() > 0 ? (LPCSTR)m_strHintCallNum : (LPCSTR)m_strSIPCallNum[m_nCurSipServer],m_nCurSipServer);
-			if (Error!=Error_Succeed)
-			{
-				m_nCurSipServer?(m_nCurSipServer=Error_Server):(m_nCurSipServer=BACK_SERVER);
-			}
-			Dbg("make call result:0x%08x", Error);
+				Dbg("head office mode no more call router, try to connect branch server.");
+				//m_nCurSipServer = MAIN_SERVER;
+				//m_nCurChanServer = MAIN_SERVER;
+				center_connect = FALSE;
+			}		
 		}
-	}
 
-	if (Error != Error_Succeed) {
-		if (Error_NetBroken == Error || Error_Unexpect == Error){
-			PostEventFIFO(new FSMEvent(USER_EVT_HANGUP));
-			m_bHangup = TRUE;
-			if (Error_Unexpect == Error){
-				LogFatal(Severity_High, Error_Unexpect, 0, "获取IP失败,请检查机器网络!");
+		//old call branch server方式
+		if(!center_connect){
+			if (m_CallingParam.nCallType != NORMAL_CALLTYPE && m_CallingParam.nCallType != DOUBLERECORD_CALLTYPE)
+			{
+				Dbg("Begin Branch Make Distribute Call!");
+				Error = MakeCall(m_nCurSipServer,m_CallingParam);
+				if (Error!=Error_Succeed)
+				{
+					m_nCurSipServer?(m_nCurSipServer=Error_Server):(m_nCurSipServer=BACK_SERVER);
+				}
+				Dbg("branch make call result:0x%08x", Error);
 			}
-			else{
-				LogFatal(Severity_High, Error_NetBroken, 0, "系统故障,尝试恢复中(预计90s内),请稍等!");
+			else
+			{	
+				if (NORMAL_CALLTYPE == m_CallingParam.nCallType){
+					Dbg("Begin Branch Make Normal Call!");
+				}
+				else{
+					Dbg("Begin Branch Make Record Call!");
+				}
+				
+				Error = MakeCall(m_strHintCallNum.GetLength() > 0 ? (LPCSTR)m_strHintCallNum : (LPCSTR)m_strSIPCallNum[m_nCurSipServer],m_nCurSipServer);
+				if (Error!=Error_Succeed)
+				{
+					m_nCurSipServer?(m_nCurSipServer=Error_Server):(m_nCurSipServer=BACK_SERVER);
+				}
+				Dbg("branch make call result:0x%08x", Error);
 			}
 		}
-		else{
-			PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL));
-		}
+	}
+	if (Error != Error_Succeed) 
+	{
+		PostEventFIFO(new FSMEvent(USER_EVT_JMP_FAIL));
 	}
 	else
 	{

+ 94 - 9
Module/mod_counterconnector/ConnectorFSM.h

@@ -3,8 +3,10 @@
 #include "SpHelper.h"
 #include "SpFSM.h"
 #include "SpIni.h"
+#include "IHttpFunc.h"
 
 #include "Event.h"
+#include "callrouter.h"
 
 #ifdef _WIN32
 #include "resource.h"
@@ -490,6 +492,47 @@ private:
 	int TranslateState(int innerState);
 	ErrorCodeEnum SetCallState(int state);
 
+	void get_format_uuid(char* strbuffer, size_t ulen)
+	{
+		UUID uuid;
+		size_t uuidlen = 0;
+		//RPC_CSTR buf;
+		//UuidCreate((UUID*)&uuid);
+		//UuidToString((UUID*)&uuid, &buf);
+
+		//uuidlen = strlen((const char*)buf);
+		//if (uuidlen < ulen) {
+		//	memcpy(strbuffer, (const char*)buf, uuidlen);
+		//}
+
+		//RpcStringFree(&buf);
+	}
+
+	ErrorCodeEnum GetLocalIP(char *buff)
+	{
+		char tmp[256];
+		gethostname(tmp, sizeof(tmp));
+		hostent *ent = gethostbyname(tmp);
+		if (ent) {
+			for (int i = 0; ent->h_addr_list[i]; ++i) {
+				if (ent->h_addrtype == AF_INET) {
+					struct in_addr *in = (struct in_addr*)ent->h_addr_list[i];
+					char *p = inet_ntoa(*in);
+					if (p[0] != '0') 
+					{
+						if(strstr(p,"198.168.") == NULL)
+						{
+							strcpy(buff, p);
+							Dbg("local ip == %s", buff);
+							return Error_Succeed;
+						}
+					}
+				}
+			}
+		}
+		return Error_Unexpect;
+	}
+
 	ErrorCodeEnum MakeCall(int nSipServer,CallingParam callingparam)
 	{
 		if (!m_pPhoneClient)
@@ -503,17 +546,17 @@ private:
 			{
 				CSimpleStringA session = "80";
 				session+=callingparam.connect_session;
-				Req.call_uri = MakeCallUri(session,callingparam.connect_ip,callingparam.connect_port);
+				Req.to_uri = MakeCallUri(session,callingparam.connect_ip,callingparam.connect_port);
 			}
 			else if((callingparam.nCallType == PADTOPAD_CALLTYPE)||(callingparam.nCallType == MOBILETOPAD_CALLTYPE))
 			{
 				CSimpleStringA session = "90";
 				session+=callingparam.connect_session;
-				Req.call_uri = MakeCallUri(session,callingparam.connect_ip,callingparam.connect_port);
+				Req.to_uri = MakeCallUri(session,callingparam.connect_ip,callingparam.connect_port);
 			}
 			else
 			{
-				Req.call_uri = MakeCallUri(callingparam.connect_session,callingparam.connect_ip,callingparam.connect_port);
+				Req.to_uri = MakeCallUri(callingparam.connect_session,callingparam.connect_ip,callingparam.connect_port);
 			}
 		}
 		else
@@ -528,17 +571,17 @@ private:
 				{
 					CSimpleStringA session = "80";
 					session+=callingparam.connect_session;
-					Req.call_uri = MakeCallUri(session,nSipServer);
+					Req.to_uri = MakeCallUri(session,nSipServer);
 				}
 				else if((callingparam.nCallType == PADTOPAD_CALLTYPE)||(callingparam.nCallType == MOBILETOPAD_CALLTYPE))
 				{
 					CSimpleStringA session = "90";
 					session+=callingparam.connect_session;
-					Req.call_uri = MakeCallUri(session,nSipServer);
+					Req.to_uri = MakeCallUri(session,nSipServer);
 				}
 				else
 				{
-					Req.call_uri = MakeCallUri(callingparam.connect_session,nSipServer);
+					Req.to_uri = MakeCallUri(callingparam.connect_session,nSipServer);
 				}
 			}
 		}
@@ -549,7 +592,7 @@ private:
 		info.connect_ip = callingparam.connect_ip;
 		info.connect_port = callingparam.connect_port;
 	    m_pPhoneClient->SetCallingParam(info);
-		Dbg("Make Distribute Call CallType = %d", info.CallType);
+		Dbg("Make Distribute Call CallType = %d, to_uri:%s", info.CallType, Req.to_uri.GetData());
 
 		ErrorCodeEnum Error = m_pPhoneClient->MakeCall(Req, Ans, 10000);
 		return Error;
@@ -568,7 +611,7 @@ private:
 		CSimpleStringA strCode;
 		PhoneService_MakeCall_Req Req;
 		PhoneService_MakeCall_Ans Ans;
-		Req.call_uri = MakeCallUri(hint_callnum,nSipServer);
+		Req.to_uri = MakeCallUri(hint_callnum,nSipServer);
 
 		PhoneService_SetCallingParam_Info info;
 		info.CallType = NORMAL_CALLTYPE;
@@ -578,7 +621,32 @@ private:
 		}
 		m_pPhoneClient->SetCallingParam(info);
 
-		Dbg("before make call, call type is %d", info.CallType);
+		Dbg("before make call, call type is %d, to_uri:%s", info.CallType, Req.to_uri.GetData());
+		ErrorCodeEnum Error = m_pPhoneClient->MakeCall(Req, Ans, 10000);
+		return Error;
+	}
+
+	ErrorCodeEnum MakeCall(const char *to_uri, const char *from_uri, const char *call_id, CallingParam callingparam)
+	{
+		if (!m_pPhoneClient)
+			return Error_NetBroken;
+		CSimpleStringA strCode;
+		PhoneService_MakeCall_Req Req;
+		PhoneService_MakeCall_Ans Ans;
+		Req.to_uri = to_uri;
+		Req.from_uri = from_uri;
+		Req.call_id = call_id;
+
+
+		//设置呼叫参数
+		PhoneService_SetCallingParam_Info info;
+		info.CallType = callingparam.nCallType;
+		info.connect_session = callingparam.connect_session;
+		info.connect_ip = callingparam.connect_ip;
+		info.connect_port = callingparam.connect_port;
+		m_pPhoneClient->SetCallingParam(info);
+		Dbg("before make call, call type is %d, to_uri:%s, from_uri:%s, call_id:%s", info.CallType, to_uri, from_uri, call_id);
+
 		ErrorCodeEnum Error = m_pPhoneClient->MakeCall(Req, Ans, 10000);
 		return Error;
 	}
@@ -739,6 +807,12 @@ private:
 		table.AddEntryString("CounterConnector", "chan_proxy_ip_backup", m_strChanProxyIP[1], NULL);
 		table.AddEntryInt("CounterConnector", "chan_proxy_port_backup", m_iChanProxyPort[1], 0);
 		table.AddEntryString("CounterConnector", "chan_default_call_no_backup", m_strChanCallNum[1], NULL);
+		table.AddEntryString("CounterConnector", "call_route_ip", m_strCallRouteIP, NULL);
+		table.AddEntryInt("CounterConnector", "call_route_port", m_iCallRoutePort, 0);
+		table.AddEntryString("CounterConnector", "call_route_access_no", m_strCallRouteAccessNo, NULL);
+		table.AddEntryString("Initializer", "SubBankNo", m_strCallRouteBranchNo, NULL);
+		table.AddEntryString("Common", "GrayLaunchUrl", m_strGrayLaunchUrl, NULL);
+		table.AddEntryString("CounterConnector", "DirectCenterPattern", m_strDirectCenterPattern, NULL);
 		CSmartPointer<IConfigInfo> spConfig;
 		ErrorCodeEnum Error = m_pEntity->GetFunction()->OpenConfig(Config_CenterSetting, spConfig);
 		if (Error == Error_Succeed) {
@@ -860,5 +934,16 @@ private:
 	int m_iChanProxyPort[2];
 	CSimpleStringA m_strChanCallNum[2];
 
+	//去分行化
+	CSimpleStringA m_strCallRouteIP;
+	int m_iCallRoutePort;
+	CSimpleStringA m_strCallRouteBranchNo;
+	CSimpleStringA m_strCallRouteAccessNo;
+	node_list_head_t *m_pCallRouteList;
+	CSimpleStringA m_strGrayLaunchUrl;
+	IHttpFunc *m_pHttpFunc;
+	BOOL m_bGrayLaunch;
+	CSimpleStringA m_strDirectCenterPattern;//临时使用,后续分行网络全部开通后去掉
+
 	BOOL m_bRing;
 };

+ 134 - 0
Module/mod_counterconnector/callroute_nodelist.cpp

@@ -0,0 +1,134 @@
+#include "callroute_nodelist.h"
+#include "strutil.h"
+#include <string.h>
+
+#ifndef	SAFE_FREE
+#define SAFE_FREE(p)		if (p){free(p);	p = NULL;}
+#endif
+
+node_list_head_t* create_node_list_head(const char* pcallernum)
+{
+	node_list_head_t* pnode = NULL;
+	if (NULL != pcallernum){
+		pnode = (node_list_head_t*)malloc(sizeof(node_list_head_t));
+		if (NULL != pnode){
+			size_t ulen = strlen(pcallernum);
+			char* pnumber = (char*)malloc(ulen+1);
+			memset(pnumber, 0, ulen+1);
+			memcpy(pnumber, pcallernum, ulen);
+			pnode->pcallernum = pnumber;
+			pnode->nodecount = 0;
+			pnode->pnext = NULL;
+		}
+	}
+
+	return pnode;
+} 
+
+
+int add_node_to_list(node_list_head_t* plist, const char* newcallernum, const char* pcallurl, const char* pstrassistip, const char*  pstrport)
+{
+	int ret = -1;
+	if (NULL == plist){
+		return ret;
+	}
+
+	if (NULL != pcallurl && NULL != pstrassistip && NULL != pstrport){
+		callurl_node_t* plast = plist->pnext;
+		callurl_node_t* pnode = (callurl_node_t*)malloc(sizeof(callurl_node_t));
+
+		size_t ulen = strlen(pcallurl);
+		char* psipurl = (char*)malloc(ulen+1);
+		char* pstrnewcallernum = NULL;
+		char* pstrip = NULL;
+		int uport = atoi(pstrport);
+
+		memset(psipurl, 0, ulen+1);
+		fifter_string(psipurl, ulen+1, pcallurl, '\'');
+
+		ulen = strlen(pstrassistip);
+		pstrip = (char*)malloc(ulen+1);
+		memset(pstrip, 0, ulen+1);
+		memcpy(pstrip, pstrassistip, ulen);
+
+		ulen = strlen(newcallernum);
+		pstrnewcallernum = (char*)malloc(ulen+1);
+		memset(pstrnewcallernum, 0, ulen+1);
+		memcpy(pstrnewcallernum, newcallernum, ulen);
+
+		pnode->strcallurl = psipurl;
+		pnode->strassistip = pstrip;
+		pnode->strnewcallernum = pstrnewcallernum;
+		pnode->uassistport = (unsigned int)uport;
+		pnode->bused = false;
+		pnode->pnext = NULL;
+
+		if (NULL != plast){
+			while(plast && NULL != plast->pnext){
+				plast = plast->pnext;
+			}
+			plast->pnext = pnode;
+			plist->nodecount++;
+		}
+		else{
+			*(&plist->pnext) = pnode;
+			plist->nodecount++;
+		}
+		ret = 0;
+	}
+	return ret;
+}
+
+
+callurl_node_t* get_no_used_node(node_list_head_t* plist){
+	callurl_node_t *phead = NULL;
+	callurl_node_t *pnode = NULL;
+	if (NULL != plist){
+		phead = plist->pnext;
+		while(phead){
+			pnode = phead;
+			if (pnode->bused == false){
+				return pnode;
+			}
+			phead = phead->pnext;
+		}
+	}
+	return NULL;
+}
+
+
+int free_node_list(node_list_head_t* plist)
+{
+	callurl_node_t *phead = NULL;
+	callurl_node_t *pnode = NULL;
+	if (NULL != plist){
+		free(plist->pcallernum);
+		plist->pcallernum = NULL;
+		phead = plist->pnext;
+		while(phead){
+			pnode = phead;
+			phead = phead->pnext;
+			free_callurl_node(pnode);
+		}
+		SAFE_FREE(plist);
+	}
+
+	return 0;
+}
+
+int free_callurl_node(callurl_node_t* pnode)
+{
+	int ret = -1;
+	if (NULL == pnode){
+		return ret;
+	}
+
+	SAFE_FREE(pnode->strnewcallernum);
+	SAFE_FREE(pnode->strassistip);
+	SAFE_FREE(pnode->strcallurl);
+
+	free(pnode);
+	pnode = NULL;
+	
+	return ret;
+}

+ 28 - 0
Module/mod_counterconnector/callroute_nodelist.h

@@ -0,0 +1,28 @@
+#ifndef	_CALLROUTE_NODELIST_
+#define _CALLROUTE_NODELIST_
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct callurl_node_s{
+	bool	bused;
+	char*	strnewcallernum;
+	char*	strcallurl;
+	char*	strassistip;
+	unsigned int	uassistport;
+	struct callurl_node_s* pnext; 
+}callurl_node_t;
+
+
+typedef struct node_list_head_s{
+	char* pcallernum;
+	unsigned int nodecount;
+	callurl_node_t*	pnext;
+}node_list_head_t;
+
+node_list_head_t* create_node_list_head(const char* pcallernum);
+int add_node_to_list(node_list_head_t* plist, const char* newcallernum, const char* pcallurl, const char* pstrassistip, const char* pstrport);
+int free_node_list(node_list_head_t* plist);
+callurl_node_t* get_no_used_node(node_list_head_t* plist);
+int free_callurl_node(callurl_node_t* pnode);
+
+#endif

+ 34 - 0
Module/mod_counterconnector/callroute_request.cpp

@@ -0,0 +1,34 @@
+#include "callroute_request.h"
+#include "strutil.h"
+
+
+int fill_packet(proxy_req_packet_t* req_packet, const char* paccessnum, const char* pcalleridnum, const char* branchnum, char*strTime)
+{
+	int ret = -1;
+	char striLen[10] = {0};
+	int iLen =  sizeof(proxy_req_packet_t) - 4;
+
+	if (NULL == req_packet){
+		return ret;
+	}
+
+	itoa(iLen, striLen, 10);
+	proxy_copy(req_packet->req_hdr.packgelen, striLen);
+	req_packet->req_hdr.version = '1';
+	proxy_copy(req_packet->req_hdr.tradefrom, "VGA");
+	proxy_copy(req_packet->req_hdr.requestcode, "RvcRouteReq");
+
+	proxy_copy(req_packet->req_hdr.reqtime, strTime);
+	proxy_copy(req_packet->req_body.bodysnum, "1");
+	proxy_copy(req_packet->req_body.bodylen, "40");
+	proxy_copy(req_packet->req_body.bodyname, "RvcRouteReq");
+	proxy_copy(req_packet->req_body.accessnum, paccessnum);
+	proxy_copy(req_packet->req_body.terminalno, pcalleridnum);
+	proxy_copy(req_packet->req_body.branchno, branchnum);
+
+	ret = 0;
+
+	return ret;
+}
+
+

+ 60 - 0
Module/mod_counterconnector/callroute_request.h

@@ -0,0 +1,60 @@
+#ifndef	_CALLROUTE_REQUEST_
+#define _CALLROUTE_REQUEST_
+#include <stdio.h>
+#include <stdlib.h>
+
+//请求包数据结构
+typedef struct proxy_req_hdr
+{
+	char	packgelen[4];					// 整包长,不含此字段(4bit)
+	char	version;						// 版本号(1bit)
+	char	tradefrom[3];					// 渠道代码(3bit) MGA
+	char	terminalno[30];					// 终端号(30bit),可不填
+	char	reqtime[14];					// 请求时间(14bit)
+	char	requestcode[16];				// 请求码(16bit)
+	char	errorcode[7];					// 错误码(7bit)回包填
+	char	errormsg[20];					// 错误信息(20bit)回包填
+	char	reserved[30];					// 保留字段(30bit)
+}proxy_req_hdr_t;
+
+typedef struct proxy_req_body
+{
+	char	bodysnum[4];					// 包体数量(4bit)
+	char	bodyname[30];					// 包体名(30bit)
+	char	bodylen[4];						// 单个包体长度(4bit)
+	char	branchno[10];					// 分行编号(10bit)可不填      
+	char	terminalno[20];					// 终端号(20bit)可不填
+	char	accessnum[10];					// 呼入码(10bit)必填
+}proxy_req_body_t;
+
+typedef struct proxy_req_packet
+{
+	proxy_req_hdr_t		req_hdr;			//请求包头
+	proxy_req_body_t	req_body;			//请求包体
+}proxy_req_packet_t;
+
+typedef struct proxy_rsp_body
+{
+	char	unkown_flag_a[4];			//1
+	char	gateway_type_a[30];			//网关类型
+	char	audio_len[4];				//内容长度
+	char	audio_centent[150];			//内容
+
+	char	unkown_flag_b[4];			//1
+	char	gateway_type_b[30];			//网关类型
+	char	video_len[4];				//内容长度
+	char	video_content_ip[20];		//内容(前20字节为ip,后10字节为端口号	
+	char	video_content_port[10];		//内容(前20字节为ip,后10字节为端口号	
+}proxy_rsp_body_t;
+
+//回复包数据结构
+typedef struct proxy_rsp_packet{
+	proxy_req_hdr_t		req_hdr;			//请求包头
+	proxy_rsp_body_t	rsp_body;
+}proxy_rsp_packet_t;
+
+
+int fill_packet(proxy_req_packet_t* req_packet, const char* paccessnum, const char* pcalleridnum, const char* branchnum, char*strTime);
+
+
+#endif

+ 254 - 0
Module/mod_counterconnector/callrouter.cpp

@@ -0,0 +1,254 @@
+#include "stdafx.h"
+#include "callrouter.h"
+#include "strutil.h"
+#include "callroute_request.h"
+#include "callroute_nodelist.h"
+#include "SpBase.h"
+
+#include <process.h>
+#include <DbgHelp.h>
+#pragma comment(lib, "dbghelp.lib")
+
+
+
+static int get_sys_time(char* pDst, size_t iLen)
+{
+	int iret = 0;
+#ifdef _WIN32||_WIN64
+	SYSTEMTIME sys; 
+	GetLocalTime( &sys ); 
+	_snprintf(pDst, iLen, "%04d%02d%02d%02d%02d%02d",sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond); 
+	if (NULL != pDst){
+		iret = strlen(pDst);
+	}
+#endif
+	return iret;
+}
+
+
+static int set_socket_attribute(SOCKET client_socket, int timeout)
+{
+	int ret = -1;
+
+	if(setsockopt(client_socket,SOL_SOCKET,SO_SNDTIMEO,(char *)&timeout,sizeof(timeout))==SOCKET_ERROR){
+		closesocket(client_socket);
+		return ret;
+	}
+
+	if(setsockopt(client_socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(timeout))==SOCKET_ERROR){
+		closesocket(client_socket);
+		return ret;
+	}
+
+	ret = 0;
+	return ret;
+}
+
+static int request_voipgateway_address(call_info_t *call_info, proxy_rsp_packet_t* rsp_packet, const size_t rsp_len)
+{
+	int ret = -1;
+	//套接字控制模式
+	u_long mode = 1;
+	//请求包结构体
+	proxy_req_packet_t	req_info = {0};
+	size_t len = sizeof(proxy_req_packet_t);
+
+	char strtime[RVC_DATALEN] = {0};
+	BOOL bconnected = FALSE;
+	int itimelen = 0;
+
+	SOCKET client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if (set_socket_attribute(client_socket, 2000)){
+		Dbg(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("request_voipgateway_address set_socket_attribute failed.");
+		return ret;
+	}
+	if (INVALID_SOCKET != client_socket){
+		struct sockaddr_in sa;  
+		sa.sin_family = AF_INET;  
+		sa.sin_addr.S_un.S_addr = inet_addr(call_info->callroute_server_ip);
+		sa.sin_port = htons(call_info->callroute_server_port);
+		memset(sa.sin_zero, 0, sizeof(sa.sin_zero)); 
+
+		//控制为非阻塞方式
+		ioctlsocket(client_socket,FIONBIO,&mode);
+		ret = connect(client_socket, (struct sockaddr *)&sa, sizeof(struct sockaddr));
+		if (0 == ret){
+			bconnected = TRUE;
+		}
+		else{
+			fd_set set;  
+			struct timeval timeout;  
+			FD_ZERO(&set);  
+			FD_SET(client_socket, &set);  
+			timeout.tv_sec = 2;  
+			timeout.tv_usec = 0;  
+			if (select(NULL, NULL, &set, NULL, &timeout)>0){  
+				bconnected = TRUE;  
+			}
+		}
+		//控制为阻塞方式
+		mode = 0;  
+		ioctlsocket(client_socket, FIONBIO, &mode);  
+		if (!bconnected){	//连接失败  
+			closesocket(client_socket);
+			Dbg(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("request_voipgateway_address connect callroute server timeout.");
+			return ret;      //超时
+		} 
+		
+		reset_buffer(&req_info, 0x20, sizeof(proxy_req_packet_t));
+		itimelen = get_sys_time(strtime, RVC_DATALEN);
+		if (0 < itimelen){
+			fill_packet(&req_info, call_info->szdest_num, call_info->szcaller_num, call_info->szbranchno, strtime);
+		}
+
+		ret = send(client_socket, (const char*)(&req_info), len, 0);
+
+		if (ret <= 0){
+			closesocket(client_socket);
+			Dbg(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("request_voipgateway_address send to callroute server failed.");
+			return ret;
+		}
+
+		ret = recv(client_socket, (char*)rsp_packet, rsp_len, 0);
+
+		closesocket(client_socket);
+		if (ret <= 0){
+			Dbg(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("request_voipgateway_address recv from callroute server failed.");
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+static bool is_response_packet_valid(proxy_rsp_packet_t* packet_info)
+{
+	bool bret = false;
+	if (NULL != packet_info){
+		char strflag[] = {0x33, 0x37, 0x37, 0x20, 0x0};
+		size_t uflaglen = strlen(strflag);
+		if (0 != memcmp(packet_info->req_hdr.packgelen, strflag, uflaglen)){
+			char packgelen[5] = {0};
+			char tradefrom[4] = {0};
+			char requestcode[17] = {0};
+			memcpy(packgelen, packet_info->req_hdr.packgelen, 4);
+		    memcpy(tradefrom, packet_info->req_hdr.tradefrom, 3);
+			memcpy(requestcode, packet_info->req_hdr.requestcode, 16);
+			Dbg(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("get mediaserver address from callroute server failed, rsp packgelen:%s, tradefrom:%s, requestcode:%s!", 
+				packgelen,tradefrom, requestcode);
+		}else{
+			bret = true;
+		}
+	}
+	return bret;
+}
+
+static int fifter_sparate_flag(proxy_rsp_packet_t* packet_info)
+{
+	int ret = -1;
+	if (NULL != packet_info){
+		rend_string(packet_info->rsp_body.audio_centent, 0x20);
+		rend_string(packet_info->rsp_body.video_content_ip, 0x20);
+		rend_string(packet_info->rsp_body.video_content_port, 0x20);
+		ret = 0;
+	}
+	return ret;
+} 
+static unsigned int separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen)
+{
+	unsigned int count = 0;
+	char *d;
+	size_t dlen = strlen(delim);
+
+	array[count++] = buf;
+
+	while (count < arraylen && array[count - 1]) {
+		if ((d = strstr(array[count - 1], delim))) {
+			*d = '\0';
+			d += dlen;
+			array[count++] = d;
+		} else
+			break;
+	}
+
+	return count;
+}
+
+
+static node_list_head_t *create_node_list_by_callernum(call_info_t *call_info, proxy_rsp_packet_t* packet_info)
+{
+	node_list_head_t *phead = NULL;
+	char new_touri[RVC_DATALEN]={0};
+	char strinterip[RVC_DATALEN]={0};
+	char new_caller_number[RVC_DATALEN]={0};
+	
+	if (NULL == call_info || NULL == packet_info){
+		return NULL;
+	}
+
+	if (is_response_packet_valid(packet_info)){
+		if (0 == fifter_sparate_flag(packet_info)){
+			char *dp[10] = {NULL};
+			int argc, x = 0;
+			argc = separate_string_string(packet_info->rsp_body.audio_centent, ",", dp, (sizeof(dp) / sizeof(dp[0])));
+			if (argc < 1){
+				return NULL;
+			}
+			phead = create_node_list_head(call_info->szcaller_num);
+			for (x = 0; x < argc; x++) {
+				char *dpname = dp[x];
+				if (dpname) {
+					//去掉'号
+					char to_uri[RVC_DATALEN]={0};
+					fifter_string(to_uri, RVC_DATALEN, dpname, '\'');
+					//to url 前面+8
+					if ('8' == dpname[0]){
+						_snprintf(new_touri, RVC_DATALEN, "%s%s", "sip:", to_uri);
+					}
+					else{
+						_snprintf(new_touri, RVC_DATALEN, "%s%s%s", "sip:", "8", to_uri);
+					}
+					//new new_caller_id_number=callernum#assist_int_ip
+					get_interger_netaddr(strinterip, RVC_DATALEN, packet_info->rsp_body.video_content_ip);
+					_snprintf(new_caller_number, RVC_DATALEN, "%s%s%s",
+						call_info->szcaller_num.GetData(), "#", strinterip);
+
+					Dbg(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("new callroute node: new_caller_number:%s new_touri:%s, assist_ip:%s, assist_port:%s!", 
+									new_caller_number, new_touri, packet_info->rsp_body.video_content_ip, packet_info->rsp_body.video_content_port);
+					add_node_to_list(phead, new_caller_number, new_touri, packet_info->rsp_body.video_content_ip, packet_info->rsp_body.video_content_port);
+				}
+			}
+		}
+	}else{
+		Dbg(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("create_node_list_by_callernum failed. szbranchno:%s, szcaller_num:%s, szdest_num:%s.", call_info->szbranchno.GetData(), call_info->szcaller_num.GetData(), call_info->szdest_num.GetData());
+	}
+
+	return phead;
+}
+
+node_list_head_t *get_callroute_list(call_info_t *call_info)
+{
+	int ret;
+	proxy_rsp_packet_t  rsp_info = {0}; 
+	size_t recvlen = sizeof(proxy_rsp_packet_t);
+
+	if (call_info->callroute_server_ip.GetLength() == 0 || 
+		call_info->callroute_server_port == 0 || 
+		call_info->szdest_num.GetLength() == 0 ||
+		call_info->szcaller_num.GetLength() == 0 ||
+		call_info->szbranchno.GetLength() == 0) {
+		Dbg(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("get_callroute_list failed call_info param is null.");
+		return NULL;
+	}
+
+	reset_buffer(&rsp_info, 0x20, sizeof(proxy_rsp_packet_t));
+	ret = request_voipgateway_address(call_info, &rsp_info, recvlen);
+	if (ret <= 0){
+		Dbg(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("get_callroute_list failed szbranchno:%s, szcaller_num:%s, szdest_num:%s.", call_info->szbranchno.GetData(), call_info->szcaller_num.GetData(), call_info->szdest_num.GetData());
+		return NULL;
+	}
+	
+	return create_node_list_by_callernum(call_info, &rsp_info);
+}
+
+

+ 25 - 0
Module/mod_counterconnector/callrouter.h

@@ -0,0 +1,25 @@
+#ifndef	_CALLROUTER_
+#define _CALLROUTER_
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "callroute_nodelist.h"
+#include "SimpleString.h"
+
+#ifndef RVC_DATALEN
+#define RVC_DATALEN 126
+#endif
+
+//call_info
+typedef struct call_info{
+	CSimpleStringA callroute_server_ip;
+	int callroute_server_port;
+	CSimpleStringA szdest_num;
+	CSimpleStringA szcaller_num;
+	CSimpleStringA szbranchno;
+}call_info_t; 
+
+
+node_list_head_t *get_callroute_list(call_info_t *call_info);
+
+#endif

+ 115 - 0
Module/mod_counterconnector/strutil.cpp

@@ -0,0 +1,115 @@
+#include "stdafx.h"
+#include "strutil.h"
+
+int reset_buffer(void* pbuf, int idata, size_t ulen)
+{
+	int ret = -1;
+	if (pbuf){
+		memset(pbuf, idata, ulen);
+		ret = 0;
+	}
+
+	return ret;
+}
+
+
+int rend_string(char* pSrc, int iflag)
+{
+	int ret = -1;
+	if (pSrc){
+		char* pindex = pSrc;
+		while(*pindex != iflag){
+			pindex++;
+		};
+		*pindex = '\0';
+		ret = 0;
+	}
+
+	return ret;
+}
+
+int fifter_string(char*pbuf, size_t usize, const char* psrc, const char cflag)
+{
+	int ret = -1;
+	int i = 0;
+	int j = 0;
+	size_t ulen = 0;
+	const char* pindex = psrc;
+	if (NULL == psrc){
+		return ret;
+	}
+
+	ulen = strlen(psrc);
+	for (i=0; i<ulen && i<usize; i++){
+		if (pindex[i] != cflag){
+			pbuf[j++] = pindex[i];
+		}
+	}
+	if (j == ulen - 2){
+		ret = 0;
+	}
+
+	return ret;
+}
+
+int get_interger_netaddr(char *strbuf, size_t ubufszie, const char* szip)
+{
+	int ret = -1;
+
+	unsigned long ulip = 0;
+	if (NULL == strbuf || NULL == szip){
+		return ret;
+	}
+
+	ulip = inet_addr(szip);
+	ultoa(ulip, strbuf, 10);
+
+	ret = 0;
+	return ret;
+}
+
+int convert_interaddr_strip(char *strbuf, size_t ubufszie, const char* szinter_ip)
+{
+	int ret = -1;
+	char* strip = NULL;
+	struct sockaddr_in addr = {0};
+	if (!szinter_ip || !strbuf){
+		return ret;
+	}
+
+	addr.sin_addr.s_addr = strtoul(szinter_ip, NULL, 10);//inet_addr(config->switch_server);
+	strip = inet_ntoa(addr.sin_addr);
+	if (strip){
+		size_t ulen = strlen(strip);
+		if (ulen < ubufszie){
+			memcpy(strbuf, strip, ulen);
+			ret = 0;
+		}
+	}
+
+	return ret;
+}
+
+
+int connect_strings(char* strbuf, size_t ulen, const char* psrca, const char* pstr, const char* psrcb)
+{
+	int ret = -1;
+	size_t ulena = 0;
+	size_t ulenb = 0;
+	size_t ulenstr = 0;
+
+	if(!psrca || !psrcb || !pstr){
+		return ret;
+	}
+
+	ulena = strlen(psrca);
+	ulenb = strlen(psrcb);
+	ulenstr = strlen(pstr);
+
+	if (ulen > ulena + ulenb + ulenstr){
+		_snprintf(strbuf, ulen, "%s%s%s", psrca, pstr, psrcb);
+		ret = 0;
+	}
+
+	return ret;
+}

+ 22 - 0
Module/mod_counterconnector/strutil.h

@@ -0,0 +1,22 @@
+#ifndef _STR_UTIL_
+#define _STR_UTIL_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <io.h>
+#include <string.h>
+
+#ifndef RVC_DATALEN
+#define RVC_DATALEN 126
+#endif
+
+#define proxy_copy(pDst, pSrc)		if(pSrc)	{	memcpy(pDst, pSrc, strlen(pSrc));	}
+
+int reset_buffer(void* pbuf, int idata, size_t ulen);
+int rend_string(char* pSrc, int iflag);
+int fifter_string(char*pbuf, size_t usize, const char* psrc, const char cflag);
+int get_interger_netaddr(char *strbuf, size_t ubufszie, const char* szip);
+int convert_interaddr_strip(char *strbuf, size_t ubufszie, const char* szinter_ip);
+int connect_strings(char* strbuf, size_t ulen, const char* psrca, const char* psrcb, const char* pstr);
+
+#endif

+ 4 - 2
Module/mod_sipphone/SIPPhone_def_g.h

@@ -51,11 +51,13 @@ namespace SIPPhone {
 
 struct PhoneService_MakeCall_Req
 {
-	CSimpleStringA call_uri;
+	CSimpleStringA to_uri;
+	CSimpleStringA from_uri;
+	CSimpleStringA call_id;
 
 	void Serialize(SpBuffer &Buf)
 	{
-		auto & buf = Buf & call_uri;
+		auto & buf = Buf & to_uri & from_uri & call_id;
 	}
 
 };

+ 3 - 1
Module/mod_sipphone/SipService.xml

@@ -10,7 +10,9 @@
 	<class name="PhoneService" overlap="true" exclusive="false">
 		<twoway name="MakeCall" overlap="true">
 			<req>
-				<param name="call_uri" type="string"/>
+				<param name="to_uri" type="string"/>
+				<param name="from_uri" type="string"/>
+				<param name="call_id" type="string"/>
 			</req>
 		</twoway>
 		<twoway name="HangupCall" overlap="true">

+ 2 - 2
Module/mod_sipphone/mod_sipphone.cpp

@@ -2098,11 +2098,11 @@ void CSIPPhoneSession::OnClose( ErrorCodeEnum eErrorCode )
 void CSIPPhoneSession::Handle_MakeCall( SpReqAnsContext<PhoneService_MakeCall_Req, PhoneService_MakeCall_Ans>::Pointer ctx )
 {
 	LOG_FUNCTION();
-	LOG_TRACE("make call [%s]", (LPCSTR)ctx->Req.call_uri);
+	LOG_TRACE("make call [%s]", (LPCSTR)ctx->Req.to_uri);
 	int rc;
 	MakeCallCommand *cmd = new MakeCallCommand();
 	cmd->pSIPPhoneSession = this;
-	cmd->strUri = ctx->Req.call_uri;
+	cmd->strUri = ctx->Req.to_uri;
 	///////////重新初始化sip话机,防止断网导致IP改变//////////////////
 
 	if (m_pEntity->m_pEndpoint){