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

VoipChannel.cpp 80KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494
  1. #include "StdAfx.h"
  2. #include "VoipChannel.h"
  3. #include "ControlShell.h"
  4. #include "Config.h"
  5. #include "MC.h"
  6. #include "ProxyShell.h"
  7. #include "ProxyExten.h"
  8. #include "IpmChannel.h"
  9. #include "DspChannel.h"
  10. #include "SessionShell.h"
  11. CVoipChannel::CImplement4Trunk CVoipChannel::ms_Implement4Trunk;
  12. CVoipChannel::CImplement4Exten CVoipChannel::ms_Implement4Exten;
  13. /*****************************************************************
  14. **【函数名称】 __constructMakeCallBody
  15. **【函数功能】 构造呼叫SIP协议体
  16. **【参数】
  17. **【返回值】
  18. ****************************************************************/
  19. void CVoipChannel::CImplement4Trunk::__constructMakeCallBody( GCPARAMEX_MAKECALL* pMakeCallEx, CVoipChannel& Chan, CIpmChannel* pImpChan, SIP_ACCOUNT* pAccount )
  20. {
  21. ASSERT(pImpChan != NULL);
  22. int nIndex;
  23. pMakeCallEx->Protocol = eGCPro_SIP;
  24. #pragma region To,From,contact,Auth
  25. pMakeCallEx->u.SIPInviteExReq.To.Valid = 1;
  26. pMakeCallEx->u.SIPInviteExReq.From.Valid = 1;
  27. ISXSIP_IE_ADDR* pMakeCallTo = &pMakeCallEx->u.SIPInviteExReq.To.Addr;
  28. ISXSIP_IE_ADDR* pMakeCallFrom = &pMakeCallEx->u.SIPInviteExReq.From.Addr;
  29. //TO域
  30. pMakeCallTo->Valid = 1;
  31. pMakeCallTo->AddType= ISXSIP_ADDTYPE_URL;
  32. pMakeCallTo->u.AddrUrl.PortNum = pAccount->ProxyPort;
  33. pMakeCallTo->u.AddrUrl.Ttl = 0xFFFF;
  34. pMakeCallTo->u.AddrUrl.LrType = 0xFF;
  35. pMakeCallTo->u.AddrUrl.MethodType = 0xFF;
  36. lstrcpy(pMakeCallTo->u.AddrUrl.User, Chan.m_CalleeNum);
  37. lstrcpy(pMakeCallTo->u.AddrUrl.Host, pAccount->Proxy);
  38. //FROM域
  39. pMakeCallFrom->Valid = 1;
  40. pMakeCallFrom->AddType = ISXSIP_ADDTYPE_URL;
  41. pMakeCallFrom->u.AddrUrl.PortNum = 0xFFFF;
  42. pMakeCallFrom->u.AddrUrl.Ttl = 0xFFFF;
  43. pMakeCallFrom->u.AddrUrl.LrType = 0xFF;
  44. pMakeCallFrom->u.AddrUrl.MethodType = 0xFF;
  45. lstrcpy(pMakeCallFrom->u.AddrUrl.User, Chan.m_CallerNum);
  46. lstrcpy(pMakeCallFrom->u.AddrUrl.Host, pAccount->Proxy);
  47. // CONTACT域
  48. ISXSIP_IE_REFERRED_BY *pReferBy = &pMakeCallEx->u.SIPInviteExReq.RefBy;
  49. pReferBy->Valid = 2;
  50. ISXSIP_IE_ADDR_EX *pContact = &pReferBy->cont_ruri.Contact;
  51. pContact->AddType = ISXSIP_ADDTYPE_URL;
  52. ISX_sr_default(PARMID_ISXSIP_ADDR_URL_EX, &pContact->u.AddrUrl);
  53. lstrcpy(pContact->u.AddrUrl.User, pAccount->Account);
  54. lstrcpy(pContact->u.AddrUrl.Host, CConfig::voipSignallingAddr());
  55. ISXSIP_IE_ADDR_EX *pRequestURI = &pReferBy->cont_ruri.RequestURI;
  56. pRequestURI->AddType = ISXSIP_ADDTYPE_URL;
  57. ISX_sr_default(PARMID_ISXSIP_ADDR_URL_EX, &pRequestURI->u.AddrUrl);
  58. lstrcpy(pRequestURI->u.AddrUrl.User, Chan.m_CalleeNum);
  59. lstrcpy(pRequestURI->u.AddrUrl.Host, pAccount->Proxy);
  60. //Auth
  61. char* pUser = pMakeCallEx->u.SIPInviteExReq.LongAuthInfo.AuthStr;
  62. ZeroMemory(pUser, 100);
  63. lstrcpy(pUser, pAccount->AuthAccount);
  64. char *pPwd = pUser + strlen(pUser) + 1;
  65. lstrcpy(pPwd, pAccount->Password);
  66. #pragma endregion
  67. #pragma region Media Part
  68. TCHAR MediaAddr[MAX_PATH] = { 0 };
  69. getMediaAddr(pImpChan, MediaAddr);
  70. pMakeCallEx->u.SIPInviteExReq.Body.Valid = 1;
  71. pMakeCallEx->u.SIPInviteExReq.Body.BodyPartyType = BodyPartyType_SDP;
  72. ISXSIP_IE_BODY_SDP_EX* pSdp = &pMakeCallEx->u.SIPInviteExReq.Body.u.BodySdp;
  73. pSdp->SdpNum = 0;
  74. //o
  75. nIndex = pSdp->SdpNum;
  76. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ORIGIN;
  77. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_ORIGIN);
  78. pSdp->Sdp[nIndex].u.Origin.NetType = ISXSIP_SDPNETTYPE_IN;
  79. pSdp->Sdp[nIndex].u.Origin.AddrType = ISXSIP_SDPADDRTYPE_IP4;
  80. lstrcpy(pSdp->Sdp[nIndex].u.Origin.SessionId, "20");
  81. lstrcpy(pSdp->Sdp[nIndex].u.Origin.UserName, "EHang");
  82. lstrcpy(pSdp->Sdp[nIndex].u.Origin.Version, "001");
  83. lstrcpy(pSdp->Sdp[nIndex].u.Origin.Addr, MediaAddr);
  84. pSdp->SdpNum++;
  85. //s
  86. nIndex = pSdp->SdpNum;
  87. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION;
  88. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION);
  89. lstrcpy(pSdp->Sdp[nIndex].u.Session.Name, "EH-Call");
  90. lstrcpy(pSdp->Sdp[nIndex].u.Session.Info, "");
  91. pSdp->SdpNum++;
  92. //c
  93. nIndex = pSdp->SdpNum;
  94. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONNECTION;
  95. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_CONNECTION);
  96. pSdp->Sdp[nIndex].u.Connection.NetType = ISXSIP_SDPNETTYPE_IN;
  97. pSdp->Sdp[nIndex].u.Connection.AddrType = ISXSIP_SDPADDRTYPE_IP4;
  98. lstrcpy(pSdp->Sdp[nIndex].u.Connection.Addr, MediaAddr);
  99. pSdp->SdpNum++;
  100. //t
  101. nIndex = pSdp->SdpNum;
  102. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION_TIME;
  103. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION_TIME);
  104. pSdp->Sdp[nIndex].u.SessionTime.Start = 0;
  105. pSdp->Sdp[nIndex].u.SessionTime.End = 0;
  106. pSdp->SdpNum++;
  107. //m
  108. int iCodecId;
  109. int iPayLoad;
  110. ISXSIP_IE_SDP_MEDIA_DESC_EX DspMediaDescEx;
  111. DspMediaDescEx.MediaPort = pImpChan->mediaPort();
  112. DspMediaDescEx.MediaProtocol = ISXSIP_SDPPROTOCOL_RTP;
  113. DspMediaDescEx.MediaType = ISXSIP_SDPMEDIATYPE_AUDIO;
  114. int iPLIndex = 0;
  115. iCodecId = AudioCodec_G711_ALAW_20MS;
  116. ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &iCodecId);
  117. DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
  118. iCodecId = AudioCodec_G729_20MS;
  119. ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &iCodecId);
  120. DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
  121. DspMediaDescEx.Payload[iPLIndex++] = 101;
  122. DspMediaDescEx.PayLoadNum = iPLIndex;
  123. ISX_sr_insertparm(&pMakeCallEx->u.SIPInviteExReq.Body, SIPPARMID_MEDIADESC, sizeof(DspMediaDescEx), &DspMediaDescEx);
  124. IP_AUDIO_CAPABILITY AudioCodec;
  125. AudioCodec.iCodecId = AudioCodec_G711_ALAW_20MS;
  126. ISX_sr_insertparm(&pMakeCallEx->u.SIPInviteExReq.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
  127. AudioCodec.iCodecId = AudioCodec_G729_20MS;
  128. ISX_sr_insertparm(&pMakeCallEx->u.SIPInviteExReq.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
  129. //a
  130. nIndex = pSdp->SdpNum;
  131. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_RTP_MAP;
  132. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_RTP_MAP);
  133. ISXSIP_IE_SDP_RTP_MAP* pSdpRtpMap = &pSdp->Sdp[nIndex].u.RtpMap;
  134. pSdpRtpMap->Payload = 101;
  135. pSdpRtpMap->ClkRate = 8000;
  136. lstrcpy(pSdpRtpMap->EncodingName, "telephone-event");
  137. lstrcpy(pSdpRtpMap->EncodingParam, "1");
  138. pSdp->SdpNum++;
  139. //a
  140. nIndex = pSdp->SdpNum;
  141. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  142. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  143. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "fmtp");
  144. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "101 0-15");
  145. pSdp->SdpNum++;
  146. //a
  147. nIndex = pSdp->SdpNum;
  148. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  149. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  150. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "ptime");
  151. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "20");
  152. pSdp->SdpNum++;
  153. #pragma endregion
  154. }
  155. /*****************************************************************
  156. **【函数名称】 __onOffered
  157. **【函数功能】 处理来电呼叫
  158. **【参数】
  159. **【返回值】
  160. ****************************************************************/
  161. void CVoipChannel::CImplement4Trunk::onOffered( CVoipChannel& Chan, GCPARAMEX_MAKECALL* pMakeCallEx )
  162. {
  163. CSessionShell::GetInstance().onLineStateChanged(Chan.m_Id, Chan.m_SessionCode, VIRTUAL_LINE_STATE_ALERTING, Chan.m_CallerNum, Chan.m_CalleeNum);
  164. //发送TRY
  165. ISX_gc_SIPSendTrying(Chan.m_CallId, EV_ASYNC);
  166. //check tel res 2018.4.9
  167. char t_callee[32] = { 0 };
  168. strncpy(t_callee, Chan.m_CalleeNum.GetBuffer(0), 31);
  169. bool t_b_ResExist = CConfig::isContainsExten(t_callee);
  170. if (t_b_ResExist) {
  171. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理中继来电,被叫号码资源存在 Caller = %s, Callee = %s"),
  172. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, t_callee);
  173. }
  174. else {
  175. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理中继来电,被叫号码资源不存在 Caller = %s, Callee = %s"),
  176. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, t_callee);
  177. //Chan.__clearCall(IPEC_SIPReasonStatus488NotAcceptableHere);
  178. }
  179. //
  180. ASSERT(Chan.m_pBindIpmCh == NULL);
  181. if((Chan.m_pBindIpmCh = CMC::GetInstance().allocIpmCh4SipCh(Chan.m_Id.NodeNo, Chan.m_Id.BoardNo)) == NULL)
  182. {
  183. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理中继来电出错, 无可用的IPM资源, 呼叫将释放, Caller = %s, Callee = %s"),
  184. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  185. Chan.__clearCall(IPEC_SIPReasonStatus486BusyHere);
  186. return;
  187. }
  188. Chan.m_pBindIpmCh->bind(&Chan);
  189. // 协商媒体编解码
  190. if(!Chan.__getCallMediaDesc(&pMakeCallEx->u.SIPInvite.Body))
  191. {
  192. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理中继来电时协商媒体编解码失败, 呼叫将释放, Caller = %s, Callee = %s"),
  193. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  194. Chan.__clearCall(IPEC_SIPReasonStatus415UnsupportedMediaType);
  195. return;
  196. }
  197. // 启动媒体
  198. if(!Chan.m_pBindIpmCh->isStarted())
  199. {
  200. if(!Chan.m_pBindIpmCh->startMedia())
  201. {
  202. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理中继来电时IPM资源启动失败, 呼叫将释放, Caller = %s, Callee = %s"),
  203. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  204. Chan.__clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  205. return;
  206. }
  207. }
  208. GCPARAMEX_ANSWERCALL AnswerCallEx;
  209. Chan.__constructAnswerBody(&AnswerCallEx);
  210. if(ISX_gc_AnswerCall(Chan.m_CallId, 0, EV_ASYNC, &AnswerCallEx) != 0)
  211. {
  212. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]应答中继来电失败, 呼叫将释放, Caller = %s, Callee = %s"),
  213. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  214. Chan.__clearCall(IPEC_SIPReasonStatus486BusyHere);
  215. }
  216. }
  217. /*****************************************************************
  218. **【函数名称】 onAlerting
  219. **【函数功能】 处理远端振铃
  220. **【参数】
  221. **【返回值】
  222. ****************************************************************/
  223. void CVoipChannel::CImplement4Trunk::onAlerting( CVoipChannel& Chan, METAEVENT* pMetaEvent )
  224. {
  225. GCPARAMEX_ACCEPTCALL* pAcceptCall = (GCPARAMEX_ACCEPTCALL*)ISX_sr_getevtdatap();
  226. ASSERT(pAcceptCall != NULL);
  227. if(pAcceptCall->u.SIPRing.Body.Valid == 1)
  228. {
  229. // 协商媒体编解码
  230. if(!Chan.__getCallMediaDesc(&pAcceptCall->u.SIPRing.Body))
  231. {
  232. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理Alerting时协商媒体编解码失败, 呼叫将释放, Caller = %s, Callee = %s"),
  233. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  234. Chan.__clearCall(IPEC_SIPReasonStatus415UnsupportedMediaType);
  235. return;
  236. }
  237. // 启动媒体
  238. ASSERT(Chan.m_pBindIpmCh != NULL);
  239. if(!Chan.m_pBindIpmCh->isStarted())
  240. {
  241. if(!Chan.m_pBindIpmCh->startMedia())
  242. {
  243. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理Alerting时IPM资源启动失败, 呼叫将释放, Caller = %s, Callee = %s"),
  244. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  245. Chan.__clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  246. return;
  247. }
  248. }
  249. CSessionShell::GetInstance().onLineStateChanged(Chan.m_Id, Chan.m_SessionCode, VIRTUAL_LINE_STATE_PROGRESSING, Chan.m_CallerNum, Chan.m_CalleeNum);
  250. }
  251. CSessionShell::GetInstance().onLineStateChanged(Chan.m_Id, Chan.m_SessionCode, VIRTUAL_LINE_STATE_RING_BACK, Chan.m_CallerNum, Chan.m_CalleeNum);
  252. }
  253. /*****************************************************************
  254. **【函数名称】 makeCall
  255. **【函数功能】 呼叫
  256. **【参数】
  257. **【返回值】 成功true,失败false
  258. ****************************************************************/
  259. bool CVoipChannel::CImplement4Trunk::makeCall( CVoipChannel& Chan, int AccountId )
  260. {
  261. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]中继模式下执行呼叫请求, caller = %s, callee = %s"),
  262. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  263. SIP_ACCOUNT* pAccount = CConfig::sipAccount().getAccount(AccountId);
  264. ASSERT(pAccount != NULL);
  265. if(pAccount == NULL)
  266. {
  267. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]进行中继呼叫时查找SIP账户[%d]失败, 呼叫将释放, Caller = %s, Callee = %s"),
  268. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, AccountId, Chan.m_CallerNum, Chan.m_CalleeNum);
  269. return false;
  270. }
  271. ASSERT(Chan.m_pBindIpmCh == NULL);
  272. if((Chan.m_pBindIpmCh = CMC::GetInstance().allocIpmCh4SipCh(Chan.m_Id.NodeNo, Chan.m_Id.BoardNo)) == NULL)
  273. {
  274. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]进行中继呼叫时分配IPM资源失败, 呼叫将释放, Caller = %s, Callee = %s"),
  275. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  276. return false;
  277. }
  278. Chan.m_pBindIpmCh->bind(&Chan);
  279. GCPARAMEX_MAKECALL MakeCallEx;
  280. ISX_sr_default(PARMID_SIP_INVITE, &MakeCallEx.u.SIPInviteExReq);
  281. __constructMakeCallBody(&MakeCallEx, Chan, Chan.m_pBindIpmCh, pAccount);
  282. return ISXE_gc_MakeCall(Chan.m_Handle, &Chan.m_CallId, NULL, NULL, -1, EV_ASYNC, &MakeCallEx) == 0;
  283. }
  284. /*****************************************************************
  285. **【函数名称】 getMediaAddr
  286. **【函数功能】 获取媒体地址
  287. **【参数】
  288. **【返回值】
  289. ****************************************************************/
  290. void CVoipChannel::CImplement4Trunk::getMediaAddr( CIpmChannel* pImpChan, LPTSTR Buffer )
  291. {
  292. ASSERT(pImpChan != NULL);
  293. pImpChan->mediaAddrTrunk(Buffer);
  294. }
  295. /*****************************************************************
  296. **【函数名称】 __constructMakeCallBody
  297. **【函数功能】 构造呼叫SIP协议体
  298. **【参数】
  299. **【返回值】
  300. ****************************************************************/
  301. void CVoipChannel::CImplement4Exten::__constructMakeCallBody( GCPARAMEX_MAKECALL* pMakeCallEx, CIpmChannel* pImpChan )
  302. {
  303. ASSERT(pImpChan != NULL);
  304. TCHAR MediaAddr[MAX_PATH] = { 0 };
  305. getMediaAddr(pImpChan, MediaAddr);
  306. int nIndex;
  307. pMakeCallEx->Protocol = eGCPro_SIP;
  308. pMakeCallEx->u.SIPInvite.Body.Valid = 1;
  309. pMakeCallEx->u.SIPInvite.Body.BodyPartyType = BodyPartyType_SDP;
  310. ISXSIP_IE_BODY_SDP_EX* pSdp = &pMakeCallEx->u.SIPInvite.Body.u.BodySdp;
  311. pSdp->SdpNum = 0;
  312. //o
  313. nIndex = pSdp->SdpNum;
  314. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ORIGIN;
  315. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_ORIGIN);
  316. pSdp->Sdp[nIndex].u.Origin.NetType = ISXSIP_SDPNETTYPE_IN;
  317. pSdp->Sdp[nIndex].u.Origin.AddrType = ISXSIP_SDPADDRTYPE_IP4;
  318. lstrcpy(pSdp->Sdp[nIndex].u.Origin.SessionId, "20");
  319. lstrcpy(pSdp->Sdp[nIndex].u.Origin.UserName, "EHang");
  320. lstrcpy(pSdp->Sdp[nIndex].u.Origin.Version, "001");
  321. lstrcpy(pSdp->Sdp[nIndex].u.Origin.Addr, MediaAddr);
  322. pSdp->SdpNum++;
  323. //s
  324. nIndex = pSdp->SdpNum;
  325. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION;
  326. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION);
  327. lstrcpy(pSdp->Sdp[nIndex].u.Session.Name, "EH-Call");
  328. lstrcpy(pSdp->Sdp[nIndex].u.Session.Info, "");
  329. pSdp->SdpNum++;
  330. //c
  331. nIndex = pSdp->SdpNum;
  332. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONNECTION;
  333. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_CONNECTION);
  334. pSdp->Sdp[nIndex].u.Connection.NetType = ISXSIP_SDPNETTYPE_IN;
  335. pSdp->Sdp[nIndex].u.Connection.AddrType = ISXSIP_SDPADDRTYPE_IP4;
  336. sprintf_s(pSdp->Sdp[nIndex].u.Connection.Addr, 32, MediaAddr);
  337. pSdp->SdpNum++;
  338. //t
  339. nIndex = pSdp->SdpNum;
  340. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION_TIME;
  341. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION_TIME);
  342. pSdp->Sdp[nIndex].u.SessionTime.Start = 0;
  343. pSdp->Sdp[nIndex].u.SessionTime.End = 0;
  344. pSdp->SdpNum++;
  345. //m
  346. int iCodecId;
  347. int iPayLoad;
  348. ISXSIP_IE_SDP_MEDIA_DESC_EX DspMediaDescEx;
  349. DspMediaDescEx.MediaPort = pImpChan->mediaPort();
  350. DspMediaDescEx.MediaProtocol = ISXSIP_SDPPROTOCOL_RTP;
  351. DspMediaDescEx.MediaType = ISXSIP_SDPMEDIATYPE_AUDIO;
  352. int iPLIndex = 0;
  353. iCodecId = AudioCodec_G711_ALAW_20MS;
  354. ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &iCodecId);
  355. DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
  356. iCodecId = AudioCodec_G729_20MS;
  357. ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &iCodecId);
  358. DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
  359. DspMediaDescEx.Payload[iPLIndex++] = 101;
  360. DspMediaDescEx.PayLoadNum = iPLIndex;
  361. ISX_sr_insertparm(&pMakeCallEx->u.SIPInvite.Body, SIPPARMID_MEDIADESC, sizeof(DspMediaDescEx), &DspMediaDescEx);
  362. IP_AUDIO_CAPABILITY AudioCodec;
  363. AudioCodec.iCodecId = AudioCodec_G711_ALAW_20MS;
  364. ISX_sr_insertparm(&pMakeCallEx->u.SIPInvite.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
  365. AudioCodec.iCodecId = AudioCodec_G729_20MS;
  366. ISX_sr_insertparm(&pMakeCallEx->u.SIPInvite.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
  367. //a
  368. nIndex = pSdp->SdpNum;
  369. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_RTP_MAP;
  370. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_RTP_MAP);
  371. ISXSIP_IE_SDP_RTP_MAP* pSdpRtpMap = &pSdp->Sdp[nIndex].u.RtpMap;
  372. pSdpRtpMap->Payload = 101;
  373. pSdpRtpMap->ClkRate = 8000;
  374. lstrcpy(pSdpRtpMap->EncodingName, "telephone-event");
  375. lstrcpy(pSdpRtpMap->EncodingParam, "1");
  376. pSdp->SdpNum++;
  377. //a
  378. nIndex = pSdp->SdpNum;
  379. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  380. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  381. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "fmtp");
  382. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "101 0-15");
  383. pSdp->SdpNum++;
  384. //a
  385. nIndex = pSdp->SdpNum;
  386. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  387. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  388. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "ptime");
  389. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "20");
  390. pSdp->SdpNum++;
  391. }
  392. /*****************************************************************
  393. **【函数名称】 __onOffered
  394. **【函数功能】 处理来电呼叫
  395. **【参数】
  396. **【返回值】
  397. ****************************************************************/
  398. void CVoipChannel::CImplement4Exten::onOffered( CVoipChannel& Chan, GCPARAMEX_MAKECALL* pMakeCallEx )
  399. {
  400. //发送TRY
  401. ISX_gc_SIPSendTrying(Chan.m_CallId, EV_ASYNC);
  402. //check tel res 2018.4.9
  403. char t_callee[32] = { 0 };
  404. strncpy(t_callee, Chan.m_CalleeNum.GetBuffer(0), 31);
  405. bool t_b_ResExist = CConfig::isContainsExten(t_callee);
  406. if (t_b_ResExist) {
  407. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理分机来电,被叫号码资源存在 Caller = %s, Callee = %s"),
  408. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, t_callee);
  409. }
  410. else {
  411. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理分机来电,被叫号码资源不存在 Caller = %s, Callee = %s"),
  412. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, t_callee);
  413. //Chan.__clearCall(IPEC_SIPReasonStatus488NotAcceptableHere);
  414. }
  415. //
  416. Chan.m_ExtenNo = atoi(Chan.m_CallerNum);
  417. ASSERT(Chan.m_pBindIpmCh == NULL);
  418. if((Chan.m_pBindIpmCh = CMC::GetInstance().allocIpmCh4SipCh(Chan.m_Id.NodeNo, Chan.m_Id.BoardNo)) == NULL)
  419. {
  420. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理分机来电出错, 无可用的IPM资源, 呼叫将释放, Caller = %s, Callee = %s"),
  421. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  422. Chan.__clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  423. return;
  424. }
  425. Chan.m_pBindIpmCh->bind(&Chan);
  426. // 协商媒体编解码
  427. if(!Chan.__getCallMediaDesc(&pMakeCallEx->u.SIPInvite.Body))
  428. {
  429. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理分机来电时协商媒体编解码失败, 呼叫将释放, Caller = %s, Callee = %s"),
  430. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  431. Chan.__clearCall(IPEC_SIPReasonStatus415UnsupportedMediaType);
  432. return;
  433. }
  434. if(!CSessionShell::GetInstance().onLineChannelEvent(Chan.m_Id, Chan.m_SessionCode, DEV_CH_EVT_FUN_CODE, Chan.m_CalleeNum, Chan.m_ExtenNo))
  435. {
  436. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理座席分机来电失败, 呼叫将释放, Caller = %s, Callee = %s"),
  437. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  438. Chan.__clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  439. }
  440. }
  441. /*****************************************************************
  442. **【函数名称】 onAlerting
  443. **【函数功能】 处理远端振铃
  444. **【参数】
  445. **【返回值】
  446. ****************************************************************/
  447. void CVoipChannel::CImplement4Exten::onAlerting( CVoipChannel& Chan, METAEVENT* pMetaEvent )
  448. {
  449. if(Chan.m_Job == DEV_LINE_CH_JOB_NONE)
  450. CSessionShell::GetInstance().onLineStateChanged(Chan.m_Id, Chan.m_SessionCode, VIRTUAL_LINE_STATE_ALERTING, Chan.m_CallerNum, Chan.m_CalleeNum);
  451. }
  452. /*****************************************************************
  453. **【函数名称】 makeCall
  454. **【函数功能】 呼叫
  455. **【参数】
  456. **【返回值】 成功true,失败false
  457. ****************************************************************/
  458. bool CVoipChannel::CImplement4Exten::makeCall( CVoipChannel& Chan, int AccountId )
  459. {
  460. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]分机模式下执行呼叫请求, caller = %s, callee = %s"),
  461. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  462. ASSERT(Chan.m_pBindIpmCh == NULL);
  463. if((Chan.m_pBindIpmCh = CMC::GetInstance().allocIpmCh4SipCh(Chan.m_Id.NodeNo, Chan.m_Id.BoardNo)) == NULL)
  464. {
  465. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]进行分机呼叫时分配IPM资源失败, 呼叫将释放, Caller = %s, Callee = %s"),
  466. Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
  467. return false;
  468. }
  469. Chan.m_pBindIpmCh->bind(&Chan);
  470. TCHAR Callee[SIP_URI_LEN] = { 0 };
  471. TCHAR Caller[SIP_URI_LEN] = { 0 };
  472. TCHAR ProxyIp[MAX_PATH] = { 0 };
  473. Chan.__getVoipAddr(ProxyIp);
  474. Chan.m_ExtenNo = atoi(Chan.m_CalleeNum);
  475. Chan.__getExtenAddrInfo(Chan.m_CalleeNum, Callee, SIP_URI_LEN);
  476. sprintf_s(Caller, SIP_URI_LEN, _T("%s@%s\0"), Chan.m_CallerNum, ProxyIp);
  477. GCPARAMEX_MAKECALL MakeCallEx;
  478. ISX_sr_default(PARMID_SIP_INVITE, &MakeCallEx.u.SIPInvite);
  479. ISX_sr_setparm(&MakeCallEx.u.SIPInvite, SIPPARMID_DESTADD, strlen(Callee), Callee);
  480. ISX_sr_setparm(&MakeCallEx.u.SIPInvite, SIPPARMID_SRCADD, strlen(Caller), Caller);
  481. __constructMakeCallBody(&MakeCallEx, Chan.m_pBindIpmCh);
  482. return ISX_gc_MakeCall(Chan.m_Handle, &Chan.m_CallId, Callee, NULL, -1, EV_ASYNC, &MakeCallEx) == 0;
  483. }
  484. /*****************************************************************
  485. **【函数名称】 getMediaAddr
  486. **【函数功能】 获取媒体地址
  487. **【参数】
  488. **【返回值】
  489. ****************************************************************/
  490. void CVoipChannel::CImplement4Exten::getMediaAddr( CIpmChannel* pImpChan, LPTSTR Buffer )
  491. {
  492. ASSERT(pImpChan != NULL);
  493. pImpChan->mediaAddrBoard(Buffer);
  494. }
  495. CVoipChannel::CVoipChannel(DEV_RES_CH_TYPE ChannelNo, DEV_RES_NO_TYPE NodeNo, DEV_RES_NO_TYPE BoardNo)
  496. : CChannelResource(DEV_RES_TYPE_VOIP, NodeNo, BoardNo, DEVICE_RES_NO_ANY, ChannelNo), m_pImplement(NULL), m_CallId(0), m_IsBlocked(false),
  497. m_Job(DEV_LINE_CH_JOB_NONE), m_ExtenNo(0), m_Mixer(*this), m_pBindIpmCh(NULL), m_MediaPort(0), m_CodecId(-1)
  498. {
  499. }
  500. CVoipChannel::~CVoipChannel(void)
  501. {
  502. close();
  503. }
  504. /*****************************************************************
  505. **【函数名称】 __clearCall
  506. **【函数功能】 清除呼叫
  507. **【参数】
  508. **【返回值】
  509. ****************************************************************/
  510. bool CVoipChannel::__clearCall( int Cause )
  511. {
  512. if(m_CallId == 0)
  513. return false;
  514. m_State = GCST_DROPCALLING;
  515. if(m_MeetingInfo.MeetingId != MEETING_ID_INVALID)
  516. CMC::GetInstance().meetingRemove(this, m_MeetingInfo);
  517. m_Mixer.release();
  518. if(ISX_gc_DropCall(m_CallId, Cause, EV_ASYNC) == 0)
  519. {
  520. m_CallId = 0;
  521. return true;
  522. }
  523. else return false;
  524. }
  525. /*****************************************************************
  526. **【函数名称】 __getVoipAddr
  527. **【函数功能】 获取
  528. **【参数】
  529. **【返回值】 成功true,失败false
  530. ****************************************************************/
  531. bool CVoipChannel::__getVoipAddr( LPTSTR AddrBuf )
  532. {
  533. return ISX_sr_getnet2cfg(m_Id.NodeNo, m_Id.BoardNo, BT_SIP, AddrBuf, NULL) == 0;
  534. }
  535. /*****************************************************************
  536. **【函数名称】 __getExtenAddrInfo
  537. **【函数功能】 获取SIP分机地址信息
  538. **【参数】
  539. **【返回值】 成功true,失败false
  540. ****************************************************************/
  541. bool CVoipChannel::__getExtenAddrInfo( LPCTSTR Exten, LPTSTR pContactAddr, int Len )
  542. {
  543. ISXSIP_REGUSER RegUser;
  544. if(ISXE_gc_SipGetRegisterUser(Exten, &RegUser) == 0)
  545. {
  546. if(RegUser.PortNum != 0xffff && RegUser.PortNum != 0)
  547. sprintf_s(pContactAddr, Len, _T("%s@%s:%d\0"), Exten, RegUser.IpAddr, RegUser.PortNum);
  548. else
  549. sprintf_s(pContactAddr, Len, _T("%s@%s\0"), Exten, RegUser.IpAddr);
  550. return true;
  551. }
  552. return false;
  553. }
  554. /*****************************************************************
  555. **【函数名称】 __constructAnswerBody
  556. **【函数功能】 构造应答SIP协议体
  557. **【参数】
  558. **【返回值】
  559. ****************************************************************/
  560. void CVoipChannel::__constructAnswerBody( GCPARAMEX_ANSWERCALL* pAnswerCallEx )
  561. {
  562. memset(pAnswerCallEx, 0, sizeof(*pAnswerCallEx));
  563. pAnswerCallEx->Protocol = eGCPro_SIP;
  564. pAnswerCallEx->u.SIPConn.Body.Valid = 1;
  565. pAnswerCallEx->u.SIPConn.Body.BodyPartyType = BodyPartyType_SDP;
  566. ISXSIP_IE_BODY_SDP_EX* pSdp = &pAnswerCallEx->u.SIPConn.Body.u.BodySdp;
  567. pSdp->SdpNum = 0;
  568. TCHAR MediaAddr[MAX_PATH] = { 0 };
  569. ASSERT(m_pBindIpmCh != NULL);
  570. m_pImplement->getMediaAddr(m_pBindIpmCh, MediaAddr);
  571. //o
  572. int nIndex = pSdp->SdpNum;
  573. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ORIGIN;
  574. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_ORIGIN);
  575. pSdp->Sdp[nIndex].u.Origin.NetType = ISXSIP_SDPNETTYPE_IN;
  576. pSdp->Sdp[nIndex].u.Origin.AddrType = ISXSIP_SDPADDRTYPE_IP4;
  577. lstrcpy(pSdp->Sdp[nIndex].u.Origin.SessionId, "20");
  578. lstrcpy(pSdp->Sdp[nIndex].u.Origin.UserName, "EHang");
  579. lstrcpy(pSdp->Sdp[nIndex].u.Origin.Version, "001");
  580. lstrcpy(pSdp->Sdp[nIndex].u.Origin.Addr, MediaAddr);
  581. pSdp->SdpNum++;
  582. //s
  583. nIndex = pSdp->SdpNum;
  584. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION;
  585. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION);
  586. lstrcpy(pSdp->Sdp[nIndex].u.Session.Name, "EH-Call");
  587. lstrcpy(pSdp->Sdp[nIndex].u.Session.Info, "");
  588. pSdp->SdpNum++;
  589. //c
  590. nIndex = pSdp->SdpNum;
  591. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONNECTION;
  592. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_CONNECTION);
  593. pSdp->Sdp[nIndex].u.Connection.NetType = ISXSIP_SDPNETTYPE_IN;
  594. pSdp->Sdp[nIndex].u.Connection.AddrType = ISXSIP_SDPADDRTYPE_IP4;
  595. lstrcpy(pSdp->Sdp[nIndex].u.Connection.Addr, MediaAddr);
  596. pSdp->SdpNum++;
  597. //t
  598. nIndex = pSdp->SdpNum;
  599. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION_TIME;
  600. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION_TIME);
  601. pSdp->Sdp[nIndex].u.SessionTime.Start = 0;
  602. pSdp->Sdp[nIndex].u.SessionTime.End = 0;
  603. pSdp->SdpNum++;
  604. //m
  605. ISXSIP_IE_SDP_MEDIA_DESC_EX DspMediaDescEx;
  606. DspMediaDescEx.MediaPort = m_pBindIpmCh->mediaPort();
  607. DspMediaDescEx.MediaProtocol = ISXSIP_SDPPROTOCOL_RTP;
  608. DspMediaDescEx.MediaType = ISXSIP_SDPMEDIATYPE_AUDIO;
  609. int iPLIndex = 0;
  610. int nPayLoad = 0;
  611. ISX_sr_convert(CONID_CODECID2PLAYLOAD, &nPayLoad, &m_CodecId);
  612. DspMediaDescEx.Payload[iPLIndex++] = nPayLoad;
  613. DspMediaDescEx.Payload[iPLIndex++] = 101;
  614. DspMediaDescEx.PayLoadNum = iPLIndex;
  615. ISX_sr_insertparm(&pAnswerCallEx->u.SIPConn.Body, SIPPARMID_MEDIADESC, sizeof(DspMediaDescEx), &DspMediaDescEx);
  616. IP_AUDIO_CAPABILITY AudioCodec;
  617. AudioCodec.iCodecId = (eAUDIOCODEC)m_CodecId;
  618. ISX_sr_insertparm(&pAnswerCallEx->u.SIPConn.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
  619. //a
  620. nIndex = pSdp->SdpNum;
  621. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_RTP_MAP;
  622. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_RTP_MAP);
  623. ISXSIP_IE_SDP_RTP_MAP* pSdpRtpMap = &pSdp->Sdp[nIndex].u.RtpMap;
  624. pSdpRtpMap->Payload = 101;
  625. pSdpRtpMap->ClkRate = 8000;
  626. lstrcpy(pSdpRtpMap->EncodingName, "telephone-event");
  627. lstrcpy(pSdpRtpMap->EncodingParam, "1");
  628. pSdp->SdpNum++;
  629. //a
  630. nIndex = pSdp->SdpNum;
  631. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  632. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  633. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "fmtp");
  634. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "101 0-15");
  635. pSdp->SdpNum++;
  636. //a
  637. nIndex = pSdp->SdpNum;
  638. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  639. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  640. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "ptime");
  641. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "20");
  642. pSdp->SdpNum++;
  643. }
  644. /*****************************************************************
  645. **【函数名称】 __constructProgressBody
  646. **【函数功能】 构造呼叫进展SIP协议体
  647. **【参数】
  648. **【返回值】
  649. ****************************************************************/
  650. void CVoipChannel::__constructProgressBody( GCPARAMEX_CALLPROGRESS* pProgressEx )
  651. {
  652. memset(pProgressEx, 0, sizeof(*pProgressEx));
  653. pProgressEx->Protocol = eGCPro_SIP;
  654. pProgressEx->u.SIPProgress.Body.Valid = 1;
  655. pProgressEx->u.SIPProgress.Body.BodyPartyType = BodyPartyType_SDP;
  656. ISXSIP_IE_BODY_SDP_EX* pSdp = &pProgressEx->u.SIPProgress.Body.u.BodySdp;
  657. pSdp->SdpNum = 0;
  658. TCHAR MediaAddr[MAX_PATH] = { 0 };
  659. ASSERT(m_pBindIpmCh != NULL);
  660. m_pImplement->getMediaAddr(m_pBindIpmCh, MediaAddr);
  661. int nIndex;
  662. //o
  663. nIndex = pSdp->SdpNum;
  664. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ORIGIN;
  665. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_ORIGIN);
  666. pSdp->Sdp[nIndex].u.Origin.NetType = ISXSIP_SDPNETTYPE_IN;
  667. pSdp->Sdp[nIndex].u.Origin.AddrType = ISXSIP_SDPADDRTYPE_IP4;
  668. lstrcpy(pSdp->Sdp[nIndex].u.Origin.SessionId, "20");
  669. lstrcpy(pSdp->Sdp[nIndex].u.Origin.UserName, "EHang");
  670. lstrcpy(pSdp->Sdp[nIndex].u.Origin.Version, "001");
  671. lstrcpy(pSdp->Sdp[nIndex].u.Origin.Addr, MediaAddr);
  672. pSdp->SdpNum++;
  673. //s
  674. nIndex = pSdp->SdpNum;
  675. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION;
  676. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION);
  677. lstrcpy(pSdp->Sdp[nIndex].u.Session.Name, "EH-Call");
  678. lstrcpy(pSdp->Sdp[nIndex].u.Session.Info, "");
  679. pSdp->SdpNum++;
  680. //c
  681. nIndex = pSdp->SdpNum;
  682. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONNECTION;
  683. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_CONNECTION);
  684. pSdp->Sdp[nIndex].u.Connection.NetType = ISXSIP_SDPNETTYPE_IN;
  685. pSdp->Sdp[nIndex].u.Connection.AddrType = ISXSIP_SDPADDRTYPE_IP4;
  686. lstrcpy(pSdp->Sdp[nIndex].u.Connection.Addr, MediaAddr);
  687. pSdp->SdpNum++;
  688. //t
  689. nIndex = pSdp->SdpNum;
  690. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION_TIME;
  691. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION_TIME);
  692. pSdp->Sdp[nIndex].u.SessionTime.Start = 0;
  693. pSdp->Sdp[nIndex].u.SessionTime.End = 0;
  694. pSdp->SdpNum++;
  695. //m
  696. ISXSIP_IE_SDP_MEDIA_DESC_EX DspMediaDescEx;
  697. DspMediaDescEx.MediaPort = m_pBindIpmCh->mediaPort();
  698. DspMediaDescEx.MediaProtocol = ISXSIP_SDPPROTOCOL_RTP;
  699. DspMediaDescEx.MediaType = ISXSIP_SDPMEDIATYPE_AUDIO;
  700. int iPLIndex = 0;
  701. int iPayLoad = 0;
  702. if(m_CodecId != -1)
  703. {
  704. ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &m_CodecId);
  705. DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
  706. }
  707. else
  708. {
  709. int iCodecId = AudioCodec_G711_ALAW_20MS;
  710. ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &iCodecId);
  711. DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
  712. iCodecId = AudioCodec_G729_20MS;
  713. ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &iCodecId);
  714. DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
  715. }
  716. DspMediaDescEx.Payload[iPLIndex++] = 101;
  717. DspMediaDescEx.PayLoadNum = iPLIndex;
  718. ISX_sr_insertparm(&pProgressEx->u.SIPProgress.Body, SIPPARMID_MEDIADESC, sizeof(DspMediaDescEx), &DspMediaDescEx);
  719. IP_AUDIO_CAPABILITY AudioCodec;
  720. if(m_CodecId != -1)
  721. {
  722. AudioCodec.iCodecId = (eAUDIOCODEC)m_CodecId;
  723. ISX_sr_insertparm(&pProgressEx->u.SIPProgress.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
  724. }
  725. else
  726. {
  727. AudioCodec.iCodecId = AudioCodec_G711_ALAW_20MS;
  728. ISX_sr_insertparm(&pProgressEx->u.SIPProgress.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
  729. AudioCodec.iCodecId = AudioCodec_G729_20MS;
  730. ISX_sr_insertparm(&pProgressEx->u.SIPProgress.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
  731. }
  732. //a
  733. nIndex = pSdp->SdpNum;
  734. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_RTP_MAP;
  735. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_RTP_MAP);
  736. ISXSIP_IE_SDP_RTP_MAP* pSdpRtpMap = &pSdp->Sdp[nIndex].u.RtpMap;
  737. pSdpRtpMap->Payload = 101;
  738. pSdpRtpMap->ClkRate = 8000;
  739. lstrcpy(pSdpRtpMap->EncodingName, "telephone-event");
  740. lstrcpy(pSdpRtpMap->EncodingParam, "1");
  741. pSdp->SdpNum++;
  742. //a
  743. nIndex = pSdp->SdpNum;
  744. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  745. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  746. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "fmtp");
  747. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "101 0-15");
  748. pSdp->SdpNum++;
  749. //a
  750. nIndex = pSdp->SdpNum;
  751. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  752. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  753. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "ptime");
  754. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "20");
  755. pSdp->SdpNum++;
  756. }
  757. /*****************************************************************
  758. **【函数名称】 __constructReinviteBody4Hold
  759. **【函数功能】 构造ReinviteACK协议体
  760. **【参数】
  761. **【返回值】
  762. ****************************************************************/
  763. void CVoipChannel::__constructReinviteBody4Hold( ISXSIP_IE_BODY_EX* pBody, bool Hold )
  764. {
  765. pBody->Valid = 1;
  766. pBody->BodyPartyType = BodyPartyType_SDP;
  767. TCHAR MediaAddr[MAX_PATH] = { 0 };
  768. ASSERT(m_pBindIpmCh != NULL);
  769. m_pImplement->getMediaAddr(m_pBindIpmCh, MediaAddr);
  770. int nIndex;
  771. ISXSIP_IE_BODY_SDP_EX* pSdp = &pBody->u.BodySdp;
  772. pSdp->SdpNum = 0;
  773. //o
  774. nIndex = pSdp->SdpNum;
  775. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ORIGIN;
  776. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_ORIGIN);
  777. pSdp->Sdp[nIndex].u.Origin.NetType = ISXSIP_SDPNETTYPE_IN;
  778. pSdp->Sdp[nIndex].u.Origin.AddrType = ISXSIP_SDPADDRTYPE_IP4;
  779. lstrcpy(pSdp->Sdp[nIndex].u.Origin.SessionId, "20");
  780. lstrcpy(pSdp->Sdp[nIndex].u.Origin.UserName, "EHang");
  781. lstrcpy(pSdp->Sdp[nIndex].u.Origin.Version, "001");
  782. lstrcpy(pSdp->Sdp[nIndex].u.Origin.Addr, MediaAddr);
  783. pSdp->SdpNum++;
  784. //s
  785. nIndex = pSdp->SdpNum;
  786. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION;
  787. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION);
  788. lstrcpy(pSdp->Sdp[nIndex].u.Session.Name, "EH-Call");
  789. lstrcpy(pSdp->Sdp[nIndex].u.Session.Info, "");
  790. pSdp->SdpNum++;
  791. //c
  792. nIndex = pSdp->SdpNum;
  793. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONNECTION;
  794. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_CONNECTION);
  795. pSdp->Sdp[nIndex].u.Connection.NetType = ISXSIP_SDPNETTYPE_IN;
  796. pSdp->Sdp[nIndex].u.Connection.AddrType = ISXSIP_SDPADDRTYPE_IP4;
  797. lstrcpy(pSdp->Sdp[nIndex].u.Connection.Addr, MediaAddr);
  798. pSdp->SdpNum++;
  799. //t
  800. nIndex = pSdp->SdpNum;
  801. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION_TIME;
  802. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION_TIME);
  803. pSdp->Sdp[nIndex].u.SessionTime.Start = 0;
  804. pSdp->Sdp[nIndex].u.SessionTime.End = 0;
  805. pSdp->SdpNum++;
  806. //m
  807. int nPLIndex = 0;
  808. int nPayLoad;
  809. ISX_sr_convert(CONID_CODECID2PLAYLOAD, &nPayLoad, &m_CodecId);
  810. nIndex = pSdp->SdpNum;
  811. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_MEDIA_DESC;
  812. pSdp->Sdp[nIndex].u.MediaDesc.MediaPort = m_pBindIpmCh->mediaPort();
  813. pSdp->Sdp[nIndex].u.MediaDesc.MediaProtocol = ISXSIP_SDPPROTOCOL_RTP;
  814. pSdp->Sdp[nIndex].u.MediaDesc.MediaType = ISXSIP_SDPMEDIATYPE_AUDIO;
  815. pSdp->Sdp[nIndex].u.MediaDesc.Payload[nPLIndex++] = nPayLoad;
  816. pSdp->Sdp[nIndex].u.MediaDesc.Payload[nPLIndex++] = 101;
  817. pSdp->Sdp[nIndex].u.MediaDesc.PayLoadNum = nPLIndex;
  818. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_MEDIA_DESC) - 1 + pSdp->Sdp[nIndex].u.MediaDesc.PayLoadNum;
  819. pSdp->SdpNum++;
  820. // a
  821. nIndex = pSdp->SdpNum;
  822. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_RTP_MAP;
  823. pSdp->Sdp[nIndex].u.RtpMap.Payload = g_SipSdpRtpMap[m_CodecId].Payload;
  824. pSdp->Sdp[nIndex].u.RtpMap.ClkRate = g_SipSdpRtpMap[m_CodecId].ClkRate;
  825. lstrcpy(pSdp->Sdp[nIndex].u.RtpMap.EncodingName, g_SipSdpRtpMap[m_CodecId].EncodingName);
  826. lstrcpy(pSdp->Sdp[nIndex].u.RtpMap.EncodingParam, g_SipSdpRtpMap[m_CodecId].EncodingParam);
  827. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_RTP_MAP);
  828. pSdp->SdpNum++;
  829. //a
  830. nIndex = pSdp->SdpNum;
  831. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  832. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  833. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "fmtp");
  834. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "101 0-15");
  835. pSdp->SdpNum++;
  836. if(Hold)
  837. {
  838. // a
  839. nIndex = pSdp->SdpNum;
  840. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONN_MODE;
  841. pSdp->Sdp[nIndex].u.ConnMode.ConnMode = ISXSIP_SDPCONNECTMODE_RECVONLY;
  842. pSdp->SdpNum++;
  843. }
  844. //a
  845. nIndex = pSdp->SdpNum;
  846. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  847. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  848. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "ptime");
  849. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "20");
  850. pSdp->SdpNum++;
  851. }
  852. /*****************************************************************
  853. **【函数名称】 __constructReinviteBody4T38
  854. **【函数功能】 构造ReinviteACK协议体
  855. **【参数】
  856. **【返回值】
  857. ****************************************************************/
  858. void CVoipChannel::__constructReinviteBody4T38( ISXSIP_IE_BODY_EX* pBody )
  859. {
  860. pBody->Valid = 1;
  861. pBody->BodyPartyType = BodyPartyType_SDP;
  862. TCHAR MediaAddr[MAX_PATH] = { 0 };
  863. ASSERT(m_pBindIpmCh != NULL);
  864. m_pImplement->getMediaAddr(m_pBindIpmCh, MediaAddr);
  865. int nIndex;
  866. ISXSIP_IE_BODY_SDP_EX* pSdp = &pBody->u.BodySdp;
  867. pSdp->SdpNum = 0;
  868. //o
  869. nIndex = pSdp->SdpNum;
  870. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ORIGIN;
  871. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_ORIGIN);
  872. pSdp->Sdp[nIndex].u.Origin.NetType = ISXSIP_SDPNETTYPE_IN;
  873. pSdp->Sdp[nIndex].u.Origin.AddrType = ISXSIP_SDPADDRTYPE_IP4;
  874. lstrcpy(pSdp->Sdp[nIndex].u.Origin.SessionId, "20");
  875. lstrcpy(pSdp->Sdp[nIndex].u.Origin.UserName, "EHang");
  876. lstrcpy(pSdp->Sdp[nIndex].u.Origin.Version, "001");
  877. lstrcpy(pSdp->Sdp[nIndex].u.Origin.Addr, MediaAddr);
  878. pSdp->SdpNum++;
  879. //s
  880. nIndex = pSdp->SdpNum;
  881. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION;
  882. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION);
  883. lstrcpy(pSdp->Sdp[nIndex].u.Session.Name, "EH-Call");
  884. lstrcpy(pSdp->Sdp[nIndex].u.Session.Info, "");
  885. pSdp->SdpNum++;
  886. //c
  887. nIndex = pSdp->SdpNum;
  888. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONNECTION;
  889. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_CONNECTION);
  890. pSdp->Sdp[nIndex].u.Connection.NetType = ISXSIP_SDPNETTYPE_IN;
  891. pSdp->Sdp[nIndex].u.Connection.AddrType = ISXSIP_SDPADDRTYPE_IP4;
  892. lstrcpy(pSdp->Sdp[nIndex].u.Connection.Addr, MediaAddr);
  893. pSdp->SdpNum++;
  894. //t
  895. nIndex = pSdp->SdpNum;
  896. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION_TIME;
  897. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION_TIME);
  898. pSdp->Sdp[nIndex].u.SessionTime.Start = 0;
  899. pSdp->Sdp[nIndex].u.SessionTime.End = 0;
  900. pSdp->SdpNum++;
  901. //m
  902. nIndex = pSdp->SdpNum;
  903. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_MEDIA_DESC;
  904. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_MEDIA_DESC_EX);
  905. pSdp->Sdp[nIndex].u.MediaDesc.MediaPort = m_pBindIpmCh->mediaPort();
  906. pSdp->Sdp[nIndex].u.MediaDesc.MediaProtocol = ISXSIP_SDPPROTOCOL_UDPTL;
  907. pSdp->Sdp[nIndex].u.MediaDesc.MediaType = ISXSIP_SDPMEDIATYPE_IMAGE;
  908. pSdp->Sdp[nIndex].u.MediaDesc.PayLoadNum = 1;
  909. pSdp->Sdp[nIndex].u.MediaDesc.Payload[0] = 0;
  910. pSdp->SdpNum++;
  911. //a
  912. nIndex = pSdp->SdpNum;
  913. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  914. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  915. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "T38FaxVersion");
  916. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "0");
  917. pSdp->SdpNum++;
  918. //a
  919. nIndex = pSdp->SdpNum;
  920. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  921. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  922. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "T38MaxBitRate");
  923. //strcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "14400");
  924. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "9600");
  925. pSdp->SdpNum++;
  926. //a
  927. nIndex = pSdp->SdpNum;
  928. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  929. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  930. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "T38FaxFillBitRemoval");
  931. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "0");
  932. pSdp->SdpNum++;
  933. //a
  934. nIndex = pSdp->SdpNum;
  935. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  936. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  937. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "T38FaxTranscodingMMR");
  938. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "0");
  939. pSdp->SdpNum++;
  940. //a
  941. nIndex = pSdp->SdpNum;
  942. pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
  943. pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
  944. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "T38FaxTranscodingJBIG");
  945. lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "0");
  946. pSdp->SdpNum++;
  947. }
  948. /*****************************************************************
  949. **【函数名称】 __getCallNumFromSipAddr
  950. **【函数功能】 从SIP URI中解析号码
  951. **【参数】
  952. **【返回值】
  953. ****************************************************************/
  954. void CVoipChannel::__getCallNumFromSipAddr( LPCTSTR Called, CString& NumBuf )
  955. {
  956. ASSERT(Called != NULL);
  957. NumBuf = _T("");
  958. TCHAR szTmpAddr[GC_ADDRSIZE];
  959. lstrcpy(szTmpAddr, Called);
  960. TCHAR *p = strstr(szTmpAddr, _T("@"));
  961. if(p != NULL)
  962. *p=0;
  963. p = strstr(szTmpAddr, _T(":"));
  964. if(p == NULL)
  965. NumBuf = szTmpAddr;
  966. else
  967. NumBuf = p+1;
  968. }
  969. /*****************************************************************
  970. **【函数名称】 __getCallMediaDesc
  971. **【函数功能】 获取呼叫的媒体描述
  972. **【参数】
  973. **【返回值】
  974. ****************************************************************/
  975. bool CVoipChannel::__getCallMediaDesc( ISXSIP_IE_BODY_EX* pSdp, int CodecId /*= -1*/ )
  976. {
  977. if(pSdp->Valid == 0 || pSdp->BodyPartyType == BodyPartyType_TRANS)
  978. return false;
  979. int iLoopNum = pSdp->u.BodySdp.SdpNum;
  980. ISXSIP_IE_BODY_SDP_EX* pSdpex = &pSdp->u.BodySdp;
  981. for(int i = 0; i < iLoopNum; i++)
  982. {
  983. if(pSdpex->Sdp[i].Tag == ISXSIP_IE_SDP_TAG_CONNECTION)
  984. {
  985. m_ConnectAddr = pSdpex->Sdp[i].u.Connection.Addr;
  986. continue;
  987. }
  988. if(pSdpex->Sdp[i].Tag != ISXSIP_IE_SDP_TAG_MEDIA_DESC)
  989. continue;
  990. if(pSdpex->Sdp[i].u.MediaDesc.MediaType != ISXSIP_SDPMEDIATYPE_AUDIO)
  991. continue;
  992. int iPayLoadNum = pSdpex->Sdp[i].u.MediaDesc.PayLoadNum;
  993. m_MediaPort = pSdpex->Sdp[i].u.MediaDesc.MediaPort;
  994. ISXSIP_IE_SDP_MEDIA_DESC_EX* pmdex = &pSdpex->Sdp[i].u.MediaDesc;
  995. if(CodecId >= 0) //如果指定了CODEC
  996. {
  997. for(int j = 0; j < iPayLoadNum; j++)
  998. {
  999. if(g_SipSdpRtpMap[CodecId].Payload == pmdex->Payload[j])
  1000. {
  1001. //取此指定AUDIO编码作为协商类型
  1002. m_CodecId = CodecId;
  1003. return true;
  1004. }
  1005. }
  1006. }
  1007. else
  1008. {
  1009. for(int j = 0; j < iPayLoadNum; j++)
  1010. {
  1011. for(int k = 0; k < AudioCodec_MaxNum; k++)
  1012. {
  1013. if(g_SipSdpRtpMap[k].Payload == pmdex->Payload[j])
  1014. {
  1015. // 从给出的媒体编码类型中取一个AUDIO编码作为协商类型
  1016. m_CodecId = k;
  1017. return true;
  1018. }
  1019. }
  1020. }
  1021. }
  1022. }
  1023. return false;
  1024. }
  1025. /*****************************************************************
  1026. **【函数名称】 __consultMedia
  1027. **【函数功能】 协商媒体
  1028. **【参数】
  1029. **【返回值】
  1030. ****************************************************************/
  1031. bool CVoipChannel::__consultMedia( ISXSIP_IE_BODY_EX* pSdp )
  1032. {
  1033. if(pSdp->Valid == 0 || pSdp->BodyPartyType == BodyPartyType_TRANS)
  1034. return false;
  1035. int iLoopNum = pSdp->u.BodySdp.SdpNum;
  1036. ISXSIP_IE_BODY_SDP_EX* pSdpex = &pSdp->u.BodySdp;
  1037. for(int i = 0; i < iLoopNum; i++)
  1038. {
  1039. if(pSdpex->Sdp[i].Tag != ISXSIP_IE_SDP_TAG_MEDIA_DESC)
  1040. continue;
  1041. if(pSdpex->Sdp[i].u.MediaDesc.MediaType != ISXSIP_SDPMEDIATYPE_AUDIO)
  1042. continue;
  1043. int iPayLoadNum = pSdpex->Sdp[i].u.MediaDesc.PayLoadNum;
  1044. ISXSIP_IE_SDP_MEDIA_DESC_EX* pmdex = &pSdpex->Sdp[i].u.MediaDesc;
  1045. for(int j = 0; j < iPayLoadNum; j++)
  1046. {
  1047. for(int k = 0; k < AudioCodec_MaxNum; k++)
  1048. {
  1049. if(g_SipSdpRtpMap[k].Payload == pmdex->Payload[j])
  1050. {
  1051. pmdex->PayLoadNum = 2;
  1052. pmdex->Payload[0] = pmdex->Payload[j];
  1053. pmdex->Payload[1] = 101;
  1054. return true;
  1055. }
  1056. }
  1057. }
  1058. }
  1059. return false;
  1060. }
  1061. /*****************************************************************
  1062. **【函数名称】 __analyzeReinvite
  1063. **【函数功能】 分析reinvite的目的
  1064. **【参数】
  1065. **【返回值】
  1066. ****************************************************************/
  1067. ReinvitePurpose CVoipChannel::__analyzeReinvite( ISXSIP_IE_BODY_SDP_EX* pSdp )
  1068. {
  1069. for(int i = 0; i < pSdp->SdpNum; ++i)
  1070. {
  1071. USHORT Tag = pSdp->Sdp[i].Tag;
  1072. if(Tag == ISXSIP_IE_SDP_TAG_CONN_MODE)
  1073. {
  1074. UCHAR ConMode = pSdp->Sdp[i].u.ConnMode.ConnMode;
  1075. if(ConMode == ISXSIP_SDPCONNECTMODE_SENDONLY)
  1076. return REINVITE_FOR_HOLD;
  1077. else if(ConMode == ISXSIP_SDPCONNECTMODE_SENDRECV)
  1078. return REINVITE_FOR_TAKEBACK;
  1079. }
  1080. else if(Tag == ISXSIP_IE_SDP_TAG_MEDIA_DESC)
  1081. {
  1082. if(pSdp->Sdp[i].u.MediaDesc.MediaType == ISXSIP_SDPMEDIATYPE_IMAGE)
  1083. return REINVITE_FOR_FAX;
  1084. }
  1085. }
  1086. return REINVITE_FOR_NULL;
  1087. }
  1088. /*****************************************************************
  1089. **【函数名称】 __onOffered
  1090. **【函数功能】 处理来电呼叫
  1091. **【参数】
  1092. **【返回值】
  1093. ****************************************************************/
  1094. void CVoipChannel::__onOffered( METAEVENT* pMetaEvent )
  1095. {
  1096. if(m_State != GCST_NULL)
  1097. {
  1098. ISX_gc_DropCall(pMetaEvent->crn, IPEC_SIPReasonStatus500ServerInternalError);
  1099. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]检测到呼叫, 但通道状态异常, 呼叫将忽略"),
  1100. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1101. return;
  1102. }
  1103. m_State = GCST_OFFERED;
  1104. m_CallId = pMetaEvent->crn;
  1105. GCPARAMEX_MAKECALL* pMakeCallEx = (GCPARAMEX_MAKECALL*)pMetaEvent->evtdatap;
  1106. ASSERT(pMakeCallEx != NULL);
  1107. CHAR DNIZ[GC_ADDRSIZE] = { 0 };
  1108. CHAR ANI[GC_ADDRSIZE] = { 0 };
  1109. ISX_gc_GetCallInfo(m_CallId, DESTINATION_ADDRESS, DNIZ);
  1110. ISX_gc_GetCallInfo(m_CallId, ORIGINATION_ADDRESS, ANI);
  1111. // 获取主、被叫号码
  1112. __getCallNumFromSipAddr(ANI, m_CallerNum);
  1113. __getCallNumFromSipAddr(DNIZ, m_CalleeNum);
  1114. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]检测到呼叫, Caller = %s, Callee = %s"),
  1115. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, ANI, DNIZ);
  1116. // 判断主叫是内线还是中继
  1117. if(isInnerSipUser(m_CallerNum)) // 内线
  1118. m_pImplement = &ms_Implement4Exten;
  1119. else // 外线
  1120. m_pImplement = &ms_Implement4Trunk;
  1121. m_pImplement->onOffered(*this, pMakeCallEx);
  1122. CMC::GetInstance().onDevResState(m_Id);
  1123. }
  1124. /*****************************************************************
  1125. **【函数名称】 __onAlerting
  1126. **【函数功能】 处理远端振铃
  1127. **【参数】
  1128. **【返回值】
  1129. ****************************************************************/
  1130. void CVoipChannel::__onAlerting( METAEVENT* pMetaEvent )
  1131. {
  1132. if(m_State == GCST_ALERTING || m_State == GCST_DROPCALLING)
  1133. return;
  1134. m_State = GCST_ALERTING;
  1135. ASSERT(m_pImplement != NULL);
  1136. m_pImplement->onAlerting(*this, pMetaEvent);
  1137. CMC::GetInstance().onDevResState(m_Id);
  1138. }
  1139. /*****************************************************************
  1140. **【函数名称】 __onProgressing
  1141. **【函数功能】 处理Progressing
  1142. **【参数】
  1143. **【返回值】
  1144. ****************************************************************/
  1145. void CVoipChannel::__onProgressing( void )
  1146. {
  1147. if(m_State == GCST_PROGRESS || m_State == GCST_DROPCALLING)
  1148. return;
  1149. GCPARAMEX_CALLPROGRESS* pProgress = (GCPARAMEX_CALLPROGRESS*)ISX_sr_getevtdatap();
  1150. ASSERT(pProgress != NULL);
  1151. // 存在收到183而无SDP紧接着又再次收到携带了SDP的183这种情况,所以在if语句判断成功后再将m_State设置为GCST_PROGRESS
  1152. if(pProgress->u.SIPProgress.Body.Valid == 1)
  1153. {
  1154. m_State = GCST_PROGRESS;
  1155. // 协商媒体编解码
  1156. if(!__getCallMediaDesc(&pProgress->u.SIPProgress.Body))
  1157. {
  1158. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理Progressing时协商媒体编解码失败, 呼叫将释放, Caller = %s, Callee = %s"),
  1159. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1160. __clearCall(IPEC_SIPReasonStatus415UnsupportedMediaType);
  1161. return;
  1162. }
  1163. // 启动媒体
  1164. ASSERT(m_pBindIpmCh != NULL);
  1165. if(!m_pBindIpmCh->isStarted())
  1166. {
  1167. if(!m_pBindIpmCh->startMedia())
  1168. {
  1169. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理Progressing时IPM资源启动失败, 呼叫将释放, Caller = %s, Callee = %s"),
  1170. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1171. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  1172. return;
  1173. }
  1174. }
  1175. CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_PROGRESSING, m_CallerNum, m_CalleeNum);
  1176. }
  1177. }
  1178. /*****************************************************************
  1179. **【函数名称】 __onConnected
  1180. **【函数功能】 处理远端接通
  1181. **【参数】
  1182. **【返回值】
  1183. ****************************************************************/
  1184. void CVoipChannel::__onConnected( METAEVENT* pMetaEvent )
  1185. {
  1186. if(m_State == GCST_DROPCALLING)
  1187. return;
  1188. m_State = GCST_CONNECTED;
  1189. GCPARAMEX_ANSWERCALL *pOutAnswerCallEx = (GCPARAMEX_ANSWERCALL*)pMetaEvent->evtdatap;
  1190. ASSERT(pOutAnswerCallEx != NULL);
  1191. if(pOutAnswerCallEx->u.SIPConn.Body.Valid == 1)
  1192. {
  1193. // 协商媒体编解码
  1194. if(!__getCallMediaDesc(&pOutAnswerCallEx->u.SIPConn.Body))
  1195. {
  1196. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理远端应答时协商媒体编解码失败, 呼叫将释放, Caller = %s, Callee = %s"),
  1197. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1198. __clearCall(IPEC_SIPReasonStatus415UnsupportedMediaType);
  1199. return;
  1200. }
  1201. }
  1202. // 启动媒体
  1203. ASSERT(m_pBindIpmCh != NULL);
  1204. if(!m_pBindIpmCh->isStarted())
  1205. {
  1206. if(!m_pBindIpmCh->startMedia())
  1207. {
  1208. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理远端应答时启动IPM资源失败, 呼叫将释放, Caller = %s, Callee = %s"),
  1209. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1210. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  1211. return;
  1212. }
  1213. }
  1214. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]远端应答, 开始通话, Caller = %s, Callee = %s"),
  1215. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1216. if(m_Job == DEV_LINE_CH_JOB_PRE_DIAL)
  1217. {
  1218. CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_INIT, m_CallerNum, m_CalleeNum);
  1219. m_Job = DEV_LINE_CH_JOB_NONE;
  1220. }
  1221. else if(m_Job == DEV_LINE_CH_JOB_OFF_HOOK)
  1222. {
  1223. CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, DEV_CH_EVT_OFF_HOOK, NULL);
  1224. m_Job = DEV_LINE_CH_JOB_NONE;
  1225. }
  1226. else
  1227. {
  1228. CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_TALKING, m_CallerNum, m_CalleeNum);
  1229. }
  1230. CMC::GetInstance().onDevResState(m_Id);
  1231. }
  1232. /*****************************************************************
  1233. **【函数名称】 __onAnswered
  1234. **【函数功能】 处理应答成功
  1235. **【参数】
  1236. **【返回值】
  1237. ****************************************************************/
  1238. void CVoipChannel::__onAnswered( void )
  1239. {
  1240. if(m_State == GCST_DROPCALLING)
  1241. return;
  1242. m_State = GCST_CONNECTED;
  1243. // 启动媒体
  1244. ASSERT(m_pBindIpmCh != NULL);
  1245. if(!m_pBindIpmCh->isStarted())
  1246. {
  1247. if(!m_pBindIpmCh->startMedia())
  1248. {
  1249. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]应答远端时启动IPM资源失败, 呼叫将释放, Caller = %s, Callee = %s"),
  1250. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1251. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  1252. return;
  1253. }
  1254. }
  1255. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]应答成功, 开始通话, Caller = %s, Callee = %s"),
  1256. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1257. CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_TALKING, m_CallerNum, m_CalleeNum);
  1258. CMC::GetInstance().onDevResState(m_Id);
  1259. }
  1260. /*****************************************************************
  1261. **【函数名称】 __onCallFinish
  1262. **【函数功能】 处理呼叫成功
  1263. **【参数】
  1264. **【返回值】
  1265. ****************************************************************/
  1266. void CVoipChannel::__onCallFinish( void )
  1267. {
  1268. m_State = GCST_NULL;
  1269. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]空闲"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1270. // 因为发现调用__ClearCall之后又收到GCEV_CONNECTED等事件,导致IPM通道stop之后又start,从而使IPM通道
  1271. // 一直处于start状态未释放,后续的呼叫若使用该IPM通道会因为start失败而造成呼叫异常,鉴于此把IPM通道的
  1272. // stop方法从__ClearCall函数移至此处调用。
  1273. if(m_pBindIpmCh != NULL)
  1274. {
  1275. m_pBindIpmCh->stopMedia();
  1276. // 未关联会话则IPM通道无法被会话释放,所以这里提前释放
  1277. if(m_SessionCode == SESSION_INVALID_CALL)
  1278. {
  1279. m_pBindIpmCh->reset();
  1280. m_pBindIpmCh = NULL;
  1281. }
  1282. }
  1283. // 通各线路状态变化
  1284. CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_FREE, NULL, NULL);
  1285. m_pImplement = NULL;
  1286. m_CallId = 0;
  1287. m_Job = DEV_LINE_CH_JOB_NONE;
  1288. m_ExtenNo = 0;
  1289. m_MediaPort = 0;
  1290. m_CodecId = -1;
  1291. m_ConnectAddr = _T("");
  1292. reset();
  1293. CMC::GetInstance().onDevResState(m_Id);
  1294. }
  1295. /*****************************************************************
  1296. **【函数名称】 __onDiconnected
  1297. **【函数功能】 处理呼叫中断
  1298. **【参数】
  1299. **【返回值】
  1300. ****************************************************************/
  1301. void CVoipChannel::__onDiconnected( METAEVENT* pMetaEvent )
  1302. {
  1303. GCPARAMEX_DROPCALL* pDropCall = (GCPARAMEX_DROPCALL*)pMetaEvent->evtdatap;
  1304. ASSERT(pDropCall != NULL);
  1305. if(m_State != GCST_CONNECTED) // 非通话中挂机
  1306. {
  1307. int ErrCode;
  1308. switch(pDropCall->u.SIPDrop.usCause)
  1309. {
  1310. case IPEC_SIPReasonStatus404NotFound:
  1311. ErrCode = CALL_FAILED_CAUSE_NUM_INVALID;
  1312. break;
  1313. case IPEC_SIPReasonStatus500ServerInternalError:
  1314. case IPEC_SIPReasonStatus480TemporarilyUnavailable:
  1315. ErrCode = CALL_FAILED_CAUSE_NO_ANSWER;
  1316. break;
  1317. case IPEC_SIPReasonStatus486BusyHere:
  1318. ErrCode = CALL_FAILED_CAUSE_USER_BUSY;
  1319. break;
  1320. case IPEC_SIPReasonStatus410Gone:
  1321. ErrCode = CALL_FAILED_CAUSE_DST_OFF;
  1322. break;
  1323. default:
  1324. ErrCode = CALL_FAILED_CAUSE_NETWORK_ERR;
  1325. break;
  1326. }
  1327. CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, DEV_CH_EVT_CALL_FAILD_CAUSE, (LPCTSTR)ErrCode);
  1328. }
  1329. m_State = GCST_DISCONNECTED;
  1330. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]检测到远端挂机, Caller = %s, Callee = %s, Cause = %d"),
  1331. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum, pDropCall->u.SIPDrop.usCause);
  1332. // 远端挂机,结束两方通道通话
  1333. __clearCall(pDropCall->u.SIPDrop.usCause);
  1334. }
  1335. /*****************************************************************
  1336. **【函数名称】 __onTaskFail
  1337. **【函数功能】 处理通道任务失败
  1338. **【参数】
  1339. **【返回值】
  1340. ****************************************************************/
  1341. void CVoipChannel::__onTaskFail( void )
  1342. {
  1343. switch(ISX_sr_getevtopertype())
  1344. {
  1345. case OPER_ACCEPTCALL:
  1346. {
  1347. ASSERT(FALSE);
  1348. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  1349. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]accept呼叫失败, Caller = %s, Callee = %s"),
  1350. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1351. }
  1352. break;
  1353. case OPER_ANSWERCALL:
  1354. {
  1355. ASSERT(FALSE);
  1356. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  1357. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]应答来电失败, Caller = %s, Callee = %s"),
  1358. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1359. }
  1360. break;
  1361. case OPER_MAKECALL:
  1362. {
  1363. ASSERT(FALSE);
  1364. __clearCall(IPEC_SIPReasonStatus200OK);
  1365. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]外呼失败, Caller = %s, Callee = %s"),
  1366. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1367. }
  1368. break;
  1369. case OPER_DROPCALL:
  1370. {
  1371. ASSERT(FALSE);
  1372. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]挂机失败, 已强制释放资源, Caller = %s, Callee = %s"),
  1373. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1374. __onCallFinish();
  1375. }
  1376. break;
  1377. case OPER_SIP_SENDREINVITE:
  1378. {
  1379. ASSERT(FALSE);
  1380. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  1381. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]发送Reinvite失败, Caller = %s, Callee = %s"),
  1382. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1383. }
  1384. break;
  1385. case OPER_SIP_SENDREINVITEACK:
  1386. {
  1387. ASSERT(FALSE);
  1388. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  1389. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]发送ReinviteACK失败, Caller = %s, Callee = %s"),
  1390. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1391. }
  1392. break;
  1393. }
  1394. }
  1395. /*****************************************************************
  1396. **【函数名称】 __onRecvInfo
  1397. **【函数功能】 处理收到的SIP消息
  1398. **【参数】
  1399. **【返回值】
  1400. ****************************************************************/
  1401. void CVoipChannel::__onRecvInfo( METAEVENT* pMetaEvent )
  1402. {
  1403. SIP_INFO* pSipInfo = (SIP_INFO*)pMetaEvent->evtdatap;
  1404. ASSERT(pSipInfo != NULL);
  1405. SIP_INFO_ACK Ack;
  1406. memcpy(&Ack.Body, &pSipInfo->Body, sizeof(ISXSIP_IE_BODY_EX));
  1407. Ack.ulSerialNo = pSipInfo->ulSerialNo;
  1408. Ack.usCause = IPEC_SIPReasonStatus200OK;
  1409. ISX_gc_SIPSendInfoAck(pMetaEvent->crn, EV_ASYNC, &Ack);
  1410. }
  1411. /*****************************************************************
  1412. **【函数名称】 __onRecvReinvite
  1413. **【函数功能】 处理Reinvite消息
  1414. **【参数】
  1415. **【返回值】
  1416. ****************************************************************/
  1417. void CVoipChannel::__onRecvReinvite( METAEVENT* pMetaEvent )
  1418. {
  1419. ISXSIP_IE_BODY_EX* pSdp = (ISXSIP_IE_BODY_EX*)pMetaEvent->evtdatap;
  1420. ASSERT(pSdp != NULL);
  1421. if(pSdp->Valid == 0 || pSdp->BodyPartyType == BodyPartyType_TRANS)
  1422. return;
  1423. ReinvitePurpose Purpose = __analyzeReinvite(&pSdp->u.BodySdp);
  1424. SIP_REINVITE_ACK Ack;
  1425. switch(Purpose)
  1426. {
  1427. case REINVITE_FOR_HOLD:
  1428. {
  1429. CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, DEV_CH_EVT_HOLD_ON, NULL, m_ExtenNo);
  1430. Ack.usCause = IPEC_SIPReasonStatus200OK;
  1431. __constructReinviteBody4Hold(&Ack.Body, true);
  1432. }
  1433. break;
  1434. case REINVITE_FOR_TAKEBACK:
  1435. {
  1436. CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, DEV_CH_EVT_TAKE_BACK, NULL, m_ExtenNo);
  1437. Ack.usCause = IPEC_SIPReasonStatus200OK;
  1438. __constructReinviteBody4Hold(&Ack.Body, false);
  1439. }
  1440. break;
  1441. case REINVITE_FOR_FAX:
  1442. {
  1443. __constructReinviteBody4T38(&Ack.Body);
  1444. ASSERT(m_pBindIpmCh != NULL);
  1445. Ack.usCause = m_pBindIpmCh->switchVF(pSdp) ? IPEC_SIPReasonStatus200OK : IPEC_SIPReasonStatus403Forbidden;
  1446. }
  1447. break;
  1448. default:
  1449. Ack.usCause = IPEC_SIPReasonStatus403Forbidden;
  1450. }
  1451. ISX_gc_SIPSendReinviteAck(m_CallId, EV_ASYNC, &Ack);
  1452. }
  1453. /*****************************************************************
  1454. **【函数名称】 __onRecvReinviteAck
  1455. **【函数功能】 处理ReinviteACK消息
  1456. **【参数】
  1457. **【返回值】
  1458. ****************************************************************/
  1459. void CVoipChannel::__onRecvReinviteAck( METAEVENT* pMetaEvent )
  1460. {
  1461. SIP_REINVITE_ACK* pReinviteAck = (SIP_REINVITE_ACK*)pMetaEvent->evtdatap;
  1462. ASSERT(pReinviteAck != NULL);
  1463. ISXSIP_IE_BODY_EX* pSdp = &pReinviteAck->Body;
  1464. if(pSdp->Valid == 0 || pSdp->BodyPartyType == BodyPartyType_TRANS)
  1465. return;
  1466. ASSERT(m_pBindIpmCh != NULL);
  1467. if(m_pBindIpmCh->switchVF(pSdp))
  1468. {
  1469. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  1470. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]响应ReinviteAck消息,切换传真模式失败, Caller = %s, Callee = %s"),
  1471. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1472. }
  1473. }
  1474. /*****************************************************************
  1475. **【函数名称】 __onRecvUpdate
  1476. **【函数功能】 处理Update消息
  1477. **【参数】
  1478. **【返回值】
  1479. ****************************************************************/
  1480. void CVoipChannel::__onRecvUpdate( METAEVENT* pMetaEvent )
  1481. {
  1482. SIP_UPDATE_IND *pUpdate = (SIP_UPDATE_IND *)pMetaEvent->evtdatap;
  1483. ASSERT(pUpdate != NULL);
  1484. SIP_GENTRANSC_ACK ack;
  1485. memcpy(&ack.Body, &pUpdate->Body, sizeof(ISXSIP_IE_BODY_EX));
  1486. ack.ulSerialNo = pUpdate->ulSerialNo;
  1487. ack.usCause = IPEC_SIPReasonStatus200OK;
  1488. ISX_gc_SIPSendUpdateAck (pMetaEvent->crn, EV_ASYNC, &ack);
  1489. }
  1490. /*****************************************************************
  1491. **【函数名称】 __onRecvSubscribe
  1492. **【函数功能】 处理subscribe消息
  1493. **【参数】
  1494. **【返回值】
  1495. ****************************************************************/
  1496. void CVoipChannel::__onRecvSubscribe( METAEVENT* pMetaEvent )
  1497. {
  1498. SIP_SUBSCRIBE_IND* pInd = (SIP_SUBSCRIBE_IND *)pMetaEvent->evtdatap;
  1499. ASSERT(pInd != NULL);
  1500. SIP_SUBSCRIBE_ACK ack;
  1501. memcpy(&ack.Expires, &pInd->Expires, sizeof(ISXSIP_IE_EXPIRES));
  1502. memcpy(&ack.Body, &pInd->Body, sizeof(ISXSIP_IE_BODY_EX));
  1503. ack.ulSerialNo = pInd->ulSerialNo;
  1504. ack.usCause = IPEC_SIPReasonStatus406NotAcceptable;
  1505. ISX_gc_SIPSendSubscribeAck(pMetaEvent->crn, EV_ASYNC, &ack);
  1506. }
  1507. /*****************************************************************
  1508. **【函数名称】 __onRecvMessage
  1509. **【函数功能】 处理message消息
  1510. **【参数】
  1511. **【返回值】
  1512. ****************************************************************/
  1513. void CVoipChannel::__onRecvMessage( METAEVENT* pMetaEvent )
  1514. {
  1515. SIP_MESSAGE_IND* pInd = (SIP_MESSAGE_IND *)pMetaEvent->evtdatap;
  1516. ASSERT(pInd != NULL);
  1517. SIP_GENTRANSC_ACK ack;
  1518. ack.usCause = IPEC_SIPReasonStatus200OK;
  1519. memcpy(&ack.Body, &pInd->Body, sizeof(ISXSIP_IE_BODY_EX));
  1520. ack.ulSerialNo = pInd->ulSerialNo;
  1521. ISX_gc_SIPSendMessageAck (pMetaEvent->crn, EV_ASYNC, &ack);
  1522. }
  1523. /*****************************************************************
  1524. **【函数名称】 __onRecvNotify
  1525. **【函数功能】 处理notify消息
  1526. **【参数】
  1527. **【返回值】
  1528. ****************************************************************/
  1529. void CVoipChannel::__onRecvNotify( METAEVENT* pMetaEvent )
  1530. {
  1531. SIP_NOTIFY_IND* pInd = (SIP_NOTIFY_IND *)pMetaEvent->evtdatap;
  1532. ASSERT(pInd != NULL);
  1533. SIP_GENTRANSC_ACK ack;
  1534. memcpy(&ack.Body, &pInd->Body, sizeof(ISXSIP_IE_BODY_EX));
  1535. ack.usCause = IPEC_SIPReasonStatus200OK;
  1536. ack.ulSerialNo = pInd->ulSerialNo;
  1537. ISX_gc_SIPSendNotifyAck (pMetaEvent->crn, EV_ASYNC, &ack);
  1538. }
  1539. /*****************************************************************
  1540. **【函数名称】 __onRecvRefer
  1541. **【函数功能】 处理refer消息
  1542. **【参数】
  1543. **【返回值】
  1544. ****************************************************************/
  1545. void CVoipChannel::__onRecvRefer( METAEVENT* pMetaEvent )
  1546. {
  1547. SIP_REFER_IND* pInd = (SIP_REFER_IND *)ISX_sr_getevtdatap();
  1548. ASSERT(pInd != NULL);
  1549. SIP_REFER_ACK ack;
  1550. memcpy(&ack.Body, &pInd->Body, sizeof(ISXSIP_IE_BODY_EX));
  1551. memcpy(&ack.Contact, &pInd->Contact, sizeof(ISXSIP_IE_CONTACT));
  1552. ack.usCause = IPEC_SIPReasonStatus403Forbidden;
  1553. ack.ulSerialNo = pInd->ulSerialNo;
  1554. ISX_gc_SIPSendReferAck(pMetaEvent->crn, EV_ASYNC, &ack);
  1555. }
  1556. /*****************************************************************
  1557. **【函数名称】 __onRecvOption
  1558. **【函数功能】 处理option消息
  1559. **【参数】
  1560. **【返回值】
  1561. ****************************************************************/
  1562. void CVoipChannel::__onRecvOption( METAEVENT* pMetaEvent )
  1563. {
  1564. SIP_OPTIONS_IND* pInd = (SIP_OPTIONS_IND *)ISX_sr_getevtdatap();
  1565. ASSERT(pInd != NULL);
  1566. SIP_GENTRANSC_ACK ack;
  1567. ZeroMemory(&ack, sizeof(ack));
  1568. ack.ulSerialNo = pInd->ulSerialNo;
  1569. ack.usCause = IPEC_SIPReasonStatus200OK;
  1570. if(__consultMedia(&pInd->Body))
  1571. memcpy(&ack.Body, &pInd->Body, sizeof(ISXSIP_IE_BODY_EX));
  1572. ISX_gc_SIPSendOptionsAck(pMetaEvent->crn, EV_ASYNC, &ack);
  1573. }
  1574. /*****************************************************************
  1575. **【函数名称】 open
  1576. **【函数功能】 打开系统资源
  1577. **【参数】
  1578. **【返回值】 成功true,失败false
  1579. ****************************************************************/
  1580. bool CVoipChannel::open( void )
  1581. {
  1582. ASSERT(m_Handle == DEV_HANDLE_INVALID);
  1583. if(ISX_gc_OpenEx(&m_Handle, m_Id.NodeNo, m_Id.BoardNo, -1, m_Id.ChanNo, EV_SYNC, this, LINETYPE_SIP) < 0)
  1584. {
  1585. m_Handle = DEV_HANDLE_INVALID;
  1586. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{VOIPCh}: VOIP通道[%d-%d-%d]打开失败"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1587. return false;
  1588. }
  1589. ISX_gc_SetEvtMsk(m_Handle, GCMSK_PROGRESS, GCACT_ADDMSK);
  1590. if( m_Id.ChanNo % 2 != 0 )
  1591. {
  1592. if(ISX_gc_WaitCall(m_Handle, NULL, NULL, -1, EV_ASYNC) < 0)
  1593. {
  1594. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{VOIPCh}: VOIP通道[%d-%d-%d]等待呼叫失败"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1595. return false;
  1596. }
  1597. }
  1598. //LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: VOIP通道[%d-%d-%d]打开成功"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1599. return true;
  1600. }
  1601. /*****************************************************************
  1602. **【函数名称】 close
  1603. **【函数功能】 关闭系统资源
  1604. **【参数】
  1605. **【返回值】
  1606. ****************************************************************/
  1607. void CVoipChannel::close( void )
  1608. {
  1609. if(m_Handle != DEV_HANDLE_INVALID)
  1610. {
  1611. ISX_gc_Close(m_Handle);
  1612. m_Handle = DEV_HANDLE_INVALID;
  1613. //LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: VOIPCh通道[%d-%d-%d]关闭"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1614. }
  1615. }
  1616. /*****************************************************************
  1617. **【函数名称】 offhook
  1618. **【函数功能】 内线摘机(只对内线有效)
  1619. **【参数】
  1620. **【返回值】
  1621. ****************************************************************/
  1622. bool CVoipChannel::offhook( bool IgnoreSession, LPCTSTR CallerNum )
  1623. {
  1624. ASSERT(CallerNum != NULL);
  1625. if(m_State != GCST_NULL)
  1626. {
  1627. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]振铃座席分机失败, 通道状态非空闲, Exten = %s"),
  1628. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, CallerNum);
  1629. return false;
  1630. }
  1631. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行振铃座席分机请求, Exten = %s"),
  1632. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, CallerNum);
  1633. if(IgnoreSession)
  1634. m_Job = DEV_LINE_CH_JOB_OFF_HOOK;
  1635. else
  1636. m_Job = DEV_LINE_CH_JOB_PRE_DIAL;
  1637. m_CalleeNum = CallerNum;
  1638. m_CallerNum = CallerNum;
  1639. m_pImplement = &ms_Implement4Exten;
  1640. return m_pImplement->makeCall(*this, INVALID_ID_SIP_ACCOUNT);
  1641. }
  1642. /*****************************************************************
  1643. **【函数名称】 dropCall
  1644. **【函数功能】 挂机
  1645. **【参数】 IsPassive 是否为被动挂机
  1646. **【返回值】
  1647. ****************************************************************/
  1648. bool CVoipChannel::dropCall( bool IsPassive )
  1649. {
  1650. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行挂机请求, caller = %s, callee = %s"),
  1651. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1652. return __clearCall(IPEC_SIPReasonStatus200OK);
  1653. }
  1654. /*****************************************************************
  1655. **【函数名称】 makeCall
  1656. **【函数功能】 启动线路拨号
  1657. **【参数】 lpCalleeNum 被叫号码
  1658. lpCallerNum 主叫号码
  1659. **【返回值】
  1660. ****************************************************************/
  1661. bool CVoipChannel::makeCall( LPCTSTR Callee, LPCTSTR Caller, int AccountId )
  1662. {
  1663. ASSERT(Callee != NULL);
  1664. ASSERT(Caller != NULL);
  1665. if(m_State != GCST_NULL)
  1666. {
  1667. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]执行呼叫请求失败, 通道未在空闲状态, caller = %s, callee = %s"),
  1668. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, Caller, Callee);
  1669. return false;
  1670. }
  1671. m_CalleeNum = Callee;
  1672. m_CallerNum = Caller;
  1673. if(AccountId == INVALID_ID_SIP_ACCOUNT) // 呼叫内线
  1674. m_pImplement = &ms_Implement4Exten;
  1675. else
  1676. m_pImplement = &ms_Implement4Trunk;
  1677. return m_pImplement->makeCall(*this, AccountId);
  1678. }
  1679. /*****************************************************************
  1680. **【函数名称】 answer
  1681. **【函数功能】 应答呼叫
  1682. **【参数】
  1683. **【返回值】
  1684. ****************************************************************/
  1685. bool CVoipChannel::answer( void )
  1686. {
  1687. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行应答请求"),
  1688. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1689. if(m_State == GCST_CONNECTED)
  1690. {
  1691. CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_TALKING, m_CallerNum, m_CalleeNum);
  1692. return true;
  1693. }
  1694. else
  1695. return false;
  1696. }
  1697. /*****************************************************************
  1698. **【函数名称】 playSound
  1699. **【函数功能】 放音收号
  1700. **【参数】 pContent 放音内容
  1701. **【返回值】
  1702. ****************************************************************/
  1703. bool CVoipChannel::playSound( PlayVoiceContent* pContent )
  1704. {
  1705. ASSERT(pContent != NULL);
  1706. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行放音请求, AudioFile = %s"),
  1707. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, pContent->szFileName);
  1708. if(m_State != GCST_CONNECTED)
  1709. {
  1710. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]放音失败, 通道未处于连接状态, AudioFile = %s"),
  1711. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, pContent->szFileName);
  1712. return false;
  1713. }
  1714. return m_Mixer.playSound(pContent);
  1715. }
  1716. /*****************************************************************
  1717. **【函数名称】 playTone
  1718. **【函数功能】 播放信号音
  1719. **【参数】 Type 信号音类型
  1720. **【返回值】
  1721. ****************************************************************/
  1722. bool CVoipChannel::playTone( int Type )
  1723. {
  1724. return m_Mixer.playTone(Type);
  1725. }
  1726. /*****************************************************************
  1727. **【函数名称】 playStop
  1728. **【函数功能】 停止放音
  1729. **【参数】
  1730. **【返回值】
  1731. ****************************************************************/
  1732. bool CVoipChannel::playStop( void )
  1733. {
  1734. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行停止放音请求"),
  1735. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1736. return m_Mixer.playStop();
  1737. }
  1738. /*****************************************************************
  1739. **【函数名称】 startRecord
  1740. **【函数功能】 开始录音
  1741. **【参数】
  1742. **【返回值】
  1743. ****************************************************************/
  1744. bool CVoipChannel::startRecord( RecordContent* pContent )
  1745. {
  1746. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行录音请求"),
  1747. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1748. if(m_State == GCST_NULL)
  1749. {
  1750. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]录音失败, 通道状态空闲"),
  1751. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1752. return false;
  1753. }
  1754. return m_Mixer.startRecord(pContent);
  1755. }
  1756. /*****************************************************************
  1757. **【函数名称】 stopRecord
  1758. **【函数功能】 停止录音
  1759. **【参数】
  1760. **【返回值】
  1761. ****************************************************************/
  1762. bool CVoipChannel::stopRecord( void )
  1763. {
  1764. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行停止录音请求"),
  1765. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1766. return m_Mixer.stopRecord();
  1767. }
  1768. /*****************************************************************
  1769. **【函数名称】 monitor
  1770. **【函数功能】 监听
  1771. **【参数】
  1772. **【返回值】
  1773. ****************************************************************/
  1774. bool CVoipChannel::monitor( COneLeg* pTalker, bool IsStop )
  1775. {
  1776. ASSERT(pTalker != NULL);
  1777. if(IsStop)
  1778. {
  1779. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行取消监听请求"),
  1780. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1781. return pTalker->cancelMonitor(this);
  1782. }
  1783. else
  1784. {
  1785. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行监听请求"),
  1786. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1787. if(m_State != GCST_CONNECTED)
  1788. {
  1789. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]监听失败, 通道未处于连接状态"),
  1790. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1791. return false;
  1792. }
  1793. return pTalker->allowMonitor(this);
  1794. }
  1795. }
  1796. /*****************************************************************
  1797. **【函数名称】 allowMonitor
  1798. **【函数功能】 允许监听
  1799. **【参数】
  1800. **【返回值】
  1801. ****************************************************************/
  1802. bool CVoipChannel::allowMonitor( COneLeg* pMonitorParty )
  1803. {
  1804. if(m_State != GCST_CONNECTED)
  1805. {
  1806. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]接受监听失败, 通道未处于连接状态"),
  1807. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1808. return false;
  1809. }
  1810. if(!m_Mixer.allowedMonitor())
  1811. {
  1812. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]接受监听失败, 无空闲混音发端可连接"),
  1813. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1814. return false;
  1815. }
  1816. return m_Mixer.setupMonitor(pMonitorParty->routeChannel());
  1817. }
  1818. /*****************************************************************
  1819. **【函数名称】 cancelMonitor
  1820. **【函数功能】 取消监听
  1821. **【参数】
  1822. **【返回值】
  1823. ****************************************************************/
  1824. bool CVoipChannel::cancelMonitor( COneLeg* pMonitorParty )
  1825. {
  1826. ASSERT(pMonitorParty != NULL);
  1827. return m_Mixer.undoMonitor(pMonitorParty->routeChannel());
  1828. }
  1829. /*****************************************************************
  1830. **【函数名称】 freeResBinded
  1831. **【函数功能】 释放绑定资源
  1832. **【参数】
  1833. **【返回值】
  1834. ****************************************************************/
  1835. void CVoipChannel::freeResBinded( void )
  1836. {
  1837. if(m_pBindIpmCh != NULL)
  1838. {
  1839. m_pBindIpmCh->reset();
  1840. m_pBindIpmCh = NULL;
  1841. }
  1842. }
  1843. /*****************************************************************
  1844. **【函数名称】 onDevEvent
  1845. **【函数功能】 设备事件处理函数
  1846. **【参数】
  1847. **【返回值】
  1848. ****************************************************************/
  1849. void CVoipChannel::onDevEvent( METAEVENT* pMetaEvent )
  1850. {
  1851. ASSERT(pMetaEvent != NULL);
  1852. switch(pMetaEvent->evttype)
  1853. {
  1854. case GCEV_OFFERED: // 呼入
  1855. __onOffered(pMetaEvent);
  1856. break;
  1857. case GCEV_DIALING:
  1858. {
  1859. m_State = GCST_DIALING;
  1860. CMC::GetInstance().onDevResState(m_Id);
  1861. }
  1862. break;
  1863. case GCEV_ACCEPT:
  1864. m_State = GCST_ACCEPTED;
  1865. break;
  1866. case GCEV_ALERTING:
  1867. __onAlerting(pMetaEvent);
  1868. break;
  1869. case GCEV_PROGRESSING:
  1870. __onProgressing();
  1871. break;
  1872. case GCEV_CONNECTED:
  1873. __onConnected(pMetaEvent);
  1874. break;
  1875. case GCEV_ANSWERED:
  1876. __onAnswered();
  1877. break;
  1878. case GCEV_DROPCALL:
  1879. __onCallFinish();
  1880. break;
  1881. case GCEV_DISCONNECTED:
  1882. __onDiconnected(pMetaEvent);
  1883. break;
  1884. case GCEV_SIP_RECVREINVITE:
  1885. __onRecvReinvite(pMetaEvent);
  1886. break;
  1887. case GCEV_SIP_RECVREINVITEACK:
  1888. __onRecvReinviteAck(pMetaEvent);
  1889. break;
  1890. case GCEV_SIP_RECVINFO:
  1891. __onRecvInfo(pMetaEvent);
  1892. break;
  1893. case GCEV_SIP_RECVUPDATE:
  1894. __onRecvUpdate(pMetaEvent);
  1895. break;
  1896. case GCEV_SIP_RECVSUBSCRIBE:
  1897. __onRecvSubscribe(pMetaEvent);
  1898. break;
  1899. case GCEV_SIP_RECVMESSAGE:
  1900. __onRecvMessage(pMetaEvent);
  1901. break;
  1902. case GCEV_SIP_RECVNOTIFY:
  1903. __onRecvNotify(pMetaEvent);
  1904. break;
  1905. case GCEV_SIP_RECVREFER:
  1906. __onRecvRefer(pMetaEvent);
  1907. break;
  1908. case GCEV_SIP_RECVOPTIONS:
  1909. __onRecvOption(pMetaEvent);
  1910. break;
  1911. case GCEV_TASKFAIL:
  1912. __onTaskFail();
  1913. break;
  1914. case GCEV_BLOCKED:
  1915. {
  1916. m_IsBlocked = true;
  1917. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]阻塞"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1918. }
  1919. break;
  1920. case GCEV_UNBLOCKED:
  1921. {
  1922. m_IsBlocked = false;
  1923. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]解除阻塞"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
  1924. }
  1925. break;
  1926. default:
  1927. break;
  1928. }
  1929. }
  1930. /*****************************************************************
  1931. **【函数名称】 isInnerSipUser
  1932. **【函数功能】 判断是否是内线SIP用户
  1933. **【参数】
  1934. **【返回值】
  1935. ****************************************************************/
  1936. bool CVoipChannel::isInnerSipUser( LPCTSTR User )
  1937. {
  1938. ASSERT(User != NULL);
  1939. ISXSIP_REGUSER RegUser;
  1940. return ISXE_gc_SipGetRegisterUser(User, &RegUser) == 0;
  1941. }
  1942. /*****************************************************************
  1943. **【函数名称】 reinvite4T38
  1944. **【函数功能】 为T38传真发送reinvite
  1945. **【参数】
  1946. **【返回值】
  1947. ****************************************************************/
  1948. bool CVoipChannel::reinvite4T38( void )
  1949. {
  1950. ISXSIP_IE_BODY_EX Body;
  1951. __constructReinviteBody4T38(&Body);
  1952. return ISX_gc_SIPSendReinvite(m_CallId, EV_ASYNC, &Body) == 0;
  1953. }
  1954. /*****************************************************************
  1955. **【函数名称】 reply
  1956. **【函数功能】 响应呼叫
  1957. **【参数】
  1958. **【返回值】
  1959. ****************************************************************/
  1960. bool CVoipChannel::reply( void )
  1961. {
  1962. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行reply, State = %d"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_State);
  1963. if(m_State == GCST_OFFERED) // 话机直接发起的呼叫请求
  1964. {
  1965. if(ISX_gc_AcceptCall(m_CallId, 0, EV_ASYNC) == 0)
  1966. {
  1967. CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_RING_BACK, m_CallerNum, m_CalleeNum);
  1968. return true;
  1969. }
  1970. else
  1971. {
  1972. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  1973. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]AcceptCall失败, 呼叫释放, Caller = %s, Callee = %s"),
  1974. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1975. return false;
  1976. }
  1977. }
  1978. else if(m_State == GCST_CONNECTED) // ocx发出的呼叫请求
  1979. {
  1980. if(!playTone(CHANNEL_TONE_RINGBACK)) // 对a-leg放振铃音
  1981. {
  1982. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]播放回铃音失败, Caller = %s, Callee = %s"),
  1983. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1984. }
  1985. return true;
  1986. }
  1987. else
  1988. {
  1989. ASSERT(FALSE);
  1990. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  1991. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]响应呼叫时状态异常, 呼叫释放,m_CallId=%ld, Caller = %s, Callee = %s"),
  1992. m_CallId,m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  1993. return false;
  1994. }
  1995. }
  1996. /*****************************************************************
  1997. **【函数名称】 progress
  1998. **【函数功能】 呼叫进展
  1999. **【参数】
  2000. **【返回值】
  2001. ****************************************************************/
  2002. bool CVoipChannel::progress( void )
  2003. {
  2004. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行progress, State = %d"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_State);
  2005. switch(m_State)
  2006. {
  2007. case GCST_OFFERED:
  2008. case GCST_ACCEPTED: // 话机直接发起的呼叫请求
  2009. {
  2010. GCPARAMEX_CALLPROGRESS gcCallProcess;
  2011. __constructProgressBody(&gcCallProcess);
  2012. ASSERT(m_pBindIpmCh != NULL);
  2013. if(ISX_gc_CallProgress(m_CallId, 0, EV_ASYNC, &gcCallProcess) != 0 || !m_pBindIpmCh->startMedia())
  2014. {
  2015. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  2016. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]progress失败, 呼叫释放, Caller = %s, Callee = %s"),
  2017. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  2018. return false;
  2019. }
  2020. return true;
  2021. }
  2022. break;
  2023. case GCST_CONNECTED: // ocx发出的呼叫请求
  2024. {
  2025. // 停止A-Leg的振铃音
  2026. playTone(CHANNEL_TONE_NULL);
  2027. return true;
  2028. }
  2029. break;
  2030. default:
  2031. {
  2032. ASSERT(FALSE);
  2033. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  2034. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]progress状态异常, 呼叫释放, Caller = %s, Callee = %s"),
  2035. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  2036. return false;
  2037. }
  2038. }
  2039. }
  2040. /*****************************************************************
  2041. **【函数名称】 accept
  2042. **【函数功能】 应答呼叫
  2043. **【参数】
  2044. **【返回值】
  2045. ****************************************************************/
  2046. bool CVoipChannel::accept( void )
  2047. {
  2048. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行accept, State = %d"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_State);
  2049. // b-leg接通
  2050. switch(m_State)
  2051. {
  2052. case GCST_OFFERED:
  2053. case GCST_ACCEPTED: // 话机直接发起的呼叫请求
  2054. {
  2055. GCPARAMEX_ANSWERCALL AnswerCallEx;
  2056. __constructAnswerBody(&AnswerCallEx);
  2057. if(ISX_gc_AnswerCall(m_CallId, 0, EV_ASYNC, &AnswerCallEx) != 0)
  2058. {
  2059. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]呼叫释放, a-leg应答呼叫失败, Caller = %s, Callee = %s"),
  2060. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  2061. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  2062. return false;
  2063. }
  2064. }
  2065. break;
  2066. case GCST_CONNECTED: // ocx发出的呼叫请求
  2067. {
  2068. // 停止A-Leg的振铃音
  2069. playTone(CHANNEL_TONE_NULL);
  2070. CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_TALKING, m_CallerNum, m_CalleeNum);
  2071. }
  2072. break;
  2073. default:
  2074. {
  2075. ASSERT(FALSE);
  2076. __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
  2077. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]呼叫释放, a-leg应答呼叫时处于异常状态, Caller = %s, Callee = %s"),
  2078. m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
  2079. return false;
  2080. }
  2081. }
  2082. return true;
  2083. }
  2084. /*****************************************************************
  2085. **【函数名称】 onPlayEnd
  2086. **【函数功能】 放音结束处理函数
  2087. **【参数】
  2088. **【返回值】
  2089. ****************************************************************/
  2090. void CVoipChannel::onPlayEnd( LPCTSTR lpDtmf )
  2091. {
  2092. // 通知呼叫控制层放音结束事件
  2093. CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, DEV_CH_EVT_PLAY_END, lpDtmf);
  2094. }
  2095. /*****************************************************************
  2096. **【函数名称】 onRecEnd
  2097. **【函数功能】 录音结束处理函数
  2098. **【参数】
  2099. **【返回值】
  2100. ****************************************************************/
  2101. void CVoipChannel::onRecEnd( UINT TaskId )
  2102. {
  2103. // 通知呼叫控制层录音结束事件
  2104. CString strTmp;
  2105. strTmp.Format(_T("%lu"), TaskId);
  2106. CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, DEV_CH_EVT_REC_END, strTmp);
  2107. }
  2108. /*****************************************************************
  2109. **【函数名称】 onToneEnd
  2110. **【函数功能】 tone音结束处理函数
  2111. **【参数】
  2112. **【返回值】
  2113. ****************************************************************/
  2114. void CVoipChannel::onToneEnd( int ToneTp )
  2115. {
  2116. // TODO: do nothing
  2117. }
  2118. /*****************************************************************
  2119. **【函数名称】 onFaxEnd
  2120. **【函数功能】 传真结束处理函数
  2121. **【参数】
  2122. **【返回值】
  2123. ****************************************************************/
  2124. void CVoipChannel::onFaxEnd( bool IsSuccess, LPCTSTR Reason )
  2125. {
  2126. CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, IsSuccess ? DEV_CH_EVT_FAX_OK : DEV_CH_EVT_FAX_FAILED, Reason);
  2127. __clearCall(IPEC_SIPReasonStatus200OK);
  2128. }
  2129. /*****************************************************************
  2130. **【函数名称】 getStateStr
  2131. **【函数功能】 返回状态字符串
  2132. **【参数】
  2133. **【返回值】
  2134. ****************************************************************/
  2135. LPCTSTR CVoipChannel::getStateStr( void ) const
  2136. {
  2137. if(m_IsBlocked)
  2138. return _T("block");
  2139. switch(m_State)
  2140. {
  2141. case GCST_NULL: return _T("free");
  2142. case GCST_DIALING: return _T("calling");
  2143. case GCST_OFFERED: return _T("alerting");
  2144. case GCST_ALERTING: return _T("ringback");
  2145. case GCST_CONNECTED: return _T("talking");
  2146. default: return _T("unknown");
  2147. }
  2148. }