⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gkclient.cpp

📁 一个c++实现的acd的例子。 ----ACDCommandListener.cpp ---ACDCommandListenerThread.cpp ---ACDConfig.cpp ---a
💻 CPP
字号:
 /*=============================================================

 
 Function:
		


 Author: Leon Wang <wlywly@sina.com  giga2@tom.com>
==============================================================*/
// GkClient.cpp: implementation of the GkClient class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "GkClient.h"
#include "acdx.h"
#include "h323utils.h"

#include <vector>
#include <algorithm>
#include <IOSTREAM.h>


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//##ModelId=42198D180097
class ACDX;
class H323Utils;

//using namespace std;
//##ModelId=424BB6460130
long GkClient::WAIT_SEC = 5;// wait 5 seconds before reconnecting to GnuGk

//##ModelId=424BB6460017
GkClient::GkClient()
{
	//splitFields_cmd.reserve(10);// for gk command
	//splitFields_alia.reserve(4);// for alias
	stopped = FALSE;
	m_buf = NULL;
}

//##ModelId=424BB6460018
GkClient::GkClient(ACDX* p, DWORD ip, int port)
{
	m_buf = NULL;
}

//##ModelId=424BB64600B3
GkClient::~GkClient()
{

}

//##ModelId=424BB6460007
unsigned __stdcall  GkClient::_RUN(void *p)
{
	GkClient * pThis = (GkClient*)p;
	pThis->RUN();
	delete pThis;
	return 0;	
}

//##ModelId=424BB64503E1
void GkClient::RUN()
{
	//DWORD ip = inet_addr("192.168.1.43");
	//open socket
	while (!stopped) {
		// connect GK port 
		int rv;
		GK_socket = socket(AF_INET, SOCK_STREAM,0);
		if(GK_socket == ~0){
			printErrorMessage();
			closesocket(GK_socket);
			return ;
		}


		struct sockaddr_in sin = {0};
		sin.sin_family = AF_INET;
		sin.sin_addr.s_addr = inet_addr(host);
		sin.sin_port = htons(port);

		rv = connect(GK_socket, (struct sockaddr*)&sin,sizeof(sin));
		if(rv != 0){
			printErrorMessage();
			closesocket(GK_socket);
			return ;
		}
         router->clearAllAliasStates();// clear list
         refresh();	// get initial gk status
		 Logger::log("Connection established.");


		while (parseMessage());//-----> need debug this function
		

	}

}

//##ModelId=424BB64600A4
void GkClient::init(ACDX* _store, CString _host, int _port)
{
        router = _store;
		host = _host;
		port = _port;
}

/**
* Stop this thread.
*/
//##ModelId=424BB6460096
void GkClient::stop()
{
	stopped = TRUE;
	close();
}

/**
* close connection to GnuGk.
*/
//##ModelId=424BB6460095
void GkClient::close()
{
	//close net io socket
	if (GK_socket!=NULL) {
		closesocket(GK_socket);
	}

}

 /**
 * Split GnuGk events into files (separated by pipe char).
 * @param aString   string to split
 * @return          array of fields
 */
//##ModelId=424BB6460086
void GkClient::splitFields(CString aString,cstring_vec_t &splitFields)
{
	if (!splitFields.empty()) {
		splitFields.clear();// clear all element
	}
	
	int flag_number = aString.Find('|');
	if (flag_number==-1) {
		return ;
	}

	// parse gk info
    
     //	find '|'  split those string in a vector
	 //	no '|' work over return vector<CString>	
     //
	while (flag_number!=-1) {
		 CString needSection = aString.Left(flag_number);
		 aString = aString.Mid(flag_number+1);
		 flag_number = aString.Find('|');
		 splitFields.push_back(needSection);
		 // last element
		 if (flag_number == -1) {
			splitFields.push_back(aString);
			break;
		 }
		 needSection.FreeExtra();
	}

}

/**
 * Split GnuGk list of aliases (separated by equals char).
 * @param aString   string to split
 * @return          array of aliases
 */
//##ModelId=424BB6460077
void GkClient::splitAliases(CString aString,cstring_vec_t & splitFields )
{
	if (!splitFields.empty()) {
		splitFields.clear();// clear all element
	}
	
	int flag_number = aString.Find('=');
	if (flag_number==-1) {
		splitFields.push_back(aString);
		return ;
	}

	// parse alias string
    
     //	find '='  split those string in a vector
	 //	no '=' work over return vector<CString>	
     //
	while (flag_number!=-1) {
		 CString needSection = aString.Left(flag_number);
		 aString = aString.Mid(flag_number+1);
		 flag_number = aString.Find('=');
		 splitFields.push_back(needSection);
		 // last element
		 if (flag_number == -1) {
			splitFields.push_back(aString);
			break;
		 }
		 needSection.FreeExtra();
	}

}

//##ModelId=424BB6460076
void GkClient::refresh()
{
	getCurrentRegistrations();
	getCurrentCalls();
}

//##ModelId=424BB6460075
void GkClient::getCurrentRegistrations()
{
    sendGkCommand("PrintAllRegistrations");
}

//##ModelId=424BB6460068
void GkClient::getCurrentCalls()
{
	sendGkCommand("PrintCurrentCalls");
}

//##ModelId=424BB6460066
void GkClient::disconnectEndpoint(CString _epid)
{
	sendGkCommand("DisconnectEndpoint " + _epid);
}

//##ModelId=424BB6460057
void GkClient::disconnectAlias(CString _alias)
{
	sendGkCommand("DisconnectAlias " + H323Utils::extractAliasName(_alias));
}

//##ModelId=424BB6460055
void GkClient::unregisterAlias(CString _alias)
{
	sendGkCommand("UnregisterAlias " + H323Utils::extractAliasName(_alias));
}

//##ModelId=424BB6460048
void GkClient::makeCall(CString _epid, CString _destination)
{
	sendGkCommand("MakeCall " + _epid + " " + _destination);
}
    /**
     * Send TransferCall command to GnuGk.
     * @param _alias        alias to stay in call
     * @param _destination  new destination to transfer the call to
	 */
//##ModelId=424BB6460039
void GkClient::transferCall(CString _alias, CString _destination)
{
	sendGkCommand("TransferCall " + H323Utils::extractAliasName(_alias) + " " + H323Utils::extractAliasName(_destination));
}

 /**
     * send RouteToAlias response to GnuGk.
     * @param _alias        endpoint alias
     * @param callingEpId   endpoint ID of calling endpoint
     * @param callRef       call reference
     */
//##ModelId=424BB646002A
void GkClient::routeToAlias(CString _alias, CString callingEpId, CString callRef)
{
	sendGkCommand("RouteToAlias " + H323Utils::extractAliasName(_alias) + " " + callingEpId + " " + callRef);
}

//##ModelId=424BB6460027
void GkClient::routeReject(CString callingEpId, CString callRef)
{
	sendGkCommand("RouteReject " + callingEpId + " " + callRef);
}

/**
 helper function to send bytes to GnuGk.
 @param cmd            
        ACDX--->  GK
*/
//##ModelId=42198D180122
// open socket connect GK and send info to GK
//##ModelId=424BB64600E4
void GkClient::sendGkCommand(CString cmd)
{
	Logger::debug("ACD->GK:" + cmd);
	// ostream.write((cmd + "\r\n").getBytes());	
	// use socket send back info
	cmd = cmd + "\n";
	//cmd = "r\n";//test code
	LPTSTR m_buf_s = cmd.GetBuffer(cmd.GetLength());
	send(GK_socket,m_buf_s,cmd.GetLength(),0); // (char*)&m_buf is error
	cmd.ReleaseBuffer();
}

//##ModelId=424BB64600D2
void GkClient::printErrorMessage()
{
	LPTSTR lpMsgBuf;
	FormatMessage( 
		FORMAT_MESSAGE_ALLOCATE_BUFFER | 
		FORMAT_MESSAGE_FROM_SYSTEM | 
		FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		GetLastError(),
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
		(LPTSTR) &lpMsgBuf,
		0,
		NULL 
		);
	// Process any inserts in lpMsgBuf.
	// ...
	// Display the string.
	//printf("%S\n", (LPCTSTR)lpMsgBuf);
	CString msg(lpMsgBuf);
	Logger::debug(msg);
	// Free the buffer.
	LocalFree( lpMsgBuf );

}
/*
 *	read all gk 7000 port info and response it
 */
//##ModelId=424BB64600C4
BOOL GkClient::parseMessage()
{

	int r = recv(GK_socket, (char*)&m_buf, sizeof(m_buf), 0);
	if(r == 0){
		printErrorMessage();
		return FALSE;
	}
	if(r == SOCKET_ERROR){
		printErrorMessage();
		return FALSE;
	}
	
    CString recvString((char*)&m_buf);
	m_buf = NULL;// leon [3/30/2005]***** hi set this can let m_buf clear char

	//save '\r\n' don't use trim function at here


	if (recvString.Find(';') != -1) 
	{
		GKecho =  GKecho + recvString + "\r\n";
	}
	else
	{
		GKecho =  GKecho + recvString;
	}
	

	recvString = "";
	recvString.FreeExtra();


	//if receive over
	if (r<sizeof(m_buf)) {

			// here I found a bug of GK ,if u h323_ID have two char, and your have multiple
			// ip address , GK will send some error msg to socket, and client will can't 
			// parse it .  maybe need change client logic, e164 test ok.
			// not sure why the last char often in mem  I want use memset but not work
			//GKecho = GKecho.Left(flagPos); // no use
			
			//back a vector parse all ';' and make cmd logic
			cstring_vec_t semicolonlist;
			parseSemicolon(semicolonlist,GKecho);	// get all cmd and history cmd
			//GKecho = "";	
			// view echo ok ?
			if (GKecho.GetLength()>1) {
				Logger::debug(GKecho);
				GKecho = "";
			}
			// for readline command
			std::vector<CString>::iterator everyLine;
			CString cmd = "";
			for(everyLine = semicolonlist.begin();everyLine!=semicolonlist.end();everyLine++)
			{
				cmd = *everyLine;//every line command
				// clear \r\n char
				cmd.TrimLeft();
				cmd.TrimRight();
				cstring_vec_t vec_flag;
				splitFields(cmd,vec_flag);
				cmd = "";
				// flush view
				//find vector of command line info and get command type do logic
				if (vec_flag.empty()) {
					return TRUE;
				}
				std::vector<CString>::iterator vec_element;
				//vec_element = std::find (vec_flag.begin(), vec_flag.end(), "RCF"); 
				vec_element = vec_flag.begin();
				//RCF endpoint register confirm
				if ((CString)(*vec_element)== ("RCF")) {
					if (vec_flag.size()>=5) {
						 CString epid = vec_flag[4];
						 // extract _list_ of aliases and add all!
						 cstring_vec_t vec_alias;
						 splitAliases(vec_flag[2],vec_alias);

							for (int i=0; i < vec_alias.size(); i++) {
							   router->addAlias(vec_alias[i], epid);
							}					
					}
				}// Disengage Confirm
				else if ((CString)(*vec_element)== ("DCF")) {
					if (vec_flag.size()>=3) {
							CString epid = vec_flag[2];
							CString crv = vec_flag[3];     // identify by epid + CRV
							router->setAliasAvailable(epid, crv);
					}
				
				}
				//Unregistration Confirm
				else if ((CString)(*vec_element)== ("UCF")) {
					if (vec_flag.size()>=3) {
						CString epid = vec_flag[2];      // remove _all_ aliases for this epid
						router->removeAllAliases(epid);
					}
				}
				// answer confirm 
				else if ((CString)(*vec_element)== ("ACF")) {
					if (vec_flag.size()>=3) {
							CString crv = vec_flag[3];       // remember CRV for DCF
							cstring_vec_t vec_alias;
							splitAliases(vec_flag[4],vec_alias);// destinationInfo
							//String [] alias = splitAliases(msgField[4]);    

							for (int i=0; i < vec_alias.size(); i++) 
							{
								router->setAliasTalking(vec_alias[i], crv);
							}
							splitAliases(vec_flag[5],vec_alias);// srcInfo
							//alias = splitAliases(msgField[5]);    // srcInfo
							for (int j=0; j < vec_alias.size(); j++) 
							{
								router->setAliasTalking(vec_alias[j], crv);
							}

					}
				}
				// vqueue  route request
				else if ((CString)(*vec_element)== ("RouteRequest"))
				{
					if (vec_flag.size()>=6) {
						  CString callingEpId = vec_flag[2];
						  CString callref = vec_flag[3];
						  CString queue = vec_flag[4];
						  router->routeCall(queue, callingEpId, callref, vec_flag[5], vec_flag[1] );
					}			
				
				}

			}
		}

	return TRUE;
}
// read line
//##ModelId=424BB64600D3
void GkClient::parseSemicolon(cstring_vec_t &semicolonlist,CString gkEcho)
{
	semicolonlist.reserve(10);
	do {
		CString t = gkEcho.Left(gkEcho.Find("\r\n"));// find each line
		// have cmd
		if (gkEcho.Find('|') ==-1) {
			break;
		}
		//cut head have cmd
		if (t.Find('|') == -1) {
			gkEcho = gkEcho.Mid(gkEcho.Find("\r\n")+2);//next line
			continue;
		}
		// cut ';'
		if (t.Find(';') != -1 ) {
			t = t.Left(t.Find(';'));
		}
		// now parse line by '\r\n' with ras cmd
		semicolonlist.push_back(t);
		//printf(t+"\r\n");// next line
		gkEcho = gkEcho.Mid(gkEcho.Find("\r\n")+2);
	}while (gkEcho.Find("\r\n")!= -1);//if have line

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -