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

📄 callcontrol_a.c

📁 基于嵌入式Linux平台的网络电话设计原程序部分代码段。
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Blueinfosys.  All rights reserved.
//
// Module Name: CallControl.cpp
//
// Abstract:
//
// Author: 
// Date: Feb 12, 2004
// Ver:1.00
//
// Modified by:
// Modified Date:
// Notes:
////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include	<stdio.h>
#include	<stdarg.h>

#include	<sys/types.h> 
#include	<sys/stat.h> 
#include	<fcntl.h> 
#include	<sys/ioctl.h> 
#include	<errno.h>
#include	<time.h>
#include	<pthread.h>
#include	<string.h>
#include	<unistd.h>
#include	<stdlib.h>
#include	<signal.h>

#include	"commondef.h"

#include	"CallControl.h"

#include	"ccuatype.h"
#include	"queue.h"
#include	"WebSrv.h"
#include	"rtp.h"
#include	"sipmessage.h"
#include	"commtrace.h"

extern	int	iInitTapi();

extern int iQXget( P_QUEUE_X p_pqQueue, UCHAR *p_ucMsg );
extern int iQXInit( P_QUEUE_X p_pqQueue, UCHAR *p_ucMsg, DWORD *pdwClock, int iUnitLen, int iMaxNumMsg );
extern int iQXput( P_QUEUE_X p_pqQueue, UCHAR *p_ucMsg );

extern int iGetFxxType( int iChannel );
extern void vSignalTrace();

int			giAutoTalk = 0;

int			gmiLineType[MAX_LINE_NUM];

extern void vCloseDevices( void );
extern BOOL gblnShutdown;

BOOL	gblnvSignalTrace = FALSE;
BOOL	gblnvPlayandRecordManager = FALSE;
BOOL	gblnvThreadSignalProc = FALSE;
BOOL	gblnvThreadReadFromDriver = FALSE;
BOOL	gblnvThreadReadDataFromDriver = FALSE;
BOOL	gblnvInitCCProc = FALSE;

extern QUEUE_X		gqxQueueTrace;
extern BOOL			gblnPbxEnable;
extern BOOL			gblnLayer3Enable;

tCC_UA_MSG		gqQueueUaMsg[ MAX_UAMSG_SAVED ]; 
DWORD			gdwQueueUaMsg[ MAX_UAMSG_SAVED ];
QUEUE_X			gqxQueueUaMsg;

CCallControl	goCC;

extern void vThreadReadFromDriver( void );
extern void	vReceiveCCMesg( ptCC_UA_MSG ptCcUaMsg );
extern void vPlayandRecordManager( void );

void vThreadSignalProc( void )
{
	tCC_UA_MSG			tCcUaMsg;
	tTraceResultMessage	tTrace;

	gblnvThreadSignalProc = TRUE;
printf( "vThreadSignalProc is up\n" );
	while( gblnShutdown == FALSE ) {
		sem_wait( &( gqxQueueUaMsg.smSemaphore ) );

		if ( iQXget( &gqxQueueUaMsg, (BYTE *)&tCcUaMsg ) != 0 ) {
			continue;
		}

		if ( gblnPbxEnable ) {
			tTrace.eType = ePbxCommand;
			tCcUaMsg.hdr.dwDirection = 0;
			tCcUaMsg.hdr.dwStatus = goCC.eGetStatus( tCcUaMsg.hdr.dwChannel );
			tTrace.u.tCcUaMsg = tCcUaMsg;
			iQXput( &gqxQueueTrace, (UCHAR *)&tTrace );
		}

		if ( tCcUaMsg.hdr.eMsgType == eSetCodecType ) {
			goCC.vSetCodec( tCcUaMsg.hdr.dwChannel, &tCcUaMsg );
			continue;
		}

		if ( tCcUaMsg.hdr.eMsgType == eShutdownMsg ) {
			continue;
		}
		if ( tCcUaMsg.hdr.eMsgType != eTimer ) {
			goCC.vCallControl( tCcUaMsg.hdr.dwChannel, eMsgFromUa, (char *)&tCcUaMsg );
		} else {
			goCC.vCallControl( tCcUaMsg.hdr.dwChannel, eMsgFromTimer, (char *)&( tCcUaMsg.u.tTimerMsg ) );
		}
	}

	gblnvThreadSignalProc = FALSE;
printf( "vThreadSignalProc is down\n" );
}

void vInitCCProc()
{
	int			iRet;
	pthread_t	tMyThread;
	int			i;

	if ( iInitTapi() == -1 ) {
		return;
	}

	// To initialize data of CC
	goCC.vInitial();

	iRet = pthread_create( &tMyThread, NULL, (void*(*)(void*))vPlayandRecordManager, NULL );
	i = 0;
	while( ( gblnvPlayandRecordManager == FALSE ) && i < MAX_THREAD_WAIT_CIRCLE ) {
		i ++;
		usleep( MAX_THREAD_WAIT_TIME_PIECE );
	}
	if ( gblnvPlayandRecordManager == FALSE ) {
printf( "gblnvPlayandRecordManager\n" );
		return;
	}

	iRet = pthread_create( &tMyThread, NULL, (void*(*)(void*))vSignalTrace, NULL );
	i = 0;
	while( ( gblnvSignalTrace == FALSE ) && i < MAX_THREAD_WAIT_CIRCLE ) {
		i ++;
		usleep( MAX_THREAD_WAIT_TIME_PIECE );
	}
	if ( gblnvSignalTrace == FALSE ) {
printf( "gblnvSignalTrace\n" );
		return;
	}

	iRet = pthread_create( &tMyThread, NULL, (void*(*)(void*))vThreadSignalProc, NULL );
	i = 0;
	while( ( gblnvThreadSignalProc == FALSE ) && i < MAX_THREAD_WAIT_CIRCLE ) {
		i ++;
		usleep( MAX_THREAD_WAIT_TIME_PIECE );
	}
	if ( gblnvThreadSignalProc == FALSE ) {
printf( "gblnvThreadSignalProc\n" );
		return;
	}

	iRet = pthread_create( &tMyThread, NULL, (void*(*)(void*))vThreadReadFromDriver, NULL );
	i = 0;
	while( ( gblnvThreadReadFromDriver == FALSE ) && i < MAX_THREAD_WAIT_CIRCLE ) {
		i ++;
		usleep( MAX_THREAD_WAIT_TIME_PIECE );
	}
	if ( gblnvThreadReadFromDriver == FALSE ) {
printf( "gblnvThreadReadFromDriver\n" );
		return;
	}

	gblnvInitCCProc = TRUE;
}

CCallControl::CCallControl()
{
	sem_init( &m_smCallControl, 0, 1 );


	mdwTimeoutLength[eT301] = 8000;		// 8 seconds, waiting for response from controller
	mdwTimeoutLength[eT302] = 1500000;	// 8 seconds, querying status of trunk periodically
	mdwTimeoutLength[eT303] = 8000;		// 8 seconds, querying status of trunk periodically
	mdwTimeoutLength[eT304] = 8000;		// 8 seconds, querying status of trunk periodically
	mdwTimeoutLength[eT305] = 8000;		// 8 seconds, querying status of trunk periodically
	mdwTimeoutLength[eT306] = 8000;		// 8 seconds, querying status of trunk periodically
	mdwTimeoutLength[eT307] = 8000;		// 8 seconds, querying status of trunk periodically
	mdwTimeoutLength[eT308] = 8000;		// 8 seconds, querying status of trunk periodically
	mdwTimeoutLength[eT309] = 5000;		// 5 seconds, waiting for dtmf input after play over
	mdwTimeoutLength[eT310] = 8000;		// 8 seconds, waiting for dtmf codes following first code
	mdwTimeoutLength[eT311] = 32000;	// 32 seconds, waiting for response from SIP UA
	mdwTimeoutLength[eT312] = 60000;	// 60 seconds, waiting extension answer
	mdwTimeoutLength[eT313] = 8000;		// 8 seconds, waiting for response from controller
	mdwTimeoutLength[eT314] = 5000;		// 5 seconds, waiting for response from SIP UA
	mdwTimeoutLength[eT315] = 32000;	// 32 seconds, waiting for response from SIP UA ( waiting for connectack )
	mdwTimeoutLength[eT316] = 100;		// 6 seconds, waiting for callid message from controller
	mdwTimeoutLength[eT317] = 180000;	// 60 seconds, waiting for the calling success or fail

	mdwTimeoutLength[eT101] = 30000;	// 30 seconds, report state of trunk to CM

	//
	// init queues
	//
	if( iQXInit( 
			&gqxQueueUaMsg, 
			(UCHAR *)&gqQueueUaMsg[0], 
			gdwQueueUaMsg, 
			sizeof(tCC_UA_MSG), 
			MAX_UAMSG_SAVED
		) != 0 
	) {
		return;
	}

	memset( (char *)&m_tWebConfig, 0, sizeof(m_tWebConfig) );

	DWORD		dwTmp;

	memset( (char *)&m_tCallidStat, 0, sizeof(m_tCallidStat) );
	memset( (char *)m_mtReportStatus, 0xff, sizeof(m_mtReportStatus) );

	for( dwTmp = 0; dwTmp < MAX_LINE_NUM; dwTmp ++ ) {
		m_mdwReportSame[dwTmp] = 0;
		m_tWebConfig.trunk_out.trunk_out_item[dwTmp].trunk_tel_no = START_TRUNK_TEL_NO + dwTmp;
		m_tWebConfig.trunk_in.trunk_in_item[dwTmp].mode = AUTO_ATTENDANT;

		mtFxxAttrib[dwTmp].boolSessionOK = FALSE;
		mtFxxAttrib[dwTmp].tRtpHeader.dwVersion = 2;
		mtFxxAttrib[dwTmp].tVoiceHead.iSocket = -1;
	}
}

CCallControl::~CCallControl()
{
}

void CCallControl::vInitial()
{
	DWORD	dwTmp;

	memset( mtFxxAttrib, 0, sizeof(mtFxxAttrib) );

	for( dwTmp = 0; dwTmp < MAX_LINE_NUM; dwTmp ++ ) {
		mtFxxAttrib[dwTmp].tmProc = new CMyTimer( dwTmp );
		meChannelStatus[dwTmp] = eTrunkIdle;
		// Updating trunk status according to response from Controller.
//		vPutDriver( dwTmp, eLineStatusRequest, 0, 0 );
		vSetTimer( dwTmp, eT301, mdwTimeoutLength[eT301] + dwTmp * 1000 );
	}
}

// channel
// eType, type of timer
// dwTimelength, timeout of timer, in milisec
void CCallControl::vSetTimer( DWORD dwChannel, eChannelTimer eType, DWORD dwTimelength )
{
	if ( gblnPbxEnable ) {

		tTraceResultMessage	tTrace;

		tTrace.eType = ePbxCommand;
		tTrace.u.tCcUaMsg.hdr.eMsgType = eSetTimer;
		tTrace.u.tCcUaMsg.hdr.dwDirection = 1;
		tTrace.u.tCcUaMsg.hdr.dwChannel = dwChannel;
		tTrace.u.tCcUaMsg.hdr.dwStatus = goCC.eGetStatus( dwChannel );
		tTrace.u.tCcUaMsg.u.tTimerMsg.dwChannel = dwChannel;
		tTrace.u.tCcUaMsg.u.tTimerMsg.dwTimerType = eType;
		iQXput( &gqxQueueTrace, (UCHAR *)&tTrace );
	}
	
	dwTimelength *= 1000;

	if ( mtFxxAttrib[dwChannel].mdwTimeID[eType] != 0 ) {
		mtFxxAttrib[dwChannel].mdwTimeID[eType] = 
			uSetUFTimer( mtFxxAttrib[dwChannel].mdwTimeID[eType], dwTimelength, eType, mtFxxAttrib[dwChannel].tmProc );
	} else {
		mtFxxAttrib[dwChannel].mdwTimeID[eType] = 
			uSetUFTimer( 0, dwTimelength, eType, mtFxxAttrib[dwChannel].tmProc );
	}
}

void CCallControl::vKillAllTimer( DWORD dwChannel )
{
	DWORD	dwTmp;

	for( dwTmp = 0; dwTmp < MAX_TIMEOUT_TYPE; dwTmp ++ ) {
		if ( mtFxxAttrib[dwChannel].mdwTimeID[dwTmp] > 0 ) {
			KillUFTimer( mtFxxAttrib[dwChannel].mdwTimeID[dwTmp] );
			mtFxxAttrib[dwChannel].mdwTimeID[dwTmp] = 0;
		}
	}
}

void CCallControl::vKillTimer( DWORD dwChannel, eChannelTimer eType )
{
	if ( gblnPbxEnable ) {

		tTraceResultMessage	tTrace;

		tTrace.eType = ePbxCommand;
		tTrace.u.tCcUaMsg.hdr.eMsgType = eKillTimer;
		tTrace.u.tCcUaMsg.hdr.dwDirection = 1;
		tTrace.u.tCcUaMsg.hdr.dwChannel = dwChannel;
		tTrace.u.tCcUaMsg.hdr.dwStatus = goCC.eGetStatus( dwChannel );
		tTrace.u.tCcUaMsg.u.tTimerMsg.dwChannel = dwChannel;
		tTrace.u.tCcUaMsg.u.tTimerMsg.dwTimerType = eType;
		iQXput( &gqxQueueTrace, (UCHAR *)&tTrace );
	}

	if ( mtFxxAttrib[dwChannel].mdwTimeID[eType] > 0 ) {
		KillUFTimer( mtFxxAttrib[dwChannel].mdwTimeID[eType] );
		mtFxxAttrib[dwChannel].mdwTimeID[eType] = 0;
	}
}

DWORD CMyTimer::operator ()(const UTIMER_PP &tpp)
{
	tCC_UA_MSG		tCcUaMsg;

	tCcUaMsg.hdr.eMsgType = eTimer;
	tCcUaMsg.hdr.dwChannel = m_dwChannel;
	tCcUaMsg.hdr.length = sizeof(tCcUaMsg.hdr) + sizeof(tCcUaMsg.u.tTimerMsg);

	tCcUaMsg.u.tTimerMsg.dwChannel = m_dwChannel;
	tCcUaMsg.u.tTimerMsg.dwTimerType = tpp.uType;

	iQXput( &gqxQueueUaMsg, (UCHAR *)&tCcUaMsg );

	return 0;
}

void CCallControl::vCallControl( DWORD dwChannel, eFxxMsgType eMsgType, char *pchMsg )
{
	if ( dwChannel >= MAX_LINE_NUM ) {
		return;
	}

	sem_wait( &m_smCallControl );

	switch( meChannelStatus[dwChannel] ) {
	case eTrunkIdle:
//		vTrunkIdle( dwChannel, eMsgType, pchMsg );
		break;
	case eTrunkReady:
//		vTrunkReady( dwChannel, eMsgType, pchMsg );
		break;
	case eTrunkStartCall:
//		vTrunkStartCall( dwChannel, eMsgType, pchMsg );
		break;
	case eTrunkConnecting:
//		vTrunkConnecting( dwChannel, eMsgType, pchMsg );
		break;
	case eTrunkConnect:
//		vTrunkConnect( dwChannel, eMsgType, pchMsg );
		break;
	case eTrunkDisconnect:
//		vTrunkDisconnect( dwChannel, eMsgType, pchMsg );
		break;
	case eTrunkAnswer:
//		vTrunkAnswer( dwChannel, eMsgType, pchMsg );
		break;
	case eTrunkPlay:
//		vTrunkPlay( dwChannel, eMsgType, pchMsg );
		break;
	case eTrunkCalling:
//		vTrunkCalling( dwChannel, eMsgType, pchMsg );
		break;
	case eTrunkWaitConnect:
//		vTrunkWaitConnect( dwChannel, eMsgType, pchMsg );
		break;
	case eTrunkDisaCalling:
//		vTrunkDisaCalling( dwChannel, eMsgType, pchMsg );
		break;
	case eTrunkDisaAnswer:
//		vTrunkDisaAnswer( dwChannel, eMsgType, pchMsg );
		break;
	case eTrunkWaitCallid:
//		vTrunkWaitCallid( dwChannel, eMsgType, pchMsg );
		break;
	}

	sem_post( &m_smCallControl );
}

void CCallControl::vSendMsgToUA( ptCC_UA_MSG ptCcUaMsg )
{
	tTraceResultMessage	tTrace;

	if ( gblnPbxEnable && ptCcUaMsg->hdr.eMsgType != eAudioData ) {
		tTrace.eType = ePbxCommand;
		ptCcUaMsg->hdr.dwDirection = 1;
		ptCcUaMsg->hdr.dwStatus = goCC.eGetStatus( ptCcUaMsg->hdr.dwChannel );
		tTrace.u.tCcUaMsg = *ptCcUaMsg;
		iQXput( &gqxQueueTrace, (UCHAR *)&tTrace );
	}

	// call function of HEGS
printf( "vReceiveCCMesg\n" );
	vReceiveCCMesg( ptCcUaMsg );
}

void CCallControl::vChangeCCStatus( DWORD dwChannel, eCCStatus eStatus )
{
	tTraceResultMessage	tTrace;

//	char				chTmpPara[8];
	if ( dwChannel >= MAX_LINE_NUM ) {
		return;
	}

	if ( gblnPbxEnable || gblnLayer3Enable ) {
		tTrace.eType = eLayer3Status;
		tTrace.u.tLayer3.dwChannel = dwChannel;
		tTrace.u.tLayer3.eStatus = goCC.eGetStatus( dwChannel );;
		tTrace.u.tLayer3.eNewStatus = eStatus;
		iQXput( &gqxQueueTrace, (UCHAR *)&tTrace );
	}

	mtFxxAttrib[dwChannel].dwT303TimeoutCounter = 0;
	mtFxxAttrib[dwChannel].dwT304TimeoutCounter = 0;
	mtFxxAttrib[dwChannel].dwT305TimeoutCounter = 0;
	mtFxxAttrib[dwChannel].dwT306TimeoutCounter = 0;
	mtFxxAttrib[dwChannel].dwT307TimeoutCounter = 0;
	mtFxxAttrib[dwChannel].dwT308TimeoutCounter = 0;
	mtFxxAttrib[dwChannel].dwT309TimeoutCounter = 0;
	mtFxxAttrib[dwChannel].dwT313TimeoutCounter = 0;
	mtFxxAttrib[dwChannel].dwDtmfRecvCounter = 0;
	mtFxxAttrib[dwChannel].boolCallOriginateStart = FALSE;

	if ( eStatus == eTrunkReady || eStatus == eTrunkIdle ) {
		mtFxxAttrib[dwChannel].iDtmfQueueLength = 0;
		mtFxxAttrib[dwChannel].boolSendDtmfEnable = FALSE;
		mtFxxAttrib[dwChannel].boolStageTwo = FALSE;
		memset( mtFxxAttrib[dwChannel].mchLastSendDtmf, 0, sizeof(mtFxxAttrib[dwChannel].mchLastSendDtmf) );
		mtFxxAttrib[dwChannel].iLastDtmfMsglen = 0;
	}

	if ( eStatus == eTrunkConnect ) {
		mtFxxAttrib[dwChannel].boolSendDtmfEnable = TRUE;
		vSetTimer( dwChannel, eT317, mdwTimeoutLength[eT317] );
	}

	if ( eStatus == eTrunkReady ) {
		mtFxxAttrib[dwChannel].eFxoCallType = eFxoCallin;
	}

	meChannelStatus[dwChannel] = eStatus;

	if ( eStatus == eTrunkConnect || eStatus == eTrunkPlay ) {
		vPutDriver( dwChannel, eACTION_TALK, 0, 0 );
	} else {
		vPutDriver( dwChannel, eACTION_TALK_DENY, 0, 0 );
	}

	vReportCCStatus( dwChannel );
}

void CCallControl::vReportCCStatus( DWORD dwChannel )
{
	tCC_UA_MSG	tCcUaMsg;

	if ( dwChannel >= MAX_LINE_NUM ) {
		return;
	}

	tCcUaMsg.hdr.eMsgType = eReportStatus;
	tCcUaMsg.hdr.dwCcIdx = 0;
	tCcUaMsg.hdr.dwUaIdx = 0;
	tCcUaMsg.hdr.dwChannel = dwChannel;
	tCcUaMsg.hdr.length = sizeof(tCcUaMsg.hdr) + sizeof(tCcUaMsg.u.tReport);

	tCcUaMsg.u.tReport.dwLineType = gmiLineType[dwChannel];
	tCcUaMsg.u.tReport.dwChannel = m_tWebConfig.trunk_out.trunk_out_item[dwChannel].trunk_tel_no;

⌨️ 快捷键说明

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