BCM VOIP 注册流程分析

来源:互联网 发布:金蝶软件多少钱 编辑:程序博客网 时间:2024/05/16 23:36

注册发起

//初始化注册callRegSetup( ®Id, &pu[i] );//分配一个注册控制块regIdx = CreateRegIdx();//将用户参数保存到注册控制块中//callgcb.reg[i]->suser.username// callgcb.reg[i]->suser. display// callgcb.reg[i]->suser. authname// callgcb.reg[i]->suser. password// callgcb.reg[i]->suser. realmlist. realm[k].realm// callgcb.reg[i]->suser. realmlist. realm[k]. username// callgcb.reg[i]->suser. realmlist. realm[k]. password// callgcb.reg[i]->suser. registrar.addr// callgcb.reg[i]->suser. aorHostport.addr// callgcb.reg[i]->suser. mohserver.addr// callgcb.reg[i]->suser. mohserver.display// callgcb.reg[i]->suser. routeSet.route[k].addr.addr// callgcb.reg[i]->suser. mohserver.scheme = CCURITYPE_SIP;// callgcb.reg[i]->suser. mohserver.params = NULL;// callgcb.reg[i]->aorValid// callgcb.reg[i]->registrarEnabled// callgcb.reg[i]->routeSetEnabledSetSuserParm(regIdx, suser);//初始状态为CCSTS_UNREGISTEREDreg->regState = CCSTS_UNREGISTERED;//无源码,不太清楚reg->pUAAuthentication->SetManager(&sipcb);reg->pUAAuthentication->ReleaseIfRef();//如果当前用户配置了realm参数,则调用协议栈接口添加鉴权凭证for (UINT32 i = 0; i < realmlist->num; i++)realm = realmlist->realm[i].realm;user = realmlist->realm[i].username;password = realmlist->realm[i].password;reg->pUAAuthentication->AddCredentialsA(realm, user, password);if (reg->registrarEnabled)//如果用户配置了路由集,则转化为MT5内部格式if (reg->routeSetEnabled)SetRoute(regIdx, reg->suser.registrar.addr, reg->suser.registrar.port, GO preloadRoute);//格式化From头域地址FormAddrOfRecord(regIdx, addressOfRecord);//格式化Request-URI//格式化Contact头域//调用协议栈句柄,初始化注册管理控制块reg->pUARegistration = BRCM_NEW(MX_NS CUARegistration);reg->pUARegistration->Initialize(&sipcb, &sipcb, &addressOfRecord, &contactHdrs,&localContactHdrs, &sipUri, &addressOfRecord, &serverLocatorListModifierCb, (mxt_opaque)serverLocOpaque, serverLocatorPrevListModifierCb,serverLocPrevOpaque, preloadRoute );//调用协议栈句柄,设置一些通用头域SetGenHeaders(*rid, NULL);//将鉴权模块附加到注册控制块中reg->pUARegistration->SetAuthenticationS(reg->pUAAuthentication, callgcb.mutex);//没有源码,不太清楚reg->pUARegistration->SetOpaqueS((mxt_opaque)(*rid), callgcb.mutex);reg->pUAAuthentication->SetOpaqueS((mxt_opaque)(*rid), callgcb.mutex);//将注册控制块索引关联到cmEndpt中cmEndpt[i].regId = regId;if( cmEndpt[i].registrarEnabled )//向注册对象中添加Authorization和Supported头sprintf( hdrValue, "Digest username=\"%s\", realm=\"%s\", nonce=\"\", uri=\"sip:%s\", response=\"\", algorithm=MD5",pu[i].authname, pu[i].registrar.addr, pu[i].registrar.addr );headers.list[headers.num].type = CCHDR_GENERIC;headers.list[headers.num].hdr.generic.name = CHDR_AUTHORIZATION_NAME;headers.list[headers.num].hdr.generic.value = hdrValue;headers.map[headers.num] = CCHDRMAP_REQ_ONLY;headers.num++;headers.list[headers.num].type = CCHDR_GENERIC;headers.list[headers.num].hdr.generic.name = CHDR_SUPPORTED_NAME;headers.list[headers.num].hdr.generic.value = CHDR_SUPPORTED_VALUE;headers.map[headers.num] = CCHDRMAP_REQ_ONLY;headers.num++;callSetParm( regId, CCPARM_GENHDRS, (void *)&headers );//重置注册超时定时器cmEndpt[i].regRetryTimerMs = 0;cmEndpt[i].regActTimerMs = EPT_REGACT_TIMER;//发起注册callRegister( regId, NULL );//仅在未注册或者已经注册成功的最终状态下,才处理注册请求if ((reg->regState == CCSTS_UNREGISTERED)|| (reg->regState == CCSTS_REGISTERED))//注册控制块状态迁为CCSTS_REGINPROGRESSreg->regState = CCSTS_REGINPROGRESS;//构建Contact头域FormRegistrationContacts(regIdx, localContactHdrs);//当前content为空,不处理FormatContent(content, msgBody);//调用协议栈句柄,发起注册请求reg->pUARegistration->RegisterA(&localContactHdrs, TO msgBody);
 

注册超时

//当前没有板子调试,协议栈没有源码,猜测当前流程从此入口进入。1、callctrl事件回调SIPCB::EvFailedARegistrationState(pRegistration, eState, pPacket);switch (FSM_(eState, callgcb.reg[uRegIdx]->regState))//正在注册过程中,收到eREGISTRATION_REQUEST_TIMEOUT事件case FSM(eREGISTRATION_REQUEST_TIMEOUT, CCSTS_REGINPROGRESS)://当前注册控制块状态迁为CCSTS_UNREGISTEREDcallgcb.reg[uRegIdx]->regState = CCSTS_UNREGISTERED;//给callmgr发送CCEVT_STATUS/ CCRSN_REG_TIMEOUT事件GCBEVTSTATUS(rid, CCRSN_REG_TIMEOUT, pp);2、callmgr处理从callctrl发来的CCEVT_STATUS/ CCRSN_REG_TIMEOUT事件cmProcessCallEventswitch (event)case CCEVT_STATUS:switch( reason )case CCRSN_REG_TIMEOUT://获取cmEndpt控制块endpt = cmFindEndptFromRegId( cid );//取消注册超时探测定时器cmEndpt[endpt].regActTimerMs = 0;//映射为CMEVT_STATUS事件cnxevent = cmMapById( cmCallEvtMap, reason);if ((cnxevent == CMEVT_STATUS) && (endpt != UNKNOWN))switch (reason)case CCRSN_REG_TIMEOUT://如果已处于在线状态if( cmEndpt[endpt].inservice == TRUE )//复位在线状态cmEndpt[endpt].inservice = FALSE;//更新是否在线状态显示cmDisplay( endpt, UNKNOWN, CMLCD_SERVER);switch ( msgtype)case CMLCD_SERVER:cmEndptNotify( endpt, UNKNOWN, CMEVT_INSERVICE, cmEndpt[endpt].inservice);cmEndptStateEngine( endpt, cid, event, data );case FSM( CMEVT_INSERVICE, CMST_ONHOOK)://这里主要调用了cmPublishEvent,当然该函数的回调//中没有对CMEVT_INSERVICE事件的处理。//更新cmEndpt关联兄弟控制块的inservicecmUpdateRegSib( endpt );//检查SIP报文是否含有Retry-Afterr头域,如果有则将当前线路的重新注//册时间更新为该值。当前超时流程不会有报文存在,所以不执行此流程。if( headers &&  headers->num )for( i = 0; i < (int)headers->num; i++ )if( headers->list[i].type == CCHDR_RETRY_AFTER )cmEndpt[endpt].regRetryTimerMs =  headers->list[i].hdr.retry.deltasec * 1000;//设置重新注册时间为用户配置的值if( !cmEndpt[endpt].regRetryTimerMs )cmEndpt[endpt].regRetryTimerMs = cmProvisionGet(PROVIS_SIP_REGRETRY_TIMER, endpt)) * 1000//当前没有对CCEVT_STATUS/CCRSN_REG_TIMEOUT事件的处理cmProtProcessCallEvent( endpt, cnxevent, reason, packet );
 

注册成功

1、callctrl事件回调SIPCB::EvRegisteredA//从sip报文中获取Allow-Events头域字段,并存储到注册控制块中reg->allowevtsGetAllowEvents(reg->allowevts, (MX_NS CSipPacket*)pPacket);RegistrationState(pRegistration, IUARegistrationMgr::eREGISTERED, pPacket);//提取应答码,并将SIP包转化成callctrl格式if (pPacket && pPacket->IsResponse())uStatus = pPacketCopy->GetStatusLine()->GetCode();strPhrase = pPacketCopy->GetStatusLine()->GetPhrase();GetPacket(*pPacketCopy, outPacket);pp = (outPacket.content != NULL || outPacket.hdrs != NULL) ? &outPacket : NULL;switch (FSM_(eState, callgcb.reg[uRegIdx]->regState))//在正在注册状态下收到注册成功case FSM(eREGISTERED, CCSTS_REGINPROGRESS)://注册控制块状态迁为CCSTS_REGISTEREDcallgcb.reg[uRegIdx]->regState = CCSTS_REGISTERED;//给callmgr发送CCEVT_STATUS/ CCRSN_REG_OK事件GCBEVTSTATUS(rid, CCRSN_REG_OK, pp);2、callmgr处理从callctrl发来的CCEVT_STATUS/CCRSN_REG_OK事件cmProcessCallEventswitch (event)case CCEVT_STATUS:switch( reason )case CCRSN_REG_OK://获取cmEndpt控制块endpt = cmFindEndptFromRegId( cid );//取消注册超时探测定时器cmEndpt[endpt].regActTimerMs = 0;//映射为CMEVT_STATUS事件cnxevent = cmMapById( cmCallEvtMap, reason);if ((cnxevent == CMEVT_STATUS) && (endpt != UNKNOWN))switch (reason)case CCRSN_REG_OK:if( cmEndpt[endpt].inservice == FALSE )//在cmEndpt控制块中记载当前已经在线 cmEndpt[endpt].inservice = TRUE;//该函数最终触发cmPublishEvent回调,但该回调中没有对应事件处理cmDisplay( endpt, UNKNOWN, CMLCD_SERVER);//将关联的兄弟cmEndpt也标记为在线cmUpdateRegSib( endpt );cmProtProcessCallEvent( endpt, cnxevent, reason, packet );if (cnxevent == CMEVT_STATUS  && (endpt != UNKNOWN))if (reason == CCRSN_REG_OK )//如果注册应答报文中含有Service-Route头域,则记录到cmEndpt控制块if( headers && headers->num )for( i = 0 ; i < headers->num ; i++ )if( headers->list[i].type == CCHDR_SERVICE_ROUTE )strcpy( cmEndpt[endpt].srAddr,headers->list[i].hdr.route.service.addr );cmEndpt[endpt].srPort =headers->list[i].hdr.route.service.port;//发送MWI消息订阅cmMwiSubscribe(endpt);//用户开启了订阅服务if ( cmEndpt[endpt].explicitMwi.enabled )//构造to字段cmSetCalledParty( endpt, &calledparty, to );//分配呼叫控制块,并初始化用户配置参数callSetup( &cid, cmEndpt[endpt].regId, CCCIDTYPE_MWI, &calledparty);//将消处订阅类型的呼叫控制块索引关联到cmEndpt中cmEndpt[endpt].explicitMwi.mwiCid = cid;//设置PREFERRED_ID头域callSetParm( cid, CCPARM_PREFERRED_ID, (void *)&prefId );//如果本地配有outband服务器,或者注册应答中含有//Service-Route头域,则当前注册包加入Route头域cmSetServiceRoute( cid, endpt );//调用协议栈句柄发起Subscribe请求callSubscribe( cmEndpt[endpt].explicitMwi.mwiCid, SUBSCRIBTION_TIMEOUT_SECS, NULL, NULL );//cmCnx控制块关联cmEndpt控制块cmCnx[cid].endpt = endpt;//MWI状态机变迁为CMMWI_SUBSCRIBINGcmEndpt[endpt].explicitMwi.mwiState = CMMWI_SUBSCRIBING;//发送注册订阅cmRegEvtPkgStateEngine( endpt, UNKNOWN, cnxevent, CCRSN_REG_OK );ep = &cmEndpt[endpt];regevt = &cmRegEvtPkg.regEvtProfBlk[endpt];switch( FSM( event, state ))case FSM( CMEVT_STATUS, CMSUBSTATE_IDLE ):switch( reason )case CCRSN_REG_OK://发起订阅cmRegEvtPkgSubscribe( UNKNOWN, regevt );//创建一个呼叫控制块,并初始化并初始化用户配置//参数callSetup( &cid, cmEndpt[endpt].regId, CCCIDTYPE_EVENT, &to )//注册订阅控制块关联呼叫控制块,并初始化状态cmCnx[cid].endpt = pRegEvt->endpt;cmCnx[cid].state = CMST_IDLE;pRegEvt->reqId.cid = cid;pRegEvt->reqId.state = CMSUBSTATE_SUBSCRIBING;//设置PREFERRED_ID头域callSetParm( cid, CCPARM_PREFERRED_ID, (void *)&to );//设置Accept: application/reginfo+xml头域sprintf( display, "Accept" );sprintf( eventValue, "%s/%s",CMREGEVT_ACCEPT_HEADER_TYPE_APP,CMREGEVT_ACCEPT_HEADER_SUBTYPE_REGINFO );headers.list[headers.num].type = CCHDR_GENERIC;headers.list[headers.num].hdr.generic.name = display;headers.list[headers.num].hdr.generic.value = eventValue;headers.map[headers.num] = CCHDRMAP_ALWAYS;headers.num++;callSetParm( cid, CCPARM_GENHDRS, (void *)&headers );//如果本地配有outband服务器,或者注册应答中含有//Service-Route头域,则当前注册包加入Route头域cmSetServiceRoute( cid, endpt );//调用协议栈句柄发起Subscribe请求callSubscribe( cid, SUBSCRIBTION_TIMEOUT_SECS,eventValue, NULL )

原创粉丝点击