📄 rtcevent.cpp
字号:
// set up session based upon type
switch(enRST) {
case RTCST_PC_TO_PC:
case RTCST_PHONE_TO_PHONE:
case RTCST_PC_TO_PHONE:
DEBUGMSG( ZONE_STATUS|ZONE_CALL, ( L"VoipDemo:Event VoIP session connected and in progress\r\n" ) );
break;
case RTCST_IM:
DEBUGMSG( ZONE_STATUS|ZONE_CALL, ( L"VoipDemo:Event IM session connected and in progress\r\n" ) );
break;
default:
break;
} // end switch Session Type
break;
} // end RTCSS_CONNECTED
case RTCSS_DISCONNECTED:
{
// turn off incoming voice session ring
hr = g_pRTCClient->PlayRing( RTCRT_PHONE, VARIANT_FALSE );
if (FAILED(hr)) {
DEBUGMSG( ZONE_ERROR, ( L"VoipDemo: Event PlayRing failed! 0x%lx\r\n", hr ) );
}
if (!g_pSessionContainer->Exist(pSess)) {
// incoming session that timed out
break;
}
// store session state locally
(*g_pSessionContainer)[pSess]->put_SessionState( enRSS );
// remove the session from the container
g_pSessionContainer->Remove(pSess);
EnterCriticalSection( g_pcsSessionDataLock );
switch (enRST) {
case RTCST_IM:
ASSERT(g_bIMSessionOpen);
g_bIMSessionOpen = FALSE;
if (!g_bVoiceSessionOpen) {
SysFreeString( g_bstrCurrentlyConnectedURI );
g_bstrCurrentlyConnectedURI = NULL;
}
break;
default:
ASSERT(g_bVoiceSessionOpen);
g_bVoiceSessionOpen = FALSE;
if (!g_bIMSessionOpen) {
SysFreeString( g_bstrCurrentlyConnectedURI );
g_bstrCurrentlyConnectedURI = NULL;
}
break;
}// end switch(sessiontype)
LeaveCriticalSection( g_pcsSessionDataLock );
} // end RTCSS_DISCONNECTED
break;
case RTCSS_INPROGRESS:
(*g_pSessionContainer)[pSess]->put_SessionState(enRSS);
break;
default:
// do nothing
break;
} // end switch (Session state)
Cleanup:
if (pSSC)
pSSC->Release();
if (pSess)
pSess->Release();
return hr;
} // end SessionStateChangeEvent()
/************************************************************************************************
HRESULT HandleParticipantStateChangeEvent ( IN IDispatch * pEvent )
Event handler for particpant state change events.
Relevant Events:
INCOMING - get participant information for display to user, ask user to accept / reject session.
CONNECTED - pass connected message to SWCB
************************************************************************************************/
HRESULT
HandleParticipantStateChangeEvent(
IN IDispatch* pEvent
)
{
HRESULT hr = S_OK;
RTC_PARTICIPANT_STATE enRPS;
RTC_SESSION_TYPE enRST;
IRTCParticipantStateChangeEvent * pPSC = NULL;
IRTCParticipant* pPart = NULL;
IRTCSession * pSess = NULL;
P_PARTICIPANT_INFO pPartInfo = NULL;
BSTR bstrPartName = NULL;
INT iRetVal = 0;
hr = pEvent->QueryInterface(
IID_IRTCParticipantStateChangeEvent,
(VOID **)&pPSC
);
if ( FAILED(hr) || !pPSC)
{
DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event QueryInterface failed in HandleParticipantStateChangeEvent 0x%lx\r\n", hr ) );
goto Cleanup;
}
// get participant, then get the session, then get the session type (IM or VOICE)
hr = pPSC->get_State( &enRPS );
if (FAILED(hr)) {
DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event: Participant::get_State failed! 0x%lx\r\n", hr ) );
goto Cleanup;
}
DEBUGMSG( ZONE_STATUS|ZONE_CALL, ( L"VoipDemo:Event RTCE_PARTICIPANT_STATE_CHANGE - %s\r\n", GetStringFromVal(enRPS, ParticipantStateTbl) ) );
hr = pPSC->get_Participant(&pPart); // does AddRef(pPart)
if (FAILED(hr) || !pPart) {
DEBUGMSG( ZONE_ERROR, (L"VoipDemo:Event failure getting participant! 0x%lx\r\n", hr) );
goto Cleanup;
}
hr = pPart->get_Session(&pSess); // does AddRef(pSess)
if(FAILED(hr) || !pSess) {
DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event get_Session failed! 0x%lx\r\n", hr ) );
goto Cleanup;
}
if (FALSE == g_pSessionContainer->Exist(pSess)) {
pSess->get_Type( &enRST );
// create a new CSession object to store the session
CSession* pSessionObj = new CSession( pSess, enRST, RTCSS_INCOMING, g_fnSWCB );
g_pSessionContainer->Add( pSess, pSessionObj );
} else {
enRST = (*g_pSessionContainer)[pSess]->get_SessionType();
}
switch(enRPS)
{
case RTCPS_INCOMING:
{
if (enRST != RTCST_PHONE_TO_PHONE) {
// get the participant info
pPartInfo = (*g_pSessionContainer)[pSess]->get_ParticipantInfo( pPart );
if ( !pPartInfo ) {
DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event Error getting participant info from CSession\r\n") );
(*g_pSessionContainer)[pSess]->Reject();
hr = E_FAIL;
goto Cleanup;
}
iRetVal = SWCB_CALL_REJECTED;
// Ensure that we only get 1 IM session
// Ensure that we're only accepting additional sessions from the same user
// that is ONLY concurrent IM and Voice from the same location
switch(enRST)
{
case RTCST_PC_TO_PC:
// case RTCST_PC_TO_PHONE: // Will never get this
EnterCriticalSection( g_pcsSessionDataLock );
if (g_bIMSessionOpen && g_bstrCurrentlyConnectedURI) {
if (!SipURIsResolve(g_bstrCurrentlyConnectedURI, pPartInfo->get_Addr())) {
LeaveCriticalSection( g_pcsSessionDataLock );
DEBUGMSG( ZONE_ERROR|ZONE_STATUS|ZONE_CALL, (L"VoipDemo: Event Error, only allowing concurrent sessions from a single source\r\n") );
(*g_pSessionContainer)[pSess]->Reject();
hr = E_FAIL;
goto Cleanup;
}
}
LeaveCriticalSection( g_pcsSessionDataLock );
// ask user to accept / deny session
iRetVal = (*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_CALL_INITIATING_INCOMING, pPartInfo, pSess );
break;
case RTCST_IM:
EnterCriticalSection( g_pcsSessionDataLock );
if (g_bVoiceSessionOpen && g_bstrCurrentlyConnectedURI) {
if (!SipURIsResolve(g_bstrCurrentlyConnectedURI, pPartInfo->get_Addr())) {
LeaveCriticalSection( g_pcsSessionDataLock );
DEBUGMSG( ZONE_ERROR|ZONE_STATUS|ZONE_CALL, (L"VoipDemo: Event Error, only allowing concurrent sessions from a single source\r\n") );
(*g_pSessionContainer)[pSess]->Reject();
hr = E_FAIL;
goto Cleanup;
}
}
LeaveCriticalSection( g_pcsSessionDataLock );
// ask user to accept / deny session
iRetVal = (*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_IM_INITIATING_INCOMING, pPartInfo, pSess );
break;
} // end switch (sessiontype)
switch (iRetVal)
{
case SWCB_CALL_REJECTED:
(*g_pSessionContainer)[pSess]->Reject();
break;
case SWCB_CALL_TIMEOUT:
// timeout do nothing
break;
case SWCB_CALL_ACCEPTED:
if ((*g_pSessionContainer)[pSess]->Accept() == FALSE) {
hr = E_FAIL;
}
EnterCriticalSection( g_pcsSessionDataLock );
if (!g_bstrCurrentlyConnectedURI)
g_bstrCurrentlyConnectedURI = SysAllocString(pPartInfo->get_Addr());
LeaveCriticalSection( g_pcsSessionDataLock );
break;
default:
DEBUGMSG( ZONE_ERROR, (L"VoipDemo: Event error from SWCB function, unexpected retval: %i\r\n", iRetVal) );
break;
} // end switch (SWCB retval)
} // end if (!enRST != RTCST_PHONE_TO_PHONE)
else {
//RTCST_PHONE_TO_PHONE
// will we ever get this message on a phone to phone session?
// phone to phone sessions should have the following states:
// INPROGRESS -> call initiating
// ANSWERING ?
// CONNECTED -> adds participant's reference to the call?
// DISCONNECTED -> remove references for all added participants??
// Note: we shouldn't accept or reject the session from here. The two phones will handle that. We should
// just show status of the call.
//
// (*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_CALL_PARTICIPANT_JOINED, , pSess )
//
}
break;
} // end case RTCPS_INCOMING
case RTCPS_CONNECTED:
{
hr = pPart->get_Name( &bstrPartName );
if (FAILED(hr)) {
DEBUGMSG( ZONE_ERROR, (L"VoipDemo: Event failed! getting name from Participant->get_Name(): 0x%l\r\n") );
goto Cleanup;
}
DEBUGMSG( ZONE_STATUS|ZONE_CALL, ( L"VoipDemo:Event participant %s connected to session %s.\r\n", bstrPartName, GetStringFromVal(enRST, SessionTypeTbl)) );
switch(enRST)
{
case RTCST_PC_TO_PC:
case RTCST_PC_TO_PHONE:
case RTCST_PHONE_TO_PHONE:
// call the SWCB function for this particular session
(*g_pSessionContainer)[pSess]->get_SWCBfn()(SWCBM_CALL_PARTICIPANT_JOINED, bstrPartName, pSess );
break;
case RTCST_IM:
// call the SWCB function for this particular session
(*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_IM_PARTICIPANT_JOINED, bstrPartName, pSess );
break;
default:
break;
} // end switch Session Type
SysFreeString( bstrPartName );
break;
}
case RTCPS_DISCONNECTED:
{
hr = pPart->get_Name( &bstrPartName );
if (FAILED(hr)) {
DEBUGMSG( ZONE_ERROR|ZONE_CALL, (L"VoipDemo: Event Failed! getting participant name. 0x%lx\r\n", hr) );
goto Cleanup;
}
switch (enRST) {
case RTCST_PC_TO_PC:
case RTCST_PC_TO_PHONE:
case RTCST_PHONE_TO_PHONE:
(*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_CALL_PARTICIPANT_LEFT, bstrPartName, pSess );
break;
case RTCST_IM:
(*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_IM_PARTICIPANT_LEFT, bstrPartName, pSess );
break;
default:
break;
}
SysFreeString( bstrPartName );
if (enRST == RTCST_PHONE_TO_PHONE) {
// if in a phone to phone call the participant leaves, do we need to explicitly remove him? or do we
// release his reference to the session? or both?
// if (pPart->get_Removable()) {
// pSess->RemoveParticipant(pPart);
// }
// pSess->Release(); // release participant's reference to the session. (?)
}
break;
}
default:
break;
} // end switch (Participant state
Cleanup:
if (pPart)
pPart->Release();
if (pSess)
pSess->Release();
if (pPSC)
pPSC->Release();
return hr;
} // end ParticipantStateChangeEvent()
/************************************************************************************************
HRESULT HandleClientEvent( IN IDispatch* pEvent )
Event Handler for client events
Currently the only relevant event is SHUTDOWN_COMPLETE, so final app cleanup
is done here.
************************************************************************************************/
HRESULT
HandleClientEvent(
IN IDispatch* pEvent
)
{
HRESULT hr = S_OK;
IRTCClientEvent * pCE;
hr = pEvent->QueryInterface(
IID_IRTCClientEvent,
(VOID **)&pCE
);
RTC_CLIENT_EVENT_TYPE enCET;
hr = pCE->get_EventType( &enCET);
pCE->Release();
pCE = NULL;
if (FAILED(hr)) {
DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event ClientEvent::get_EventType failed! 0x%lx\r\n", hr ) );
return hr;
}
DEBUGMSG( ZONE_STATUS|ZONE_CALL, ( L"VoipDemo:Event RTCE_CLIENT - %s\r\n", GetStringFromVal(enCET, ClientEventTbl) ) );
switch(enCET)
{
case RTCCET_ASYNC_CLEANUP_DONE:
{
// PrepareForShutdown has completed. It's okay to shutdown now.
// This event is being observed by ShutdownRTC()
SetEvent( g_hShutdownEventComplete );
DEBUGMSG( ZONE_STATUS, ( L"VoipDemo: Event RTCE_ASYNC_CLEANUP completed\r\n" ) );
break;
}
default:
break;
}
return hr;
} // end ClientEvent()
/************************************************************************************************
HRESULT HandleMessagingEvent( IN IDispatch* pEvent )
Event Handler for messaging events
Takes incoming messages and passes them to the UI for display to the user. It currently
just ignores status messages, as the GUI doesn't yet support them.
************************************************************************************************/
HRESULT
HandleMessagingEvent(
IN IDispatch* pEvent
)
{
HRESULT hr = S_OK;
IRTCSession* pSess = NULL;
IRTCParticipant* pPart = NULL;
IRTCMessagingEvent * pME;
hr = pEvent->QueryInterface(
IID_IRTCMessagingEvent,
(VOID **)&pME
);
// For use with multiple IM sessions, to identify on which session a messages is coming
hr = pME->get_Session( &pSess ); // does AddRef(pSess)
if (FAILED(hr)) {
DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event MessagingEvent::get_Session failed 0x%lx\r\n", hr ) );
goto Cleanup;
}
hr = pME->get_Participant( &pPart);
if (FAILED(hr)) {
DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event MessagingEvent::get_Participant failed 0x%lx\r\n", hr ) );
goto Cleanup;
}
RTC_MESSAGING_EVENT_TYPE enMET;
hr = pME->get_EventType( &enMET );
if (FAILED(hr)) {
DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event MessagingEvent::get_EventType failed! 0x%lx\r\n", hr ) );
goto Cleanup;
}
switch (enMET)
{
case RTCMSET_MESSAGE:
BSTR bstrIMMsg;
hr = pME->get_Message( &bstrIMMsg );
if (SUCCEEDED(hr)) {
DEBUGMSG( ZONE_STATUS|ZONE_CALL, ( L"VoipDemo:Event incoming IM message received.\r\n" ) );
// form the message into our internal message structure
IM_MSG sIMMsg = { (*g_pSessionContainer)[pSess]->get_ParticipantInfo(pPart), bstrIMMsg };
// pass the message to the UI for display
(*g_pSessionContainer)[pSess]->get_SWCBfn()( SWCBM_IM_MESSAGE_ARRIVED, &sIMMsg, pSess );
SysFreeString( bstrIMMsg );
} else {
DEBUGMSG( ZONE_ERROR, ( L"VoipDemo:Event MessagingEvent::get_Message failed! 0x%lx\r\n", hr ) );
}
// ring to note incoming message
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -