📄 proxyservices.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "ProxyServices.hpp"
#include "CommonFunctions.hpp" //for CommonUtilities
#include "VoIPApp.hpp" //for public accessors
#include "Debug.hpp"
//strings used for subscribing the voice mail indication from RTC
const WCHAR c_AcceptedContentForSubscription[] = L"application/simple-message-summary";
const WCHAR c_EventForSubscription[] = L"message-summary";
/*------------------------------------------------------------------------------
ParseVoiceMailNotification
helper function to parse the voice mail notification to get whether there is
a new voice mail waiting and different voice mail counts, the syntax of input
notificaiton can be found at RFC3842.
Parameters:
MessageData: [in] string of the message data
MessageLength: [in] the length of the message data string
pThereIsVoiceMailWaiting: [out] indicate whether there is voice mail or not
pNumberOfNewVoiceMails: [out] number of new voice mails
pNumberOfOldVoiceMails: [out] number of old voice mails
pNumberOfUrgentNewVoiceMails: [out] number of urgent new voice mails
pNumberOfUrgentOldVoiceMails: [out] number of urgent old voice mails
Returns:
S_OK indicates success, otherwise failure
------------------------------------------------------------------------------*/
HRESULT ParseVoiceMailNotification(
__in_ecount(MessageDataLength) const WCHAR* MessageData,
UINT MessageDataLength,
__out bool* pThereIsVoiceMailWaiting,
__out UINT* pNumberOfNewVoiceMails,
__out UINT* pNumberOfOldVoiceMails,
__out UINT* pNumberOfUrgentNewVoiceMails,
__out UINT* pNumberOfUrgentOldVoiceMails
)
{
if (
!MessageData ||
!(*MessageData) ||
!MessageDataLength ||
!pThereIsVoiceMailWaiting ||
!pNumberOfNewVoiceMails ||
!pNumberOfOldVoiceMails ||
!pNumberOfUrgentNewVoiceMails ||
!pNumberOfUrgentOldVoiceMails
)
{
//internal function, verify the input parmeters only
ASSERT(FALSE);
return E_INVALIDARG;
}
//lower cased const text strings
const WCHAR c_MessageStatusLineHeader[] = L"messages-waiting:";
const WCHAR c_MessageSummaryLineHeader[] = L"voice-message:";
const WCHAR c_YesText[] = L"yes";
const WCHAR c_NoText[] = L"no";
WCHAR Buffer[MAX_PATH] = TEXT("");
WCHAR* pCurrent = Buffer;
WCHAR* pSeperator = NULL;
//copy the whole string into buffer
StringCchCopyN(
Buffer,
ARRAYSIZE(Buffer),
MessageData,
MessageDataLength
);
//convert the buffer into lower case
wcslwr(Buffer);
//eat spaces
while ((*pCurrent == L' ') || (*pCurrent == L'\t'))
{
pCurrent++;
}
//see if we can find the 'Message-Waiting' string
if (wcsncmp(pCurrent, c_MessageStatusLineHeader, ARRAYSIZE(c_MessageStatusLineHeader) - 1) != 0)
{
return E_FAIL;
}
//move the pointer right after 'Message-Waiting'
pCurrent += (ARRAYSIZE(c_MessageStatusLineHeader) - 1);
//eat spaces
while ((*pCurrent == L' ') || (*pCurrent == L'\t'))
{
pCurrent++;
}
//check to see whether there is a 'Yes' or 'No'.
if (wcsncmp(pCurrent, c_YesText, ARRAYSIZE(c_YesText) - 1) == 0)
{
*pThereIsVoiceMailWaiting = true;
}
else if (wcsncmp(pCurrent, c_NoText, ARRAYSIZE(c_NoText) - 1) == 0)
{
*pThereIsVoiceMailWaiting = false;
}
else
{
return E_FAIL;
}
//find the substring 'voice-message:'
pCurrent = wcsstr(pCurrent, c_MessageSummaryLineHeader);
if (!pCurrent)
{
return S_FALSE;
}
//move the pointer right after 'Voice Message:'
pCurrent += (ARRAYSIZE(c_MessageSummaryLineHeader) - 1);
//parse the rest of the message to find out each message count
//it should have format NewMsgCount / OldMsgCount (NewUrgentMsgCount / OldUrgentMsgCount)
//basic idea is to go through below map table to find the seperator character, and then
//get the number before that seprator character.
struct NumberAndSeperator_t
{
UINT* pNumber;
WCHAR SeperatorWChar;
};
const NumberAndSeperator_t c_ParseMap[] = {
{pNumberOfNewVoiceMails, L'/'},
{pNumberOfOldVoiceMails, L'('},
{pNumberOfUrgentNewVoiceMails, L'/'},
{pNumberOfUrgentOldVoiceMails, L')'},
};
for (UINT Index = 0; Index < ARRAYSIZE(c_ParseMap); Index++)
{
if (!(*pCurrent))
{
return E_FAIL;
}
pSeperator = wcschr(pCurrent, c_ParseMap[Index].SeperatorWChar);
if (pSeperator)
{
*pSeperator = 0;
}
*(c_ParseMap[Index].pNumber) = _wtol(pCurrent);
if (pSeperator)
{
pCurrent = ++pSeperator;
}
else
{
break;
}
}
return S_OK;
}
const DWORD ProxyServices_t::SubscriptionCollection_t::UNSUBSCRIBING = 0x00000001;
const DWORD ProxyServices_t::SubscriptionCollection_t::SUBSCRIBE_AFTER_REGISTER = 0x00000002;
const DWORD ProxyServices_t::SubscriptionCollection_t::SUBSCRIBE_AFTER_UNSUBSCRIBE = 0x00000004;
const DWORD ProxyServices_t::sc_SettingFlags = SEF_VOIP_SIP_SETTINGS | SEF_VOIP_VOICEMAIL_SETTINGS | SEF_VOIP_VOICEMAIL_NUMBER | SEF_VOIP_BACKUP_SIP_SETTINGS;
/*------------------------------------------------------------------------------
ProxyServices_t::ProxyServices_t
Constructor
------------------------------------------------------------------------------*/
ProxyServices_t::ProxyServices_t() :
m_cpActiveSIPProfile(NULL)
{
ResetStatusFlags();
}
/*------------------------------------------------------------------------------
ProxyServices_t::~ProxyServices_t
Destructor
------------------------------------------------------------------------------*/
ProxyServices_t::~ProxyServices_t()
{
ResetStatusFlags();
}
void
ProxyServices_t::ResetStatusFlags()
{
m_RegistrationStatusFlags = VOIP_NO_SIP_SETTINGS_BITMASK;
RegistrySetDWORD(
SN_VOIP_SERVERSTATUS_ROOT,
SN_VOIP_SERVERSTATUS_PATH,
SN_VOIP_SERVERSTATUS_VALUE,
m_RegistrationStatusFlags
);
m_SubscriptionStatusFlags = VOIP_NO_VOICEMAIL_SETTINGS_BITMASK;
RegistrySetDWORD(
SN_VOIP_VOICEMAILSTATUS_ROOT,
SN_VOIP_VOICEMAILSTATUS_PATH,
SN_VOIP_VOICEMAILSTATUS_VALUE,
m_SubscriptionStatusFlags
);
return;
}
/*------------------------------------------------------------------------------
ProxyServices_t::Initialize
Initialize this instance of the ProxyServices_t
Parameters:
pVoIPPhoneCanvas: [in] the pointer to VoIPPhoneCanvas_t object
Returns: none
------------------------------------------------------------------------------*/
void
ProxyServices_t::Initialize(
void
)
{
UpdateRegistrationStatus();
}
/*------------------------------------------------------------------------------
ProxyServices_t::StartServices
Starts proxy services (kicks off first registrations and subscriptions)
Returns: none
------------------------------------------------------------------------------*/
void
ProxyServices_t::StartServices()
{
m_cpActiveSIPProfile = NULL;
//force the setting change happen for the first time
OnSettingsChange(sc_SettingFlags);
//register as a listener to setting changes
GetApp()->GetSettings().RegisterHandler(
sc_SettingFlags,
static_cast<ISettingChangeHandler_t*>(this)
);
return;
}
/*------------------------------------------------------------------------------
ProxyServices_t::StopServices
Stops proxy services
Returns: none
------------------------------------------------------------------------------*/
void
ProxyServices_t::StopServices()
{
//unregister itself from settings_t first
(GetApp()->GetSettings()).UnregisterHandler(
static_cast<ISettingChangeHandler_t*>(this)
);
//unregister from the SIP proxies
UnregisterClientFromSIPProxy(&m_SIPProxyCollection);
//reset all the values in the collection
m_SIPProxyCollection.m_cpEnabledProfile = NULL;
m_SIPProxyCollection.m_cpToBeEnabledProfile = NULL;
m_SIPProxyCollection.m_Unregistering = false;
m_SIPProxyCollection.m_RegistrationState = RTCRS_NOT_REGISTERED;
UnregisterClientFromSIPProxy(&m_BackupProxyCollection);
//reset the values in the collection
m_BackupProxyCollection.m_cpEnabledProfile = NULL;
m_BackupProxyCollection.m_cpToBeEnabledProfile = NULL;
m_BackupProxyCollection.m_Unregistering = false;
m_BackupProxyCollection.m_RegistrationState = RTCRS_NOT_REGISTERED;
//unsubscribe from the voicemail servers
UnsubscribeFromVoicemailServer();
//reset all the values in the collection
m_VoicemailCollection.m_cpSubscribeProxy = NULL;
m_VoicemailCollection.m_cpSubscription = NULL;
m_VoicemailCollection.m_Flags = 0;
//reset the active SIP profile pointer
m_cpActiveSIPProfile = NULL;
//update voip status flags in statstore
UpdateRegistrationStatus();
return;
}
/*------------------------------------------------------------------------------
ProxyServices_t::NullOutRTCPointers
Null out all the RTC smart pointers
Returns: none
------------------------------------------------------------------------------*/
void
ProxyServices_t::NullOutRTCPointers()
{
//null out the active profile
PhoneAppUtilities_t::NullOutCOMPtr<IRTCProfile>(&m_cpActiveSIPProfile);
//null out all the collections profiles
PhoneAppUtilities_t::NullOutCOMPtr<IRTCProfile>(&m_SIPProxyCollection.m_cpEnabledProfile);
PhoneAppUtilities_t::NullOutCOMPtr<IRTCProfile>(&m_SIPProxyCollection.m_cpToBeEnabledProfile);
PhoneAppUtilities_t::NullOutCOMPtr<IRTCProfile>(&m_BackupProxyCollection.m_cpEnabledProfile);
PhoneAppUtilities_t::NullOutCOMPtr<IRTCProfile>(&m_BackupProxyCollection.m_cpToBeEnabledProfile);
PhoneAppUtilities_t::NullOutCOMPtr<IRTCProfile> (&m_VoicemailCollection.m_cpSubscribeProxy);
PhoneAppUtilities_t::NullOutCOMPtr<IRTCSubscription>(&m_VoicemailCollection.m_cpSubscription);
return;
}
/*------------------------------------------------------------------------------
ProxyServices_t::OnSettingsChange
implements the ISettingChangeHandler_t::OnSettingsChange
------------------------------------------------------------------------------*/
HRESULT
ProxyServices_t::OnSettingsChange(
DWORD SettingFlags
)
{
if (SettingFlags & SEF_VOIP_SIP_SETTINGS)
{
OnSIPSettingsChange( &m_SIPProxyCollection, Settings_t::SettingTypeSIPSettings );
//clear out the old user info from registry when main sip server updates
UpdateUserInfoInRegistry();
}
if (SettingFlags & SEF_VOIP_BACKUP_SIP_SETTINGS)
{
OnSIPSettingsChange( &m_BackupProxyCollection, Settings_t::SettingTypeBackupSIPSettings );
}
if (SettingFlags & SEF_VOIP_VOICEMAIL_SETTINGS)
{
OnVoicemailSettingsChange();
}
if (SettingFlags & SEF_VOIP_VOICEMAIL_NUMBER)
{
OnVoicemailNumberChange();
}
return S_OK;
}
/*------------------------------------------------------------------------------
ProxyServices_t::OnSIPSettingsChange
Handle new SIP settings (main server or backup server). Kick off a
new REGISTER to the server.
------------------------------------------------------------------------------*/
HRESULT
ProxyServices_t::OnSIPSettingsChange(
__in ProxyServices_t::ProfileCollection_t* pCollection,
__in Settings_t::SettingType_e SettingType
)
{
ASSERT(pCollection);
//if there is already a ToBeEnabled profile - we need to
//null it out first
if (pCollection->m_cpToBeEnabledProfile != NULL)
{
//CComPtr automatically releases its references
pCollection->m_cpToBeEnabledProfile = NULL;
}
HRESULT hr = GetApp()->GetSettings().GetRegistrationProfile(
SettingType,
&pCollection->m_cpToBeEnabledProfile
);
//if we couldn't get the new data, still unregister with the last server...
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to generate regisration profile - cannot continue -- error code = 0x%x", hr));
UnregisterClientFromSIPProxy(pCollection);
return hr;
}
//start the new REGISTER transaction
return RegisterClientWithSIPProxy(pCollection);
}
/*------------------------------------------------------------------------------
ProxyServices_t::RegisterClientWithSIPProxy
Start a new REGISTER transaction with a SIP proxy
------------------------------------------------------------------------------*/
HRESULT
ProxyServices_t::RegisterClientWithSIPProxy(
__in ProxyServices_t::ProfileCollection_t* pCollection
)
{
ASSERT(pCollection);
HRESULT hr = S_OK;
//if we already have an enabled profile - we need to first disable it before
//continuing
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -