#include "StdAfx.h" #include "DevVoip.h" #include "Config.h" #include "MC.h" #include "VoipChannel.h" #include "SipRegister.h" CDevVoip::CDevVoip(DEV_RES_NO_TYPE NodeNo, DEV_RES_NO_TYPE BoardNo) : CDevResource(NodeNo, BoardNo), m_CurPos(0), m_SerialNoSeed(0), m_NetId(0), m_Serve4Exten(false) { } CDevVoip::~CDevVoip(void) { __freeRegister(); } /***************************************************************** **【函数名称】 __getRegisterByAccountId **【函数功能】 通过账号ID查找注册对象 **【参数】 **【返回值】 ****************************************************************/ CSipRegister* CDevVoip::__getRegisterByAccountId( int AccountId, bool NewWhenNull /*= false*/ ) { POSITION Pos = m_SipRegisterList.GetHeadPosition(); while(Pos != NULL) { CSipRegister* pReg = m_SipRegisterList.GetNext(Pos); ASSERT(pReg != NULL); if(pReg->accountId() == AccountId) return pReg; } if(NewWhenNull) { if(CConfig::sipAccount().getAccount(AccountId) != NULL) { CSipRegister* pReg = new CSipRegister(this, AccountId); ASSERT(pReg != NULL); m_SipRegisterList.AddTail(pReg); return pReg; } } return NULL; } /***************************************************************** **【函数名称】 __getRegisterBySerialNo **【函数功能】 通过注册序号查找注册对象 **【参数】 **【返回值】 ****************************************************************/ CSipRegister* CDevVoip::__getRegisterBySerialNo( UINT SerialNo ) { POSITION Pos = m_SipRegisterList.GetHeadPosition(); while(Pos != NULL) { CSipRegister* pReg = m_SipRegisterList.GetNext(Pos); ASSERT(pReg != NULL); if(pReg->serialNo() == SerialNo) return pReg; } return NULL; } /***************************************************************** **【函数名称】 __freeRegister **【函数功能】 释放注册对象 **【参数】 **【返回值】 ****************************************************************/ void CDevVoip::__freeRegister( void ) { while(m_SipRegisterList.GetCount() > 0) { delete m_SipRegisterList.RemoveHead(); } } /***************************************************************** **【函数名称】 __regist **【函数功能】 启动注册对象 **【参数】 **【返回值】 ****************************************************************/ void CDevVoip::__regist( void ) { TRUNK_ITEM* pItem = NULL; CCfgTrunkItem& TrunkItem = CConfig::trunkItem(); POSITION Pos = TrunkItem.GetHeadPosition(); while(Pos != NULL) { pItem = TrunkItem.GetNext(Pos); if(pItem->Node == m_NodeNo && pItem->Board == m_BoardNo) { CSipRegister* pReg = __getRegisterByAccountId(pItem->SipAccountId, true); if(pReg != NULL) pReg->regist(); } } } /***************************************************************** **【函数名称】 __checkNetId **【函数功能】 检索网络标识 **【参数】 **【返回值】 ****************************************************************/ void CDevVoip::__checkNetId( void ) { TCHAR IpAddr[IP_PORT_LEN] = { 0 }; TCHAR NetMask[IP_PORT_LEN] = { 0 }; ISX_sr_getnet2cfg(m_NodeNo, m_BoardNo, BT_SIP, IpAddr, NetMask); BYTE IpA = 0; BYTE IpB = 0; BYTE IpC = 0; BYTE IpD = 0; BYTE MaskA = 0; BYTE MaskB = 0; BYTE MaskC = 0; BYTE MaskD = 0; TCHAR* lpNext = NULL; TCHAR* lpToken = strtok_s(IpAddr, ".", &lpNext); IpA = atoi(lpToken); lpToken = strtok_s(NULL, ".", &lpNext); IpB = atoi(lpToken); lpToken = strtok_s(NULL, ".", &lpNext); IpC = atoi(lpToken); lpToken = strtok_s(NULL, ".", &lpNext); IpD = atoi(lpToken); lpNext = NULL; lpToken = strtok_s(NetMask, ".", &lpNext); MaskA = atoi(lpToken); lpToken = strtok_s(NULL, ".", &lpNext); MaskB = atoi(lpToken); lpToken = strtok_s(NULL, ".", &lpNext); MaskC = atoi(lpToken); lpToken = strtok_s(NULL, ".", &lpNext); MaskD = atoi(lpToken); IpA &= MaskA; IpB &= MaskB; IpC &= MaskC; IpD &= MaskD; // 计算网络标识,和IPM板标识相同的则可以相互服务 m_NetId = IpA; m_NetId = m_NetId << 8; m_NetId ^= IpB; m_NetId = m_NetId << 8; m_NetId ^= IpC; m_NetId = m_NetId << 8; m_NetId ^= IpD; // 检索当前SIP板和MC是否在同一子网,若在同一子网则可以为分机分配通道 lstrcpy(IpAddr, CConfig::mcAddr()); lpNext = NULL; lpToken = strtok_s(IpAddr, ".", &lpNext); IpA = atoi(lpToken); lpToken = strtok_s(NULL, ".", &lpNext); IpB = atoi(lpToken); lpToken = strtok_s(NULL, ".", &lpNext); IpC = atoi(lpToken); lpToken = strtok_s(NULL, ".", &lpNext); IpD = atoi(lpToken); IpA &= MaskA; IpB &= MaskB; IpC &= MaskC; IpD &= MaskD; ULONG McNetId = 0; McNetId = IpA; McNetId = McNetId << 8; McNetId ^= IpB; McNetId = McNetId << 8; McNetId ^= IpC; McNetId = McNetId << 8; McNetId ^= IpD; m_Serve4Exten = (McNetId == m_NetId ? true : false) ; } /***************************************************************** **【函数名称】 open **【函数功能】 VOIP设备打开函数 **【参数】 **【返回值】 ****************************************************************/ bool CDevVoip::open( void ) { if(m_state != STATUS_WORKING || m_VoipChList.GetCount() > 0) return false; m_CurPos = 0; for (int i = 0; i < m_Capacity; i++) { CVoipChannel* pChannel = new CVoipChannel(i, m_NodeNo, m_BoardNo); ASSERT(pChannel != NULL); if(pChannel != NULL) { if(pChannel->open()) { m_VoipChList.Add(pChannel); CMC::GetInstance().onDevResCreate(pChannel->id()); } else delete pChannel; } } __checkNetId(); __regist(); LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{DevVoip}: VOIP[%d-%d]成功打开%d条VOIP通道"), m_NodeNo, m_BoardNo, m_VoipChList.GetCount()); return true; } /***************************************************************** **【函数名称】 close **【函数功能】 VOIP设备关闭函数 **【参数】 **【返回值】 ****************************************************************/ void CDevVoip::close( void ) { __freeRegister(); for(int i = 0; i < m_VoipChList.GetCount(); ++i) { CVoipChannel* pChannel = m_VoipChList[i]; ASSERT(pChannel != NULL); CMC::GetInstance().onDevResDestroy(pChannel->id()); pChannel->close(); delete pChannel; } m_VoipChList.RemoveAll(); m_CurPos = 0; LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{DevVoip}: VOIP[%d-%d]通道全部关闭"), m_NodeNo, m_BoardNo); } /***************************************************************** **【函数名称】 makeSerialNo **【函数功能】 生成注册序列号 **【参数】 **【返回值】 ****************************************************************/ UINT CDevVoip::makeSerialNo( void ) { // 序列号,有效范围 0~4095 if(++m_SerialNoSeed > 4095) m_SerialNoSeed = 0; return m_SerialNoSeed; } /***************************************************************** **【函数名称】 getFreeVoipCh **【函数功能】 获取空闲通道 **【参数】 **【返回值】 ****************************************************************/ CVoipChannel* CDevVoip::getFreeVoipCh( void ) { CSingleLock locker(&m_LockSection); locker.Lock(); // 本操作需锁定 for(int i = 0; i < m_VoipChList.GetCount(); ++i) // 保证遍历一轮 { if(m_CurPos >= m_VoipChList.GetCount()) m_CurPos = 0; CVoipChannel* pChannel = m_VoipChList[m_CurPos++]; ASSERT(pChannel != NULL); // 当前是否空闲 if(pChannel->isEvenNo() && pChannel->isValid() && pChannel->isFree()) return pChannel; } return NULL; } /***************************************************************** **【函数名称】 findChan **【函数功能】 查找指定资源 **【参数】 **【返回值】 ****************************************************************/ CVoipChannel* CDevVoip::findChan( int ResId ) { if(ResId < 0 || ResId >= m_VoipChList.GetCount()) return NULL; else return m_VoipChList[ResId]; } /***************************************************************** **【函数名称】 onSipRegSent **【函数功能】 处理SIP注册发送事件 **【参数】 **【返回值】 ****************************************************************/ void CDevVoip::onSipRegSent( SEND_SIPREG_RET* pSent ) { ASSERT(pSent != NULL); CSipRegister* pReg = __getRegisterBySerialNo(pSent->RegisterId.ulSerialNo); if(pReg != NULL) pReg->onRegSent(pSent); } /***************************************************************** **【函数名称】 onSipRegAck **【函数功能】 处理SIP注册确认事件 **【参数】 **【返回值】 ****************************************************************/ void CDevVoip::onSipRegAck( SIP_REGISTER_ACK* pAck ) { ASSERT(pAck != NULL); CSipRegister* pReg = __getRegisterBySerialNo(pAck->RegisterId.ulSerialNo); if(pReg != NULL) pReg->processRegResult(pAck); } /***************************************************************** **【函数名称】 onSipTransaction **【函数功能】 处理事务 **【参数】 **【返回值】 ****************************************************************/ void CDevVoip::onSipTransaction( SIP_TRANSACTION_IND* pTransaction ) { SIP_TRANSACTION_ACK Ack; ZeroMemory(&Ack, sizeof(SIP_TRANSACTION_ACK)); Ack.ucIsxNo = pTransaction->ucIsxNo; Ack.ucBrdNo = pTransaction->ucBrdNo; Ack.ucTranscType = pTransaction->ucTranscType; if(pTransaction->ucTranscType == SIP_TRANSCTYPE_OPTIONS) { Ack.u.options_ack.ulSerialNo = pTransaction->u.options.ulSerialNo; Ack.u.options_ack.usCause = IPEC_SIPReasonStatus200OK; } ISX_gc_SIPSendTransactionAck(EV_ASYNC, &Ack); } /***************************************************************** **【函数名称】 isOk **【函数功能】 判断设备状态 **【参数】 **【返回值】 ****************************************************************/ bool CDevVoip::isOk( void ) const { return (m_state == STATUS_WORKING && m_VoipChList.GetCount() == m_Capacity); }