/*
 *
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *      Implementation of Weave Device Manager, a common class
 *      that implements discovery, pairing and provisioning of Weave
 *      devices.
 *
 */

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include <time.h>

// This module uses Legacy WDM (V2)
#include <Weave/Profiles/data-management/Legacy/WdmManagedNamespace.h>

#include <Weave/Core/WeaveCore.h>
#include <Weave/Support/Base64.h>
#include <Weave/Support/CodeUtils.h>
#include <Weave/Core/WeaveEncoding.h>
#include <Weave/Profiles/WeaveProfiles.h>
#include <Weave/Profiles/common/CommonProfile.h>
#include <Weave/Profiles/echo/WeaveEcho.h>
#include <Weave/Profiles/network-provisioning/NetworkProvisioning.h>
#include <Weave/Profiles/service-provisioning/ServiceProvisioning.h>
#include <Weave/Profiles/fabric-provisioning/FabricProvisioning.h>
#include <Weave/Profiles/data-management/DataManagement.h>
#include <Weave/Profiles/device-description/DeviceDescription.h>
#include <Weave/Profiles/device-control/DeviceControl.h>
#include <Weave/Profiles/vendor/nestlabs/device-description/NestProductIdentifiers.hpp>
#include <Weave/Profiles/security/WeaveSecurity.h>
#include <Weave/Profiles/security/WeaveAccessToken.h>
#include <Weave/Profiles/token-pairing/TokenPairing.h>
#include "WeaveDeviceManager.h"
#include <Weave/Support/verhoeff/Verhoeff.h>
#include <Weave/Support/crypto/WeaveCrypto.h>
#include <Weave/Support/logging/WeaveLogging.h>
#include <Weave/Support/ErrorStr.h>
#include <Weave/Support/NestCerts.h>
#include <Weave/Support/TimeUtils.h>
#include <Weave/Profiles/vendor/nestlabs/alarm/WeaveAlarm.h>
#include <Weave/Profiles/vendor/nestlabs/dropcam-legacy-pairing/DropcamLegacyPairing.h>

namespace nl {
namespace Weave {
namespace DeviceManager {

using namespace nl::Weave::Encoding;
using namespace nl::Weave::Profiles;
using namespace nl::Weave::Profiles::DataManagement;
using namespace nl::Weave::Profiles::DeviceDescription;
using namespace nl::Weave::Profiles::NetworkProvisioning;
using namespace nl::Weave::Profiles::Security;
using namespace nl::Weave::Profiles::ServiceProvisioning;
using namespace nl::Weave::Profiles::TokenPairing;
using namespace nl::Weave::Profiles::Vendor::Nestlabs::DeviceDescription;
using namespace nl::Weave::Profiles::Vendor::Nestlabs::DropcamLegacyPairing;
using namespace nl::Weave::Profiles::Vendor::Nestlabs::Thermostat;
using namespace nl::Weave::TLV;

static bool IsProductWildcard(uint16_t productId);

static const uint32_t ENUMERATED_NODES_LIST_INITIAL_SIZE = 256;

WeaveDeviceManager *WeaveDeviceManager::sListeningDeviceMgr = NULL;

WeaveDeviceManager::WeaveDeviceManager()
{
    State = kState_NotInitialized;
}

WEAVE_ERROR WeaveDeviceManager::Init(WeaveExchangeManager *exchangeMgr, WeaveSecurityManager *securityMgr)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    AppState = NULL;
    mMessageLayer = exchangeMgr->MessageLayer;
    mSystemLayer = mMessageLayer->SystemLayer;
    mExchangeMgr = exchangeMgr;
    mSecurityMgr = securityMgr;
    mConState = kConnectionState_NotConnected;
    mDeviceCon = NULL;
    mOpState = kOpState_Idle;
    mCurReq = NULL;
    mCurReqMsg = NULL;
    mAppReqState = NULL;
    memset(&mOnComplete, 0, sizeof(mOnComplete));
    mOnError = NULL;
    mOnStart = NULL;
    mOnConnectionClosedFunc = NULL;
    mOnConnectionClosedAppReq = NULL;
    mDeviceAddr = IPAddress::Any;
    mAssistingDeviceAddr = IPAddress::Any;
    mDeviceIntf = INET_NULL_INTERFACEID;
    mAssistingDeviceIntf = INET_NULL_INTERFACEID;
    mDeviceId = kNodeIdNotSpecified;
    mAssistingDeviceId = kNodeIdNotSpecified;
    mConTimeout = secondsToMilliseconds(60);
    mConTryCount = 0;
    mSessionKeyId = WeaveKeyId::kNone;
    mEncType = kWeaveEncryptionType_None;
    mAuthType = kAuthType_None;
    mAssistingDeviceAuthType = kAuthType_None;
    mRemoteDeviceAuthType = kAuthType_None;
    mAuthKey = NULL;
    mAssistingDeviceAuthKey = NULL;
    mRemoteDeviceAuthKey = NULL;
    mAuthKeyLen = 0;
    mAssistingDeviceAuthKeyLen = 0;
    mRemoteDeviceAuthKeyLen = 0;
    mConMonitorTimeout = 0;
    mConMonitorInterval = 0;
    mConMonitorEnabled = false;
    mRemotePassiveRendezvousTimeout = 0;
    mRemotePassiveRendezvousInactivityTimeout = 0;
    mRemotePassiveRendezvousTimerIsRunning = false;
    mAutoReconnect = true;
    mRendezvousLinkLocal = true;
    mUseAccessToken = true;
    mConnectedToRemoteDevice = false;
    mIsUnsecuredConnectionListenerSet = false;
    mActiveLocale = NULL;
    mPingSize = 0;
    mTokenPairingCertificate = NULL;
    mTokenPairingCertificateLen = 0;
    mCameraNonce = NULL;
    mEnumeratedNodes = NULL;
    mEnumeratedNodesLen = 0;
    mEnumeratedNodesMaxLen = 0;

    // By default, rendezvous messages are sent to the IPv6 link-local, all-nodes multicast address.
    mRendezvousAddr = IPAddress::MakeIPv6Multicast(kIPv6MulticastScope_Link, kIPV6MulticastGroup_AllNodes);

    State = kState_Initialized;

    err = mDMClient.InitClient(this, exchangeMgr);
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "mDMClient.Init() failed: %s", ErrorStr(err));
    }

    return err;
}

WEAVE_ERROR WeaveDeviceManager::Shutdown()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    State = kState_NotInitialized;

    if (mCurReq != NULL)
    {
        mCurReq->Close();
        mCurReq = NULL;
    }

    if (mCurReqMsg != NULL)
    {
        PacketBuffer::Free(mCurReqMsg);
        mCurReqMsg = NULL;
    }

    if (mDeviceCon != NULL)
    {
        mDeviceCon->Abort();
        mDeviceCon = NULL;
    }

    if (mSystemLayer != NULL)
    {
        mSystemLayer->CancelTimer(HandleConnectionIdentifyTimeout, this);
        mSystemLayer->CancelTimer(RetrySession, this);
        mSystemLayer->CancelTimer(HandleDeviceEnumerationTimeout, this);
        CancelConnectionMonitorTimer();
        CancelRemotePassiveRendezvousTimer();
    }

    ClearAuthKey();

    if (mTokenPairingCertificate != NULL)
    {
        free(mTokenPairingCertificate);
        mTokenPairingCertificate = NULL;
        mTokenPairingCertificateLen = 0;
    }

    mSystemLayer = NULL;
    mMessageLayer = NULL;
    mExchangeMgr = NULL;
    mSecurityMgr = NULL;
    mConState = kConnectionState_NotConnected;
    mOpState = kOpState_Idle;
    mAppReqState = NULL;
    memset(&mOnComplete, 0, sizeof(mOnComplete));
    mOnError = NULL;
    mOnStart = NULL;

    return err;
}

WEAVE_ERROR WeaveDeviceManager::GetDeviceId(uint64_t& deviceId)
{
    deviceId = mDeviceId;
    return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveDeviceManager::GetDeviceAddress(IPAddress& deviceAddr)
{
    deviceAddr = mDeviceAddr;
    return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveDeviceManager::ConnectDevice(uint64_t deviceId, IPAddress deviceAddr,
        void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if ((mOpState != kOpState_Idle && mOpState != kOpState_RestartRemotePassiveRendezvous) ||
            mConState != kConnectionState_NotConnected)
        return WEAVE_ERROR_INCORRECT_STATE;

    mDeviceId = deviceId;
    mDeviceAddr = deviceAddr;
    mDeviceIntf = INET_NULL_INTERFACEID;
    mDeviceCriteria.Reset();

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;

    mAuthType = kAuthType_None;
    ClearAuthKey();

    mConMonitorEnabled = false;

    mOpState = kOpState_ConnectDevice;

    err = InitiateConnection();
    if (err != WEAVE_NO_ERROR)
        ClearOpState();

    return err;
}

WEAVE_ERROR WeaveDeviceManager::ConnectDevice(uint64_t deviceId, IPAddress deviceAddr, const char *pairingCode,
        void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if ((mOpState != kOpState_Idle && mOpState != kOpState_RestartRemotePassiveRendezvous) ||
            mConState != kConnectionState_NotConnected)
        return WEAVE_ERROR_INCORRECT_STATE;

    mDeviceId = deviceId;
    mDeviceAddr = deviceAddr;
    mDeviceIntf = INET_NULL_INTERFACEID;
    mDeviceCriteria.Reset();

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;

    mAuthType = kAuthType_PASEWithPairingCode;
    err = SaveAuthKey(pairingCode);
    SuccessOrExit(err);

    mConMonitorEnabled = false;

    mOpState = kOpState_ConnectDevice;
    err = InitiateConnection();

exit:
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::ConnectDevice(uint64_t deviceId, IPAddress deviceAddr, const uint8_t *accessToken, uint32_t accessTokenLen,
        void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if ((mOpState != kOpState_Idle && mOpState != kOpState_RestartRemotePassiveRendezvous) ||
        mConState != kConnectionState_NotConnected)
        return WEAVE_ERROR_INCORRECT_STATE;

    mDeviceId = deviceId;
    mDeviceAddr = deviceAddr;
    mDeviceIntf = INET_NULL_INTERFACEID;
    mDeviceCriteria.Reset();

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;

    if (mUseAccessToken && accessTokenLen != 0)
    {
        mAuthType = kAuthType_CASEWithAccessToken;
        err = SaveAuthKey(accessToken, accessTokenLen);
        SuccessOrExit(err);
    }
    else
    {
        mAuthType = kAuthType_None;
        ClearAuthKey();
    }

    mConMonitorEnabled = false;

    mOpState = kOpState_ConnectDevice;
    err = InitiateConnection();

exit:
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::StartDeviceEnumeration(void* appReqState, const IdentifyDeviceCriteria &deviceCriteria,
        DeviceEnumerationResponseFunct onResponse, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    VerifyOrExit(mOpState == kOpState_Idle, err = WEAVE_ERROR_INCORRECT_STATE);

    mDeviceCriteria = deviceCriteria;

    mAppReqState = appReqState;
    mOnComplete.DeviceEnumeration = onResponse;
    mOnError = onError;

    mOpState = kOpState_EnumerateDevices;

    err = InitiateDeviceEnumeration();

exit:
    if (err != WEAVE_NO_ERROR)
    {
        ClearOpState();
    }

    return err;
}

WEAVE_ERROR WeaveDeviceManager::InitiateDeviceEnumeration()
{
    WEAVE_ERROR             err     = WEAVE_NO_ERROR;
    PacketBuffer*           msgBuf  = NULL;
    IdentifyRequestMessage  reqMsg;
    uint16_t                sendFlags;

    VerifyOrExit(kOpState_EnumerateDevices == mOpState, err = WEAVE_ERROR_INCORRECT_STATE);

    // Refresh the message layer endpoints to cope with changes in network interface status
    // (e.g. new addresses being assigned).
    err = mMessageLayer->RefreshEndpoints();
    SuccessOrExit(err);

    // Form an Identify device request containing the device criteria specified by the application.
    reqMsg.TargetFabricId = mDeviceCriteria.TargetFabricId;
    reqMsg.TargetModes = mDeviceCriteria.TargetModes;
    reqMsg.TargetVendorId = mDeviceCriteria.TargetVendorId;

    if (mDeviceCriteria.TargetVendorId == kWeaveVendor_NestLabs && IsProductWildcard(mDeviceCriteria.TargetProductId))
    {
        reqMsg.TargetProductId = 0xFFFF;
    }
    else
    {
        reqMsg.TargetProductId = mDeviceCriteria.TargetProductId;
    }

    // Encode the Identify device request message.
    msgBuf = PacketBuffer::New();
    VerifyOrExit(NULL != msgBuf, err = WEAVE_ERROR_NO_MEMORY);

    err = reqMsg.Encode(msgBuf);
    SuccessOrExit(err);

    // Construct an exchange context if necessary. Otherwise, reuse existing multicast ExchangeContext.
    if (NULL == mCurReq)
    {
        mCurReq = mExchangeMgr->NewContext(kAnyNodeId, this);
        VerifyOrExit(NULL != mCurReq, err = WEAVE_ERROR_NO_MEMORY);
        mCurReq->OnMessageReceived = HandleDeviceEnumerationIdentifyResponse;
    }

    WeaveLogProgress(DeviceManager, "Sending IdentifyRequest to enumerate devices");

    // Send the Identify message.
    //
    // If the 'enumerate-devices link-local' option is enabled, AND the message layer is not bound to
    // a specific local IPv6 address, THEN ...
    //
    // Send the multicast identify request from the host's link-local addresses, rather than
    // from its site-local or global addresses. This results in the device responding using its
    // link-local address, which in turn causes the device manager to connect to the device using the
    // link-local address. This is all to work around a bug in OS X/iOS that prevents those systems
    // from communicating on any site-local IPv6 subnets when in the presence of a router that is
    // advertising a default route to the Internet at large. (See DOLO-2479).
    //
    // We disable the 'enumerate-devices link-local' feature when the message layer is bound to a specific
    // address because binding to a specific address is generally used when testing the device manager
    // and a mock-device running on a single host with a single interface.  In this case multicasting
    // using the interface's single link-local address doesn't work.
    //
    sendFlags = (mRendezvousLinkLocal && !mMessageLayer->IsBoundToLocalIPv6Address())
            ? ExchangeContext::kSendFlag_MulticastFromLinkLocal
            : 0;
    err = mCurReq->SendMessage(kWeaveProfile_DeviceDescription, kMessageType_IdentifyRequest, msgBuf, sendFlags);
    msgBuf = NULL;

    if (err == System::MapErrorPOSIX(ENETUNREACH) || err == System::MapErrorPOSIX(EHOSTUNREACH) ||
        err == System::MapErrorPOSIX(EPIPE))
    {
        err = WEAVE_NO_ERROR;
    }
    SuccessOrExit(err);

    // Arm the retry timer.
    err = mSystemLayer->StartTimer(kEnumerateDevicesRetryInterval, HandleDeviceEnumerationTimeout, this);
    SuccessOrExit(err);

exit:
    if (msgBuf != NULL)
    {
        PacketBuffer::Free(msgBuf);
    }

    return err;
}

void WeaveDeviceManager::StopDeviceEnumeration()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    VerifyOrExit(kOpState_EnumerateDevices == mOpState, err = WEAVE_ERROR_INCORRECT_STATE);

    mSystemLayer->CancelTimer(HandleDeviceEnumerationTimeout, this);

    if (mEnumeratedNodes)
    {
        free(mEnumeratedNodes);
    }

    mEnumeratedNodes = NULL;
    mEnumeratedNodesLen = 0;
    mEnumeratedNodesMaxLen = 0;

    ClearOpState();

exit:
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "StopDeviceEnumeration failure: err = %d", err);
    }
}


WEAVE_ERROR WeaveDeviceManager::RendezvousDevice(const IdentifyDeviceCriteria &deviceCriteria,
        void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (mOpState != kOpState_Idle || mConState != kConnectionState_NotConnected)
        return WEAVE_ERROR_INCORRECT_STATE;

    mDeviceId = deviceCriteria.TargetDeviceId;
    mDeviceAddr = mRendezvousAddr;
    mDeviceIntf = INET_NULL_INTERFACEID;
    mDeviceCriteria = deviceCriteria;

    mAuthType = kAuthType_None;
    ClearAuthKey();

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;

    mConMonitorEnabled = false;

    mOpState = kOpState_RendezvousDevice;

    err = InitiateConnection();
    if (err != WEAVE_NO_ERROR)
        ClearOpState();

    return err;
}

WEAVE_ERROR WeaveDeviceManager::RendezvousDevice(const char *pairingCode, void* appReqState,
        CompleteFunct onComplete, ErrorFunct onError)
{
    IdentifyDeviceCriteria deviceCriteria;
    deviceCriteria.TargetFabricId = kTargetFabricId_Any;
    deviceCriteria.TargetModes = kTargetDeviceMode_UserSelectedMode;
    deviceCriteria.TargetVendorId = kWeaveVendor_NestLabs;
    deviceCriteria.TargetProductId = 5; // Topaz

    return RendezvousDevice(pairingCode, deviceCriteria, appReqState, onComplete, onError);
}

WEAVE_ERROR WeaveDeviceManager::RendezvousDevice(const char *pairingCode, const IdentifyDeviceCriteria &deviceCriteria,
        void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (mOpState != kOpState_Idle || mConState != kConnectionState_NotConnected)
        return WEAVE_ERROR_INCORRECT_STATE;

    mDeviceId = deviceCriteria.TargetDeviceId;
    mDeviceAddr = mRendezvousAddr;
    mDeviceIntf = INET_NULL_INTERFACEID;
    mDeviceCriteria = deviceCriteria;

    mAuthType = kAuthType_PASEWithPairingCode;
    err = SaveAuthKey(pairingCode);
    SuccessOrExit(err);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;

    mConMonitorEnabled = false;

    mOpState = kOpState_RendezvousDevice;

    err = InitiateConnection();

exit:
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::RendezvousDevice(const uint8_t *accessToken, uint32_t accessTokenLen,
        const IdentifyDeviceCriteria &deviceCriteria,
        void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (mOpState != kOpState_Idle || mConState != kConnectionState_NotConnected)
        return WEAVE_ERROR_INCORRECT_STATE;

    mDeviceId = deviceCriteria.TargetDeviceId;
    mDeviceAddr = mRendezvousAddr;
    mDeviceIntf = INET_NULL_INTERFACEID;
    mDeviceCriteria = deviceCriteria;

    if (mUseAccessToken && accessTokenLen != 0)
    {
        mAuthType = kAuthType_CASEWithAccessToken;
        err = SaveAuthKey(accessToken, accessTokenLen);
        SuccessOrExit(err);
    }
    else
    {
        mAuthType = kAuthType_None;
        ClearAuthKey();
    }

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;

    mConMonitorEnabled = false;

    mOpState = kOpState_RendezvousDevice;

    err = InitiateConnection();

exit:
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::PassiveRendezvousDevice(void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (mOpState != kOpState_Idle || mConState != kConnectionState_NotConnected ||
            sListeningDeviceMgr != NULL)
    {
        err = WEAVE_ERROR_INCORRECT_STATE;
        ExitNow();
    }

    mDeviceId = kAnyNodeId;
    mDeviceAddr = IPAddress::Any;
    mDeviceIntf = INET_NULL_INTERFACEID;

    mAuthType = kAuthType_None;
    ClearAuthKey();

    mConMonitorEnabled = false;

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;

    err = SetUnsecuredConnectionHandler();
    SuccessOrExit(err);

    mOpState = kOpState_PassiveRendezvousDevice;
    mConState = kConnectionState_WaitDeviceConnect;

    // Setup pointer to device manager instance is currently doing a passive rendezvous.  Because the
    // device connects to the device manager in the passive rendezvous case there can only be one
    // device manager instance in this mode at a time.
    sListeningDeviceMgr = this;

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceManager::PassiveRendezvousDevice(const char *pairingCode, void* appReqState, CompleteFunct onComplete, ErrorFunct onError, StartFunct onStart)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (mOpState != kOpState_Idle || mConState != kConnectionState_NotConnected || sListeningDeviceMgr != NULL)
        return WEAVE_ERROR_INCORRECT_STATE;

    mDeviceId = kAnyNodeId;
    mDeviceAddr = IPAddress::Any;
    mDeviceIntf = INET_NULL_INTERFACEID;

    mAuthType = kAuthType_PASEWithPairingCode;
    err = SaveAuthKey(pairingCode);
    SuccessOrExit(err);

    mConMonitorEnabled = false;

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOnStart = onStart;

    err = SetUnsecuredConnectionHandler();
    SuccessOrExit(err);

    mOpState = kOpState_PassiveRendezvousDevice;
    mConState = kConnectionState_WaitDeviceConnect;

    // Setup pointer to device manager instance is currently doing a passive rendezvous.  Because the
    // device connects to the device manager in the passive rendezvous case there can only be one
    // device manager instance in this mode at a time.
    sListeningDeviceMgr = this;

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceManager::PassiveRendezvousDevice(const uint8_t *accessToken, uint32_t accessTokenLen, void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (mOpState != kOpState_Idle || mConState != kConnectionState_NotConnected || sListeningDeviceMgr != NULL)
        return WEAVE_ERROR_INCORRECT_STATE;

    mDeviceId = kAnyNodeId;
    mDeviceAddr = IPAddress::Any;
    mDeviceIntf = INET_NULL_INTERFACEID;

    if (mUseAccessToken && accessTokenLen != 0)
    {
        mAuthType = kAuthType_CASEWithAccessToken;
        err = SaveAuthKey(accessToken, accessTokenLen);
        SuccessOrExit(err);
    }
    else
    {
        mAuthType = kAuthType_None;
        ClearAuthKey();
    }

    mConMonitorEnabled = false;

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;

    err = SetUnsecuredConnectionHandler();
    SuccessOrExit(err);

    mConState = kConnectionState_WaitDeviceConnect;
    mOpState = kOpState_PassiveRendezvousDevice;

    // Setup pointer to device manager instance is currently doing a passive rendezvous.  Because the
    // device connects to the device manager in the passive rendezvous case there can only be one
    // device manager instance in this mode at a time.
    sListeningDeviceMgr = this;

exit:
    return err;
}

#if CONFIG_NETWORK_LAYER_BLE
WEAVE_ERROR WeaveDeviceManager::ConnectBle(BLE_CONNECTION_OBJECT connObj,
                                           void *appReqState, CompleteFunct onComplete, ErrorFunct onError, bool autoClose)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (mOpState != kOpState_Idle || mConState != kConnectionState_NotConnected ||
            sListeningDeviceMgr != NULL)
    {
        err = WEAVE_ERROR_INCORRECT_STATE;
        ExitNow();
    }

    mAuthType = kAuthType_None;
    ClearAuthKey();

    err = InitiateBleConnection(connObj, appReqState, onComplete, onError, autoClose);

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceManager::ConnectBle(BLE_CONNECTION_OBJECT connObj, const char *pairingCode,
                                           void *appReqState, CompleteFunct onComplete, ErrorFunct onError, bool autoClose)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (mOpState != kOpState_Idle || mConState != kConnectionState_NotConnected ||
            sListeningDeviceMgr != NULL)
    {
        err = WEAVE_ERROR_INCORRECT_STATE;
        ExitNow();
    }

    mAuthType = kAuthType_PASEWithPairingCode;
    err = SaveAuthKey(pairingCode);
    SuccessOrExit(err);

    err = InitiateBleConnection(connObj, appReqState, onComplete, onError, autoClose);

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceManager::ConnectBle(BLE_CONNECTION_OBJECT connObj, const uint8_t *accessToken,
                                           uint32_t accessTokenLen, void *appReqState, CompleteFunct onComplete, ErrorFunct onError, bool autoClose)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (mOpState != kOpState_Idle || mConState != kConnectionState_NotConnected ||
            sListeningDeviceMgr != NULL)
    {
        err = WEAVE_ERROR_INCORRECT_STATE;
        ExitNow();
    }

    if (mUseAccessToken && accessTokenLen != 0)
    {
        mAuthType = kAuthType_CASEWithAccessToken;
        err = SaveAuthKey(accessToken, accessTokenLen);
        SuccessOrExit(err);
    }
    else
    {
        mAuthType = kAuthType_None;
        ClearAuthKey();
    }

    err = InitiateBleConnection(connObj, appReqState, onComplete, onError, autoClose);

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceManager::InitiateBleConnection(BLE_CONNECTION_OBJECT connObj,
                                                      void *appReqState, CompleteFunct onComplete, ErrorFunct onError, bool autoClose)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveConnection *bleCon;

    mDeviceId = kAnyNodeId;
    mDeviceAddr = IPAddress::Any;
    mDeviceIntf = INET_NULL_INTERFACEID;
    mDeviceCriteria.Reset();

    mConMonitorEnabled = false;

    // We can't auto-reconnect via BLE, since BLE connection management occurs outside of Weave.
    mAutoReconnect = false;

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;

    mOpState = kOpState_InitializeBleConnection;
    mConState = kConnectionState_ConnectDevice;

    // Setup pointer to listening device manager. This lets us reuse the code in static HandleConnectionReceived
    // callback also used by PassiveRendezvous.
    sListeningDeviceMgr = this;

    // Bind BLE connection object to new WeaveConnection.
    bleCon = mMessageLayer->NewConnection();
    VerifyOrExit(bleCon != NULL, err = WEAVE_ERROR_TOO_MANY_CONNECTIONS);

    bleCon->AppState = this;
    bleCon->OnConnectionComplete = HandleConnectionComplete;
    bleCon->OnConnectionClosed = HandleConnectionClosed;

    err = bleCon->ConnectBle(connObj, kWeaveAuthMode_Unauthenticated, autoClose);
    SuccessOrExit(err);

exit:
    if (err != WEAVE_NO_ERROR)
    {
        ClearOpState();
        mConState = kConnectionState_NotConnected;
        sListeningDeviceMgr = NULL;
    }

    return err;
}

#endif /* CONFIG_NETWORK_LAYER_BLE */

WEAVE_ERROR WeaveDeviceManager::RemotePassiveRendezvous(IPAddress rendezvousDeviceAddr, const uint8_t *accessToken,
        uint32_t accessTokenLen, const uint16_t rendezvousTimeoutSec, const uint16_t inactivityTimeoutSec,
        void *appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Save remote device authentication info, including auth type. Can't just SaveAuthKey() here, as this would
    // clear the auth key for the assisting device. We must preserve this key in case the Device Manager needs to
    // reconnect to the assisting device before it can send the RPR request.
    err = SaveRemoteDeviceAuthInfo(kAuthType_CASEWithAccessToken, (const char *)accessToken, accessTokenLen);
    SuccessOrExit(err);

    err = DoRemotePassiveRendezvous(rendezvousDeviceAddr, rendezvousTimeoutSec, inactivityTimeoutSec, appReqState, onComplete,
            onError);

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceManager::RemotePassiveRendezvous(IPAddress rendezvousDeviceAddr, const char *pairingCode,
        const uint16_t rendezvousTimeoutSec, const uint16_t inactivityTimeoutSec, void *appReqState,
        CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Save remote device authentication info, including auth type. Can't just SaveAuthKey() here, as this would
    // clear the auth key for the assisting device. We must preserve this key in case the Device Manager needs to
    // reconnect to the assisting device before it can send the RPR request.
    err = SaveRemoteDeviceAuthInfo(kAuthType_PASEWithPairingCode, pairingCode, 0);
    SuccessOrExit(err);

    err = DoRemotePassiveRendezvous(rendezvousDeviceAddr, rendezvousTimeoutSec, inactivityTimeoutSec, appReqState, onComplete,
            onError);

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceManager::RemotePassiveRendezvous(IPAddress rendezvousDeviceAddr,
        const uint16_t rendezvousTimeoutSec, const uint16_t inactivityTimeoutSec, void *appReqState,
        CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Save remote device authentication info, including auth type. Can't just SaveAuthKey() here, as this would
    // clear the auth key for the assisting device. We must preserve this key in case the Device Manager needs to
    // reconnect to the assisting device before it can send the RPR request.
    err = SaveRemoteDeviceAuthInfo(kAuthType_None, NULL, 0);
    SuccessOrExit(err);

    err = DoRemotePassiveRendezvous(rendezvousDeviceAddr, rendezvousTimeoutSec, inactivityTimeoutSec, appReqState, onComplete,
            onError);

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceManager::DoRemotePassiveRendezvous(IPAddress rendezvousDeviceAddr,
        const uint16_t rendezvousTimeoutSec, const uint16_t inactivityTimeoutSec, void *appReqState,
        CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;
    uint8_t*        p;

#if WEAVE_DETAIL_LOGGING
    char rendezvousDeviceAddrStr[48]; // max(INET6_ADDRSTRLEN, 40) - see inet_ntop (POSIX), ip6addr_ntoa (LwIP)

    WeaveLogDetail(DeviceManager, "RemotePassiveRendezvous (");
    WeaveLogDetail(DeviceManager, "   rendezvousDeviceAddr = %s,", rendezvousDeviceAddr.ToString(
            rendezvousDeviceAddrStr, 48));
    WeaveLogDetail(DeviceManager, "   rendezvousTimeoutSec   = %u,", rendezvousTimeoutSec);
    WeaveLogDetail(DeviceManager, "   inactivityTimeoutSec   = %u )", inactivityTimeoutSec);
#endif // WEAVE_DETAIL_LOGGING

    // Ensure DM is in the correct state to perform a Remote Passive Rendezvous.
    if (mOpState != kOpState_Idle || mConMonitorEnabled == true)
    {
        if (mConMonitorEnabled == true)
        {
            WeaveLogError(DeviceManager, "Must disable ConnectionMonitor before RPR");
        }
        else
        {
            WeaveLogError(DeviceManager, "RPR failed, other operation in progress, opState = %d", mOpState);
        }
        err = WEAVE_ERROR_INCORRECT_STATE;
        ExitNow();
    }
    else if (onComplete == NULL || onError == NULL)
    {
        if (onComplete == NULL)
        {
            WeaveLogError(DeviceManager, "null onComplete");
        }
        else
        {
            WeaveLogError(DeviceManager, "null onError");
        }
        err = WEAVE_ERROR_INVALID_ARGUMENT;
        ExitNow();
    }

    // Save rendezvous and inactivity timeout values, in case we need to reestablish RPR with assisting device and
    // pack these values into another RPR request.
    mRemotePassiveRendezvousTimeout = rendezvousTimeoutSec;
    mRemotePassiveRendezvousInactivityTimeout = inactivityTimeoutSec;
    mRemoteDeviceAddr = rendezvousDeviceAddr;

    // Construct Remote Passive Rendezvous Request.
    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    p = msgBuf->Start();
    LittleEndian::Write16(p, rendezvousTimeoutSec);
    LittleEndian::Write16(p, inactivityTimeoutSec);

    // Encode filter address in standard big-endian, big-wordian (sic) form.
    rendezvousDeviceAddr.WriteAddress(p);

    // Set message buffer data length.
    msgBuf->SetDataLength(DeviceControl::kMessageLength_RemotePassiveRendezvous);

    // Hook DM return callbacks, app state, and OpState.
    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_RemotePassiveRendezvousRequest;

    // Start client-side timer for rendezvous with remote host.
    if (mRemotePassiveRendezvousTimerIsRunning == false) // In retry case, don't restart timer
    {
        err = StartRemotePassiveRendezvousTimer();
        SuccessOrExit(err);
    }

    WeaveLogProgress(DeviceManager, "Sending RPR request...");
    err = SendRequest(kWeaveProfile_DeviceControl, DeviceControl::kMsgType_RemotePassiveRendezvous,
            msgBuf, HandleDeviceControlResponse);
    msgBuf = NULL;
    SuccessOrExit(err);

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);

    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "RemotePassiveRendezvous failed, err = %d", err);

        // Cancel RemotePassiveRendezvous timer, clear OpState and free saved copy of pairing code, leaving
        // connection to assisting device open.
        CancelRemotePassiveRendezvous();
    }

    return err;
}

WEAVE_ERROR WeaveDeviceManager::SaveAssistingDeviceConnectionInfo()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Save info needed to reconnect to assisting device.
    mAssistingDeviceAddr = mDeviceAddr;
    mAssistingDeviceIntf = mDeviceIntf;
    mAssistingDeviceId = mDeviceId;

    // Clear previous copy of assisting device auth key, if any.
    ClearAuthKey(mAssistingDeviceAuthKey, mAssistingDeviceAuthKeyLen);

    // Save copy of info needed to reauthenticate with assisting device from scratch.
    mAssistingDeviceAuthType = mAuthType;
    mAssistingDeviceAuthKeyLen = mAuthKeyLen;

    mAssistingDeviceAuthKey = malloc(mAuthKeyLen);
    VerifyOrExit(mAssistingDeviceAuthKey != NULL, err = WEAVE_ERROR_NO_MEMORY);
    memcpy(mAssistingDeviceAuthKey, mAuthKey, mAuthKeyLen);

exit:
    return err;
}

void WeaveDeviceManager::RestoreAssistingDeviceAddressInfo()
{
    // Restore info needed to reconnect to assisting device.
    mDeviceAddr = mAssistingDeviceAddr;
    mDeviceIntf = mAssistingDeviceIntf;
    mDeviceId = mAssistingDeviceId;
}

WEAVE_ERROR WeaveDeviceManager::RestoreAssistingDeviceAuthInfo()
{
    // Restore info needed to reestablish secure session with assisting device from scratch
    mAuthType = mAssistingDeviceAuthType;

    // SaveAuthKey securely clears existing mAuthKey, if any
    return SaveAuthKey(static_cast<const uint8_t *>(mAssistingDeviceAuthKey), mAssistingDeviceAuthKeyLen);
}

void WeaveDeviceManager::ResetConnectionInfo()
{
    mSessionKeyId = WeaveKeyId::kNone;
    mEncType = kWeaveEncryptionType_None;
    mDeviceCon->PeerNodeId = kNodeIdNotSpecified;
    mDeviceId = kNodeIdNotSpecified;
    mDeviceAddr = IPAddress::Any;
    mDeviceIntf = INET_NULL_INTERFACEID;
}

void WeaveDeviceManager::HandleAssistingDeviceReconnectCompleteEntry(WeaveDeviceManager *devMgr, void *appReqState)
{
    devMgr->HandleRemotePassiveRendezvousReconnectComplete();
}

void WeaveDeviceManager::HandleRemotePassiveRendezvousReconnectComplete()
{
    WEAVE_ERROR err = RemotePassiveRendezvous(mRemoteDeviceAddr, static_cast<const char*>(mRemoteDeviceAuthKey),
            mRemotePassiveRendezvousTimeout, mRemotePassiveRendezvousInactivityTimeout,
            mAppReqState, mOnRemotePassiveRendezvousComplete, mOnError);

    if (err != WEAVE_NO_ERROR)
    {
        mOnError(this, mAppReqState, err, NULL);
    }
}

WEAVE_ERROR WeaveDeviceManager::StartReconnectToAssistingDevice()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Save application's OnComplete callback. mOnComplete will be temporarily overwritten by arg to ConnectDevice()
    // below while the DM attempts to reconnect to the assisting device.
    mOnRemotePassiveRendezvousComplete = mOnComplete.General;

    // Restore assisting device address info for use by common ConnectDevice() code path.
    RestoreAssistingDeviceAddressInfo();

    // Restore auth info for assisting device so we attempt re-authentication from scratch.
    err = RestoreAssistingDeviceAuthInfo();
    SuccessOrExit(err);

    // Reconnect to assisting device, using same auth type and credentials with which we last connected to it.
    switch (mAuthType)
    {
    case kAuthType_PASEWithPairingCode:
        WeaveLogProgress(DeviceManager, "Reconnecting to assisting device with PASE auth");
        err = ConnectDevice(mDeviceId, mDeviceAddr, static_cast<const char *>(mAuthKey), mAppReqState,
                HandleAssistingDeviceReconnectCompleteEntry, mOnError);
        break;

    case kAuthType_CASEWithAccessToken:
        WeaveLogProgress(DeviceManager, "Reconnecting to assisting device with CASE auth");
        err = ConnectDevice(mDeviceId, mDeviceAddr, static_cast<const uint8_t *>(mAuthKey), mAuthKeyLen, mAppReqState,
                HandleAssistingDeviceReconnectCompleteEntry, mOnError);
        break;

    case kAuthType_None:
        WeaveLogProgress(DeviceManager, "Reconnecting to assisting device without authentication");
        err = ConnectDevice(mDeviceId, mDeviceAddr, mAppReqState,
                HandleAssistingDeviceReconnectCompleteEntry, mOnError);
        break;

    default:
        err = WEAVE_ERROR_INCORRECT_STATE;
        break;
    }

exit:
    return err;
}

void WeaveDeviceManager::CancelRemotePassiveRendezvous()
{
    // Clear any OpState set by Remote Passive Rendezvous process.
    ClearOpState();

    // Clear dynamically-allocated copy of assisting device auth key.
    ClearAuthKey(mAssistingDeviceAuthKey, mAssistingDeviceAuthKeyLen);

    // Clear dynamically-allocated remote device auth key.
    ClearAuthKey(mRemoteDeviceAuthKey, mRemoteDeviceAuthKeyLen);

    // Cancel Remote Passive Rendezvous timer if it's running.
    CancelRemotePassiveRendezvousTimer();
}

WEAVE_ERROR WeaveDeviceManager::ReconnectDevice(void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (mOpState != kOpState_Idle || mConState != kConnectionState_NotConnected)
        return WEAVE_ERROR_INCORRECT_STATE;

    if (mDeviceId == kNodeIdNotSpecified || mDeviceAddr == IPAddress::Any)
        return WEAVE_ERROR_INCORRECT_STATE;

    mDeviceCriteria.Reset();

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;

    mOpState = kOpState_ReconnectDevice;

    err = InitiateConnection();
    if (err != WEAVE_NO_ERROR)
        ClearOpState();

    return err;
}

WEAVE_ERROR WeaveDeviceManager::EnableConnectionMonitor(uint16_t interval, uint16_t timeout, void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;
    uint8_t*        p;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    p = msgBuf->Start();
    LittleEndian::Write16(p, timeout);
    LittleEndian::Write16(p, interval);
    msgBuf->SetDataLength(4);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_EnableConnectionMonitor;

    CancelConnectionMonitorTimer();
    mConMonitorEnabled = false;
    mConMonitorInterval = interval;
    mConMonitorTimeout = timeout;

    err = SendRequest(kWeaveProfile_DeviceControl, DeviceControl::kMsgType_EnableConnectionMonitor, msgBuf,
            HandleDeviceControlResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::DisableConnectionMonitor(void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    CancelConnectionMonitorTimer();
    mConMonitorEnabled = false;

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_DisableConnectionMonitor;

    err = SendRequest(kWeaveProfile_DeviceControl, DeviceControl::kMsgType_DisableConnectionMonitor, msgBuf,
            HandleDeviceControlResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

void WeaveDeviceManager::Close()
{
    Close(false);
}

void WeaveDeviceManager::Close(bool graceful)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Cancel outstanding Remote Passive Rendezvous attempt, if any, and clear associated state.
    CancelRemotePassiveRendezvous();

    // Close connection to device, if any, and clear associated state.
    CloseDeviceConnection(graceful);

    // Cancel our unsecured listen, if enabled.
    err = ClearUnsecuredConnectionHandler();
    if (err != WEAVE_NO_ERROR)
        WeaveLogProgress(DeviceControl, "ClearUnsecuredConnectionListener failed, err = %d", err);

    // If this instance of the device manager was performing a passive rendezvous, clear any associated state.
    if (sListeningDeviceMgr == this)
        sListeningDeviceMgr = NULL;
}

void WeaveDeviceManager::CloseDeviceConnection()
{
    CloseDeviceConnection(false);
}

void WeaveDeviceManager::CloseDeviceConnection(bool graceful)
{
    WeaveLogProgress(DeviceManager, "Closing connection to device");

    // Clear the current operation state.  NOTE that calling CloseDeviceConnection() with an operation outstanding
    // results in the operation's completion functions never being called.
    ClearOpState();

    // Close the connection to the device.
    if (mDeviceCon != NULL)
    {
        if (graceful)
        {
            mDeviceCon->Close();
        }
        else
        {
            mDeviceCon->OnConnectionComplete = NULL;
            mDeviceCon->OnConnectionClosed = NULL;
            mDeviceCon->Abort();
            mDeviceCon = NULL;
        }
    }

    // Cancel any outstanding timers.
    mSystemLayer->CancelTimer(HandleConnectionIdentifyTimeout, this);
    mSystemLayer->CancelTimer(RetrySession, this);
    CancelConnectionMonitorTimer();

    // Reset various state.
    //
    // NOTE: The following are expressly not reset when Close() is called to
    // allow internal callers to continue to use these values during clean-up
    // and error reporting.
    //
    //     mDeviceId/mDeviceAddr/mDeviceIntf
    //     mRendezvousAddr
    //     mAuthType/mAuthKey/mAuthKeyLen
    //     mOpTimeout
    //     mAutoReconnect
    //     mOnComplete/mOnError
    //     mAppReqState
    //     mConMonitorEnabled/mConMonitorInterval/mConMonitorTimeout
    //
    //
    mConState = kConnectionState_NotConnected;
    mConTryCount = 0;
    mSessionKeyId = WeaveKeyId::kNone;
    mEncType = kWeaveEncryptionType_None;
    mConnectedToRemoteDevice = false;
    if (mTokenPairingCertificate != NULL)
    {
        free(mTokenPairingCertificate);
        mTokenPairingCertificate = NULL;
        mTokenPairingCertificateLen = 0;
    }

}

bool WeaveDeviceManager::IsConnected() const
{
    return mConState == kConnectionState_Connected;
}

void WeaveDeviceManager::SetConnectionClosedCallback(ConnectionClosedFunc onConnecionClosedFunc, void *onConnecionClosedAppReq)
{
    mOnConnectionClosedFunc = onConnecionClosedFunc;
    mOnConnectionClosedAppReq = onConnecionClosedAppReq;
}

WEAVE_ERROR WeaveDeviceManager::IdentifyDevice(void* appReqState, IdentifyDeviceCompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR             err     = WEAVE_NO_ERROR;
    PacketBuffer*           msgBuf  = NULL;
    IdentifyRequestMessage  reqMsg;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    reqMsg.TargetFabricId = kTargetFabricId_Any;
    reqMsg.TargetModes = kTargetDeviceMode_Any;
    reqMsg.TargetVendorId = 0xFFFF; // Any vendor
    reqMsg.TargetProductId = 0xFFFF; // Any product

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    err = reqMsg.Encode(msgBuf);
    SuccessOrExit(err);

    mAppReqState = appReqState;
    mOnComplete.IdentifyDevice = onComplete;
    mOnError = onError;
    mOpState = kOpState_IdentifyDevice;

    err = SendRequest(kWeaveProfile_DeviceDescription, DeviceDescription::kMessageType_IdentifyRequest,
            msgBuf, HandleIdentifyDeviceResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::PairToken(const uint8_t *pairingToken, uint32_t pairingTokenLen, void* appReqState, PairTokenCompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;
    uint8_t*        p;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    p = msgBuf->Start();
    VerifyOrExit(msgBuf->AvailableDataLength() > pairingTokenLen, err = WEAVE_ERROR_MESSAGE_TOO_LONG);
    memcpy(p, pairingToken, pairingTokenLen);
    msgBuf->SetDataLength(pairingTokenLen);

    mAppReqState = appReqState;
    mOnComplete.PairToken = onComplete;
    mOnError = onError;
    mOpState = kOpState_PairToken;

    if (mTokenPairingCertificate != NULL)
    {
        WeaveLogError(DeviceManager, "% TokenPairingCertificate not NULL.", __FUNCTION__);
        mTokenPairingCertificate = NULL;
        mTokenPairingCertificateLen = 0;
    }

    err = SendRequest(kWeaveProfile_TokenPairing, TokenPairing::kMsgType_PairTokenRequest,
            msgBuf, HandlePairTokenResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::UnpairToken(void* appReqState, UnpairTokenCompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    mAppReqState = appReqState;
    mOnComplete.UnpairToken = onComplete;
    mOnError = onError;
    mOpState = kOpState_UnpairToken;

    err = SendRequest(kWeaveProfile_TokenPairing, TokenPairing::kMsgType_UnpairTokenRequest,
            msgBuf, HandleUnpairTokenResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::ScanNetworks(NetworkType networkType, void* appReqState,
        NetworkScanCompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    Put8(msgBuf->Start(), (uint8_t) networkType);
    msgBuf->SetDataLength(1);

    mAppReqState = appReqState;
    mOnComplete.ScanNetworks = onComplete;
    mOnError = onError;
    mOpState = kOpState_ScanNetworks;

    err = SendRequest(kWeaveProfile_NetworkProvisioning, NetworkProvisioning::kMsgType_ScanNetworks, msgBuf,
            HandleNetworkProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::AddNetwork(const NetworkInfo *netInfo, void* appReqState,
        AddNetworkCompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;
    TLVWriter       writer;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    writer.Init(msgBuf);

    err = netInfo->Encode(writer, NetworkInfo::kEncodeFlag_All);
    SuccessOrExit(err);

    err = writer.Finalize();
    SuccessOrExit(err);

    mAppReqState = appReqState;
    mOnComplete.AddNetwork = onComplete;
    mOnError = onError;
    mOpState = kOpState_AddNetwork;

    err = SendRequest(kWeaveProfile_NetworkProvisioning, kMsgType_AddNetwork, msgBuf,
            HandleNetworkProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::UpdateNetwork(const NetworkInfo *netInfo, void* appReqState, CompleteFunct onComplete,
        ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;
    TLVWriter       writer;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    writer.Init(msgBuf);

    err = netInfo->Encode(writer, NetworkInfo::kEncodeFlag_All);
    SuccessOrExit(err);

    err = writer.Finalize();
    SuccessOrExit(err);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_UpdateNetwork;

    err = SendRequest(kWeaveProfile_NetworkProvisioning, kMsgType_UpdateNetwork, msgBuf,
            HandleNetworkProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::RemoveNetwork(uint32_t networkId, void* appReqState, CompleteFunct onComplete,
        ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    LittleEndian::Put32(msgBuf->Start(), networkId);
    msgBuf->SetDataLength(4);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_RemoveNetwork;

    err = SendRequest(kWeaveProfile_NetworkProvisioning, NetworkProvisioning::kMsgType_RemoveNetwork, msgBuf,
            HandleNetworkProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::GetCameraAuthData(const char* nonce, void* appReqState,
        GetCameraAuthDataCompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    PacketBuffer *msgBuf = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    // Validate args
    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);
    VerifyOrExit(NULL != nonce, err = WEAVE_ERROR_INVALID_ARGUMENT);
    VerifyOrExit(strlen(nonce) == CAMERA_NONCE_LEN, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    VerifyOrExit(mCameraNonce == NULL, err = WEAVE_ERROR_INCORRECT_STATE);

    // Save copy of nonce for HandleGetCameraAuthResponse callback
    VerifyOrExit(asprintf(&mCameraNonce, "%s", nonce) > 0, err = WEAVE_ERROR_NO_MEMORY);

    err = EncodeCameraAuthDataRequest(msgBuf, nonce);
    SuccessOrExit(err);

    mAppReqState = appReqState;
    mOnComplete.GetCameraAuthData = onComplete;
    mOnError = onError;
    mOpState = kOpState_GetCameraAuthData;

    err = SendRequest(kWeaveProfile_DropcamLegacyPairing, kMsgType_CameraAuthDataRequest, msgBuf,
            HandleGetCameraAuthDataResponseEntry);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::GetNetworks(uint8_t flags, void* appReqState,
        GetNetworksCompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    Put8(msgBuf->Start(), (uint8_t) flags);
    msgBuf->SetDataLength(1);

    mAppReqState = appReqState;
    mOnComplete.GetNetworks = onComplete;
    mOnError = onError;
    mOpState = kOpState_GetNetworks;

    err = SendRequest(kWeaveProfile_NetworkProvisioning, NetworkProvisioning::kMsgType_GetNetworks, msgBuf,
            HandleNetworkProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::GetActiveLocale(void* appReqState, GetActiveLocaleCompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    uint64_t deviceId = kNodeIdNotSpecified;
    const uint16_t txnId = 1;
    const uint32_t timeout = 10000; // milliseconds
    ReferencedTLVData pathList;

    mAppReqState = appReqState;
    mOnComplete.GetActiveLocale = onComplete;
    mOnError = onError;
    mOpState = kOpState_GetActiveLocale;

    err = GetDeviceId(deviceId);
    SuccessOrExit(err);

    VerifyOrExit(mDeviceCon != NULL, err = WEAVE_ERROR_INCORRECT_STATE);

    err = mDMClient.BindRequest(mDeviceCon);
    SuccessOrExit(err);

    err = pathList.init(WriteLocaleRequest, this);
    SuccessOrExit(err);

    err = mDMClient.ViewRequest(pathList, txnId, timeout);
    SuccessOrExit(err);

exit:
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "%s failed: %s", __FUNCTION__, ErrorStr(err));
        ClearOpState();
    }
    return err;
}

WEAVE_ERROR WeaveDeviceManager::GetAvailableLocales(void* appReqState, GetAvailableLocalesCompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    uint64_t deviceId = kNodeIdNotSpecified;
    const uint16_t txnId = 1;
    const uint32_t timeout = 10000; // milliseconds
    ReferencedTLVData pathList;

    mAppReqState = appReqState;
    mOnComplete.GetAvailableLocales = onComplete;
    mOnError = onError;
    mOpState = kOpState_GetAvailableLocales;

    err = GetDeviceId(deviceId);
    SuccessOrExit(err);

    VerifyOrExit(mDeviceCon != NULL, err = WEAVE_ERROR_INCORRECT_STATE);

    err = mDMClient.BindRequest(mDeviceCon);
    SuccessOrExit(err);

    err = pathList.init(WriteLocaleRequest, this);
    SuccessOrExit(err);

    err = mDMClient.ViewRequest(pathList, txnId, timeout);
    SuccessOrExit(err);

exit:
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "%s failed: %s", __FUNCTION__, ErrorStr(err));
        ClearOpState();
    }
    return err;
}

WEAVE_ERROR WeaveDeviceManager::SetActiveLocale(void* appReqState, const char *aLocale, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    uint64_t deviceId = kNodeIdNotSpecified;
    const uint16_t txnId = 1;
    const uint32_t timeout = 10000; // milliseconds
    ReferencedTLVData dataList;

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_SetActiveLocale;
    mActiveLocale = aLocale;

    err = GetDeviceId(deviceId);
    SuccessOrExit(err);

    VerifyOrExit(mDeviceCon != NULL, err = WEAVE_ERROR_INCORRECT_STATE);

    err = mDMClient.BindRequest(mDeviceCon);
    SuccessOrExit(err);

    err = dataList.init(WriteLocaleRequest, this);
    SuccessOrExit(err);

    err = mDMClient.UpdateRequest(dataList, txnId, timeout);
    SuccessOrExit(err);

exit:
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "%s failed: %s", __FUNCTION__, ErrorStr(err));
        ClearOpState();
    }
    return err;
}

void WeaveDeviceManager::WriteLocaleRequest(TLVWriter &aWriter, void *ctx)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    const uint16_t pathLen = 1;

    WeaveDeviceManager *deviceMgr = (WeaveDeviceManager *) ctx;

    switch (deviceMgr->mOpState)
    {
        case kOpState_GetActiveLocale:
            err = StartPathList(aWriter);
            SuccessOrExit(err);

            err = EncodePath(aWriter,
                             AnonymousTag,
                             kWeaveProfile_Locale,
                             kInstanceIdNotSpecified,
                             pathLen,
                             ProfileTag(kWeaveProfile_Locale, Locale::kTag_ActiveLocale)
                             );
            SuccessOrExit(err);

            err =  EndList(aWriter);
            SuccessOrExit(err);

            err = aWriter.Finalize();
            break;

        case kOpState_SetActiveLocale:
            WeaveLogProgress(DeviceManager, "Set active locale to %s", deviceMgr->mActiveLocale);

            err = StartDataList(aWriter);
            SuccessOrExit(err);

            err = StartDataListElement(aWriter);
            SuccessOrExit(err);

            err = EncodePath(aWriter,
                             ContextTag(kTag_WDMDataListElementPath),
                             kWeaveProfile_Locale,
                             kInstanceIdNotSpecified,
                             pathLen,
                             ProfileTag(kWeaveProfile_Locale, Locale::kTag_ActiveLocale)
                             );
            SuccessOrExit(err);

            err = aWriter.Put(ContextTag(kTag_WDMDataListElementVersion), (uint64_t)1);
            SuccessOrExit(err);

            err = aWriter.PutString(ContextTag(kTag_WDMDataListElementData), deviceMgr->mActiveLocale);
            SuccessOrExit(err);

            err = EndDataListElement(aWriter);
            SuccessOrExit(err);

            err = EndList(aWriter);
            SuccessOrExit(err);

            err = aWriter.Finalize();
            break;

        case kOpState_GetAvailableLocales:
            err = StartPathList(aWriter);
            SuccessOrExit(err);

            err = EncodePath(aWriter,
                             AnonymousTag,
                             kWeaveProfile_Locale,
                             kInstanceIdNotSpecified,
                             pathLen,
                             ProfileTag(kWeaveProfile_Locale, Locale::kTag_AvailableLocales)
                             );
            SuccessOrExit(err);

            err =  EndList(aWriter);
            SuccessOrExit(err);

            err = aWriter.Finalize();
            break;

        default:
            WeaveLogError(DeviceManager, "Incorrect OpState for %s: %d", __FUNCTION__, deviceMgr->mOpState);
            err = WEAVE_ERROR_INCORRECT_STATE;
            break;
    }

exit:
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "%s failed: %s", __FUNCTION__, ErrorStr(err));
    }
}

WEAVE_ERROR WeaveDeviceManager::ThermostatGetEntryKey(void* appReqState, ThermostatGetEntryKeyCompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    uint64_t deviceId = kNodeIdNotSpecified;
    const uint16_t txnId = 1;
    const uint32_t timeout = 10000; // milliseconds
    ReferencedTLVData pathList;

    mAppReqState = appReqState;
    mOnComplete.ThermostatGetEntryKey = onComplete;
    mOnError = onError;
    mOpState = kOpState_ThermostatGetEntryKey;

    err = GetDeviceId(deviceId);
    SuccessOrExit(err);

    VerifyOrExit(mDeviceCon != NULL, err = WEAVE_ERROR_INCORRECT_STATE);

    err = mDMClient.BindRequest(mDeviceCon);
    SuccessOrExit(err);

    err = pathList.init(WriteThermostatRequest, this);
    SuccessOrExit(err);

    err = mDMClient.ViewRequest(pathList, txnId, timeout);
    SuccessOrExit(err);

exit:
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "%s failed: %s", __FUNCTION__, ErrorStr(err));
        ClearOpState();
    }
    return err;
}

WEAVE_ERROR WeaveDeviceManager::ThermostatSystemTestStatus(void* appReqState, ThermostatSystemTestStatusCompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    uint64_t deviceId = kNodeIdNotSpecified;
    const uint16_t txnId = 1;
    const uint32_t timeout = 10000; // milliseconds
    ReferencedTLVData pathList;

    mAppReqState = appReqState;
    mOnComplete.ThermostatSystemStatus = onComplete;
    mOnError = onError;
    mOpState = kOpState_ThermostatSystemTestStatus;

    err = GetDeviceId(deviceId);
    SuccessOrExit(err);

    VerifyOrExit(mDeviceCon != NULL, err = WEAVE_ERROR_INCORRECT_STATE);

    err = mDMClient.BindRequest(mDeviceCon);
    SuccessOrExit(err);

    err = pathList.init(WriteThermostatRequest, this);
    SuccessOrExit(err);

    err = mDMClient.ViewRequest(pathList, txnId, timeout);
    SuccessOrExit(err);

exit:
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "%s failed: %s", __FUNCTION__, ErrorStr(err));
        ClearOpState();
    }
    return err;
}

void WeaveDeviceManager::WriteThermostatRequest(TLVWriter &aWriter, void *ctx)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    const uint16_t pathLen = 1;

    WeaveDeviceManager *deviceMgr = (WeaveDeviceManager *) ctx;

    switch (deviceMgr->mOpState)
    {
        case kOpState_ThermostatGetEntryKey:
            err = StartPathList(aWriter);
            SuccessOrExit(err);

            err = EncodePath(aWriter,
                             AnonymousTag,
                             kWeaveProfile_NestThermostat,
                             kInstanceIdNotSpecified,
                             pathLen,
                             ProfileTag(kWeaveProfile_NestThermostat, Vendor::Nestlabs::Thermostat::kTag_LegacyEntryKey)
                             );
            SuccessOrExit(err);

            err =  EndList(aWriter);
            SuccessOrExit(err);

            err = aWriter.Finalize();
            break;

        case kOpState_ThermostatSystemTestStatus:
            err = StartPathList(aWriter);
            SuccessOrExit(err);

            err = EncodePath(aWriter,
                             AnonymousTag,
                             kWeaveProfile_NestThermostat,
                             kInstanceIdNotSpecified,
                             pathLen,
                             ProfileTag(kWeaveProfile_NestThermostat, Vendor::Nestlabs::Thermostat::kTag_SystemTestStatusKey)
                             );
            SuccessOrExit(err);

            err =  EndList(aWriter);
            SuccessOrExit(err);

            err = aWriter.Finalize();
            break;

        default:
            WeaveLogError(DeviceManager, "Incorrect OpState for %s: %d", __FUNCTION__, deviceMgr->mOpState);
            err = WEAVE_ERROR_INCORRECT_STATE;
            break;
    }

exit:
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "%s failed: %s", __FUNCTION__, ErrorStr(err));
    }
}

WEAVE_ERROR WeaveDeviceManager::EnableNetwork(uint32_t networkId, void* appReqState, CompleteFunct onComplete,
        ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    LittleEndian::Put32(msgBuf->Start(), networkId);
    msgBuf->SetDataLength(4);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_EnableNetwork;

    err = SendRequest(kWeaveProfile_NetworkProvisioning, NetworkProvisioning::kMsgType_EnableNetwork, msgBuf,
            HandleNetworkProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::DisableNetwork(uint32_t networkId, void* appReqState, CompleteFunct onComplete,
        ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    LittleEndian::Put32(msgBuf->Start(), networkId);
    msgBuf->SetDataLength(4);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_DisableNetwork;

    err = SendRequest(kWeaveProfile_NetworkProvisioning, NetworkProvisioning::kMsgType_DisableNetwork, msgBuf,
            HandleNetworkProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::TestNetworkConnectivity(uint32_t networkId, void* appReqState, CompleteFunct onComplete,
        ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    LittleEndian::Put32(msgBuf->Start(), networkId);
    msgBuf->SetDataLength(4);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_TestNetworkConnectivity;

    err = SendRequest(kWeaveProfile_NetworkProvisioning, NetworkProvisioning::kMsgType_TestConnectivity, msgBuf,
            HandleNetworkProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::GetRendezvousMode(void* appReqState, GetRendezvousModeCompleteFunct onComplete,
        ErrorFunct onError)
{
    return WEAVE_ERROR_NOT_IMPLEMENTED;
}

WEAVE_ERROR WeaveDeviceManager::SetRendezvousMode(uint16_t modeFlags, void* appReqState, CompleteFunct onComplete,
        ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    LittleEndian::Put16(msgBuf->Start(), modeFlags);
    msgBuf->SetDataLength(2);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_SetRendezvousMode;

    err = SendRequest(kWeaveProfile_NetworkProvisioning, NetworkProvisioning::kMsgType_SetRendezvousMode, msgBuf,
            HandleNetworkProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::GetLastNetworkProvisioningResult(void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_GetLastNPResult;

    err = SendRequest(kWeaveProfile_NetworkProvisioning, NetworkProvisioning::kMsgType_GetLastResult, msgBuf,
            HandleNetworkProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::CreateFabric(void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);
    msgBuf->SetDataLength(0);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_CreateFabric;

    err = SendRequest(kWeaveProfile_FabricProvisioning, FabricProvisioning::kMsgType_CreateFabric, msgBuf,
            HandleFabricProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::LeaveFabric(void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);
    msgBuf->SetDataLength(0);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_LeaveFabric;

    err = SendRequest(kWeaveProfile_FabricProvisioning, FabricProvisioning::kMsgType_LeaveFabric, msgBuf,
            HandleFabricProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::GetFabricConfig(void* appReqState, GetFabricConfigCompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);
    msgBuf->SetDataLength(0);

    mAppReqState = appReqState;
    mOnComplete.GetFabricConfig = onComplete;
    mOnError = onError;
    mOpState = kOpState_GetFabricConfig;

    err = SendRequest(kWeaveProfile_FabricProvisioning, FabricProvisioning::kMsgType_GetFabricConfig, msgBuf,
            HandleFabricProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::JoinExistingFabric(const uint8_t *fabricConfig, uint32_t fabricConfigLen,
        void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);
    VerifyOrExit(msgBuf->AvailableDataLength() >= fabricConfigLen, err = WEAVE_ERROR_BUFFER_TOO_SMALL);
    memcpy(msgBuf->Start(), fabricConfig, fabricConfigLen);
    msgBuf->SetDataLength(fabricConfigLen);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_JoinExistingFabric;

    err = SendRequest(kWeaveProfile_FabricProvisioning, FabricProvisioning::kMsgType_JoinExistingFabric, msgBuf,
            HandleFabricProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::RegisterServicePairAccount(uint64_t serviceId, const char *accountId,
                                                           const uint8_t *serviceConfig, uint16_t serviceConfigLen,
                                                           const uint8_t *pairingToken, uint16_t pairingTokenLen,
                                                           const uint8_t *pairingInitData, uint16_t pairingInitDataLen,
                                                           void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR                         err             = WEAVE_NO_ERROR;
    PacketBuffer*                       msgBuf          = NULL;
    size_t                              accountIdLen    = strlen(accountId);
    RegisterServicePairAccountMessage   msg;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msg.ServiceId = serviceId;
    msg.AccountId = accountId;
    msg.AccountIdLen = accountIdLen;
    msg.ServiceConfig = serviceConfig;
    msg.ServiceConfigLen = serviceConfigLen;
    msg.PairingToken = pairingToken;
    msg.PairingTokenLen = pairingTokenLen;
    msg.PairingInitData = pairingInitData;
    msg.PairingInitDataLen = pairingInitDataLen;

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    err = msg.Encode(msgBuf);
    SuccessOrExit(err);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_RegisterServicePairAccount;

    err = SendRequest(kWeaveProfile_ServiceProvisioning, ServiceProvisioning::kMsgType_RegisterServicePairAccount, msgBuf,
            HandleServiceProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::UpdateService(uint64_t serviceId, const uint8_t *serviceConfig, uint16_t serviceConfigLen,
                                              void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR             err     = WEAVE_NO_ERROR;
    PacketBuffer*           msgBuf  = NULL;
    UpdateServiceMessage    msg;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    msg.ServiceId = serviceId;
    msg.ServiceConfig = serviceConfig;
    msg.ServiceConfigLen = serviceConfigLen;

    err = msg.Encode(msgBuf);
    SuccessOrExit(err);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_UpdateService;

    err = SendRequest(kWeaveProfile_ServiceProvisioning, ServiceProvisioning::kMsgType_UpdateService, msgBuf,
            HandleServiceProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::UnregisterService(uint64_t serviceId, void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;
    uint8_t*        p;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    p = msgBuf->Start();
    LittleEndian::Write64(p, serviceId);
    msgBuf->SetDataLength(8);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_UnregisterService;

    err = SendRequest(kWeaveProfile_ServiceProvisioning, ServiceProvisioning::kMsgType_UnregisterService, msgBuf,
            HandleServiceProvisioningResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::ArmFailSafe(uint8_t armMode, uint32_t failSafeToken, void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;
    uint8_t*        p;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    p = msgBuf->Start();
    Write8(p, armMode);
    LittleEndian::Write32(p, failSafeToken);
    msgBuf->SetDataLength(5);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_ArmFailSafe;

    err = SendRequest(kWeaveProfile_DeviceControl, DeviceControl::kMsgType_ArmFailSafe, msgBuf,
            HandleDeviceControlResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::DisarmFailSafe(void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    msgBuf->SetDataLength(0);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_DisarmFailSafe;

    err = SendRequest(kWeaveProfile_DeviceControl, DeviceControl::kMsgType_DisarmFailSafe, msgBuf,
            HandleDeviceControlResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::StartSystemTest(void* appReqState, uint32_t profileId, uint32_t testId, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;
    uint8_t*        p;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    p = msgBuf->Start();
    LittleEndian::Write32(p, profileId);
    LittleEndian::Write32(p, testId);
    msgBuf->SetDataLength(DeviceControl::kMessageLength_StartSystemTest);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_StartSystemTest;

    err = SendRequest(kWeaveProfile_DeviceControl, DeviceControl::kMsgType_StartSystemTest, msgBuf,
            HandleDeviceControlResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::StopSystemTest(void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    msgBuf->SetDataLength(DeviceControl::kMessageLength_StopSystemTest);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_StopSystemTest;

    err = SendRequest(kWeaveProfile_DeviceControl, DeviceControl::kMsgType_StopSystemTest, msgBuf,
            HandleDeviceControlResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::ResetConfig(uint16_t resetFlags, void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;
    uint8_t*        p;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    p = msgBuf->Start();
    LittleEndian::Write16(p, resetFlags);
    msgBuf->SetDataLength(2);

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_ResetConfig;

    err = SendRequest(kWeaveProfile_DeviceControl, DeviceControl::kMsgType_ResetConfig, msgBuf,
            HandleDeviceControlResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::Ping(void* appReqState, CompleteFunct onComplete, ErrorFunct onError)
{
    return Ping(appReqState, 0, onComplete, onError);
}

WEAVE_ERROR WeaveDeviceManager::Ping(void* appReqState, int32_t payloadSize, CompleteFunct onComplete, ErrorFunct onError)
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onComplete != NULL && onError != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);
    msgBuf->SetDataLength(payloadSize);

    // Require ping message to fit within one PacketBuffer.
    WeaveLogProgress(DeviceManager, "DataLength: %d, payload: %d, next: %p", msgBuf->DataLength(), payloadSize, msgBuf->Next());
    VerifyOrExit(((msgBuf->DataLength() == payloadSize) && (msgBuf->Next() == NULL)), err = WEAVE_ERROR_INVALID_MESSAGE_LENGTH);

    if (payloadSize > 0) {
        // fill with test pattern
        uint8_t *data = msgBuf->Start();
        for (int i = 0; i < payloadSize; i++) {
            *data++ = 0xff & i;
        }
    }
    // Store ping size so return function can check for truncation.
    mPingSize = payloadSize;

    mAppReqState = appReqState;
    mOnComplete.General = onComplete;
    mOnError = onError;
    mOpState = kOpState_Ping;

    err = SendRequest(kWeaveProfile_Echo, kEchoMessageType_EchoRequest, msgBuf, HandlePingResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearOpState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::SignedHush(uint32_t proximityVerificationCode, uint32_t challenge, uint16_t keyId, const uint8_t *key, uint16_t keySize,
                                           void* appReqState, HushCompleteFunct onHushComplete, ErrorFunct onError)
{
    WEAVE_ERROR         err             = WEAVE_NO_ERROR;
    PacketBuffer*       msgBuf          = NULL;
    AlarmHushRequest    hushRequest;

    if (mOpState != kOpState_Idle)
        return WEAVE_ERROR_INCORRECT_STATE;

    VerifyOrExit(onHushComplete != NULL && onError != NULL && key != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    hushRequest.mProximityVerificationCode = proximityVerificationCode;

    err = hushRequest.sign(challenge, keyId, key, keySize);
    SuccessOrExit(err);

    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);
    msgBuf->SetDataLength(0);

    err = hushRequest.pack(msgBuf);
    SuccessOrExit(err);

    mAppReqState = appReqState;
    mOnComplete.Hush = onHushComplete;
    mOnError = onError;
    mOpState = kOpState_Hush;

    err = SendRequest(kWeaveProfile_Alarm, kAlarmMessageType_AlarmHushRequest, msgBuf, HandleHushResponse);
    msgBuf = NULL;

exit:
    if (msgBuf != NULL)
    {
        PacketBuffer::Free(msgBuf);
    }

    if (err != WEAVE_NO_ERROR)
    {
        ClearOpState();
    }
    return err;
}

bool WeaveDeviceManager::IsValidPairingCode(const char *pairingCode)
{
    if (pairingCode == NULL)
        return false;

    size_t len = strlen(pairingCode);

    if (len < 6)
        return false;

    return Verhoeff32::ValidateCheckChar(pairingCode, len);
}

WEAVE_ERROR WeaveDeviceManager::SetRendezvousAddress(IPAddress addr)
{
    if (addr == IPAddress::Any)
        addr = IPAddress::MakeIPv6Multicast(kIPv6MulticastScope_Link, kIPV6MulticastGroup_AllNodes);
    mRendezvousAddr = addr;
    return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveDeviceManager::SetAutoReconnect(bool autoReconnect)
{
    WEAVE_ERROR ret = WEAVE_NO_ERROR;

    VerifyOrExit(mConnectedToRemoteDevice == false, ret = WEAVE_ERROR_INCORRECT_STATE);

    mAutoReconnect = autoReconnect;

exit:
    return ret;
}

WEAVE_ERROR WeaveDeviceManager::SetUseAccessToken(bool useAccessToken)
{
    mUseAccessToken = useAccessToken;
    return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveDeviceManager::SetRendezvousLinkLocal(bool RendezvousLinkLocal)
{
    mRendezvousLinkLocal = RendezvousLinkLocal;
    return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveDeviceManager::SetConnectTimeout(uint32_t timeoutMS)
{
    mConTimeout = timeoutMS;
    return WEAVE_NO_ERROR;
}

// DEPRECATED
WEAVE_ERROR WeaveDeviceManager::SetWiFiRendezvousAddress(IPAddress addr)
{
    return SetRendezvousAddress(addr);
}

WEAVE_ERROR WeaveDeviceManager::SendRequest(uint32_t profileId, uint16_t msgType, PacketBuffer *msgBuf,
        ExchangeContext::MessageReceiveFunct onMsgRcvd)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Verify there isn't a request already outstanding.
    VerifyOrExit(mCurReq == NULL, err = WEAVE_ERROR_INCORRECT_STATE);

    // Save the information about the new request.
    mCurReqProfileId = profileId;
    mCurReqMsgType = msgType;
    mCurReqMsg = msgBuf;
    msgBuf = NULL;
    mCurReqRcvFunct = onMsgRcvd;

    // If not already connected...
    if (!IsConnected())
    {
        // Return an error if auto-reconnect not enabled.
        VerifyOrExit(mAutoReconnect, err = WEAVE_ERROR_NOT_CONNECTED);

        // Return an error if we haven't previously connected.
        VerifyOrExit(mDeviceId != kNodeIdNotSpecified && mDeviceAddr != IPAddress::Any, err = WEAVE_ERROR_NOT_CONNECTED);

        // Initiate a new connection to the previously connected device.
        mDeviceCriteria.Reset();
        err = InitiateConnection();
    }

    // Otherwise, there is a connection so send the request immediately.
    else
        err = SendPendingRequest();

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        ClearRequestState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::SendPendingRequest()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Verify there's a request ready to go.
    VerifyOrExit(mCurReqMsg != NULL, err = WEAVE_ERROR_INCORRECT_STATE);

    // Verify we have a connection.
    VerifyOrExit(IsConnected(), err = WEAVE_ERROR_INCORRECT_STATE);

    // Verify there isn't already a request in progress.
    VerifyOrExit(mCurReq == NULL && mCurReqMsg != NULL, err = WEAVE_ERROR_INCORRECT_STATE);

    // Create and initialize an exchange context for the request.
    mCurReq = mExchangeMgr->NewContext(mDeviceId, this);
    VerifyOrExit(mCurReq != NULL, err = WEAVE_ERROR_NO_MEMORY);
    mCurReq->Con = mDeviceCon;
    mCurReq->KeyId = mSessionKeyId;
    mCurReq->EncryptionType = mEncType;
    mCurReq->OnMessageReceived = mCurReqRcvFunct;
    mCurReq->OnConnectionClosed = HandleRequestConnectionClosed;

    // TODO: setup request timeout

    // Send the current request over the connection.
    err = mCurReq->SendMessage(mCurReqProfileId, mCurReqMsgType, mCurReqMsg, 0);
    mCurReqMsg = NULL;

exit:
    if (mCurReqMsg)
    {
        PacketBuffer::Free(mCurReqMsg);
    }

    if (err != WEAVE_NO_ERROR)
        ClearRequestState();
    return err;
}

WEAVE_ERROR WeaveDeviceManager::SaveAuthKey(const char *pairingCode)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    VerifyOrExit(pairingCode != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    if (mAuthKey != pairingCode)
    {
        ClearAuthKey();
        mAuthKey = strdup(pairingCode);
        VerifyOrExit(mAuthKey != NULL, err = WEAVE_ERROR_NO_MEMORY);

        VerifyOrExit(mMessageLayer != NULL, err = WEAVE_ERROR_INCORRECT_STATE);
        VerifyOrExit(mMessageLayer->FabricState != NULL, err = WEAVE_ERROR_INCORRECT_STATE);
        mMessageLayer->FabricState->PairingCode = static_cast<const char *>(mAuthKey);
    }

    mAuthKeyLen = strlen(pairingCode);
    VerifyOrExit(mAuthKeyLen <= kMaxPairingCodeLength, err = WEAVE_ERROR_INVALID_ARGUMENT);

exit:
    if (err != WEAVE_NO_ERROR)
        ClearAuthKey();

    return err;
}

WEAVE_ERROR WeaveDeviceManager::SaveAuthKey(const uint8_t *accessToken, uint32_t accessTokenLen)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    VerifyOrExit(accessToken != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    if (mAuthKey != accessToken)
    {
        ClearAuthKey();
        mAuthKey = malloc(accessTokenLen);
        VerifyOrExit(mAuthKey != NULL, err = WEAVE_ERROR_NO_MEMORY);
        memcpy(mAuthKey, accessToken, accessTokenLen);
    }

    mAuthKeyLen = accessTokenLen;

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceManager::SaveRemoteDeviceAuthInfo(uint8_t authType, const char *authKey, uint32_t authKeyLen)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    mRemoteDeviceAuthType = authType;

    switch (authType)
    {
    case kAuthType_PASEWithPairingCode:
        if (mRemoteDeviceAuthKey != authKey)
        {
            ClearAuthKey(mRemoteDeviceAuthKey, mRemoteDeviceAuthKeyLen);
            mRemoteDeviceAuthKey = strdup(authKey);
            VerifyOrExit(mRemoteDeviceAuthKey != NULL, err = WEAVE_ERROR_NO_MEMORY);
        }

        mRemoteDeviceAuthKeyLen = strlen(authKey);
        VerifyOrExit(mRemoteDeviceAuthKeyLen <= kMaxPairingCodeLength, err = WEAVE_ERROR_INVALID_ARGUMENT);
        break;

    case kAuthType_CASEWithAccessToken:
        if (mRemoteDeviceAuthKey != authKey)
        {
            ClearAuthKey(mRemoteDeviceAuthKey, mRemoteDeviceAuthKeyLen);
            mRemoteDeviceAuthKey = malloc(authKeyLen);
            VerifyOrExit(mRemoteDeviceAuthKey != NULL, err = WEAVE_ERROR_NO_MEMORY);

            memcpy(mRemoteDeviceAuthKey, authKey, authKeyLen);
        }

        mRemoteDeviceAuthKeyLen = authKeyLen;
        break;

    case kAuthType_None:
        break;

    default:
        err = WEAVE_ERROR_INVALID_ARGUMENT;
        break;
    }

exit:
    if (err != WEAVE_NO_ERROR)
    {
        ClearAuthKey(mRemoteDeviceAuthKey, mRemoteDeviceAuthKeyLen);
        mRemoteDeviceAuthType = kAuthType_None;
    }

    return err;
}

void WeaveDeviceManager::ClearAuthKey()
{
    ClearAuthKey(mAuthKey, mAuthKeyLen);

    if (mMessageLayer && mMessageLayer->FabricState)
    {
        mMessageLayer->FabricState->PairingCode = NULL;
    }
}

void WeaveDeviceManager::ClearAuthKey(void *&authKey, uint32_t &authKeyLen)
{
    if (authKey != NULL)
    {
        nl::Weave::Crypto::ClearSecretData((uint8_t *)authKey, authKeyLen);
        free(authKey);
        authKey = NULL;
    }

    authKeyLen = 0;
}

void WeaveDeviceManager::ClearRequestState()
{
    if (mCurReq != NULL)
    {
        mCurReq->Close();
        mCurReq = NULL;
    }

    if (mCurReqMsg != NULL)
    {
        PacketBuffer::Free(mCurReqMsg);
        mCurReqMsg = NULL;
    }

    if (mCameraNonce != NULL)
    {
        free(mCameraNonce);
        mCameraNonce = NULL;
    }

    mCurReqProfileId = 0;
    mCurReqMsgType = 0;
    mCurReqRcvFunct = NULL;
}

void WeaveDeviceManager::ClearOpState()
{
    ClearRequestState();
    mOpState = kOpState_Idle;
}

void WeaveDeviceManager::HandleUnsecuredConnectionCallbackRemoved(void *appState)
{
    WeaveDeviceManager *devMgr = static_cast<WeaveDeviceManager *>(appState);

    // Ensure we don't call ClearUnsecuredConnectionListener after our listener has been removed.
    devMgr->mIsUnsecuredConnectionListenerSet = false;

    // If another application has pre-empted our (Remote)PassiveRendezvous, close it down.
    devMgr->Close();

    // Tell the application we can't complete the requested operation.
    devMgr->mOnError(devMgr, devMgr->mAppReqState, WEAVE_ERROR_CALLBACK_REPLACED, NULL);
}

void WeaveDeviceManager::HandleRequestConnectionClosed(ExchangeContext *ec, WeaveConnection *con, WEAVE_ERROR conErr)
{
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;

    if (devMgr->mOpState == kOpState_Idle || ec != devMgr->mCurReq)
    {
        ec->Close();
        return;
    }

    // Cancel timers and clear state.
    devMgr->Close();

    // Call the user's OnError callback.
    devMgr->mOnError(devMgr, devMgr->mAppReqState, WEAVE_ERROR_CONNECTION_CLOSED_UNEXPECTEDLY, NULL);
}

WEAVE_ERROR WeaveDeviceManager::InitiateConnection()
{
    WEAVE_ERROR             err     = WEAVE_NO_ERROR;
    PacketBuffer*           msgBuf  = NULL;
    IdentifyRequestMessage  reqMsg;
    uint16_t                sendFlags;

    VerifyOrExit(mConState == kConnectionState_NotConnected || mConState == kConnectionState_IdentifyDevice,
        err = WEAVE_ERROR_INCORRECT_STATE);


    // If starting from the NotConnected state, reset the connection identify count.
    if (mConState == kConnectionState_NotConnected)
    {
        WeaveLogProgress(DeviceManager, "Initiating connection to device");
        mConTryCount = 0;
    }

    // Refresh the message layer endpoints to cope with changes in network interface status
    // (e.g. new addresses being assigned).
    err = mMessageLayer->RefreshEndpoints();
    SuccessOrExit(err);

    // Form an Identify device request containing the device criteria specified by the application.
    reqMsg.TargetFabricId = mDeviceCriteria.TargetFabricId;
    reqMsg.TargetModes = mDeviceCriteria.TargetModes;
    reqMsg.TargetVendorId = mDeviceCriteria.TargetVendorId;

    if (mDeviceCriteria.TargetVendorId == kWeaveVendor_NestLabs && IsProductWildcard(mDeviceCriteria.TargetProductId))
    {
        reqMsg.TargetProductId = 0xFFFF;
    }
    else
    {
        reqMsg.TargetProductId = mDeviceCriteria.TargetProductId;
    }

    // Encode the Identify device request message.
    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);
    err = reqMsg.Encode(msgBuf);
    SuccessOrExit(err);

    // Construct an exchange context if needed.
    if (mCurReq == NULL)
    {
        InterfaceId targetIntf = (mDeviceAddr.IsIPv6LinkLocal()) ? mDeviceIntf : INET_NULL_INTERFACEID;
        mCurReq = mExchangeMgr->NewContext(mDeviceId, mDeviceAddr, WEAVE_PORT, targetIntf, this);
        VerifyOrExit(mCurReq != NULL, err = WEAVE_ERROR_NO_MEMORY);
        mCurReq->OnMessageReceived = HandleConnectionIdentifyResponse;

        // TODO setup request timeout
    }

    WeaveLogProgress(DeviceManager, "Sending IdentifyRequest to locate device");

    mConState = kConnectionState_IdentifyDevice;

    // Send the Identify message.
    //
    // If performing a multicast identify, AND the 'rendezvous link-local' option is enabled,
    // AND the message layer is not bound to a specific local IPv6 address, THEN ...
    //
    // Send the multicast identify request from the host's link-local addresses, rather than
    // from its site-local or global addresses. This results in the device responding using its
    // link-local address, which in turn causes the device manager to connect to the device using the
    // link-local address. This is all to work around a bug in OS X/iOS that prevents those systems
    // from communicating on any site-local IPv6 subnets when in the presence of a router that is
    // advertising a default route to the Internet at large. (See DOLO-2479).
    //
    // We disable the 'rendezvous link-local' feature when the message layer is bound to a specific
    // address because binding to a specific address is generally used when testing the device manager
    // and a mock-device running on a single host with a single interface.  In this case multicasting
    // using the interface's single link-local address doesn't work.
    //
    sendFlags = (mDeviceAddr.IsMulticast() && mRendezvousLinkLocal && !mMessageLayer->IsBoundToLocalIPv6Address())
            ? ExchangeContext::kSendFlag_MulticastFromLinkLocal
            : 0;
    err = mCurReq->SendMessage(kWeaveProfile_DeviceDescription, kMessageType_IdentifyRequest, msgBuf, sendFlags);
    msgBuf = NULL;
    if (err == System::MapErrorPOSIX(ENETUNREACH) || err == System::MapErrorPOSIX(EHOSTUNREACH) ||
        err == System::MapErrorPOSIX(EPIPE))
        err = WEAVE_NO_ERROR;
    SuccessOrExit(err);

    // Arm the retry timer.
    err = mSystemLayer->StartTimer(kConRetryInterval, HandleConnectionIdentifyTimeout, this);
    SuccessOrExit(err);

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR)
        Close();
    return err;
}

bool WeaveDeviceManager::IsNodeInList(uint64_t nodeId, uint64_t *list, uint32_t listLen)
{
    uint32_t idx;

    for (idx = 0; idx < listLen; idx++)
    {
        if (list[idx] == nodeId)
        {
            return true;
        }
    }

    return false;
}

WEAVE_ERROR WeaveDeviceManager::AddNodeToList(uint64_t nodeId, uint64_t *&list, uint32_t &listLen, uint32_t &listMaxLen, uint32_t initialMaxLen)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    uint64_t *tmp;

    // If list is uninitialized, allocate default amount of initial space
    if (!list)
    {
        list = static_cast<uint64_t *>(malloc(sizeof(uint64_t) * initialMaxLen));
        VerifyOrExit(NULL != list, err = WEAVE_ERROR_NO_MEMORY);

        listMaxLen = initialMaxLen;
    }
    // Resize list (double the current space) if necessary
    else if (listLen == listMaxLen)
    {
        VerifyOrExit((static_cast<uint64_t>(listMaxLen) * 2) < UINT32_MAX, err = WEAVE_ERROR_NO_MEMORY);

        tmp = static_cast<uint64_t *>(realloc(list, listMaxLen * 2));
        VerifyOrExit(NULL != tmp, err = WEAVE_ERROR_NO_MEMORY);

        list = tmp;
        listMaxLen *= 2;
    }

    list[listLen] = nodeId;
    listLen++;

exit:
    return err;
}

void WeaveDeviceManager::HandleDeviceEnumerationIdentifyResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
    uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;
    IdentifyResponseMessage respMsg;
    bool isMatch;

    VerifyOrExit(kOpState_EnumerateDevices == devMgr->mOpState, err = WEAVE_ERROR_INCORRECT_STATE);

    // If we got an Identify response, check that it matches the requested criteria and ignore it
    // if not.
    VerifyOrExit(profileId == kWeaveProfile_DeviceDescription && msgType == kMessageType_IdentifyResponse, err = WEAVE_ERROR_INVALID_MESSAGE_TYPE);

    // Parse the identify response.
    err = IdentifyResponseMessage::Decode(payload, respMsg);
    SuccessOrExit(err);

    err = FilterIdentifyResponse(respMsg, devMgr->mDeviceCriteria, msgInfo->SourceNodeId, isMatch);
    SuccessOrExit(err);

    // Exit silently if responder doesn't match search critera
    VerifyOrExit(isMatch, err = WEAVE_NO_ERROR);

    // Exit silently if responder ID's already enumerated
    VerifyOrExit(!IsNodeInList(msgInfo->SourceNodeId, devMgr->mEnumeratedNodes, devMgr->mEnumeratedNodesLen), err = WEAVE_NO_ERROR);

    // Mark responder ID as enumerated
    err = AddNodeToList(msgInfo->SourceNodeId, devMgr->mEnumeratedNodes, devMgr->mEnumeratedNodesLen, devMgr->mEnumeratedNodesMaxLen,
                        ENUMERATED_NODES_LIST_INITIAL_SIZE);
    SuccessOrExit(err);

    // Notify the application
    devMgr->mOnComplete.DeviceEnumeration(devMgr, devMgr->mAppReqState, const_cast<const WeaveDeviceDescriptor *>(&respMsg.DeviceDesc), pktInfo->SrcAddress, pktInfo->Interface);

exit:
    if (payload)
    {
        PacketBuffer::Free(payload);
    }

    if (WEAVE_NO_ERROR != err)
    {
        WeaveLogError(DeviceManager, "HandleDeviceEnumerationIdentifyResponse failure: err = %d", err);
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    }
}

void WeaveDeviceManager::HandleConnectionIdentifyResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
        uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;
    IdentifyResponseMessage respMsg;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding operation.
    if (ec != devMgr->mCurReq)
    {
        ec->Close();
        ExitNow(err = WEAVE_ERROR_INCORRECT_STATE);
    }

    // Verify that we're in the correct connection state.
    VerifyOrExit(devMgr->mConState == kConnectionState_IdentifyDevice, err = WEAVE_ERROR_INCORRECT_STATE);

    // If we got an Identify response, check that it matches the requested criteria and ignore it
    // if not.
    if (profileId == kWeaveProfile_DeviceDescription && msgType == kMessageType_IdentifyResponse)
    {
        // Parse the identify response.
        err = IdentifyResponseMessage::Decode(payload, respMsg);
        SuccessOrExit(err);

        bool isMatch;
        err = FilterIdentifyResponse(respMsg, devMgr->mDeviceCriteria, msgInfo->SourceNodeId, isMatch);
        SuccessOrExit(err);
        if (!isMatch)
            ExitNow();
    }

    // Discard the current exchange context.
    devMgr->mCurReq->Close();
    devMgr->mCurReq = NULL;

    // Cancel the identify timer.
    devMgr->mSystemLayer->CancelTimer(HandleConnectionIdentifyTimeout, devMgr);

    // If we got an Identify response...
    if (profileId == kWeaveProfile_DeviceDescription && msgType == kMessageType_IdentifyResponse)
    {
#if WEAVE_PROGRESS_LOGGING
        {
            char msgSourceStr[WEAVE_MAX_MESSAGE_SOURCE_STR_LENGTH];
            WeaveMessageSourceToStr(msgSourceStr, sizeof(msgSourceStr), msgInfo);
            WeaveLogProgress(DeviceManager, "Received identify response from device %s", msgSourceStr);
        }
#endif

        // Save the id and address of the device that responded, along with the interface over which
        // the response was received.
        //
        // NOTE that, since this interaction was unsecured, this is only the PURPORTED id
        // of the device.  Once we establish a secure session with the device, we will know for sure
        // that this is the device's id.

        devMgr->mDeviceId = msgInfo->SourceNodeId;
        if (pktInfo != NULL)
        {
            devMgr->mDeviceAddr = pktInfo->SrcAddress;
            devMgr->mDeviceIntf = pktInfo->Interface;
        }
        else
        {
            devMgr->mDeviceAddr = IPAddress::Any;
            devMgr->mDeviceIntf = INET_NULL_INTERFACEID;
        }
        if (devMgr->mDeviceCon != NULL && devMgr->mDeviceCon->PeerNodeId == kNodeIdNotSpecified)
            devMgr->mDeviceCon->PeerNodeId = msgInfo->SourceNodeId;

        // If performing a passive rendezvous or initializing a Weave BLE connection...
        if (devMgr->mOpState == kOpState_PassiveRendezvousDevice ||
            devMgr->mOpState == kOpState_InitializeBleConnection)
        {
            // Initiate a secure session. If this fails, fail the passive rendezvous or BLE connection
            // initialization.
            err = devMgr->StartSession();
            SuccessOrExit(err);
        }

        // Otherwise we're performing a connect or an active rendezvous, so...
        else
        {
            // Initiate a connection to the node id/ip address from which the response was sent.
            err = devMgr->StartConnectDevice(devMgr->mDeviceId, devMgr->mDeviceAddr);
            SuccessOrExit(err);
        }
    }

    // If we got a status report message...
    else if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        DeviceStatus devStatus;

        // End the connection process.
        devMgr->Close();

        // Decode the supplied status report.
        err = devMgr->DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        // Call the app's OnError callback.
        devMgr->mOnError(devMgr, devMgr->mAppReqState, WEAVE_ERROR_STATUS_REPORT_RECEIVED, &devStatus);
    }

    // Fail if we got an unexpected response.
    else
        ExitNow(err = WEAVE_ERROR_INVALID_MESSAGE_TYPE);

exit:
    if (payload != NULL)
        PacketBuffer::Free(payload);

    if (err != WEAVE_NO_ERROR)
    {
        devMgr->Close();
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    }
}

WEAVE_ERROR WeaveDeviceManager::FilterIdentifyResponse(IdentifyResponseMessage &respMsg, IdentifyDeviceCriteria criteria, uint64_t sourceNodeId,
    bool& isMatch)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    isMatch = false;

    if (criteria.TargetFabricId != kTargetFabricId_Any)
    {
        if (criteria.TargetFabricId == kTargetFabricId_AnyFabric && respMsg.DeviceDesc.FabricId == 0)
            ExitNow();
        else if (criteria.TargetFabricId == kTargetFabricId_NotInFabric && respMsg.DeviceDesc.FabricId != 0)
            ExitNow();
        else if (criteria.TargetFabricId != respMsg.DeviceDesc.FabricId)
            ExitNow();
    }

    if (criteria.TargetVendorId != 0xFFFF)
    {
        if (criteria.TargetVendorId != respMsg.DeviceDesc.VendorId)
            ExitNow();

        if (criteria.TargetVendorId == kWeaveVendor_NestLabs)
        {
            if (criteria.TargetProductId == kProductWildcardId_NestThermostat)
            {
                if (respMsg.DeviceDesc.ProductId != kNestWeaveProduct_Diamond &&
                    respMsg.DeviceDesc.ProductId != kNestWeaveProduct_Diamond2 &&
                    respMsg.DeviceDesc.ProductId != kNestWeaveProduct_Diamond3)
                    ExitNow();
            }
            else if (criteria.TargetProductId == kProductWildcardId_NestProtect)
            {
                if (respMsg.DeviceDesc.ProductId != kNestWeaveProduct_Topaz &&
                    respMsg.DeviceDesc.ProductId != kNestWeaveProduct_Topaz2)
                    ExitNow();
            }
            else if (criteria.TargetProductId == kProductWildcardId_NestCam)
            {
                if (respMsg.DeviceDesc.ProductId != kNestWeaveProduct_Quartz &&
                    respMsg.DeviceDesc.ProductId != kNestWeaveProduct_SmokyQuartz &&
                    respMsg.DeviceDesc.ProductId != kNestWeaveProduct_Quartz2 &&
                    respMsg.DeviceDesc.ProductId != kNestWeaveProduct_BlackQuartz &&
                    respMsg.DeviceDesc.ProductId != kNestWeaveProduct_RoseQuartz)
                    ExitNow();
            }
            else if (criteria.TargetProductId != 0xFFFF)
            {
                if (respMsg.DeviceDesc.ProductId != criteria.TargetProductId)
                    ExitNow();
            }
        }
    }

    if (criteria.TargetDeviceId != kAnyNodeId)
    {
        if (sourceNodeId != criteria.TargetDeviceId)
            ExitNow();
    }

    isMatch = true;

exit:
    return err;
}

void WeaveDeviceManager::HandleDeviceEnumerationTimeout(System::Layer* aSystemLayer, void* aAppState, System::Error aError)
{
    WeaveDeviceManager* lDevMgr  = reinterpret_cast<WeaveDeviceManager*>(aAppState);
    WEAVE_ERROR         lError = static_cast<WEAVE_ERROR>(aError);

    // Bail immediately if no device enumeration in progress. (This should never be the case.)
    VerifyOrExit(kOpState_EnumerateDevices == lDevMgr->mOpState, lError = WEAVE_ERROR_INCORRECT_STATE);

    // Restart the device enumeration process.
    lError = lDevMgr->InitiateDeviceEnumeration();
    SuccessOrExit(lError);

exit:
    if (lError != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "HandleDeviceEnumerationTimeout failure, err = %d", lError);
    }
}

void WeaveDeviceManager::HandleConnectionIdentifyTimeout(System::Layer* aSystemLayer, void* aAppState, System::Error aError)
{
    WeaveDeviceManager* lDevMgr  = reinterpret_cast<WeaveDeviceManager*>(aAppState);
    WEAVE_ERROR         lError = static_cast<WEAVE_ERROR>(aError);

    // Bail immediately if not in the right state. (This should never be the case.)
    if (lDevMgr->mConState != kConnectionState_IdentifyDevice)
        return;

    // If we've reached the retry limit, fail the operation with a timeout error.
    if (lDevMgr->mConTimeout != 0 && lDevMgr->mConTryCount * kConRetryInterval >= lDevMgr->mConTimeout)
    {
        WeaveLogProgress(DeviceManager, "Failed to locate device");
        ExitNow(lError = WEAVE_ERROR_DEVICE_LOCATE_TIMEOUT);
    }

    // Otherwise, try again...
    lDevMgr->mConTryCount++;

    // Restart the connection process.
    lError = lDevMgr->InitiateConnection();
    SuccessOrExit(lError);

exit:
    if (lError != WEAVE_NO_ERROR)
    {
        lDevMgr->Close();
        lDevMgr->mOnError(lDevMgr, lDevMgr->mAppReqState, lError, NULL);
    }
}

WEAVE_ERROR WeaveDeviceManager::SetUnsecuredConnectionHandler()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (mIsUnsecuredConnectionListenerSet == false)
    {
        err = mMessageLayer->SetUnsecuredConnectionListener(HandleConnectionReceived,
            HandleUnsecuredConnectionCallbackRemoved, true, this);
        SuccessOrExit(err);

        mIsUnsecuredConnectionListenerSet = true;
    }

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceManager::ClearUnsecuredConnectionHandler()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (mIsUnsecuredConnectionListenerSet == true)
    {
        err = mMessageLayer->ClearUnsecuredConnectionListener(HandleConnectionReceived,
            HandleUnsecuredConnectionCallbackRemoved);
        SuccessOrExit(err);

        mIsUnsecuredConnectionListenerSet = false;
    }

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceManager::StartConnectDevice(uint64_t deviceId, IPAddress deviceAddr)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    InterfaceId targetIntf;

    VerifyOrExit(mDeviceCon == NULL, err = WEAVE_ERROR_INCORRECT_STATE);

#if WEAVE_PROGRESS_LOGGING
    {
        char ipAddrStr[64];
        deviceAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
        WeaveLogProgress(DeviceManager, "Initiating weave connection to device %llX (%s)", deviceId, ipAddrStr);
    }
#endif

    mDeviceCon = mMessageLayer->NewConnection();
    VerifyOrExit(mDeviceCon != NULL, err = WEAVE_ERROR_TOO_MANY_CONNECTIONS);

    mDeviceCon->AppState = this;
    mDeviceCon->OnConnectionComplete = HandleConnectionComplete;
    mDeviceCon->OnConnectionClosed = HandleConnectionClosed;

    mConState = kConnectionState_ConnectDevice;

    targetIntf = (mDeviceAddr.IsIPv6LinkLocal()) ? mDeviceIntf : INET_NULL_INTERFACEID;

    err = mDeviceCon->Connect(deviceId, kWeaveAuthMode_Unauthenticated, deviceAddr, WEAVE_PORT, targetIntf);
    SuccessOrExit(err);

exit:
    if (err != WEAVE_NO_ERROR)
        Close();
    return err;
}

void WeaveDeviceManager::HandleConnectionComplete(WeaveConnection *con, WEAVE_ERROR err)
{
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) con->AppState;

    // Bail immediately if not in the correct state.
    if (devMgr->mConState != kConnectionState_ConnectDevice)
    {
        WeaveLogProgress(DeviceManager, "Connection completed in wrong state = %d", devMgr->mConState);
        con->Close();
        return;
    }

    // If the connection succeeded...
    if (err == WEAVE_NO_ERROR)
    {
        WeaveLogProgress(DeviceManager, "Connected to device");

        if (devMgr->mOpState == kOpState_InitializeBleConnection) // If BLE connection...
        {
            //TODO Clean up this kludge:
            devMgr->mConState = kConnectionState_WaitDeviceConnect;

            devMgr->HandleConnectionReceived(devMgr->mMessageLayer, con);
        }
        else // Else, TCP connection...
        {
            // Reset the connection try counter. We will reuse this during session establishment.
            devMgr->mConTryCount = 0;

            // Initiate a secure session.
            err = devMgr->StartSession();
        }
    }
    else
    {
        if (err == WEAVE_ERROR_TIMEOUT )
        {
            err = WEAVE_ERROR_DEVICE_CONNECT_TIMEOUT;
        }
        WeaveLogProgress(DeviceManager, "Failed to connect to device: %s", ErrorStr(err));
    }

    if (err != WEAVE_NO_ERROR)
    {
        devMgr->Close();
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    }
}

void WeaveDeviceManager::HandleConnectionReceived(WeaveMessageLayer *msgLayer, WeaveConnection *con)
{
    WEAVE_ERROR             err     = WEAVE_NO_ERROR;
    WeaveDeviceManager*     devMgr  = sListeningDeviceMgr;
    PacketBuffer*           msgBuf  = NULL;
    IdentifyRequestMessage  reqMsg;

    if (devMgr != NULL && devMgr->mConState == kConnectionState_WaitDeviceConnect)
    {

#if WEAVE_PROGRESS_LOGGING
        if (devMgr->mOpState == kOpState_PassiveRendezvousDevice)
        {
            char ipAddrStr[64];
            con->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
            WeaveLogProgress(DeviceManager, "Received connection from device (%s)", ipAddrStr);
        }
        else if (devMgr->mOpState == kOpState_InitializeBleConnection)
        {
            WeaveLogProgress(DeviceManager, "Initializing Weave BLE connection");
        }
#endif

        // Let the app know we're starting the
        // authentication/provisioning process.
        if (devMgr->mOnStart)
        {
            devMgr->mOnStart(devMgr, devMgr->mAppReqState, con);
        }

        // Capture the connection object.
        devMgr->mDeviceCon = con;
        devMgr->mDeviceCon->AppState = devMgr;
        devMgr->mDeviceCon->OnConnectionClosed = HandleConnectionClosed;

        // Disallow further incoming connections. Since we can only process one connection at a time
        // we must do this even if the connecting device isn't the one we want to talk to.
        sListeningDeviceMgr = NULL;

        // Remove unsecured incoming connection handler if performing passive rendezvous.
        if (devMgr->mOpState == kOpState_PassiveRendezvousDevice)
        {
            err = devMgr->ClearUnsecuredConnectionHandler();
            SuccessOrExit(err);
        }

        // Encode an Identify device request message. Since we're doing this solely to get the device's
        // node id, we leave all criteria fields blank (i.e. wildcarded).
        msgBuf = PacketBuffer::New();
        VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);
        reqMsg.Reset();
        err = reqMsg.Encode(msgBuf);
        SuccessOrExit(err);

        // Construct an exchange context.
        devMgr->mCurReq = devMgr->mExchangeMgr->NewContext(con, devMgr);
        VerifyOrExit(devMgr->mCurReq != NULL, err = WEAVE_ERROR_NO_MEMORY);
        devMgr->mCurReq->OnMessageReceived = HandleConnectionIdentifyResponse;

        // Since we don't know the device's id yet, arrange to send the identify request to the 'Any' node id.
        devMgr->mCurReq->PeerNodeId = kAnyNodeId;

        WeaveLogProgress(DeviceManager, "Sending IdentifyRequest to device");

        devMgr->mConState = kConnectionState_IdentifyDevice;

        // Send the Identify message.
        err = devMgr->mCurReq->SendMessage(kWeaveProfile_DeviceDescription, kMessageType_IdentifyRequest, msgBuf, 0);
        msgBuf = NULL;
        SuccessOrExit(err);
    }
    else
    {
        WeaveLogError(DeviceManager, "Unexpected connection rxd, closing");
        con->Close();
    }

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);
    if (err != WEAVE_NO_ERROR && devMgr != NULL)
    {
        devMgr->Close();
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    }
}

void WeaveDeviceManager::HandleConnectionClosed(WeaveConnection *con, WEAVE_ERROR conErr)
{
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) con->AppState;

    devMgr->mConState = kConnectionState_NotConnected;

    if (devMgr->mDeviceCon == con)
        devMgr->mDeviceCon = NULL;
    con->Close();

    // Clear connection security info, cancel any timers, and clear OpState.
    devMgr->Close();

    // If we have a callback, invoke it,
    if (devMgr->mOnConnectionClosedFunc)
    {
        devMgr->mOnConnectionClosedFunc(devMgr, devMgr->mOnConnectionClosedAppReq, con, conErr);
    }

    WeaveLogProgress(DeviceManager, "Connection to device closed");
}

WEAVE_ERROR WeaveDeviceManager::StartSession()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Bump the counter every time we attempt to establish a secure session.
    mConTryCount++;

    switch (mAuthType)
    {
    case kAuthType_PASEWithPairingCode:
        WeaveLogProgress(DeviceManager, "Initiating PASE session");
        mConState = kConnectionState_StartSession;
        err = mSecurityMgr->StartPASESession(mDeviceCon, kWeaveAuthMode_PASE_PairingCode, this,
                                             HandleSessionEstablished, HandleSessionError,
                                             (const uint8_t *)mAuthKey, mAuthKeyLen);
        break;

    case kAuthType_CASEWithAccessToken:
        WeaveLogProgress(DeviceManager, "Initiating CASE session");
        mConState = kConnectionState_StartSession;
        // For compatibility with devices that pre-date CASE Config2, propose CASE Config1 in the
        // initial CASE BeginSessionRequest.  Later devices will recognize that the device manager
        // supports Config2 and force a reconfigure.
#if WEAVE_CONFIG_ENABLE_CASE_INITIATOR
        mSecurityMgr->InitiatorCASEConfig = Profiles::Security::CASE::kCASEConfig_Config1;
#endif
        err = mSecurityMgr->StartCASESession(mDeviceCon, mDeviceCon->PeerNodeId, mDeviceCon->PeerAddr, mDeviceCon->PeerPort,
                                             kWeaveAuthMode_CASE_Device, this,
                                             HandleSessionEstablished, HandleSessionError, this);
        break;

    case kAuthType_None:
        mSessionKeyId = WeaveKeyId::kNone;
        mEncType = kWeaveEncryptionType_None;
        ReenableConnectionMonitor();
        break;

    default:
        err = WEAVE_ERROR_INCORRECT_STATE;
        break;
    }

    return err;
}

void WeaveDeviceManager::HandleSessionEstablished(WeaveSecurityManager *sm, WeaveConnection *con, void *appReqState,
        uint16_t sessionKeyId, uint64_t peerNodeId, uint8_t encType)
{
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *)appReqState;

    // Bail immediately if not in the correct state.
    if (devMgr->mConState != kConnectionState_StartSession || con != devMgr->mDeviceCon)
    {
        WeaveLogError(DeviceManager, "Session established, wrong conState, closing connection");
        con->Close();
        return;
    }

    WeaveLogProgress(DeviceManager, "Secure session established");

    if (devMgr->mOpState == kOpState_RemotePassiveRendezvousAuthenticate)
    {
        WeaveLogProgress(DeviceManager, "Successfully authenticated remote device.");

        // Cancel RemotePassiveRendezvous timer. We have now completed the Remote Passive Rendezvous.
        devMgr->CancelRemotePassiveRendezvousTimer();
    }

    // Save the session key and encryption type for the new session. We will use these later when making requests
    // to the device.
    devMgr->mSessionKeyId = sessionKeyId;
    devMgr->mEncType = encType;

    // Re-enable the connection monitor if needed.
    devMgr->ReenableConnectionMonitor();
}

void WeaveDeviceManager::HandleSessionError(WeaveSecurityManager *sm, WeaveConnection *con, void *appReqState, WEAVE_ERROR localErr, uint64_t peerNodeId, StatusReport *statusReport)
{
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *)appReqState;
    DeviceStatus devStatus;
    DeviceStatus *devStatusArg = NULL;

    // Bail immediately if not in the correct state. May occur if the connection closes abruptly and the
    // SecurityManager's HandleConnectionClosed callback fires _after_ the DeviceManager's own callback.
    // In this case, con is already closed and mOnError has already been called, so we should just exit.
    if (devMgr->mConState != kConnectionState_StartSession)
    {
        return;
    }

    // Report the result.
    if (localErr == WEAVE_ERROR_STATUS_REPORT_RECEIVED && statusReport != NULL)
    {
        WeaveLogProgress(DeviceManager, "Secure session failed: %s", StatusReportStr(statusReport->mProfileId, statusReport->mStatusCode));
    }
    else
    {
        if (localErr == WEAVE_ERROR_TIMEOUT)
        {
            localErr = WEAVE_ERROR_DEVICE_AUTH_TIMEOUT;
        }
        WeaveLogProgress(DeviceManager, "Secure session failed: %s", ErrorStr(localErr));
    }

    // If the device returned a Common:Busy response, it likely means it's in a state where it can't perform
    // the crypto operations necessary to initiate a new session (e.g. because its busy establishing a secure
    // session with the service).  In this situation, we wait a little bit and retry the operation, but
    // only for a limited number of times.
    if (localErr == WEAVE_ERROR_STATUS_REPORT_RECEIVED && statusReport != NULL &&
        statusReport->mProfileId == kWeaveProfile_Common && statusReport->mStatusCode == Common::kStatus_Busy)
    {
        // If we haven't reached the retry limit yet...
        if (devMgr->mConTryCount < kMaxSessionRetryCount)
        {
            // Arm the retry timer.
            localErr = devMgr->mSystemLayer->StartTimer(kSessionRetryInterval, RetrySession, devMgr);
            if (localErr == WEAVE_NO_ERROR)
            {
                WeaveLogProgress(DeviceManager, "Retrying session establishment after %d ms", kSessionRetryInterval);
                return;
            }
        }
    }

    if (devMgr->mOpState == kOpState_RemotePassiveRendezvousAuthenticate)
    {
        // If we failed to authenticate a remote device as part of Remote Passive Rendezvous, give up on that
        // particular device and listen for the next remote passive rendezvous connection.
        devMgr->RestartRemotePassiveRendezvousListen();
    }
    else
    {
        // Close the connection.
        devMgr->Close();

        // Call the user's error callback.
        if (localErr == WEAVE_ERROR_STATUS_REPORT_RECEIVED && statusReport != NULL)
        {
            devStatus.StatusProfileId = statusReport->mProfileId;
            devStatus.StatusCode = statusReport->mStatusCode;
            devStatus.SystemErrorCode = 0;
            devStatusArg = &devStatus;
        }

        devMgr->mOnError(devMgr, devMgr->mAppReqState, localErr, devStatusArg);
    }
}

void WeaveDeviceManager::RetrySession(System::Layer* aSystemLayer, void* aAppState, System::Error aError)
{
    WeaveDeviceManager* lDevMgr  = reinterpret_cast<WeaveDeviceManager*>(aAppState);
    WEAVE_ERROR         lError = static_cast<WEAVE_ERROR>(aError);

    // Bail immediately if not in the right state. (This should never be the case.)
    if (lDevMgr->mConState != kConnectionState_StartSession)
        return;

    // Try again to establish a secure session.
    lError = lDevMgr->StartSession();

    if (lError != WEAVE_NO_ERROR)
    {
        lDevMgr->Close();
        lDevMgr->mOnError(lDevMgr, lDevMgr->mAppReqState, lError, NULL);
    }
}

void WeaveDeviceManager::RestartRemotePassiveRendezvousListen()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Close tunneled connection to remote device, if any, and reset rendezvous timer.
    CloseDeviceConnection();

    // Do not attempt reconnect as we timed out during authentication.
    if (mOpState == kOpState_RemotePassiveRendezvousTimedOut)
    {
        WeaveLogProgress(DeviceManager, "RemotePassiveRendezvous timed-out, not restarting");
        err = WEAVE_ERROR_TIMEOUT;
    }
    else
    {
        WeaveLogProgress(DeviceManager, "Restarting Remote Passive Rendezvous");

        // Nobody else is allowed to try anything while we're reconnecting to the assisting device.
        mOpState = kOpState_RestartRemotePassiveRendezvous;

        // Reconnect to assisting device and attempt to reuse existing secure session. Establish new secure session from
        // scratch if necessary.
        err = StartReconnectToAssistingDevice();
    }

    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogProgress(DeviceManager, "RestartRemotePassiveRendezvous failed");

        // Something went wrong, and we couldn't reconnect to the assisting device to continue the Remote Passive
        // Rendezvous. Use big DeviceManager hammer to reset timers and other state.
        Close();

        // Call application's OnError callback.
        mOnError(this, mAppReqState, err, NULL);
    }
}

void WeaveDeviceManager::ReenableConnectionMonitor()
{
    WEAVE_ERROR     err     = WEAVE_NO_ERROR;
    PacketBuffer*   msgBuf  = NULL;
    uint8_t*        p;

    if (mConMonitorEnabled)
    {
        mConState = kConnectionState_ReenableConnectionMonitor;

        msgBuf = PacketBuffer::New();
        VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

        p = msgBuf->Start();
        LittleEndian::Write16(p, mConMonitorTimeout);
        LittleEndian::Write16(p, mConMonitorInterval);
        msgBuf->SetDataLength(4);

        // Create and initialize an exchange context for the request.
        mCurReq = mExchangeMgr->NewContext(mDeviceId, this);
        VerifyOrExit(mCurReq != NULL, err = WEAVE_ERROR_NO_MEMORY);
        mCurReq->Con = mDeviceCon;
        mCurReq->KeyId = mSessionKeyId;
        mCurReq->EncryptionType = mEncType;
        mCurReq->OnMessageReceived = HandleReenableConnectionMonitorResponse;
        mCurReq->OnConnectionClosed = HandleRequestConnectionClosed;
        // OnResponseTimeout, OnRetransmit

        // TODO: setup request timeout

        // Send the current request over the connection.
        err = mCurReq->SendMessage(kWeaveProfile_DeviceControl, DeviceControl::kMsgType_EnableConnectionMonitor,
                msgBuf, 0);
        msgBuf = NULL;

    }
    else
        HandleConnectionReady();

exit:
    if (msgBuf != NULL)
        PacketBuffer::Free(msgBuf);

    if (err != WEAVE_NO_ERROR)
    {
        Close();
        mOnError(this, mAppReqState, err, NULL);
    }
}

void WeaveDeviceManager::HandleReenableConnectionMonitorResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo,
        const WeaveMessageInfo *msgInfo, uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;

    ec->Close();
    if (ec != devMgr->mCurReq)
        ExitNow();
    devMgr->mCurReq = NULL;

    if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        DeviceStatus devStatus;

        err = devMgr->DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        if (devStatus.StatusProfileId == kWeaveProfile_Common && devStatus.StatusCode == Common::kStatus_Success)
        {
            devMgr->StartConnectionMonitorTimer();

            devMgr->HandleConnectionReady();
        }
        else
        {
            devMgr->Close();
            devMgr->mOnError(devMgr, devMgr->mAppReqState, WEAVE_ERROR_STATUS_REPORT_RECEIVED, &devStatus);
        }
    }

    else
        err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;

exit:
    if (payload != NULL)
        PacketBuffer::Free(payload);
    if (err != WEAVE_NO_ERROR)
    {
        devMgr->Close();
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    }
}

void WeaveDeviceManager::HandleConnectionReady()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    mConState = kConnectionState_Connected;

    // Register to receive unsolicited EchoRequest messages from the device.
    err = mExchangeMgr->RegisterUnsolicitedMessageHandler(kWeaveProfile_Echo, kEchoMessageType_EchoRequest,
            mDeviceCon, HandleEchoRequest, this);
    SuccessOrExit(err);

    // If the operation being performed is RendezvousDevice, PassiveRendezvousDevice, ConnectDevice,
    // RemotePassiveRendezvousAuthenticate, InitializeBleConnection, or ReconnectDevice, complete the operation and
    // call the app's callback.
    if (mOpState == kOpState_ConnectDevice || mOpState == kOpState_RendezvousDevice ||
        mOpState == kOpState_PassiveRendezvousDevice || mOpState == kOpState_ReconnectDevice ||
        mOpState == kOpState_RemotePassiveRendezvousAuthenticate || mOpState == kOpState_RemotePassiveRendezvousTimedOut ||
        mOpState == kOpState_InitializeBleConnection)
    {
        ClearOpState();
        mOnComplete.General(this, mAppReqState);
    }

    // Otherwise, if another operation is waiting for the connection to become ready, send the operation's
    // request now.
    else if (mOpState != kOpState_Idle)
    {
        err = SendPendingRequest();
    }

exit:
    if (err != WEAVE_NO_ERROR)
    {
        ClearOpState();
        mOnError(this, mAppReqState, err, NULL);
    }
}

void WeaveDeviceManager::HandleIdentifyDeviceResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo,
        const WeaveMessageInfo *msgInfo, uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;
    OpState opState = devMgr->mOpState;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding request.
    if (ec != devMgr->mCurReq)
    {
        ec->Close();
        ExitNow();
    }

    // At this point the operation is effectively complete. Therefore we clear the current operation before
    // continuing. This is important because the user could start another operation during one of the callbacks
    // that happen below.
    devMgr->ClearOpState();

    // Decode and dispatch the response message.
    if (profileId == kWeaveProfile_DeviceDescription && msgType == DeviceDescription::kMessageType_IdentifyResponse)
    {
        IdentifyResponseMessage respMsg;

        VerifyOrExit(opState == kOpState_IdentifyDevice, err = WEAVE_ERROR_INVALID_MESSAGE_TYPE);

        // Parse the identify response.
        err = IdentifyResponseMessage::Decode(payload, respMsg);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        // Call the user's completion function.
        devMgr->mOnComplete.IdentifyDevice(devMgr, devMgr->mAppReqState, &respMsg.DeviceDesc);
    }

    else
        err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;

exit:
    if (err != WEAVE_NO_ERROR)
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    if (payload != NULL)
        PacketBuffer::Free(payload);
}

void WeaveDeviceManager::HandlePairTokenResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo,
        const WeaveMessageInfo *msgInfo, uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;
    OpState opState = devMgr->mOpState;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding request.
    if (ec != devMgr->mCurReq)
    {
        ec->Close();
        ExitNow();
    }

    VerifyOrExit(opState == kOpState_PairToken, err = WEAVE_ERROR_INVALID_MESSAGE_TYPE);

    if (profileId == kWeaveProfile_TokenPairing && msgType == TokenPairing::kMsgType_TokenCertificateResponse)
    {
        VerifyOrExit(devMgr->mTokenPairingCertificate == NULL, err = WEAVE_ERROR_INCORRECT_STATE);
        devMgr->mTokenPairingCertificate = (uint8_t *)malloc(payload->DataLength());
        VerifyOrExit(devMgr->mTokenPairingCertificate != NULL, err = WEAVE_ERROR_NO_MEMORY);
        memcpy(devMgr->mTokenPairingCertificate, payload->Start(), payload->DataLength());
        devMgr->mTokenPairingCertificateLen = payload->DataLength();
        // Do not clear op state yet.
    }
    else if (profileId == kWeaveProfile_TokenPairing && msgType == TokenPairing::kMsgType_TokenPairedResponse)
    {
        devMgr->ClearOpState();

        if (devMgr->mTokenPairingCertificate != NULL)
        {
            // TODO(jay): StitchTogether(payload, mTokenPairingCertificate, mTokenPairingCertificateLen);
            free(devMgr->mTokenPairingCertificate);
            devMgr->mTokenPairingCertificate = NULL;
            devMgr->mTokenPairingCertificateLen = 0;
        }

        devMgr->mOnComplete.PairToken(devMgr, devMgr->mAppReqState, payload->Start(), payload->DataLength());
    }
    else if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        DeviceStatus devStatus;

        devMgr->ClearOpState();

        err = devMgr->DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        if (devStatus.StatusProfileId == kWeaveProfile_Common && devStatus.StatusCode == Common::kStatus_Success)
        {
          // Protocol should only send kWeaveProfile_Common status on errors.
          err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;
        }
        else
        {
          devMgr->mOnError(devMgr, devMgr->mAppReqState, WEAVE_ERROR_STATUS_REPORT_RECEIVED, &devStatus);
          devMgr->ClearOpState();
        }
    }
    else
    {
        err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;
    }

exit:
    if (err != WEAVE_NO_ERROR)
    {
        devMgr->ClearOpState();
        if (devMgr->mTokenPairingCertificate != NULL)
        {
            free(devMgr->mTokenPairingCertificate);
            devMgr->mTokenPairingCertificate = NULL;
            devMgr->mTokenPairingCertificateLen = 0;
        }

        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    }
    if (payload != NULL)
        PacketBuffer::Free(payload);
}

void WeaveDeviceManager::HandleUnpairTokenResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo,
        const WeaveMessageInfo *msgInfo, uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;
    OpState opState = devMgr->mOpState;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding request.
    if (ec != devMgr->mCurReq)
    {
        ec->Close();
        ExitNow();
    }

    devMgr->ClearOpState();

    VerifyOrExit(opState == kOpState_UnpairToken, err = WEAVE_ERROR_INVALID_MESSAGE_TYPE);

    if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        DeviceStatus devStatus;

        err = devMgr->DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        if (devStatus.StatusProfileId == kWeaveProfile_Common && devStatus.StatusCode == Common::kStatus_Success)
            devMgr->mOnComplete.General(devMgr, devMgr->mAppReqState);
        else
            devMgr->mOnError(devMgr, devMgr->mAppReqState, WEAVE_ERROR_STATUS_REPORT_RECEIVED, &devStatus);
    }
    else
    {
      err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;
    }

exit:
    if (err != WEAVE_NO_ERROR)
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    if (payload != NULL)
        PacketBuffer::Free(payload);
}

void WeaveDeviceManager::HandleNetworkProvisioningResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
        uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;
    OpState opState = devMgr->mOpState;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding request.
    if (ec != devMgr->mCurReq)
    {
        ec->Close();
        ExitNow();
    }

    // At this point the operation is effectively complete. Therefore we clear the current operation before
    // continuing. This is important because the user could start another operation during one of the callbacks
    // that happen below.
    devMgr->ClearOpState();

    // Decode and dispatch the response message.
    if (profileId == kWeaveProfile_NetworkProvisioning && msgType == NetworkProvisioning::kMsgType_NetworkScanComplete)
    {
        VerifyOrExit(opState == kOpState_ScanNetworks, err = WEAVE_ERROR_INVALID_MESSAGE_TYPE);

        uint16_t resultCount = 0;
        NetworkInfo *netInfoList = NULL;

        err = DecodeNetworkInfoList(payload, resultCount, netInfoList);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        devMgr->mOnComplete.ScanNetworks(devMgr, devMgr->mAppReqState, resultCount, netInfoList);

        delete[] netInfoList;
    }

    else if (profileId == kWeaveProfile_NetworkProvisioning &&
             msgType == NetworkProvisioning::kMsgType_AddNetworkComplete)
    {
        VerifyOrExit(opState == kOpState_AddNetwork, err = WEAVE_ERROR_INVALID_MESSAGE_TYPE);

        uint16_t dataLen = payload->DataLength();
        VerifyOrExit(dataLen == 4, err = WEAVE_ERROR_INVALID_MESSAGE_LENGTH);

        uint32_t networkId = LittleEndian::Get32(payload->Start());

        PacketBuffer::Free(payload);
        payload = NULL;

        devMgr->mOnComplete.AddNetwork(devMgr, devMgr->mAppReqState, networkId);
    }

    else if (profileId == kWeaveProfile_NetworkProvisioning && msgType == NetworkProvisioning::kMsgType_GetNetworksComplete)
    {
        VerifyOrExit(opState == kOpState_GetNetworks, err = WEAVE_ERROR_INVALID_MESSAGE_TYPE);

        uint16_t resultCount = 0;
        NetworkInfo *netInfoList = NULL;

        err = DecodeNetworkInfoList(payload, resultCount, netInfoList);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        devMgr->mOnComplete.GetNetworks(devMgr, devMgr->mAppReqState, resultCount, netInfoList);

        delete[] netInfoList;
    }

    else if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        DeviceStatus devStatus;

        err = devMgr->DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        if (devStatus.StatusProfileId == kWeaveProfile_Common && devStatus.StatusCode == Common::kStatus_Success)
            devMgr->mOnComplete.General(devMgr, devMgr->mAppReqState);
        else
            devMgr->mOnError(devMgr, devMgr->mAppReqState, WEAVE_ERROR_STATUS_REPORT_RECEIVED, &devStatus);
    }

    else
        err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;

exit:
    if (err != WEAVE_NO_ERROR)
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    if (payload != NULL)
        PacketBuffer::Free(payload);
}

void WeaveDeviceManager::HandleServiceProvisioningResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
        uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding request.
    if (ec != devMgr->mCurReq)
    {
        ec->Close();
        ExitNow();
    }

    // At this point the operation is effectively complete. Therefore we clear the current operation before
    // continuing. This is important because the user could start another operation during one of the callbacks
    // that happen below.
    devMgr->ClearOpState();

    // Decode and dispatch the response message.
    if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        DeviceStatus devStatus;

        err = devMgr->DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        if (devStatus.StatusProfileId == kWeaveProfile_Common && devStatus.StatusCode == Common::kStatus_Success)
            devMgr->mOnComplete.General(devMgr, devMgr->mAppReqState);
        else
            devMgr->mOnError(devMgr, devMgr->mAppReqState, WEAVE_ERROR_STATUS_REPORT_RECEIVED, &devStatus);
    }

    else
        err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;

exit:
    if (err != WEAVE_NO_ERROR)
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    if (payload != NULL)
        PacketBuffer::Free(payload);
}

void WeaveDeviceManager::HandleFabricProvisioningResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
        uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;
    OpState savedOpState = devMgr->mOpState;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding request.
    if (ec != devMgr->mCurReq)
    {
        ec->Close();
        ExitNow();
    }

    // At this point the operation is effectively complete. Therefore we clear the current operation before
    // continuing. This is important because the user could start another operation during one of the callbacks
    // that happen below.
    devMgr->ClearOpState();

    // Decode and dispatch the response message.
    if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        DeviceStatus devStatus;

        err = devMgr->DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        if (devStatus.StatusProfileId == kWeaveProfile_Common && devStatus.StatusCode == Common::kStatus_Success)
            devMgr->mOnComplete.General(devMgr, devMgr->mAppReqState);
        else
            devMgr->mOnError(devMgr, devMgr->mAppReqState, WEAVE_ERROR_STATUS_REPORT_RECEIVED, &devStatus);
    }

    else if (profileId == kWeaveProfile_FabricProvisioning && msgType == nl::Weave::Profiles::FabricProvisioning::kMsgType_GetFabricConfigComplete)
    {
        VerifyOrExit(savedOpState == kOpState_GetFabricConfig, err = WEAVE_ERROR_INCORRECT_STATE);
        devMgr->mOnComplete.GetFabricConfig(devMgr, devMgr->mAppReqState, payload->Start(), payload->DataLength());
    }

    else
        err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;

exit:
    if (err != WEAVE_NO_ERROR)
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    if (payload != NULL)
        PacketBuffer::Free(payload);
}

void WeaveDeviceManager::HandleGetCameraAuthDataResponseEntry(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
        uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;

    devMgr->HandleGetCameraAuthDataResponse(ec, pktInfo, msgInfo, profileId, msgType, payload);
}

void WeaveDeviceManager::Eui48ToString(char *strBuf, uint8_t (&eui)[EUI48_LEN])
{
    // Generate string representation of camera's EUI-48 MAC address
    for (int idx = 0; idx < EUI48_LEN; idx++)
    {
        snprintf(&strBuf[idx * 2], 3, "%02X", eui[idx]);
    }
    strBuf[EUI48_STR_LEN - 1] = '\0';
}

void WeaveDeviceManager::HandleGetCameraAuthDataResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
        uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WeaveLogDetail(DeviceManager, "Entering HandleGetCameraAuthDataResponse");

    WEAVE_ERROR err = WEAVE_NO_ERROR;
    DeviceStatus devStatus;
    DeviceStatus *retDevStatus = NULL;
    OpState prevOpState = mOpState;
    uint8_t macAddress[EUI48_LEN];
    uint8_t hmac[HMAC_BUF_LEN];
    uint8_t authData[CAMERA_AUTH_DATA_LEN];
    char authDataStr[CAMERA_AUTH_DATA_LEN * 2]; // base64-encoded authData
    char macAddressStr[EUI48_STR_LEN];
    uint8_t *cursor;
    uint8_t idx;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding request.
    if (ec != mCurReq)
    {
        ec->Close();
        ExitNow();
    }

    // Decode and dispatch the response message.
    if (profileId == kWeaveProfile_DropcamLegacyPairing && msgType == kMsgType_CameraAuthDataResponse)
    {
        VerifyOrExit(prevOpState == kOpState_GetCameraAuthData, err = WEAVE_ERROR_INVALID_MESSAGE_TYPE);

        err = DecodeCameraAuthDataResponse(payload, macAddress, hmac);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        Eui48ToString(macAddressStr, macAddress);

        // Generate auth_data argument string for Dropcam setup.weave_start web API
        cursor = authData;

        memcpy(cursor, static_cast<void *>(macAddress), EUI48_LEN);
        cursor += EUI48_LEN;

        memcpy(cursor, static_cast<void *>(mCameraNonce), CAMERA_NONCE_LEN);
        cursor += CAMERA_NONCE_LEN;

        memcpy(cursor, hmac, CAMERA_HMAC_LEN);

        idx = Base64URLEncode(authData, CAMERA_AUTH_DATA_LEN, authDataStr);
        VerifyOrExit(idx > 0, err = WEAVE_END_OF_INPUT);
        authDataStr[idx] = '\0';

        // At this point the operation is effectively complete. Therefore we clear the current operation before
        // continuing. This is important because the user could start another operation in the callback below.
        ClearOpState();

        mOnComplete.GetCameraAuthData(this, mAppReqState, macAddressStr, authDataStr);
    }
    else if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        err = DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        err = WEAVE_ERROR_STATUS_REPORT_RECEIVED;
        retDevStatus = &devStatus;
    }
    else
    {
        err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;
    }

exit:
    if (payload != NULL)
    {
        PacketBuffer::Free(payload);
    }

    if (err != WEAVE_NO_ERROR)
    {
        // At this point the operation is effectively complete. Therefore we clear the current operation before
        // continuing. This is important because the user could start another operation in the callback below.
        ClearOpState();

        // Call application's error callback.
        mOnError(this, mAppReqState, err, retDevStatus);
    }
}

void WeaveDeviceManager::HandleDeviceControlResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
        uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WeaveLogDetail(DeviceManager, "Entering HandleDeviceControlReponse");

    WEAVE_ERROR err = WEAVE_NO_ERROR;
    DeviceStatus devStatus;
    DeviceStatus *retDevStatus = NULL;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;
    OpState prevOpState = devMgr->mOpState;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding request.
    if (ec != devMgr->mCurReq)
    {
        ec->Close();
        ExitNow();
    }

    // If we don't need to keep the exchange open for further Remote Passive Rendezovus messages, then at this point
    // the operation is effectively complete. Therefore we clear the current operation before continuing. This is
    // important because the user could start another operation during one of the callbacks that happen below.
    if (prevOpState != kOpState_RemotePassiveRendezvousRequest)
        devMgr->ClearOpState();

    // Decode and dispatch the response message.
    if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        err = devMgr->DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        if (devStatus.StatusProfileId == kWeaveProfile_Common && devStatus.StatusCode == Common::kStatus_Success)
        {
            // If operation was Remote Passive Rendezvous, don't notify the application of the RPR requests's success
            // via OnComplete, as we still need to actually rendezvous with a remote device. Instead, prepare to
            // receive a RemoteConnectionComplete or error messages, and set mOpState to prevent other DM clients from
            // sending messages over our connection to the assisting device until the RPR succeeds or fails.
            if (prevOpState == kOpState_RemotePassiveRendezvousRequest)
            {
                WeaveLogProgress(DeviceManager, "RemotePassiveRendezvousRequest succeeded");

                // Prepare to receive RemoteConnectionComplete or error message.
                devMgr->mCurReq->OnMessageReceived = HandleRemotePassiveRendezvousComplete;

                // Set mOpState to prevent Device Manager from sending messages to assisting device while
                // waiting for RemoteConnectionComplete message.
                devMgr->mOpState = kOpState_AwaitingRemoteConnectionComplete;
                SuccessOrExit(err);

                WeaveLogProgress(DeviceManager, "Waiting for RemoteConnectionComplete...");
            }
            else
            {
                // If operation was an EnableConnectionMonitor, and positive values were supplied for the interval
                // and timeout, then mark connection monitoring enabled locally and start the connection monitor
                // timer.
                if (prevOpState == kOpState_EnableConnectionMonitor &&
                    devMgr->mConMonitorInterval > 0 && devMgr->mConMonitorTimeout > 0)
                {
                    WeaveLogProgress(DeviceManager, "EnableConnectionMonitor Request succeeded");

                    devMgr->mConMonitorEnabled = true;
                    devMgr->StartConnectionMonitorTimer();
                }

                // Notify application of DeviceControl request's success.
                devMgr->mOnComplete.General(devMgr, devMgr->mAppReqState);
            }
        }
        else
        {
            err = WEAVE_ERROR_STATUS_REPORT_RECEIVED;
            retDevStatus = &devStatus;
        }
    }
    else
    {
        err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;
    }

exit:
    if (payload != NULL)
        PacketBuffer::Free(payload);

    if (err != WEAVE_NO_ERROR)
    {
        if (prevOpState == kOpState_RemotePassiveRendezvousRequest)
        {
            // Must close connection if we performed a Remote Passive Rendezvous request; if it succeeded, this
            // request revoked our ability to send further messages to the assisting device over the current
            // connection.
            devMgr->Close();
        }

        // Call application's error callback.
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, retDevStatus);
    }
}

void WeaveDeviceManager::HandleRemotePassiveRendezvousComplete(ExchangeContext *ec, const IPPacketInfo *pktInfo, const
        WeaveMessageInfo *msgInfo, uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    WeaveLogProgress(DeviceManager, "Entering HandleRemotePassiveRendezvousComplete");

    DeviceStatus devStatus;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding request.
    if (ec != devMgr->mCurReq)
    {
        ec->Close();
        ExitNow();
    }

    // At this point the operation is effectively complete. Therefore we clear the current operation before
    // continuing. This is important because the user could start another operation during one of the callbacks
    // that happen below.
    devMgr->ClearOpState();

    // Dispatch message.
    if (profileId == kWeaveProfile_DeviceControl && msgType == DeviceControl::kMsgType_RemoteConnectionComplete)
    {
        WeaveLogProgress(DeviceManager, "Received RemoteConnectionComplete");
        devMgr->HandleRemoteConnectionComplete();
    }
    else if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        err = devMgr->DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        if (devStatus.StatusProfileId == kWeaveProfile_DeviceControl && devStatus.StatusCode ==
                DeviceControl::kStatusCode_RemotePassiveRendezvousTimedOut)
        {
            WeaveLogProgress(DeviceManager, "RemotePassiveRendezvous timed out on assisting device");
            devMgr->CancelRemotePassiveRendezvous();
            err = WEAVE_ERROR_TIMEOUT;
        }
        else
        {
            WeaveLogProgress(DeviceManager, "Received unexpected status report, profile = %u, code = %u",
                    devStatus.StatusProfileId, devStatus.StatusCode);
            err = WEAVE_ERROR_STATUS_REPORT_RECEIVED;
        }
    }
    else
    {
        WeaveLogProgress(DeviceManager, "Received unexpected message type = %u", msgType);
        err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;
    }

exit:
    if (payload != NULL)
        PacketBuffer::Free(payload);

    if (err != WEAVE_NO_ERROR)
    {
        // Call application's error callback.
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, &devStatus);
    }
}

void WeaveDeviceManager::HandlePingResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
        uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;
    OpState opState = devMgr->mOpState;
    int i;
    uint8_t *data;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding request.
    if (ec != devMgr->mCurReq)
    {
        ec->Close();
        ExitNow();
    }

    // At this point the operation is effectively complete. Therefore we clear the current operation before
    // continuing. This is important because the user could start another operation during one of the callbacks
    // that happen below.
    devMgr->ClearOpState();

    // Verify that the outstanding operation is a ping.
    VerifyOrExit(opState == kOpState_Ping, err = WEAVE_ERROR_INCORRECT_STATE);

    // Decode and dispatch the response message.
    if (profileId == kWeaveProfile_Echo && msgType == kEchoMessageType_EchoResponse)
    {
        VerifyOrExit(payload->DataLength() == devMgr->mPingSize, err = WEAVE_ERROR_INVALID_ARGUMENT);

        // check test pattern
        data = payload->Start();
        for (i = 0; i < payload->DataLength(); i++) {
            VerifyOrExit(data[i] == (0xff & i), err = WEAVE_ERROR_INVALID_ARGUMENT);
        }

        PacketBuffer::Free(payload);
        payload = NULL;

        devMgr->mOnComplete.General(devMgr, devMgr->mAppReqState);
    }
    else if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        DeviceStatus devStatus;

        err = devMgr->DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        devMgr->mOnError(devMgr, devMgr->mAppReqState, WEAVE_ERROR_STATUS_REPORT_RECEIVED, &devStatus);
    }

    else
        err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;

exit:
    if (err != WEAVE_NO_ERROR)
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    if (payload != NULL)
        PacketBuffer::Free(payload);
}

void WeaveDeviceManager::HandleHushResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
        uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;
    OpState opState = devMgr->mOpState;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding request.
    VerifyOrExit(ec == devMgr->mCurReq, ec->Close());

    // At this point the operation is effectively complete. Therefore we clear the current operation before
    // continuing. This is important because the user could start another operation during one of the callbacks
    // that happen below.
    devMgr->ClearOpState();

    // Verify that the outstanding operation is a hush.
    VerifyOrExit(opState == kOpState_Hush, err = WEAVE_ERROR_INCORRECT_STATE);

    // Decode and dispatch the response message.
    if (profileId == kWeaveProfile_Alarm && msgType == kAlarmMessageType_AlarmHushResponse)
    {
        AlarmHushResponse alarmHushResponse;
        err = AlarmHushResponse::parse(payload, &alarmHushResponse);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        devMgr->mOnComplete.Hush(devMgr, devMgr->mAppReqState, alarmHushResponse.mHushResult, alarmHushResponse.mLength, alarmHushResponse.mConditions);
    }
    else if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        DeviceStatus devStatus;

        err = devMgr->DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        devMgr->mOnError(devMgr, devMgr->mAppReqState, WEAVE_ERROR_STATUS_REPORT_RECEIVED, &devStatus);
    }
    else
        err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;

exit:
    if (err != WEAVE_NO_ERROR)
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, NULL);
    if (payload != NULL)
        PacketBuffer::Free(payload);
}

void WeaveDeviceManager::StartConnectionMonitorTimer()
{
    if (mConMonitorEnabled && mConMonitorTimeout != 0)
    {
        mSystemLayer->StartTimer(mConMonitorTimeout, HandleConnectionMonitorTimeout, this);
    }
}

void WeaveDeviceManager::CancelConnectionMonitorTimer()
{
    mSystemLayer->CancelTimer(HandleConnectionMonitorTimeout, this);
}

void WeaveDeviceManager::HandleEchoRequest(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
        uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *)ec->AppState;

    WeaveLogProgress(DeviceManager, "EchoRequest received from device");

    // Send an Echo Response back to the device.
    ec->SendMessage(kWeaveProfile_Echo, kEchoMessageType_EchoResponse, payload);

    // Discard the exchange context.
    ec->Close();

    devMgr->StartConnectionMonitorTimer();
}

void WeaveDeviceManager::HandleConnectionMonitorTimeout(System::Layer* aSystemLayer, void* aAppState, System::Error aError)
{
    WeaveDeviceManager* lDevMgr  = reinterpret_cast<WeaveDeviceManager*>(aAppState);

    if (lDevMgr->mConMonitorEnabled)
    {
        OpState prevOpState = lDevMgr->mOpState;

        WeaveLogProgress(DeviceManager, "Connection monitor timeout");

        lDevMgr->Close();

        if (prevOpState != kOpState_Idle)
            lDevMgr->mOnError(lDevMgr, lDevMgr->mAppReqState, WEAVE_ERROR_TIMEOUT, NULL);
    }
}

WEAVE_ERROR WeaveDeviceManager::StartRemotePassiveRendezvousTimer()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    mSystemLayer->CancelTimer(HandleRemotePassiveRendezvousTimeout, this);

    if (mRemotePassiveRendezvousTimeout > 0)
    {
        // Start timer for mRemotePassiveRendezvousTimeout + 2 seconds. This allows time for the assisting device to
        // send the client an error message on timeout, in which case the client can keep its connection to the
        // assisting device open for further communication.
        err = mSystemLayer->StartTimer(secondsToMilliseconds(mRemotePassiveRendezvousTimeout) +
                secondsToMilliseconds(2),
                HandleRemotePassiveRendezvousTimeout,
                this);
        SuccessOrExit(err);

        mRemotePassiveRendezvousTimerIsRunning = true;
    }

exit:
    return err;
}

void WeaveDeviceManager::CancelRemotePassiveRendezvousTimer()
{
    // Mark timer as no longer running.
    mRemotePassiveRendezvousTimerIsRunning = false;

    mSystemLayer->CancelTimer(HandleRemotePassiveRendezvousTimeout, this);
}

void WeaveDeviceManager::HandleRemotePassiveRendezvousTimeout(System::Layer* aSystemLayer, void* aAppState, System::Error aError)
{
    WeaveDeviceManager* lDevMgr  = reinterpret_cast<WeaveDeviceManager*>(aAppState);

    // Mark timer as no longer running.
    lDevMgr->mRemotePassiveRendezvousTimerIsRunning = false;

    // Close() existing connection to assisting device or remote device, if any, and reset associated state.
    if (lDevMgr->mOpState != kOpState_RemotePassiveRendezvousAuthenticate)
    {
        WeaveLogProgress(DeviceManager, "Remote Passive Rendezvous timed out");

        lDevMgr->Close();
        lDevMgr->mOnError(lDevMgr, lDevMgr->mAppReqState, WEAVE_ERROR_TIMEOUT, NULL);
    }
    else
    {
        lDevMgr->mOpState = kOpState_RemotePassiveRendezvousTimedOut;
    }
}

void WeaveDeviceManager::HandleRemoteConnectionComplete()
{
    WEAVE_ERROR             err     = WEAVE_NO_ERROR;
    IdentifyRequestMessage  reqMsg;
    PacketBuffer*           msgBuf  = NULL;

    // We can't auto-reconnect to a remote device, as it may not even be on our network.
    mAutoReconnect = false;

    // Set OpState. No other actions allowed until we've identified and authenticated the remote device.
    mOpState = kOpState_RemotePassiveRendezvousAuthenticate;

    // Save info required to reconnect to assisting device in case we don't immediately rendezvous with the correct
    // joiner.
    err = SaveAssistingDeviceConnectionInfo();
    SuccessOrExit(err);

    // We are now connected to a remote device via a WeaveConnectionTunnel, so enable this flag to prevent
    // the use of auto-reconnect, as to do so wouldn't make sense in this context.
    mConnectedToRemoteDevice = true;

    // Reset existing session and connection state, as we've effectively connected to a new device.
    ResetConnectionInfo();

    // We must explicitly encode a source node ID in every message sent to the remote host. If we do not, the
    // Weave stack assumes that the recipient of our messages can infer this ID from our ULA. However, in the
    // Remote Passive Rendezvous case, the remote host cannot 'see' our ULA, only the address of the assisting
    // device. Thus we must explictly encode our source node ID so the remote host returns messages to us with
    // the correct destination ID.
    mDeviceCon->SendSourceNodeId = true;

    // Prepare to authenticate with the new device.
    mAuthType = mRemoteDeviceAuthType;
    if (mAuthType != kAuthType_None)
    {
        err = SaveAuthKey(static_cast<const uint8_t *>(mRemoteDeviceAuthKey), mRemoteDeviceAuthKeyLen);
        SuccessOrExit(err);
    }

    // Encode an Identify device request message. Since we're doing this solely to get the device's
    // node id, we leave all criteria fields blank (i.e. wildcarded).
    msgBuf = PacketBuffer::New();
    VerifyOrExit(msgBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    reqMsg.Reset();
    err = reqMsg.Encode(msgBuf);
    SuccessOrExit(err);

    // Construct an exchange context.
    mCurReq = mExchangeMgr->NewContext(mDeviceCon, this);
    VerifyOrExit(mCurReq != NULL, err = WEAVE_ERROR_NO_MEMORY);
    mCurReq->ResponseTimeout = secondsToMilliseconds(5);
    mCurReq->OnMessageReceived = HandleRemoteIdentifyResponse;
    mCurReq->OnConnectionClosed = HandleRemoteIdentifyConnectionClosed;
    mCurReq->OnRetransmissionTimeout = HandleRemoteIdentifyTimeout;
    mCurReq->OnResponseTimeout = HandleRemoteIdentifyTimeout;

    // Since we don't know the device's id yet, arrange to send the identify request to the 'Any' node id.
    mCurReq->PeerNodeId = kAnyNodeId;

    WeaveLogProgress(DeviceManager, "Sending RPR IdentifyRequest to remote device");

    mConState = kConnectionState_IdentifyRemoteDevice;

    // Send the Identify message.
    err = mCurReq->SendMessage(kWeaveProfile_DeviceDescription, kMessageType_IdentifyRequest, msgBuf, 0);
    msgBuf = NULL;
    SuccessOrExit(err);

    WeaveLogProgress(DeviceManager, "Sent IdentifyRequest successfully");

exit:
    if (msgBuf != NULL)
    {
        PacketBuffer::Free(msgBuf);
    }

    if (err == WEAVE_ERROR_WRONG_ENCRYPTION_TYPE)
    {
        // If message had wrong encryption type, i.e. was potentially spoofed, ignore it and continue listening for
        // the authentic Remote Connection Complete.
        WeaveLogError(DeviceManager, "Rxd RemoteConnectionComplete w/ bogus encryption, discarding");
    }
    else if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "Failed send RPR Identify req, err = %d", err);

        // Halt Remote Passive Rendezvous process and close connection to assisting device, as we entered Remote
        // Passive Rendezvous connected state and can no longer send Weave messages to the assisting device on the
        // current connection.
        Close();

        // Call application's OnError callback.
        mOnError(this, mAppReqState, err, NULL);
    }
}

void WeaveDeviceManager::HandleRemoteIdentifyResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo,
        const WeaveMessageInfo *msgInfo, uint32_t profileId, uint8_t msgType, PacketBuffer *payload)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;
    DeviceStatus devStatus;
    DeviceStatus *devStatusPtr = NULL;

    // Sanity check that the passed-in exchange context is in fact the one that represents the current
    // outstanding operation.
    if (ec != devMgr->mCurReq)
    {
        ec->Close();
        PacketBuffer::Free(payload);
        ExitNow(err = WEAVE_ERROR_INCORRECT_STATE);
    }

    // Discard the exchange context.
    devMgr->mCurReq->Close();
    devMgr->mCurReq = NULL;

    // Verify that we're in the correct connection state.
    VerifyOrExit(devMgr->mConState == kConnectionState_IdentifyRemoteDevice,
            err = WEAVE_ERROR_INCORRECT_STATE);

    // If we got an Identify response...
    if (profileId == kWeaveProfile_DeviceDescription && msgType == kMessageType_IdentifyResponse)
    {
#if WEAVE_PROGRESS_LOGGING
        {
            char msgSourceStr[WEAVE_MAX_MESSAGE_SOURCE_STR_LENGTH];
            WeaveMessageSourceToStr(msgSourceStr, sizeof(msgSourceStr), msgInfo);
            WeaveLogProgress(DeviceManager, "Received RPR identify response from device %s", msgSourceStr); //TODO get remote IP address from RemoteConnectionComplete msg
        }
#endif

        // Save only the id of the device that responded. Since we've connected to this device
        // via Remote Passive Rendezvous, the device address and interface are not useful to us.
        //
        // NOTE that, since this interaction was unsecured, this is only the PURPORTED id
        // of the device.  Once we establish a secure session with the device, we will know for sure
        // that this is the device's id.
        IdentifyResponseMessage respMsg;
        err = IdentifyResponseMessage::Decode(payload, respMsg);
        SuccessOrExit(err);

        PacketBuffer::Free(payload);
        payload = NULL;

        // Note that usually device ID in DeviceDesc is not set, and receiver is supposed to
        // use the source node id in message header as the purported device ID
        devMgr->mDeviceId = msgInfo->SourceNodeId;

        if (devMgr->mDeviceCon != NULL && devMgr->mDeviceCon->PeerNodeId == kNodeIdNotSpecified)
        {
            WeaveLogProgress(DeviceManager, "Setting mDeviceCon source node ID = %llX", devMgr->mDeviceId);
            devMgr->mDeviceCon->PeerNodeId = devMgr->mDeviceId;
        }

        // Initiate a secure session.
        err = devMgr->StartSession();
        SuccessOrExit(err);
    }
    // If we got a status report...
    else if (profileId == kWeaveProfile_Common && msgType == nl::Weave::Profiles::Common::kMsgType_StatusReport)
    {
        // Decode the supplied status report.
        err = devMgr->DecodeStatusReport(payload, devStatus);
        SuccessOrExit(err);

        devStatusPtr = &devStatus;

        // Disconnect from remote device and listen for the next rendezvous connection if we got a status report.
        devMgr->RestartRemotePassiveRendezvousListen();
    }
    // If we got something unexpected...
    else
    {
        // Disconnect from remote device and listen for the next rendezvous connection if we got an unexpected
        // profile or message type.
        devMgr->RestartRemotePassiveRendezvousListen();
    }

exit:
    if (payload != NULL)
        PacketBuffer::Free(payload);

    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "Failed handle RPR Id rx, err = %d", err);

        // Halt Remote Passive Rendezvous process and close connection to assisting device, as we entered Remote
        // Passive Rendezvous connected state and can no longer send Weave messages to the assisting device on the
        // current connection.
        devMgr->Close();

        // Call application's OnError callback.
        devMgr->mOnError(devMgr, devMgr->mAppReqState, err, devStatusPtr);
    }
}

void WeaveDeviceManager::HandleRemoteIdentifyConnectionClosed(ExchangeContext *ec, WeaveConnection *con,
    WEAVE_ERROR conErr)
{
    WeaveLogError(DeviceManager, "RPR connection closed during remote Id");
    WeaveDeviceManager *devMgr = (WeaveDeviceManager *) ec->AppState;

    if (con == devMgr->mDeviceCon)
        devMgr->mDeviceCon = NULL;

    // Continue with RPR regardless of conErr, as there may be other devices with which to rendezvous.
    devMgr->RestartRemotePassiveRendezvousListen();
}

void WeaveDeviceManager::HandleRemoteIdentifyTimeout(ExchangeContext *ec)
{
    WeaveLogError(DeviceManager, "RPR Id timed out");
    WeaveDeviceManager *devMgr = static_cast<WeaveDeviceManager *>(ec->AppState);

    // Continue with RPR, as there may be other devices with which to rendezvous.
    devMgr->RestartRemotePassiveRendezvousListen();
}

WEAVE_ERROR WeaveDeviceManager::DecodeStatusReport(PacketBuffer *msgBuf, DeviceStatus& status)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    TLVReader reader;
    uint8_t *p = msgBuf->Start();
    uint16_t dataLen = msgBuf->DataLength();
    TLVType containingType;

    static const uint64_t SystemErrorCodeTag = ProfileTag(kWeaveProfile_Common, Common::kTag_SystemErrorCode);

    VerifyOrExit(dataLen >= 6, err = WEAVE_ERROR_INVALID_MESSAGE_LENGTH);

    status.StatusProfileId = LittleEndian::Read32(p);
    status.StatusCode = LittleEndian::Read16(p);

    if (dataLen > 6)
    {
        msgBuf->SetStart(p);

        reader.Init(msgBuf);

        err = reader.Next();
        SuccessOrExit(err);

        VerifyOrExit(reader.GetType() == kTLVType_Structure, err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);

        err = reader.EnterContainer(containingType);
        SuccessOrExit(err);

        while ((err = reader.Next()) == WEAVE_NO_ERROR)
        {
            if (reader.GetTag() == SystemErrorCodeTag)
            {
                VerifyOrExit(reader.GetType() == kTLVType_UnsignedInteger, err = WEAVE_ERROR_WRONG_TLV_TYPE);
                err = reader.Get(status.SystemErrorCode);
                SuccessOrExit(err);
            }
        }

        if (err != WEAVE_END_OF_TLV)
            ExitNow();

        err = reader.ExitContainer(containingType);
        SuccessOrExit(err);

        err = reader.Next();
        if (err != WEAVE_END_OF_TLV)
            ExitNow(err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);
        err = WEAVE_NO_ERROR;
    }
    else
        status.SystemErrorCode = WEAVE_NO_ERROR;

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceManager::DecodeNetworkInfoList(PacketBuffer *msgBuf, uint16_t& count,
        NetworkInfo *& netInfoList)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    TLVReader reader;
    uint8_t *p = msgBuf->Start();
    uint16_t dataLen = msgBuf->DataLength();

    netInfoList = NULL;

    VerifyOrExit(dataLen >= 2, err = WEAVE_ERROR_INVALID_MESSAGE_LENGTH);

    count = Read8(p);

    msgBuf->SetStart(p);
    reader.Init(msgBuf);
    reader.ImplicitProfileId = kWeaveProfile_NetworkProvisioning;

    err = reader.Next();
    SuccessOrExit(err);

    err = NetworkInfo::DecodeList(reader, count, netInfoList);
    SuccessOrExit(err);

    err = reader.Next();
    if (err != WEAVE_END_OF_TLV)
    {
        if (err == WEAVE_NO_ERROR)
            err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT;
        ExitNow();
    }

    return WEAVE_NO_ERROR;

exit:
    if (err != WEAVE_NO_ERROR)
        delete[] netInfoList;
    return err;
}

WEAVE_ERROR WeaveDeviceManager::GetNodeCertInfo(bool isInitiator, uint8_t *buf, uint16_t bufSize, uint16_t& certInfoLen)
{
    WEAVE_ERROR err;

    // Decode the supplied access token and generate a CASE Certificate Info TLV structure
    // containing the certificate(s) from the access token.
    err = CASECertInfoFromAccessToken((const uint8_t *)mAuthKey, mAuthKeyLen, buf, bufSize, certInfoLen);
    SuccessOrExit(err);

exit:
    if (err != WEAVE_NO_ERROR)
        err = WEAVE_ERROR_INVALID_ACCESS_TOKEN;
    return err;
}

// Get the local node's private key.
WEAVE_ERROR WeaveDeviceManager::GetNodePrivateKey(bool isInitiator, const uint8_t *& weavePrivKey, uint16_t& weavePrivKeyLen)
{
    WEAVE_ERROR err;
    uint8_t *privKeyBuf = NULL;

    // Allocate a buffer to hold the private key.  Since the key is held within the access token, a
    // buffer as big as the access token will always be sufficient.
    privKeyBuf = (uint8_t *)malloc(mAuthKeyLen);
    VerifyOrExit(privKeyBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    // Extract the private key from the access token, converting the encoding to a EllipticCurvePrivateKey TLV object.
    err = ExtractPrivateKeyFromAccessToken((const uint8_t *)mAuthKey, mAuthKeyLen, privKeyBuf, mAuthKeyLen, weavePrivKeyLen);
    SuccessOrExit(err);

    // Pass the extracted key back to the caller.
    weavePrivKey = privKeyBuf;
    privKeyBuf = NULL;

exit:
    if (err != WEAVE_NO_ERROR)
        err = WEAVE_ERROR_INVALID_ACCESS_TOKEN;
    if (privKeyBuf != NULL)
        free(privKeyBuf);
    return err;
}

// Called when the CASE engine is done with the buffer returned by GetNodePrivateKey().
WEAVE_ERROR WeaveDeviceManager::ReleaseNodePrivateKey(const uint8_t *weavePrivKey)
{
    free((void *)weavePrivKey);
    return WEAVE_NO_ERROR;
}

// Get payload information, if any, to be included in the message to the peer.
WEAVE_ERROR WeaveDeviceManager::GetNodePayload(bool isInitiator, uint8_t *buf, uint16_t bufSize, uint16_t& payloadLen)
{
    // No payload
    payloadLen = 0;
    return WEAVE_NO_ERROR;
}

// Prepare the supplied certificate set and validation context for use in validating the certificate of a peer.
// This method is responsible for loading the trust anchors into the certificate set.
WEAVE_ERROR WeaveDeviceManager::BeginCertValidation(bool isInitiator, WeaveCertificateSet& certSet, ValidationContext& validContext)
{
    WEAVE_ERROR err;
    WeaveCertificateData *cert;

    err = certSet.Init(kMaxCASECerts, kCertDecodeBufferSize);
    SuccessOrExit(err);

    err = certSet.LoadCert(nl::NestCerts::Development::Root::Cert, nl::NestCerts::Development::Root::CertLength, 0, cert);
    SuccessOrExit(err);
    cert->CertFlags |= kCertFlag_IsTrusted;

    err = certSet.LoadCert(nl::NestCerts::Production::Root::Cert, nl::NestCerts::Production::Root::CertLength, 0, cert);
    SuccessOrExit(err);
    cert->CertFlags |= kCertFlag_IsTrusted;

    err = certSet.LoadCert(nl::NestCerts::Development::DeviceCA::Cert, nl::NestCerts::Development::DeviceCA::CertLength, kDecodeFlag_GenerateTBSHash, cert);
    SuccessOrExit(err);

    err = certSet.LoadCert(nl::NestCerts::Production::DeviceCA::Cert, nl::NestCerts::Production::DeviceCA::CertLength, kDecodeFlag_GenerateTBSHash, cert);
    SuccessOrExit(err);

    memset(&validContext, 0, sizeof(validContext));
    validContext.EffectiveTime = SecondsSinceEpochToPackedCertTime(time(NULL));
    validContext.RequiredKeyUsages = kKeyUsageFlag_DigitalSignature;
    validContext.RequiredKeyPurposes = (isInitiator) ? kKeyPurposeFlag_ServerAuth : kKeyPurposeFlag_ClientAuth;

exit:
    return err;
}

// Called with the results of validating the peer's certificate.
WEAVE_ERROR WeaveDeviceManager::HandleCertValidationResult(bool isInitiator, WEAVE_ERROR& validRes,
        WeaveCertificateData *peerCert, uint64_t peerNodeId, WeaveCertificateSet& certSet, ValidationContext& validContext)
{
    // If the device's certificate is otherwise valid, make sure its subject DN matches the expected device id.
    if (validRes == WEAVE_NO_ERROR)
    {
        // Verify that the device authenticated with a device certificate. If so...
        if (peerCert->CertType == kCertType_Device)
        {
            // Get the node id from the certificate subject.
            uint64_t certDeviceId = peerCert->SubjectDN.AttrValue.WeaveId;

            // This is a work-around for Nest DVT devices that were built with incorrect certificates.
            // Specifically, the device id in the certificate didn't include Nest's OUI (the first
            // 3 bytes of the EUI-64 that makes up the id). Here we grandfather these in by assuming
            // anything that has an OUI of 0 is in fact a Nest device.
            if ((certDeviceId & 0xFFFFFF0000000000ULL) == 0)
                certDeviceId |= 0x18B4300000000000ULL;

            // Verify the target device id against the device id in the certificate.
            if (mDeviceId != kAnyNodeId && certDeviceId != mDeviceId)
                validRes = WEAVE_ERROR_WRONG_CERT_SUBJECT;
        }

        // Otherwise reject the session.
        else
        {
            validRes = WEAVE_ERROR_WRONG_CERT_TYPE;
        }
    }

    return WEAVE_NO_ERROR;
}

// Called when peer certificate validation is complete.
WEAVE_ERROR WeaveDeviceManager::EndCertValidation(WeaveCertificateSet& certSet, ValidationContext& validContext)
{
    // Nothing to do
    return WEAVE_NO_ERROR;
}

bool IsProductWildcard(uint16_t productId)
{
    return (productId >= kProductWildcardId_RangeStart && productId <= kProductWildcardId_RangeEnd);
}

WeaveDeviceManager::WDMDMClient::WDMDMClient(void)
{
    mDeviceMgr = NULL;
}

WeaveDeviceManager::WDMDMClient::~WDMDMClient(void)
{
    mDeviceMgr = NULL;
}

WEAVE_ERROR WeaveDeviceManager::WDMDMClient::InitClient(WeaveDeviceManager *aDeviceMgr, WeaveExchangeManager *aExchangeMgr)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    err = DMClient::Init(aExchangeMgr);
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "%s DMClient::Init() failed: %s", __PRETTY_FUNCTION__, ErrorStr(err));
    }
    else
    {
        mDeviceMgr = aDeviceMgr;
    }

    return err;
}

WEAVE_ERROR WeaveDeviceManager::WDMDMClient::ViewConfirm(const uint64_t &aResponderId, StatusReport &aStatus, uint16_t aTxnId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    WeaveLogProgress(DeviceManager, "%s - non-success status", __PRETTY_FUNCTION__);

    if (mDeviceMgr)
    {
        mDeviceMgr->ClearOpState();
        mDeviceMgr->mOnComplete.General(mDeviceMgr, mDeviceMgr->mAppReqState);
    }

    return err;
}

WEAVE_ERROR WeaveDeviceManager::WDMDMClient::ViewConfirm(const uint64_t &aResponderId, ReferencedTLVData &aDataList, uint16_t aTxnId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    TLVReader dataListRdr;
    TLVReader pathRdr;
    TLVReader containerRdr;
    TLVType pathContainer;
    TLVType profileContainer;
    uint64_t version;
    uint32_t profileId;
    uint64_t tagViewed;
    uint32_t bufSize;
    char *buf = NULL;
    uint16_t index;
    uint16_t localeNum = 0;
    char **localeList = NULL;

    WeaveLogProgress(DeviceManager, "%s - success status", __PRETTY_FUNCTION__);
    if (mDeviceMgr)
    {
        mDeviceMgr->ClearOpState();
    }

    OpenDataList(aDataList, dataListRdr);
    SuccessOrExit(err);

    err = dataListRdr.Next();
    SuccessOrExit(err);

    err = OpenDataListElement(dataListRdr, pathRdr, version);
    SuccessOrExit(err);

    VerifyOrExit(pathRdr.GetType() == kTLVType_Path, err = WEAVE_ERROR_WRONG_TLV_TYPE);

    err = ValidateWDMTag(kTag_WDMDataListElementPath, pathRdr);
    SuccessOrExit(err);

    err = pathRdr.EnterContainer(pathContainer);
    SuccessOrExit(err);

    err = pathRdr.Next();
    SuccessOrExit(err);

    VerifyOrExit(pathRdr.GetType() == kTLVType_Structure, err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);

    err = ValidateWDMTag(kTag_WDMPathProfile, pathRdr);
    SuccessOrExit(err);

    err = pathRdr.EnterContainer(profileContainer);
    SuccessOrExit(err);

    err = pathRdr.Next();
    SuccessOrExit(err);

    err = ValidateWDMTag(kTag_WDMPathProfileId, pathRdr);
    SuccessOrExit(err);

    err = pathRdr.Get(profileId);
    SuccessOrExit(err);

    err = pathRdr.ExitContainer(profileContainer);
    SuccessOrExit(err);

    err = pathRdr.Next();
    SuccessOrExit(err);

    tagViewed = pathRdr.GetTag();
    switch (profileId)
    {
        case kWeaveProfile_NestThermostat:
            WeaveLogProgress(DeviceManager, "View Nest Thermostat");
            if (tagViewed == ProfileTag(kWeaveProfile_NestThermostat, Vendor::Nestlabs::Thermostat::kTag_LegacyEntryKey))
            {
                bufSize = dataListRdr.GetLength() + 1;
                buf = (char *)malloc(bufSize);
                err = dataListRdr.GetString(buf, bufSize);
                SuccessOrExit(err);
                WeaveLogProgress(DeviceManager, "entry key = %s", buf);
                if (mDeviceMgr)
                {
                    mDeviceMgr->mOnComplete.ThermostatGetEntryKey(mDeviceMgr, mDeviceMgr->mAppReqState, buf);
                }
            }
            else if (tagViewed == ProfileTag(kWeaveProfile_NestThermostat, Vendor::Nestlabs::Thermostat::kTag_SystemTestStatusKey))
            {
                uint64_t status = UINT64_MAX;
                err = dataListRdr.Get(status);
                SuccessOrExit(err);
                WeaveLogProgress(DeviceManager, "system test status = %llu", status);
                if (mDeviceMgr)
                {
                    mDeviceMgr->mOnComplete.ThermostatSystemStatus(mDeviceMgr, mDeviceMgr->mAppReqState, status);
                }
            }
            else
            {
                WeaveLogError(DeviceManager, "Unsupported nest thermostat tag: %llu", tagViewed);
                err = WEAVE_ERROR_INCORRECT_STATE;
            }
            break;

        case kWeaveProfile_Locale:
            WeaveLogProgress(DeviceManager, "View Locale");
            if (tagViewed == ProfileTag(kWeaveProfile_Locale, Locale::kTag_ActiveLocale))
            {
                bufSize = dataListRdr.GetLength() + 1;
                buf = (char *)malloc(bufSize);
                err = dataListRdr.GetString(buf, bufSize);
                SuccessOrExit(err);
                WeaveLogProgress(DeviceManager, "active locale = %s", buf);
                if (mDeviceMgr)
                {
                    mDeviceMgr->mOnComplete.GetActiveLocale(mDeviceMgr, mDeviceMgr->mAppReqState, buf);
                }
            }
            else if (tagViewed == ProfileTag(kWeaveProfile_Locale, Locale::kTag_AvailableLocales))
            {
                err = dataListRdr.OpenContainer(containerRdr);
                SuccessOrExit(err);

                while (containerRdr.Next() == WEAVE_NO_ERROR)
                {
                    localeNum++;
                }
                WeaveLogProgress(DeviceManager, "#available locales = %d", localeNum);

                err = dataListRdr.OpenContainer(containerRdr);
                SuccessOrExit(err);

                localeList = (char **)malloc(sizeof(char *) * localeNum);
                for (index = 0; containerRdr.Next() == WEAVE_NO_ERROR; index++)
                {
                    localeList[index] = (char *)malloc(128);
                    err = containerRdr.GetString(localeList[index], 128);
                    SuccessOrExit(err);
                    WeaveLogProgress(DeviceManager, "\t%s", localeList[index]);
                }

                err = dataListRdr.CloseContainer(containerRdr);
                SuccessOrExit(err);

                if (mDeviceMgr)
                {
                    mDeviceMgr->mOnComplete.GetAvailableLocales(mDeviceMgr, mDeviceMgr->mAppReqState, localeNum, (const char **)localeList);
                }
            }
            else
            {
                WeaveLogError(DeviceManager, "Unsupported nest thermostat tag: %llu", tagViewed);
                err = WEAVE_ERROR_INCORRECT_STATE;
            }
            break;

        default:
            WeaveLogError(DeviceManager, "Unknown profileId: %llu", profileId);
            err = WEAVE_ERROR_INCORRECT_STATE;
            break;
    }

exit:
    if (buf != NULL)
    {
        free(buf);
    }
    if (localeList != NULL && localeNum > 0)
    {
        for (index = 0; index < localeNum; index++)
        {
            free(localeList[index]);
        }
    }
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceManager, "%s failed: %s", __FUNCTION__, ErrorStr(err));
        if (mDeviceMgr)
        {
            mDeviceMgr->mOnError(mDeviceMgr, mDeviceMgr->mAppReqState, err, NULL);
        }
    }
    return err;
}

WEAVE_ERROR WeaveDeviceManager::WDMDMClient::UpdateConfirm(const uint64_t &aResponderId, StatusReport &aStatus, uint16_t aTxnId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    WeaveLogProgress(DeviceManager, "%s", __PRETTY_FUNCTION__);

    if (mDeviceMgr)
    {
        mDeviceMgr->ClearOpState();
        mDeviceMgr->mOnComplete.General(mDeviceMgr, mDeviceMgr->mAppReqState);
    }

    return err;
}

void WeaveDeviceManager::WDMDMClient::IncompleteIndication(const uint64_t &aPeerNodeId, StatusReport &aReport)
{

/*
 * this was added as a result of the fix to WEAV-142 and related
 * jiras. the code that belongs here is whatever the application wants
 * to do in case of a binding failure. at this point, the main (really
 * only) reason a binding will fail is the unexpected closure of a TCP
 * connection that supports it. in future, other failure scenarios may
 * arise.
 */

}

#if WEAVE_CONFIG_WDM_ALLOW_CLIENT_SUBSCRIPTION

WEAVE_ERROR WeaveDeviceManager::WDMDMClient::SubscribeConfirm(const uint64_t &aResponderId, const TopicIdentifier &aTopicId, uint16_t aTxnId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    return err;
}

WEAVE_ERROR WeaveDeviceManager::WDMDMClient::SubscribeConfirm(const uint64_t &aResponderId, const TopicIdentifier &aTopicId, ReferencedTLVData &aDataList, uint16_t aTxnId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    return err;
}

WEAVE_ERROR WeaveDeviceManager::WDMDMClient::SubscribeConfirm(const uint64_t &aResponderId, StatusReport &aStatus, uint16_t aTxnId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    return err;
}

WEAVE_ERROR WeaveDeviceManager::WDMDMClient::UnsubscribeIndication(const uint64_t &aPublisherId, const TopicIdentifier &aTopicId, StatusReport &aReport)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    return err;
}

WEAVE_ERROR WeaveDeviceManager::WDMDMClient::CancelSubscriptionConfirm(const uint64_t &aResponderId, const TopicIdentifier &aTopicId, StatusReport &aStatus, uint16_t aTxnId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    return err;
}

WEAVE_ERROR WeaveDeviceManager::WDMDMClient::NotifyIndication(const TopicIdentifier &aTopicId, ReferencedTLVData &aDataList)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    return err;
}

#endif // WEAVE_CONFIG_WDM_ALLOW_CLIENT_SUBSCRIPTION

} // namespace DeviceManager
} // namespace Weave
} // namespace nl
