修改三方通话功能,在发起三方通话时,先保持住主叫,然后再拉回主叫到会议

DevVoip.cpp 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. #include "StdAfx.h"
  2. #include "DevVoip.h"
  3. #include "Config.h"
  4. #include "MC.h"
  5. #include "VoipChannel.h"
  6. #include "SipRegister.h"
  7. 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)
  8. {
  9. }
  10. CDevVoip::~CDevVoip(void)
  11. {
  12. __freeRegister();
  13. }
  14. /*****************************************************************
  15. **【函数名称】 __getRegisterByAccountId
  16. **【函数功能】 通过账号ID查找注册对象
  17. **【参数】
  18. **【返回值】
  19. ****************************************************************/
  20. CSipRegister* CDevVoip::__getRegisterByAccountId( int AccountId, bool NewWhenNull /*= false*/ )
  21. {
  22. POSITION Pos = m_SipRegisterList.GetHeadPosition();
  23. while(Pos != NULL)
  24. {
  25. CSipRegister* pReg = m_SipRegisterList.GetNext(Pos);
  26. ASSERT(pReg != NULL);
  27. if(pReg->accountId() == AccountId)
  28. return pReg;
  29. }
  30. if(NewWhenNull)
  31. {
  32. if(CConfig::sipAccount().getAccount(AccountId) != NULL)
  33. {
  34. CSipRegister* pReg = new CSipRegister(this, AccountId);
  35. ASSERT(pReg != NULL);
  36. m_SipRegisterList.AddTail(pReg);
  37. return pReg;
  38. }
  39. }
  40. return NULL;
  41. }
  42. /*****************************************************************
  43. **【函数名称】 __getRegisterBySerialNo
  44. **【函数功能】 通过注册序号查找注册对象
  45. **【参数】
  46. **【返回值】
  47. ****************************************************************/
  48. CSipRegister* CDevVoip::__getRegisterBySerialNo( UINT SerialNo )
  49. {
  50. POSITION Pos = m_SipRegisterList.GetHeadPosition();
  51. while(Pos != NULL)
  52. {
  53. CSipRegister* pReg = m_SipRegisterList.GetNext(Pos);
  54. ASSERT(pReg != NULL);
  55. if(pReg->serialNo() == SerialNo)
  56. return pReg;
  57. }
  58. return NULL;
  59. }
  60. /*****************************************************************
  61. **【函数名称】 __freeRegister
  62. **【函数功能】 释放注册对象
  63. **【参数】
  64. **【返回值】
  65. ****************************************************************/
  66. void CDevVoip::__freeRegister( void )
  67. {
  68. while(m_SipRegisterList.GetCount() > 0)
  69. {
  70. delete m_SipRegisterList.RemoveHead();
  71. }
  72. }
  73. /*****************************************************************
  74. **【函数名称】 __regist
  75. **【函数功能】 启动注册对象
  76. **【参数】
  77. **【返回值】
  78. ****************************************************************/
  79. void CDevVoip::__regist( void )
  80. {
  81. TRUNK_ITEM* pItem = NULL;
  82. CCfgTrunkItem& TrunkItem = CConfig::trunkItem();
  83. POSITION Pos = TrunkItem.GetHeadPosition();
  84. while(Pos != NULL)
  85. {
  86. pItem = TrunkItem.GetNext(Pos);
  87. if(pItem->Node == m_NodeNo && pItem->Board == m_BoardNo)
  88. {
  89. CSipRegister* pReg = __getRegisterByAccountId(pItem->SipAccountId, true);
  90. if(pReg != NULL)
  91. pReg->regist();
  92. }
  93. }
  94. }
  95. /*****************************************************************
  96. **【函数名称】 __checkNetId
  97. **【函数功能】 检索网络标识
  98. **【参数】
  99. **【返回值】
  100. ****************************************************************/
  101. void CDevVoip::__checkNetId( void )
  102. {
  103. TCHAR IpAddr[IP_PORT_LEN] = { 0 };
  104. TCHAR NetMask[IP_PORT_LEN] = { 0 };
  105. ISX_sr_getnet2cfg(m_NodeNo, m_BoardNo, BT_SIP, IpAddr, NetMask);
  106. BYTE IpA = 0;
  107. BYTE IpB = 0;
  108. BYTE IpC = 0;
  109. BYTE IpD = 0;
  110. BYTE MaskA = 0;
  111. BYTE MaskB = 0;
  112. BYTE MaskC = 0;
  113. BYTE MaskD = 0;
  114. TCHAR* lpNext = NULL;
  115. TCHAR* lpToken = strtok_s(IpAddr, ".", &lpNext);
  116. IpA = atoi(lpToken);
  117. lpToken = strtok_s(NULL, ".", &lpNext);
  118. IpB = atoi(lpToken);
  119. lpToken = strtok_s(NULL, ".", &lpNext);
  120. IpC = atoi(lpToken);
  121. lpToken = strtok_s(NULL, ".", &lpNext);
  122. IpD = atoi(lpToken);
  123. lpNext = NULL;
  124. lpToken = strtok_s(NetMask, ".", &lpNext);
  125. MaskA = atoi(lpToken);
  126. lpToken = strtok_s(NULL, ".", &lpNext);
  127. MaskB = atoi(lpToken);
  128. lpToken = strtok_s(NULL, ".", &lpNext);
  129. MaskC = atoi(lpToken);
  130. lpToken = strtok_s(NULL, ".", &lpNext);
  131. MaskD = atoi(lpToken);
  132. IpA &= MaskA;
  133. IpB &= MaskB;
  134. IpC &= MaskC;
  135. IpD &= MaskD;
  136. // 计算网络标识,和IPM板标识相同的则可以相互服务
  137. m_NetId = IpA;
  138. m_NetId = m_NetId << 8;
  139. m_NetId ^= IpB;
  140. m_NetId = m_NetId << 8;
  141. m_NetId ^= IpC;
  142. m_NetId = m_NetId << 8;
  143. m_NetId ^= IpD;
  144. // 检索当前SIP板和MC是否在同一子网,若在同一子网则可以为分机分配通道
  145. lstrcpy(IpAddr, CConfig::mcAddr());
  146. lpNext = NULL;
  147. lpToken = strtok_s(IpAddr, ".", &lpNext);
  148. IpA = atoi(lpToken);
  149. lpToken = strtok_s(NULL, ".", &lpNext);
  150. IpB = atoi(lpToken);
  151. lpToken = strtok_s(NULL, ".", &lpNext);
  152. IpC = atoi(lpToken);
  153. lpToken = strtok_s(NULL, ".", &lpNext);
  154. IpD = atoi(lpToken);
  155. IpA &= MaskA;
  156. IpB &= MaskB;
  157. IpC &= MaskC;
  158. IpD &= MaskD;
  159. ULONG McNetId = 0;
  160. McNetId = IpA;
  161. McNetId = McNetId << 8;
  162. McNetId ^= IpB;
  163. McNetId = McNetId << 8;
  164. McNetId ^= IpC;
  165. McNetId = McNetId << 8;
  166. McNetId ^= IpD;
  167. m_Serve4Exten = (McNetId == m_NetId ? true : false) ;
  168. }
  169. /*****************************************************************
  170. **【函数名称】 open
  171. **【函数功能】 VOIP设备打开函数
  172. **【参数】
  173. **【返回值】
  174. ****************************************************************/
  175. bool CDevVoip::open( void )
  176. {
  177. if(m_state != STATUS_WORKING || m_VoipChList.GetCount() > 0)
  178. return false;
  179. m_CurPos = 0;
  180. for (int i = 0; i < m_Capacity; i++)
  181. {
  182. CVoipChannel* pChannel = new CVoipChannel(i, m_NodeNo, m_BoardNo);
  183. ASSERT(pChannel != NULL);
  184. if(pChannel != NULL)
  185. {
  186. if(pChannel->open())
  187. {
  188. m_VoipChList.Add(pChannel);
  189. CMC::GetInstance().onDevResCreate(pChannel->id());
  190. }
  191. else
  192. delete pChannel;
  193. }
  194. }
  195. __checkNetId();
  196. __regist();
  197. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{DevVoip}: VOIP[%d-%d]成功打开%d条VOIP通道"), m_NodeNo, m_BoardNo, m_VoipChList.GetCount());
  198. return true;
  199. }
  200. /*****************************************************************
  201. **【函数名称】 close
  202. **【函数功能】 VOIP设备关闭函数
  203. **【参数】
  204. **【返回值】
  205. ****************************************************************/
  206. void CDevVoip::close( void )
  207. {
  208. __freeRegister();
  209. for(int i = 0; i < m_VoipChList.GetCount(); ++i)
  210. {
  211. CVoipChannel* pChannel = m_VoipChList[i];
  212. ASSERT(pChannel != NULL);
  213. CMC::GetInstance().onDevResDestroy(pChannel->id());
  214. pChannel->close();
  215. delete pChannel;
  216. }
  217. m_VoipChList.RemoveAll();
  218. m_CurPos = 0;
  219. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{DevVoip}: VOIP[%d-%d]通道全部关闭"), m_NodeNo, m_BoardNo);
  220. }
  221. /*****************************************************************
  222. **【函数名称】 makeSerialNo
  223. **【函数功能】 生成注册序列号
  224. **【参数】
  225. **【返回值】
  226. ****************************************************************/
  227. UINT CDevVoip::makeSerialNo( void )
  228. {
  229. // 序列号,有效范围 0~4095
  230. if(++m_SerialNoSeed > 4095)
  231. m_SerialNoSeed = 0;
  232. return m_SerialNoSeed;
  233. }
  234. /*****************************************************************
  235. **【函数名称】 getFreeVoipCh
  236. **【函数功能】 获取空闲通道
  237. **【参数】
  238. **【返回值】
  239. ****************************************************************/
  240. CVoipChannel* CDevVoip::getFreeVoipCh( void )
  241. {
  242. CSingleLock locker(&m_LockSection);
  243. locker.Lock(); // 本操作需锁定
  244. for(int i = 0; i < m_VoipChList.GetCount(); ++i) // 保证遍历一轮
  245. {
  246. if(m_CurPos >= m_VoipChList.GetCount())
  247. m_CurPos = 0;
  248. CVoipChannel* pChannel = m_VoipChList[m_CurPos++];
  249. ASSERT(pChannel != NULL);
  250. // 当前是否空闲
  251. if(pChannel->isEvenNo() && pChannel->isValid() && pChannel->isFree())
  252. return pChannel;
  253. }
  254. return NULL;
  255. }
  256. /*****************************************************************
  257. **【函数名称】 findChan
  258. **【函数功能】 查找指定资源
  259. **【参数】
  260. **【返回值】
  261. ****************************************************************/
  262. CVoipChannel* CDevVoip::findChan( int ResId )
  263. {
  264. if(ResId < 0 || ResId >= m_VoipChList.GetCount())
  265. return NULL;
  266. else
  267. return m_VoipChList[ResId];
  268. }
  269. /*****************************************************************
  270. **【函数名称】 onSipRegSent
  271. **【函数功能】 处理SIP注册发送事件
  272. **【参数】
  273. **【返回值】
  274. ****************************************************************/
  275. void CDevVoip::onSipRegSent( SEND_SIPREG_RET* pSent )
  276. {
  277. ASSERT(pSent != NULL);
  278. CSipRegister* pReg = __getRegisterBySerialNo(pSent->RegisterId.ulSerialNo);
  279. if(pReg != NULL)
  280. pReg->onRegSent(pSent);
  281. }
  282. /*****************************************************************
  283. **【函数名称】 onSipRegAck
  284. **【函数功能】 处理SIP注册确认事件
  285. **【参数】
  286. **【返回值】
  287. ****************************************************************/
  288. void CDevVoip::onSipRegAck( SIP_REGISTER_ACK* pAck )
  289. {
  290. ASSERT(pAck != NULL);
  291. CSipRegister* pReg = __getRegisterBySerialNo(pAck->RegisterId.ulSerialNo);
  292. if(pReg != NULL)
  293. pReg->processRegResult(pAck);
  294. }
  295. /*****************************************************************
  296. **【函数名称】 onSipTransaction
  297. **【函数功能】 处理事务
  298. **【参数】
  299. **【返回值】
  300. ****************************************************************/
  301. void CDevVoip::onSipTransaction( SIP_TRANSACTION_IND* pTransaction )
  302. {
  303. SIP_TRANSACTION_ACK Ack;
  304. ZeroMemory(&Ack, sizeof(SIP_TRANSACTION_ACK));
  305. Ack.ucIsxNo = pTransaction->ucIsxNo;
  306. Ack.ucBrdNo = pTransaction->ucBrdNo;
  307. Ack.ucTranscType = pTransaction->ucTranscType;
  308. if(pTransaction->ucTranscType == SIP_TRANSCTYPE_OPTIONS)
  309. {
  310. Ack.u.options_ack.ulSerialNo = pTransaction->u.options.ulSerialNo;
  311. Ack.u.options_ack.usCause = IPEC_SIPReasonStatus200OK;
  312. }
  313. ISX_gc_SIPSendTransactionAck(EV_ASYNC, &Ack);
  314. }
  315. /*****************************************************************
  316. **【函数名称】 isOk
  317. **【函数功能】 判断设备状态
  318. **【参数】
  319. **【返回值】
  320. ****************************************************************/
  321. bool CDevVoip::isOk( void ) const
  322. {
  323. return (m_state == STATUS_WORKING && m_VoipChList.GetCount() == m_Capacity);
  324. }