📄 gkclient.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 + -