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

📄 proxyservices.cpp

📁 一个WinCE6。0下的IP phone的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// 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 + -