| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463 |
- #include "StdAfx.h"
- #include "VoipChannel.h"
- #include "ControlShell.h"
- #include "Config.h"
- #include "MC.h"
- #include "ProxyShell.h"
- #include "ProxyExten.h"
- #include "IpmChannel.h"
- #include "DspChannel.h"
- #include "SessionShell.h"
- CVoipChannel::CImplement4Trunk CVoipChannel::ms_Implement4Trunk;
- CVoipChannel::CImplement4Exten CVoipChannel::ms_Implement4Exten;
- /*****************************************************************
- **【函数名称】 __constructMakeCallBody
- **【函数功能】 构造呼叫SIP协议体
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::CImplement4Trunk::__constructMakeCallBody( GCPARAMEX_MAKECALL* pMakeCallEx, CVoipChannel& Chan, CIpmChannel* pImpChan, SIP_ACCOUNT* pAccount )
- {
- ASSERT(pImpChan != NULL);
- int nIndex;
- pMakeCallEx->Protocol = eGCPro_SIP;
- #pragma region To,From,contact,Auth
- pMakeCallEx->u.SIPInviteExReq.To.Valid = 1;
- pMakeCallEx->u.SIPInviteExReq.From.Valid = 1;
- ISXSIP_IE_ADDR* pMakeCallTo = &pMakeCallEx->u.SIPInviteExReq.To.Addr;
- ISXSIP_IE_ADDR* pMakeCallFrom = &pMakeCallEx->u.SIPInviteExReq.From.Addr;
- //TO域
- pMakeCallTo->Valid = 1;
- pMakeCallTo->AddType= ISXSIP_ADDTYPE_URL;
- pMakeCallTo->u.AddrUrl.PortNum = pAccount->ProxyPort;
- pMakeCallTo->u.AddrUrl.Ttl = 0xFFFF;
- pMakeCallTo->u.AddrUrl.LrType = 0xFF;
- pMakeCallTo->u.AddrUrl.MethodType = 0xFF;
- lstrcpy(pMakeCallTo->u.AddrUrl.User, Chan.m_CalleeNum);
- lstrcpy(pMakeCallTo->u.AddrUrl.Host, pAccount->Proxy);
- //FROM域
- pMakeCallFrom->Valid = 1;
- pMakeCallFrom->AddType = ISXSIP_ADDTYPE_URL;
- pMakeCallFrom->u.AddrUrl.PortNum = 0xFFFF;
- pMakeCallFrom->u.AddrUrl.Ttl = 0xFFFF;
- pMakeCallFrom->u.AddrUrl.LrType = 0xFF;
- pMakeCallFrom->u.AddrUrl.MethodType = 0xFF;
- lstrcpy(pMakeCallFrom->u.AddrUrl.User, Chan.m_CallerNum);
- lstrcpy(pMakeCallFrom->u.AddrUrl.Host, pAccount->Proxy);
- // CONTACT域
- ISXSIP_IE_REFERRED_BY *pReferBy = &pMakeCallEx->u.SIPInviteExReq.RefBy;
- pReferBy->Valid = 2;
- ISXSIP_IE_ADDR_EX *pContact = &pReferBy->cont_ruri.Contact;
- pContact->AddType = ISXSIP_ADDTYPE_URL;
- ISX_sr_default(PARMID_ISXSIP_ADDR_URL_EX, &pContact->u.AddrUrl);
- lstrcpy(pContact->u.AddrUrl.User, pAccount->Account);
- lstrcpy(pContact->u.AddrUrl.Host, CConfig::voipSignallingAddr());
- ISXSIP_IE_ADDR_EX *pRequestURI = &pReferBy->cont_ruri.RequestURI;
- pRequestURI->AddType = ISXSIP_ADDTYPE_URL;
- ISX_sr_default(PARMID_ISXSIP_ADDR_URL_EX, &pRequestURI->u.AddrUrl);
- lstrcpy(pRequestURI->u.AddrUrl.User, Chan.m_CalleeNum);
- lstrcpy(pRequestURI->u.AddrUrl.Host, pAccount->Proxy);
- //Auth
- char* pUser = pMakeCallEx->u.SIPInviteExReq.LongAuthInfo.AuthStr;
- ZeroMemory(pUser, 100);
- lstrcpy(pUser, pAccount->AuthAccount);
- char *pPwd = pUser + strlen(pUser) + 1;
- lstrcpy(pPwd, pAccount->Password);
- #pragma endregion
- #pragma region Media Part
- TCHAR MediaAddr[MAX_PATH] = { 0 };
- getMediaAddr(pImpChan, MediaAddr);
- pMakeCallEx->u.SIPInviteExReq.Body.Valid = 1;
- pMakeCallEx->u.SIPInviteExReq.Body.BodyPartyType = BodyPartyType_SDP;
- ISXSIP_IE_BODY_SDP_EX* pSdp = &pMakeCallEx->u.SIPInviteExReq.Body.u.BodySdp;
- pSdp->SdpNum = 0;
- //o
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ORIGIN;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_ORIGIN);
- pSdp->Sdp[nIndex].u.Origin.NetType = ISXSIP_SDPNETTYPE_IN;
- pSdp->Sdp[nIndex].u.Origin.AddrType = ISXSIP_SDPADDRTYPE_IP4;
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.SessionId, "20");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.UserName, "EHang");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.Version, "001");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.Addr, MediaAddr);
- pSdp->SdpNum++;
- //s
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION);
- lstrcpy(pSdp->Sdp[nIndex].u.Session.Name, "EH-Call");
- lstrcpy(pSdp->Sdp[nIndex].u.Session.Info, "");
- pSdp->SdpNum++;
- //c
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONNECTION;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_CONNECTION);
- pSdp->Sdp[nIndex].u.Connection.NetType = ISXSIP_SDPNETTYPE_IN;
- pSdp->Sdp[nIndex].u.Connection.AddrType = ISXSIP_SDPADDRTYPE_IP4;
- lstrcpy(pSdp->Sdp[nIndex].u.Connection.Addr, MediaAddr);
- pSdp->SdpNum++;
- //t
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION_TIME;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION_TIME);
- pSdp->Sdp[nIndex].u.SessionTime.Start = 0;
- pSdp->Sdp[nIndex].u.SessionTime.End = 0;
- pSdp->SdpNum++;
- //m
- int iCodecId;
- int iPayLoad;
- ISXSIP_IE_SDP_MEDIA_DESC_EX DspMediaDescEx;
- DspMediaDescEx.MediaPort = pImpChan->mediaPort();
- DspMediaDescEx.MediaProtocol = ISXSIP_SDPPROTOCOL_RTP;
- DspMediaDescEx.MediaType = ISXSIP_SDPMEDIATYPE_AUDIO;
- int iPLIndex = 0;
- iCodecId = AudioCodec_G711_ALAW_20MS;
- ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &iCodecId);
- DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
- iCodecId = AudioCodec_G729_20MS;
- ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &iCodecId);
- DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
- DspMediaDescEx.Payload[iPLIndex++] = 101;
- DspMediaDescEx.PayLoadNum = iPLIndex;
- ISX_sr_insertparm(&pMakeCallEx->u.SIPInviteExReq.Body, SIPPARMID_MEDIADESC, sizeof(DspMediaDescEx), &DspMediaDescEx);
- IP_AUDIO_CAPABILITY AudioCodec;
- AudioCodec.iCodecId = AudioCodec_G711_ALAW_20MS;
- ISX_sr_insertparm(&pMakeCallEx->u.SIPInviteExReq.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
- AudioCodec.iCodecId = AudioCodec_G729_20MS;
- ISX_sr_insertparm(&pMakeCallEx->u.SIPInviteExReq.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_RTP_MAP;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_RTP_MAP);
- ISXSIP_IE_SDP_RTP_MAP* pSdpRtpMap = &pSdp->Sdp[nIndex].u.RtpMap;
- pSdpRtpMap->Payload = 101;
- pSdpRtpMap->ClkRate = 8000;
- lstrcpy(pSdpRtpMap->EncodingName, "telephone-event");
- lstrcpy(pSdpRtpMap->EncodingParam, "1");
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "fmtp");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "101 0-15");
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "ptime");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "20");
- pSdp->SdpNum++;
- #pragma endregion
- }
- /*****************************************************************
- **【函数名称】 __onOffered
- **【函数功能】 处理来电呼叫
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::CImplement4Trunk::onOffered( CVoipChannel& Chan, GCPARAMEX_MAKECALL* pMakeCallEx )
- {
- CSessionShell::GetInstance().onLineStateChanged(Chan.m_Id, Chan.m_SessionCode, VIRTUAL_LINE_STATE_ALERTING, Chan.m_CallerNum, Chan.m_CalleeNum);
- //发送TRY
- ISX_gc_SIPSendTrying(Chan.m_CallId, EV_ASYNC);
- ASSERT(Chan.m_pBindIpmCh == NULL);
- if((Chan.m_pBindIpmCh = CMC::GetInstance().allocIpmCh4SipCh(Chan.m_Id.NodeNo, Chan.m_Id.BoardNo)) == NULL)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理中继来电出错, 无可用的IPM资源, 呼叫将释放, Caller = %s, Callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- Chan.__clearCall(IPEC_SIPReasonStatus486BusyHere);
- return;
- }
- Chan.m_pBindIpmCh->bind(&Chan);
- // 协商媒体编解码
- if(!Chan.__getCallMediaDesc(&pMakeCallEx->u.SIPInvite.Body))
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理中继来电时协商媒体编解码失败, 呼叫将释放, Caller = %s, Callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- Chan.__clearCall(IPEC_SIPReasonStatus415UnsupportedMediaType);
- return;
- }
- // 启动媒体
- if(!Chan.m_pBindIpmCh->isStarted())
- {
- if(!Chan.m_pBindIpmCh->startMedia())
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理中继来电时IPM资源启动失败, 呼叫将释放, Caller = %s, Callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- Chan.__clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- return;
- }
- }
- GCPARAMEX_ANSWERCALL AnswerCallEx;
- Chan.__constructAnswerBody(&AnswerCallEx);
- if(ISX_gc_AnswerCall(Chan.m_CallId, 0, EV_ASYNC, &AnswerCallEx) != 0)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]应答中继来电失败, 呼叫将释放, Caller = %s, Callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- Chan.__clearCall(IPEC_SIPReasonStatus486BusyHere);
- }
- }
- /*****************************************************************
- **【函数名称】 onAlerting
- **【函数功能】 处理远端振铃
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::CImplement4Trunk::onAlerting( CVoipChannel& Chan, METAEVENT* pMetaEvent )
- {
- GCPARAMEX_ACCEPTCALL* pAcceptCall = (GCPARAMEX_ACCEPTCALL*)ISX_sr_getevtdatap();
- ASSERT(pAcceptCall != NULL);
- if(pAcceptCall->u.SIPRing.Body.Valid == 1)
- {
- // 协商媒体编解码
- if(!Chan.__getCallMediaDesc(&pAcceptCall->u.SIPRing.Body))
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理Alerting时协商媒体编解码失败, 呼叫将释放, Caller = %s, Callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- Chan.__clearCall(IPEC_SIPReasonStatus415UnsupportedMediaType);
- return;
- }
- // 启动媒体
- ASSERT(Chan.m_pBindIpmCh != NULL);
- if(!Chan.m_pBindIpmCh->isStarted())
- {
- if(!Chan.m_pBindIpmCh->startMedia())
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理Alerting时IPM资源启动失败, 呼叫将释放, Caller = %s, Callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- Chan.__clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- return;
- }
- }
- CSessionShell::GetInstance().onLineStateChanged(Chan.m_Id, Chan.m_SessionCode, VIRTUAL_LINE_STATE_PROGRESSING, Chan.m_CallerNum, Chan.m_CalleeNum);
- }
- CSessionShell::GetInstance().onLineStateChanged(Chan.m_Id, Chan.m_SessionCode, VIRTUAL_LINE_STATE_RING_BACK, Chan.m_CallerNum, Chan.m_CalleeNum);
- }
- /*****************************************************************
- **【函数名称】 makeCall
- **【函数功能】 呼叫
- **【参数】
- **【返回值】 成功true,失败false
- ****************************************************************/
- bool CVoipChannel::CImplement4Trunk::makeCall( CVoipChannel& Chan, int AccountId )
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]中继模式下执行呼叫请求, caller = %s, callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- SIP_ACCOUNT* pAccount = CConfig::sipAccount().getAccount(AccountId);
- ASSERT(pAccount != NULL);
- if(pAccount == NULL)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]进行中继呼叫时查找SIP账户[%d]失败, 呼叫将释放, Caller = %s, Callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, AccountId, Chan.m_CallerNum, Chan.m_CalleeNum);
- return false;
- }
- ASSERT(Chan.m_pBindIpmCh == NULL);
- if((Chan.m_pBindIpmCh = CMC::GetInstance().allocIpmCh4SipCh(Chan.m_Id.NodeNo, Chan.m_Id.BoardNo)) == NULL)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]进行中继呼叫时分配IPM资源失败, 呼叫将释放, Caller = %s, Callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- return false;
- }
- Chan.m_pBindIpmCh->bind(&Chan);
- GCPARAMEX_MAKECALL MakeCallEx;
- ISX_sr_default(PARMID_SIP_INVITE, &MakeCallEx.u.SIPInviteExReq);
-
- __constructMakeCallBody(&MakeCallEx, Chan, Chan.m_pBindIpmCh, pAccount);
- return ISXE_gc_MakeCall(Chan.m_Handle, &Chan.m_CallId, NULL, NULL, -1, EV_ASYNC, &MakeCallEx) == 0;
- }
- /*****************************************************************
- **【函数名称】 getMediaAddr
- **【函数功能】 获取媒体地址
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::CImplement4Trunk::getMediaAddr( CIpmChannel* pImpChan, LPTSTR Buffer )
- {
- ASSERT(pImpChan != NULL);
- pImpChan->mediaAddrTrunk(Buffer);
- }
- /*****************************************************************
- **【函数名称】 __constructMakeCallBody
- **【函数功能】 构造呼叫SIP协议体
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::CImplement4Exten::__constructMakeCallBody( GCPARAMEX_MAKECALL* pMakeCallEx, CIpmChannel* pImpChan )
- {
- ASSERT(pImpChan != NULL);
- TCHAR MediaAddr[MAX_PATH] = { 0 };
- getMediaAddr(pImpChan, MediaAddr);
- int nIndex;
- pMakeCallEx->Protocol = eGCPro_SIP;
- pMakeCallEx->u.SIPInvite.Body.Valid = 1;
- pMakeCallEx->u.SIPInvite.Body.BodyPartyType = BodyPartyType_SDP;
- ISXSIP_IE_BODY_SDP_EX* pSdp = &pMakeCallEx->u.SIPInvite.Body.u.BodySdp;
- pSdp->SdpNum = 0;
- //o
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ORIGIN;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_ORIGIN);
- pSdp->Sdp[nIndex].u.Origin.NetType = ISXSIP_SDPNETTYPE_IN;
- pSdp->Sdp[nIndex].u.Origin.AddrType = ISXSIP_SDPADDRTYPE_IP4;
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.SessionId, "20");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.UserName, "EHang");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.Version, "001");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.Addr, MediaAddr);
- pSdp->SdpNum++;
- //s
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION);
- lstrcpy(pSdp->Sdp[nIndex].u.Session.Name, "EH-Call");
- lstrcpy(pSdp->Sdp[nIndex].u.Session.Info, "");
- pSdp->SdpNum++;
- //c
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONNECTION;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_CONNECTION);
- pSdp->Sdp[nIndex].u.Connection.NetType = ISXSIP_SDPNETTYPE_IN;
- pSdp->Sdp[nIndex].u.Connection.AddrType = ISXSIP_SDPADDRTYPE_IP4;
- sprintf_s(pSdp->Sdp[nIndex].u.Connection.Addr, 32, MediaAddr);
- pSdp->SdpNum++;
- //t
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION_TIME;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION_TIME);
- pSdp->Sdp[nIndex].u.SessionTime.Start = 0;
- pSdp->Sdp[nIndex].u.SessionTime.End = 0;
- pSdp->SdpNum++;
- //m
- int iCodecId;
- int iPayLoad;
- ISXSIP_IE_SDP_MEDIA_DESC_EX DspMediaDescEx;
- DspMediaDescEx.MediaPort = pImpChan->mediaPort();
- DspMediaDescEx.MediaProtocol = ISXSIP_SDPPROTOCOL_RTP;
- DspMediaDescEx.MediaType = ISXSIP_SDPMEDIATYPE_AUDIO;
- int iPLIndex = 0;
- iCodecId = AudioCodec_G711_ALAW_20MS;
- ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &iCodecId);
- DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
- iCodecId = AudioCodec_G729_20MS;
- ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &iCodecId);
- DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
- DspMediaDescEx.Payload[iPLIndex++] = 101;
- DspMediaDescEx.PayLoadNum = iPLIndex;
- ISX_sr_insertparm(&pMakeCallEx->u.SIPInvite.Body, SIPPARMID_MEDIADESC, sizeof(DspMediaDescEx), &DspMediaDescEx);
- IP_AUDIO_CAPABILITY AudioCodec;
- AudioCodec.iCodecId = AudioCodec_G711_ALAW_20MS;
- ISX_sr_insertparm(&pMakeCallEx->u.SIPInvite.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
- AudioCodec.iCodecId = AudioCodec_G729_20MS;
- ISX_sr_insertparm(&pMakeCallEx->u.SIPInvite.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_RTP_MAP;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_RTP_MAP);
- ISXSIP_IE_SDP_RTP_MAP* pSdpRtpMap = &pSdp->Sdp[nIndex].u.RtpMap;
- pSdpRtpMap->Payload = 101;
- pSdpRtpMap->ClkRate = 8000;
- lstrcpy(pSdpRtpMap->EncodingName, "telephone-event");
- lstrcpy(pSdpRtpMap->EncodingParam, "1");
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "fmtp");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "101 0-15");
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "ptime");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "20");
- pSdp->SdpNum++;
- }
- /*****************************************************************
- **【函数名称】 __onOffered
- **【函数功能】 处理来电呼叫
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::CImplement4Exten::onOffered( CVoipChannel& Chan, GCPARAMEX_MAKECALL* pMakeCallEx )
- {
- //发送TRY
- ISX_gc_SIPSendTrying(Chan.m_CallId, EV_ASYNC);
- Chan.m_ExtenNo = atoi(Chan.m_CallerNum);
- ASSERT(Chan.m_pBindIpmCh == NULL);
- if((Chan.m_pBindIpmCh = CMC::GetInstance().allocIpmCh4SipCh(Chan.m_Id.NodeNo, Chan.m_Id.BoardNo)) == NULL)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理分机来电出错, 无可用的IPM资源, 呼叫将释放, Caller = %s, Callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- Chan.__clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- return;
- }
- Chan.m_pBindIpmCh->bind(&Chan);
- // 协商媒体编解码
- if(!Chan.__getCallMediaDesc(&pMakeCallEx->u.SIPInvite.Body))
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理分机来电时协商媒体编解码失败, 呼叫将释放, Caller = %s, Callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- Chan.__clearCall(IPEC_SIPReasonStatus415UnsupportedMediaType);
- return;
- }
- if(!CSessionShell::GetInstance().onLineChannelEvent(Chan.m_Id, Chan.m_SessionCode, DEV_CH_EVT_FUN_CODE, Chan.m_CalleeNum, Chan.m_ExtenNo))
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理座席分机来电失败, 呼叫将释放, Caller = %s, Callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- Chan.__clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- }
- }
- /*****************************************************************
- **【函数名称】 onAlerting
- **【函数功能】 处理远端振铃
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::CImplement4Exten::onAlerting( CVoipChannel& Chan, METAEVENT* pMetaEvent )
- {
- if(Chan.m_Job == DEV_LINE_CH_JOB_NONE)
- CSessionShell::GetInstance().onLineStateChanged(Chan.m_Id, Chan.m_SessionCode, VIRTUAL_LINE_STATE_ALERTING, Chan.m_CallerNum, Chan.m_CalleeNum);
- }
- /*****************************************************************
- **【函数名称】 makeCall
- **【函数功能】 呼叫
- **【参数】
- **【返回值】 成功true,失败false
- ****************************************************************/
- bool CVoipChannel::CImplement4Exten::makeCall( CVoipChannel& Chan, int AccountId )
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]分机模式下执行呼叫请求, caller = %s, callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- ASSERT(Chan.m_pBindIpmCh == NULL);
- if((Chan.m_pBindIpmCh = CMC::GetInstance().allocIpmCh4SipCh(Chan.m_Id.NodeNo, Chan.m_Id.BoardNo)) == NULL)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]进行分机呼叫时分配IPM资源失败, 呼叫将释放, Caller = %s, Callee = %s"),
- Chan.m_Id.NodeNo, Chan.m_Id.BoardNo, Chan.m_Id.ChanNo, Chan.m_CallerNum, Chan.m_CalleeNum);
- return false;
- }
- Chan.m_pBindIpmCh->bind(&Chan);
- TCHAR Callee[SIP_URI_LEN] = { 0 };
- TCHAR Caller[SIP_URI_LEN] = { 0 };
- TCHAR ProxyIp[MAX_PATH] = { 0 };
- Chan.__getVoipAddr(ProxyIp);
- Chan.m_ExtenNo = atoi(Chan.m_CalleeNum);
- Chan.__getExtenAddrInfo(Chan.m_CalleeNum, Callee, SIP_URI_LEN);
- sprintf_s(Caller, SIP_URI_LEN, _T("%s@%s\0"), Chan.m_CallerNum, ProxyIp);
- GCPARAMEX_MAKECALL MakeCallEx;
- ISX_sr_default(PARMID_SIP_INVITE, &MakeCallEx.u.SIPInvite);
- ISX_sr_setparm(&MakeCallEx.u.SIPInvite, SIPPARMID_DESTADD, strlen(Callee), Callee);
- ISX_sr_setparm(&MakeCallEx.u.SIPInvite, SIPPARMID_SRCADD, strlen(Caller), Caller);
- __constructMakeCallBody(&MakeCallEx, Chan.m_pBindIpmCh);
- return ISX_gc_MakeCall(Chan.m_Handle, &Chan.m_CallId, Callee, NULL, -1, EV_ASYNC, &MakeCallEx) == 0;
- }
- /*****************************************************************
- **【函数名称】 getMediaAddr
- **【函数功能】 获取媒体地址
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::CImplement4Exten::getMediaAddr( CIpmChannel* pImpChan, LPTSTR Buffer )
- {
- ASSERT(pImpChan != NULL);
- pImpChan->mediaAddrBoard(Buffer);
- }
- CVoipChannel::CVoipChannel(DEV_RES_CH_TYPE ChannelNo, DEV_RES_NO_TYPE NodeNo, DEV_RES_NO_TYPE BoardNo)
- : CChannelResource(DEV_RES_TYPE_VOIP, NodeNo, BoardNo, DEVICE_RES_NO_ANY, ChannelNo), m_pImplement(NULL), m_CallId(0), m_IsBlocked(false),
- m_Job(DEV_LINE_CH_JOB_NONE), m_ExtenNo(0), m_Mixer(*this), m_pBindIpmCh(NULL), m_MediaPort(0), m_CodecId(-1)
- {
- }
- CVoipChannel::~CVoipChannel(void)
- {
- close();
- }
- /*****************************************************************
- **【函数名称】 __clearCall
- **【函数功能】 清除呼叫
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::__clearCall( int Cause )
- {
- if(m_CallId == 0)
- return false;
- m_State = GCST_DROPCALLING;
- if(m_MeetingInfo.MeetingId != MEETING_ID_INVALID)
- CMC::GetInstance().meetingRemove(this, m_MeetingInfo);
- m_Mixer.release();
- if(ISX_gc_DropCall(m_CallId, Cause, EV_ASYNC) == 0)
- {
- m_CallId = 0;
- return true;
- }
- else return false;
- }
- /*****************************************************************
- **【函数名称】 __getVoipAddr
- **【函数功能】 获取
- **【参数】
- **【返回值】 成功true,失败false
- ****************************************************************/
- bool CVoipChannel::__getVoipAddr( LPTSTR AddrBuf )
- {
- return ISX_sr_getnet2cfg(m_Id.NodeNo, m_Id.BoardNo, BT_SIP, AddrBuf, NULL) == 0;
- }
- /*****************************************************************
- **【函数名称】 __getExtenAddrInfo
- **【函数功能】 获取SIP分机地址信息
- **【参数】
- **【返回值】 成功true,失败false
- ****************************************************************/
- bool CVoipChannel::__getExtenAddrInfo( LPCTSTR Exten, LPTSTR pContactAddr, int Len )
- {
- ISXSIP_REGUSER RegUser;
- if(ISXE_gc_SipGetRegisterUser(Exten, &RegUser) == 0)
- {
- if(RegUser.PortNum != 0xffff && RegUser.PortNum != 0)
- sprintf_s(pContactAddr, Len, _T("%s@%s:%d\0"), Exten, RegUser.IpAddr, RegUser.PortNum);
- else
- sprintf_s(pContactAddr, Len, _T("%s@%s\0"), Exten, RegUser.IpAddr);
- return true;
- }
- return false;
- }
- /*****************************************************************
- **【函数名称】 __constructAnswerBody
- **【函数功能】 构造应答SIP协议体
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__constructAnswerBody( GCPARAMEX_ANSWERCALL* pAnswerCallEx )
- {
- memset(pAnswerCallEx, 0, sizeof(*pAnswerCallEx));
- pAnswerCallEx->Protocol = eGCPro_SIP;
- pAnswerCallEx->u.SIPConn.Body.Valid = 1;
- pAnswerCallEx->u.SIPConn.Body.BodyPartyType = BodyPartyType_SDP;
- ISXSIP_IE_BODY_SDP_EX* pSdp = &pAnswerCallEx->u.SIPConn.Body.u.BodySdp;
- pSdp->SdpNum = 0;
- TCHAR MediaAddr[MAX_PATH] = { 0 };
- ASSERT(m_pBindIpmCh != NULL);
- m_pImplement->getMediaAddr(m_pBindIpmCh, MediaAddr);
- //o
- int nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ORIGIN;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_ORIGIN);
- pSdp->Sdp[nIndex].u.Origin.NetType = ISXSIP_SDPNETTYPE_IN;
- pSdp->Sdp[nIndex].u.Origin.AddrType = ISXSIP_SDPADDRTYPE_IP4;
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.SessionId, "20");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.UserName, "EHang");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.Version, "001");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.Addr, MediaAddr);
- pSdp->SdpNum++;
- //s
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION);
- lstrcpy(pSdp->Sdp[nIndex].u.Session.Name, "EH-Call");
- lstrcpy(pSdp->Sdp[nIndex].u.Session.Info, "");
- pSdp->SdpNum++;
- //c
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONNECTION;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_CONNECTION);
- pSdp->Sdp[nIndex].u.Connection.NetType = ISXSIP_SDPNETTYPE_IN;
- pSdp->Sdp[nIndex].u.Connection.AddrType = ISXSIP_SDPADDRTYPE_IP4;
- lstrcpy(pSdp->Sdp[nIndex].u.Connection.Addr, MediaAddr);
- pSdp->SdpNum++;
- //t
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION_TIME;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION_TIME);
- pSdp->Sdp[nIndex].u.SessionTime.Start = 0;
- pSdp->Sdp[nIndex].u.SessionTime.End = 0;
- pSdp->SdpNum++;
- //m
- ISXSIP_IE_SDP_MEDIA_DESC_EX DspMediaDescEx;
- DspMediaDescEx.MediaPort = m_pBindIpmCh->mediaPort();
- DspMediaDescEx.MediaProtocol = ISXSIP_SDPPROTOCOL_RTP;
- DspMediaDescEx.MediaType = ISXSIP_SDPMEDIATYPE_AUDIO;
- int iPLIndex = 0;
- int nPayLoad = 0;
- ISX_sr_convert(CONID_CODECID2PLAYLOAD, &nPayLoad, &m_CodecId);
- DspMediaDescEx.Payload[iPLIndex++] = nPayLoad;
- DspMediaDescEx.Payload[iPLIndex++] = 101;
- DspMediaDescEx.PayLoadNum = iPLIndex;
- ISX_sr_insertparm(&pAnswerCallEx->u.SIPConn.Body, SIPPARMID_MEDIADESC, sizeof(DspMediaDescEx), &DspMediaDescEx);
- IP_AUDIO_CAPABILITY AudioCodec;
- AudioCodec.iCodecId = (eAUDIOCODEC)m_CodecId;
- ISX_sr_insertparm(&pAnswerCallEx->u.SIPConn.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_RTP_MAP;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_RTP_MAP);
- ISXSIP_IE_SDP_RTP_MAP* pSdpRtpMap = &pSdp->Sdp[nIndex].u.RtpMap;
- pSdpRtpMap->Payload = 101;
- pSdpRtpMap->ClkRate = 8000;
- lstrcpy(pSdpRtpMap->EncodingName, "telephone-event");
- lstrcpy(pSdpRtpMap->EncodingParam, "1");
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "fmtp");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "101 0-15");
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "ptime");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "20");
- pSdp->SdpNum++;
- }
- /*****************************************************************
- **【函数名称】 __constructProgressBody
- **【函数功能】 构造呼叫进展SIP协议体
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__constructProgressBody( GCPARAMEX_CALLPROGRESS* pProgressEx )
- {
- memset(pProgressEx, 0, sizeof(*pProgressEx));
- pProgressEx->Protocol = eGCPro_SIP;
- pProgressEx->u.SIPProgress.Body.Valid = 1;
- pProgressEx->u.SIPProgress.Body.BodyPartyType = BodyPartyType_SDP;
- ISXSIP_IE_BODY_SDP_EX* pSdp = &pProgressEx->u.SIPProgress.Body.u.BodySdp;
- pSdp->SdpNum = 0;
- TCHAR MediaAddr[MAX_PATH] = { 0 };
- ASSERT(m_pBindIpmCh != NULL);
- m_pImplement->getMediaAddr(m_pBindIpmCh, MediaAddr);
- int nIndex;
- //o
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ORIGIN;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_ORIGIN);
- pSdp->Sdp[nIndex].u.Origin.NetType = ISXSIP_SDPNETTYPE_IN;
- pSdp->Sdp[nIndex].u.Origin.AddrType = ISXSIP_SDPADDRTYPE_IP4;
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.SessionId, "20");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.UserName, "EHang");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.Version, "001");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.Addr, MediaAddr);
- pSdp->SdpNum++;
- //s
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION);
- lstrcpy(pSdp->Sdp[nIndex].u.Session.Name, "EH-Call");
- lstrcpy(pSdp->Sdp[nIndex].u.Session.Info, "");
- pSdp->SdpNum++;
- //c
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONNECTION;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_CONNECTION);
- pSdp->Sdp[nIndex].u.Connection.NetType = ISXSIP_SDPNETTYPE_IN;
- pSdp->Sdp[nIndex].u.Connection.AddrType = ISXSIP_SDPADDRTYPE_IP4;
- lstrcpy(pSdp->Sdp[nIndex].u.Connection.Addr, MediaAddr);
- pSdp->SdpNum++;
- //t
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION_TIME;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION_TIME);
- pSdp->Sdp[nIndex].u.SessionTime.Start = 0;
- pSdp->Sdp[nIndex].u.SessionTime.End = 0;
- pSdp->SdpNum++;
- //m
- ISXSIP_IE_SDP_MEDIA_DESC_EX DspMediaDescEx;
- DspMediaDescEx.MediaPort = m_pBindIpmCh->mediaPort();
- DspMediaDescEx.MediaProtocol = ISXSIP_SDPPROTOCOL_RTP;
- DspMediaDescEx.MediaType = ISXSIP_SDPMEDIATYPE_AUDIO;
- int iPLIndex = 0;
- int iPayLoad = 0;
- if(m_CodecId != -1)
- {
- ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &m_CodecId);
- DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
- }
- else
- {
- int iCodecId = AudioCodec_G711_ALAW_20MS;
- ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &iCodecId);
- DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
- iCodecId = AudioCodec_G729_20MS;
- ISX_sr_convert(CONID_CODECID2PLAYLOAD, &iPayLoad, &iCodecId);
- DspMediaDescEx.Payload[iPLIndex++] = iPayLoad;
- }
- DspMediaDescEx.Payload[iPLIndex++] = 101;
- DspMediaDescEx.PayLoadNum = iPLIndex;
- ISX_sr_insertparm(&pProgressEx->u.SIPProgress.Body, SIPPARMID_MEDIADESC, sizeof(DspMediaDescEx), &DspMediaDescEx);
- IP_AUDIO_CAPABILITY AudioCodec;
- if(m_CodecId != -1)
- {
- AudioCodec.iCodecId = (eAUDIOCODEC)m_CodecId;
- ISX_sr_insertparm(&pProgressEx->u.SIPProgress.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
- }
- else
- {
- AudioCodec.iCodecId = AudioCodec_G711_ALAW_20MS;
- ISX_sr_insertparm(&pProgressEx->u.SIPProgress.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
- AudioCodec.iCodecId = AudioCodec_G729_20MS;
- ISX_sr_insertparm(&pProgressEx->u.SIPProgress.Body, SIPPARMID_CHCAP, sizeof(AudioCodec), &AudioCodec);
- }
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_RTP_MAP;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_RTP_MAP);
- ISXSIP_IE_SDP_RTP_MAP* pSdpRtpMap = &pSdp->Sdp[nIndex].u.RtpMap;
- pSdpRtpMap->Payload = 101;
- pSdpRtpMap->ClkRate = 8000;
- lstrcpy(pSdpRtpMap->EncodingName, "telephone-event");
- lstrcpy(pSdpRtpMap->EncodingParam, "1");
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "fmtp");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "101 0-15");
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "ptime");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "20");
- pSdp->SdpNum++;
- }
- /*****************************************************************
- **【函数名称】 __constructReinviteBody4Hold
- **【函数功能】 构造ReinviteACK协议体
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__constructReinviteBody4Hold( ISXSIP_IE_BODY_EX* pBody, bool Hold )
- {
- pBody->Valid = 1;
- pBody->BodyPartyType = BodyPartyType_SDP;
- TCHAR MediaAddr[MAX_PATH] = { 0 };
- ASSERT(m_pBindIpmCh != NULL);
- m_pImplement->getMediaAddr(m_pBindIpmCh, MediaAddr);
- int nIndex;
- ISXSIP_IE_BODY_SDP_EX* pSdp = &pBody->u.BodySdp;
- pSdp->SdpNum = 0;
- //o
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ORIGIN;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_ORIGIN);
- pSdp->Sdp[nIndex].u.Origin.NetType = ISXSIP_SDPNETTYPE_IN;
- pSdp->Sdp[nIndex].u.Origin.AddrType = ISXSIP_SDPADDRTYPE_IP4;
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.SessionId, "20");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.UserName, "EHang");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.Version, "001");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.Addr, MediaAddr);
- pSdp->SdpNum++;
- //s
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION);
- lstrcpy(pSdp->Sdp[nIndex].u.Session.Name, "EH-Call");
- lstrcpy(pSdp->Sdp[nIndex].u.Session.Info, "");
- pSdp->SdpNum++;
- //c
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONNECTION;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_CONNECTION);
- pSdp->Sdp[nIndex].u.Connection.NetType = ISXSIP_SDPNETTYPE_IN;
- pSdp->Sdp[nIndex].u.Connection.AddrType = ISXSIP_SDPADDRTYPE_IP4;
- lstrcpy(pSdp->Sdp[nIndex].u.Connection.Addr, MediaAddr);
- pSdp->SdpNum++;
- //t
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION_TIME;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION_TIME);
- pSdp->Sdp[nIndex].u.SessionTime.Start = 0;
- pSdp->Sdp[nIndex].u.SessionTime.End = 0;
- pSdp->SdpNum++;
- //m
- int nPLIndex = 0;
- int nPayLoad;
- ISX_sr_convert(CONID_CODECID2PLAYLOAD, &nPayLoad, &m_CodecId);
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_MEDIA_DESC;
- pSdp->Sdp[nIndex].u.MediaDesc.MediaPort = m_pBindIpmCh->mediaPort();
- pSdp->Sdp[nIndex].u.MediaDesc.MediaProtocol = ISXSIP_SDPPROTOCOL_RTP;
- pSdp->Sdp[nIndex].u.MediaDesc.MediaType = ISXSIP_SDPMEDIATYPE_AUDIO;
- pSdp->Sdp[nIndex].u.MediaDesc.Payload[nPLIndex++] = nPayLoad;
- pSdp->Sdp[nIndex].u.MediaDesc.Payload[nPLIndex++] = 101;
- pSdp->Sdp[nIndex].u.MediaDesc.PayLoadNum = nPLIndex;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_MEDIA_DESC) - 1 + pSdp->Sdp[nIndex].u.MediaDesc.PayLoadNum;
- pSdp->SdpNum++;
- // a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_RTP_MAP;
- pSdp->Sdp[nIndex].u.RtpMap.Payload = g_SipSdpRtpMap[m_CodecId].Payload;
- pSdp->Sdp[nIndex].u.RtpMap.ClkRate = g_SipSdpRtpMap[m_CodecId].ClkRate;
- lstrcpy(pSdp->Sdp[nIndex].u.RtpMap.EncodingName, g_SipSdpRtpMap[m_CodecId].EncodingName);
- lstrcpy(pSdp->Sdp[nIndex].u.RtpMap.EncodingParam, g_SipSdpRtpMap[m_CodecId].EncodingParam);
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_RTP_MAP);
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "fmtp");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "101 0-15");
- pSdp->SdpNum++;
- if(Hold)
- {
- // a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONN_MODE;
- pSdp->Sdp[nIndex].u.ConnMode.ConnMode = ISXSIP_SDPCONNECTMODE_RECVONLY;
- pSdp->SdpNum++;
- }
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "ptime");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "20");
- pSdp->SdpNum++;
- }
- /*****************************************************************
- **【函数名称】 __constructReinviteBody4T38
- **【函数功能】 构造ReinviteACK协议体
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__constructReinviteBody4T38( ISXSIP_IE_BODY_EX* pBody )
- {
- pBody->Valid = 1;
- pBody->BodyPartyType = BodyPartyType_SDP;
- TCHAR MediaAddr[MAX_PATH] = { 0 };
- ASSERT(m_pBindIpmCh != NULL);
- m_pImplement->getMediaAddr(m_pBindIpmCh, MediaAddr);
- int nIndex;
- ISXSIP_IE_BODY_SDP_EX* pSdp = &pBody->u.BodySdp;
- pSdp->SdpNum = 0;
- //o
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ORIGIN;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_ORIGIN);
- pSdp->Sdp[nIndex].u.Origin.NetType = ISXSIP_SDPNETTYPE_IN;
- pSdp->Sdp[nIndex].u.Origin.AddrType = ISXSIP_SDPADDRTYPE_IP4;
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.SessionId, "20");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.UserName, "EHang");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.Version, "001");
- lstrcpy(pSdp->Sdp[nIndex].u.Origin.Addr, MediaAddr);
- pSdp->SdpNum++;
- //s
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION);
- lstrcpy(pSdp->Sdp[nIndex].u.Session.Name, "EH-Call");
- lstrcpy(pSdp->Sdp[nIndex].u.Session.Info, "");
- pSdp->SdpNum++;
- //c
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_CONNECTION;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_CONNECTION);
- pSdp->Sdp[nIndex].u.Connection.NetType = ISXSIP_SDPNETTYPE_IN;
- pSdp->Sdp[nIndex].u.Connection.AddrType = ISXSIP_SDPADDRTYPE_IP4;
- lstrcpy(pSdp->Sdp[nIndex].u.Connection.Addr, MediaAddr);
- pSdp->SdpNum++;
- //t
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_SESSION_TIME;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_SESSION_TIME);
- pSdp->Sdp[nIndex].u.SessionTime.Start = 0;
- pSdp->Sdp[nIndex].u.SessionTime.End = 0;
- pSdp->SdpNum++;
- //m
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_MEDIA_DESC;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_MEDIA_DESC_EX);
- pSdp->Sdp[nIndex].u.MediaDesc.MediaPort = m_pBindIpmCh->mediaPort();
- pSdp->Sdp[nIndex].u.MediaDesc.MediaProtocol = ISXSIP_SDPPROTOCOL_UDPTL;
- pSdp->Sdp[nIndex].u.MediaDesc.MediaType = ISXSIP_SDPMEDIATYPE_IMAGE;
- pSdp->Sdp[nIndex].u.MediaDesc.PayLoadNum = 1;
- pSdp->Sdp[nIndex].u.MediaDesc.Payload[0] = 0;
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "T38FaxVersion");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "0");
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "T38MaxBitRate");
- //strcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "14400");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "9600");
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "T38FaxFillBitRemoval");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "0");
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "T38FaxTranscodingMMR");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "0");
- pSdp->SdpNum++;
- //a
- nIndex = pSdp->SdpNum;
- pSdp->Sdp[nIndex].Tag = ISXSIP_IE_SDP_TAG_ATTRIBUTE;
- pSdp->Sdp[nIndex].Len = sizeof(ISXSIP_IE_SDP_TAG_ATTRIBUTE);
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Name, "T38FaxTranscodingJBIG");
- lstrcpy(pSdp->Sdp[nIndex].u.Attribute.Value, "0");
- pSdp->SdpNum++;
- }
- /*****************************************************************
- **【函数名称】 __getCallNumFromSipAddr
- **【函数功能】 从SIP URI中解析号码
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__getCallNumFromSipAddr( LPCTSTR Called, CString& NumBuf )
- {
- ASSERT(Called != NULL);
- NumBuf = _T("");
- TCHAR szTmpAddr[GC_ADDRSIZE];
- lstrcpy(szTmpAddr, Called);
- TCHAR *p = strstr(szTmpAddr, _T("@"));
- if(p != NULL)
- *p=0;
- p = strstr(szTmpAddr, _T(":"));
- if(p == NULL)
- NumBuf = szTmpAddr;
- else
- NumBuf = p+1;
- }
- /*****************************************************************
- **【函数名称】 __getCallMediaDesc
- **【函数功能】 获取呼叫的媒体描述
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::__getCallMediaDesc( ISXSIP_IE_BODY_EX* pSdp, int CodecId /*= -1*/ )
- {
- if(pSdp->Valid == 0 || pSdp->BodyPartyType == BodyPartyType_TRANS)
- return false;
- int iLoopNum = pSdp->u.BodySdp.SdpNum;
- ISXSIP_IE_BODY_SDP_EX* pSdpex = &pSdp->u.BodySdp;
- for(int i = 0; i < iLoopNum; i++)
- {
- if(pSdpex->Sdp[i].Tag == ISXSIP_IE_SDP_TAG_CONNECTION)
- {
- m_ConnectAddr = pSdpex->Sdp[i].u.Connection.Addr;
- continue;
- }
- if(pSdpex->Sdp[i].Tag != ISXSIP_IE_SDP_TAG_MEDIA_DESC)
- continue;
- if(pSdpex->Sdp[i].u.MediaDesc.MediaType != ISXSIP_SDPMEDIATYPE_AUDIO)
- continue;
- int iPayLoadNum = pSdpex->Sdp[i].u.MediaDesc.PayLoadNum;
- m_MediaPort = pSdpex->Sdp[i].u.MediaDesc.MediaPort;
- ISXSIP_IE_SDP_MEDIA_DESC_EX* pmdex = &pSdpex->Sdp[i].u.MediaDesc;
- if(CodecId >= 0) //如果指定了CODEC
- {
- for(int j = 0; j < iPayLoadNum; j++)
- {
- if(g_SipSdpRtpMap[CodecId].Payload == pmdex->Payload[j])
- {
- //取此指定AUDIO编码作为协商类型
- m_CodecId = CodecId;
- return true;
- }
- }
- }
- else
- {
- for(int j = 0; j < iPayLoadNum; j++)
- {
- for(int k = 0; k < AudioCodec_MaxNum; k++)
- {
- if(g_SipSdpRtpMap[k].Payload == pmdex->Payload[j])
- {
- // 从给出的媒体编码类型中取一个AUDIO编码作为协商类型
- m_CodecId = k;
- return true;
- }
- }
- }
- }
- }
- return false;
- }
- /*****************************************************************
- **【函数名称】 __consultMedia
- **【函数功能】 协商媒体
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::__consultMedia( ISXSIP_IE_BODY_EX* pSdp )
- {
- if(pSdp->Valid == 0 || pSdp->BodyPartyType == BodyPartyType_TRANS)
- return false;
- int iLoopNum = pSdp->u.BodySdp.SdpNum;
- ISXSIP_IE_BODY_SDP_EX* pSdpex = &pSdp->u.BodySdp;
- for(int i = 0; i < iLoopNum; i++)
- {
- if(pSdpex->Sdp[i].Tag != ISXSIP_IE_SDP_TAG_MEDIA_DESC)
- continue;
- if(pSdpex->Sdp[i].u.MediaDesc.MediaType != ISXSIP_SDPMEDIATYPE_AUDIO)
- continue;
- int iPayLoadNum = pSdpex->Sdp[i].u.MediaDesc.PayLoadNum;
- ISXSIP_IE_SDP_MEDIA_DESC_EX* pmdex = &pSdpex->Sdp[i].u.MediaDesc;
- for(int j = 0; j < iPayLoadNum; j++)
- {
- for(int k = 0; k < AudioCodec_MaxNum; k++)
- {
- if(g_SipSdpRtpMap[k].Payload == pmdex->Payload[j])
- {
- pmdex->PayLoadNum = 2;
- pmdex->Payload[0] = pmdex->Payload[j];
- pmdex->Payload[1] = 101;
- return true;
- }
- }
- }
- }
- return false;
- }
- /*****************************************************************
- **【函数名称】 __analyzeReinvite
- **【函数功能】 分析reinvite的目的
- **【参数】
- **【返回值】
- ****************************************************************/
- ReinvitePurpose CVoipChannel::__analyzeReinvite( ISXSIP_IE_BODY_SDP_EX* pSdp )
- {
- for(int i = 0; i < pSdp->SdpNum; ++i)
- {
- USHORT Tag = pSdp->Sdp[i].Tag;
- if(Tag == ISXSIP_IE_SDP_TAG_CONN_MODE)
- {
- UCHAR ConMode = pSdp->Sdp[i].u.ConnMode.ConnMode;
- if(ConMode == ISXSIP_SDPCONNECTMODE_SENDONLY)
- return REINVITE_FOR_HOLD;
- else if(ConMode == ISXSIP_SDPCONNECTMODE_SENDRECV)
- return REINVITE_FOR_TAKEBACK;
- }
- else if(Tag == ISXSIP_IE_SDP_TAG_MEDIA_DESC)
- {
- if(pSdp->Sdp[i].u.MediaDesc.MediaType == ISXSIP_SDPMEDIATYPE_IMAGE)
- return REINVITE_FOR_FAX;
- }
- }
- return REINVITE_FOR_NULL;
- }
- /*****************************************************************
- **【函数名称】 __onOffered
- **【函数功能】 处理来电呼叫
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onOffered( METAEVENT* pMetaEvent )
- {
- if(m_State != GCST_NULL)
- {
- ISX_gc_DropCall(pMetaEvent->crn, IPEC_SIPReasonStatus500ServerInternalError);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]检测到呼叫, 但通道状态异常, 呼叫将忽略"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return;
- }
- m_State = GCST_OFFERED;
- m_CallId = pMetaEvent->crn;
- GCPARAMEX_MAKECALL* pMakeCallEx = (GCPARAMEX_MAKECALL*)pMetaEvent->evtdatap;
- ASSERT(pMakeCallEx != NULL);
- CHAR DNIZ[GC_ADDRSIZE] = { 0 };
- CHAR ANI[GC_ADDRSIZE] = { 0 };
- ISX_gc_GetCallInfo(m_CallId, DESTINATION_ADDRESS, DNIZ);
- ISX_gc_GetCallInfo(m_CallId, ORIGINATION_ADDRESS, ANI);
- // 获取主、被叫号码
- __getCallNumFromSipAddr(ANI, m_CallerNum);
- __getCallNumFromSipAddr(DNIZ, m_CalleeNum);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]检测到呼叫, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, ANI, DNIZ);
- // 判断主叫是内线还是中继
- if(isInnerSipUser(m_CallerNum)) // 内线
- m_pImplement = &ms_Implement4Exten;
- else // 外线
- m_pImplement = &ms_Implement4Trunk;
- m_pImplement->onOffered(*this, pMakeCallEx);
- CMC::GetInstance().onDevResState(m_Id);
- }
- /*****************************************************************
- **【函数名称】 __onAlerting
- **【函数功能】 处理远端振铃
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onAlerting( METAEVENT* pMetaEvent )
- {
- if(m_State == GCST_ALERTING || m_State == GCST_DROPCALLING)
- return;
-
- m_State = GCST_ALERTING;
- ASSERT(m_pImplement != NULL);
- m_pImplement->onAlerting(*this, pMetaEvent);
- CMC::GetInstance().onDevResState(m_Id);
- }
- /*****************************************************************
- **【函数名称】 __onProgressing
- **【函数功能】 处理Progressing
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onProgressing( void )
- {
- if(m_State == GCST_PROGRESS || m_State == GCST_DROPCALLING)
- return;
- GCPARAMEX_CALLPROGRESS* pProgress = (GCPARAMEX_CALLPROGRESS*)ISX_sr_getevtdatap();
- ASSERT(pProgress != NULL);
- // 存在收到183而无SDP紧接着又再次收到携带了SDP的183这种情况,所以在if语句判断成功后再将m_State设置为GCST_PROGRESS
- if(pProgress->u.SIPProgress.Body.Valid == 1)
- {
- m_State = GCST_PROGRESS;
- // 协商媒体编解码
- if(!__getCallMediaDesc(&pProgress->u.SIPProgress.Body))
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理Progressing时协商媒体编解码失败, 呼叫将释放, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- __clearCall(IPEC_SIPReasonStatus415UnsupportedMediaType);
- return;
- }
- // 启动媒体
- ASSERT(m_pBindIpmCh != NULL);
- if(!m_pBindIpmCh->isStarted())
- {
- if(!m_pBindIpmCh->startMedia())
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理Progressing时IPM资源启动失败, 呼叫将释放, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- return;
- }
- }
- CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_PROGRESSING, m_CallerNum, m_CalleeNum);
- }
- }
- /*****************************************************************
- **【函数名称】 __onConnected
- **【函数功能】 处理远端接通
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onConnected( METAEVENT* pMetaEvent )
- {
- if(m_State == GCST_DROPCALLING)
- return;
- m_State = GCST_CONNECTED;
- GCPARAMEX_ANSWERCALL *pOutAnswerCallEx = (GCPARAMEX_ANSWERCALL*)pMetaEvent->evtdatap;
- ASSERT(pOutAnswerCallEx != NULL);
- if(pOutAnswerCallEx->u.SIPConn.Body.Valid == 1)
- {
- // 协商媒体编解码
- if(!__getCallMediaDesc(&pOutAnswerCallEx->u.SIPConn.Body))
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理远端应答时协商媒体编解码失败, 呼叫将释放, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- __clearCall(IPEC_SIPReasonStatus415UnsupportedMediaType);
- return;
- }
- }
- // 启动媒体
- ASSERT(m_pBindIpmCh != NULL);
- if(!m_pBindIpmCh->isStarted())
- {
- if(!m_pBindIpmCh->startMedia())
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]处理远端应答时启动IPM资源失败, 呼叫将释放, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- return;
- }
- }
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]远端应答, 开始通话, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- if(m_Job == DEV_LINE_CH_JOB_PRE_DIAL)
- {
- CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_INIT, m_CallerNum, m_CalleeNum);
- m_Job = DEV_LINE_CH_JOB_NONE;
- }
- else if(m_Job == DEV_LINE_CH_JOB_OFF_HOOK)
- {
- CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, DEV_CH_EVT_OFF_HOOK, NULL);
- m_Job = DEV_LINE_CH_JOB_NONE;
- }
- else
- {
- CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_TALKING, m_CallerNum, m_CalleeNum);
- }
- CMC::GetInstance().onDevResState(m_Id);
- }
- /*****************************************************************
- **【函数名称】 __onAnswered
- **【函数功能】 处理应答成功
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onAnswered( void )
- {
- if(m_State == GCST_DROPCALLING)
- return;
- m_State = GCST_CONNECTED;
- // 启动媒体
- ASSERT(m_pBindIpmCh != NULL);
- if(!m_pBindIpmCh->isStarted())
- {
- if(!m_pBindIpmCh->startMedia())
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]应答远端时启动IPM资源失败, 呼叫将释放, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- return;
- }
- }
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]应答成功, 开始通话, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_TALKING, m_CallerNum, m_CalleeNum);
- CMC::GetInstance().onDevResState(m_Id);
- }
- /*****************************************************************
- **【函数名称】 __onCallFinish
- **【函数功能】 处理呼叫成功
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onCallFinish( void )
- {
- m_State = GCST_NULL;
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]空闲"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- // 因为发现调用__ClearCall之后又收到GCEV_CONNECTED等事件,导致IPM通道stop之后又start,从而使IPM通道
- // 一直处于start状态未释放,后续的呼叫若使用该IPM通道会因为start失败而造成呼叫异常,鉴于此把IPM通道的
- // stop方法从__ClearCall函数移至此处调用。
- if(m_pBindIpmCh != NULL)
- {
- m_pBindIpmCh->stopMedia();
- // 未关联会话则IPM通道无法被会话释放,所以这里提前释放
- if(m_SessionCode == SESSION_INVALID_CALL)
- {
- m_pBindIpmCh->reset();
- m_pBindIpmCh = NULL;
- }
- }
- // 通各线路状态变化
- CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_FREE, NULL, NULL);
- m_pImplement = NULL;
- m_CallId = 0;
- m_Job = DEV_LINE_CH_JOB_NONE;
- m_ExtenNo = 0;
- m_MediaPort = 0;
- m_CodecId = -1;
- m_ConnectAddr = _T("");
- reset();
- CMC::GetInstance().onDevResState(m_Id);
- }
- /*****************************************************************
- **【函数名称】 __onDiconnected
- **【函数功能】 处理呼叫中断
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onDiconnected( METAEVENT* pMetaEvent )
- {
- GCPARAMEX_DROPCALL* pDropCall = (GCPARAMEX_DROPCALL*)pMetaEvent->evtdatap;
- ASSERT(pDropCall != NULL);
- if(m_State != GCST_CONNECTED) // 非通话中挂机
- {
- int ErrCode;
- switch(pDropCall->u.SIPDrop.usCause)
- {
- case IPEC_SIPReasonStatus404NotFound:
- ErrCode = CALL_FAILED_CAUSE_NUM_INVALID;
- break;
- case IPEC_SIPReasonStatus500ServerInternalError:
- case IPEC_SIPReasonStatus480TemporarilyUnavailable:
- ErrCode = CALL_FAILED_CAUSE_NO_ANSWER;
- break;
- case IPEC_SIPReasonStatus486BusyHere:
- ErrCode = CALL_FAILED_CAUSE_USER_BUSY;
- break;
- case IPEC_SIPReasonStatus410Gone:
- ErrCode = CALL_FAILED_CAUSE_DST_OFF;
- break;
- default:
- ErrCode = CALL_FAILED_CAUSE_NETWORK_ERR;
- break;
- }
- CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, DEV_CH_EVT_CALL_FAILD_CAUSE, (LPCTSTR)ErrCode);
- }
- m_State = GCST_DISCONNECTED;
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]检测到远端挂机, Caller = %s, Callee = %s, Cause = %d"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum, pDropCall->u.SIPDrop.usCause);
- // 远端挂机,结束两方通道通话
- __clearCall(pDropCall->u.SIPDrop.usCause);
- }
- /*****************************************************************
- **【函数名称】 __onTaskFail
- **【函数功能】 处理通道任务失败
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onTaskFail( void )
- {
- switch(ISX_sr_getevtopertype())
- {
- case OPER_ACCEPTCALL:
- {
- ASSERT(FALSE);
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]accept呼叫失败, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- }
- break;
- case OPER_ANSWERCALL:
- {
- ASSERT(FALSE);
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]应答来电失败, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- }
- break;
- case OPER_MAKECALL:
- {
- ASSERT(FALSE);
- __clearCall(IPEC_SIPReasonStatus200OK);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]外呼失败, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- }
- break;
- case OPER_DROPCALL:
- {
- ASSERT(FALSE);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]挂机失败, 已强制释放资源, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- __onCallFinish();
- }
- break;
- case OPER_SIP_SENDREINVITE:
- {
- ASSERT(FALSE);
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]发送Reinvite失败, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- }
- break;
- case OPER_SIP_SENDREINVITEACK:
- {
- ASSERT(FALSE);
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]发送ReinviteACK失败, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- }
- break;
- }
- }
- /*****************************************************************
- **【函数名称】 __onRecvInfo
- **【函数功能】 处理收到的SIP消息
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onRecvInfo( METAEVENT* pMetaEvent )
- {
- SIP_INFO* pSipInfo = (SIP_INFO*)pMetaEvent->evtdatap;
- ASSERT(pSipInfo != NULL);
- SIP_INFO_ACK Ack;
- memcpy(&Ack.Body, &pSipInfo->Body, sizeof(ISXSIP_IE_BODY_EX));
- Ack.ulSerialNo = pSipInfo->ulSerialNo;
- Ack.usCause = IPEC_SIPReasonStatus200OK;
- ISX_gc_SIPSendInfoAck(pMetaEvent->crn, EV_ASYNC, &Ack);
- }
- /*****************************************************************
- **【函数名称】 __onRecvReinvite
- **【函数功能】 处理Reinvite消息
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onRecvReinvite( METAEVENT* pMetaEvent )
- {
- ISXSIP_IE_BODY_EX* pSdp = (ISXSIP_IE_BODY_EX*)pMetaEvent->evtdatap;
- ASSERT(pSdp != NULL);
- if(pSdp->Valid == 0 || pSdp->BodyPartyType == BodyPartyType_TRANS)
- return;
- ReinvitePurpose Purpose = __analyzeReinvite(&pSdp->u.BodySdp);
- SIP_REINVITE_ACK Ack;
- switch(Purpose)
- {
- case REINVITE_FOR_HOLD:
- {
- CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, DEV_CH_EVT_HOLD_ON, NULL, m_ExtenNo);
- Ack.usCause = IPEC_SIPReasonStatus200OK;
- __constructReinviteBody4Hold(&Ack.Body, true);
- }
- break;
- case REINVITE_FOR_TAKEBACK:
- {
- CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, DEV_CH_EVT_TAKE_BACK, NULL, m_ExtenNo);
- Ack.usCause = IPEC_SIPReasonStatus200OK;
- __constructReinviteBody4Hold(&Ack.Body, false);
- }
- break;
- case REINVITE_FOR_FAX:
- {
- __constructReinviteBody4T38(&Ack.Body);
- ASSERT(m_pBindIpmCh != NULL);
- Ack.usCause = m_pBindIpmCh->switchVF(pSdp) ? IPEC_SIPReasonStatus200OK : IPEC_SIPReasonStatus403Forbidden;
- }
- break;
- default:
- Ack.usCause = IPEC_SIPReasonStatus403Forbidden;
- }
- ISX_gc_SIPSendReinviteAck(m_CallId, EV_ASYNC, &Ack);
- }
- /*****************************************************************
- **【函数名称】 __onRecvReinviteAck
- **【函数功能】 处理ReinviteACK消息
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onRecvReinviteAck( METAEVENT* pMetaEvent )
- {
- SIP_REINVITE_ACK* pReinviteAck = (SIP_REINVITE_ACK*)pMetaEvent->evtdatap;
- ASSERT(pReinviteAck != NULL);
- ISXSIP_IE_BODY_EX* pSdp = &pReinviteAck->Body;
- if(pSdp->Valid == 0 || pSdp->BodyPartyType == BodyPartyType_TRANS)
- return;
- ASSERT(m_pBindIpmCh != NULL);
- if(m_pBindIpmCh->switchVF(pSdp))
- {
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]响应ReinviteAck消息,切换传真模式失败, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- }
- }
- /*****************************************************************
- **【函数名称】 __onRecvUpdate
- **【函数功能】 处理Update消息
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onRecvUpdate( METAEVENT* pMetaEvent )
- {
- SIP_UPDATE_IND *pUpdate = (SIP_UPDATE_IND *)pMetaEvent->evtdatap;
- ASSERT(pUpdate != NULL);
- SIP_GENTRANSC_ACK ack;
- memcpy(&ack.Body, &pUpdate->Body, sizeof(ISXSIP_IE_BODY_EX));
- ack.ulSerialNo = pUpdate->ulSerialNo;
- ack.usCause = IPEC_SIPReasonStatus200OK;
- ISX_gc_SIPSendUpdateAck (pMetaEvent->crn, EV_ASYNC, &ack);
- }
- /*****************************************************************
- **【函数名称】 __onRecvSubscribe
- **【函数功能】 处理subscribe消息
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onRecvSubscribe( METAEVENT* pMetaEvent )
- {
- SIP_SUBSCRIBE_IND* pInd = (SIP_SUBSCRIBE_IND *)pMetaEvent->evtdatap;
- ASSERT(pInd != NULL);
- SIP_SUBSCRIBE_ACK ack;
- memcpy(&ack.Expires, &pInd->Expires, sizeof(ISXSIP_IE_EXPIRES));
- memcpy(&ack.Body, &pInd->Body, sizeof(ISXSIP_IE_BODY_EX));
- ack.ulSerialNo = pInd->ulSerialNo;
- ack.usCause = IPEC_SIPReasonStatus406NotAcceptable;
- ISX_gc_SIPSendSubscribeAck(pMetaEvent->crn, EV_ASYNC, &ack);
- }
- /*****************************************************************
- **【函数名称】 __onRecvMessage
- **【函数功能】 处理message消息
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onRecvMessage( METAEVENT* pMetaEvent )
- {
- SIP_MESSAGE_IND* pInd = (SIP_MESSAGE_IND *)pMetaEvent->evtdatap;
- ASSERT(pInd != NULL);
- SIP_GENTRANSC_ACK ack;
- ack.usCause = IPEC_SIPReasonStatus200OK;
- memcpy(&ack.Body, &pInd->Body, sizeof(ISXSIP_IE_BODY_EX));
- ack.ulSerialNo = pInd->ulSerialNo;
- ISX_gc_SIPSendMessageAck (pMetaEvent->crn, EV_ASYNC, &ack);
- }
- /*****************************************************************
- **【函数名称】 __onRecvNotify
- **【函数功能】 处理notify消息
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onRecvNotify( METAEVENT* pMetaEvent )
- {
- SIP_NOTIFY_IND* pInd = (SIP_NOTIFY_IND *)pMetaEvent->evtdatap;
- ASSERT(pInd != NULL);
- SIP_GENTRANSC_ACK ack;
- memcpy(&ack.Body, &pInd->Body, sizeof(ISXSIP_IE_BODY_EX));
- ack.usCause = IPEC_SIPReasonStatus200OK;
- ack.ulSerialNo = pInd->ulSerialNo;
- ISX_gc_SIPSendNotifyAck (pMetaEvent->crn, EV_ASYNC, &ack);
- }
- /*****************************************************************
- **【函数名称】 __onRecvRefer
- **【函数功能】 处理refer消息
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onRecvRefer( METAEVENT* pMetaEvent )
- {
- SIP_REFER_IND* pInd = (SIP_REFER_IND *)ISX_sr_getevtdatap();
- ASSERT(pInd != NULL);
- SIP_REFER_ACK ack;
- memcpy(&ack.Body, &pInd->Body, sizeof(ISXSIP_IE_BODY_EX));
- memcpy(&ack.Contact, &pInd->Contact, sizeof(ISXSIP_IE_CONTACT));
- ack.usCause = IPEC_SIPReasonStatus403Forbidden;
- ack.ulSerialNo = pInd->ulSerialNo;
- ISX_gc_SIPSendReferAck(pMetaEvent->crn, EV_ASYNC, &ack);
- }
- /*****************************************************************
- **【函数名称】 __onRecvOption
- **【函数功能】 处理option消息
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::__onRecvOption( METAEVENT* pMetaEvent )
- {
- SIP_OPTIONS_IND* pInd = (SIP_OPTIONS_IND *)ISX_sr_getevtdatap();
- ASSERT(pInd != NULL);
- SIP_GENTRANSC_ACK ack;
- ZeroMemory(&ack, sizeof(ack));
- ack.ulSerialNo = pInd->ulSerialNo;
- ack.usCause = IPEC_SIPReasonStatus200OK;
- if(__consultMedia(&pInd->Body))
- memcpy(&ack.Body, &pInd->Body, sizeof(ISXSIP_IE_BODY_EX));
-
- ISX_gc_SIPSendOptionsAck(pMetaEvent->crn, EV_ASYNC, &ack);
- }
- /*****************************************************************
- **【函数名称】 open
- **【函数功能】 打开系统资源
- **【参数】
- **【返回值】 成功true,失败false
- ****************************************************************/
- bool CVoipChannel::open( void )
- {
- ASSERT(m_Handle == DEV_HANDLE_INVALID);
- if(ISX_gc_OpenEx(&m_Handle, m_Id.NodeNo, m_Id.BoardNo, -1, m_Id.ChanNo, EV_SYNC, this, LINETYPE_SIP) < 0)
- {
- m_Handle = DEV_HANDLE_INVALID;
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{VOIPCh}: VOIP通道[%d-%d-%d]打开失败"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return false;
- }
- ISX_gc_SetEvtMsk(m_Handle, GCMSK_PROGRESS, GCACT_ADDMSK);
- if( m_Id.ChanNo % 2 != 0 )
- {
- if(ISX_gc_WaitCall(m_Handle, NULL, NULL, -1, EV_ASYNC) < 0)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{VOIPCh}: VOIP通道[%d-%d-%d]等待呼叫失败"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return false;
- }
- }
- //LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: VOIP通道[%d-%d-%d]打开成功"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return true;
- }
- /*****************************************************************
- **【函数名称】 close
- **【函数功能】 关闭系统资源
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::close( void )
- {
- if(m_Handle != DEV_HANDLE_INVALID)
- {
- ISX_gc_Close(m_Handle);
- m_Handle = DEV_HANDLE_INVALID;
- //LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: VOIPCh通道[%d-%d-%d]关闭"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- }
- }
- /*****************************************************************
- **【函数名称】 offhook
- **【函数功能】 内线摘机(只对内线有效)
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::offhook( bool IgnoreSession, LPCTSTR CallerNum )
- {
- ASSERT(CallerNum != NULL);
- if(m_State != GCST_NULL)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]振铃座席分机失败, 通道状态非空闲, Exten = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, CallerNum);
- return false;
- }
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行振铃座席分机请求, Exten = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, CallerNum);
- if(IgnoreSession)
- m_Job = DEV_LINE_CH_JOB_OFF_HOOK;
- else
- m_Job = DEV_LINE_CH_JOB_PRE_DIAL;
- m_CalleeNum = CallerNum;
- m_CallerNum = CallerNum;
- m_pImplement = &ms_Implement4Exten;
- return m_pImplement->makeCall(*this, INVALID_ID_SIP_ACCOUNT);
- }
- /*****************************************************************
- **【函数名称】 dropCall
- **【函数功能】 挂机
- **【参数】 IsPassive 是否为被动挂机
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::dropCall( bool IsPassive )
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行挂机请求, caller = %s, callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- return __clearCall(IPEC_SIPReasonStatus200OK);
- }
- /*****************************************************************
- **【函数名称】 makeCall
- **【函数功能】 启动线路拨号
- **【参数】 lpCalleeNum 被叫号码
- lpCallerNum 主叫号码
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::makeCall( LPCTSTR Callee, LPCTSTR Caller, int AccountId )
- {
- ASSERT(Callee != NULL);
- ASSERT(Caller != NULL);
- if(m_State != GCST_NULL)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]执行呼叫请求失败, 通道未在空闲状态, caller = %s, callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, Caller, Callee);
- return false;
- }
- m_CalleeNum = Callee;
- m_CallerNum = Caller;
- if(AccountId == INVALID_ID_SIP_ACCOUNT) // 呼叫内线
- m_pImplement = &ms_Implement4Exten;
- else
- m_pImplement = &ms_Implement4Trunk;
- return m_pImplement->makeCall(*this, AccountId);
- }
- /*****************************************************************
- **【函数名称】 answer
- **【函数功能】 应答呼叫
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::answer( void )
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行应答请求"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- if(m_State == GCST_CONNECTED)
- {
- CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_TALKING, m_CallerNum, m_CalleeNum);
- return true;
- }
- else
- return false;
- }
- /*****************************************************************
- **【函数名称】 playSound
- **【函数功能】 放音收号
- **【参数】 pContent 放音内容
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::playSound( PlayVoiceContent* pContent )
- {
- ASSERT(pContent != NULL);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行放音请求, AudioFile = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, pContent->szFileName);
- if(m_State != GCST_CONNECTED)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]放音失败, 通道未处于连接状态, AudioFile = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, pContent->szFileName);
- return false;
- }
- return m_Mixer.playSound(pContent);
- }
- /*****************************************************************
- **【函数名称】 playTone
- **【函数功能】 播放信号音
- **【参数】 Type 信号音类型
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::playTone( int Type )
- {
- return m_Mixer.playTone(Type);
- }
- /*****************************************************************
- **【函数名称】 playStop
- **【函数功能】 停止放音
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::playStop( void )
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行停止放音请求"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return m_Mixer.playStop();
- }
- /*****************************************************************
- **【函数名称】 startRecord
- **【函数功能】 开始录音
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::startRecord( RecordContent* pContent )
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行录音请求"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- if(m_State == GCST_NULL)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]录音失败, 通道状态空闲"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return false;
- }
- return m_Mixer.startRecord(pContent);
- }
- /*****************************************************************
- **【函数名称】 stopRecord
- **【函数功能】 停止录音
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::stopRecord( void )
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行停止录音请求"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return m_Mixer.stopRecord();
- }
- /*****************************************************************
- **【函数名称】 monitor
- **【函数功能】 监听
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::monitor( COneLeg* pTalker, bool IsStop )
- {
- ASSERT(pTalker != NULL);
- if(IsStop)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行取消监听请求"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return pTalker->cancelMonitor(this);
- }
- else
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]执行监听请求"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- if(m_State != GCST_CONNECTED)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]监听失败, 通道未处于连接状态"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return false;
- }
- return pTalker->allowMonitor(this);
- }
- }
- /*****************************************************************
- **【函数名称】 allowMonitor
- **【函数功能】 允许监听
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::allowMonitor( COneLeg* pMonitorParty )
- {
- if(m_State != GCST_CONNECTED)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]接受监听失败, 通道未处于连接状态"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return false;
- }
- if(!m_Mixer.allowedMonitor())
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]接受监听失败, 无空闲混音发端可连接"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- return false;
- }
- return m_Mixer.setupMonitor(pMonitorParty->routeChannel());
- }
- /*****************************************************************
- **【函数名称】 cancelMonitor
- **【函数功能】 取消监听
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::cancelMonitor( COneLeg* pMonitorParty )
- {
- ASSERT(pMonitorParty != NULL);
- return m_Mixer.undoMonitor(pMonitorParty->routeChannel());
- }
- /*****************************************************************
- **【函数名称】 freeResBinded
- **【函数功能】 释放绑定资源
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::freeResBinded( void )
- {
- if(m_pBindIpmCh != NULL)
- {
- m_pBindIpmCh->reset();
- m_pBindIpmCh = NULL;
- }
- }
- /*****************************************************************
- **【函数名称】 onDevEvent
- **【函数功能】 设备事件处理函数
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::onDevEvent( METAEVENT* pMetaEvent )
- {
- ASSERT(pMetaEvent != NULL);
- switch(pMetaEvent->evttype)
- {
- case GCEV_OFFERED: // 呼入
- __onOffered(pMetaEvent);
- break;
- case GCEV_DIALING:
- {
- m_State = GCST_DIALING;
- CMC::GetInstance().onDevResState(m_Id);
- }
- break;
- case GCEV_ACCEPT:
- m_State = GCST_ACCEPTED;
- break;
- case GCEV_ALERTING:
- __onAlerting(pMetaEvent);
- break;
- case GCEV_PROGRESSING:
- __onProgressing();
- break;
- case GCEV_CONNECTED:
- __onConnected(pMetaEvent);
- break;
- case GCEV_ANSWERED:
- __onAnswered();
- break;
- case GCEV_DROPCALL:
- __onCallFinish();
- break;
- case GCEV_DISCONNECTED:
- __onDiconnected(pMetaEvent);
- break;
- case GCEV_SIP_RECVREINVITE:
- __onRecvReinvite(pMetaEvent);
- break;
- case GCEV_SIP_RECVREINVITEACK:
- __onRecvReinviteAck(pMetaEvent);
- break;
- case GCEV_SIP_RECVINFO:
- __onRecvInfo(pMetaEvent);
- break;
- case GCEV_SIP_RECVUPDATE:
- __onRecvUpdate(pMetaEvent);
- break;
- case GCEV_SIP_RECVSUBSCRIBE:
- __onRecvSubscribe(pMetaEvent);
- break;
- case GCEV_SIP_RECVMESSAGE:
- __onRecvMessage(pMetaEvent);
- break;
- case GCEV_SIP_RECVNOTIFY:
- __onRecvNotify(pMetaEvent);
- break;
- case GCEV_SIP_RECVREFER:
- __onRecvRefer(pMetaEvent);
- break;
- case GCEV_SIP_RECVOPTIONS:
- __onRecvOption(pMetaEvent);
- break;
- case GCEV_TASKFAIL:
- __onTaskFail();
- break;
- case GCEV_BLOCKED:
- {
- m_IsBlocked = true;
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]阻塞"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- }
- break;
- case GCEV_UNBLOCKED:
- {
- m_IsBlocked = false;
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{VOIPCh}: 通道[%d-%d-%d]解除阻塞"), m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo);
- }
- break;
- default:
- break;
- }
- }
- /*****************************************************************
- **【函数名称】 isInnerSipUser
- **【函数功能】 判断是否是内线SIP用户
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::isInnerSipUser( LPCTSTR User )
- {
- ASSERT(User != NULL);
- ISXSIP_REGUSER RegUser;
- return ISXE_gc_SipGetRegisterUser(User, &RegUser) == 0;
- }
- /*****************************************************************
- **【函数名称】 reinvite4T38
- **【函数功能】 为T38传真发送reinvite
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::reinvite4T38( void )
- {
- ISXSIP_IE_BODY_EX Body;
- __constructReinviteBody4T38(&Body);
- return ISX_gc_SIPSendReinvite(m_CallId, EV_ASYNC, &Body) == 0;
- }
- /*****************************************************************
- **【函数名称】 reply
- **【函数功能】 响应呼叫
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::reply( void )
- {
- 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);
- if(m_State == GCST_OFFERED) // 话机直接发起的呼叫请求
- {
- if(ISX_gc_AcceptCall(m_CallId, 0, EV_ASYNC) == 0)
- {
- CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_RING_BACK, m_CallerNum, m_CalleeNum);
- return true;
- }
- else
- {
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]AcceptCall失败, 呼叫释放, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- return false;
- }
- }
- else if(m_State == GCST_CONNECTED) // ocx发出的呼叫请求
- {
- if(!playTone(CHANNEL_TONE_RINGBACK)) // 对a-leg放振铃音
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]播放回铃音失败, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- }
- return true;
- }
- else
- {
- ASSERT(FALSE);
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]响应呼叫时状态异常, 呼叫释放, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- return false;
- }
- }
- /*****************************************************************
- **【函数名称】 progress
- **【函数功能】 呼叫进展
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::progress( void )
- {
- 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);
- switch(m_State)
- {
- case GCST_OFFERED:
- case GCST_ACCEPTED: // 话机直接发起的呼叫请求
- {
- GCPARAMEX_CALLPROGRESS gcCallProcess;
- __constructProgressBody(&gcCallProcess);
- ASSERT(m_pBindIpmCh != NULL);
- if(ISX_gc_CallProgress(m_CallId, 0, EV_ASYNC, &gcCallProcess) != 0 || !m_pBindIpmCh->startMedia())
- {
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]progress失败, 呼叫释放, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- return false;
- }
- return true;
- }
- break;
- case GCST_CONNECTED: // ocx发出的呼叫请求
- {
- // 停止A-Leg的振铃音
- playTone(CHANNEL_TONE_NULL);
- return true;
- }
- break;
- default:
- {
- ASSERT(FALSE);
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]progress状态异常, 呼叫释放, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- return false;
- }
- }
- }
- /*****************************************************************
- **【函数名称】 accept
- **【函数功能】 应答呼叫
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CVoipChannel::accept( void )
- {
- 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);
- // b-leg接通
- switch(m_State)
- {
- case GCST_OFFERED:
- case GCST_ACCEPTED: // 话机直接发起的呼叫请求
- {
- GCPARAMEX_ANSWERCALL AnswerCallEx;
- __constructAnswerBody(&AnswerCallEx);
- if(ISX_gc_AnswerCall(m_CallId, 0, EV_ASYNC, &AnswerCallEx) != 0)
- {
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]呼叫释放, a-leg应答呼叫失败, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- return false;
- }
- }
- break;
- case GCST_CONNECTED: // ocx发出的呼叫请求
- {
- // 停止A-Leg的振铃音
- playTone(CHANNEL_TONE_NULL);
- CSessionShell::GetInstance().onLineStateChanged(m_Id, m_SessionCode, VIRTUAL_LINE_STATE_TALKING, m_CallerNum, m_CalleeNum);
- }
- break;
- default:
- {
- ASSERT(FALSE);
- __clearCall(IPEC_SIPReasonStatus500ServerInternalError);
- LOGGER(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{VOIPCh}: 通道[%d-%d-%d]呼叫释放, a-leg应答呼叫时处于异常状态, Caller = %s, Callee = %s"),
- m_Id.NodeNo, m_Id.BoardNo, m_Id.ChanNo, m_CallerNum, m_CalleeNum);
- return false;
- }
- }
- return true;
- }
- /*****************************************************************
- **【函数名称】 onPlayEnd
- **【函数功能】 放音结束处理函数
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::onPlayEnd( LPCTSTR lpDtmf )
- {
- // 通知呼叫控制层放音结束事件
- CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, DEV_CH_EVT_PLAY_END, lpDtmf);
- }
- /*****************************************************************
- **【函数名称】 onRecEnd
- **【函数功能】 录音结束处理函数
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::onRecEnd( UINT TaskId )
- {
- // 通知呼叫控制层录音结束事件
- CString strTmp;
- strTmp.Format(_T("%lu"), TaskId);
- CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, DEV_CH_EVT_REC_END, strTmp);
- }
- /*****************************************************************
- **【函数名称】 onToneEnd
- **【函数功能】 tone音结束处理函数
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::onToneEnd( int ToneTp )
- {
- // TODO: do nothing
- }
- /*****************************************************************
- **【函数名称】 onFaxEnd
- **【函数功能】 传真结束处理函数
- **【参数】
- **【返回值】
- ****************************************************************/
- void CVoipChannel::onFaxEnd( bool IsSuccess, LPCTSTR Reason )
- {
- CSessionShell::GetInstance().onLineChannelEvent(m_Id, m_SessionCode, IsSuccess ? DEV_CH_EVT_FAX_OK : DEV_CH_EVT_FAX_FAILED, Reason);
- __clearCall(IPEC_SIPReasonStatus200OK);
- }
- /*****************************************************************
- **【函数名称】 getStateStr
- **【函数功能】 返回状态字符串
- **【参数】
- **【返回值】
- ****************************************************************/
- LPCTSTR CVoipChannel::getStateStr( void ) const
- {
- if(m_IsBlocked)
- return _T("block");
- switch(m_State)
- {
- case GCST_NULL: return _T("free");
- case GCST_DIALING: return _T("calling");
- case GCST_OFFERED: return _T("alerting");
- case GCST_ALERTING: return _T("ringback");
- case GCST_CONNECTED: return _T("talking");
- default: return _T("unknown");
- }
- }
|