📄 rvmegacotermmgr.c
字号:
/******************************************************************************
Filename : rvmegacotermmgr.c
Description: Methods for MEGACO 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.9.00$
$Author: D.Elbert$
******************************************************************************/
#include "rvmegacoerrors.h"
#include "rvmegacotermmgr.h"
#include "rvmegacocontext.h"
#include "rvmegacoterm.h"
#include "rvmdm.h"
#include "rvmegacotermevent.h"
#include "rvmegacotrans.h"
#include "rvmegacoentity.h"
/* Size of event queue */
#define RV_MEGACOTERMMGR_EVQUEUESIZE 32
/* Size of event thread stack */
#define RV_MEGACOTERMMGR_EVSTACKSIZE 12288
/* Initial hash table size */
#define RV_MEGACOCONTEXTS_BUCKETS 50
/* Used for contexts */
#define RvMegacoContextPtrConstructCopy rvDefaultConstructCopy
#define RvMegacoContextPtrGetAllocator rvDefaultGetAllocator
#define RvMegacoContextPtrDestruct rvDefaultDestruct
rvDefineHash(RvUint32,RvMegacoContextPtr)
/*-------------------------------------------------------------------------
Context Manager Methods
-------------------------------------------------------------------------*/
/* Callback table for physical terminations */
extern RvMdmXTermClbks * rvMegacoPhysTermMdmXClbks;
extern RvMdmXTermClbks * rvMegacoEphTermMdmXClbks;
extern RvMdmXTermClbks * rvMegacoRootTermMdmXClbks;
#define MEGACO_ERROR(x) printf(x)
void procServiceChangeReply(RvMegacoTcb *tcb, const RvMegacoTransactionReply *reply, void *data, RvTransactionStatus reason);
void rvMegacoTermMgrCommFailure(RvMegacoTermMgr * mgr);
static char rvSubtractAllTrans[] = "Transaction = 1 { Context = * { Subtract = * } }";
RvUint32 newContextId(RvMegacoTermMgr * mgr) {
RvUint32 tmp;
rvMutexLock(&mgr->lock);
if(mgr->curId==0xFFFFFFFE)
tmp = mgr->curId = 1;
else
tmp = ++mgr->curId;
rvMutexUnlock(&mgr->lock);
return tmp;
}
RvMegacoTerm * rvMegacoTermMgrFindInNullContext(RvMegacoTermMgr * mgr,const char * id)
{
RvMegacoTerm* term;
rvMutexLock(&mgr->lock);
term = rvMegacoContextGetTermInNull(&mgr->nullContext,id);
rvMutexUnlock(&mgr->lock);
return term;
}
RvBool rvMegacoTermMgrForEachInNullContext(RvMegacoTermMgr * mgr,RvGraphNodeFunc f, void *data) {
RvBool retval;
rvMutexLock(&mgr->lock);
retval = rvGraphForEachNode(&mgr->nullContext.topology,f,data);
rvMutexUnlock(&mgr->lock);
return retval;
}
RvBool rvMegacoTermMgrForEachInActiveContexts(RvMegacoTermMgr * mgr,RvGraphNodeFunc f, void *data) {
RvBool retval;
RvMegacoContext * context = NULL;
RvHashIter(RvUint32,RvMegacoContextPtr) i, nextIter, end;
rvMutexLock(&mgr->lock);
end = rvHashEnd(RvUint32,RvMegacoContextPtr)(&mgr->contextTable);
for(i=rvHashBegin(RvUint32,RvMegacoContextPtr)(&mgr->contextTable);
rvHashIterEqual(RvUint32,RvMegacoContextPtr)(&i,&end)!=rvTrue;
i=nextIter) {
/* Get the next because the context may be remove from the list during processing */
nextIter =rvHashIterNext(RvUint32,RvMegacoContextPtr)(i);
context = *rvHashIterData(RvUint32,RvMegacoContextPtr)(i);
if( (retval=rvGraphForEachNode(&context->topology,f,data))!=rvFalse ) {
break;
}
}
rvMutexUnlock(&mgr->lock);
return retval;
}
void rvMegacoTermMgrRemoveFromNullContext(RvMegacoTermMgr * mgr,RvMegacoTerm * term) {
rvMegacoTermOutNullCtxt(term);
}
void rvMegacoTermMgrAddToNullContext(RvMegacoTermMgr * mgr,RvMegacoTerm * term) {
rvMutexLock(&mgr->lock);
rvMegacoTermRestoreDefaultState(term);
rvMegacoTermInNullCtxt(term);
rvMegacoTermSetContext(term,&mgr->nullContext);
rvMutexUnlock(&mgr->lock);
}
RvMegacoContext * rvMegacoTermMgrFindContext(RvMegacoTermMgr * mgr,unsigned int id) {
RvMegacoContext ** contextPtr2;
rvMutexLock(&mgr->lock);
contextPtr2 = rvHashFind(RvUint32,RvMegacoContextPtr)(&mgr->contextTable,&id);
rvMutexUnlock(&mgr->lock);
if(contextPtr2!=NULL)
return *contextPtr2;
else
return NULL;
}
RvMegacoTerm * rvMegacoTermMgrFindInActiveContexts(RvMegacoTermMgr * mgr,const char * id) {
RvMegacoTerm * term = NULL;
RvHashIter(RvUint32,RvMegacoContextPtr) i, nextIter, end;
RvMegacoContext* context;
rvMutexLock(&mgr->lock);
end = rvHashEnd(RvUint32,RvMegacoContextPtr)(&mgr->contextTable);
for(i=rvHashBegin(RvUint32,RvMegacoContextPtr)(&mgr->contextTable);
rvHashIterEqual(RvUint32,RvMegacoContextPtr)(&i,&end)!=rvTrue;
i=nextIter) {
nextIter =rvHashIterNext(RvUint32,RvMegacoContextPtr)(i);
context = *rvHashIterData(RvUint32,RvMegacoContextPtr)(i);
term = rvMegacoContextGetTerm(context,id);
if(term != NULL)
break;
}
rvMutexUnlock(&mgr->lock);
return term;
}
RvMegacoTerm * findInAllContexts(RvMegacoTermMgr * mgr,const char * id) {
RvMegacoTerm * term = NULL;
rvMutexLock(&mgr->lock);
if((term=rvMegacoTermMgrFindInActiveContexts(mgr,id))!=NULL)
{
rvMutexUnlock(&mgr->lock);
return term;
}
/* All the physical terminations are in the null context */
if( (term=rvMegacoTermMgrFindInNullContext(mgr,id))!=NULL )
{
rvMutexUnlock(&mgr->lock);
return term;
}
/* Maybe there is an ephemeral termination left here? */
if( (term=rvMegacoContextGetTerm(&mgr->ephContext,id))!=NULL )
{
rvMutexUnlock(&mgr->lock);
return term;
}
rvMutexUnlock(&mgr->lock);
return term;
}
RvMegacoContext * rvMegacoTermMgrGetNullContext(RvMegacoTermMgr * mgr)
{
RvMegacoContext* rval;
rvMutexLock(&mgr->lock);
rval = &mgr->nullContext;
rvMutexUnlock(&mgr->lock);
return rval;
}
RvMegacoContext * rvMegacoTermMgrCreateContext(RvMegacoTermMgr * mgr) {
RvMegacoContext * context;
RvUint32 id;
rvMutexLock(&mgr->lock);
/* Check if one more context can be created */
if(rvHashSize(&mgr->contextTable)==rvMegacoTermMgrGetMaxContexts(mgr))
return NULL;
context = rvAllocAllocate(mgr->alloc,sizeof(RvMegacoContext));
rvMegacoContextConstruct(context,newContextId(mgr),mgr,mgr->alloc);
id = rvMegacoContextGetId(context);
rvHashInsertUnique(RvUint32,RvMegacoContextPtr)(&mgr->contextTable,&id,&context);
rvMdmTermMgrContextCreated_(mgr->mdmTermMgr,context);
rvMutexUnlock(&mgr->lock);
return context;
}
void rvMegacoTermMgrDeleteContext(RvMegacoTermMgr * mgr,RvMegacoContext * context) {
RvUint32 id;
rvMutexLock(&mgr->lock);
id = rvMegacoContextGetId(context);
rvHashEraseKey(RvUint32,RvMegacoContextPtr)(&mgr->contextTable,&id);
rvMdmTermMgrContextDeleted_(mgr->mdmTermMgr,context);
rvMegacoContextDestruct(context);
rvAllocDeallocate(mgr->alloc,sizeof(RvMegacoContext),context);
rvMutexUnlock(&mgr->lock);
}
void rvMegacoTermMgrProcessAction(RvMegacoTermMgr * mgr,const RvMegacoAction * action,RvMegacoTransactionReply * transReply) {
RvMegacoContext * context=NULL;
RvHashIter(RvUint32,RvMegacoContextPtr) i, nextIter, end;
const RvMegacoContextId * contextId = rvMegacoActionGetContextId(action);
RvMegacoContextIdType contextType = rvMegacoContextIdGetType(contextId);
/*
TODO : For now the TermMgr can effectively process only one transaction at the time
Do a more intelligent lock so actions in different contexts can be processed concurrently
(at least when context callback is not used ).
Take into account deadlock issues between contexts (MOVE)
Other: no need to lock in functions that are only internal and called
by locked functions...
*/
rvMutexLock(&mgr->lock);
if(contextType!=RV_MEGACOCONTEXTID_ALL) {
/* Find the context by id or create one if needed */
if(contextType==RV_MEGACOCONTEXTID_CHOOSE)
context = rvMegacoTermMgrCreateContext(mgr);
else if(contextType==RV_MEGACOCONTEXTID_NORMAL)
context = rvMegacoTermMgrFindContext(mgr,rvMegacoContextIdGetId(contextId));
else if(contextType==RV_MEGACOCONTEXTID_NULL)
context = rvMegacoTermMgrGetNullContext(mgr);
if(context==NULL) { /* MEGACO_ERROR: Context not found */
RvMegacoErrorDescriptor error;
if(contextType==RV_MEGACOCONTEXTID_CHOOSE)
rvMegacoErrorDescriptorConstructA(&error,RV_MEGACOERROR_NOTAVAIL_CTXTID,
"No ContextIDs available",mgr->alloc);
else
rvMegacoErrorDescriptorConstructA(&error,RV_MEGACOERROR_UNKNWN_CTXTID,
"The transaction refers to an unknown ContextId",mgr->alloc);
rvMegacoTransactionReplySetError(transReply,&error);
rvMegacoErrorDescriptorDestruct(&error);
rvMutexUnlock(&mgr->lock);
return;
}
rvMegacoContextProcessAction(context,action,transReply,rvFalse);
}
else {
/* For wildcard case,build a different action response for each context */
size_t oldReplies = rvMegacoTransactionReplyGetNumReplies(transReply);
end = rvHashEnd(RvUint32,RvMegacoContextPtr)(&mgr->contextTable);
for(i=rvHashBegin(RvUint32,RvMegacoContextPtr)(&mgr->contextTable);
rvHashIterEqual(RvUint32,RvMegacoContextPtr)(&i,&end)!=rvTrue;
i=nextIter) {
/* Get the next because the context may be remove from the list during processing */
nextIter =rvHashIterNext(RvUint32,RvMegacoContextPtr)(i);
context = *rvHashIterData(RvUint32,RvMegacoContextPtr)(i);
rvMegacoContextProcessAction(context,action,transReply,rvTrue);
}
/* If no replies were added to ALL context, set an error */
if( rvMegacoTransactionReplyGetNumReplies(transReply) == oldReplies )
rvMegacoContextSetWildError(transReply,mgr->alloc) ;
}
rvMutexUnlock(&mgr->lock);
}
void processAck(RvMegacoTcb *tcb, void *data, RvTransactionStatus reason)
{
RvMegacoTermMgr* mgr = (RvMegacoTermMgr*)data;
switch(reason)
{
case RVTRANSACTIONSTATUS_SENDREPLY_LLFAIL:
rvMegacoTermMgrCommFailure(mgr);
break;
case RVTRANSACTIONSTATUS_SENDREPLY_TIMEOUT:
break;
case RVTRANSACTIONSTATUS_RCV_REPLYACK:
break;
case RVTRANSACTIONSTATUS_TCB_CLEANUP:
break;
}
}
void rvMegacoTermMgrProcessTransaction(RvMegacoTcb *tcb, const RvMegacoTransaction *transaction, void *data)
{
RvMegacoTermMgr* mgr = (RvMegacoTermMgr*)data;
size_t numActions,i;
RvMegacoTransactionReply transReply,*transReplyPtr;
transReplyPtr = &transReply;
rvMegacoTransactionReplyConstructA(transReplyPtr,transaction,mgr->alloc);
/*mgr->msgCounter++; */ /* for future use: indicates a message arrived so we can turn off recovery mechanism */
/* can't process transaction if mg is not registered */
if ( !(mgr->state == RV_MEGACOTERMMGRSTATE_REGISTERED) ) {
RvMegacoErrorDescriptor error;
rvMegacoErrorDescriptorConstructA(&error,RV_MEGACOERROR_CMD_NORESTART,
"Command Received before Restart Response",mgr->alloc);
rvMegacoTransactionReplySetError(transReplyPtr,&error);
rvMegacoErrorDescriptorDestruct(&error);
}
else {
numActions = rvMegacoTransactionGetNumActions(transaction);
for(i=0;i<numActions;i++) {
rvMegacoTermMgrProcessAction(mgr,rvMegacoTransactionGetAction(transaction,i),transReplyPtr);
}
}
#ifndef RV_MEGACOTERMMGR_TESTSTACKON
rvMegacoTcbSendReply(tcb, transReplyPtr, processAck, data);
#else
rvMegacoTestStackSendReply(mgr,transReplyPtr);
#endif
rvMegacoTransactionReplyDestruct(transReplyPtr);
return;
}
void rvMegacoTermMgrSendTermServiceChangeUp(RvMegacoTermMgr * mgr,struct RvMegacoTerm_ * term,RvMegacoServiceChangeDescriptor * sc)
{
RvMegacoCommand command;
RvMegacoContextId contextId;
RvMegacoTransaction transaction;
RvMegacoAction action;
RvMegacoTerminationId tId;
rvMegacoTerminationIdConstruct(&tId, term->terminationId);
rvMegacoServiceChangeCommandConstruct(&command, &tId, sc);
rvMegacoContextIdConstructSpecial(&contextId, RV_MEGACOCONTEXTID_NULL);
/* Construct action */
rvMegacoActionConstruct(&action, &contextId);
/* Add command to action */
rvMegacoActionAddCommand(&action, &command);
/* Construct transaction */
rvMegacoTransactionConstruct(&transaction);
/* Add action to transaction */
rvMegacoTransactionAddAction(&transaction, &action);
/* Send transaction */
#ifndef RV_MEGACOTERMMGR_TESTSTACKON
rvMegacoEntitySendRequest(&mgr->mgcEntity, &transaction, rvMegacoTermMgrProcReply, mgr);
#else
rvMegacoTestStackSendRequest(mgr,&transaction);
#endif
/* Destroy objects */
rvMegacoTerminationIdDestruct(&tId);
rvMegacoTransactionDestruct(&transaction);
rvMegacoActionDestruct(&action);
rvMegacoContextIdDestruct(&contextId);
rvMegacoServiceChangeCommandDestruct(&command);
}
/*---------------------------------------------------------------------------*/
/* Callbacks to the MdmTermMgr - are internal functions */
/*---------------------------------------------------------------------------*/
static RvBool sendServiceChangeToAddress(RvMegacoTermMgr * mgr,RvMegacoTerm * term,
const RvMegacoEntityAddress* remoteAddr,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -