| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- #include "StdAfx.h"
- #include "IpmChannel.h"
- #include "Config.h"
- #include "MC.h"
- #include "VoipChannel.h"
- CIpmChannel::CIpmChannel(DEV_RES_CH_TYPE ChannelNo, DEV_RES_NO_TYPE NodeNo, DEV_RES_NO_TYPE BoardNo)
- : CChannelResource(DEV_RES_TYPE_IPM, NodeNo, BoardNo, DEVICE_RES_NO_ANY, ChannelNo),
- m_pVoipChanBind(NULL), m_StartFlag(false), m_FaxFlag(false)
- {
- }
- CIpmChannel::~CIpmChannel(void)
- {
- }
- /*****************************************************************
- **【函数名称】 __onAnswer
- **【函数功能】 应答检测处理
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIpmChannel::__onAnswer( METAEVENT* pMetaEvent )
- {
- if(ISX_sr_getevtlen() > 1)
- {
- /*获取RTP流中携带的远端IP和端口*/
- IPMEV_ANSWER_INFO *pAnswerInfo = (IPMEV_ANSWER_INFO *)ISX_sr_getevtdatap();
- ASSERT(pAnswerInfo != NULL);
- if(pAnswerInfo != NULL)
- {
- /*确认远端IP和端口有变化,需要重新启动媒体协商*/
- if(strcmp(m_XoipCfg.DstIpAddr.IpAddr, pAnswerInfo->RemoteIpAddr) != 0 || m_XoipCfg.DstRtpPort.UdpPort != pAnswerInfo->RemoteUdpPort)
- {
- lstrcpy(m_XoipCfg.DstIpAddr.IpAddr, pAnswerInfo->RemoteIpAddr);
- m_XoipCfg.DstRtpPort.UdpPort = pAnswerInfo->RemoteUdpPort;
- ISX_ipm_SetParm(m_Handle, &m_XoipCfg, EV_ASYNC);
- }
- if(pAnswerInfo->ucEvtType == 0)
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{IPMCh}: 通道[%d-%d-%d]语音停止, Remote[addr = %s, port = %u]"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_XoipCfg.DstIpAddr.IpAddr, m_XoipCfg.DstRtpPort.UdpPort);
- else
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{IPMCh}: 通道[%d-%d-%d]语音开始, Remote[addr = %s, port = %u]"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_XoipCfg.DstIpAddr.IpAddr, m_XoipCfg.DstRtpPort.UdpPort);
- }
- }
- else
- {
- UCHAR AnswerFlag = *(UCHAR*)ISX_sr_getevtdatap();
- if(AnswerFlag == 0)
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{IPMCh}: 通道[%d-%d-%d]语音停止, Remote[addr = %s, port = %u]"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_XoipCfg.DstIpAddr.IpAddr, m_XoipCfg.DstRtpPort.UdpPort);
- else
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{IPMCh}: 通道[%d-%d-%d]语音开始, Remote[addr = %s, port = %u]"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_XoipCfg.DstIpAddr.IpAddr, m_XoipCfg.DstRtpPort.UdpPort);
- }
- }
- /*****************************************************************
- **【函数名称】 __onSetParam
- **【函数功能】 传输参数设置的响应
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIpmChannel::__onSetParam( METAEVENT* pMetaEvent )
- {
- ISX_ipm_SwitchVF(m_Handle, IPM_SWITCH_FAX2VOICE, EV_ASYNC);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{IPMCh}: 通道[%d-%d-%d]远端地址更改响应, Remote[addr = %s, port = %u]"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_XoipCfg.DstIpAddr.IpAddr, m_XoipCfg.DstRtpPort.UdpPort);
- }
- /*****************************************************************
- **【函数名称】 __onFax
- **【函数功能】 传真启动处理
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIpmChannel::__onFax( METAEVENT* pMetaEvent )
- {
- UCHAR FaxMark = *( UCHAR *)ISX_sr_getevtdatap();
- // FaxMark = 0表示传真启动
- if(FaxMark == 0 && !m_FaxFlag)
- {
- if(m_pVoipChanBind != NULL)
- m_pVoipChanBind->reinvite4T38();
- }
- }
- /*****************************************************************
- **【函数名称】 open
- **【函数功能】 打开系统资源
- **【参数】
- **【返回值】 成功true,失败false
- ****************************************************************/
- bool CIpmChannel::open( void )
- {
- ASSERT(m_Handle == DEV_HANDLE_INVALID);
- m_Handle = ISX_ipm_Open(m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, this);
- if (m_Handle <= -1)
- {
- m_Handle = DEV_HANDLE_INVALID;
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{IPMCh}: 通道[%d-%d-%d]打开失败"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return false;
- }
-
- eIPM_EVENT EnableEvt[] = {EVT_RFC2833, EVT_ENERGY_DETECTOR, EVT_ANSWER_DETECTOR, EVT_FAX, EVT_RTP_TIMEOUT};
- ISX_ipm_EnableEvents(m_Handle, EnableEvt, 5, EV_SYNC, 0);
- ISX_ipm_ReceiveDigits(m_Handle, NULL, EV_SYNC);
- //LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{IPMCh}: 通道[%d-%d-%d]打开成功"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return true;
- }
- /*****************************************************************
- **【函数名称】 close
- **【函数功能】 关闭系统资源
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIpmChannel::close( void )
- {
- if(m_Handle != DEV_HANDLE_INVALID)
- {
- ISX_ipm_Close(m_Handle);
- m_Handle = DEV_HANDLE_INVALID;
- //LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{IPMCh}: 通道[%d-%d-%d]关闭"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- }
- }
- /*****************************************************************
- **【函数名称】 startMedia
- **【函数功能】 启动通道媒体流
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CIpmChannel::startMedia( void )
- {
- if(m_StartFlag)
- return false;
- ASSERT(m_pVoipChanBind != NULL);
- ISX_ipm_Set2Default(&m_XoipCfg);
- m_SrcAddr.IpAddr.Valid = 1;
- mediaAddrBoard(m_SrcAddr.IpAddr.IpAddr);
- m_SrcAddr.RtpPort.Valid = 1;
- m_SrcAddr.RtpPort.UdpPort = mediaPort();
- m_XoipCfg.VoiceCfg.SrcRTCPPort.Valid = 0 ;
- m_XoipCfg.VoiceCfg.SrcRTCPPort.UdpPort = 0;
- m_XoipCfg.DstIpAddr.Valid = 1;
- lstrcpy(m_XoipCfg.DstIpAddr.IpAddr, m_pVoipChanBind->getPeerConnectAddr());
- m_XoipCfg.DstRtpPort.Valid = 1;
- m_XoipCfg.DstRtpPort.UdpPort = m_pVoipChanBind->getPeerMediaPort();
- m_XoipCfg.VoiceCfg.DstRTCPPort.Valid = 0 ;
- m_XoipCfg.VoiceCfg.DstRTCPPort.UdpPort = 0;
- m_XoipCfg.FaxCfg.SrcT38Port.Valid = 0;
- m_XoipCfg.FaxCfg.SrcT38Port.UdpPort = 0;
- m_XoipCfg.FaxCfg.DstT38Port.Valid = 0;
- m_XoipCfg.FaxCfg.DstT38Port.UdpPort = 0;
- m_XoipCfg.VoiceCfg.PayloadType.Valid = 1;
- m_XoipCfg.VoiceCfg.PayloadType.PaylaodType = m_pVoipChanBind->getPeerCodecId();
- m_XoipCfg.DtmfCfg.DigitRelay.Valid = 1;
- m_XoipCfg.DtmfCfg.DigitRelay.DigitRelayMode = DRM_ERASE_AND_RELAY_RFC2833;
- m_XoipCfg.DtmfCfg.DynamicPayload.Valid = 0;
- m_XoipCfg.VoiceCfg.EchoCancel.Valid = 1;
- m_XoipCfg.VoiceCfg.EchoCancel.EchoCancel = 1;
- m_XoipCfg.VoiceCfg.EchoCancel.EchoCancellerLength = ECLength128MSec;
- if(ISX_ipm_StartMedia(m_Handle, &m_SrcAddr, &m_XoipCfg, EV_ASYNC, 0) == 0)
- m_StartFlag = true;
- else
- m_StartFlag = false;
- return m_StartFlag;
- }
- /*****************************************************************
- **【函数名称】 stopMedia
- **【函数功能】 停止通道媒体流
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIpmChannel::stopMedia( void )
- {
- ISX_ipm_Stop(m_Handle, STOP_ALL, EV_ASYNC);
- m_StartFlag = false;
- }
- /*****************************************************************
- **【函数名称】 switchVF
- **【函数功能】 语音与传真之间转换
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CIpmChannel::switchVF( ISXSIP_IE_BODY_EX* pSdp )
- {
- ASSERT(!m_FaxFlag);
- if(m_FaxFlag)
- return false;
- ASSERT(pSdp != NULL);
- USHORT Port = 0;
- int LoopNum = pSdp->u.BodySdp.SdpNum;
- ISXSIP_IE_BODY_SDP_EX* pSdpex = &pSdp->u.BodySdp;
- for(int i = 0; i < LoopNum; i++)
- {
- if(pSdpex->Sdp[i].Tag != ISXSIP_IE_SDP_TAG_MEDIA_DESC)
- continue;
- if(pSdpex->Sdp[i].u.MediaDesc.MediaPort > 0)
- {
- Port = pSdpex->Sdp[i].u.MediaDesc.MediaPort;
- break;
- }
- }
- if(Port > 0)
- {
- m_XoipCfg.FaxCfg.FaxType.Valid = 1;
- m_XoipCfg.FaxCfg.FaxType.FaxType = 1; // Fax配置类型,可以为:0为禁止传真,1为Relay,允许T.38传真中继,2 为Bypass,传真旁路
- m_XoipCfg.VoiceCfg.EchoCancel.Valid = 1;
- m_XoipCfg.VoiceCfg.EchoCancel.EchoCancel = 0;
- m_XoipCfg.FaxCfg.SrcT38Port.Valid = 0;
- m_XoipCfg.FaxCfg.SrcT38Port.UdpPort = 0;
- m_XoipCfg.FaxCfg.DstT38Port.Valid = 1;
- m_XoipCfg.FaxCfg.DstT38Port.UdpPort = Port;
- ISX_ipm_SetParm(m_Handle, &m_XoipCfg, EV_ASYNC);
- if(ISX_ipm_SwitchVF(m_Handle, IPM_SWITCH_VOICE2FAX, EV_ASYNC) == 0)
- {
- m_FaxFlag = true;
- return true;
- }
- }
-
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{IPMCh}: 通道[%d-%d-%d]在语音和传真模式间切换失败"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return false;
- }
- /*****************************************************************
- **【函数名称】 onDevEvent
- **【函数功能】 系统事件处理
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIpmChannel::onDevEvent( METAEVENT* pMetaEvent )
- {
- ASSERT(pMetaEvent != NULL);
- switch(pMetaEvent->evttype)
- {
- case IPMEV_ANSWER:
- __onAnswer(pMetaEvent);
- break;
- case IPMEV_SET_PARM:
- __onSetParam(pMetaEvent);
- break;
- case IPMEV_FAX:
- __onFax(pMetaEvent);
- break;
- }
- }
- /*****************************************************************
- **【函数名称】 reset
- **【函数功能】 重置成员变量
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIpmChannel::reset( void )
- {
- m_StartFlag = false;
- m_FaxFlag = false;
- m_pVoipChanBind = NULL;
- CMC::GetInstance().onDevResState(m_Id);
- }
- /*****************************************************************
- **【函数名称】 state
- **【函数功能】 返回状态字符串
- **【参数】
- **【返回值】
- ****************************************************************/
- LPCTSTR CIpmChannel::getStateStr( void ) const
- {
- if(m_pVoipChanBind != NULL)
- return _T("busy");
- else
- return (m_FaxFlag ? _T("fax") : _T("free"));
- }
- /*****************************************************************
- **【函数名称】 bind
- **【函数功能】 绑定VOIP通道
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIpmChannel::bind( CVoipChannel* pVoipChannel )
- {
- m_pVoipChanBind = pVoipChannel;
- CMC::GetInstance().onDevResState(m_Id);
- }
- /*****************************************************************
- **【函数名称】 startFax
- **【函数功能】 开始传真
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIpmChannel::startFax( void )
- {
- m_FaxFlag = true;
- CMC::GetInstance().onDevResState(m_Id);
- }
- /*****************************************************************
- **【函数名称】 stopFax
- **【函数功能】 结束传真
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIpmChannel::stopFax( void )
- {
- m_FaxFlag = false;
- CMC::GetInstance().onDevResState(m_Id);
- }
- /*****************************************************************
- **【函数名称】 mediaAddrBoard
- **【函数功能】 获取IPM板第二网口地址
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CIpmChannel::mediaAddrBoard( LPTSTR Buffer )
- {
- return ISX_sr_getnet2cfg(m_Id.NodeNo, m_Id.BoardNo, BT_XOIP, Buffer, NULL) == 0;
- }
- /*****************************************************************
- **【函数名称】 mediaAddrTrunk
- **【函数功能】 获取IPM板中继媒体地址
- **【参数】
- **【返回值】
- ****************************************************************/
- void CIpmChannel::mediaAddrTrunk( LPTSTR Buffer )
- {
- lstrcpy(Buffer, CConfig::voipMediaAddr());
- }
|