1 : 在main 函数中 , 新建一个
pSimpleCall = tbnew CSimpleCall(CmdLineArgs);
接着再调用 Result = pSimpleCall->Init(); 初始化数据库连接,
并且把自己 attach到CTBCMCLIB , 能够attach的前提是 继承自CTBCMCLibUser
Result = CTBCMCLib::Attach( this );
然后再 Result = pSimpleCall->Run();
2 : pSimpleCall->Run(); 实际就是调用 CTBCMCLib::GetInstance()->Run(&mfQuit);
3:因为 CsimpleCall 的 定义是
class CSimpleCall : public CTBCMCLibUser , public ITBCAFServiceAlmMgmtClient /* ALM (application launch management) client (being launched, shutdown, monitored by Toolpack OAM application) */ , public ITBCAFServiceCmMgmtClient /* CM (Configuration management) client (being notified when Toolpack configuration is reloaded) */ , public ITBCMCFreeListener<CTBCMCLeg> /* CTBCMCLeg free listener (we are responsible to free memory for terminated call legs) */ , public ITBCMCFreeListener<ITBCAFCallFlow> /* CTBCMCLeg free listener (we are responsible to free memory for terminated call flows) */
所以它能 接收到 calllegpresent 消息
四 : 在 Oncalllegpresent 事件里 , 判断NAP ,并根据NAP决定采用哪个 callplow
else if (strNAP == "SIP1") { strCallFlow = "TestCallee"; strServiceTemplate = "TestCallee"; }
然后再根据 strServiceTemplate决定 new 一个什么样的callflow
else if(strServiceTemplate == "TestCallee") { /*int rate[10] = {10, 30, 60, 120, 240, 480, 600, 1200, 2400, 3600};*/ //int duration = rand() % rate[rand() % 10] + 3; int duration = rand() % 600 + 3; pCall = tbnew CVHTestCallee(duration, "prompt://DestNum", ConfigParams.mTextCDRFolder, this, this); }
最后调用此 pcall的 AddIncoming 和 InitCall 方法
Result = pCall->AddIncoming( in_LegId, ptrIncomingLegAttribute, ptrIncomingLegProtocolAttributes, ptrAcceptCallProtAttribute );
Result = pCall->InitCall(&pCall);
*** 从 AddIncoming到 OnInitIncomingCallLeg 的顺序是 :
AddIncoming调用 CTBCAFCallFlow::CreateIncomingCallLeg,然后
CTBCAFCallFlow::CreateIncomingCallLeg 调用 mpCallInterface->OnInitIncomingCallLeg
final, 在 CTBCAFCallFlow::Construct 函数中, 早已写明: mpCallInterface = this;
五 : 因为pcall是继承自 CVHCallFlow 的子类, 在 CVHCallFlow 中 , override 了 OnInitIncomingCallLeg 事件 , 调用
ProcessEvents(in_pCallLeg, Event_OnInitCallLeg, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
此处要重点说明: 不仅是 OnInitIncomingCallLeg 事件,实际上 , OnInitOutgoingCallLeg,OnInitCallLeg 等所有继承自CTBCAFCallFlow的事件都是类似这样的代码 :
TBX_RESULT CVHCallFlow::OnInitOutgoingCallLeg(PCTBCAFCallLeg in_pCallLeg, PCTBCMC_PROTOCOL_ATTRIBUTE io_pCreateCallProtocolAttribute) { TBCAF_MUTEX_GET_SCOPE_BEGIN(&mMutex) CAFCODE(CVHCallFlow::OnInitCallLeg) { ProcessEvents(in_pCallLeg, Event_OnInitCallLeg, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); TBX_EXIT_SUCCESS(TBX_RESULT_OK); } CAFCODE_DEFAULT_HANDLE{} RETURN; TBCAF_MUTEX_GET_SCOPE_END(&mMutex) }
也就是说 , 处理过程全部转到了 ProcessEvents
六 : 然后在 CVHCallFlow的 ProcessEvents事件里 , 有这样的代码
switch(mState) { case STATE_IncomingLeg: result = StateIncomingLeg(in_pCallLeg, in_vhEvent, io_ppThis, in_ProtocolAttribute, in_Reason, in_pEvent, in_pError, in_pMediaProfile, in_pIVR_Reason, in_pMedia_Reason, in_CollectedDigitAttribute); TBCAF_EXIT_ON_ERROR(result, "StateIncomingLeg failed"); break;
这里的 STATE_IncomingLeg 是 CVHCallFlow 子类构造函数的参数
所有继承自 CVHCallFlow 的子类 , 只需设置好自己的所有可能的state , 并编写相应的 StateIncomingLeg(针对STATE_IncomingLeg 状态 ) ,以及其他 StateXXX 即可 。
并在何时的state里 , 真正把2个callLeg连接起来 。
----------------Q & A
1 : in CVHCCallFlow , 这三个变量
LEG_INFO mLegA;
LEG_INFO mLegB;
LEG_INFO mLegIn;
是在何时得到赋值,分别代表什么?
A :