⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rvmegacocontext.c

📁 h.248协议源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	rvPtrVectorConstruct(&tClasses,x->alloc);

	/* Loop over matching terminations, add a reply for each one unless is 
	   a wildcarded response or termination list is required */
	while((term=getNextMatchingTerm(x,command,&i,&j))!=NULL) {

		/* The action reply will be added only if there is at least one command reply */
		matchedTerm++;
		addActionReply(x,actionReply,transReply);

		/* Add the first command reply */
		if(matchedTerm==1) { 
			/* Add the wildcarded id */
			commReply = addCommandReply(x,rvMegacoTerminationIdGetId(termId),command,*actionReply);	
		}

		stat = processCommandPerTermWild(x,term,command,commReply,&pkgs,&tClasses);
		/* Stop processing on error unless the command is optional */
		if(stat!=rvTrue && !rvMegacoCommandIsOptional(command))
			break;
	}

	rvPtrVectorDestruct(&pkgs);
	rvPtrVectorDestruct(&tClasses);

	if(stat!=rvTrue)
		return stat;

	/* Return an error message if no terminations were matched, unless the context is ALL */
	/* If there is already an action response return an error anyway (for consistency)    */
	if(!matchedTerm && (!contextAll || *actionReply!=NULL ) ) {
		addActionReply(x,actionReply,transReply);
		commReply = addCommandReply(x,rvMegacoTerminationIdGetId(termId),command,*actionReply);	
		setCommandError(x,commReply,RV_MEGACOERROR_NOMATCH_TERMID,"No TerminationID matched a wildcard");
		return rvFalse;
	}
	return stat;
}

static RvBool processCommandSingleTerm(RvMegacoContext * x,const RvMegacoCommand * command,
									   RvMegacoActionReply** actionReply,
									   RvMegacoTransactionReply * transReply,
									   RvBool contextAll) {
	RvMegacoTerm * term;
	RvMegacoCommandReply * commReply;
	const RvMegacoTerminationId * termId = rvMegacoCommandGetTerminationId(command);
	int errCode = 0;

	/* Get a valid termination to apply the command. If it can't, return with error */
	term = getCommandTerm(x,command,&errCode,contextAll);
	if(term==NULL) { 
		/* If context is all don't set an error for term not found except in case that there is already an action
		   reply,meaning that a previous command generated a response or when some other error happens  */
		if(!contextAll || *actionReply!=NULL || errCode!=0 ) { 
			addActionReply(x,actionReply,transReply);
			commReply = addCommandReply(x,rvMegacoTerminationIdGetId(termId),command,*actionReply);	
			setTermError(x,commReply,errCode);
		}
		return rvFalse;
	}
	addActionReply(x,actionReply,transReply);
	commReply = addCommandReply(x,rvMegacoTermGetId(term),command,*actionReply);	
	return processCommandPerTerm(x,term,command,commReply);
}

/* If the MG has been disabled by the MGC , still need to accept SVC so it can 
   come up again */
static RvBool checkTermMgrAvailable(RvMegacoContext * x,const RvMegacoCommand * command,
									RvMegacoCommandType commType,
									RvMegacoActionReply** actionReply,
									RvMegacoTransactionReply * transReply) {

	/* If the termination manager is disabled, accept only SVC */
	if(rvMegacoTermMgrIsDisabled(x->termMgr) && commType!=RV_MEGACOCOMMANDTYPE_SVCCHANGE ) {
		RvMegacoCommandReply reply;

		addActionReply(x,actionReply,transReply);
		rvMegacoCommandReplyConstructA(&reply,command,x->alloc);
		setCommandError(x,&reply,RV_MEGACOERROR_NOTAVAIL_SRVC,"Service Unavailable");
		rvMegacoActionReplyAddReply(*actionReply,&reply);
		rvMegacoCommandReplyDestruct(&reply);

		return rvFalse;
	}

	return rvTrue;
}


static RvBool processCommand(RvMegacoContext * x,const RvMegacoCommand * command,
							 RvMegacoActionReply** actionReply,
							 RvMegacoTransactionReply * transReply,
							 RvBool contextAll) {
	const RvMegacoTerminationId * termId = rvMegacoCommandGetTerminationId(command);
	RvMegacoCommandType commType = rvMegacoCommandGetType(command);
/*	RvBool idIsWild = rvMegacoTerminationIdIsWild(termId);*/
/*	RvBool idIsChoose = rvMegacoTerminationIdIsChoose(termId);*/
	RvBool isWildRsp = rvMegacoCommandGetWildResponseFlag(command);

	/* Have to check at this level to be able to accept a SVC */
	if(!checkTermMgrAvailable(x,command,commType,actionReply,transReply))
		return rvFalse;

	if(!rvMegacoTerminationIdIsWild(termId) )
		return processCommandSingleTerm(x,command,actionReply,transReply,contextAll);

	switch(commType) {
		case RV_MEGACOCOMMANDTYPE_ADD:
		case RV_MEGACOCOMMANDTYPE_MOVE:
			return processCommTermInOtherContext(x,command,actionReply,transReply,contextAll);

		case RV_MEGACOCOMMANDTYPE_MODIFY:
		case RV_MEGACOCOMMANDTYPE_SUBTRACT:
		case RV_MEGACOCOMMANDTYPE_AUDITVAL:
			if(isWildRsp)
				return processCommTermInContextWildRsp(x,command,actionReply,transReply,contextAll);
			else
				return processCommTermInContext(x,command,actionReply,transReply,contextAll);

		case RV_MEGACOCOMMANDTYPE_SVCCHANGE:
				return processCommTermInContext(x,command,actionReply,transReply,contextAll);

		case RV_MEGACOCOMMANDTYPE_AUDITCAP:
			/* Special case: Audit all capabilities in null context with wildcard response */
			/* Termination must be "*" and context must be NULL */
			if( isNullContext(x) && isWildRsp && 
				!strcmp(rvMegacoTerminationIdGetId(termId),"*") && !contextAll )	
				return processAuditAll(x,command,rvMegacoTerminationIdGetId(termId),
									   actionReply,transReply);
			else if(isWildRsp)
				return processCommTermInContextWildRsp(x,command,actionReply,transReply,contextAll);
			else
				return processCommTermInContext(x,command,actionReply,transReply,contextAll);
		default:
			return rvTrue;
	}
}

/* Find a termination by id */
RvMegacoTerm * rvMegacoContextGetTerm(RvMegacoContext * x,const char * id) {
	RvMegacoTerm * term = NULL;
	rvMutexLock(&x->mutex);
	term =  rvMegacoTopologyGetTerm(&x->topology,id);

	/* Check if the termination is really in the null context */
	if(term!=NULL && isNullContext(x) && !rvMegacoTermIsInNullCtxt(term) )
		term = NULL;

	rvMutexUnlock(&x->mutex);
	return term;
}
/* Find a termination by id in null context */
RvMegacoTerm * rvMegacoContextGetTermInNull(RvMegacoContext * x,const char * id) {
	RvMegacoTerm * term = NULL;
	rvMutexLock(&x->mutex);
	term =  rvMegacoTopologyGetTerm(&x->topology,id);

	rvMutexUnlock(&x->mutex);
	return term;
}

/* Note: this may be changed later to allow allocating the terminations from 
   a pool, or use some special allocator for terminations */
RvMegacoTerm * rvMegacoContextAddNewTerm(RvMegacoContext * x,const char * id) {
	RvMegacoTerm * term; 
	rvMutexLock(&x->mutex);
	term = rvAllocAllocate(x->alloc,sizeof(RvMegacoTerm));
	rvMegacoTermConstruct(term,id,x,x->alloc);
	/* If context is NULL or Ephemeral, don't create links */
	if(x->id==0)
		rvMegacoTopologyAddTerm(&x->topology,term,NULL);
	else
		rvMegacoTopologyAddTerm(&x->topology,term,x->alloc);
	rvMutexUnlock(&x->mutex);
	return term;
}

static RvMegacoTerm * addUnknownTerm(RvMegacoContext * x,const char * partialName) {
	RvMegacoTerm * term = rvMegacoContextAddNewTerm(x,partialName);
	rvMegacoTermSetType(term,RV_MDMTERMTYPE_UNKNOWN);
	/* Construct the mdmTerm */
	rvMdmTermConstruct_(rvMegacoTermGetMdmTerm(term),NULL,rvMegacoTmpTermMdmXClbks,term);
	return term;
}

/* Find and validate the command termination */
static RvMegacoTerm*  getSelectedTerm(RvMegacoContext * x,const RvMegacoCommand * command,
									 int* errCode) {
/*	RvMegacoTerm * term = NULL; */
	RvMdmTerm* selectTerm;
	RvMegacoTerm * tmpTerm = NULL;
	const RvMegacoTerminationId * termId = rvMegacoCommandGetTerminationId(command);

	/* Save in case that it fails later */
	x->chooseId = termId;

	/* A "temporary" term is created to hold the rigth topology
	   and the command. This will be later replaced by the term selected
	   by the application (physical or ephemeral)
	*/
	tmpTerm = addUnknownTerm(x,rvMegacoTerminationIdGetId(termId));
	if(tmpTerm==NULL) { 
		*errCode = RV_MEGACOERROR_NOTAVAIL_TERMID;
		return NULL;
	}

	/* Note: the temporary termination must provide access to topology,
	   requested media and partial (or total) name */
	rvMdmTermSetRequestedMedia_(rvMegacoTermGetMdmTerm(tmpTerm),rvMegacoAddCommandGetMedia(command));
	selectTerm = rvMdmTermMgrSelectTermination_(x->termMgr->mdmTermMgr,rvMegacoTermGetMdmTerm(tmpTerm));
	if( selectTerm==NULL ) {
		*errCode = RV_MEGACOERROR_NOTAVAIL_TERMID;
	}
	/* Not required because topology will be set later
	else { // Duplicate the temporary term topology, 
		term = (RvMegacoTerm *)rvMdmTermGetXTerm_(selectTerm);
		rvMegacoTopologyDuplicate(&x->topology,tmpTerm,term);
	}
	*/

	/* Release temporary termination */
	rvMegacoTopologyRemoveTerm(&x->topology,tmpTerm,x->alloc);
	rvMegacoTermDestruct(tmpTerm);
	rvAllocDeallocate(x->alloc,sizeof(RvMegacoTerm),tmpTerm);

	return (RvMegacoTerm *)rvMdmTermGetXTerm_(selectTerm);
}
		

/* Only for not wildcarded commands */
/* If errCode is set in return,the error should be returned even for context ALL */
/* (some commands require error even in this case: ADD and MOVE */
static RvMegacoTerm*  getCommandTerm(RvMegacoContext * x,const RvMegacoCommand * command,
									 int* errCode,RvBool contextAll) {

	const RvMegacoTerminationId * termId = rvMegacoCommandGetTerminationId(command);
	const char * id = rvMegacoTerminationIdGetId(termId);
	RvMegacoTerm * term = NULL;
	RvMegacoCommandType type = rvMegacoCommandGetType(command);

	if(rvMegacoTerminationIdIsChoose(termId) && type==RV_MEGACOCOMMANDTYPE_ADD) {
		term = getSelectedTerm(x,command,errCode);
		/* Save first selected term for topology */
		if(x->chosenTerm==NULL)
			x->chosenTerm = term;
	}

	else if(rvMegacoTerminationIdIsNormal(termId)) {
		switch(type) {
			case RV_MEGACOCOMMANDTYPE_ADD:
				term = rvMegacoTermMgrFindInNullContext(x->termMgr,id); 
				if( term!=NULL && !rvMegacoTermIsInNullCtxt(term) ) {
					term = NULL;	
					*errCode = RV_MEGACOERROR_INUSE_TERMID;
				}
				break;
			case RV_MEGACOCOMMANDTYPE_MODIFY:
			case RV_MEGACOCOMMANDTYPE_AUDITVAL:
			case RV_MEGACOCOMMANDTYPE_AUDITCAP:
			case RV_MEGACOCOMMANDTYPE_SVCCHANGE:
				/* If some command is addressed at a termination in the NULL 
					context, but it is already active, set correct error code */
				if( isNullContext(x) ) {
					term = rvMegacoTermMgrFindInNullContext(x->termMgr,id); 
					if( term!=NULL && !rvMegacoTermIsInNullCtxt(term) ) {
						term = NULL;	
						*errCode = RV_MEGACOERROR_INUSE_TERMID;
					}
				}
				else /* Termination must be in active context */ 
					term = rvMegacoContextGetTerm(x,id); break;

			case RV_MEGACOCOMMANDTYPE_SUBTRACT:
				term = rvMegacoContextGetTerm(x,id); break;

			case RV_MEGACOCOMMANDTYPE_MOVE:
				term = rvMegacoTermMgrFindInActiveContexts(x->termMgr,id); break;
		}
	}
	/* Root termination is allowed only for certain commands and only
	   for the null context */
	/* For audit is allowed for other contexts for the special case 
	   that audit of context id */
	else if(rvMegacoTerminationIdIsRoot(termId) ) {
		switch(type) {
			case RV_MEGACOCOMMANDTYPE_AUDITVAL:
			case RV_MEGACOCOMMANDTYPE_AUDITCAP:	
				if(contextAll || isNullContext(x) )
					term = rvMegacoTermMgrGetRootTermination(x->termMgr); break;
			case RV_MEGACOCOMMANDTYPE_MODIFY:
			case RV_MEGACOCOMMANDTYPE_SVCCHANGE:
				if( isNullContext(x) )
					term = rvMegacoTermMgrGetRootTermination(x->termMgr); 
				break;
		}
	}

	return term;
}

/* Add an action reply if it doesn't exist */
static void addActionReply(RvMegacoContext * x,RvMegacoActionReply ** actionReply_,RvMegacoTransactionReply * transReply) {
	RvMegacoContextId contextId;
	RvMegacoActionReply actionReply,* newReply;
	unsigned int id = rvMegacoContextGetId(x);

	if(*actionReply_!=NULL)
		return;
	
	if(id==0)
		rvMegacoContextIdConstructSpecial(&contextId,RV_MEGACOCONTEXTID_NULL);
	else
		rvMegacoContextIdConstruct(&contextId,id);

	rvMegacoActionReplyConstructExA(&actionReply,&contextId,x->alloc);	
	rvMegacoContextIdDestruct(&contextId);
	rvMegacoTransactionReplyAddReply(transReply,&actionReply);
	rvMegacoActionReplyDestruct(&actionReply);	
	newReply = (RvMegacoActionReply*)rvMegacoTransactionReplyGetReply(transReply,rvMegacoTransactionReplyGetNumReplies(transReply)-1);
	*actionReply_ = newReply;
}

RvBool rvMegacoContextProcessAction(RvMegacoContext * x,const RvMegacoAction * action,
									RvMegacoTransactionReply * transReply,
									RvBool contextAll) {
	size_t i;
	RvMegacoActionReply * actionReply = NULL;
	RvBool stat = rvTrue;
	const RvMegacoContextProperties* contextProperties;
	RvMdmError error;
	rvMdmErrorConstruct_(&error);
	
	rvMutexLock(&x->mutex);

	contextProperties = rvMegacoActionGetContextProperties(action);
	if(!rvMegacoContextPropertiesIsEmpty(contextProperties)) {
		/* Set context properties */
		rvMegacoContextSetEmergency(x,rvMegacoContextPropertiesIsEmergency(contextProperties));
		rvMegacoContextSetPriority(x,rvMegacoContextPropertiesGetPriority(contextProperties));
		x->topologyDescr = rvMegacoContextPropertiesGetTopology(contextProperties);
	}
	else
		x->topologyDescr = NULL;

	/* There is no choose termination at the beginning */
	x->chosenTerm=NULL;

	/* Get the commands from the list and process them */
	/* TODO: Rollback preprocessed commands if a processCommand fails ?? */
	for(i=0;i<rvMegacoActionGetNumCommands(action);i++)  {
		if(!processCommand(x,rvMegacoActionGetCommand(action,i),&actionReply,transReply,contextAll)) {
			stat = rvFalse;
			break;
		}
	}

	/* Avoid the case that a empty context is left 'dangling' 
	   because there is no way to explicitly clean it */
	if(contextIsEmpty(x)) {
		rvMegacoTermMgrDeleteContext(x->termMgr,x);
		return stat;
	}

	/* There is no topology in the null context */
	if( stat && !isNullContext(x) ) {
		const RvMegacoTopologyDescriptor * topology = rvMegacoContextPropertiesGetTopology(contextProperties);
		rvMegacoTopologyUpdate(&x->topology,x->chosenTerm,topology);
		/* Call callbacks to connect media streams created before */
		rvMegacoTopologyUpdateMediaConnections(&x->topology,&error);

		/* If there is no response, create one with the topology */
		/* Note: maybe this is always required if there is a topology descriptor? */
		/* Note: Is not clear what to encode in the topology argumments,by echo the input */
		if( rvMegacoTopologyDescriptorGetNumTriples(topology) && actionReply == NULL) {
			addActionReply(x,&actionReply,transReply);
			rvMegacoActionReplySetContextProperties(actionReply,contextProperties);													
		}			
	}

	rvMutexUnlock(&x->mutex);

	return stat;
}

/***************************************************************************/
/*		Process commands					                               */
/***************************************************************************/
static void processMoveCommand(RvMegacoContext * x,RvMegacoTerm * term,
							   const RvMegacoCommand * command,RvMegacoCommandReply * commReply) {

	/* Termination can't be moved to the NULL context */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -