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

📄 rvmegacotermevent.c

📁 h.248协议源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************
Filename   : rvmegacotermevent.c
Description: Event-processing MEGACO Termination Functions
******************************************************************************
                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$
******************************************************************************/
#include "rvmutex.h"
#include "rvstr.h"
#include "rvmegacotermmgr.h"
#include "rvmegacocontext.h"
#include "rvmegacoterm.h"
#include "rvmdm.h"
#include "rvmegacotermevent.h"
#include "rvmegacotermdigitmap.h"
#include "rvmegacoerrors.h"

#define rvNeverEqual(a, b) ((a)==(b))
#define RvMegacoObservedEventConstructCopy rvMegacoObservedEventConstructCopy
#define RvMegacoObservedEventDestruct rvMegacoObservedEventDestruct
#define RvMegacoObservedEventEqual rvNeverEqual

rvDefineList(RvMegacoObservedEvent)
rvDefineListAllocBack(RvMegacoObservedEvent)

static RvTimeStamp nullTime = {0,0,0,0,0,0};

static void buildObservedEvent2(RvMegacoTerm * x,RvMegacoObservedEvent * obsEvent,
								const RvMegacoPackageItem *name,unsigned int streamId,
								const RvMegacoParameterList * args,RvAlloc * alloc) {
	RvTimeStamp timestamp;	

	/* If processing a buffered event,use the original time */
	if(x->bufferedTime!=NULL) 
		rvMegacoObservedEventConstructA(obsEvent,name,x->bufferedTime,alloc);
	else { /* Set current time */
		rvTimeStampConstructCurrentTime(&timestamp);
		rvMegacoObservedEventConstructA(obsEvent,name,&timestamp,alloc);
	}	

	if(streamId)
		rvMegacoObservedEventSetStreamId(obsEvent,streamId);
	if(args!=NULL) {
		rvMegacoParameterListCopy((RvMegacoParameterList*)rvMegacoObservedEventGetParameterList(obsEvent),args);
	}
}


static void buildObservedEvent(RvMegacoTerm * x,RvMegacoObservedEvent * obsEvent,
							   const RvMegacoPackageItem *name,RvMdmMediaStream * media,
							   const RvMegacoParameterList * args) {
	unsigned int streamId = rvMegacoMediaStreamGetId((RvMegacoMediaStream*)(media));
	
	buildObservedEvent2(x,obsEvent,name,streamId,args,x->alloc);
}

/*Generate an event completion for digitmaps for the dd package */
void  rvMegacoDigitMapBuildDDEvComplete(RvMegacoParameterList *parameters,
										const char * digitString,
										RvMegacoDigitMapMatchType matchType,
										void* userData) {
	RvAlloc * alloc = (RvAlloc*)userData;

	/* If the digitString is empty, don't encode the parameter.
	   In the package, encoding an empty string is required,
	   but the syntax doesn't support it */
	if(strlen(digitString)) {

		RvString quotedDigits;
		RvMegacoParameterValue value;
		
		/* Build the parameter value (digit string) */
		rvStringConstruct(&quotedDigits,"\"",alloc);
		rvStringConcatenate(&quotedDigits,digitString);
		rvStringConcatenate(&quotedDigits,"\"");
		rvMegacoParameterValueConstructA(&value,rvStringGetData(&quotedDigits),alloc);

		/* Add to digit string parameter list */
		rvMegacoParameterListSet2(parameters,"ds",&value);

		rvMegacoParameterValueDestruct(&value);
		rvStringDestruct(&quotedDigits);
	}

	/* Add Termination method */
	if(matchType!=RV_MEGACODIGITMAP_NOMATCH)
	{
		RvMegacoParameterValue value;

		if(matchType==RV_MEGACODIGITMAP_UNAMBIGUOUSMATCH)
			rvMegacoParameterValueConstructA(&value,"UM",alloc);
		if(matchType==RV_MEGACODIGITMAP_PARTIALMATCH)
			rvMegacoParameterValueConstructA(&value,"PM",alloc);
		if(matchType==RV_MEGACODIGITMAP_FULLMATCH)
			rvMegacoParameterValueConstructA(&value,"FM",alloc);

		/* Add termination method to parameter list */
		rvMegacoParameterListSet2(parameters,"Meth",&value);

		/* Destruct local objects */
		rvMegacoParameterValueDestruct(&value);
	}
}

/* Return mapped character or RV_MDMTERMEVENT_NOTFOUND if failed to translate */
char rvMegacoDigitMapTranslateDDEvent(const char * eventName, const RvMegacoParameterList* args) {
/*
+------+--------------+
| DTMF | Event Symbol |
+------+--------------+
| d0   | "0"          |
| d1   | "1"          |
| d2   | "2"          |
| d3   | "3"          |
| d4   | "4"          |
| d5   | "5"          |
| d6   | "6"          |
| d7   | "7"          |
| d8   | "8"          |
| d9   | "9"          |
| da   | "A" or "a"   |
| db   | "B" or "b"   |
| dc   | "C" or "c"   |
| dd   | "D" or "d"   |
| ds   | "E" or "e"   |
| do   | "F" or "f"   |
+------+--------------+
*/
	if(strlen(eventName)!=2)
		return RV_MDMTERMEVENT_NOTFOUND;

	if(eventName[1]>='0' && eventName[1]<='9')
		return eventName[1];
	if(eventName[1]>='a' && eventName[1]<='d')
		return eventName[1];
	if(eventName[1]=='s')
		return 'e';
	if(eventName[1]=='o')
		return 'f';

	return RV_MDMTERMEVENT_NOTFOUND;
}


/* Add a new event to the observed events list */
static void accumulateEvent(RvMegacoTerm * x,const RvMegacoPackageItem *name,RvMdmMediaStream * media,
							const RvMegacoParameterList * args) {
	
	/* Add event to observed event descriptor */
	RvMegacoObservedEvent event;
	buildObservedEvent(x,&event,name,media,args);
	rvMegacoObservedEventsDescriptorAddEvent(&x->obsEventsDescr,&event);
	rvMegacoObservedEventDestruct(&event);
}

static const RvMegacoRequestedEvent* eventInEventDescr(RvMegacoTerm * x,const RvMegacoPackageItem *name,RvMdmMediaStream * media) {
	const RvMegacoRequestedEvent * event;
	const RvMegacoPackageItem * evName;
	size_t i,max = rvMegacoEventsDescriptorGetNumEvents(&x->eventsDescr);

	for(i=0;i<max;i++) {
		event = rvMegacoEventsDescriptorGetEvent(&x->eventsDescr,i);
		evName = rvMegacoRequestedEventGetName(event);

		/* The media streams should match */
		if(!rvMegacoMediaStreamMatchId((RvMegacoMediaStream*)media,
									   rvMegacoRequestedEventGetStreamId(event)))
			return NULL;

		if(rvMegacoPackageItemEqual(evName,name)==rvTrue) 
			return event;
		/* Wilcard case: all events in the package */
		if((rvStrIcmp(rvMegacoPackageItemGetPackage(evName),rvMegacoPackageItemGetPackage(name))==0)
			&& 
		   (rvStrIcmp(rvMegacoPackageItemGetItem(evName),"*")==0) )
		   return event;
	}	

	return NULL;
}

/* Send notify event */
static void sendNotify(RvMegacoTerm * x) {
	/* Notify the observed event descriptor */
	rvMegacoContextSendNotify(x->context,rvMegacoTermGetId(x),&x->obsEventsDescr);
	/* Clear the observed events */
	rvMegacoObservedEventsDescriptorClear(&x->obsEventsDescr);
}

static void processEmbFields(RvMegacoTerm * x,const RvMegacoRequestedEvent * requestedEvent) {
	RvMegacoEventsDescriptor tmpEventsDescr;

	/* Process the requested event */
	rvMegacoTermProcessSignals(x,rvMegacoRequestedEventGetEmbSignals(requestedEvent),NULL);
	/* temp is necessary because request points into old requestedEvents! */
	rvMegacoEventsDescriptorConstructCopy(&tmpEventsDescr,rvMegacoRequestedEventGetEmbEvents(requestedEvent),x->alloc);
	rvMegacoTermProcessEvents(x,&tmpEventsDescr,NULL);

	/* Destruct local objects */
	rvMegacoEventsDescriptorDestruct(&tmpEventsDescr);
}

void rvMegacoTermSetLockStep(RvMegacoTerm * x,RvBool newMode) {
	if(newMode==rvFalse && x->lockStep==rvTrue) {
		x->bufferActive = rvTrue;	
		rvListClear(RvMegacoObservedEvent)(&x->eventBuffer);
	}
	x->lockStep = newMode;
}

static const RvMegacoRequestedEvent * processRequestedEvent(RvMegacoTerm * x,const RvMegacoPackageItem *name,RvMdmMediaStream * media,
							const RvMegacoParameterList * args) {

	const RvMegacoRequestedEvent * requestedEvent;

	if( (requestedEvent=eventInEventDescr(x,name,media))==NULL)
		return NULL;

	/* Activate event buffering for next event */
	if(x->lockStep==rvTrue) 
		x->bufferActive = rvTrue;	

	/* Stop signals if required */
	if(!rvMegacoRequestedEventGetKeepActiveFlag(requestedEvent)) 
		rvMegacoTermEventStopSignals(x);

	/* Add event to observed event descriptor */
	accumulateEvent(x,name,media,args);

	return requestedEvent;
}

/* Process and send notify */
static RvBool processNotifyEvent(RvMegacoTerm * x,const RvMegacoPackageItem *name,
							   RvMdmMediaStream * media,
							   const RvMegacoParameterList * args) {
	const RvMegacoRequestedEvent * requestedEvent;

	/* Add required events to the observed event descriptor */
	if(!(requestedEvent=processRequestedEvent(x,name,media,args)))
		return rvFalse;

	/* Notify the observed event descriptor */
	sendNotify(x);

	processEmbFields(x,requestedEvent);

	return rvTrue;
}

static RvBool processAccumulateEvent(RvMegacoTerm * x,const RvMegacoPackageItem *name,
							   RvMdmMediaStream * media,
							   const RvMegacoParameterList * args) {
	const RvMegacoRequestedEvent * requestedEvent;

	/* Add required events to the observed event descriptor */
	if(!(requestedEvent=processRequestedEvent(x,name,media,args)))
		return rvFalse;

	processEmbFields(x,requestedEvent);

	return rvTrue;
}

static RvBool eventInBufferDescr(RvMegacoTerm * x,const RvMegacoPackageItem *name,RvMdmMediaStream* media) {
	const RvMegacoEvent * event;
	const RvMegacoPackageItem * evName;
	size_t i,max = rvMegacoEventBufferDescriptorGetNumEvents(&x->eventBufferDescr);

	for(i=0;i<max;i++) {
		event = rvMegacoEventBufferDescriptorGetEvent(&x->eventBufferDescr,i);
		evName = rvMegacoEventGetName(event);

		/* The media streams should match */
		if(!rvMegacoMediaStreamMatchId((RvMegacoMediaStream*)media,
									   rvMegacoEventGetStreamId(event)))
			return rvFalse;

		if(rvMegacoPackageItemEqual(evName,name)==rvTrue)
			return rvTrue;
	}	
	return rvFalse;
}

static void addEventToBuffer(RvMegacoTerm * x,const RvMegacoPackageItem *name,
							 RvMdmMediaStream * media,const RvMegacoParameterList * args) {

	if(eventInBufferDescr(x,name,media)) {
		/* Construct observed event and add to linked list */
		RvMegacoObservedEvent * obsEvent = rvListAllocBack(RvMegacoObservedEvent)(&x->eventBuffer);
		buildObservedEvent(x,obsEvent,name,media,args);
	}
}

static RvBool isInDigitMapPkg(RvMegacoTerm * x,const RvMegacoPackageItem *name) {
	return !rvStrIcmp(rvMegacoPackageItemGetPackage(&x->digitMapEC->pkgItem),
					  rvMegacoPackageItemGetPackage(name));
}

void rvMegTermEventPushAuditDMEventCompletion(RvMegacoTerm * x) {
	RvMegacoParameterList parameters;

	/* Build the digitmap parameters */
	rvMegacoParameterListConstructA(&parameters,x->alloc);
	x->digitMapEC->evCompleteF(&parameters,rvStringGetData(&x->dialString),
							   RV_MEGACODIGITMAP_NOMATCH,x->digitMapEC->userData);
							   
	/* Add event to the observed events descriptor */
	accumulateEvent(x,&x->digitMapEC->pkgItem,NULL,&parameters);

	/* Destruct local objects */
	rvMegacoParameterListDestruct(&parameters);
}

void rvMegTermEventPopAuditDMEventCompletion(RvMegacoTerm * x) {
	RvVector(RvMegacoObservedEvent)* events;
	events = &x->obsEventsDescr.events;
	rvVectorPopBack(RvMegacoObservedEvent)(events);
}

static void generateDMEventCompletion(RvMegacoTerm * x,RvMdmMediaStream * media) {
	RvMegacoParameterList parameters;

	/* Disable digitmap and timer */
	rvMegacoTermDeactivateDigitMap(x);

	/* Build the digitmap parameters */
	rvMegacoParameterListConstructA(&parameters,x->alloc);
	x->digitMapEC->evCompleteF(&parameters,rvStringGetData(&x->dialString),
							  x->digitMapStat,x->digitMapEC->userData);
							   
	/* Add event to the observed events descriptor */
	accumulateEvent(x,&x->digitMapEC->pkgItem,media,&parameters);

	/* Reset the dial string and make digit map inactive */
	rvStringResize(&x->dialString,0);

	/* Destruct local objects */
	rvMegacoParameterListDestruct(&parameters);
}

/* This will generate two notifies because the ec event 
   can have embedded parameters changing the processing of the new event */
static void processDigitMapUnmatch(RvMegacoTerm * x,const RvMegacoPackageItem *name,
								 RvMdmMediaStream * media,const RvMegacoParameterList * args) {
	generateDMEventCompletion(x,media);
	sendNotify(x);
	processEmbFields(x,x->digitMapReqEvent);

	/* Process last event */
	/* Send a new notify if the event has to be 
	   specifically detected */
	processNotifyEvent(x,name,media,args);
}

/* 
Order of processing:
If an event causes
the digitmap to stop (no possible match).
1. First report the digitmap completion (fail status)
2. Then report the event

If is in the package and matches but reporting is explicitly required
(i.e. if using wildcard in the package)
2. First report the event
1. Then report the digitmap event completion (if is done).

Timer events are never reported!
*/
static RvBool processDigitMapEvent(RvMegacoTerm * x,const RvMegacoPackageItem *name,
								   RvMdmMediaStream * media,const RvMegacoParameterList * args) {
	unsigned int timerDuration;
	char newDigit;
	RvMegacoDigitMapMatchType lastStat = x->digitMapStat;

	newDigit = x->digitMapEC->translateF(rvMegacoPackageItemGetItem(name), args);
	/* Treat this as a nonmatch event */
	if (newDigit == RV_MDMTERMEVENT_NOTFOUND) {
		/* The reported match state is the last match */
		x->digitMapStat=lastStat;
		processDigitMapUnmatch(x,name,media,args);
	}
	else if (newDigit != RV_MDMTERMEVENT_IGNORE) {

		rvStringPushBack(&x->dialString,newDigit);
		x->digitMapStat = rvMegacoDigitMapMatch(&x->digitMap,rvStringGetData(&x->dialString),&timerDuration);

		if(x->digitMapStat==RV_MEGACODIGITMAP_NOMATCH) {
			/* Substract last event and generate a digitmap completion event */
			rvStringResize(&x->dialString,rvStringGetSize(&x->dialString)-1);
			/* The reported match state is the last match */
			x->digitMapStat=lastStat;
			processDigitMapUnmatch(x,name,media,args);

⌨️ 快捷键说明

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