realvod.cpp

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

CPP
1,090
字号
 *  IRMAPlayerConnectionAdviseSink::OnURL                    ref:  rmaallow.h
 *
 *  The server core calls this routine when the connected player requests
 *  a URL. The requested URL is stored in the passed IRMARequest object,
 *  along with all 822 Headers that accompanied the request.
 */
STDMETHODIMP 
CExampleAllowance::OnURL(THIS_ IRMARequest* pRequest)
{
    PN_RESULT	hResult = PNR_OK;
    const char* pURL	= NULL;

	//从Cookie中取得用户名和密码
	IRMAValues *pIRMAValues = NULL;
	pRequest->GetRequestHeaders(pIRMAValues);
	IRMABuffer *pPropertyValue = NULL;
	if (pIRMAValues != NULL)
	{
		//取得Cookie
		hResult = pIRMAValues->GetPropertyCString(
				"Cookie", pPropertyValue);
		//得到用户名字和密码
		GetUserInfoFromCookie((const char *)pPropertyValue->GetBuffer());
		PN_RELEASE(pPropertyValue);
		PN_RELEASE(pIRMAValues);
	}	
 

    // Obtain the requested URL
    pRequest->GetURL(pURL);

	for (m_theIterator = m_vectorProtectedDir.begin()
			; m_theIterator != m_vectorProtectedDir.end()
			; m_theIterator++)
	{
		if (strstr(pURL, m_theIterator->c_str()))
		{
			//设置当前的状态为访问受保护的资源。
			m_bIsCommercial = true;
			hResult = HandleProtectedURLRequest();
			break;
		}
	}	

	if (!strcmp(pURL, "limited.rm"))
    {
		// The player requested the limited.rm URL
		hResult = HandleLimitedURLRequest();
    }
    else if (!strcmp(pURL, "jukebox.rm"))
    {
		// The player requested the jukebox.rm URL
		hResult = HandleJukeboxURLRequest();
    }

    /*
     * Note: Most IRMAPlayerConnectionAdviseSink interface functions have
     * a corresponding response function in the IRMAPlayerConnectionResponse
     * interface. This function should be called when the plug-in has 
     * finished processing the notification.
     *
     * The connected player will not be permitted to begin playback until 
     * all allowance plugins have called OnURLDone() with a Status of PNR_OK.
     */
	if (PNR_READ_PENDING == hResult)
	{		
		//必须等待授权的结果,所以不能
		//调用m_nPCResponse->OnURLDone(hResult);
		//调用OnURLDone()的任务在ReadDone中完成。
		//设置CallBack
		m_hCallback = m_pScheduler->RelativeEnter(this
									, 1000 * 100/*100秒钟*/);
		if (m_hCallback)
		{
			fprintf(stdout, "加入OnAuthenticationTimeout成功\n");
		}
		else
		{
			fprintf(stdout, "加入OnAuthenticationTimeout功能失败!!\n");
		}
	}
	else
	{
		m_pPCResponse->OnURLDone(hResult);
	}    
    return PNR_OK;
}

/****************************************************************************
 *  IRMAPlayerConnectionAdviseSink::OnBegin                  ref:  rmaallow.h
 *
 *  The server core calls this routine when the player begins or resumes
 *  playback.
 */
STDMETHODIMP 
CExampleAllowance::OnBegin(void)
{
	m_stsStatus = statusNormal;
	if (m_bIsCommercial)
	{
		//设置CallBack
		m_hCallback = m_pScheduler->RelativeEnter(this, m_uCallbackInterval);
		if (m_hCallback)
		{
			fprintf(stdout, "加入HeartBeating功能\n");
		}
		else
		{
			fprintf(stdout, "加入HeartBeating功能失败!!\n");
		}
		
		m_stsStatus = statusHeartbeating;
	}
    m_pPCResponse->OnBeginDone(PNR_OK);
	
    return PNR_OK;
}

/****************************************************************************
 *  IRMAPlayerConnectionAdviseSink::OnPause                  ref:  rmaallow.h
 *
 *  The server core calls this routine when the player pauses playback.
 */
STDMETHODIMP 
CExampleAllowance::OnPause(void)
{
    m_pPCResponse->OnPauseDone(PNR_OK);

    return PNR_OK;
}

/****************************************************************************
 *  IRMAPlayerConnectionAdviseSink::OnStop                   ref:  rmaallow.h
 *
 *  The server core calls this routine when the player stops playback.
 */
STDMETHODIMP 
CExampleAllowance::OnStop(void)
{
	m_bWaitingBillingResp = false;
	//移除CallBack
	if (m_hCallback)
	{
		fprintf(stdout, "移除Scheduler\n");
		m_pScheduler->Remove(m_hCallback);
		m_hCallback = NULL;
	}
	PN_RELEASE(m_pUDPSocket); //Cancel Read operation

	m_vectorProtectedDir.clear();

    if (m_bViewingLimitedURL)
    {
	// This player has finished viewing the "limited.rm" URL
	DecrementLimitedURLCount();
	m_bViewingLimitedURL = FALSE;
    }

    m_pPCResponse->OnStopDone(PNR_OK);

    return PNR_OK;
}

/****************************************************************************
 *  IRMAPlayerConnectionAdviseSink::OnDone                   ref:  rmaallow.h
 *
 *  The server core calls this routine when the player has disconnected
 *  from the server.
 *  
 */
STDMETHODIMP 
CExampleAllowance::OnDone(void)
{
    return PNR_OK;
}


/****************************************************************************
 *  CExampleAllowance::~CExampleAllowance                    ref:   exallow.h
 *
 *  Destructor
 */
CExampleAllowance::~CExampleAllowance(void)
{
	fprintf(stdout, "Entering ~CExampleAllowance()...\n");
    PN_RELEASE(m_pClassFactory);

	PN_RELEASE(m_pRegistry);
    
    PN_RELEASE(m_pPCResponse);
    
	PN_RELEASE(m_pPlayerController);
    
	PN_RELEASE(m_pPlayerRegistryName);

	PN_RELEASE(m_pNetworkServices);	
	//释放IRMAScheduler
	PN_RELEASE(m_pScheduler);
	//释放IRMAErrorMessages
	PN_RELEASE(m_pError);
	PN_RELEASE(m_pUDPSocket);
	PN_RELEASE(m_pUDPDataBuffer);
}


// IUnknown COM Interface Methods

/****************************************************************************
 *  IUnknown::AddRef                                            ref:  pncom.h
 *
 *  This routine increases the object reference count in a thread safe
 *  manner. The reference count is used to manage the lifetime of an object.
 *  This method must be explicitly called by the user whenever a new
 *  reference to an object is used.
 */
STDMETHODIMP_(UINT32)
CExampleAllowance::AddRef(void)
{
    return InterlockedIncrement(&m_RefCount);
}


/****************************************************************************
 *  IUnknown::Release                                           ref:  pncom.h
 *
 *  This routine decreases the object reference count in a thread safe
 *  manner, and deletes the object if no more references to it exist. It must
 *  be called explicitly by the user whenever an object is no longer needed.
 */
STDMETHODIMP_(UINT32)
CExampleAllowance::Release(void)
{
    if (InterlockedDecrement(&m_RefCount) > 0)
    {
		return m_RefCount;
    }

    delete this;
    return 0;
}


/****************************************************************************
 *  IUnknown::QueryInterface                                    ref:  pncom.h
 *
 *  This routine indicates which interfaces this object supports. If a given
 *  interface is supported, the object's reference count is incremented, and
 *  a reference to that interface is returned. Otherwise a NULL object and
 *  error code are returned. This method is called by other objects to
 *  discover the functionality of this object.
 */
STDMETHODIMP
CExampleAllowance::QueryInterface
(
    REFIID interfaceID,
    void** ppInterfaceObj
)
{
    // By definition all COM objects support the IUnknown interface
    if (IsEqualIID(interfaceID, IID_IUnknown))
    {
		AddRef();
		*ppInterfaceObj = (IUnknown*)(IRMAPlugin*)this;
		return PNR_OK;
    }
	
    // IRMAPlugin interface is supported
    else if (IsEqualIID(interfaceID, IID_IRMAPlugin))
    {
		AddRef();
		*ppInterfaceObj = (IRMAPlugin*)this;
		return PNR_OK;
    }
	
    // IRMAPlayerConnectionAdviseSink interface is supported
    else if (IsEqualIID(interfaceID, IID_IRMAPlayerConnectionAdviseSink))
    {
		AddRef();
		*ppInterfaceObj = (IRMAPlayerConnectionAdviseSink*)this;
		return PNR_OK;
    }
	
    // No other interfaces are supported
    *ppInterfaceObj = NULL;
    return PNR_NOINTERFACE;
}

PN_RESULT
CExampleAllowance::HandleLimitedURLRequest()
{
	PN_RESULT   hResult      = PNR_OK;
	INT32   nClientCount = 0;
	IRMABuffer* pBuffer      = NULL;
	
	// Find out how many players are currently watching this URL
	if (PNR_OK != m_pRegistry->GetIntByName("server.LimitedURLCount", 
		nClientCount))
	{
		// The registry item does not exist yet, so create it
		nClientCount = 0;
		m_pRegistry->AddInt("server.LimitedURLCount", nClientCount);
	}
	
	// Test the limit, to determine if it has reached capacity
	if (nClientCount >= MAX_LIMITED_URL_COUNT)
	{
		// We have reached capacity, so send them an alert message
		m_pClassFactory->CreateInstance(CLSID_IRMABuffer, (void**)&pBuffer);
		pBuffer->Set((const UCHAR*)LIMITED_URL_ALERT, 
			strlen(LIMITED_URL_ALERT) + 1);
		m_pPlayerController->AlertAndDisconnect(pBuffer);
		PN_RELEASE(pBuffer);
		
		hResult = PNR_FAIL;
	}
	else
	{
		// We have not reached capacity, so let them have access
		m_bViewingLimitedURL = TRUE;
		
		// Increment the count and update its registry value
		nClientCount++;
		m_pRegistry->SetIntByName("server.LimitedURLCount", nClientCount);
	}
	
	return hResult;
}

PN_RESULT
CExampleAllowance::HandleJukeboxURLRequest()
{
    UINT32	ulRand  = 0;
    char	pNewURL[256];
    IRMABuffer* pBuffer = NULL;

    // Generate a random number between 0 and 2
    srand((unsigned)time(NULL));
    ulRand = rand() % 3;

    // Choose a redirect URL based on the result
    switch(ulRand)
    {
	case 0:
	{
	    sprintf(pNewURL, "song1.rm");
	}
	break;

	case 1:
	{
	    sprintf(pNewURL, "song2.rm");
	}
	break;

	case 2:
	default:
	{
	    sprintf(pNewURL, "song3.rm");
	}
	break;
    }

    // Redirect the player
    m_pClassFactory->CreateInstance(CLSID_IRMABuffer, (void**)&pBuffer);

⌨️ 快捷键说明

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