📄 proxyservices.cpp
字号:
{
HRESULT hr = S_OK;
//The voicemail settings have changed - meaning we need to
//get the new proxy-profile for subscribing with the server.
//First, determine which RTC profile to use (one set by the CSP, or use the same
//as the "active" registrar.
if ( GetApp()->GetSettings().IsSettingAvailable(Settings_t::SettingTypeVoicemailSettings) )
{
//clear out any old profile
m_VoicemailCollection.m_cpSubscribeProxy = NULL;
//get the new profile
hr = GetApp()->GetSettings().GetVoicemailProfile(
&m_VoicemailCollection.m_cpSubscribeProxy
);
//if this failed - unsubscribe the old value and be done with it
if (FAILED(hr))
{
UnsubscribeFromVoicemailServer();
return hr;
}
}
else
{
//otherwise, we want to use our "active" profile
m_VoicemailCollection.m_cpSubscribeProxy = NULL;
}
return SubscribeWithVoicemailServer();
}
/*------------------------------------------------------------------------------
ProxyServices_t::SubscribeWithVoicemailServer
Start the SUBSCRIBE transaction with the proxy server.
------------------------------------------------------------------------------*/
HRESULT
ProxyServices_t::SubscribeWithVoicemailServer()
{
HRESULT hr = S_OK;
//if we are already subscribed to a voice mail server, unsubscribe it first
if (m_VoicemailCollection.m_cpSubscription != NULL)
{
//start unsubscribing
hr = UnsubscribeFromVoicemailServer();
if (SUCCEEDED(hr))
{
//if this succeeded, then we need to wait for the
//existing subscription to finish unsubscribing
m_VoicemailCollection.m_Flags |= SubscriptionCollection_t::SUBSCRIBE_AFTER_UNSUBSCRIBE;
return S_OK;
}
//otherwise, this failed - NULL out the subscription and continue
m_VoicemailCollection.m_cpSubscription = NULL;
}
//if there is no active profile for registration, we always wait for registration done
//before we start subscription
if (m_cpActiveSIPProfile == NULL)
{
m_VoicemailCollection.m_Flags |= SubscriptionCollection_t::SUBSCRIBE_AFTER_REGISTER;
return S_OK;
}
//we need to choose a profile to subscribe with -
IRTCProfile* pProxyProfile = m_VoicemailCollection.m_cpSubscribeProxy;
//special processing if we are sharing the profile with the registration server
if (pProxyProfile == NULL)
{
pProxyProfile = m_cpActiveSIPProfile;
}
//now we have the our proxy profile - we can subscribe to the voicemail server
ce::auto_bstr AcceptedContent = SysAllocString(c_AcceptedContentForSubscription);
ce::auto_bstr EventPackage = SysAllocString(c_EventForSubscription);
if (EventPackage == NULL || AcceptedContent == NULL)
{
return E_OUTOFMEMORY;
}
//if RTC is not initialized yet, return
if (GetRTCClientPointer() == NULL)
{
return E_FAIL;
}
CComPtr<IRTCClientSubscriber> cpSubscriber;
hr = GetRTCClientPointer()->QueryInterface(
IID_IRTCClientSubscriber,
reinterpret_cast<VOID**>(&cpSubscriber)
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to get the subscriber object from the RTC client - error 0x%x", hr));
return hr;
}
//start the SUBSCRIBE transaction
hr = cpSubscriber->CreateSubscription(
pProxyProfile,
AcceptedContent,
EventPackage,
NULL,
NULL,
&m_VoicemailCollection.m_cpSubscription
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to create subscription with subscriber -- error 0x%x", hr));
return hr;
}
return S_OK;
}
/*------------------------------------------------------------------------------
ProxyServices_t::UnsubscribeFromVoicemailServer
Starts the unSUBSCRIBE transaction with the SIP proxy
------------------------------------------------------------------------------*/
HRESULT
ProxyServices_t::UnsubscribeFromVoicemailServer()
{
//make sure we have a valid subscription to unsubscribe with
if (m_VoicemailCollection.m_cpSubscription == NULL)
{
return E_FAIL;
}
HRESULT hr = m_VoicemailCollection.m_cpSubscription->Unsubscribe();
if (FAILED(hr))
{
return hr;
}
m_VoicemailCollection.m_Flags |= SubscriptionCollection_t::UNSUBSCRIBING;
return S_OK;
}
/*------------------------------------------------------------------------------
ProxyServices_t::OnSubscriptionStateChangeEvent
Handles a Subscription State Change event from the RTC event sink.
------------------------------------------------------------------------------*/
HRESULT
ProxyServices_t::OnSubscriptionStateChangeEvent(
IRTCSubscriptionStateChangeEvent* pEvent
)
{
ASSERT(pEvent != NULL);
CComPtr<IRTCSubscription> cpSubscription;
//Get the subscription from the event to determine if this is our subscription -
//otherwise it is a subscription we don't care about
HRESULT hr = pEvent->get_Subscription(&cpSubscription);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to get a subscription from the subscription state change event - error code = 0x%x", hr));
return hr;
}
//validate that this is the subscription we care about.
if (! PhoneAppUtilities_t::AreCOMPointersEqual<IRTCSubscription>(cpSubscription, m_VoicemailCollection.m_cpSubscription))
{
return S_OK;
}
RTC_SUBSCRIPTION_STATE SubscriptionState = RTCSUBC_ERROR;
//Get the new subscription state
hr = pEvent->get_SubscriptionState(&SubscriptionState);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to get the subscription state from the event object - error code = 0x%x", hr));
return hr;
}
UINT NewVoicemailStatus = VOIP_NO_VOICEMAIL_SETTINGS_BITMASK;
switch (SubscriptionState)
{
case RTCSUBC_SUBSCRIBING:
case RTCSUBC_UNSUBSCRIBING:
break;
case RTCSUBC_SUBSCRIBED:
ASSERT(!(m_VoicemailCollection.m_Flags & SubscriptionCollection_t::UNSUBSCRIBING));
NewVoicemailStatus = VOIP_VOICEMAIL_SUBSCRIBED_BITMASK;
break;
case RTCSUBC_NOT_SUBSCRIBED:
case RTCSUBC_LOGGED_OFF:
case RTCSUBC_ERROR:
NewVoicemailStatus = (SubscriptionState == RTCSUBC_NOT_SUBSCRIBED) ?
VOIP_VOICEMAIL_UNSUBSCRIBED_BITMASK :
VOIP_VOICEMAIL_SUBSCRIPTION_ERROR_BITMASK;
//if we are in the process of unsubscribing...
if (m_VoicemailCollection.m_Flags & SubscriptionCollection_t::UNSUBSCRIBING)
{
m_VoicemailCollection.m_Flags &= ~(SubscriptionCollection_t::UNSUBSCRIBING);
m_VoicemailCollection.m_cpSubscription = NULL;
//if we are supposed to start a new SUBSCRIBE transaction, start it now
if (m_VoicemailCollection.m_Flags & SubscriptionCollection_t::SUBSCRIBE_AFTER_UNSUBSCRIBE)
{
m_VoicemailCollection.m_Flags &= ~(SubscriptionCollection_t::SUBSCRIBE_AFTER_UNSUBSCRIBE);
SubscribeWithVoicemailServer();
}
}
break;
default:
ASSERT(FALSE);
return E_UNEXPECTED;
}
//If there is a voicemail status change, then notify everyone else
if (NewVoicemailStatus != m_SubscriptionStatusFlags)
{
m_SubscriptionStatusFlags = NewVoicemailStatus;
RegistrySetDWORD(
SN_VOIP_VOICEMAILSTATUS_ROOT,
SN_VOIP_VOICEMAILSTATUS_PATH,
SN_VOIP_VOICEMAILSTATUS_VALUE,
m_SubscriptionStatusFlags
);
}
return S_OK;
}
/*------------------------------------------------------------------------------
ProxyServices_t::OnSubscriptionNotificationEvent
Handles a Subscription Notification event from the RTC event sink
------------------------------------------------------------------------------*/
HRESULT
ProxyServices_t::OnSubscriptionNotificationEvent(
__in IRTCSubscriptionNotificationEvent* pEvent
)
{
ASSERT(pEvent != NULL);
CComPtr<IRTCSubscription> cpSubscription;
//Get the subscription from the event to determine if this is our subscription -
//otherwise it is a subscription we don't care about
HRESULT hr = pEvent->get_Subscription(&cpSubscription);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to get a subscription from the subscription state change event - error code = 0x%x", hr));
return hr;
}
//Is this our subscription?
if (! PhoneAppUtilities_t::AreCOMPointersEqual<IRTCSubscription>(
m_VoicemailCollection.m_cpSubscription,
cpSubscription
))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_EVENT, (L"This event concerns a subscription we are not tracking - ignoring..."));
return S_OK;
}
//blindly accept this event (so the server won't continue sending us data...)
pEvent->Accept(NULL, NULL);
ce::auto_bstr ContentType;
ce::auto_bstr MessageData;
hr = pEvent->GetNotificationData(
&ContentType,
&MessageData
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at gettting notification data from event object -- error code = 0x%x", hr));
return hr;
}
if (wcsicmp(ContentType, c_AcceptedContentForSubscription) != 0)
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_EVENT, (L"This event's content type doesn't match with what we subscribed - ignoring..."));
return S_OK;
}
bool ThereIsVoiceMailWaiting = false;
UINT NumberOfNewVoiceMails = 0;
UINT NumberOfOldVoiceMails = 0;
UINT NumberOfUrgentNewVoiceMails = 0;
UINT NumberOfUrgentOldVoiceMails = 0;
hr = ParseVoiceMailNotification(
MessageData,
SysStringLen(MessageData),
&ThereIsVoiceMailWaiting,
&NumberOfNewVoiceMails,
&NumberOfOldVoiceMails,
&NumberOfUrgentNewVoiceMails,
&NumberOfUrgentOldVoiceMails
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to parse the voice mail notification"));
return hr;
}
///TODO: notify the UI to update voicemail indication
return S_OK;
}
/*------------------------------------------------------------------------------
ProxyServices_t::OnVoicemailNumberChange
Cache the voice mail number and notify the the cprog with the updated voice mail number
------------------------------------------------------------------------------*/
HRESULT
ProxyServices_t::OnVoicemailNumberChange()
{
//handle the voicemail number changes
return GetApp()->GetSettings().UpdateVoicemailNumber();
}
/*------------------------------------------------------------------------------
ProxyServices_t::GetBackupSIPProfile
Get the active backup profile object.
This will return the enabled backup profile IFF the backup profile is registered
AND the backup profile is not the active profile (meaning the main profile is active)
------------------------------------------------------------------------------*/
IRTCProfile*
ProxyServices_t::GetBackupSIPProfile(
void
)
{
if (m_BackupProxyCollection.m_RegistrationState != RTCRS_REGISTERED)
{
return NULL;
}
if (PhoneAppUtilities_t::AreCOMPointersEqual<IRTCProfile>(m_cpActiveSIPProfile, m_BackupProxyCollection.m_cpEnabledProfile))
{
return NULL;
}
return m_BackupProxyCollection.m_cpEnabledProfile;
}
/*------------------------------------------------------------------------------
ProxyServices_t::UpdateUserInfoInRegistry
Update provision related user info in registry
Parameters:
pProfile: if this parameter is NULL, we will clean up the user info in registry
otherwise, get user info from this pProfile
------------------------------------------------------------------------------*/
void
ProxyServices_t::UpdateUserInfoInRegistry(
IRTCProfile* pProfile
)
{
if (pProfile == NULL)
{
//clear out all the old registry info
RegistrySetString(
SN_VOIP_LOCALURI_ROOT,
SN_VOIP_LOCALURI_PATH,
SN_VOIP_LOCALURI_VALUE,
L""
);
RegistrySetString(
SN_VOIP_RTCUSERNAME_ROOT,
SN_VOIP_RTCUSERNAME_PATH,
SN_VOIP_RTCUSERNAME_VALUE,
L""
);
return;
}
ce::auto_bstr bstrBuffer;
if (SUCCEEDED(m_cpActiveSIPProfile->get_UserURI(&bstrBuffer)))
{
WCHAR* pLocalURI = bstrBuffer;
ce::auto_bstr bstrFriendlyNumber;
HRESULT hr = GetApp()->GetDialEngine().GetPhoneNumberToDisplay(
bstrBuffer,
-1,
NULL,
&bstrFriendlyNumber
);
if (SUCCEEDED(hr))
{
pLocalURI = bstrFriendlyNumber;
}
else
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at getting display-able number, hr = 0x%x", hr));
}
//save it to registry, do not care about the return value
RegistrySetString(
SN_VOIP_LOCALURI_ROOT,
SN_VOIP_LOCALURI_PATH,
SN_VOIP_LOCALURI_VALUE,
pLocalURI
);
}
if (SUCCEEDED(m_cpActiveSIPProfile->get_UserName(&bstrBuffer)))
{
//save it to registry, do not care about the return value
RegistrySetString(
SN_VOIP_RTCUSERNAME_ROOT,
SN_VOIP_RTCUSERNAME_PATH,
SN_VOIP_RTCUSERNAME_VALUE,
bstrBuffer
);
}
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -