📄 rvmegacocontext.c
字号:
/******************************************************************************
Filename : rvmegacocontext.c
Description: Methods for MEGACO Context (part of Termination Manager)
******************************************************************************
Copyright (c) 1999 RADVision Inc.
************************************************************************
NOTICE:
This document contains information that is proprietary to RADVision LTD.
No part of this publication may be reproduced in any form whatsoever
without written prior approval by RADVision LTD..
RADVision LTD. reserves the right to revise this publication and make
changes without obligation to notify any person of such revisions or
changes.
******************************************************************************
$Revision:$
$Date:11.15.00$
$Author: D.Elbert$
******************************************************************************/
#define MEGACO_ERROR(x) printf(x)
#include "rvmegacoerrors.h"
#include "rvmegacotermmgrutil.h"
#include "rvmegacotermmgr.h"
#include "rvmegacotopology.h"
#include "rvmegacocontext.h"
#include "rvmegacotermevent.h"
#include "rvmegacoentity.h"
/* Callback table for temporary terminations */
extern RvMdmXTermClbks * rvMegacoTmpTermMdmXClbks;
/* Static (internal) functions */
static RvMegacoCommandReply * addCommandReply(RvMegacoContext * x,const char* termId,const RvMegacoCommand * command,RvMegacoActionReply * actionReply);
static void setCommandError(RvMegacoContext * x,RvMegacoCommandReply * commReply,unsigned int code,const char * msg);
static RvMegacoTerm* getCommandTerm(RvMegacoContext * x,const RvMegacoCommand * command,
int* errCode,RvBool contextAll);
static void processServiceChange(RvMegacoContext * x,RvMegacoTerm * term,const RvMegacoCommand * command,RvMegacoCommandReply * commReply);
static void addActionReply(RvMegacoContext * x,RvMegacoActionReply ** actionReply,RvMegacoTransactionReply * transReply);
RvUint32 rvMegacoContextGetId(RvMegacoContext * x) {
return x->id;
}
RvBool rvMegacoContextMatchId(RvMegacoContext * x,RvUint32 id) {
return (id==x->id);
}
static RvBool isNullContext(RvMegacoContext * x) {
return (x->id==0);
}
static RvBool contextIsEmpty(RvMegacoContext * x) {
if(isNullContext(x)) /* Null context is never empty! */
return rvFalse;
return (rvMegacoTopologyGetNumNodes(&x->topology)==0);
}
/* TODO: This should check if is empty or absent */
static RvBool hasEmpyAudit(const RvMegacoAuditDescriptor* audit) {
RvMegacoAuditItems items = rvMegacoAuditDescriptorGetRequestedInfo(audit);
if( items & RV_MEGACOAUDITITEMS_STATS)
return rvFalse;
return rvTrue;
}
/* Note: the context is already locked here */
static RvBool canAddTerm(RvMegacoContext * x,RvMegacoTerm * term,RvMegacoCommandReply * commReply) {
if(rvMegacoTopologyGetNumTerm(&x->topology)==rvMegacoTermMgrGetMaxTermPerContext(x->termMgr)) {
/* Too many terminations in context */
setCommandError(x,commReply,RV_MEGACOERROR_NOTAVAIL_TERMID,"No TerminationID available");
return rvFalse;
}
return rvTrue;
}
/* Process Commands */
static void processMoveCommand(RvMegacoContext * x,RvMegacoTerm * t,const RvMegacoCommand * command,RvMegacoCommandReply * commReply);
static void processSubtractCommand(RvMegacoContext * x,RvMegacoTerm * t,const RvMegacoCommand * command,RvMegacoCommandReply * commReply);
static void processAddCommand(RvMegacoContext * x,RvMegacoTerm * t,const RvMegacoCommand * command,RvMegacoCommandReply * commReply);
static void processModifyCommand(RvMegacoContext * x,RvMegacoTerm * t,const RvMegacoCommand * command,RvMegacoCommandReply * commReply);
static void processAuditValue(RvMegacoContext * x,RvMegacoTerm * t,const RvMegacoCommand * command,RvMegacoCommandReply * commReply);
static void processAuditCaps(RvMegacoContext * x,RvMegacoTerm * term,const RvMegacoCommand * command,RvMegacoCommandReply * commReply);
/* Process a command for a given termination */
static RvBool processCommandPerTerm(RvMegacoContext * x,RvMegacoTerm* term,const RvMegacoCommand * command,RvMegacoCommandReply * commReply) {
RvMegacoCommandType commType = rvMegacoCommandGetType(command);
/* TODO: The inactive termination should reject signals, etc
But this is really the MGC problem!
if(rvMegacoTermIsInactive(term) && comType!=RV_MEGACOCOMMANDTYPE_SVCCHANGE ) {
setCommandError(x,commReply,RV_MEGACOERROR_NOTAVAIL_SRVC,"Termination inactive");
return rvFalse;
}
*/
/* Process the command */
switch(commType) {
case RV_MEGACOCOMMANDTYPE_ADD:
processAddCommand(x,term,command,commReply);
break;
case RV_MEGACOCOMMANDTYPE_MODIFY:
processModifyCommand(x,term,command,commReply);
break;
case RV_MEGACOCOMMANDTYPE_SUBTRACT:
processSubtractCommand(x,term,command,commReply);
break;
case RV_MEGACOCOMMANDTYPE_MOVE:
processMoveCommand(x,term,command,commReply);
break;
case RV_MEGACOCOMMANDTYPE_AUDITVAL:
processAuditValue(x,term,command,commReply);
break;
case RV_MEGACOCOMMANDTYPE_AUDITCAP:
processAuditCaps(x,term,command,commReply);
break;
case RV_MEGACOCOMMANDTYPE_SVCCHANGE:
processServiceChange(x,term,command,commReply);
break;
}
return rvMegacoTermMgrUtilIsCmdRspValid(commReply);
}
/* Process a command for a termination with wildcard response */
static RvBool processCommandPerTermWild(RvMegacoContext * x,RvMegacoTerm* term,const RvMegacoCommand * command,RvMegacoCommandReply * commReply,
RvPtrVector* pkgs,RvPtrVector* tClasses) {
/* Special case: a AUDIT with Termination Id == "Root"
This is used to get a list of contexts so don't generate a command response */
if(term==rvMegacoTermMgrGetRootTermination(x->termMgr) && !isNullContext(x) )
return rvTrue;
/* Process the command */
rvMegacoTermProcessCommandStart(term);
switch(rvMegacoCommandGetType(command)) {
case RV_MEGACOCOMMANDTYPE_AUDITVAL:
rvMegacoTermProcessAuditValueWild(term,rvMegacoAuditValCommandGetAudit(command),commReply);
break;
case RV_MEGACOCOMMANDTYPE_AUDITCAP:
rvMegacoTermProcessAuditCapsWild(term,rvMegacoAuditCapCommandGetAudit(command),commReply,
pkgs,tClasses);
break;
}
rvMegacoTermProcessCommandEnd(term);
return rvMegacoTermMgrUtilIsCmdRspValid(commReply);
}
/* Process a command for a termination with wildcard response */
static RvBool processAuditAll(RvMegacoContext * x,const RvMegacoCommand * command,
const char* termId,
RvMegacoActionReply** actionReply,
RvMegacoTransactionReply * transReply) {
RvMdmTermMgr* mdmMgr = x->termMgr->mdmTermMgr;
RvMegacoCommandReply * commReply;
RvPtrVector pkgs;
rvPtrVectorConstruct(&pkgs,x->alloc);
addActionReply(x,actionReply,transReply);
commReply = addCommandReply(x,termId,command,*actionReply);
rvMegacoTermProcessAuditCapsWildAll(mdmMgr,rvMegacoAuditCapCommandGetAudit(command),
commReply,&pkgs,x->alloc);
rvPtrVectorDestruct(&pkgs);
return rvMegacoTermMgrUtilIsCmdRspValid(commReply);
}
static void setTermError(RvMegacoContext * x,RvMegacoCommandReply* commReply,int errCode) {
if(errCode == RV_MEGACOERROR_NOTAVAIL_TERMID)
setCommandError(x,commReply,RV_MEGACOERROR_NOTAVAIL_TERMID,"No TerminationID available");
if(errCode==RV_MEGACOERROR_INUSE_TERMID)
setCommandError(x,commReply,RV_MEGACOERROR_INUSE_TERMID,"TerminationID is already in a Context");
else
setCommandError(x,commReply,RV_MEGACOERROR_UNKNWN_TERMID,"Unknown TerminationID");
}
typedef struct {
int matchedTerm;
RvBool idIsWild,idIsChoose;
RvMegacoContext * x;
const RvMegacoCommand * command;
RvMegacoActionReply** actionReply;
RvMegacoTransactionReply * transReply;
RvBool contextAll;
RvBool stat;
} RvMegacoContextProcOtherCtxtInfo;
static void constructProcOtherCtxtInfo(RvMegacoContextProcOtherCtxtInfo* info,
RvMegacoContext * x,const RvMegacoCommand * command,
RvMegacoActionReply** actionReply,
RvMegacoTransactionReply * transReply,RvBool contextAll) {
info->matchedTerm = 0;
info->x = x;
info->command = command;
info->actionReply = actionReply;
info->transReply = transReply;
info->contextAll = contextAll;
info->stat = rvTrue;
}
static RvBool processMatchingTerm(void *node, void *data) {
RvMegacoTerm* term = (RvMegacoTerm*)node;
RvMegacoContextProcOtherCtxtInfo* info = (RvMegacoContextProcOtherCtxtInfo*)data;
const RvMegacoTerminationId * termId = rvMegacoCommandGetTerminationId(info->command);
RvMegacoCommandReply * commReply;
/* Physical terms always stay in null context, so we need to check for special flag */
if(rvMegacoCommandGetType(info->command)==RV_MEGACOCOMMANDTYPE_ADD && !rvMegacoTermIsInNullCtxt(term))
return rvFalse;
/* For a MOVE command, don't process if the current and the destination are the same */
/* Note: this may not always give the best error code - check */
if(rvMegacoCommandGetType(info->command)==RV_MEGACOCOMMANDTYPE_MOVE && info->x==rvMegacoTermGetContext(term))
return rvFalse;
if(!rvMegacoTermMatchWildcard(term,rvMegacoTerminationIdGetId(termId)) )
return rvFalse;
/* If context is null, check if the termination is really there */
if( isNullContext(info->x) && !rvMegacoTermIsInNullCtxt(term))
return rvFalse;
info->matchedTerm++;
addActionReply(info->x,info->actionReply,info->transReply);
commReply = addCommandReply(info->x,rvMegacoTermGetId(term),info->command,*(info->actionReply));
info->stat = processCommandPerTerm(info->x,term,info->command,commReply);
/* Stop processing on error unless the command is optional */
if(info->stat!=rvTrue && !rvMegacoCommandIsOptional(info->command))
return rvTrue;
return rvFalse;
}
static RvBool processCommTermInOtherContext(RvMegacoContext * x,const RvMegacoCommand * command,
RvMegacoActionReply** actionReply,
RvMegacoTransactionReply * transReply,
RvBool contextAll) {
RvMegacoContextProcOtherCtxtInfo info;
const RvMegacoTerminationId * termId = rvMegacoCommandGetTerminationId(command);
RvMegacoCommandReply* commReply;
constructProcOtherCtxtInfo(&info,x,command,actionReply,transReply,contextAll);
if(rvMegacoCommandGetType(command)==RV_MEGACOCOMMANDTYPE_ADD)
rvMegacoTermMgrForEachInNullContext(x->termMgr,processMatchingTerm,&info);
if(rvMegacoCommandGetType(command)==RV_MEGACOCOMMANDTYPE_MOVE)
rvMegacoTermMgrForEachInActiveContexts(x->termMgr,processMatchingTerm,&info);
/* 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(!info.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 info.stat;
}
static RvMegacoTerm* getNextMatchingTerm(RvMegacoContext * x,const RvMegacoCommand * command,RvGraphNodeIter* i,RvGraphNodeIter* j) {
RvGraphNodeIter nextIter;
const RvMegacoTerminationId * termId = rvMegacoCommandGetTerminationId(command);
RvMegacoTerm* term;
RvBool isWildRsp = rvMegacoCommandGetWildResponseFlag(command);
RvMegacoContext* ephContext = &x->termMgr->ephContext;
if(*i==0)
*i=rvGraphBegin(&x->topology);
if(*i!=rvGraphEnd(&x->topology)) {
for(;*i!=rvGraphEnd(&x->topology); *i=nextIter) {
nextIter = rvGraphNodeIterNext(*i);
term = (RvMegacoTerm*)rvGraphNodeIterGetNode(*i);
/* If context is null, check if the termination is really there */
if( isNullContext(x) && !rvMegacoTermIsInNullCtxt(term))
continue;
if(rvMegacoTermMatchWildcard(term,rvMegacoTerminationIdGetId(termId))) {
*i = nextIter;
return term;
}
}
}
/* Try to found a match in some "dummy" ephemeral termination */
/* This is to allow a response to an audit caps or values for a "nonexisting"
ephemeral termination - The user must register a "dummy" ephemeral matching
the name pattern so the capabilities are taken from there */
if(isWildRsp && isNullContext(x) &&
*j!=rvGraphEnd(&ephContext->topology) &&
*i==rvGraphEnd(&x->topology) ) {
if(*j==0)
*j=rvGraphBegin(&ephContext->topology);
for(;*j!=rvGraphEnd(&ephContext->topology);*j=nextIter) {
nextIter = rvGraphNodeIterNext(*j);
term = (RvMegacoTerm*)rvGraphNodeIterGetNode(*j);
/* If context is null, check if the termination is really there */
if(!rvMegacoTermIsInNullCtxt(term))
continue;
if(rvMegacoTermMatchWildcard(term,rvMegacoTerminationIdGetId(termId))) {
*j = nextIter;
return term;
}
}
}
return NULL;
}
static RvBool processCommTermInContext(RvMegacoContext * x,const RvMegacoCommand * command,
RvMegacoActionReply** actionReply,
RvMegacoTransactionReply * transReply,
RvBool contextAll) {
RvMegacoTerm * term;
RvMegacoCommandReply * commReply;
RvBool stat = rvTrue;
int matchedTerm = 0;
RvGraphNodeIter i = 0, j= 0;
const RvMegacoTerminationId * termId = rvMegacoCommandGetTerminationId(command);
/* 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) {
commReply = addCommandReply(x,rvMegacoTermGetId(term),command,*actionReply);
}
if(rvMegacoCommandReplyIsTerminationList(commReply) ) {
RvMegacoTerminationId tmpId;
rvMegacoTerminationIdConstructA(&tmpId,rvMegacoTermGetId(term),x->alloc);
rvMegacoCommandReplyAddTermination(commReply,&tmpId);
rvMegacoTerminationIdDestruct(&tmpId);
}
else {
if(matchedTerm>1) /* Add additional replies if is not wildcarded response */
commReply = addCommandReply(x,rvMegacoTermGetId(term),command,*actionReply);
stat = processCommandPerTerm(x,term,command,commReply);
/* Stop processing on error unless the command is optional */
if(stat!=rvTrue && !rvMegacoCommandIsOptional(command))
break;
}
}
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 processCommTermInContextWildRsp(RvMegacoContext * x,const RvMegacoCommand * command,
RvMegacoActionReply** actionReply,
RvMegacoTransactionReply * transReply,
RvBool contextAll) {
RvMegacoTerm * term;
RvMegacoCommandReply * commReply;
RvBool stat = rvTrue;
int matchedTerm = 0;
RvGraphNodeIter i = 0, j= 0;
const RvMegacoTerminationId * termId = rvMegacoCommandGetTerminationId(command);
RvPtrVector pkgs,tClasses;
/* Keep the information about classes and packages processed */
rvPtrVectorConstruct(&pkgs,x->alloc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -