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

📄 rvphonelink.c

📁 h.248协议源码
💻 C
字号:
/******************************************************************************
Filename:    rvphonelink.c
Description: rvphone termination handling
*******************************************************************************
                Copyright (c) 2001 RADVISION
*******************************************************************************
NOTICE:
This document contains information that is proprietary to RADVISION.
No part of this publication may be reproduced in any form whatsoever 
without written prior approval by RADVISION.

RADVISION reserves the right to revise this publication and make changes
without obligation to notify any person of such revisions or changes.
******************************************************************************/

#include "rvphonelink.h"
#include "rvphysterm.h"
#include "rvmegacogateway.h"

typedef struct
{
	RvEppClient *eppClient;
	RvEppClientEndpoint *endpoint;
	RvSocketEngine *engine;
} RvPhoneLink;

static RvPhoneLink *rvPhoneLinkConstruct(RvPhoneLink *x, RvEppClient *ec, RvEppClientEndpoint *ece, RvSocketEngine *engine)
{
	x->eppClient = ec;
	x->endpoint = ece;
	x->engine = engine;
	return x;
}

static void rvPhoneLinkDestruct(RvPhoneLink *x)
{
}

/******************************************************************************/

typedef struct
{
	RvRtpLink rtpLink;
	RvEppConnId connId;
	RvPhoneLink *phoneLink;
} RvPhoneMedia;

static RvPhoneMedia *rvPhoneMediaConstruct(RvPhoneMedia *phoneMedia, RvPhoneLink *phoneLink)
{
	RvEppConnParameters connParams;

	rvRtpLinkConstruct(&phoneMedia->rtpLink, phoneLink->engine);

	rvEppConnParametersConstruct(&connParams);
	rvEppConnParametersSetMode(&connParams, RV_EPPCONNMODE_SENDRECV);
	rvEppConnParametersSetCodec(&connParams, 0);
	rvEppConnParametersSetRate(&connParams, 8000);
	rvEppConnParametersSetIp(&connParams, rvRtpLinkGetLocalIpAddr());
	rvEppConnParametersSetPort(&connParams, rvRtpLinkGetLocalPort(&phoneMedia->rtpLink));
	phoneMedia->connId = rvEppClientOpen(phoneLink->eppClient, phoneLink->endpoint, &connParams);
	rvEppConnParametersDestruct(&connParams);
	
	rvRtpLinkSetRemoteAddress(&phoneMedia->rtpLink,
		rvEppClientEndpointGetIp(phoneLink->endpoint),
		rvEppClientGetPort(phoneLink->eppClient, phoneLink->endpoint, phoneMedia->connId));

	phoneMedia->phoneLink = phoneLink;

	return phoneMedia;
}

static void rvPhoneMediaDestruct(RvPhoneMedia *phoneMedia)
{
	RvPhoneLink *phoneLink = phoneMedia->phoneLink;

	rvRtpLinkDestruct(&phoneMedia->rtpLink);
	rvEppClientClose(phoneLink->eppClient, phoneLink->endpoint, phoneMedia->connId);
}

/******************************************************************************/

static void rvPhoneMgrOnRegister(RvEppClient *ec, RvEppClientEndpoint *ece, void *data)
{
	RvPhoneMgr *phoneMgr = (RvPhoneMgr *)data;
	RvMegacoGateway* gw = rvMdmTermMgrGetUserData(phoneMgr->termMgr);
	RvMdmTermDefaultProperties termProperties;
	RvMdmServiceChange sc;
	RvMdmTerm *termination;
	RvPhoneLink *phoneLink;
	int size;

	rvMdmTermDefaultPropertiesConstruct(&termProperties);
	rvMdmServiceChangeConstruct(&sc);
	rvMdmServiceChangeSetMethod(&sc, RV_MDMSERVICECHANGEMETHOD_RESTART);
	rvMdmServiceChangeSetReason(&sc, RV_MDMSERVICECHANGEREASON_SERVICERESTORED);

	termination = rvMdmTermMgrRegisterPhysicalTermination(phoneMgr->termMgr,
		phoneMgr->phoneClass, rvEppClientEndpointGetName(ece), &termProperties, &sc);

	/*send service change only after the first termination registers */
	if ((size = rvPtrListSize(&gw->phoneMgr.eppClient.endpoints)) == 1) 
		rvMegacoGatewayStart(gw);

	phoneLink = (RvPhoneLink *)rvAllocAllocate(&rvDefaultAlloc, sizeof(RvPhoneLink));
	rvPhoneLinkConstruct(phoneLink, ec, ece, phoneMgr->engine);

	rvMdmTermSetUserData(termination, phoneLink);
	rvEppClientEndpointSetUserData(ece, termination);
	
	rvMdmServiceChangeDestruct(&sc);
	rvMdmTermDefaultPropertiesDestruct(&termProperties);
}

static void rvPhoneMgrOnUnregister(RvEppClient *ec, RvEppClientEndpoint *ece, void *data)
{
	RvPhoneMgr *phoneMgr = (RvPhoneMgr *)data;
	RvMdmTerm *termination = (RvMdmTerm *)rvEppClientEndpointGetUserData(ece);
	RvPhoneLink *phoneLink = (RvPhoneLink *)rvMdmTermGetUserData(termination);
	RvMdmServiceChange sc;

	rvMdmServiceChangeConstruct(&sc);
	rvMdmServiceChangeSetMethod(&sc, RV_MDMSERVICECHANGEMETHOD_FORCED);
	rvMdmServiceChangeSetReason(&sc, RV_MDMSERVICECHANGEREASON_TERMOUTOFSVC);
	
	rvMdmTermMgrUnregisterTermination(phoneMgr->termMgr, termination, &sc);
	rvPhoneLinkDestruct(phoneLink);
	rvAllocDeallocate(&rvDefaultAlloc, sizeof(RvPhoneLink), phoneLink);

	rvMdmServiceChangeDestruct(&sc);
}

static void rvPhoneMgrOnEvent(RvEppClient *ec, RvEppClientEndpoint *ece, const char *eventName, char *eventParams, void *data)
{
	/* convert EPP event names to MEGACO event names */
	const char *pkg, *id = NULL;
	const char *dtmfDetect = "dd", *analogLine = "al";
	char ddEvent[] = "d?";

	if(!eventName[1] && eventName[0]) /* length of eventName == 1 */
	{
		pkg = dtmfDetect;
		id = ddEvent;
		if(eventName[0] == '*')
			ddEvent[1] = 's';
		else if(eventName[0] == '#')
			ddEvent[1] = 'o';
		else
			ddEvent[1] = eventName[0];		
	}
	else if(!rvStrIcmp(eventName, "hd"))
		pkg = analogLine, id = "of";
	else if(!rvStrIcmp(eventName, "hu"))
		pkg = analogLine, id = "on";
	else if(!rvStrIcmp(eventName, "hf"))
		pkg = analogLine, id = "fl";

	if(id != NULL)
	{
		RvMdmTerm *termination = (RvMdmTerm *)rvEppClientEndpointGetUserData(ece);
		rvMdmTermProcessEvent(termination, pkg, id, NULL, NULL);
	}
}

static const char *getEppSignalName(const RvMdmSignal *signal)
{
	const char *pkg = rvMdmSignalGetPkg(signal);
	const char *id = rvMdmSignalGetId(signal);
	if(!rvStrIcmp(pkg, "cg"))
	{
		if(!rvStrIcmp(id, "bt"))
			return "bz";
		if(!rvStrIcmp(id, "dt"))
			return "dl";
		if(!rvStrIcmp(id, "rt"))
			return "rt";
		if(!rvStrIcmp(id, "wt"))
			return "ro";
	}
	else if(!rvStrIcmp(pkg, "al"))
	{
		if(!rvStrIcmp(id, "ri"))
			return "rg";
	}
	return NULL;
}

static RvBool rvPhoneMgrStartSignal(RvMdmTerm *term, RvMdmSignal *s, OUT RvMdmError *mdmError)
{
	const char *signalName = getEppSignalName(s);
	if(signalName != NULL)
	{
		RvPhoneLink *phoneLink = (RvPhoneLink *)rvMdmTermGetUserData(term);
		rvEppClientStart(phoneLink->eppClient, phoneLink->endpoint, signalName);
	}
	return rvTrue;
}

static RvBool rvPhoneMgrStopSignal(RvMdmTerm *term, RvMdmSignal *s, OUT RvMdmError *mdmError)
{
	const char *signalName = getEppSignalName(s);
	if(signalName != NULL)
	{
		RvPhoneLink *phoneLink = (RvPhoneLink *)rvMdmTermGetUserData(term);
		rvEppClientStop(phoneLink->eppClient, phoneLink->endpoint, signalName);
	}
	return rvTrue;
}

static RvBool rvPhoneMgrCreateMedia(RvMdmTerm *term,
	RvMdmMediaStream *media, RvMdmMediaStreamDescr *streamDescr, RvMdmError *mdmError)
{
	RvPhoneLink *phoneLink = (RvPhoneLink *)rvMdmTermGetUserData(term);
	RvPhoneMedia *phoneMedia = (RvPhoneMedia *)rvAllocAllocate(&rvDefaultAlloc, sizeof(RvPhoneMedia));

	rvPhoneMediaConstruct(phoneMedia, phoneLink);
	rvMdmMediaStreamSetUserData(media, phoneMedia);

	return rvTrue;
}

static RvBool rvPhoneMgrModifyMedia(RvMdmTerm *term,
	RvMdmMediaStream *media, RvMdmMediaStreamDescr *streamDescr, RvMdmError *mediaError)
{
	return rvTrue;
}

static RvBool rvPhoneMgrDestroyMedia(RvMdmTerm *term, RvMdmMediaStream *media, OUT RvMdmError *mdmError)
{
	RvPhoneMedia *phoneMedia = (RvPhoneMedia *)rvMdmMediaStreamGetUserData(media);

	rvPhoneMediaDestruct(phoneMedia);
	rvAllocDeallocate(&rvDefaultAlloc, sizeof(RvPhoneMedia), phoneMedia);	
	
	return rvTrue;
}

static RvBool rvPhoneMgrDeletePhysicalTerm(RvMdmTerm *termination, void *termMgr)
{
	RvPhoneLink *phoneLink = (RvPhoneLink *)rvMdmTermGetUserData(termination);
	rvMdmTermMgrUnregisterTermination((RvMdmTermMgr *)termMgr, termination, NULL);
	rvPhoneLinkDestruct(phoneLink);
	rvAllocDeallocate(&rvDefaultAlloc, sizeof(RvPhoneLink), phoneLink);
	return rvFalse;
}

static RvRtpLink *rvPhoneMgrGetRtpLink(RvMdmMediaStream *stream)
{
	return &((RvPhoneMedia *)rvMdmMediaStreamGetUserData(stream))->rtpLink;
}

static RvBool rvPhoneMgrProcessHookEvent(RvMdmTerm *termination, 
					  const char *pkg, const char *name, RvMdmMediaStream *mediaStream,
					  const RvMdmParameterList *parameters, RvMdmError *errorInfo)
{
	char value[256];
	RvPhoneLink *phoneLink = (RvPhoneLink *)rvMdmTermGetUserData(termination);

	RvBool onHook = rvEppClientQuery(phoneLink->eppClient, phoneLink->endpoint,
		rvMdmTermGetId(termination), "hookstate", value) != NULL && strcmp(value, "on") == 0;

	return rvMdmHookEventProcessParams(termination, pkg, name, onHook, parameters, errorInfo);	
}

RvPhysTermData rvPhoneMgrClassData = { rvPhoneMgrGetRtpLink,
	rvPhoneMgrProcessHookEvent, rvPhoneMgrProcessHookEvent };

RvPhoneMgr *rvPhoneMgrConstruct(RvPhoneMgr *mgr, RvMdmTermMgr *termMgr, rtpEngine *engine)
{
	const RvInetPort eppPort = 3044;

	mgr->termMgr = termMgr;
	mgr->phoneClass = rvMdmTermMgrCreateTermClass(termMgr);
	mgr->engine = engine;

	rvEppClientConstruct(&mgr->eppClient, eppPort, 
		rvPhoneMgrOnRegister, rvPhoneMgrOnEvent, rvPhoneMgrOnUnregister, mgr);

	rvMdmTermClassRegisterStartSignalCB(mgr->phoneClass, rvPhoneMgrStartSignal);
	rvMdmTermClassRegisterStopSignalCB(mgr->phoneClass, rvPhoneMgrStopSignal);
	rvMdmTermClassRegisterCreateMediaCB(mgr->phoneClass, rvPhoneMgrCreateMedia);
	rvMdmTermClassRegisterModifyMediaCB(mgr->phoneClass, rvPhoneMgrModifyMedia);
	rvMdmTermClassRegisterDestroyMediaCB(mgr->phoneClass, rvPhoneMgrDestroyMedia);	
	rvMdmTermClassAddSupportedPkg(mgr->phoneClass, "al", 0);
	rvMdmTermClassAddSupportedPkg(mgr->phoneClass, "cg", 0);
	rvMdmTermClassAddSupportedPkg(mgr->phoneClass, "dd", 0);
	rvMdmTermClassSetUserData(mgr->phoneClass, &rvPhoneMgrClassData);
	
	return mgr;
}

void rvPhoneMgrDestruct(RvPhoneMgr *mgr)
{
	rvEppClientDestruct(&mgr->eppClient);
	rvMdmTermMgrForEachPhysicalTerm(mgr->termMgr, rvPhoneMgrDeletePhysicalTerm, mgr->termMgr);
}

⌨️ 快捷键说明

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