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

📄 rvmegacotrans.c

📁 h.248协议源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#if (0)
******************************************************************************
Filename    :rvmegacotrans.c
Description :This file contains the structures used for the Transaction 
	Manager Control Blocks
******************************************************************************
                Copyright (c) 2000 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:$
$Author:L.Amberger$
******************************************************************************
#endif

#include "rvmegacotrans.h"
#include "rvmegacoentity.h"
#include "rvmegacostack.h"
#include "rvmegacoencode.h"
#include "rvmegacoerrors.h"
#include "rvlog.h"

#define RV_MEGACOTM_DFLT_TMR_VAL    1000
#define RV_MEGACOTM_SHORTINACTIVE_TO 1
#define RV_MEGACOTM_INACTIVE_TO     30000
#define RV_MEGACOTM_PROCESSING_TO   1000
#define RV_MEGACOTM_RESPONDED_TO    30000
#define RV_MEGACOTM_CMD_TO          1000

static void rvTransMgrTimerProc(RvTimer *timer, void *data);
static void rvMegacoTcbStopNStartTimer(RvMegacoTcbPtr t, int tValue);

RvMegacoTcb *rvMegacoTcbConstruct(RvMegacoTcb *tcb,RvMegacoStack *stack, RvMegacoEntity *localEntity,RvMegacoEntity *remoteEntity, RvBool useLocal, const RvMegacoTransaction *trans)
{
	rvLogEnter(&rvLog, "rvMegacoTcbConstruct");
	rvMutexConstruct(&tcb->lock);
	tcb->useLocal = useLocal;
	tcb->tId = rvMegacoTransactionGetId(trans);
	tcb->state = RV_MEGACOTCB_STATE_IDLE;
	rvTimerConstruct(&tcb->Timer[0], RV_MEGACOTM_DFLT_TMR_VAL, rvTransMgrTimerProc, tcb);
	rvTimerConstruct(&tcb->Timer[1], RV_MEGACOTM_DFLT_TMR_VAL, rvTransMgrTimerProc, tcb);
	tcb->CurrentTimer = 0;
	rvStrStreamConstruct(&tcb->encodedTransaction, RV_MEGACOTCB_ENCODEBUFINITSIZE, stack->sendBufAlloc);
	tcb->stack = stack;
	tcb->localEntity = localEntity;
	tcb->destEntity = remoteEntity;
	tcb->firstSend = rvTrue;
	tcb->msgFreed= rvFalse;
	tcb->replyReceived = rvFalse;
	tcb->data = NULL;
	tcb->SentPending = rvFalse;
	tcb->EntityDestructed = rvFalse;
	rvMutexLock(&stack->mutex);
	stack->totalTransactions++;
	stack->curTransactions++;
	rvMutexUnlock(&stack->mutex);
	rvLogLeave(&rvLog, "rvMegacoTcbConstruct");
	return tcb;
}
/* Note: This function is ONLY called by the entity destruct function to remove TCBs */
/* IT MARKS THE ENTITY AS HAVING BEEN DESTRUCTED */
void rvMegacoTcbMarkForDestruct(RvMegacoTcb *tcbPtr,RvTransactionStatus reason)
{
	rvLogEnter(&rvLog, "rvMegacoTcbMarkForDestruct");
	rvMutexLock(&tcbPtr->lock);

	switch (tcbPtr->state)
		{
		/* If the state is one that indicates this was a command that was received */
		case RV_MEGACOTCB_STATE_RESP_TO_SEND:
		case RV_MEGACOTCB_STATE_RESPONDED:
		case RV_MEGACOTCB_STATE_RESP_SEND_FAIL:
		case RV_MEGACOTCB_STATE_WAITAPPLRESPONSE:
			if (tcbPtr->AckCallBack != NULL)
				tcbPtr->AckCallBack(tcbPtr,tcbPtr->data, reason);
			break;
	/* If the state is one that indicates this was a command that was sent */
		case RV_MEGACOTCB_STATE_CMD_TO_SEND:
		case RV_MEGACOTCB_STATE_CMDSENT:
		case RV_MEGACOTCB_STATE_CMD_SEND_FAIL:
			if(tcbPtr->ReplyCallBack != NULL)
				tcbPtr->ReplyCallBack(tcbPtr,NULL,tcbPtr->data,reason);
			break;
	}
	tcbPtr->EntityDestructed = rvTrue;
	tcbPtr->state = RV_MEGACOTCB_STATE_INACTIVE;
	rvMegacoTcbStopNStartTimer(tcbPtr,RV_MEGACOTM_SHORTINACTIVE_TO);

	rvMutexUnlock(&tcbPtr->lock);
	rvLogLeave(&rvLog, "rvMegacoTcbMarkForDestruct");
}

void rvMegacoTcbDestruct(RvMegacoTcb *tcb)
{
	rvLogEnter(&rvLog, "rvMegacoTcbDestruct");
	rvMutexLock(&tcb->stack->mutex);
	tcb->stack->curTransactions--;
	rvMutexUnlock(&tcb->stack->mutex);
	rvMutexDestruct(&tcb->lock);
	rvTimerDestruct(&tcb->Timer[0]);
	rvTimerDestruct(&tcb->Timer[1]);
	if(tcb->msgFreed != rvTrue)
		rvStrStreamDestruct(&tcb->encodedTransaction);
	rvLogLeave(&rvLog, "rvMegacoTcbDestruct");
}

static void rvMegacoTcbStopCurrentTimer(RvMegacoTcbPtr t)
{
	rvLogEnter(&rvLog, "rvMegacoTcbStopCurrentTimer");

	rvTimerStop(&t->Timer[t->CurrentTimer]);
	if(t->CurrentTimer == 0)
		t->CurrentTimer = 1;
	else
		t->CurrentTimer = 0;

	rvLogLeave(&rvLog, "rvMegacoTcbStopCurrentTimer");
}

static void rvMegacoTcbStopNStartTimer(RvMegacoTcbPtr t, int tValue)
{
	rvLogEnter(&rvLog, "rvMegacoTcbStopNStartTimer");

	rvTimerStop(&t->Timer[t->CurrentTimer]);
	if(t->CurrentTimer == 0)
		t->CurrentTimer = 1;
	else
		t->CurrentTimer = 0;
	rvTimerReset(&t->Timer[t->CurrentTimer],tValue);

	rvLogLeave(&rvLog, "rvMegacoTcbStopNStartTimer");
}
			
void rvTransMgrTimerProc(RvTimer *timer,void * data)
{	
	RvHrtime totalTimeInNs;
	RvHrtime currTime;
	RvMegacoTcb *tcbPtr = (RvMegacoTcb *)data;
	RvMegacoStack *stack = tcbPtr->stack;
	RvBool doUnlock = rvTrue;
	RvMegacoEntity *destEntity;

	rvLogEnter(&rvLog, "rvTransMgrTimerProc");

	if (tcbPtr->EntityDestructed == rvFalse)
		rvLogStr2(&rvLog, "tcb timer exp", rvMegacoEntityAddressGetAddress(&tcbPtr->destEntity->mId));

	if (timer != &tcbPtr->Timer[tcbPtr->CurrentTimer])
		return;

	rvMutexLock(&tcbPtr->lock);
	if (tcbPtr->EntityDestructed == rvTrue)		/* If the entity was destructed then there's nothing else to do */
		{
		rvMutexUnlock(&tcbPtr->lock);
		rvMegacoTcbDestruct(tcbPtr);
		rvAllocDeallocate(stack->tcbAlloc, sizeof(RvMegacoTcb), tcbPtr);
		return;
		}

	/* Get the entity */
	destEntity = rvMegacoTcbGetRemoteEntity(tcbPtr);
	rvMutexUnlock(&tcbPtr->lock);

	/* Must Lock the entity first */
	
	rvMutexLock(&destEntity->mutex);
	rvMutexLock(&tcbPtr->lock);


	if (rvTimerGetId(timer) != rvTimerGetId(&tcbPtr->Timer[tcbPtr->CurrentTimer]))
		{	/* Ignore this timer it is not the current one! */
		rvLogInt2(&rvLog, "This is not the Current TCB Timer", rvTimerGetId(timer), 10);
		rvMutexUnlock(&tcbPtr->lock);
		rvMutexUnlock(&destEntity->mutex);
		rvLogLeave(&rvLog, "rvTransMgrTimerProc");
		return;
		}

	switch (tcbPtr->state)
		{
		case RV_MEGACOTCB_STATE_IDLE:
			/* ignore this */
			break;
		case RV_MEGACOTCB_STATE_RESP_TO_SEND:
			/* This shouldn't happen - ignore it */
			break;
		case RV_MEGACOTCB_STATE_RESPONDED:
			/* Mark the block for release */
			tcbPtr->state = RV_MEGACOTCB_STATE_INACTIVE;
			rvTimerReset(timer,RV_MEGACOTM_INACTIVE_TO);
			if (tcbPtr->AckCallBack != NULL)
				{
				rvMutexUnlock(&tcbPtr->lock);
				rvMutexUnlock(&destEntity->mutex);
				doUnlock = rvFalse;
				tcbPtr->AckCallBack(tcbPtr,tcbPtr->data, RVTRANSACTIONSTATUS_SENDREPLY_TIMEOUT);
				}
			break;

		case RV_MEGACOTCB_STATE_RESP_SEND_FAIL:
			tcbPtr->state = RV_MEGACOTCB_STATE_INACTIVE;
			rvTimerReset(timer,RV_MEGACOTM_INACTIVE_TO);
			if (tcbPtr->AckCallBack != NULL)
				{
				rvMutexUnlock(&tcbPtr->lock);
				rvMutexUnlock(&destEntity->mutex);
				doUnlock = rvFalse;
				tcbPtr->AckCallBack(tcbPtr,tcbPtr->data, RVTRANSACTIONSTATUS_SENDREPLY_LLFAIL);
				}
			break;

		case RV_MEGACOTCB_STATE_WAITAPPLRESPONSE:	/* The application didn't respond */
			tcbPtr->state = RV_MEGACOTCB_STATE_INACTIVE;
			rvTimerReset(timer,RV_MEGACOTM_INACTIVE_TO);	
			break;
		case RV_MEGACOTCB_STATE_CMD_TO_SEND:
			/* This should never happen since the timer doesn't get set until */
			/* the command is actually sent */
			break;
		case RV_MEGACOTCB_STATE_CMDSENT:
			currTime = rvTimeGetHrtime();
			totalTimeInNs = rvTimeHrSubtract(currTime,tcbPtr->OrigSendTime);
			if (totalTimeInNs < stack->tMax)
				{
				tcbPtr->firstSend = rvFalse;
				tcbPtr->state = RV_MEGACOTCB_STATE_CMD_TO_SEND;
				rvMutexUnlock(&tcbPtr->lock);
				rvMutexUnlock(&destEntity->mutex);
				doUnlock = rvFalse;
				rvMegacoEntitySendListInsert(tcbPtr->destEntity,tcbPtr);
				}
			else
				{/* report an error */
				tcbPtr->state = RV_MEGACOTCB_STATE_INACTIVE;
				rvTimerReset(timer,RV_MEGACOTM_INACTIVE_TO);
				if (tcbPtr->ReplyCallBack != NULL)
					{
					rvMutexUnlock(&tcbPtr->lock);
					rvMutexUnlock(&destEntity->mutex);
					doUnlock = rvFalse;
					tcbPtr->ReplyCallBack(tcbPtr,NULL,tcbPtr->data,RVTRANSACTIONSTATUS_SENDREQ_FAIL );
					}
				}
			break;
		case RV_MEGACOTCB_STATE_CMD_SEND_FAIL:
			tcbPtr->state = RV_MEGACOTCB_STATE_INACTIVE;
			rvTimerReset(timer,RV_MEGACOTM_INACTIVE_TO);
			if (tcbPtr->ReplyCallBack != NULL)
				{
				rvMutexUnlock(&tcbPtr->lock);
				rvMutexUnlock(&destEntity->mutex);
				doUnlock = rvFalse;
				tcbPtr->ReplyCallBack(tcbPtr,NULL,tcbPtr->data, RVTRANSACTIONSTATUS_SENDREQ_LLFAIL );
				}
			break;

		case RV_MEGACOTCB_STATE_INACTIVE:
 			rvMutexUnlock(&tcbPtr->lock);
			rvMutexUnlock(&destEntity->mutex);
			/* release all memory associated with this TCB and then free the TCB */
			if (tcbPtr->EntityDestructed == rvFalse) 
			{
				/* only remove from hash if entity has not been destructed */
				if (tcbPtr->useLocal == rvTrue)
					rvMegacoEntityRemoveTcb(tcbPtr->localEntity, tcbPtr->tId);
				else
					rvMegacoEntityRemoveTcb(tcbPtr->destEntity, tcbPtr->tId); 
			}
			rvMegacoTcbDestruct(tcbPtr);
			rvAllocDeallocate(stack->tcbAlloc, sizeof(RvMegacoTcb), tcbPtr);
			doUnlock = rvFalse;
			break;
		}	
	if( doUnlock == rvTrue)
		{
 		rvMutexUnlock(&tcbPtr->lock);
		rvMutexUnlock(&destEntity->mutex);
		}

	rvLogLeave(&rvLog, "rvTransMgrTimerProc");
}

void rvMegacoTransMgrRecvRequest( RvMegacoEntity *remoteEntity, const RvMegacoTransaction *trans)
{
	RvMegacoTcbPtr tcbPtr;
	RvMegacoErrorDescriptor errorDesc;
	RvMegacoTransactionReply transReply;
	RvBool alreadyUnlocked = rvFalse;
	RvMegacoTransactionId tId = rvMegacoTransactionGetId(trans);
	RvMegacoStack* stack = remoteEntity->stack;
	RvMegacoEntity*	localEntity;

	rvLogEnter(&rvLog, "rvMegacoTransMgrRecvRequest");

	localEntity = rvMegacoEntityGetLocalEntity(remoteEntity);
	/* Find the TCB using the transaction Id */
	rvMutexLock(&localEntity->mutex);
	tcbPtr = rvMegacoEntityFindTcb(remoteEntity, tId); 
	/* Or, add it to the hash table if it's a new transaction */
	if (tcbPtr == NULL)
		{
		tcbPtr = (RvMegacoTcb *)rvAllocAllocate(stack->tcbAlloc, sizeof(RvMegacoTcb));
		rvMegacoTcbConstruct(tcbPtr, stack,localEntity, remoteEntity, rvFalse, trans);
		rvMegacoEntityAddTcb(remoteEntity, tcbPtr);
		}

	rvMutexLock(&tcbPtr->lock);
	rvMutexUnlock(&localEntity->mutex);

	switch (tcbPtr->state)
		{
		case RV_MEGACOTCB_STATE_IDLE:
			tcbPtr->state = RV_MEGACOTCB_STATE_WAITAPPLRESPONSE;
			rvTimerReset(&tcbPtr->Timer[tcbPtr->CurrentTimer],RV_MEGACOTM_PROCESSING_TO);
			/* Invoke application callback */
			rvMutexUnlock(&tcbPtr->lock);
			alreadyUnlocked = rvTrue;
			if (localEntity->u.local.processRequest != NULL)
				localEntity->u.local.processRequest(tcbPtr,trans,localEntity->u.local.processRequestData);
			break;
		case RV_MEGACOTCB_STATE_RESP_TO_SEND:
			/* Trigger the enitity to do a send */
			rvMegacoEntitySendNow(remoteEntity);
			break;
		case RV_MEGACOTCB_STATE_RESPONDED:
			/* resend the response */
			tcbPtr->state = RV_MEGACOTCB_STATE_RESP_TO_SEND;
			rvMegacoEntitySendListInsert(tcbPtr->destEntity,tcbPtr);
			break;
		case RV_MEGACOTCB_STATE_WAITAPPLRESPONSE:
			/* send a provisional response */
			rvMegacoTcbStopCurrentTimer( tcbPtr);
			rvMutexUnlock(&tcbPtr->lock);
			alreadyUnlocked = rvTrue;
			rvMegacoTcbSendPending(tcbPtr,NULL,NULL);
			break;
		case RV_MEGACOTCB_STATE_CMDSENT:/* This is an error - we sent a command with this Id*/
		case RV_MEGACOTCB_STATE_CMD_TO_SEND:/* This is an error - we are about to send a command with this Id*/
			rvMegacoErrorDescriptorConstructA(&errorDesc, RV_MEGACOERROR_BAD_ID, "Incorrect ID", stack->msgAlloc);
			rvMegacoTransactionReplyConstructA(&transReply, trans, stack->msgAlloc);
			rvMegacoTransactionReplySetError(&transReply, &errorDesc);
			rvMegacoTcbStopCurrentTimer( tcbPtr);
			rvMutexUnlock(&tcbPtr->lock);
			alreadyUnlocked = rvTrue;
			rvMegacoTcbSendReply(tcbPtr,&transReply,NULL,NULL);
			rvMegacoErrorDescriptorDestruct(&errorDesc);
			rvMegacoTransactionReplyDestruct(&transReply);
			break;
		case RV_MEGACOTCB_STATE_INACTIVE:/* This transaction is waiting to be released don't respond to it */
			break;
	}
	if (!alreadyUnlocked)

⌨️ 快捷键说明

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