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

📄 fxocallsetup.c

📁 基于嵌入式Linux平台的网络电话外部交换局呼叫设置功能部分代码段。
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Blueinfosys.  All rights reserved.
//
// Module Name: Fxowaitconnect.cpp
//
// Abstract:
//
// Author: Yang Xin
// Date: Feb 13, 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	"ccuatype.h"
#include	"queue.h"
#include	"WebSrv.h"
#include	"rtp.h"
#include	"sipmessage.h"
#include	"commtrace.h"
#include	"CallControl.h"

void CCallControl::vFxowaitconnect( DWORD dwChannel, eFxxMsgType eMsgType, char *pchMsg )
{
	tCC_UA_MSG			tCcUaMsg;
	DWORD				dwIdx;
	char				*ptr;

	ptCC_UA_MSG			ptMsgReq;
	ptFXEVENTMESSAGE	ptEvent;
	ptMyTimerMsg		ptTimer;
	ptFxxAttrib			ptAttrib = &mtFxxAttrib[dwChannel];

	ptMsgReq = (ptCC_UA_MSG)pchMsg;
	ptEvent = (ptFXEVENTMESSAGE)pchMsg;
	ptTimer = (ptMyTimerMsg)pchMsg;

	switch( eMsgType ) {
	case eMsgFromUa:
		switch( ptMsgReq->hdr.eMsgType ) {
		case eSetup:
			COMMFUNC_V( dwChannel, &tCcUaMsg, ptMsgReq );
			break;
		case eAlerting:
			dwIdx = eFirstcall;
			ptAttrib->mtCallInfo[dwIdx].dwUaIdx = ptMsgReq->hdr.dwUaIdx;
			ptAttrib->mtCallInfo[dwIdx].tSetup.dwCallee = ptMsgReq->u.tAlert.dwCallee;

			if ( ptAttrib->mtCallInfo[dwIdx].tSetup.cDispName[0] &&
				ptAttrib->mtCallInfo[dwIdx].tSetup.cDispName[1] ) {
				memset( (char *)&tCcUaMsg, 0, sizeof(tCcUaMsg) );
				tCcUaMsg.hdr.eMsgType = eCallid;
				tCcUaMsg.hdr.length = sizeof( tCcUaMsg.hdr ) + sizeof( tCcUaMsg.u.tCallid );
				tCcUaMsg.hdr.dwChannel = dwChannel;

				memcpy( tCcUaMsg.u.tCallid.cDispName, ptAttrib->mtCallInfo[dwIdx].tSetup.cDispName, MAX_TELNO_LEN * 2 );
				if ( ptAttrib->mtCallInfo[dwIdx].tSetup.dwCallee == m_tModuleInfo.port.dwTelno[dwChannel] ) {
					tCcUaMsg.u.tCallid.iDestNumber = ptAttrib->mtCallInfo[dwIdx].tSetup.dwCaller;
				} else {
					tCcUaMsg.u.tCallid.iDestNumber = ptAttrib->mtCallInfo[dwIdx].tSetup.dwCallee;
				}
				tCcUaMsg.u.tCallid.dwSrcNumber = m_tModuleInfo.port.dwTelno[dwChannel];
				tCcUaMsg.hdr.dwCcIdx = dwIdx;
				tCcUaMsg.hdr.dwUaIdx = ptAttrib->mtCallInfo[dwIdx].dwUaIdx;
				vSendMsgToUA( &tCcUaMsg );
			}

			if ( ptAttrib->mtCallInfo[dwIdx].dwDirectCall == 1 ) {
				vSetTimer( dwChannel, eT207, mdwTimeoutLength[eT207] );
				break;
			}
			if ( ptMsgReq->u.tAlert.dwLineType == 2
				&& m_tModuleInfo.port.dwDirectTel[dwChannel] == 0 ) {
				ptAttrib->mtCallInfo[dwIdx].boolFxoCall = TRUE;
			}

			vSetTimer( dwChannel, eT207, mdwTimeoutLength[eT207] );
			break;
		case eConnect:
			vKillTimer( dwChannel, eT207 );

			dwIdx = eFirstcall;
printf( "003KKKKKKKKKKKKKKKKKKKKKKK, %d\n", ptMsgReq->u.tConnect.dwLineType );
			if ( ptMsgReq->u.tConnect.dwLineType == 2
				&& m_tModuleInfo.port.dwDirectTel[dwChannel] == 0 ) {
				ptAttrib->mtCallInfo[dwIdx].boolFxoCall = TRUE;
				vKillAllTimer( dwChannel );

				vReportBill( dwChannel, eBillEnd );
				ptAttrib->dwBillSn = 0;
				ptAttrib->eActiveCall = eFirstcall;
				RELEASECOMP( dwChannel, &tCcUaMsg, eRls_OnHook );

				ptAttrib->mtCallInfo[dwIdx].dwDirectCall = 0;
				ptAttrib->mtCallInfo[eFirstcall].tSetup.cDispName[0] = 0;
				ptAttrib->mchCallidNumber[0] = 0;
				ptAttrib->dwDtmfCallidCounter = 0;
				vPutDriver( dwChannel, eACTION_FXO_ONHOOK, NULL, 0 );
				vPutDriver( dwChannel, eACTION_IDLE, NULL, 0 );
				vSetTimer( dwChannel, eT114, mdwTimeoutLength[eT114] );
				vChangeCCStatus( dwChannel, eFxo_end );
				break;
			}
			memset( (char *)&tCcUaMsg, 0, sizeof(tCcUaMsg) );
			tCcUaMsg.hdr.eMsgType = eConnectAck;
			tCcUaMsg.hdr.length = sizeof( tCcUaMsg.hdr ) + sizeof( tCcUaMsg.u.tConnectAck );
			tCcUaMsg.hdr.dwChannel = dwChannel;
			tCcUaMsg.u.tConnectAck.dwCaller = ptMsgReq->u.tConnect.dwCaller;
			tCcUaMsg.u.tConnectAck.dwCallee = ptMsgReq->u.tConnect.dwCallee;

			tCcUaMsg.hdr.dwCcIdx = dwIdx;
			tCcUaMsg.hdr.dwUaIdx = ptMsgReq->hdr.dwUaIdx;

			ptAttrib->mtCallInfo[dwIdx].tSetup.dwCallee = ptMsgReq->u.tConnect.dwCallee;
			ptAttrib->mtCallInfo[dwIdx].dwUaIdx = ptMsgReq->hdr.dwUaIdx;

			vSendMsgToUA( &tCcUaMsg );

			if ( ptAttrib->mtCallInfo[dwIdx].dwDirectCall == 1 ) {
				vReportBill( dwChannel, eBillStart );
				vPutDriver( dwChannel, eACTION_FXO_OFFHOOK, NULL, 0 );
				ptAttrib->mtCallInfo[dwIdx].dwDirectCall = 0;
			} else {
				vPutDriver( dwChannel, eACTION_FXS_RINGBACK_OFF, NULL, 0 );
			}
			vSetTimer( dwChannel, eT116, mdwTimeoutLength[eT116] );
#ifdef	FXO_CONTROL
			vSetTimer( dwChannel, eT119, mdwTimeoutLength[eT119] );
#endif
			ptAttrib->dwFxoStatusEnquiryCounter = 0;
			vChangeCCStatus( dwChannel, eFxo_talking );
			break;
		case eRtpSessionOK:
			dwIdx = eFirstcall;
			ptAttrib->mtCallInfo[dwIdx].boolDtmfTransferReady = TRUE;
			break;
		case eReleaseComplete:
			vKillTimer( dwChannel, eT207 );

			dwIdx = eFirstcall;
			if ( blnCOMMFUNC_FXO_ACD( dwChannel, &tCcUaMsg, ptMsgReq, dwIdx ) == TRUE ) {
				break;
			}

			if ( ptAttrib->mtCallInfo[dwIdx].dwDirectCall == 1 ) {
				vSetTimer( dwChannel, eT112, mdwTimeoutLength[eT112] );
				vChangeCCStatus( dwChannel, eFxo_idle );
				break;
			}
			if ( ptAttrib->mtCallInfo[eFirstcall].tSetup.dwCallee ==
				ptAttrib->dwAgentNumber &&
				ptAttrib->boolAutoAgentService == FALSE ) {
				// 不使用电脑自动应答、人工值班台无人应答则挂机
				vPutDriver( dwChannel, eACTION_FXO_ONHOOK, NULL, 0 );
				vSetTimer( dwChannel, eT114, mdwTimeoutLength[eT114] );
				vChangeCCStatus( dwChannel, eFxo_end );
				break;
			}
			vPutDriver( dwChannel, eACTION_FXS_RINGBACK_OFF, NULL, 0 );
			switch( ptMsgReq->u.tRlscmplt.eReason ) {
			case eRls_Busy:
				vPlayVoiceFile( dwChannel, eBusyWelcome );
				break;
			case eRls_NoAnswer:
			case eRls_AcdTimeout:
				vPlayVoiceFile( dwChannel, eNoAnsWelcome );
				break;
			case eRls_Disable:
				vPlayVoiceFile( dwChannel, eDisable );
				break;
			default:
				vPlayVoiceFile( dwChannel, eWelcome );
				break;
			}
			if ( ptAttrib->boolAutoAgentService == TRUE ) {
				ptAttrib->dwPlayMode = 3;
			} else {
				if ( ptAttrib->mtCallInfo[eFirstcall].tSetup.dwCallee ==
					ptAttrib->dwAgentNumber ) {
					ptAttrib->dwPlayMode = 8;
				} else {
					ptAttrib->dwPlayMode = 7;
				}
			}
			vChangeCCStatus( dwChannel, eFxo_play );
			break;
		default:
			break;
		}
		break;
	case eMsgFromDriver:
		printf("fxocallsetup,%d\n",ptEvent->dwEventType);
		switch( ptEvent->dwEventType ) {
		case eEVENT_FXO_RING_ON:
			vSetTimer( dwChannel, eT113, mdwTimeoutLength[eT113] );
			if ( ptAttrib->dwDtmfCallidCounter ) {
				ptAttrib->mchDtmfCallid[ptAttrib->dwDtmfCallidCounter] = 0;
				if ( !ptAttrib->mchCallidNumber[0] ) {
					memcpy( ptAttrib->mchCallidNumber, ptAttrib->mchDtmfCallid, MAX_TELNO_LEN );
					dwIdx = eFirstcall;
					strcpy( ptAttrib->mtCallInfo[dwIdx].tSetup.cDispName, ptAttrib->mchDtmfCallid );

					if ( m_tModuleInfo.port.dwDirectTel[dwChannel] ) {
						// 直通呼叫
						ptAttrib->mtCallInfo[0].dwDirectCall = 1;
						memset( (char *)&tCcUaMsg, 0, sizeof(tCcUaMsg) );
						tCcUaMsg.hdr.eMsgType = eCallid;
						tCcUaMsg.hdr.length = sizeof( tCcUaMsg.hdr ) + sizeof( tCcUaMsg.u.tCallid );
						tCcUaMsg.hdr.dwChannel = dwChannel;

						memcpy( tCcUaMsg.u.tCallid.cDispName, ptAttrib->mtCallInfo[dwIdx].tSetup.cDispName, MAX_TELNO_LEN * 2 );
						dwIdx = eFirstcall;
						if ( ptAttrib->mtCallInfo[dwIdx].tSetup.dwCallee == m_tModuleInfo.port.dwTelno[dwChannel] ) {
							tCcUaMsg.u.tCallid.iDestNumber = ptAttrib->mtCallInfo[dwIdx].tSetup.dwCaller;
						} else {
							tCcUaMsg.u.tCallid.iDestNumber = ptAttrib->mtCallInfo[dwIdx].tSetup.dwCallee;
						}
						tCcUaMsg.u.tCallid.dwSrcNumber = m_tModuleInfo.port.dwTelno[dwChannel];
						tCcUaMsg.hdr.dwCcIdx = dwIdx;
						tCcUaMsg.hdr.dwUaIdx = ptAttrib->mtCallInfo[dwIdx].dwUaIdx;
						vSendMsgToUA( &tCcUaMsg );
						break;
					}
				}
				ptAttrib->dwDtmfCallidCounter = 0;
			}
			break;
		case eEVENT_BUSY_TONE:
			vKillTimer( dwChannel, eT207 );

			ptAttrib->eActiveCall = eFirstcall;
			RELEASECOMP( dwChannel, &tCcUaMsg, eRls_OnHook );

			vPutDriver( dwChannel, eACTION_FXS_RINGBACK_OFF, NULL, 0 );
			vPutDriver( dwChannel, eACTION_FXO_ONHOOK, NULL, 0 );
			vSetTimer( dwChannel, eT114, mdwTimeoutLength[eT114] );
			vChangeCCStatus( dwChannel, eFxo_end );
			break;
		case eEVENT_DTMF_CODE:
			if ( m_tModuleInfo.port.dwDirectTel[dwChannel] ) {
				if ( ptEvent->chBuffer[0] >= 0 && ptEvent->chBuffer[0] <= 9 ) {
					ptAttrib->mchDtmfCallid[ptAttrib->dwDtmfCallidCounter] = ptEvent->chBuffer[0] + '0';
					ptAttrib->dwDtmfCallidCounter ++;
				}
				break;
			}

			dwIdx = eFirstcall;
			ptr = ptAttrib->mtCallInfo[dwIdx].mchCallNumber;
			ptr[ptAttrib->mtCallInfo[dwIdx].dwCallNumber++] = ptEvent->chBuffer[0];
			if ( ptAttrib->mtCallInfo[dwIdx].dwCallNumber >= MAX_DTMF_SAVED ) {
				ptAttrib->mtCallInfo[dwIdx].dwCallNumber = MAX_DTMF_SAVED - 1;
			}
//			ptAttrib->mtCallInfo[dwIdx].dwCallNumber %= MAX_DTMF_SAVED;
//			if ( ptAttrib->dwInputFxsNumber ) {		// 汇接
//				if ( ( ptr[0] == 0 && ptAttrib->dwInputFxsGrade < INLAND_REMOTE_CALL ) 
//					|| ( ptr[0] == 0 && ptr[1] == 0 && ptAttrib->dwInputFxsGrade < OVERSEAS_CALL
//					&& ptAttrib->mtCallInfo[dwIdx].dwCallNumber > 1 ) ) {
					// 长途呼叫必须要有长途权限
					// no authorization to start a remote call
//					vKillTimer( dwChannel, eT207 );

//					ptAttrib->eActiveCall = eFirstcall;
//					RELEASECOMP( dwChannel, &tCcUaMsg, eRls_OnHook );

//					COMMFUNC_X( dwChannel );

//					break;
//				}
//			}

			memset( (char *)&tCcUaMsg, 0, sizeof(tCcUaMsg) );
			tCcUaMsg.hdr.eMsgType = eDtmfCode;
			tCcUaMsg.hdr.length = sizeof( tCcUaMsg.hdr ) + sizeof( tCcUaMsg.u.tDtmfCode );
			tCcUaMsg.hdr.dwChannel = dwChannel;

			tCcUaMsg.u.tDtmfCode.dwDtmfValue = ptEvent->chBuffer[dwIdx];
//			tCcUaMsg.u.tDtmfCode.dwSrcNumber  = m_tModuleInfo.port.iTelno[dwChannel];
//			if ( ptAttrib->mtCallInfo[dwIdx].tSetup.dwCallee == tCcUaMsg.u.tDtmfCode.dwSrcNumber ) {
//				tCcUaMsg.u.tDtmfCode.dwDestNumber = ptAttrib->mtCallInfo[dwIdx].tSetup.dwCaller;
//			} else {
//				tCcUaMsg.u.tDtmfCode.dwDestNumber = ptAttrib->mtCallInfo[dwIdx].tSetup.dwCallee;
//			}
			tCcUaMsg.hdr.dwCcIdx = dwIdx;
			tCcUaMsg.hdr.dwUaIdx = ptAttrib->mtCallInfo[dwIdx].dwUaIdx;
			vSendMsgToUA( &tCcUaMsg );
			break;
		case eEVENT_FXO_CALLID_RCV:
			printf("fxocallsetup recv callid:%s\n",ptEvent->chBuffer+8);
			dwIdx = eFirstcall;
			memset( (char *)&tCcUaMsg, 0, sizeof(tCcUaMsg) );
			tCcUaMsg.hdr.eMsgType = eCallid;
			tCcUaMsg.hdr.length = sizeof( tCcUaMsg.hdr ) + sizeof( tCcUaMsg.u.tCallid );
			tCcUaMsg.hdr.dwChannel = dwChannel;

			tCcUaMsg.u.tCallid.cDispName[0] = '9';
			memcpy( tCcUaMsg.u.tCallid.cDispName, ptEvent->chBuffer + 8, MAX_TELNO_LEN * 2 - 1 );
			strcpy( (char *)( ptAttrib->mtCallInfo[dwIdx].tSetup.cDispName ), (char *)( ptEvent->chBuffer + 8 ) );
			if ( ptAttrib->mtCallInfo[dwIdx].tSetup.dwCallee == m_tModuleInfo.port.dwTelno[dwChannel] ) {
				tCcUaMsg.u.tCallid.iDestNumber = ptAttrib->mtCallInfo[dwIdx].tSetup.dwCaller;
			} else {
				tCcUaMsg.u.tCallid.iDestNumber = ptAttrib->mtCallInfo[dwIdx].tSetup.dwCallee;
			}
			tCcUaMsg.u.tCallid.dwSrcNumber = m_tModuleInfo.port.dwTelno[dwChannel];
			tCcUaMsg.hdr.dwCcIdx = dwIdx;
			tCcUaMsg.hdr.dwUaIdx = ptAttrib->mtCallInfo[dwIdx].dwUaIdx;
			vSendMsgToUA( &tCcUaMsg );
			break;
		default:
			break;
		}
		break;
	case eMsgFromTimer:
		switch( ptTimer->dwTimerType ) {
		case eT207:
			dwIdx = eFirstcall;
			if ( ptAttrib->mtCallInfo[dwIdx].dwDirectCall == 1 ) {
				vSetTimer( dwChannel, eT112, mdwTimeoutLength[eT112] );
				vChangeCCStatus( dwChannel, eFxo_idle );
				break;
			}
			vPutDriver( dwChannel, eACTION_FXS_RINGBACK_OFF, NULL, 0 );
			vPlayVoiceFile( dwChannel, eNoAnsWelcome );
			ptAttrib->dwPlayMode = 3;
			vChangeCCStatus( dwChannel, eFxo_play );
			break;
		case eT113:
			vKillAllTimer( dwChannel );

//			if ( ptAttrib->dwBillSn ) {
				vReportBill( dwChannel, eBillEnd );
				ptAttrib->dwBillSn = 0;
//			}

			ptAttrib->eActiveCall = eFirstcall;
			RELEASECOMP( dwChannel, &tCcUaMsg, eRls_OnHook );

			ptAttrib->mtCallInfo[dwIdx].dwDirectCall = 0;
			ptAttrib->mtCallInfo[eFirstcall].tSetup.cDispName[0] = 0;
			ptAttrib->mchCallidNumber[0] = 0;
			ptAttrib->dwDtmfCallidCounter = 0;
			vPutDriver( dwChannel, eACTION_IDLE, NULL, 0 );
			vChangeCCStatus( dwChannel, eFxo_idle );
			break;
		default:
			break;
		}
		break;
	default:
		break;
	}
}

void CCallControl::vFxoconnecting( DWORD dwChannel, eFxxMsgType eMsgType, char *pchMsg )
{
	tCC_UA_MSG			tCcUaMsg;
	DWORD				dwIdx;
	char				*ptr;
	char				chBuffer[MAX_TELNO_LEN * 4];

	ptCC_UA_MSG			ptMsgReq;
	ptFXEVENTMESSAGE	ptEvent;
	ptMyTimerMsg		ptTimer;
	ptFxxAttrib			ptAttrib = &mtFxxAttrib[dwChannel];

	ptMsgReq = (ptCC_UA_MSG)pchMsg;
	ptEvent = (ptFXEVENTMESSAGE)pchMsg;
	ptTimer = (ptMyTimerMsg)pchMsg;

	switch( eMsgType ) {
	case eMsgFromUa:
		switch( ptMsgReq->hdr.eMsgType ) {
		case eSetup:
			if ( ptMsgReq->u.tSetup.boolTransfer == TRUE ) {
				// receive a call transfered
				// send alerting to UA
				// save call information
				vKillTimer( dwChannel, eT117 );
				dwIdx = eFirstcall;
				ptAttrib->mtCallInfo[dwIdx].tSetup = ptMsgReq->u.tSetup;
				sprintf( chBuffer, "%ld%s",
					ptMsgReq->u.tSetup.dwTransferNumber, ptMsgReq->u.tSetup.cDispName );
				chBuffer[MAX_TELNO_LEN * 2 - 1] = 0;
				strcpy( ptAttrib->mtCallInfo[dwIdx].tSetup.cDispName, chBuffer );
			
				// save serial number of UA
				ptAttrib->mtCallInfo[dwIdx].dwUaIdx = ptMsgReq->hdr.dwUaIdx;

				memset( (char *)&tCcUaMsg, 0, sizeof(tCcUaMsg) );
				tCcUaMsg.hdr.eMsgType = eConnect;
				tCcUaMsg.hdr.length = sizeof( tCcUaMsg.hdr ) + sizeof( tCcUaMsg.u.tConnect );
				tCcUaMsg.hdr.dwChannel = dwChannel;

				tCcUaMsg.u.tConnect.dwCallee = ptMsgReq->u.tSetup.dwCallee;
				tCcUaMsg.u.tConnect.dwCaller = ptMsgReq->u.tSetup.dwCaller;
				tCcUaMsg.u.tConnect.dwLineType = 2;

				tCcUaMsg.hdr.dwCcIdx = dwIdx;
				tCcUaMsg.hdr.dwUaIdx = ptMsgReq->hdr.dwUaIdx;

				vSendMsgToUA( &tCcUaMsg );

				break;
			}
			COMMFUNC_V( dwChannel, &tCcUaMsg, ptMsgReq );
			break;
		case eReleaseComplete:
			if ( ptMsgReq->u.tRlscmplt.eReason == eRls_Transfer ) {
				// 呼叫转移产生的RleaseComplete消息
				vSetTimer( dwChannel, eT117, mdwTimeoutLength[eT117] );
				break;
			}
			vKillTimer( dwChannel, eT208 );
			

⌨️ 快捷键说明

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