realvod.cpp

来自「本人买的<<VC++项目开发实例>>源代码配套光盘.」· C++ 代码 · 共 1,090 行 · 第 1/3 页

CPP
1,090
字号
/****************************************************************************
 *
 *  $Id: exallow.cpp,v 1.1 1998/12/03 18:44:43 darrens Exp $
 *
 *  Copyright (C) 1998 RealNetworks, Inc.
 *  All rights reserved.
 *
 *  http://www.real.com/devzone
 *
 *  This program contains proprietary information of RealNetworks, Inc.,
 *  and is licensed subject to restrictions on use and distribution.
 *
 *  exallow.cpp
 *
 *  Example Allowance plug-in for the RealMedia Architecture (RMA).
 */

/****************************************************************************
 *  This is an example of an Allowance plug-in. The purpose of an Allowance
 *  server plug-in is to monitor player connections to the server and make 
 *  decisions about what each player is allowed to do. The Allowance plug-in
 *  receives a notification for each significant event in a player's 
 *  connection lifetime, and can act to restrict the player's rights after
 *  receiving any one of these notifications. The ways in which an Allowance
 *  plug-in can restrict a player are varied, and include disconnecting,
 *  redirecting, authenticating, or granting limited permissions to the
 *  player in terms of which content can be played.
 *
 *  In order for your plug-in to achieve this functionality, it must
 *  implement the IRMAPlayerConnectionAdviseSink interface which has 
 *  methods for receiving notifications of many events in the course of
 *  each player connection. The IRMAPlugin interface must also be 
 *  implemented to handle fundamental plug-in operations.
 *
 *
 *  Example: exallow.cpp
 *
 *  This example demonstrates a simple Allowance Plug-in. It will impose the
 *  following two restrictions upon incoming player connections, to
 *  demonstrate just a few of the ways in which Allowance Plug-ins can be
 *  used to customize and extend the capabilities of the RMA server:
 *
 *  1) A maximum of 5 players will be allowed to view the 
 *     rtsp://server:port/limited.rm URL at any given time. If a player 
 *     requests this URL while 5 players are already viewing it, the 6th
 *     player will receive an alert message, asking them to try again later.
 *
 *  2) A player attempting to view the rtsp://server:port/jukebox.rm URL
 *     will be randomly redirected to one of the following URLs:
 *
 *                  - rtsp://server:port/song1.rm
 *                  - rtsp://server:port/song2.rm
 *                  - rtsp://server:port/song3.rm
 *
 *  To test this example plug-in, simply build the plug-in, place it in
 *  your RMA server plug-in directory, and place RealMedia (.rm) files in
 *  your content directory with the names mentioned above (limited.rm, 
 *  song1.rm, song2.rm, and song3.rm). Connect to one of the two special URLs
 *  with a RealPlayer to verify that the Allowance plug-in is working 
 *  properly.
 *
 *
 *  The RMA server calls the various interface routines at well defined times.
 *  The sequence of the major events is as follows:
 *
 *  Upon RMA server startup:
 *  - RMACreateInstance() creates new instance of CMyExampleRenderer class
 *  - GetPlugInInfo()     returns descriptive information about the plug-in
 *
 *  When a player first connects to the server:
 *  - OnConnection()	    called when a player connects
 *  - SetPlayerController() called to provide a player controlling interface
 *  - SetRegistryID()	    called to provide the location of player info.
 *  - OnURL()		    called when the player requests a URL
 *
 *  During the player's connection:
 *  - OnBegin()		    called when player starts or resumes
 *  - OnStop()		    called when player stops
 *  - OnPause()		    called when the playback is paused
 *  - OnDone()		    called when the player has disconnected
 *
 *
 *  Note:
 *  The routines are listed roughly in the order in which they are called.
 */


/****************************************************************************
 * Defines
 */
#define	INITGUID     /* Interface ID's */
#define	MAX_LIMITED_URL_COUNT 5
#define LIMITED_URL_ALERT "Too many users are viewing this stream. Please try again later."
//UDP正在读取中。
#define PNR_READ_PENDING MAKE_HRESULT(0,SS_GLO,0x7)
#define PNR_READ_BILLING_PENDING MAKE_HRESULT(0,SS_GLO,0x11)
/****************************************************************************
 * Includes
 */
#include <stdio.h>     /* printf, sprintf */
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "dotnet.h"
#include "pntypes.h" 
#include "pncom.h"     /* IUnknown */
#include "rmacomm.h"   /* IRMACommonClassFactory */
#include "rmapckts.h"  /* IRMABuffer, IRMAPacket, IRMAValues */
#include "rmaplugn.h"  /* IRMAPlugin */
#include "rmaallow.h"  /* IRMAPlayerConnectionAdviseSink */
#include "rmamon.h"    /* IRMAPNRegistry */
#include "rmafiles.h"  /* IRMARequest */
#include "rmaerror.h"	/* IRMAErrorMessages */
#include "realVOD.h"   /* CExampleAllowance */

//检查变量,用于do{...}while(false);结构。
#define CHECK_VALUE_AND_BREAK(x) if (!(x)) \
						{\
						break; \
						}
//构造IP地址,地址是按照本地字节顺序组织的4字节整数。
inline ULONG32 IPv4(UINT8 Ip1, UINT8 Ip2, UINT8 Ip3, UINT8 Ip4)
{
	return (Ip4 + ((UINT32)Ip3 << 8) + ((UINT32)Ip2 << 16) + ((UINT32)Ip1 << 24)); 
}
/****************************************************************************
 *  RMACreateInstance                                        ref:  rmaplugn.h
 *
 *  This routine creates a new instance of the CExampleAllowance class.
 *  It is called when the RMA server application is launched.
 */
STDAPI
RMACreateInstance(IUnknown** ppExAllowanceObj)
{
    *ppExAllowanceObj = (IUnknown*)(IRMAPlugin*)new CExampleAllowance();
    if (*ppExAllowanceObj != NULL)
    {
		(*ppExAllowanceObj)->AddRef();
		return PNR_OK;
    }

    return PNR_OUTOFMEMORY;
}


/****************************************************************************
 *  CExampleAllowance static variables                        ref:  exallow.h
 *
 *  These variables are passed to the RMA server to provide information about
 *  this plug-in. They are required to be static in order to remain valid
 *  for the lifetime of the plug-in.
 */
const char* CExampleAllowance::zm_pDescription = MY_DESCRIPTION;
const char* CExampleAllowance::zm_pCopyright   = MY_COPYRIGHT;
const char* CExampleAllowance::zm_pMoreInfoURL = MY_MORE_INFO_URL;


/****************************************************************************
 *  CExampleAllowance::CExampleAllowance                      ref:  exallow.h
 *
 *  Constructor
 */
CExampleAllowance::CExampleAllowance(void)
    : m_RefCount	    (0),
      m_pClassFactory	    (NULL),
      m_pRegistry	    (NULL),
      m_pPCResponse	    (NULL),
      m_pPlayerController   (NULL),
      m_ulPlayerRegistryID  (0),
      m_pPlayerRegistryName (NULL),
      m_bViewingLimitedURL  (FALSE),
	  m_pNetworkServices	(NULL)	//初始化变量
	  , m_uCallbackInterval (1000)//(3 * 60 * 1000) //3分钟中断
	  , m_hCallback			(NULL)
	  , m_pScheduler		(NULL)
	  , m_stsStatus			(statusNormal)
	  , m_pError			(NULL)  //初始化变量
	  , m_pUDPSocket		(NULL)
	  , m_pUDPDataBuffer	(NULL)
	  , m_bIsCommercial		(false)	//设置当前为访问不受保护资源
	  , m_bWaitingBillingResp (false) //是否正在等待计费的返回标志
{
	fprintf(stdout, "Entering CExampleAllowance()...\n");
	memset(m_szPassword, 0, sizeof(m_szPassword));
	memset(m_szUserName, 0, sizeof(m_szUserName));
}


/****************************************************************************
 *  IRMAPlugin::GetPluginInfo                                ref:  rmaplugn.h
 *
 *  This routine returns descriptive information about the plug-in. It is 
 *  called when the RMA server application is launched.
 */
STDMETHODIMP
CExampleAllowance::GetPluginInfo
(
    REF(BOOL)        bLoadMultiple,
    REF(const char*) pDescription,
    REF(const char*) pCopyright,
    REF(const char*) pMoreInfoURL,
    REF(UINT32)      versionNumber
)
{
    bLoadMultiple = TRUE;
    pDescription  = zm_pDescription;
    pCopyright    = zm_pCopyright;
    pMoreInfoURL  = zm_pMoreInfoURL;
    versionNumber = MY_PLUGIN_VERSION;

    return PNR_OK;
}


/****************************************************************************
 *  IRMAPlugin::InitPlugin                                   ref:  rmaplugn.h
 *
 *  This routine performs initialization steps such as determining if
 *  required interfaces are available. It is called when the RMA core 
 *  application is launched, and whenever a new player Allowance object
 *  is needed.
 */
STDMETHODIMP
CExampleAllowance::InitPlugin(IUnknown* pContext)
{
	fprintf(stdout, "初始化InitPlugin()\n");
	m_bWaitingBillingResp = false;
    /*
     * Store a reference to the IRMACommonClassFactory interface which is
     * used to create commonly used RMA objects such as IRMAPacket, 
     * IRMAValues, and IRMABuffers.
     */
	PN_RESULT hResult = PNR_FAILED;
	do
	{
		hResult = pContext->QueryInterface(IID_IRMACommonClassFactory, 
			(void**)&m_pClassFactory);
		CHECK_VALUE_AND_BREAK(m_pClassFactory)
		/*
		* Store a reference to the IRMAPNRegistry interface which is
		* used to retrieve useful information about the connected player
		*/
		hResult = pContext->QueryInterface(IID_IRMAPNRegistry, 
			(void**)&m_pRegistry);
		CHECK_VALUE_AND_BREAK(m_pRegistry);

		//取得关键字路径
		IRMABuffer *pPropertyValue = NULL;
		const char *szBasePath = "config.VicAliPlugin.Commercial.KeyWord";
		char pathKey[1024] = {0};
		int i = 0;

		sprintf(pathKey, "%s%d", szBasePath, i);
		m_pRegistry->GetStrByName(pathKey, pPropertyValue);
		while(pPropertyValue)
		{
			m_vectorProtectedDir.push_back((char *)pPropertyValue->GetBuffer());
			PN_RELEASE(pPropertyValue);

			sprintf(pathKey, "%s%d", szBasePath, ++i);
			m_pRegistry->GetStrByName(pathKey, pPropertyValue);
		}				

		for (m_theIterator = m_vectorProtectedDir.begin()
					; m_theIterator != m_vectorProtectedDir.end()
					; m_theIterator++)
		{
			fprintf(stdout, "Keyword--->%s\n", m_theIterator->c_str());
		}

		//取得IRMANetworkServices
		hResult = pContext->QueryInterface(IID_IRMANetworkServices
			,(void **)&m_pNetworkServices);
		CHECK_VALUE_AND_BREAK(m_pNetworkServices);
		
		//取得IRMAScheduler
		hResult = pContext->QueryInterface(IID_IRMAScheduler
			, (void **)&m_pScheduler);
		CHECK_VALUE_AND_BREAK(m_pScheduler);
		//取得IRMANetworkServices
		hResult = pContext->QueryInterface(IID_IRMAErrorMessages
			,(void **)&m_pError);
		CHECK_VALUE_AND_BREAK(m_pError);
		//创建UDP Socket
		hResult = m_pNetworkServices->CreateUDPSocket(&m_pUDPSocket);
		if (NULL == m_pUDPSocket)
		{			
			fprintf(stdout, "CreateUDPSocket fail.\n");
			break;
		}
		else
		{
			fprintf(stdout, "CreateUDPSocket successfully.\n");
		}				
		hResult = m_pUDPSocket->Init(IPv4(127, 0, 0, 1)/*127.0.0.1*/, 0, this);
		CHECK_VALUE_AND_BREAK(hResult);
		/* 
		* Note that QueryInterface() takes care of adding a reference to the
		* interface for us. You are however responsible for releasing the
		* reference to the object when you are done using it by calling
		* the Release() routine.
		*/
	}while(false);

    return hResult;
}


/****************************************************************************
 *  IRMAPlayerConnectionAdviseSink::OnConnection             ref:  rmaallow.h
 *
 *  The server core calls this routine when a new player has connected
 *  to the server.
 */
STDMETHODIMP 
CExampleAllowance::OnConnection(THIS_ IRMAPlayerConnectionResponse* pResponse)
{
    m_pPCResponse = pResponse;
    m_pPCResponse->AddRef();

    m_pPCResponse->OnConnectionDone(PNR_OK);

    return PNR_OK;
}

/****************************************************************************
 *  IRMAPlayerConnectionAdviseSink::SetPlayerController      ref:  rmaallow.h
 *
 *  The server core calls this routine to supply the Allowance plug-in with
 *  an interface by which the player can be controlled. For example, this 
 *  interface can be used to disconnect the player, send them an alert 
 *  message, or redirect them to another URL.
 */
STDMETHODIMP
CExampleAllowance::SetPlayerController(THIS_ 
				       IRMAPlayerController* pPlayerController)
{
    m_pPlayerController = pPlayerController;
    m_pPlayerController->AddRef();

    return PNR_OK;
}

/****************************************************************************
 *  IRMAPlayerConnectionAdviseSink::SetRegistryID            ref:  rmaallow.h
 *
 *  The server core calls this routine to supply the Allowance plug-in with
 *  a server registry ID, which can be used to find out various pieces of
 *  information about the connected player. For example, the player's IP
 *  Address, GUID, and Protocol are all stored under this key in the server
 *  registry.
 */
STDMETHODIMP
CExampleAllowance::SetRegistryID(THIS_ UINT32 ulPlayerRegistryID)
{
    m_ulPlayerRegistryID = ulPlayerRegistryID;

    // Obtain the name of the key for obtaining subkeys later
    m_pRegistry->GetPropName(ulPlayerRegistryID, m_pPlayerRegistryName);

    return PNR_OK;
}

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

⌨️ 快捷键说明

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