升龙物业 老版本 ocx IPO, 加密狗 转值班电话

VoipChannel.cpp 78KB

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