linux版本中间件

Session.cpp 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. #include "Session.h"
  2. #include <boost/filesystem.hpp>
  3. #include "FsProxy.h"
  4. #include "ChanTrunk.h"
  5. #include "ChanExten.h"
  6. #include "JsonStringMaker.h"
  7. #include "Util.h"
  8. #include "SqlWrite.h"
  9. #include "Config.h"
  10. Session::Session(CFsProxy* pParent, string Id) : m_pParent(pParent), m_Id(Id), m_IsAnswer(false), m_IsSaveDb(true), m_AtionId(0)
  11. {
  12. }
  13. Session::~Session()
  14. {
  15. }
  16. bool Session::isContainChanId(const std::string & chanId)
  17. {
  18. std::unique_lock<std::mutex> lock(m_ChanLock);
  19. for (auto pChan : m_ListChan)
  20. {
  21. if (pChan->chanId() == chanId)
  22. return true;
  23. }
  24. return false;
  25. }
  26. void Session::prepare(PCHAN_EVENT_NOTIFY pNotify)
  27. {
  28. if (m_Id != pNotify->ChanId) // 触发会话的通道不是会话主通道,则查找并添加主通道
  29. {
  30. VirtualChan* pChan = m_pParent->getBusyChan(m_Id);
  31. if (pChan != nullptr)
  32. __addChan(pChan);
  33. }
  34. }
  35. void Session::onChanEvent(PCHAN_EVENT_NOTIFY pNotify)
  36. {
  37. if (pNotify == nullptr) return;
  38. VirtualChan* pChan = __getChan(pNotify->ChanId);
  39. if (pChan == nullptr)
  40. {
  41. pChan = __findChan(pNotify);
  42. if (pChan != nullptr)
  43. __addChan(pChan);
  44. else
  45. {
  46. Format fmt("{Fs.Session}: 处理通道事件时查找对应通道失败, Caller = %s, Callee = %s");
  47. fmt % pNotify->Caller % pNotify->Callee;
  48. LOG_WARN_S(fmt.str());
  49. return;
  50. }
  51. }
  52. __notifyDbSaveChanEvent(pChan, pNotify); // 通话记录保存
  53. pChan->onChanEvent(pNotify);
  54. __notifyIncomingChanEvent(pChan, pNotify); // 来电弹屏
  55. // 过滤无效状态
  56. if (pChan->state() == CHAN_LOGIC_STATE_FREE && pNotify->EventId == CHANNEL_EVENT_CREATE)
  57. return;
  58. __notifySessionChanEvent(pChan, pNotify);
  59. __onRecord(pChan, pNotify); // 执行录音
  60. __onPlayAgentNo(pChan, pNotify); // 判断是否报工号
  61. try
  62. {
  63. if (pChan->isFree())
  64. __onChanFree(pChan, pNotify);
  65. }
  66. catch (const std::exception& e)
  67. {
  68. LOG_WARN(("{Fs.Session.onChanEvent}: 通道空闲处理函数执行发生异常[%s], Caller = %s, Callee = %s"),e.what(), pNotify->Caller.c_str(), pNotify->Callee.c_str());
  69. }
  70. }
  71. void Session::onChanDtmf(PDTMF_NOTIFY pNotify)
  72. {
  73. }
  74. void Session::onChanHold(PHOLD_NOTIFY pNotify)
  75. {
  76. VirtualChan* pChan = __getChan(pNotify->ChanId);
  77. if (pChan != nullptr)
  78. {
  79. pChan->onChanHold(pNotify->EvtType);
  80. }
  81. }
  82. VirtualChan * Session::getAssoChan(VirtualChan * pChan)
  83. {
  84. std::unique_lock<std::mutex> lock(m_ChanLock);
  85. auto it = m_ListChan.begin();
  86. while (it != m_ListChan.end())
  87. {
  88. if (*it != pChan)
  89. return *it;
  90. ++it;
  91. }
  92. return nullptr;
  93. }
  94. VirtualChan * Session::getAssoFinalChan()
  95. {
  96. std::unique_lock<std::mutex> lock(m_ChanLock);
  97. return m_ListChan.back();
  98. }
  99. VirtualChan * Session::getAssoFinalChan(VirtualChan * pChan)
  100. {
  101. std::unique_lock<std::mutex> lock(m_ChanLock);
  102. auto pFinalChan = m_ListChan.back();
  103. if (pFinalChan == pChan)return nullptr; // 是同一条,返回空
  104. return m_ListChan.back();
  105. }
  106. VirtualChan * Session::__getFirstChan()
  107. {
  108. std::unique_lock<std::mutex> lock(m_ChanLock);
  109. if(m_ListChan.empty())
  110. return nullptr;
  111. return m_ListChan.front();
  112. }
  113. VirtualChan * Session::__getChan(string ChanId)
  114. {
  115. std::unique_lock<std::mutex> lock(m_ChanLock);
  116. auto it = m_ListChan.begin();
  117. while (it != m_ListChan.end())
  118. {
  119. if ((*it)->chanId() == ChanId)
  120. return *it;
  121. ++it;
  122. }
  123. return nullptr;
  124. }
  125. VirtualChan * Session::__findChan(PCHAN_EVENT_NOTIFY pNotify)
  126. {
  127. VirtualChan* pChan = nullptr;
  128. if (pNotify->EventId == CHANNEL_EVENT_CREATE)
  129. {
  130. stringstream str;
  131. uint32_t ExtenNo = 0;
  132. if (pNotify->Direction == CALL_DIRECTION_INBOUND)
  133. str << pNotify->Caller; //ExtenNo = stoul(pNotify->Caller); // 呼入FS
  134. else
  135. str << pNotify->Callee; //ExtenNo = stoul(pNotify->Callee); // FS呼出
  136. str >> ExtenNo;
  137. pChan = m_pParent->getExten(ExtenNo);
  138. if (pChan == nullptr) // 分机通道中无,则说明是中继通道
  139. {
  140. pChan = m_pParent->getFreeTrunk();
  141. if (pChan == nullptr)
  142. {
  143. Format fmt("{Fs.Session}: 处理通道事件时获取空闲中继通道失败, Caller = %s, Callee = %s");
  144. fmt % pNotify->Caller % pNotify->Callee;
  145. LOG_WARN_S(fmt.str());
  146. m_pParent->onChanPoor(this, pNotify);
  147. }
  148. }
  149. }
  150. else
  151. {
  152. pChan = m_pParent->getBusyChan(pNotify->ChanId);
  153. }
  154. return pChan;
  155. }
  156. void Session::__addChan(VirtualChan * pChan)
  157. {
  158. std::unique_lock<std::mutex> lock(m_ChanLock);
  159. m_ListChan.emplace_back(pChan);
  160. }
  161. /*****************************************************************
  162. **【函数名称】 __delChan
  163. **【函数功能】 删除指定通道
  164. **【参数】
  165. **【返回值】
  166. *****************************************************************/
  167. void Session::__delChan(VirtualChan * pChan)
  168. {
  169. std::unique_lock<std::mutex> lock(m_ChanLock);
  170. m_ListChan.remove(pChan);
  171. }
  172. /*****************************************************************
  173. **【函数名称】 __clearChan
  174. **【函数功能】 清空通道
  175. **【参数】
  176. **【返回值】
  177. *****************************************************************/
  178. void Session::__clearChan(void)
  179. {
  180. std::unique_lock<std::mutex> lock(m_ChanLock);
  181. m_ListChan.clear();
  182. }
  183. void Session::__notifySessionChanEvent(VirtualChan * pChanHost, PCHAN_EVENT_NOTIFY pNotify)
  184. {
  185. std::unique_lock<std::mutex> lock(m_ChanLock);
  186. auto it = m_ListChan.begin();
  187. while (it != m_ListChan.end())
  188. {
  189. if ((*it) != pChanHost)
  190. {
  191. (*it)->onSessionChanEvent(pChanHost, pNotify);
  192. }
  193. ++it;
  194. }
  195. }
  196. /*
  197. ** 分机来电事件
  198. */
  199. void Session::__notifyIncomingChanEvent(VirtualChan * pChanHost, PCHAN_EVENT_NOTIFY pNotify)
  200. {
  201. if (pNotify->Caller == pNotify->Callee && pNotify->Called.empty()) // 自震分机不弹屏/班长坐席操作不弹屏
  202. return;
  203. // 会话有两条通道,且当前通道为分机,当前时间为创建对话,发送来电事件给当前分机
  204. if (m_ListChan.size()==2 && pChanHost->type() == DEV_RES_TYPE_EXT && pNotify->EventId == CHANNEL_EVENT_CREATE)
  205. {
  206. std::string CallID = pNotify->CcId.empty()==true ? pNotify->CallId : pNotify->CcId;
  207. std::string ExtenNo = std::to_string(pChanHost->no());
  208. std::string Number = pNotify->Caller; // 主叫号码
  209. std::string callee = pNotify->Callee; // 被叫号码
  210. std::string TrunkNumber;
  211. int inComingType = 0;
  212. inComingType = 1;
  213. auto pFirstChan = __getFirstChan();
  214. if (pFirstChan != nullptr && pFirstChan->type() == DEV_RES_TYPE_TRUNK)
  215. TrunkNumber = pFirstChan->calleeNum();
  216. std::string data = m_pParent->creatJsonIncoming(CallID, Number, callee, TrunkNumber,inComingType);
  217. m_pParent->send2Agent(ExtenNo,data); // 发送来电事件到坐席
  218. }
  219. if (m_ListChan.size() == 1 && pNotify->EventId == CHANNEL_EVENT_CREATE)
  220. {
  221. if (pChanHost->type() == DEV_RES_TYPE_EXT) // 分机外呼弹屏
  222. {
  223. std::string CallID = pNotify->CcId.empty() == true ? pNotify->CallId : pNotify->CcId;
  224. std::string ExtenNo = std::to_string(pChanHost->no());
  225. std::string Number = pChanHost->callerNum(); //pNotify->Caller; // 主叫号码 , 代接,强插时主叫问题
  226. std::string callee = pNotify->Callee; // 被叫号码
  227. if (Number == callee && !pNotify->Called.empty())
  228. {
  229. callee = pNotify->Called;
  230. }
  231. std::string TrunkNumber;
  232. int inComingType = 0;
  233. if (pNotify->CallType == 0) // 分机外呼
  234. {
  235. inComingType = 2;
  236. if (pNotify->Caller != pNotify->Callee && pNotify->Direction == CALL_DIRECTION_OUTBOUND) // 该条件下会议 收到来电弹屏
  237. inComingType = 1;
  238. }
  239. else // 自动外呼
  240. {
  241. inComingType = 3;
  242. }
  243. std::string data = m_pParent->creatJsonIncoming(CallID, Number, callee, TrunkNumber, inComingType);
  244. m_pParent->send2Agent(ExtenNo, data); // 发送来电事件到坐席
  245. }
  246. }
  247. //if (m_ListChan.size() == 2 && pNotify->EventId == CHANNEL_EVENT_CREATE)
  248. //{
  249. // std::string CallID = pNotify->CcId.empty() == true ? pNotify->CallId : pNotify->CcId;
  250. // std::string ExtenNo = std::to_string(pChanHost->no());
  251. // std::string Number = pNotify->Caller; // 主叫号码
  252. // std::string callee = pNotify->Callee; // 被叫号码
  253. // std::string TrunkNumber; // 中继号码
  254. // int inComingType = 0;
  255. // auto pFirstChan = __getFirstChan();
  256. // if (pFirstChan != nullptr && pFirstChan->type() == DEV_RES_TYPE_TRUNK)
  257. // {
  258. // TrunkNumber = pFirstChan->calleeNum();
  259. // inComingType = 2; // 来电
  260. // }
  261. // else if(pFirstChan != nullptr && pFirstChan->type() == DEV_RES_TYPE_EXT)
  262. // {
  263. // inComingType = 1; // 分机外呼
  264. // if(pNotify->CallType == 2) // 自动外呼
  265. // inComingType = 3; // 分机外呼
  266. // }
  267. // std::string data = m_pParent->creatJsonIncoming(CallID, Number, callee, TrunkNumber, inComingType);
  268. // m_pParent->send2Agent(ExtenNo, data); // 发送来电事件到坐席
  269. //}
  270. }
  271. void Session::__notifyDbSaveChanEvent(VirtualChan * pChanHost, PCHAN_EVENT_NOTIFY pNotify)
  272. {
  273. if (pNotify == nullptr || pChanHost == nullptr) return;
  274. // 自动外呼不用该方法保存数据库
  275. if (pNotify->CallType != 0)
  276. {
  277. __saveAutoCallDB(pChanHost,pNotify);
  278. return;
  279. }
  280. if (pChanHost->isInMeeting()&& pNotify->EventId == CHANNEL_EVENT_HANGUP_COMPLETE) // 会议,
  281. {
  282. Format fmt("update rep_conference set end_time = '%s' where uuid = '%s'");
  283. fmt %Util::CurTime() % pChanHost->sessionId();
  284. SqlWrite::GetInstance()->addSql(fmt.str());
  285. }
  286. if (!pChanHost->opNumber().empty()) // 强插等操作会有操作码
  287. {
  288. return;
  289. }
  290. if (pNotify->EventId == CHANNEL_EVENT_CREATE && pChanHost->type() == DEV_RES_TYPE_EXT && pChanHost == __getFirstChan()) // 分机为主叫时数据库新添加一条记录
  291. {
  292. std::string curTime = Util::CurTime();
  293. std::string callid = pNotify->CcId.empty() == true ? pNotify->CallId : pNotify->CcId;
  294. std::string agent = m_pParent->getAgentByExten(pNotify->Caller);
  295. Format fmt("insert into rep_cdr(uuid,caller_agent,caller,call_type,create_time,action_id) values('%s','%s','%s',%d,'%s',%d)"); // 分机呼叫 call_type=1
  296. fmt %callid %agent % pNotify->Caller % 1 % curTime % 1;
  297. SqlWrite::GetInstance()->addSql(fmt.str());
  298. }
  299. else if (pNotify->EventId == CHANNEL_EVENT_CREATE && pChanHost != __getFirstChan()) // b腿创建
  300. {
  301. m_AtionId++;
  302. m_RingTime.clear();
  303. m_AnswerTime.clear();
  304. m_IsSaveDb = true;
  305. if (m_AtionId >1 )
  306. {
  307. auto pChan = __getFirstChan();
  308. if (pChan != nullptr)
  309. {
  310. int call_type = 0;
  311. if (pChan->type() == DEV_RES_TYPE_EXT)
  312. {
  313. call_type = 1;
  314. }
  315. std::string curTime = Util::CurTime();
  316. std::string callid = pNotify->CcId.empty() == true ? pNotify->CallId : pNotify->CcId;
  317. std::string agent = m_pParent->getAgentByExten(pNotify->Caller);
  318. Format fmt("insert into rep_cdr(uuid,caller_agent,caller,call_type,create_time,action_id) values('%s','%s','%s',%d,'%s',%d)"); // 分机呼叫 call_type=1
  319. fmt %callid %agent % pNotify->Caller % call_type % curTime % m_AtionId;
  320. SqlWrite::GetInstance()->addSql(fmt.str());
  321. }
  322. }
  323. }
  324. else if ((pNotify->EventId == CHANNEL_EVENT_PROGRESS || pNotify->EventId == CHANNEL_EVENT_PROGRESS_MEDIA) && pChanHost != __getFirstChan()) // 呼出振铃
  325. {
  326. if (m_RingTime.empty())
  327. m_RingTime = Util::CurTime();
  328. }
  329. else if (pNotify->EventId == CHANNEL_EVENT_ANSWER && pChanHost != __getFirstChan())
  330. {
  331. m_AnswerTime = Util::CurTime();
  332. m_IsAnswer = true;
  333. }
  334. if (pNotify->EventId == CHANNEL_EVENT_HANGUP_COMPLETE && m_IsSaveDb ) // 收到挂机事件,且第一次更新数据库(update)
  335. {
  336. std::string curTime = Util::CurTime();
  337. std::string agent;
  338. std::string callee; // 被叫
  339. std::string group; // 坐席组
  340. if (pChanHost->type() == DEV_RES_TYPE_TRUNK && pChanHost == __getFirstChan()) // 中继呼入且先挂机
  341. {
  342. auto pAssoChan = getAssoChan(pChanHost); // 根据对端线路获取被叫
  343. if (pAssoChan != nullptr)
  344. {
  345. callee = pAssoChan->calleeNum();
  346. }
  347. }
  348. else
  349. {
  350. if (pChanHost->isInMeeting()) // 会议时
  351. callee = pNotify->Caller;
  352. else
  353. callee = pNotify->Callee;
  354. }
  355. agent = m_pParent->getAgentByExten(callee,group);
  356. auto fun = [](std::string time)->std::string { if (time.empty()) return "null"; else return "'" + time + "'"; }; // 匿名函数用于转化时间
  357. m_RingTime = fun(m_RingTime);
  358. m_AnswerTime = fun(m_AnswerTime);
  359. if (m_AtionId == 0)
  360. m_AtionId = 1;
  361. // 增加被叫坐席组
  362. Format fmt("update rep_cdr set group_no = '%s',callee_agent = '%s',callee = '%s', ring_time = %s,answer_time = %s,is_answer = %d,end_time = '%s',record_path = '%s', hangup_cause = '%s' where uuid = '%s' and action_id = %d");
  363. fmt %group %agent %callee % m_RingTime %m_AnswerTime %m_IsAnswer %curTime %m_RecordFile %pNotify->HangupCause %pChanHost->sessionId() % m_AtionId;
  364. SqlWrite::GetInstance()->addSql(fmt.str());
  365. // 清空
  366. m_RingTime.clear();
  367. m_AnswerTime.clear();
  368. m_IsAnswer = false;
  369. m_IsSaveDb = false;
  370. }
  371. if (pNotify->EventId == CHANNEL_EVENT_HANGUP_COMPLETE && pChanHost->type() == DEV_RES_TYPE_TRUNK)
  372. {
  373. std::string curTime = Util::CurTime();
  374. Format fmt("update rep_cdr set hangup_time = '%s' where uuid = '%s'");
  375. fmt %curTime %pChanHost->sessionId();
  376. SqlWrite::GetInstance()->addSql(fmt.str());
  377. }
  378. }
  379. void Session::__saveAutoCallDB(VirtualChan * pChanHost, PCHAN_EVENT_NOTIFY pNotify)
  380. {
  381. if (pNotify->EventId == CHANNEL_EVENT_CREATE && pChanHost == __getFirstChan()) // 分机为主叫时数据库新添加一条记录
  382. {
  383. std::string curTime = Util::CurTime();
  384. std::string callid = pNotify->CcId.empty() == true ? pNotify->CallId : pNotify->CcId;
  385. std::string sql;
  386. if (pNotify->CallType == VOICE_CALL)
  387. {
  388. Format fmt("insert into rep_auto_cdr(uuid,caller,create_time,task_id) values('%s','%s','%s',%ld)"); // 语音呼叫 call_type=1
  389. fmt %callid % pNotify->Caller % curTime %pNotify->TaskId;
  390. sql = fmt.str();
  391. }
  392. else
  393. {
  394. std::string agent = m_pParent->getAgentByExten(pNotify->Caller);
  395. Format fmt("insert into rep_auto_cdr(uuid,agent,caller,create_time,task_id) values('%s','%s','%s','%s',%ld)"); // 分机呼叫 call_type=2
  396. fmt %callid %agent %pNotify->Callee %curTime %pNotify->TaskId;
  397. //Format fmt("insert into auto_cdr(uuid,caller,create_time,task_id) values('%s','%s','%s',%ld)"); // 分机呼叫 call_type=2
  398. //fmt %callid % pNotify->Callee % curTime %pNotify->TaskId;
  399. sql = fmt.str();
  400. }
  401. SqlWrite::GetInstance()->addSql(sql);
  402. }
  403. else if ((pNotify->EventId == CHANNEL_EVENT_PROGRESS || pNotify->EventId == CHANNEL_EVENT_PROGRESS_MEDIA) && (pChanHost != __getFirstChan() || pNotify->CallType == VOICE_CALL)) // 呼出振铃
  404. {
  405. if (m_RingTime.empty())
  406. m_RingTime = Util::CurTime();
  407. }
  408. else if (pNotify->EventId == CHANNEL_EVENT_ANSWER && (pChanHost != __getFirstChan() || pNotify->CallType == VOICE_CALL))
  409. {
  410. m_AnswerTime = Util::CurTime();
  411. }
  412. else if (pNotify->EventId == CHANNEL_EVENT_HANGUP_COMPLETE && m_IsSaveDb) // 收到挂机事件,且第一次更新数据库(update)
  413. {
  414. std::string curTime = Util::CurTime();
  415. auto fun = [](std::string time)->std::string { if (time.empty()) return "null"; else return "'" + time + "'"; }; // 匿名函数用于转化时间
  416. m_RingTime = fun(m_RingTime);
  417. m_AnswerTime = fun(m_AnswerTime);
  418. Format fmt("update rep_auto_cdr set callee = '%s', ring_time = %s,answer_time = %s,end_time = '%s',record_path = '%s', hangup_cause = '%s' where uuid = '%s'");
  419. if (pNotify->CallType == VOICE_CALL) // 语音外呼被叫 接通挂机时取 caller
  420. fmt %pNotify->Caller % m_RingTime %m_AnswerTime %curTime %m_RecordFile %pNotify->HangupCause %pChanHost->sessionId();
  421. else
  422. fmt %pNotify->Callee % m_RingTime %m_AnswerTime %curTime %m_RecordFile %pNotify->HangupCause %pChanHost->sessionId();
  423. SqlWrite::GetInstance()->addSql(fmt.str());
  424. // 清空
  425. m_RingTime.clear();
  426. m_AnswerTime.clear();
  427. m_IsSaveDb = false;
  428. }
  429. }
  430. void Session::__onChanFree(VirtualChan * pChan, PCHAN_EVENT_NOTIFY pNotify)
  431. {
  432. //if (m_Id == pNotify->ChanId) // 若会话主通道空闲则清空会话
  433. // __clearChan();
  434. //else
  435. // __delChan(pChan);
  436. __delChan(pChan); // 防止重复收到挂机事件覆盖之前的有效数据
  437. if (pChan->isVoid()) // 若通道已被丢弃,则删除
  438. m_pParent->delChan(pChan);
  439. }
  440. void Session::__onPlayAgentNo(VirtualChan * pChan, PCHAN_EVENT_NOTIFY pNotify)
  441. {
  442. if (pChan == nullptr)
  443. {
  444. LOG_ERROR_S("通道pChan已被释放!!!");
  445. return;
  446. }
  447. if(pNotify == nullptr)
  448. {
  449. LOG_ERROR_S("通道事件pNotify已被释放!!!");
  450. return;
  451. }
  452. // 事件为接听,通道为分机,线路数为2, 对端为外线,进行播报工号
  453. if (pNotify->EventId != CHANNEL_EVENT_ANSWER || pChan->isInMeeting() || m_ListChan.size() != 2)
  454. {
  455. //LOG_DEBUG("调用播报工号 %d %d %d ", pNotify->EventId, pChan->isInMeeting(), m_ListChan.size());
  456. return;
  457. }
  458. VirtualChan* pFirstChan = __getFirstChan();
  459. if (pFirstChan != nullptr && pFirstChan->type() == DEV_RES_TYPE_TRUNK && pChan->type() == DEV_RES_TYPE_EXT)
  460. {
  461. m_pParent->playAgentNo(pChan);
  462. }
  463. }
  464. void Session::__onRecord(VirtualChan * pChan, PCHAN_EVENT_NOTIFY pNotify)
  465. {
  466. /*
  467. if (pChan == __getFirstChan() && pNotify->EventId == CHANNEL_EVENT_ANSWER)
  468. {
  469. std::string Number;
  470. Number = pNotify->Caller;
  471. // 判断是否需要录音
  472. std::string sql = boost::str(Format("select id from record where caller = '%s'") % Number);
  473. JdbcHelper::GetInstance()->jdbc_executeQuery(sql, [=](sql::PreparedStatement* stmt) {
  474. }, [=](sql::ResultSet* result) {
  475. if (!result->next()) // 数据库查不到记录,进行录音
  476. {
  477. LOG_DEBUG("操作标识:%ld", pNotify->ChanOpInstance);
  478. //if (pNotify->ChanOpInstance == 0) // 会议不进行再次录音
  479. if(CConfig::GetInstance()->isAutoRecord())
  480. COperationReactor::GetInstance()->procOperation(-1, LINE_OP_RECORD, pChan->no(), nullptr); // 执行录音
  481. }
  482. }, NULL);
  483. }
  484. */
  485. // 保持状态过滤
  486. auto Status = (HELD_STATE_FILTER_MASK & pChan->state());
  487. // 通话
  488. //if (Status == TRUNK_STATE_TALKING || Status == INNER_STATE_TALKING)
  489. if(Status == CHAN_LOGIC_STATE_TALKING)
  490. {
  491. for (auto pTempChan : m_ListChan)
  492. {
  493. if (pTempChan == NULL || pTempChan == pChan)
  494. continue;
  495. auto nTempStatus = (HELD_STATE_FILTER_MASK & pTempChan->state());
  496. //if (nTempStatus == TRUNK_STATE_TALKING || nTempStatus == INNER_STATE_TALKING)
  497. if (nTempStatus == CHAN_LOGIC_STATE_TALKING)
  498. {
  499. LOG_DEBUG("进行录音操作处理");
  500. __onLineTalking(pChan);
  501. __onLineTalking(pTempChan);
  502. break;
  503. }
  504. }
  505. }
  506. }
  507. void Session::__createFileName(VirtualChan * pChan)
  508. {
  509. if (m_RecordFile.empty() || m_RecordFile == "")
  510. {
  511. std::string strCurTime = Util::CurTime();
  512. strCurTime = std::regex_replace(strCurTime, std::regex("-|:"), "");
  513. auto index = strCurTime.find(" ");
  514. std::string data = strCurTime.substr(0, index);
  515. std::string time = strCurTime.substr(index+1);
  516. std::string strTempCallID = regex_replace(m_Id, std::regex("-"), "");
  517. strTempCallID = time + "_" + strTempCallID;
  518. m_RecordFile = CConfig::GetInstance()->recordPath() + "/" + data + "/";
  519. // 判断文件夹是否存在
  520. boost::filesystem::path p(m_RecordFile);
  521. if (!boost::filesystem::exists(p))
  522. {
  523. boost::filesystem::create_directories(p);
  524. }
  525. std::stringstream ss;
  526. ss << m_RecordFile << pChan->no() << "/" << strTempCallID;
  527. if (CConfig::GetInstance()->isVideo()) {
  528. ss << ".mp4";
  529. }
  530. else {
  531. ss << ".wav";
  532. }
  533. m_RecordFile = ss.str();
  534. }
  535. }
  536. void Session::__onLineTalking(VirtualChan * pChan)
  537. {
  538. // 如果是监听 不再产生录音文件文件路径
  539. //if (pChan->currOp() == PDU_CMD_AGENT_MONI_LISTEN) return;
  540. // 对该线路进行录音处理
  541. if (pChan == NULL) return;
  542. if (pChan->type() != DEV_RES_TYPE_EXT) return;
  543. if (pChan->recordFile() != "") return ;
  544. if (m_RecordFile.empty() || m_RecordFile == "")
  545. {
  546. __createFileName(pChan);
  547. LineOpParam LineOpInfo;
  548. memset(&LineOpInfo, 0, sizeof(LineOpInfo));
  549. LineOpInfo.szParam3 = m_RecordFile;
  550. COperationReactor::GetInstance()->procOperation(-1, LINE_OP_RECORD, pChan->no(), &LineOpInfo); // 执行录音
  551. pChan->setRecordFile(m_RecordFile);
  552. for (auto pTempChan : m_ListChan)
  553. {
  554. if (pTempChan != NULL && pTempChan->type() != pChan->type() && pTempChan->recordFile() == "")
  555. pTempChan->setRecordFile(m_RecordFile);
  556. }
  557. }
  558. else
  559. {
  560. pChan->setRecordFile(m_RecordFile);
  561. }
  562. }