框架初始化

//MTF基础模块初始化
rvIppSipSystemInit()
	//RV基础支撑模块初始化(如时间戳、信号量、内存管理等系统抽象层对象的初始化)
	RvCBaseInit();
	
	//获取内存对象信息,默认的内存对象构造详见RvCBaseInit中的RvMemoryInit
	RvMemoryGetInfo(NULL, NULL, &memInfo);
	initialAlloc = memInfo.bytes_requested_byuser;
	
	//设置内存分配对象为上面构造的默认内存分配管理对象。
	prvDefaultAlloc  = rvAllocGetDefaultAllocator();
	
	memset(&sipExtClbksDeprecated, 0, sizeof(RvIppSipExtClbks));

//MTF对象构造
SipStack_MtfConstruct(&gstSipUserConfig, (char *)&gstSipUserConfig)
	//将用户设置的MTF调试配置映射到MTF所需的对应值,保存到gstLogFilterTable
	SipStack_LogLevelPrintParse(…);
	
	//设置RV日志配置,其中MTF_LOG_PATH为"/var/temp/mtflog.log"
	SipStack_AppLogInitial( gstLogFilterTable, MTF_LOG_PATH );
		IppLogInit( ippFilters, szLogFileName )
			//分配日志管理对象资源
			RvMemoryAlloc(NULL, sizeof(*g_logMgr)…
			
			//构造日志管理对象,为每个RV基础模块构造日志源对象
			RvLogConstruct(g_logMgr)
			
			//构造线程对象,并不构造新的对象,而是直接使用用户当前线程。
			RvThreadConstructFromUserThread(g_logMgr, &g_th);
			
			//设置线程对象名字
			RvThreadSetName(&g_th,"MTF_LOG");
			
			//为MTF所有模块构造日志源对象
			for (i = 0; (i < (int)LOGSRC_NUMBER)&& (status == RV_OK); i++)
				RvLogSourceConstruct(g_logMgr, logSrcTable[i].logSrc, 
				logSrcTable[i].logSrcName, logSrcTable[i].logSrcName)
			
			//构建输出终端串口的日志监听对象,最终向串口的日志输出调用了
			// logPrintTerminal函数
			RvLogListenerConstructTerminal(&g_logListener, g_logMgr, RV_TRUE);
			
			//构建向文件输出的日志监听对象
RvLogListenerConstructLogfile(&g_logListener, g_logMgr, szLogFileName, 1, 0, 
			RV_TRUE);
			
			//先将所有的日志源对象过滤掩码设置为默认
			RvLogSetGlobalMask(g_logMgr, 0);
			
			//在根据用户设置进行日志源对象控制
			logSetFilters(ippFilters);
	
	//初始化MTF默认配置参数
	rvIppSipInitConfig(&sipCfg);
	
	//更新为用户的配置参数
	SipStack_LoadSipConfigMTFParams(pUserConfig, &sipCfg);
	
	//注册状态改变的回调,目前这里面仅仅是处理状态显示,感觉这里不太合理,这个回
	//调是SIP Stack的回调,比较底层,这里做一些SIP Stack相关处理更好,状态显示合理	//的地方应该在termRegistrationStateChangedCB回调中处理
	sipExtClbks.regClientStateChangedCB         = SipStack_MtfSipRegClientStateChanged;
	
	//注册SIP协议栈扩展支持的回调
rvMtfRegisterSipExtCallbacks(&sipExtClbks);
	
	//数图对象构造,初始化默认值
	rvMdmDigitMapConstruct(&digitMap);
	
	//使用用户配置构造数图
	rvMtfUtilBuildDigitMap(&digitMap, pUserConfig->digitMapPatterns);
		//设置数图对象启始定时器、位间短定时器、位间长定时器
		rvMdmDigitMapSetStartTimeout( digitMap, 100 );
		rvMdmDigitMapSetShortTimeout( digitMap, 5 );
		rvMdmDigitMapSetLongTimeout( digitMap, 10 );
		
		//根据用户配置构造数图组到digitMap对象中。
		//数图对象构成如下:
		// RvMdmDigitMap. Patterns[n]表示一条数图规则
		//RvMdmDigitMap.Patterns[n]. elements[n]表示一条数图规则中的子元素对象,
		//例如123即3个子元素对象。
		//这里的S、L指示符好像有问题。
	
	sipCfg.digitMapPtr = &digitMap;
	
	//MTF对象构造
	rvMtfSipConstruct(&pUserConfig->mtfHandle, &sipCfg);
		g_mtfMgr = mtfMgr;
		mtfMgr->userData = NULL;
		
		//从用户配置中获取生成端口范围参数,设置到g_mtfMgr->portRange
		rvMtfMgrPortRangeConstruct(g_mtfMgr->portRange,config);
		
		//注册SIP栈的日志打印回调
		// sipExtClbksDeprecated.stackConfigF.pfnPrintLogEntryEvHandler
		deprecatedSipExtClbks.stackConfigF = userSipStackConfig;
		rvIppSipRegisterExtClbks(&deprecatedSipExtClbks);
		
		//SIP栈初始化,这里启动了MTF及SIP栈处理的核心线程任务
		rvIppSipStackInitialize(&(mtfMgr->sipStackHandle), config);
			//构造并初始化g_basePhone对象
			rvCCBasePhoneConstruct(rvCCBasePhoneGetBasePhone());
			
			//初始化SIP栈配置
			RvSipStackInitCfg(sizeof(stackCfg), &stackCfg);
			
			//将用户配置的本地地址设置到SIP栈的本地TCP地址/UCP地址
			//配置参数中。
			strncpy(stackCfg.localTcpAddress, cfg->localAddress…
			strncpy(stackCfg.localUdpAddress, cfg->localAddress,…
			
			//如果配置了outband地址,则设置到SIP栈配置中,地址格式则设置到
			//outboundProxyIpAddress,域名格式则设置到outboundProxyHostName
			if (!rvSipControlIsAddressEmpty(cfg->outboundProxyAddress))
				if (IppUtilIsIpAddress(cfg->outboundProxyAddress))
					strncpy(stackCfg.outboundProxyIpAddress, cfg->outboundProxyAddress.
				else
					stackCfg.outboundProxyHostName = cfg->outboundProxyAddress;
			
			//其它一些SIP栈配置
			stackCfg.outboundProxyPort = cfg->outboundProxyPort;
			……
			
			//使用用户设置配置SIP栈中所有日志源对象过滤掩码
			rvSipControlSetCfgLogFilters(&stackCfg, cfg->logOptions);
			
			//设置SIP支持字段的扩展支持字符串
			strcpy(tempList, "replaces,100rel,path,sec-agree");
			stackCfg.supportedExtensionList = tempList;
			
			// sipExtClbksDeprecated.stackConfigF和
			// sipExtClbks.stackConfigCB两个回调的触发,目的为了在SIP栈配置阶段
			//看一下上层用户是否有其它处理需求。
			rvIppSipExtStackConfigCB(&stackCfg);
			
			//如果用户设置了会话定时器配置,则在扩展列表中增加会话刷新的需求字符
			if (cfg->sessionTimerSessionExpires > 0)
				strcpy(&tempList[0], stackCfg.supportedExtensionList);
				strcat(tempList, ",timer");
				stackCfg.supportedExtensionList = tempList;
			
			//协议栈核心线程构造,这里的回调sipStackProcessInit是SIP Stack的核心
//调用,调用RvSipStackConstruct进行SIP Stack各核心组件模块执行。
			ProtocolThreadConstruct(cfg->priority, sipStackProcessInit, sipStackProcessEnd,
cfg, PROTOCOL);
	//构造协议栈处理线程对象并启动,该线程的执行函数为
	// protocolThread,该函数负责整个SIP Stack及MTF的消息处理。
	//该函数在下面单独分析。
				RvThreadConstruct(protocolThread, NULL, IppLogMgr(), &thread);
				RvThreadSetPriority(&thread, priority);
				RvThreadSetStack(&thread, NULL, RV_PROTOCOLTHREAD_STACKSIZE);
				RvThreadSetName(&thread,"MTF_PRT");
				RvThreadCreate(&thread);
				initiated++;
				RvThreadStart(&thread);
				
				//等待协议栈线程函数执行,该信号量触发代码在protocolThread函数中
				RvSemaphoreWait(&threadConstructed, IppLogMgr());
				
				//保存当前协议版本的构造函数和销毁函数,同时向“MTF_PRT”线程
//发送消息,消息的内容为“0”,该SOCKET处理函数在protocolThread
//中,该线程函数收到内容为“0”的消息时,会执行sipStackProcessInit
//进行协议栈核心代码调用。
				protocolConstructF[protocol]=pcf;	//sipStackProcessInit
				protocolDestructF[protocol]=pdf;	//sipStackProcessEnd
				protocolParam[protocol]=param;	//cfg
				sendEventToMsgSocket((void*)protocol);	//protocol =“0”
			
			//暂时等待,当SIP栈核心线程启动成功之后,就会触发该信号量,使该
			//流程继续向后执行。semStackConstructed信号量触发的代码在
			//sipStackProcessInit函数中,该函数在上面做为SIP栈核心线程的主程序执行
			RvSemaphoreWait(&g_threadData.semStackConstructed, IppLogMgr());
		
		//IP Phone对象构造及相关回调设置
		rvIPPhoneConstruct(&mtfMgr->termMgr, config);
			//构造终端管理对象
			rvMdmTermMgrConstruct_(mgr, prvDefaultAlloc);
				//注册所有终端处理包
				rvMdmRegisterPackages(mgr);
					//创建模拟线路处理包对象,该对象是HASH类型对象
					//其中索引key为“al”字符,配对的为RvMdmPackagePtr对象
					//该对象中存储signals和events列表,也就是说通过字符串“al”
					//可以得到RvMdmPackagePtr对象,在该对象中可以得到信号列表
					//和事件列表。
					pkg = rvMdmTermMgrCreatePackage(mgr,"al");
					
					//向“al”包中注册摘机事件
					rvMdmPackageRegisterEvent(pkg,"of");
					
					//向“al”包中注册挂机事件
					rvMdmPackageRegisterEvent(pkg,"on");
					
					//注册其它事件、信号及包对象
			
			//资源分配
			rvMtfAllocatorAlloc(sizeof(RvCCIPPhone), (void**)&ipPhone);
			
			//ipPhone对象构造
			rvCCIPPhoneConstruct(ipPhone, mgr, cfg);
				//SDP管理对象构造
				RvSdpMgrConstructWithConfig(&cfg->sdpStackCfg, sizeof(RvSdpStackCfg));
					//从线程私有变量中获取SDP全局索引值
					__globals__ = 
(RvSdpGlobals *)RvGetGlobalDataPtr(RV_SDP_GLOBALS_INDEX);
					
					//创建SDP全局数据
					RvCreateGlobalData(RV_SDP_GLOBALS_INDEX,RvSdpInitializeGlobals,
NULL,RvSdpDestroyGlobals)
//调用RvSdpInitializeGlobals进行全局数据初始化
						gsGlobalsDataArray[index].iGlobalData = (*crtF)(index,usrData);
						gsGlobalsDataArray[index].iDestroyFunc = dstrF;
						gsGlobalsDataArray[index].iRefCount = 1;
						gsGlobalsDataArray[index].iIndex = index;
					
					__globals__->_sdpRefCount ++;	//引用递增
					
					//设置默认内存分配对象
					rvSdpSetDefaultAllocator(rvAllocGetDefaultAllocator());
					
					//注册属性处理参数
					rvSdpRegisterAttributes();
						//指示该属性可以出现多次
						attrD.bIsSingle = RV_FALSE;
						//指示该属性只能出现在媒体描述符中
					attrD.bMediaScopeOnly = RV_TRUE;
						//设置该参数的解析、编码、释放等回调处理函数
					    attrD.parseFunc = rvSdpRtpMapParsing;
					attrD.encodeFunc = rvSdpRtpMapGetValue;
					attrD.destroyFunc = rvSdpRtpMapSpecAttrDestruct;
					attrD.copyFunc = rvSdpRtpMapSpecAttrCopy;
						
						//将rtpmap属性处理加入到全局SDP数据中
						rvSdpSpecAttrInternalRegister("rtpmap",SDP_FIELDTYPE_RTP_MAP,
&attrD,NULL,NULL,&d)
	RvSdpInternalSpecAttrData *d;
	//获取空闲的属性设置对象
							d = gSpecAttrs + gSpecAttrsCnt;
							
							//将上面设置的指定参数配置存入属性对象中
							d->iName = “rtpmap”
							d->iAttrFieldType =SDP_FIELDTYPE_RTP_MAP,
						d->parseFunc = pSpecAttrData->parseFunc;
						d->copyFunc = pSpecAttrData->copyFunc;
						d->destroyFunc = pSpecAttrData->destroyFunc;
							……
							
							gSpecAttrsCnt ++;	//属性个数递增
						
						d->iReshuffleFunc = (rvAttrReshuffleCB)rvSdpRtpMapReshuffle;
						……
					
					//SDP编码集构造
					rvSdpCodecInitialize();
						gsParsersTableLen = 0;
						
						//TELE EVENT编码解析对象构造
						RvSdpCodec_DTMF_Init(rvSdpGetDefaultAllocator());
							//将编码对应的fmtp及a参数属性解析到
							// cp->iFmtpParamData和cp->iAttrParamData中,如果出现
							//多个参数属性及形成链表。
							cp = RvSdpCodecParserInternalConstruct(
gs_DTMF_FmtpParserData, gs_DTMF_AttrsParserData,a);

//设置编码名称,及处理fmtp属性时的参数列表串的分隔
//符,这里编码名称是数据形式主要考虑可能有多个别名存
//在。
cp->iCodecNames[0] = "PCMU";
cp->iSeparator = ';';

//将上面设置好的编码解析对象注册到编码解析表中
RvSdpCodecRegister(cp)
	//设置iParsingErrorCB、iFmtpUnknownNameCB、
	// iFmtpTreatParamCB回调
	RvSdpCodecSetCallbacks(cp);
	//加入编码解析表
	gsParsersTable[gsParsersTableLen++] = cp;
						……
				
				//g_basePhone.pmdmProvider,mdm provider对象
				mdmProvider = rvCCBasePhoneGetMdmProvider();
				
				//创建Provider MDM对象
				rvCCProviderMdmConstruct(mdmProvider, rvCCBasePhoneGetCallMgr(),
				termMgr, cfg, termMgr->a);
					//这里p是mdmProvider对象
					p->funcs->createConnectionF = rvCCProviderMdmCreateConnection;
					
					//将MTF一些配置参数存储在mdmProvider.provider中
					provider = p->provider;
				provider->a = a;
provider->callMgr = callMgr;
					provider->autoAnswer = cfg->autoAnswer;
					provider->semiTransferWithNoCancel = cfg->semiTransferWithNoCancel;
					provider->blindTransferByeAfterRefer = cfg->blindTransferByeAfterRefer;
					……
					
					//给mdmProvider.provider.funcs设置终端处理函数,包括
					//ringbackF = rvCCConnMdmRingback;
//disconnectF = rvCCConnMdmDisconnecting;
//getMediaF = rvCCConnMdmGetMedia;
//getMediaCapsF = rvCCConnMdmGetMediaCaps;
//makeCallF = rvCCConnMdmMakeCall;
//rejectF = rvCCConnMdmReject;
//callAnsweredF = rvCCConnMdmCallAnswered;
//createMediaF = rvCCConnMdmCreateMedia;
//setRemoteMediaF = rvCCConnMdmSetRemoteMedia;
//setLocalMediaF = rvCCConnMdmSetLocalMedia;
//restartMediaF = rvCCConnMdmRestartMedia;
//addressAnalyzeF = rvCCConnMdmAddressAnalyze;
//releaseF = rvCCConnMdmRelease;
//processTermEventF = rvCCConnMdmProcessEvent;
//joinConferenceF = rvCCConnMdmJoinConference;
//leaveConferenceF = rvCCConnMdmLeaveConference;
//transferOfferedF = rvCCConnMdmTransferOffered;
//transferConnectedF = rvCCConnMdmTransferConnected;
//isTransferedConnF = rvCCConnMdmIsTransferedConn;
//getCallerNumberF = rvCCConnMdmGetCallerNumber;
//terminateF = rvCCConnMdmTerminate;
//modifyMediaF         = rvCCConnMdmModifyMedia;
//modifyMediaDoneF     = rvCCConnMdmModifyMediaDone;
//holdF = rvCCConnTermMdmHold;
//unholdF = rvCCConnTermMdmUnhold;
//disconnectMediaF = rvCCConnMdmDisconnectMedia;
//connectMediaF = (RvCCConnectionTermConnectMediaF)rvCCConnMdmConnectMedia;
//remoteHoldF = rvCCConnTermMdmRemoteHold;
//remoteUnholdF = rvCCConnTermMdmRemoteUnhold;
//setHoldIndicatorF = rvCCConnTermMdmSetHoldIndicator;
//playDtmfF         = rvCCConnTermMdmPlayDtmf;
//setMuteIndicatorF = rvCCConnTermMdmSetMuteIndicator;
//muteF             = rvCCConnTermMdmMute;
					rvInitConnFuncs(provider);
					
					//给mdmProvider.provider.clbks设置终端信号回调,包括
					//initiatedCB =        rvCCConnMdmInitiatedCB;
					//newDigitCB =         rvCCConnMdmNewDigitCB;
					//callAnsweredCB =     rvCCConnMdmCallAnsweredCB;
					//callDeliveredCB =    rvCCConnMdmCallDeliveredCB;
					//offeredCB =          rvCCConnMdmOfferedCB;
					//transferInProcessCB = rvCCCallTransferInProcessCB;
					//conferenceJoinedCB = rvCCCallConferenceJoinedCB;
					//transferOfferedCB =  rvCCConnMdmTransferOfferedCB;
					//sendUserEventCB =    rvCCCallSendUserEventCB;
					//mediaModifiedCB      =       rvCCCallModifyMediaCB;
					//mediaModifiedDoneCB  =       rvCCCallModifyMediaDoneCB;
				rvInitConnCallbacks(provider);
					
					provider->mdmTermMgr = termMgr;
				provider->mdmTermMgr->xTermMgr = p;	//这里p为mdmProvider
					
					//设置provider->mdmTermMgr->xTermMgrClbks终端管理回调集合
					//包括
					//RvMdmXTermMgrRegisterPhysTermCB
					//RvMdmXTermMgrRegisterPhysTermAsyncCB
					//RvMdmXTermMgrRegisterEphTermCB
					//RvMdmXTermMgrUnregisterTermCB
					//RvMdmXTermMgrUnregisterTermAsyncCB
					//RvMdmXTermMgrFindTermCB
					//RvMdmXTermMgrFindTermCB
					//RvMdmXTermMgrStartCB
					//RvMdmXTermMgrStopCB
					//RvMdmXTermMgrDestructCB
					//RvMdmXTermMgrForEachPhysTermCB
					//RvMdmXTermMgrMediaCapsUpdatedCB
					//RvMdmXTermMgrRegisterAllTermsToNetworkCB
					//RvMdmXTermMgrRegisterTermToNetworkCB
					//RvMdmXTermMgrUnregisterTermFromNetworkCB
					rvMdmTermMgrRegisterXTermMgrClbks_(provider->mdmTermMgr, 
					&rvMdmTermMgrClbks);
					
					//获取按键检测包对象
					pkg = rvMdmTermMgrGetPackage(provider->mdmTermMgr, "dd");
					
					//构造数图数据对象,设置了两个关键函数
					//evCompleteF =rvMdmDigitMapBuildDDEvComplete
					//translateF =rvMdmDigitMapTranslateDDEvent
					rvMdmDigitMapDataConstruct(&dmData,"ce",
					rvMdmDigitMapBuildDDEvComplete,
rvMdmDigitMapTranslateDDEvent,
provider->mdmTermMgr->a);
					
					//将数图数据对象存储到终端管理对象中,mgr->digitMapData
					rvMdmPackageRegisterDigitMapData(pkg,&dmData);
					
					//将上面在rvMtfUtilBuildDigitMap中构造的数图对象存储到
					//provider->digitMap中,如果用户没有配置数图,则使用
					// rvCCTerminalMdmCreateDefaultDigitMap构造一个默认数图
					//,该默认数图为XXXX | XXX*XXX*XXX*XXX
					rvMdmDigitMapCopy(&provider->digitMap, cfg->digitMapPtr);
					
					rvMdmControlStarted = 1;	//标记MDM CONTROL已经启动
				
				//显示字符
				//mdmProvider.provider.displayData = rvCCIpPhoneDisplayLogo
				rvCCProviderMdmSetDisplayData(mdmProvider,rvCCIpPhoneDisplayLogo);
				//mdmProvider.provider. connClbks.addressAnalyzeCB = addressAnalyzeCB
				rvCCProviderMdmRegisterAddressAnalyzeCB(mdmProvider,
addressAnalyzeCB);
				
				//mdmProvider.provider.connClbks.inProcessCB = inProcessCB
				rvCCProviderMdmRegisterInProcessCB(mdmProvider, inProcessCB);
				
				// g_basePhone.pmdmProvider.provider.mdmTermMgr = termMgr
				setMdmTermMgr(termMgr);
				
				// termMgr.mapAddressToTermF =mapAddressToTermination
				rvMdmTermMgrRegisterMapAddressToTermCB(termMgr, 
					mapAddressToTermination);
			
			//存储ipPhone对象到终端管理中
			mgr->xApp = ipPhone;
			
			//设置sip phone终端管理回调
			//xTermMgrClbks[0].registerPhysTermF = sipPhoneRegisterPhysTerm;
			//….registerPhysTermAsyncF=sipPhoneRegisterPhysTermAsync
			//….unregisterTermF=sipPhoneUnregisterPhysTerm
			//….mediaCapsUpdatedF=sipPhoneSetMediaCaps
			//….registerAllTermsToNetworkF=registerAllTermsToNetwork
			//….registerTermToNetworkF=registerTermToNetwork
			//…. unregisterTermFromNetworkF = unregisterTermFromNetwork
			//…. startF = NULL
			//….stopF  = sipPhoneStop
			//….destructF = sipPhoneMgrDestruct
			rvCCSipPhoneGetCallback(&xTermMgrClbks[0]);
			
			//设置终端管理对象的终端管理回调,最终是调用的上面的xTermMgrClbks
			mgr->xTermMgrClbks->registerPhysTermF = ipPhoneRegisterPhysTerm;
			mgr->xTermMgrClbks->registerPhysTermAsyncF = ipPhoneRegisterPhysTermAsync;
			mgr->xTermMgrClbks->unregisterTermF = ipPhoneUnregisterPhysTerm;
			mgr->xTermMgrClbks->mediaCapsUpdatedF = ipPhoneSetMediaCaps;
			mgr->xTermMgrClbks->registerAllTermsToNetworkF = 
				ipPhoneRegisterAllTermsToNetwork;
			mgr->xTermMgrClbks->registerTermToNetworkF = 
				ipPhoneRegisterTermToNetwork;
			mgr->xTermMgrClbks->unregisterTermFromNetworkF =
ipPhoneUnregisterTermFromNetwork;
			mgr->xTermMgrClbks->startF = ipPhoneStart;
			mgr->xTermMgrClbks->stopF  = ipPhoneStop;
			mgr->xTermMgrClbks->destructF = ipPhoneMgrDestruct;
		
		//终端管理的使用者是MTF管理对象
		//termMgr.userData = mtfMgr
		rvMdmTermMgrSetUserData(&mtfMgr->termMgr, mtfMgr);
		
		//注册终端管理对象相关回调
		// termMgr.connect = NULL
		// termMgr.disconnect = NULL
		// termMgr.select = NULL
		// termMgr.deleteEphF = NULL
		// termMgr.mapAddressToTermF = NULL
		// termMgr.mapAddressToTermNewF = rvMapAddressToTerminationCB
		registerMdmInternalCallbacks(mtfMgr);
		
		//清除MDM扩展处理回调,不使用,包含如下:
		//mdmExtClbksDeprecated.connectionCreated
		//mdmExtClbksDeprecated.connectionDestructed
		//mdmExtClbksDeprecated.display
		//mdmExtClbksDeprecated.displayData
		//mdmExtClbksDeprecated.mapUserEvent
		//mdmExtClbksDeprecated.postProcessEvent
		//mdmExtClbksDeprecated.preProcessEvent
rvIppMdmRegisterExtClbks(&deprecatedMdmExtClbks);
		
		//创建终端类对象
mtfMgr->rtpClass = rvMdmTermMgrCreateTermClass(&mtfMgr->termMgr);
	rvMdmTermClassConstructA_(termClass,mgr->a);
	//设置当前终端类对象支持通用包能力,存储在termClass.pkgsCaps.packages
	rvMdmTermClassAddSupportedPkg(termClass,"g",1);

//初始化RTP终端类对象
//mtfMgr->rtpClass.createMediaF = NULL
//mtfMgr->rtpClass.modifyMediaF= NULL
//mtfMgr->rtpClass.destroyMediaF= NULL
//mtfMgr->rtpClass.modifyMediaCompletedF= NULL
		rvInitRtpTermClass(mtfMgr->rtpClass);
		
		//初始化各终端类对象
rvInitIppClasses(mtfMgr);
	//创建音频传送终端类
			mtfMgr->atClass = rvMdmTermMgrCreateTermClass(&mtfMgr->termMgr);
			
			//初始化终端类回调,包括
			//startSignalF =rvStartSignalIntCB
			//stopSignalF =rvStopSignalIntCB
			//playSignalF = rvPlaySignalIntCB
			//createMediaF =rvPhysCreateMediaIntCB
			//destroyMediaF =rvPhysDestroyMediaIntCB
			//mapDialStringToAddressF = rvMapDialStringToAddressCB
			//matchDialStringF = rvMatchDialStringToPatternCB
			//registerPhysTermCompletedF = rvRegisterTermCompletedCB
			//unregisterTermCompletedF = rvUnregisterTermCompletedCB
			//unregisterTermFromNetworkCompletedF=
				rvUnregisterTermFromNetworkCompletedCB
			initClassCallbacks(mtfMgr->atClass);
			
			//创建用户接口终端类,并初始化回调
			mtfMgr->uiClass = rvMdmTermMgrCreateTermClass(&mtfMgr->termMgr);
			initClassCallbacks(mtfMgr->uiClass);
			
			//注册模拟线路终端类,并初始化回调
			mtfMgr->phoneClass = rvMdmTermMgrCreateTermClass(&mtfMgr->termMgr);
			initClassCallbacks(mtfMgr->phoneClass);
			
			//创建Ip phone用户接口相关的包对象,包括
			// dis、key、kp、ce、labelkey、kf、ind、ks、rvcc包对象
			rvMdmTermMgrRegisterIPPhoneUiPackages(&mtfMgr->termMgr);
			
			//设置用户接口终端类支持dis、key、kp、labelkey、kf、ind、ks、rvcc包能力
			rvMdmTermClassSetIPPhoneUIPackages(mtfMgr->uiClass)
			
			//设置音频传输终端类支持dg、cg、rtp、tdmc包能力
			rvMdmTermClassSetAudioTransducerPackages(mtfMgr->atClass);
			
			//设置模拟线路终端类支持al、dd、dd-end、cg、dg、andisp、rvcc、rtp、tdmc
			//包能力
			rvMdmTermClassSetAnalogLinePackages(mtfMgr->phoneClass);
			
			//设置模拟线路终端类支持dis、key、kp、labelkey、kf、ind、ks、rvcc包能力
			rvMdmTermClassSetIPPhoneUIPackages(mtfMgr->phoneClass);
			
			//设置模拟线路终端类支持dg、cg、rtp、tdmc包能力
			rvMdmTermClassSetAudioTransducerPackages(mtfMgr->phoneClass);
		
		//为IP Phone对象添加SIP管理对象
rvCCIPPhoneAddSIP(&mtfMgr->termMgr,config, mtfMgr->sipStackHandle);
	// g_basePhone.usedProvider[0]=RV_TRUE;
			rvCCBasePhoneUse();
//Provdier SIP对象构造
rvCCProviderSipConstruct(rvCCBasePhoneGetNetProvider(), rvCCBasePhoneGetCallMgr(), stackHandle, cfg,
((RvCCIPPhone*)termMgr->xApp)->a);
				p->funcs->createConnectionF = rvCCProviderSipCreateConnection;
				provider = p->provider;
				
				//将相关参数存储到Provider SIP对象的provider中
				provider->autoRegister = cfg->autoRegister;
			provider->callWaitingReply  = cfg->callWaitingReply;
			provider->watchdogTimeout   = cfg->watchdogTimeout;
				….
				
				//设置SIP连接相关函数,包括
				//acceptF = rvCCConnSipAccept;
//rejectF = rvCCConnSipReject;
//ringbackF = rvCCConnSipRingback;
//disconnectF = rvCCConnSipDisconnecting;
//getMediaF = rvCCConnSipGetMedia;
//getMediaCapsF = rvCCConnSipGetMediaCaps;
//makeCallF = rvCCConnSipMakeCall;
//callAnsweredF = rvCCConnSipCallAnswered;
//createMediaF = rvCCConnSipCreateMedia;
//setRemoteMediaF = rvCCConnSipSetRemoteMedia;
//remoteHoldF = rvCCConnSipRemoteHold;
				//remoteUnholdF = rvCCConnSipRemoteUnhold;
//holdF = rvCCConnSipHold;
				//unholdF = rvCCConnSipUnhold;
//getCallerIdF = rvCCConnSipGetCallerId;
//getCallerNameF = rvCCConnSipGetCallerName;
//getCallerAddressF = rvCCConnSipGetCallerAddress;
//getCallerNumberF = rvCCConnSipGetCallerNumber;
				//transferInitF = rvCCConnSipTransferInit;
//transferInProgressF = rvCCConnSipTransferInProgress;
//playDtmfF = rvCCConnSipPlayDtmf;
//terminateF = rvCCConnSipTerminate;
//releaseF = rvCCConnSipRelease;
//modifyMediaF         = rvCCConnSipModifyMedia;
//modifyMediaDoneF     = rvCCConnSipModifyMediaDone;
				//processTermEventF = rvCCConnSipProcessEvent;
//forwardCallF =       rvCCConnSipForwardCall;
				//getProtocolIdF = rvCCConnSipGetProtocolId;
				//getRemoteDisplayNameF = rvCCConnSipGetRemoteDisplayName;
				//getRemotePhoneNumberF = rvCCConnSipGetRemotePhoneNumber;
//getRemoteUriF		 = rvCCConnSipGetRemoteUri;
				rvInitConnFuncs(provider);
				
				//设置SIP连接相关回调
				//initiatedCB =        rvCCConnSipInitiatedCB;
				//callDeliveredCB =    rvCCConnSipCallDeliveredCB;
				//offeredCB =          rvCCConnSipOfferedCB;
				//transferInitCB =     rvCCConnSipTransferInitCB;
				//transferOfferedCB =  rvCCConnSipTransferOfferedCB;
				//mediaCreatedCB =     rvCCConnSipMediaCreatedCB;
				//mediaUpdatedCB =     rvCCCallMediaUpdatedCB;
				//mediaModifiedCB      =   rvCCCallModifyMediaCB;
				//mediaModifiedDoneCB  =   rvCCCallModifyMediaDoneCB;
				rvInitConnCallbacks(provider);
				
				//构造SIP管理对象
				rvSipControlConstruct(&provider->sipMgr, stackHandle, cfg);
					g_sipControl = x;	//x为provider->sipMgr
					
					//SIP管理对象存储配置
					x->stackHndl = stackHandle;
					x->stackTcpPort = cfg->stackTcpPort;
					x->stackUdpPort = cfg->stackUdpPort;
					……
					
					//给Sip Stack组件注册所有回调
					setCallBackFunctions( rvSipControlGetStackHandle(x), 
					&x->stackCallbacks);
						//获取Sip Stack组件各管理模块句柄
						RvSipStackGetCallLegMgrHandle(stackHndl,
					&hCallLegMgr);
					RvSipStackGetTransportMgrHandle(stackHndl,  &hTransportMgr);
					RvSipStackGetTransactionMgrHandle(stackHndl,   
							&hTranscMgr);
					RvSipStackGetRegClientMgrHandle(stackHndl,  &hRegClientMgr);
					RvSipStackGetAuthenticatorHandle(stackHndl, &hAuth);
					RvSipStackGetTransmitterMgrHandle(stackHndl,
&hTransmitterMgr);
						RvSipStackGetSubsMgrHandle(stackHndl, &hSubsMgr);
						RvSipStackGetSecAgreeMgrHandle(stackHndl, &hSecAgreeMgr);
						
						//Sip管理对象向Sip Stack组件的对话框模块注册回调
						stackCallbacks->sipCallLegEvHandlers.pfnCallLegCreatedEvHandler
= AppCallLegCreatedEvHandler;
						……
						RvSipCallLegMgrSetEvHandlers( hCallLegMgr,
&stackCallbacks->sipCallLegEvHandlers, 
sizeof(RvSipCallLegEvHandlers));
						
						//Sip管理对象向Sip Stack组件的事务层模块注册回调
						stackCallbacks->sipTransEvHandlers.pfnEvTransactionCreated  =
	AppTranscCreatedEvHandler;
						……
						RvSipTransactionMgrSetEvHandlers( hTranscMgr, NULL,
						&stackCallbacks->sipTransEvHandlers,
						sizeof(RvSipTransactionEvHandlers));
						
						//Sip管理对象向Sip Stack组件的传输层模块注册回调
						stackCallbacks->sipTransactionMgrEvHandlers.
pfnEvNewRequestRcvd =AppTransactionManagerNewRequestRcvd;
						RvSipTransactionMgrSetMgrEvHandlers(…)
						
						//Sip管理对象向Sip Stack组件的注册客户端模块注册回调
						stackCallbacks->sipRegClientEvHandlers.pfnStateChangedEvHandler
							= AppRegClientStateChangedEvHandler;
						……
						RvSipRegClientMgrSetEvHandlers(…)
						
						//Sip管理对象向Sip Stack组件的鉴权模块注册回调
						stackCallbacks->sipAuthEvHandlers.pfnMD5AuthenticationHandler
 = AppAuthenticationMD5Ev;
						……
						RvSipAuthenticatorSetEvHandlers(…… )
						
						//Sip管理对象向Sip Stack组件的传送模块注册回调
						stackCallbacks->sipTransmitterEvHandlers.
pfnRegExpResolutionNeededEvHandler = 
AppRegExpResolutionNeededEvHandler;
						
						RvSipTransmitterMgrSetEvHandlers(…)
						
						//Sip管理对象向Sip Stack组件的订阅模块注册回调
						stackCallbacks->sipSubsEvHandlers.pfnSubsCreatedEvHandler	
= AppSipSubsCreatedEvHandler;
						RvSipSubsMgrSetEvHandlers(…);
						
						//Sip管理对象向Sip Stack组件的安全联盟模块注册回调
						stackCallbacks->sipSecAgreeEvHandlers.
pfnSecAgreeStatusEvHandler = rvSecAgreeStatusEvHandler;
						RvSipSecAgreeMgrSetSecAgreeEvHandlers(…)
					
					//使用sipExtClbksDeprecated.registerStackEventsF或
					// sipExtClbks.registerStackEventsCB上层回调,来通知用户是否需要						//在Sip管理对象向Sip Stack注册关键回调过程中进行其它处理。
					rvIppSipExtRegisterStackEventsCB(x, stackHandle);
					
					//其它sip配置参数的保存
				
				//用于SIP资源使用的周期性检测
				if(provider->watchdogTimeout > 0)
					rvSipControlWatchDogTimerConstruct((RvCCProvider*)provider);
				
				provider->callMgr = callMgr;
			
			//设置Sip管理对象的回调
			// sipProvider.provider.connClbks.addressAnalyzeCB =addressSipAnalyzeCB
			//sipProvider.provider.connClbks. inProcessCB =inProcessCB
rvCCProviderSipRegisterAddressAnalyzeCB(rvCCBasePhoneGetNetProvider(), 
				addressAnalyzeCB);
			rvCCProviderSipRegisterInProcessCB(rvCCBasePhoneGetNetProvider(),
inProcessCB);
		
		//设置mtf对象句柄为Sip Stack对象的使用者
		// pStackMgr->hAppStack = hMtf;
RvSipStackSetAppHandle(mtfMgr->sipStackHandle, (RvSipAppStackHandle)*hMtf);
		
		//随机数生成器构造
RvRandomGeneratorConstruct(&mtfMgr->randomGenerator,
(RvUint32)RvClockGet(NULL,NULL));
	
	rvMdmDigitMapDestruct(&digitMap);
	
	//将sip stack句柄存储到pUserConfig->sipStackHandle中
	rvMtfGetSipStackHandle(pUserConfig->mtfHandle, &pUserConfig->sipStackHandle);
	
	//构造本地媒体能力集
SipStack_ConstructLocalSdpMsg();
	//遍历所有线路
		for(i=0; i<RVSIP_LINE_NUM; i++)
			//构造SDP消息
			sdpMsg= rvSdpMsgConstruct(sdpMsg);
			gstSipUserConfig.sdpOfFullCaps[i] = sdpMsg;
			//设置ver及origin字段信息
rvSdpMsgSetVersion2(sdpMsg,"0");
			rvSdpMsgSetOrigin(sdpMsg, gstSipUserConfig.localAddress, "12345", 
"12345", RV_SDPNETTYPE_IN, 
RV_SDPADDRTYPE_IP4, gstSipUserConfig.localAddress );
			
			//向SDP消息中增加一个音频描述符对象
			rvSdpMsgAddMediaDescr(sdpMsg, RV_SDPMEDIATYPE_AUDIO, 
			gstSipUserConfig.localRtpPort, RV_SDPPROTOCOL_RTP);
			
			//设置音频描述符对象的地址字段
			rvSdpMediaDescrAddConnection(pMediaDescr, RV_SDPNETTYPE_IN,
RV_SDPADDRTYPE_IP4, gstSipUserConfig.localAddress);
			
			//遍历所有编码
			for(j=0; j<VICL_NUM; j++)
				//添置payload列表及rtpmap属性
				rvSdpMediaDescrAddPayloadNumber(pMediaDescr,
gstSipStackencodingMap[k].pt);
				rvSdpMediaDescrAddRtpMap(pMediaDescr, gstSipStackencodingMap[k].pt,
gstSipStackencodingMap[k].encodingName,
gstSipStackencodingMap[k].clockRate);
				
				//添加fmtp字段(主要G723和G729编码的静音属性)
				rvSdpMediaDescrAddFmtp(pMediaDescr, "18 annexb=no");
				rvSdpMediaDescrAddFmtp(pMediaDescr, "4 bitrate=6.3;annexa=no");
				
				//如果用户配置了RFC2833按键方式,则添加tele event编码
				if(gstSipUserConfig.dtmfRelay == RV_IPP_DTMF_RELAY_OOB )
					rvSdpMediaDescrAddPayloadNumber(pMediaDescr, 101);
					rvSdpMediaDescrAddRtpMap(pMediaDescr, 101,  "telephone-event",
					8000);
				
				//添加ptime
				rvSdpMediaDescrAddSpecialAttributeByType(pMediaDescr,
					SDP_FIELDTYPE_ATTR_PTIME, pTime);
				
				//设置连接模式
				rvSdpMsgSetConnectionMode(sdpMsg, RV_SDPCONNECTMODE_SENDRECV);
				
				//将本地集力级加载到Mtf组件中
				rvMtfLoadMediaCapabilities(gstSipUserConfig.mtfHandle, sdpMsg);
					//将sdp消息对象加载到sdpList消息列表中
					sdpMsg = rvSdpMsgListAddMsg( &sdpList);
					rvSdpMsgCopy( sdpMsg, mediaCaps);
					
					//将本地和远端媒体能力集存储到rtp终端类的mediaCaps中,此
					//本地和远端都为本地的能力值。
					rvMdmTermClassAddMediaCapabilities( mtfMgr->rtpClass, &sdpList,
&sdpList, ¶ms);
					
					//使用mgr->xTermMgrClbks->mediaCapsUpdatedF回调通过MTF
					//上层用户,编码能力集有更新。
					rvMdmTermMgrMediaCapabilitiesUpdated(&mtfMgr->termMgr,
mtfMgr->rtpClass);
					
					//将本地和远端媒体能力集存储到at终端类中
					rvMdmTermClassAddMediaCapabilities(mtfMgr->atClass, &sdpList,
					&sdpList, ¶ms);
					
					//将本地和远端媒体能力集存储到phone终端类中
					rvMdmTermClassAddMediaCapabilities(mtfMgr->phoneClass, &sdpList,
					&sdpList, ¶ms);
	
	//注册MTF终端处理的回调
	mdmClbks.startSignalCB = SipStack_MtfStartSignalCB;
    mdmClbks.stopSignalCB = SipStack_MtfStopSignalCB;
mdmClbks.mapDialStringToAddressCB = SipStack_MtfMapDialStringToAddressCB;
mdmClbks.unregisterTermFromServerCompletedCB = 
		SipStack_MtfUnregisterTermFromServerCompletedCB;
	rvMtfRegisterMdmCallbacks(pUserConfig->mtfHandle, &mdmClbks);
	
	//注册MTF媒体处理回调
	mediaClbks.destroyMediaStreamCB = SipStack_MtfDestroyMediaCB;
mediaClbks.connectMediaCB = SipStack_MtfConnectMediaCB;
	mediaClbks.modifyMediaCompletedCB = SipStack_MtfModifyMediaCompletedCB;
	rvMtfRegisterMediaCallbacks(pUserConfig->mtfHandle, &mediaClbks);

//注册MTF连接相关的媒体回调
	connMediaClbks.connCreateMediaStreamCB = SipStack_MtfCreateMediaCB;
	connMediaClbks.connModifyMediaStreamCB = SipStack_MtfModifyMediaCB;
rvMtfRegisterConnMediaCallbacks(pUserConfig->mtfHandle, &connMediaClbks);

//注册MTF扩展回调处理
mdmExtClbks.connStateChangedCB = SipStack_MtfConnStateChangedCB;
mdmExtClbks.termRegistrationStateChangedCB = 
SipStack_MtfTermRegistrationStateChangedCB;
mdmExtClbks.termTransferCompletedCB = SipStack_MtfTermTransferCompletedCB;
mdmExtClbks.postProcessEventCB = SipStack_MtfPostProcessEventCB;
	rvMtfRegisterMdmExtCallbacks(&mdmExtClbks);
	
	//注册MTF处理IMS相关回调
	imsClbks.secAgreeNegCompletedEv = RvMtfHandleSecAgreeNegCompletedEv;
	rvMtfRegisterImsCallbacks(pUserConfig->mtfHandle, &imsClbks);
	
	//构建rtp对象
	RvRtpInit();
		//RV基础支撑模块初始化,已经在前面初始化过了。
		RvCBaseInit();
		
		//获取本地地址
		RvHostLocalGetAddress(logMgr, &numAddrs, rvRtpInstance.hostIPs);
		rvRtpInstance.addressesNum = numAddrs;
		
		//构造随机数生成器对象
		RvRandomGeneratorConstruct(&rvRtpInstance.randomGenerator,
		(RvRandom)(RvTimestampGet(logMgr)>>8));
		
		//构造目标地址内存池
		RvRtpDestinationAddressPoolConstruct();
		
		//第一个本地地址存储到rvRtpInstance.rvLocalAddress中
		RvAddressCopy(&rvRtpInstance.hostIPs[0], &rvRtpInstance.rvLocalAddress);
		
		//构造select引擎对象,之前已经构造了,这里仅仅是引用递增
		rtpMaxSessions = RVRTP_MAXSESSIONS;
		RvSelectConstruct(rtpMaxSessions, 0, logMgr, &rvRtpInstance.selectEngine);

//注册模拟线路终端对象
SipStack_RegisterAnalog()
	for(i = 0;i < RVSIP_LINE_NUM;i++)
		//初始化默认终端配置
		rvMtfTerminationInitConfig(&termConfig[i]);
		
		//使用用户配置更新终端配置
		SipStack_ConfigTermParam(i,&termConfig[i]);
		
		gstSipTermDC[i].pstTermConfig=&termConfig[i];
		
		//向MTF注册模拟线路终端
		rvMtfRegisterAnalogTermination (gstSipUserConfig.mtfHandle,
			gstSipUserConfig.mtfHandle, termConfig[i].username,    &termConfig[i],
			(RvMtfTerminalAppHandle)&gstSipTermDC[i],&gstIppTerm[i]);
				//设置终端默认配置,并使用用户配置进行更新
				rvMdmTermDefaultPropertiesConstruct(&termProperties);
				setTermProperties(&termProperties, termConfig);
				
				//注册模拟线路类型终端
				rvMdmTermMgrRegisterPhysicalTerminationAsync(termMgr,
mtfMgr->phoneClass, termId, &termProperties, (void*)hAppTerm);
	//该回调函数为ipPhoneRegisterPhysTermAsync,在下面单独
	//分析
					mgr->xTermMgrClbks->registerPhysTermAsyncF(mgr->xTermMgr, c, 
id, termProperties, userData);

//空函数
rvMtfStart(gstSipUserConfig.mtfHandle)

//MTF主线程处理函数
protocolThread
	//构造select引擎对象,并获取该引擎对象中的定时器队列做为MTF定时器机制处理。
	IppTimerInit();
	
	//将select引擎对象存储到engine变量中
	RvSelectGetThreadEngine(IppLogMgr(), &engine);
	
	//创建MTF消息处理,该消息处理基于SOCKET方式,并将该SOCKET对象加载到select
	//引擎对象中。其中消息处理回调函数为msgSocketCB,该函数的简单描述在下文。
	createMsgSockets();
	
	//触发信号量,让上文ProtocolThreadConstruct函数继续同步执行
	RvSemaphorePost(&threadConstructed, IppLogMgr());
	
	//进入MTF线程主处理循环中,这里主要处理MTF事件,及调度SIP Stack的消息处理,
	//也就是说Sip Stack对网络侧收到的数据报文,MTF从用户侧收到的事件,及定时器
	//事件的执行都是靠这里的主select引擎来调度。
	while (initiated)
		RvSelectWaitAndBlock(engine, timeout)
	
	//当将MTF释放时,这里执行协议栈的销毁回调处理,该函数在ProtocolThreadConstruct
	//函数中设置为sipStackProcessEnd
	for (protocol=0;protocol<RV_MTF_PROTOCOL_NUM;protocol++)
		protocolDestructF[protocol](protocolParam[protocol]);
	
	//select引擎销毁
	IppTimerEnd();

-------------------------------------------------------------------------------------------------------------------------------
//用户层向MTF发送的事件处理
msgSocketCB
	//从MTF事件socket中获取用户传入的消息信息
	RvSocketReceiveBuffer(&recvsock, (RvUint8*)&data,sizeof(data),IppLogMgr (),&bytesRcvd, 
	&fromAddr);
	
	if ((RvSize_t)data<RV_MTF_PROTOCOL_NUM)
		//当用户层发来的消息内容仅仅为小的数值时,做特殊处理,这里仅仅在
		//ProtocolThreadConstruct函数进行MTF核心线程初始化时,让MTF调用设置
		//的函数sipStackProcessInit进行Sip Stack的初始化。
		protocolConstructF[(RvSize_t)data](protocolParam[(RvSize_t)data]);
	else
		//对于其它内容的消息,则都归为向MTF发启的终端事件,这个处理函数中
		//MTF主要的业务处理函数,暂时不进行全面分析,待后面根据特定业务处理流程
		//中再进行分析。
		rvCCProviderMdmProcessTerminationEvent(data);

//注册物理终端
ipPhoneRegisterPhysTermAsync
	//注册物理终端
	mdmTerm = rvMdmProviderRegisterPhysTermAsync(x,c,id,termProperties, userData);
		//获取终端类型,这里返回RV_CCTERMINALTYPE_ANALOG
		type = rvCCProviderMdmFindTerminalType(c, id);
		
		//创建终端对象
		t = rvCCProviderMdmCreateTerminal(p, type, id, 0, termProperties);
			//终端创建
			rvCCTerminalMdmConstruct(t, x, id, type, clbks, termProperties,  provider->a);
				term->provider = p;
				term->alloc = a;
				
				//构造动态关键字段,这里设置了一个很重要的标记
				//x->blockedEventTypeMask = RV_BLOCKEDEVENT_NOTIFY,用于后继终端					//事件上报给MTF,MTF是否进行该终端事件处理的判断条件。
				constructDynamicFields(term);
				
				term->termType = type;	//RV_CCTERMINALTYPE_ANALOG
				term->terminalId = id	//用户号码
			term->type = RV_MDMTERMTYPE_UNKNOWN;
			term->inactive = RV_TRUE;
				term->numberOfLines = 2;
				……
				
				//设置终端配置属性
				rvMdmTermDefaultPropertiesConstructA(&term->defaultState, a);
				
				//x->terminal = term;
				//x->audioTermState = RV_CCAUDIOTERM_PASSIVE;
				//x->clbks = clbks;	//NULL
				rvCCTerminalInit(x, term, clbks);
				
				//一个终端拥有3个连接资源
				maxConnections = rvCCTerminalGetNumberOfLines(x);
				
				//一个终端可以建立2个呼叫
				term->numberOfLines =  2;	
				
				//为终端分配连接资源
				for (i=0;i<maxConnections;i++)
					x->connections[i] = rvAllocConnection(x, p);
					//x->lineId = i + 1;
					rvCCConnectionSetLineId(x->connections[i],i+1);
				
				term->compEventPkg = "dd";
				
				//为终端设置了两个数图处理定时器
				//digitMapTimer[0]和digitMapTimer[1]
				//分别对应的回调函数为digitMapTimerProcess0、digitMapTimerProcess1
				rvMdmTermDigitMapTimerConstruct(term);
				
				//当前没有为线路配置数图,所以使用的是从mdmProvider中取的全局					//性数图参数。
				if (*rvMdmDigitMapDescriptorGetName(&defaultProperties->digitMap))
					//no thing
				else
					//设置终端的数图,当前数图名为“dialplan0”
					setTermDigitMap(term, p);
				
				//如果配置了放播号音的时间,则初始化播号音定时器,并设置定时器的
				//超时处理回调为rvCCTerminalMdmDialToneTimerExpired
				if (rvCCProviderMdmGetDialToneDuration(…) > 0)
					IppTimerConstruct(&term->dialToneTimer,
					rvCCProviderMdmGetDialToneDuration(p),
					rvCCTerminalMdmDialToneTimerExpired, x);
				
				//如果配置了注册完成超时时间值,则初始化注册完成定时器,当注册包				//发出后,在指定超时时间没有完成,则执行定时器回调函数
				//rvCCTerminalMdmRegisterCompleteTimerExpired
				if (provider->registerCompleteTimeout > 0)
					IppTimerConstruct(&term->registerCompleteTimer,
					provider->registerCompleteTimeout * 1000,
					rvCCTerminalMdmRegisterCompleteTimerExpired, x);
				
				term->outOfBandDtmfRelayEnabled =
rvCCProviderMdmGetoutOfBandDtmf(…);
				term->playDtmfEnabled           = RV_FALSE;
				
				//显示信息初始化
				//x->presentationName[0] = '\0';
			//x->callerIdPermission = RV_MDM_PRSENTATION_RESTRICTED;
			//x->calleeIdPermission = RV_MDM_PRSENTATION_RESTRICTED;
				rvMdmTermPresentationInfoConstruct(&(term->presentationInfo));
				
				//设置呼叫转移业务参数为关闭
				// cfwData->cfwTypes[0].cfwState = RV_IPP_CFW_STATE_DEACTIVATED;
				// cfwData->cfwTypes[0].cfwState = RV_IPP_CFW_STATE_DEACTIVATED;
				// cfwData->cfwTypes[0].cfwState = RV_IPP_CFW_STATE_DEACTIVATED;
				rvCCCfwDataInitToDefaultValues(&(term->cfwData));
				
				//设置终端状态x->state = RV_CCTERMINAL_IDLE_STATE;
				rvCCTerminalSetState(x, RV_CCTERMINAL_IDLE_STATE);
			
			//将创建好的终端对象加入provider的终端列表中
			rvCCProviderMdmAddTerminal(provider, t);
		
		term = rvCCTerminalMdmGetImpl(t);
		
		//mdmTerm构造
		//term->termClass = 	termClass;	//mtfMgr->phoneClass
	//term->xTerm = xTerm;	//上面使用rvCCProviderMdmCreateTerminal创建好的终端
	//term->userData = NULL;
		//term-> type = RV_MDMTERMTYPE_PHYSICAL
		rvMdmTermConstruct_(&term->mdmTerm, c, t);
		rvCCTerminalMdmSetType(term, RV_MDMTERMTYPE_PHYSICAL);
		
		//存储本地和远端媒体能力集
		term->mediaCaps = rvMdmTermClassGetMediaCapabilites_(c);
		term->inactive = RV_FALSE;
		
		//使用用户配置中更新当前终端相关配置
		loadTerminalProperties(t, termProperties);
			rvMdmTermPhoneNumbersCopy(&(term->phoneNumbers),
&(termProperties->phoneNumbers));
			rvCCTerminalMdmLoadPresentationInfo(term, termProperties);
		
		//term->mdmTerm.userData =gstIppTerm[i];
		rvMdmTermSetUserData(&term->mdmTerm, userData);
		
		//给MTF主线程任务发送终端注册的事件,MTF处理事件的回调函数为
		// rvMdmTermProcessBlockedEvent,该函数里如果判断出是收到的终端注册
		//事件,则执行processBlockedEventRegisterTerm。
		//processBlockedEventRegisterTerm函数在下面单独分析。
		rvMdmTermQueueRegisterTermEvent(&term->mdmTerm);
			//向MTF发送消息
			rvMdmTermPostEvent(t);
			
			//标记当明终端阻塞在注册处理
			//term.blockedEventTypeMask |= RV_BLOCKEDEVENT_REGISTER
			rvCCTerminalMdmBlockedEventSetReg(term, RV_TRUE);
	
	//如果Sip协议在使用,当前已经使用
	if (rvCCBasePhoneIsUsed_(RV_MTF_PROTOCOL_SIP))
		//继续执行物理终端注册的后续处理,主要是自动注册触发
		//该函数后面在另一文档进行单独分析。
		sipPhoneRegisterPhysTermAsyncStep(mdmTerm, x, c, id, termProperties, userData);
		
		//如果用户配置了注册完成超时时间,则在上面已经创建了注册完成定时器,这里		//需要启动该定时器。
		timer = &mdmTerminal->registerCompleteTimer;
		if (timer->callback != NULL)
			IppTimerStart(timer,IPP_TIMER_DONT_CHECK_IF_STARTED, 0);

-------------------------------------------------------------------------------------------------------------------------------
//MTF处理终端注册事件
processBlockedEventRegisterTerm
	//为当前终端安装数图
	rvCCTerminalMdmInstallDigitMap(x, RV_FALSE);
		//从当前终端中查找索引为“dialplan0”的数图,并构成数图描述符对象
		rvStringConstruct(&name, "dialplan0", term->alloc);
		dm = rvMdmTermGetDigitMap(term, &name);
		rvMdmDigitMapDescriptorConstruct(&dmDescr, "dialplan0", dm);
		
		//人为构造请求事件,用于向终端安装数图
		buildReqEventCE(term, &dmDescr,activateDigitMap);
			//构造一个kp/ce包的请求事件对象
			rvMdmPackageItemConstruct(&pkgItem, "kp", "ce");
			rvMdmRequestedEventConstruct(&reqEvent, &pkgItem);
			rvMdmDigitMapDescriptorCopy(&reqEvent.digitMap, dmDescr);
			
			//安装数图,这里activateDigitMap = false
			rvMdmTermProcessDigitMapParameter(x, &reqEvent,activateDigitMap);
				//从请求事件对象中抽取数图描述符对象及请求包的标识
				digitMapDescr = rvMdmRequestedEventGetEmbDigitMap(reqEvent);
				name = rvMdmRequestedEventGetName(reqEvent);
				
				//数图定时器关闭,去激活
				rvMdmTermDeactivateDigitMap(x);
				
				//初始化状态,并保存请求事务对象
				rvStringResize(&x->dialString,0);
				x->digitMapStat = RV_MDMDIGITMAP_PARTIALMATCH;
				x->digitMapMedia = NULL;
				x->digitMapReqEvent = reqEvent;
				
				//从终端管理对象中获取之前已经注册的“kp”包对象
				x->digitMapEC = rvMdmTermMgrGetDigitMapPkgInfo_(…);
				
				//取出请求事件中的数图复制到终端digitMap中,用于终端之后数图处理
				//的匹配。
				rvMdmDigitMapCopy(&x->digitMap,rvMdmDigitMapDescriptorGetDigitMap
(digitMapDescr));
		
		//从数图描述符中获取数图,重新存储到终端对象storedDigitMaps中
		rvMdmTermProcessDigitMap(term, &dmDescr);
	
	//清除终端的RV_BLOCKEDEVENT_REGISTER标记
	rvCCTerminalMdmBlockedEventSetReg(term, RV_FALSE);
	
	//调用当前终端类的rvRegisterTermCompletedCB回调来处理终端注册完成通知,最终
	//rvRegisterTermCompletedCB函数会调用MTF中注册的registerAnalogTermCompletedCB
	//回调来通知用户层。
	rvMdmTermRegisterPhysTermDone_(&term->mdmTerm);


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值