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

📄 rtcs.cpp

📁 Windows CE .Net 下面 VOIP编程的经典实例。对于初学Windows 平台下VOIP编程技术的程序员颇具借鉴意义!
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*************************************************************************


  Disclaimer:

    This code and information is provided "as is" without warranty of
    any kind, either expressed or implied, including but not limited to
    the implied warranties of merchantability and/or fitness for a
    particular purpose.

Module Name:

	rtcs.cpp

Abstract:

    Provides functions for UI to interface with the rest of the app.

Notes:
	
	This helps to keep the UI and RTC as separate as possible.

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

// instantiate global variables
#define _Instantiate_Globals_ 1

#include <windows.h>
#include "rtcs.h"
#include "rtcInternal.h"
#include <iptypes.h>
#include <iphlpapi.h>

int g_iAlloc = 0;
int g_iFree = 0;

HANDLE g_hShutdownEventComplete = NULL;
extern DWORD g_dwMainThreadID;
BSTR ReadProfileFromFile(void);

/***********************************************************************************************
	Global variables
************************************************************************************************/
extern LOCAL_USER_INFO*	g_pLocalUserInfo;	// local user information
extern HINSTANCE		m_hInstance;		// main program instance (for resources, etc.)

STRING_TBL BuddyStatusTbl[] = {
	RTCXS_PRESENCE_OFFLINE,			L"RTCXS_PRESENCE_OFFLINE",
	RTCXS_PRESENCE_ONLINE,			L"RTCXS_PRESENCE_ONLINE",
	RTCXS_PRESENCE_AWAY,			L"RTCXS_PRESENCE_AWAY",
	RTCXS_PRESENCE_IDLE,			L"RTCXS_PRESENCE_IDLE",
	RTCXS_PRESENCE_BUSY,			L"RTCXS_PRESENCE_BUSY",
	RTCXS_PRESENCE_BE_RIGHT_BACK,	L"RTCXS_PRESENCE_BE_RIGHT_BACK",
	RTCXS_PRESENCE_ON_THE_PHONE,	L"RTCXS_PRESENCE_ON_THE_PHONE",
	RTCXS_PRESENCE_OUT_TO_LUNCH,	L"RTCXS_PRESENCE_OUT_TO_LUNCH",
	END_VAL,	L"Unknown Buddy Status"
}; // used by HandleBuddyEvent(), and SetMyStatus() in rtcs.cpp 


IRES_TBL EstatRTCTbl[] = {
	ES_ONLINE,	RTCXS_PRESENCE_ONLINE,
	ES_OFFLINE,	RTCXS_PRESENCE_OFFLINE,
	ES_AWAY,	RTCXS_PRESENCE_AWAY,
	ES_PHONE,	RTCXS_PRESENCE_ON_THE_PHONE,
	ES_LUNCH,	RTCXS_PRESENCE_OUT_TO_LUNCH,
	ES_BUSY,	RTCXS_PRESENCE_BUSY,
	ES_BEBACK,	RTCXS_PRESENCE_BE_RIGHT_BACK,
	END_VAL,	-1
}; // used to match internal presence status with RTC presence status codes


/************************************************************************************************
	Internal function prototypes
 ************************************************************************************************/

BOOL InitializePresence(BSTR bstrName);
BOOL OpenRegKey( LPWSTR szRegKey, HKEY* hKey );

/************************************************************************************************
 
   InitializeRTC
 
 	Performs all steps necessary to initialize the RTC side of the app.
 
 	- Creates & initializes the COM objects
 		registers the event handler with RTC & starts to listen for incoming connections
	- Calls InitializePresence
 	- sets the local URI and name for outgoing SIP headers
 
 ************************************************************************************************/

BOOL 
InitializeRTC(
			  FARPROC fnSWCB,
			  HINSTANCE hInst
			  )
{
    HRESULT hr = S_OK;
	BOOL bRV = TRUE;
	HANDLE hDB = NULL;
	CEOID oid = 0;
	BOOL bDone = FALSE;

    // Connect to the RTC stuff
	DEBUGMSG( ZONE_STATUS|ZONE_INIT|ZONE_WARN, (L"Voipdemo: Beginning Initialization of RTC.\r\n") );

    hr =  CoInitializeEx(NULL, COINIT_MULTITHREADED);
	
    if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR, (L"VoipDemo: CoInitializeEx Failed 0x%X\r\n", hr) );
		return FALSE;
    }
	
    hr = CoCreateInstance(
		CLSID_RTCClient,
		NULL,
		CLSCTX_INPROC_SERVER,
		IID_IRTCClient,
		(LPVOID *)&g_pRTCClient
		);
    
	if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR, (L"VoipDemo: CoCreateInstance(RTCClient) Failed 0x%X\r\n", hr) );
		return FALSE;
	}
	
	hr = g_pRTCClient->Initialize();

	if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR, (L"VoipDemo: Failed to initialize RTCClient 0x%lx\r\n",hr) );
			bRV = FALSE;
			goto Cleanup;	
	} 

	g_pcsSessionDataLock = new CRITICAL_SECTION;
	InitializeCriticalSection( g_pcsSessionDataLock );

	g_pRTCEvents = new CRTCEvents;

	if (g_pRTCEvents == NULL) {
		DEBUGMSG( ZONE_ERROR, (L"VoipDemo: Unable to allocate memory for event interface.") );
		bRV = FALSE;
		goto Cleanup;
	}

	// Register the event handler with the RTC Client
	RegisterEventInterface();
	
	// Get notifications for desired events only
	// Media and Intensity events are not necessary

	g_pRTCClient->put_EventFilter(
						     RTCEF_CLIENT						|
							 RTCEF_REGISTRATION_STATE_CHANGE	|
							 RTCEF_SESSION_STATE_CHANGE			|
							 RTCEF_PARTICIPANT_STATE_CHANGE		|
							 RTCEF_MESSAGING					|
							 RTCEF_BUDDY						|
							 RTCEF_WATCHER
							 );

	// To store the email address of the person, we need to use profiles, or message headers on the IM messages...		
	if (!InitializePresence( g_pLocalUserInfo->get_Name() )) {
		bRV = FALSE;
		goto Cleanup;		
	}

	// store name and URI for other clients to pull from the session connections
	g_pRTCClient->put_LocalUserURI( g_pLocalUserInfo->get_Addr() );
	g_pRTCClient->put_LocalUserName( g_pLocalUserInfo->get_Name() );

#ifdef RTC_PERSISTENT_STORAGE_UNIMPLEMENTED
	// import the buddies/watchers list from the CE DB
	hDB = MyAddrDB_Init( hInst );
	
	do {
		CEPROPVAL* pPropVal = NULL;
		oid = MyAddrDB_Read( hDB, 0, &pPropVal);
		
		if ( oid == -1 || oid == 0 || !pPropVal ) {
			bDone = TRUE;
		} else {
			switch ((BUDDYTYPE) pPropVal[DBF_TYPE].val.lVal) 
			{
			case BT_WATCHER:
				// note, we use EMAIL as a way of holding the watcher's state (allowed or blocked)
				AddWatcherRTC(pPropVal[DBF_ADDR].val.lpwstr, pPropVal[DBF_NAME].val.lpwstr, pPropVal[DBF_BLOB].val.lpwstr, FALSE );				
				break;
			case BT_MYSELF:
				// change my info (use email to store phone number, if exist
//				SetMyInfo(pPropVal[DBF_ADDR].val.lpwstr, pPropVal[DBF_NAME.val.lpwstr], pPropVal[DBF_BLOB].val.lpwstr);
				break;
			case BT_PHONE: 
				// note DBF_BLOB is actually the phone number
				AddBuddyRTC(pPropVal[DBF_BLOB].val.lpwstr, pPropVal[DBF_NAME].val.lpwstr, (BUDDYTYPE) pPropVal[DBF_TYPE].val.lVal, VARIANT_TRUE, NULL);
				break;
			case BT_COMPUTER:
				AddBuddyRTC(pPropVal[DBF_ADDR].val.lpwstr, pPropVal[DBF_NAME].val.lpwstr, (BUDDYTYPE) pPropVal[DBF_TYPE].val.lVal, VARIANT_TRUE, NULL);
				break;
			default:
				break;
			}  // end switch(buddytype)
		} // end if valid buddy						
	}while (!bDone);

	MyAddrDB_Close(hDB);

	// notify re-added watchers of my status, change so RTC is certain to send out the notification
	SetMyStatusRTC(ES_OFFLINE);
	SetMyStatusRTC(ES_ONLINE);
#endif // RTC_PERSISTENT_STORAGE_UNIMPLEMENTED

	// instantiate session container
	g_pSessionContainer = new CSessionContainer;

	if (g_pSessionContainer == NULL) {
		DEBUGMSG( ZONE_ERROR, (L"VoipDemo: Unable to allocate memory for CSessionContainer.") );
		bRV = FALSE;
		goto Cleanup;
	}

	// store SWCB function pointer
	ASSERT(fnSWCB != NULL);		
	g_fnSWCB = (SWCB_FN_PTR) fnSWCB;

	DEBUGMSG( ZONE_STATUS|ZONE_CALL, (L"VoipDemo: Setting RTC to listen for new calls\r\n") );
	
	hr = g_pRTCClient->put_ListenForIncomingSessions( RTCLM_BOTH );
	
	if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR, (L"VoipDemo: put_ListenForIncomingSessions failed 0x%lx\r\n", hr) );
		bRV = FALSE;
		goto Cleanup;
	}

Cleanup:
	if (bRV == FALSE) {
		ForceShutdownRTC();
	}

	DEBUGMSG( ZONE_STATUS|ZONE_INIT|ZONE_WARN, (L"Voipdemo: Initialization of RTC Successful.\r\n") );
	return bRV;	
} // end InitializeRTC( )

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

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

BOOL
InitializePresence(BSTR bstrName) 
{
	HRESULT hr = S_OK;

#ifdef USE_AMUNSERVER
	IRTCClientProvisioning* pProvisioning;
	
	hr = g_pRTCClient->QueryInterface(IID_IRTCClientProvisioning, (LPVOID *)&pProvisioning);

	if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR|ZONE_PROVISION, (L"Voipdemo: Error querying client interface for provisioning interface.\r\n") );
		ASSERT(FALSE);
	}

	// Load the default XML profile
	BSTR bstrProfile = NULL;

	// Read the profile from file "profile.xml"
	bstrProfile = ReadProfileFromFile();

	// If "profile.xml" is not found on disk use the default profile
	if (!bstrProfile)
	{
		DEBUGMSG( ZONE_ERROR|ZONE_PRESENCE|ZONE_PROVISION, (L"Voipdemo: \"profile.xml\" not found, using default profile\r\n") );
		bstrProfile = SysAllocString( DEFAULT_XML_PROFILE );
	}

	if (!bstrProfile) {
		DEBUGMSG( ZONE_ERROR|ZONE_PRESENCE|ZONE_PROVISION, (L"Voipdemo: Error parsing XML profile, non-existent\r\n") );
		ASSERT(FALSE);
		return FALSE;
	}


	DEBUGMSG( ZONE_STATUS|ZONE_PRESENCE|ZONE_PROVISION, (L"VoipDemo: Creating default XML profile for registration\r\n") );
	hr = pProvisioning->CreateProfile(bstrProfile,&g_pRTCProfile);

	SysFreeString(bstrProfile);

	if (FAILED(hr)) { 
		DEBUGMSG( ZONE_ERROR|ZONE_PRESENCE|ZONE_PROVISION, (L"VoipDemo: InitializePresence() CreateProfile Failed! 0x%lx\r\n") );
		pProvisioning->Release();
		return FALSE;
	}
	
	// update credentials 
    hr = g_pRTCProfile->SetCredentials(g_pLocalUserInfo->get_Addr(), g_pLocalUserInfo->get_Name(), NULL);

	DEBUGMSG( ZONE_STATUS|ZONE_PRESENCE|ZONE_PROVISION, (L"VoipDemo: Enabling profile\r\n") );
	
	//register
	hr = pProvisioning->EnableProfile( g_pRTCProfile, RTCRF_REGISTER_ALL );

#ifndef NO_PHONE_TO_PHONE
// Load the phone to phone XML profile
	bstrProfile = SysAllocString( PHONE_TO_PHONE_XML_PROFILE );

	if (!bstrProfile) {
		DEBUGMSG( ZONE_ERROR|ZONE_PRESENCE|ZONE_PROVISION, (L"Voipdemo: Error parsing phone to phone XML profile, non-existent\r\n") );
		ASSERT(FALSE);
		return FALSE;
	}

	IRTCProfile* pP2PProfile = NULL

	DEBUGMSG( ZONE_STATUS|ZONE_PRESENCE|ZONE_PROVISION, (L"VoipDemo: Creating phone to phone XML profile for registration\r\n") );
	hr = pProvisioning->CreateProfile(bstrProfile,&pP2PProfile);

	SysFreeString(bstrProfile);

	if (FAILED(hr)) { 
		DEBUGMSG( ZONE_ERROR|ZONE_PRESENCE|ZONE_PROVISION, (L"VoipDemo: InitializePresence() CreateProfile Failed on phone to phone profile! 0x%lx\r\n") );
		pProvisioning->Release();
		return FALSE;
	}
	
	// update credentials 
    hr = pP2PProfile->SetCredentials(g_pLocalUserInfo->get_Addr(), g_pLocalUserInfo->get_Name(), NULL);

	DEBUGMSG( ZONE_STATUS|ZONE_PRESENCE|ZONE_PROVISION, (L"VoipDemo: Enabling phone to phone profile\r\n") );
	
	//register
	hr = pProvisioning->EnableProfile( pP2PProfile, RTCRF_REGISTER_ALL );

	// release our reference to phone to phone profile (the rtc core will take care of it now)
	pP2PProfile->Release();
#endif

	pProvisioning->Release();

	if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR, (L"VoipDemo: InitializePresence() EnableProfile Failed! 0x%lx\r\n") );
		return FALSE;
	}
#endif // USE_AMUNSERVER

	hr = g_pRTCClient->QueryInterface( IID_IRTCClientPresence, (LPVOID *)&g_pRTCPresence );

	if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR|ZONE_PRESENCE, (L"VoipDemo: Unable to QueryInterface IRTCClientPresence interface from the RTC Client 0x%lx",hr) );
		return FALSE;
	}

	VARIANT v;
	::VariantInit(&v);

	// Enable presence & store it to/read it from a file
#ifdef RTC_PERSISTENT_STORAGE_UNIMPLEMENTED
	hr = g_pRTCPresence->EnablePresence(VARIANT_FALSE, v);
#else
    v.bstrVal = SysAllocString(DEFAULT_PRESENCE_STORAGE);
    v.vt = VT_BSTR;

	hr = g_pRTCPresence->EnablePresence(VARIANT_TRUE, v);

	if (SUCCEEDED(hr)) {
		DEBUGMSG( ZONE_STATUS|ZONE_PRESENCE, (L"VoipDemo: Enabled Presence, using %s as persistent store\r\n", v.bstrVal) );
		SysFreeString(v.bstrVal);
	}

#endif // RTC_PERSISTENT_STORAGE_UNIMPLEMENTED

	if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR|ZONE_PRESENCE, (L"Voipdemo: EnablePresence failed! 0x%lx\r\n", hr) );
		g_pRTCPresence->Release();		
		return FALSE;
	}

#ifdef RTC_PERSISTENT_STORAGE_UNIMPLEMENTED
	hr = g_pRTCPresence->put_OfferWatcherMode(RTCOWM_OFFER_WATCHER_EVENT);
	DEBUGMSG( ZONE_STATUS|ZONE_PRESENCE, (L"VoipDemo: Incoming watchers will trigger a watcer event so that they may be stored outside of RTC\r\n") );
#else
	hr = g_pRTCPresence->put_OfferWatcherMode(RTCOWM_AUTOMATICALLY_ADD_WATCHER);
	DEBUGMSG( ZONE_STATUS|ZONE_PRESENCE, (L"VoipDemo: Auto-add watchers set to true\r\n") );
#endif //RTC_PERSISTENT_STORAGE_UNIMPLEMENTED
	hr = g_pRTCPresence->SetLocalPresenceInfo(RTCXS_PRESENCE_ONLINE, NULL);
	DEBUGMSG( ZONE_STATUS|ZONE_PRESENCE, (L"VoipDemo: Set Presence Online\r\n") );
	return TRUE;
}


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

  ForceShutdownRTC
 	
 	Force a hard shutdown.  This will be called during errors before the main thread msg loop.  
	If the function is called in the main loop, any attempts to read from the RTC interface
	pointers will fail.

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

VOID
ForceShutdownRTC()
{
	HRESULT hr = S_OK;

	DEBUGMSG( ZONE_STATUS|ZONE_INIT, ( L"VoipDemo: Forcing hard shutdown of RTC.\r\n" ) );
	

	if (g_pSessionContainer)
		delete g_pSessionContainer;

	if (g_pRTCPresence) {
		// tell my buddies I'm leaving
		SetMyStatusRTC(ES_OFFLINE);
		g_pRTCPresence->Release();
		g_pRTCPresence = NULL;
	}

#ifdef USE_AMUNSERVER
	if (g_pRTCProvision) {
		g_pRTCProvision->DisableProfile(g_pRTCProfile);

		if (g_pRTCProfile) {
			g_pRTCProfile->Release();
			g_pRTCPresence = NULL;
		}
	}	
#endif	
	if (g_pRTCClient) {
		hr = g_pRTCClient->Shutdown();
	}

	if (FAILED(hr)) {
		DEBUGMSG( ZONE_ERROR, ( L"VoipDemo: Shutdown call on RTCClient object failed 0x%lx!\r\n", hr ) );		
		// make sure we know that this happened
		ASSERT(FALSE);		
	}
	
	// final app cleanup
	DEBUGMSG( ZONE_STATUS, (L"VoipDemo: Unregistering event notification interface.\r\n") );
	UnregisterEventInterface();	

    if (g_pcsSessionDataLock) {
        EnterCriticalSection( g_pcsSessionDataLock );
        LeaveCriticalSection( g_pcsSessionDataLock );
        DeleteCriticalSection( g_pcsSessionDataLock );
        delete g_pcsSessionDataLock;
        g_pcsSessionDataLock = NULL;
    }
	
    if (g_pRTCEvents) {
        delete g_pRTCEvents;
        g_pRTCEvents = NULL;
    }

	g_pRTCClient->Release();
	g_pRTCClient = NULL;

	CoUninitialize();
	
	DEBUGMSG( 1, ( L"VoipDemo: Successful termination of RTCClient\r\n" ) );
	
	NKDbgPrintfW( L"VoipDemo: Exiting\r\n" );
}


/*-----------------------------------------------------------------------------

	Function:		ShutdownRTC( void ) 

	Parameters:

	Return value:	0

	Abstract:		Attempt a graceful shutdown

	Notes:			None

-------------------------------------------------------------------------------*/

DWORD WINAPI ShutdownRTC( LPVOID option )
{
	// Stop listening for incoming sessions

⌨️ 快捷键说明

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