diff --git a/examples/all-clusters-app/esp32/main/EchoServer.cpp b/examples/all-clusters-app/esp32/main/EchoServer.cpp deleted file mode 100644 index 232de50c0f7cab..00000000000000 --- a/examples/all-clusters-app/esp32/main/EchoServer.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * - * 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. - */ - -#include "esp_event.h" -#include "esp_log.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "nvs_flash.h" - -#include -#include -#include -#include -#include - -#include "lwip/err.h" -#include "lwip/sockets.h" -#include "lwip/sys.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "DataModelHandler.h" -#include "Globals.h" -#include "LEDWidget.h" - -static const char * TAG = "echo_server"; - -using namespace ::chip; -using namespace ::chip::Inet; -using namespace ::chip::Transport; - -namespace { - -/** - * @brief implements something like "od -c", changes an arbitrary byte string - * into a single-line of ascii. Destroys any byte-wise encoding that - * might be present, e.g. utf-8. - * - * @param bytes potentially unprintable buffer - * @param bytes_len length of bytes - * @param out where to put the printable string - * @param out_len length of out - * @return size_t required size of output buffer, including null-termination - */ -static size_t odc(const uint8_t * bytes, size_t bytes_len, char * out, size_t out_len) -{ - size_t required = 1; // always need null termination - memset(out, 0, out_len); - // count and print - for (; bytes_len > 0; bytes_len--, bytes++) - { - uint8_t byte = *bytes; - - if ((byte >= '\t' && byte <= '\r') || byte == '\\') - { - static const char * kCodes = "tnvfr"; - char code = (byte == '\\') ? '\\' : kCodes[byte - '\t']; - required += 2; - if (out_len > 2) - { - *out++ = '\\'; - *out++ = code; - out_len -= 2; - } - } - else if (byte >= ' ' && byte <= '~') - { - required += 1; - if (out_len > 1) - { - *out++ = byte; - out_len--; - } - } - else - { - static const size_t kBinCodeLen = sizeof("\\xFF") - 1; - static const char * kCodes = "0123456789ABCDEF"; - - required += kBinCodeLen; - if (out_len > kBinCodeLen) - { - *out++ = '\\'; - *out++ = 'x'; - *out++ = kCodes[(byte & 0xf0) >> 4]; - *out++ = kCodes[byte & 0xf]; - out_len -= kBinCodeLen; - } - } - } - - return required; -} - -class EchoServerCallback : public SecureSessionMgrDelegate -{ -public: - void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, - const Transport::PeerConnectionState * state, System::PacketBufferHandle buffer, - SecureSessionMgr * mgr) override - { - CHIP_ERROR err; - const size_t data_len = buffer->DataLength(); - - // as soon as a client connects, assume it is connected - VerifyOrExit(mgr != NULL && !buffer.IsNull(), ESP_LOGE(TAG, "Received data but couldn't process it...")); - VerifyOrExit(state->GetPeerNodeId() != kUndefinedNodeId, ESP_LOGE(TAG, "Unknown source for received message")); - - { - char src_addr[Transport::PeerAddress::kMaxToStringSize]; - - state->GetPeerAddress().ToString(src_addr, sizeof(src_addr)); - - ESP_LOGI(TAG, "Packet received from %s: %zu bytes", src_addr, static_cast(data_len)); - } - - // FIXME: Long-term we shouldn't be guessing what sort of message this is - // based on the message bytes. We're doing this for now to support both - // data model messages and text echo messages, but in the long term we - // should either do echo via a data model command or do echo on a separate - // port from data model processing. - if (ContentMayBeADataModelMessage(buffer)) - { - HandleDataModelMessage(header, std::move(buffer), mgr); - } - else - { - char logmsg[512]; - - odc(buffer->Start(), data_len, logmsg, sizeof(logmsg)); - - ESP_LOGI(TAG, "Client sent: %s", logmsg); - - // Attempt to echo back - err = mgr->SendMessage(header.GetSourceNodeId().Value(), buffer.Release_ForNow()); - if (err != CHIP_NO_ERROR) - { - ESP_LOGE(TAG, "Unable to echo back to client: %s", ErrorStr(err)); - } - else - { - ESP_LOGI(TAG, "Echo sent"); - } - } - - exit:; - } - - void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source, SecureSessionMgr * mgr) override - { - ESP_LOGE(TAG, "ERROR: %s\n Got UDP error", ErrorStr(error)); - statusLED1.BlinkOnError(); - } - - void OnNewConnection(const Transport::PeerConnectionState * state, SecureSessionMgr * mgr) override - { - ESP_LOGI(TAG, "Received a new connection."); - } - -private: - /** - * A data model message has nonzero length and always has a first byte whose - * value is one of: 0x00, 0x01, 0x02, 0x03. See chipZclEncodeZclHeader for the - * construction of the message and in particular the first byte. - * - * Echo messages should generally not have a first byte with those values, so we - * can use that to try to distinguish between the two. - */ - bool ContentMayBeADataModelMessage(const System::PacketBufferHandle & buffer) - { - const size_t data_len = buffer->DataLength(); - const uint8_t * data = buffer->Start(); - bool maybeDataModelMessage = true; - - // Has to have nonzero length. - VerifyOrExit(data_len > 0, maybeDataModelMessage = false); - - // Has to have a valid first byte value. - VerifyOrExit(data[0] < 0x04, maybeDataModelMessage = false); - - exit: - return maybeDataModelMessage; - } -}; - -EchoServerCallback gCallbacks; - -TransportMgr - gTransports; -SecureSessionMgr sessions; - -} // namespace - -namespace chip { -SecureSessionMgr & SessionManager() -{ - return sessions; -} -} // namespace chip - -// The echo server assumes the platform's networking has been setup already -void startServer(NodeId localNodeId) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - err = gTransports.Init(UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv6).SetInterfaceId(nullptr), - UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv4)); - SuccessOrExit(err); - err = sessions.Init(localNodeId, &DeviceLayer::SystemLayer, &gTransports); - SuccessOrExit(err); - - sessions.SetDelegate(&gCallbacks); - -exit: - if (err != CHIP_NO_ERROR) - { - ESP_LOGE(TAG, "ERROR setting up transport: %s", ErrorStr(err)); - } - else - { - ESP_LOGI(TAG, "Echo Server Listening..."); - } -} - -void PairingComplete(NodeId assignedNodeId, NodeId peerNodeId, SecurePairingSession * pairing) -{ - Optional peer(Transport::Type::kUndefined); - startServer(assignedNodeId); - sessions.NewPairing(peer, peerNodeId, pairing); -} diff --git a/examples/all-clusters-app/esp32/main/RendezvousDeviceDelegate.cpp b/examples/all-clusters-app/esp32/main/RendezvousDeviceDelegate.cpp deleted file mode 100644 index de539548964c2d..00000000000000 --- a/examples/all-clusters-app/esp32/main/RendezvousDeviceDelegate.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * - * 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. - */ - -#include "RendezvousDeviceDelegate.h" - -#include "BluetoothWidget.h" -#include "Globals.h" -#include "esp_log.h" -#include -#include -#include -#include -#include - -using namespace ::chip; -using namespace ::chip::Inet; -using namespace ::chip::System; - -extern void PairingComplete(NodeId assignedNodeId, NodeId peerNodeId, SecurePairingSession * pairing); - -static const char * TAG = "rendezvous-devicedelegate"; - -RendezvousDeviceDelegate::RendezvousDeviceDelegate() -{ - CHIP_ERROR err = CHIP_NO_ERROR; - RendezvousParameters params; - - uint32_t setupPINCode; - err = DeviceLayer::ConfigurationMgr().GetSetupPinCode(setupPINCode); - SuccessOrExit(err); - - params.SetSetupPINCode(setupPINCode).SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer()); - - mRendezvousSession = chip::Platform::New(this); - err = mRendezvousSession->Init(params, nullptr); - -exit: - if (err != CHIP_NO_ERROR) - { - ESP_LOGE(TAG, "RendezvousDeviceDelegate Init failure: %s", ErrorStr(err)); - } -} - -void RendezvousDeviceDelegate::OnRendezvousComplete() -{ - ESP_LOGI(TAG, "Device completed Rendezvous process\n"); - if (mRendezvousSession->GetLocalNodeId().HasValue() && mRendezvousSession->GetRemoteNodeId().HasValue()) - { - PairingComplete(mRendezvousSession->GetLocalNodeId().Value(), mRendezvousSession->GetRemoteNodeId().Value(), - &mRendezvousSession->GetPairingSession()); - } - else - { - ESP_LOGI(TAG, "Commissioner did not assign a node ID to the device!!!\n"); - } -} - -void RendezvousDeviceDelegate::OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err) -{ - if (err != CHIP_NO_ERROR) - { - ESP_LOGE(TAG, "OnRendezvousStatusUpdate: %s, status %d", ErrorStr(err), status); - } - - switch (status) - { - case RendezvousSessionDelegate::SecurePairingSuccess: - ESP_LOGI(TAG, "Device completed SPAKE2+ handshake\n"); - bluetoothLED.Set(true); - break; - - case RendezvousSessionDelegate::SecurePairingFailed: - ESP_LOGI(TAG, "Failed in SPAKE2+ handshake\n"); - bluetoothLED.Set(false); - break; - - case RendezvousSessionDelegate::NetworkProvisioningSuccess: - - ESP_LOGI(TAG, "Device was assigned an ip address\n"); - bluetoothLED.Set(false); - break; - - case RendezvousSessionDelegate::NetworkProvisioningFailed: - - ESP_LOGI(TAG, "Failed in network provisioning\n"); - bluetoothLED.Set(false); - break; - - default: - break; - }; -} diff --git a/examples/all-clusters-app/esp32/main/main.cpp b/examples/all-clusters-app/esp32/main/main.cpp index e579e9650430f9..eb9ceaa53016b0 100644 --- a/examples/all-clusters-app/esp32/main/main.cpp +++ b/examples/all-clusters-app/esp32/main/main.cpp @@ -15,10 +15,10 @@ * limitations under the License. */ +#include "AppDelegate.h" #include "BluetoothWidget.h" #include "Button.h" #include "CHIPDeviceManager.h" -#include "DataModelHandler.h" #include "DeviceCallbacks.h" #include "Display.h" #include "Globals.h" @@ -26,8 +26,8 @@ #include "ListScreen.h" #include "QRCodeScreen.h" #include "QRCodeUtil.h" -#include "RendezvousDeviceDelegate.h" #include "ScreenManager.h" +#include "Server.h" #include "WiFiWidget.h" #include "esp_heap_caps_init.h" #include "esp_log.h" @@ -45,13 +45,11 @@ #include #include -#include #include #include #include #include #include -#include using namespace ::chip; using namespace ::chip::DeviceManager; @@ -83,12 +81,9 @@ using namespace ::chip::DeviceLayer; // Used to indicate that an IP address has been added to the QRCode #define EXAMPLE_VENDOR_TAG_IP 1 -extern void PairingComplete(NodeId assignedNodeId, NodeId peerNodeId, SecurePairingSession * pairing); - const char * TAG = "all-clusters-app"; static DeviceCallbacks EchoCallbacks; -RendezvousDeviceDelegate * rendezvousDelegate = nullptr; namespace { @@ -342,11 +337,6 @@ bool isRendezvousBLE() return static_cast(CONFIG_RENDEZVOUS_MODE) == RendezvousInformationFlags::kBLE; } -bool isRendezvousBypassed() -{ - return static_cast(CONFIG_RENDEZVOUS_MODE) == RendezvousInformationFlags::kNone; -} - std::string createSetupPayload() { CHIP_ERROR err = CHIP_NO_ERROR; @@ -431,7 +421,13 @@ std::string createSetupPayload() return result; }; -static SecurePairingUsingTestSecret gTestPairing; +class AppCallbacks : public AppDelegate +{ +public: +void OnReceiveError() override { statusLED1.BlinkOnError(); } +void OnRendezvousStarted() override { bluetoothLED.Set(true); } +void OnRendezvousStopped() override { bluetoothLED.Set(false); } +}; } // namespace @@ -484,18 +480,9 @@ extern "C" void app_main() bluetoothLED.Init(); wifiLED.Init(); - // Start the Echo Server - InitDataModelHandler(); - - if (isRendezvousBLE()) - { - rendezvousDelegate = chip::Platform::New(); - } - else if (isRendezvousBypassed()) - { - ChipLogProgress(Ble, "Rendezvous and Secure Pairing skipped. Using test secret."); - PairingComplete(chip::kTestDeviceNodeId, chip::kTestControllerNodeId, &gTestPairing); - } + // Init ZCL Data Model and CHIP App Server + AppCallbacks callbacks; + InitServer(&callbacks); std::string qrCodeText = createSetupPayload(); ESP_LOGI(TAG, "QR CODE Text: '%s'", qrCodeText.c_str()); diff --git a/examples/common/chip-app-server/DataModelHandler.cpp b/examples/common/chip-app-server/DataModelHandler.cpp index ab10b1f69f44b5..e4b0d7307070f7 100644 --- a/examples/common/chip-app-server/DataModelHandler.cpp +++ b/examples/common/chip-app-server/DataModelHandler.cpp @@ -20,27 +20,125 @@ * This file implements the handler for data model messages. */ -#include -#include -#include - #include "DataModelHandler.h" #include #include #include #include +#include +#include +#include using namespace ::chip; /** - * Handle a message that should be processed via our data model processing - * codepath. This function will free the packet buffer. + * A data model message has nonzero length and always has a first byte whose + * value is one of: 0x00, 0x01, 0x02, 0x03. See chipZclEncodeZclHeader for the + * construction of the message and in particular the first byte. * - * @param [in] buffer The buffer holding the message. This function guarantees - * that it will free the buffer before returning. + * Echo messages should generally not have a first byte with those values, so we + * can use that to try to distinguish between the two. */ -void HandleDataModelMessage(const PacketHeader & header, System::PacketBufferHandle buffer, SecureSessionMgr * mgr) +bool ContentMayBeADataModelMessage(const System::PacketBufferHandle & buffer) +{ + const size_t data_len = buffer->DataLength(); + const uint8_t * data = buffer->Start(); + bool maybeDataModelMessage = true; + + // Has to have nonzero length. + VerifyOrExit(data_len > 0, maybeDataModelMessage = false); + + // Has to have a valid first byte value. + VerifyOrExit(data[0] < 0x04, maybeDataModelMessage = false); + +exit: + return maybeDataModelMessage; +} + +/** + * @brief implements something like "od -c", changes an arbitrary byte string + * into a single-line of ascii. Destroys any byte-wise encoding that + * might be present, e.g. utf-8. + * + * @param bytes potentially unprintable buffer + * @param bytes_len length of bytes + * @param out where to put the printable string + * @param out_len length of out + * @return size_t required size of output buffer, including null-termination + */ +static size_t odc(const uint8_t * bytes, size_t bytes_len, char * out, size_t out_len) +{ + size_t required = 1; // always need null termination + memset(out, 0, out_len); + // count and print + for (; bytes_len > 0; bytes_len--, bytes++) + { + uint8_t byte = *bytes; + + if ((byte >= '\t' && byte <= '\r') || byte == '\\') + { + static const char * kCodes = "tnvfr"; + char code = (byte == '\\') ? '\\' : kCodes[byte - '\t']; + required += 2; + if (out_len > 2) + { + *out++ = '\\'; + *out++ = code; + out_len -= 2; + } + } + else if (byte >= ' ' && byte <= '~') + { + required += 1; + if (out_len > 1) + { + *out++ = byte; + out_len--; + } + } + else + { + static const size_t kBinCodeLen = sizeof("\\xFF") - 1; + static const char * kCodes = "0123456789ABCDEF"; + + required += kBinCodeLen; + if (out_len > kBinCodeLen) + { + *out++ = '\\'; + *out++ = 'x'; + *out++ = kCodes[(byte & 0xf0) >> 4]; + *out++ = kCodes[byte & 0xf]; + out_len -= kBinCodeLen; + } + } + } + + return required; +} + +void ProcessOthersMessage(const PacketHeader & header, System::PacketBufferHandle & buffer, SecureSessionMgr * mgr) +{ + CHIP_ERROR err; + char logmsg[512]; + + odc(buffer->Start(), buffer->DataLength(), logmsg, sizeof(logmsg)); + + ChipLogProgress(AppServer, "Client sent: %s", logmsg); + + // Attempt to echo back + err = mgr->SendMessage(header.GetSourceNodeId().Value(), buffer.Release_ForNow()); + if (err != CHIP_NO_ERROR) + { + ChipLogProgress(AppServer, "Unable to echo back to client: %s", ErrorStr(err)); + } + else + { + ChipLogProgress(AppServer, "Echo sent"); + } +} + +void ProcessDataModelMessage(const PacketHeader & header, System::PacketBufferHandle & buffer) { EmberApsFrame frame; bool ok = extractApsFrame(buffer->Start(), buffer->DataLength(), &frame) > 0; @@ -72,6 +170,30 @@ void HandleDataModelMessage(const PacketHeader & header, System::PacketBufferHan } } +/** + * Handle a message that should be processed via our data model processing + * codepath. This function will free the packet buffer. + * + * @param [in] buffer The buffer holding the message. This function guarantees + * that it will free the buffer before returning. + */ +void HandleDataModelMessage(const PacketHeader & header, System::PacketBufferHandle buffer, SecureSessionMgr * mgr) +{ + // FIXME: Long-term we shouldn't be guessing what sort of message this is + // based on the message bytes. We're doing this for now to support both + // data model messages and text echo messages, but in the long term we + // should either do echo via a data model command or do echo on a separate + // port from data model processing. + if (ContentMayBeADataModelMessage(buffer)) + { + ProcessDataModelMessage(header, buffer); + } + else + { + ProcessOthersMessage(header, buffer, mgr); + } +} + void InitDataModelHandler() { emberAfEndpointConfigure(); diff --git a/examples/common/chip-app-server/RendezvousServer.cpp b/examples/common/chip-app-server/RendezvousServer.cpp index 0996c2b6b6884b..1bf3a980285764 100644 --- a/examples/common/chip-app-server/RendezvousServer.cpp +++ b/examples/common/chip-app-server/RendezvousServer.cpp @@ -18,7 +18,6 @@ #include "RendezvousServer.h" #include "SessionManager.h" - #include #include #include @@ -63,8 +62,15 @@ void RendezvousServer::OnRendezvousMessageReceived(const PacketHeader & packetHe void RendezvousServer::OnRendezvousComplete() { ChipLogProgress(AppServer, "Device completed Rendezvous process"); - SessionManager().NewPairing(Optional{}, mRendezvousSession.GetRemoteNodeId().Value(), - &mRendezvousSession.GetPairingSession()); + if (mRendezvousSession.GetLocalNodeId().HasValue() && mRendezvousSession.GetRemoteNodeId().HasValue()) + { + SessionManager().NewPairing(Optional{}, mRendezvousSession.GetRemoteNodeId().Value(), + &mRendezvousSession.GetPairingSession()); + } + else + { + ChipLogError(AppServer, "Commissioner did not assign a node ID to the device!!!"); + } } void RendezvousServer::OnRendezvousStatusUpdate(Status status, CHIP_ERROR err) @@ -75,12 +81,37 @@ void RendezvousServer::OnRendezvousStatusUpdate(Status status, CHIP_ERROR err) { case RendezvousSessionDelegate::SecurePairingSuccess: ChipLogProgress(AppServer, "Device completed SPAKE2+ handshake"); + if (mDelegate != nullptr) + { + mDelegate->OnRendezvousStarted(); + } + break; + + case RendezvousSessionDelegate::SecurePairingFailed: + ChipLogProgress(AppServer, "Failed in SPAKE2+ handshake"); + if (mDelegate != nullptr) + { + mDelegate->OnRendezvousStopped(); + } break; + case RendezvousSessionDelegate::NetworkProvisioningSuccess: ChipLogProgress(AppServer, "Device was assigned network credentials"); chip::Mdns::DiscoveryManager::GetInstance().StartPublishDevice(); + if (mDelegate != nullptr) + { + mDelegate->OnRendezvousStopped(); + } + break; + case RendezvousSessionDelegate::NetworkProvisioningFailed: + ChipLogProgress(AppServer, "Failed in network provisioning"); + if (mDelegate != nullptr) + { + mDelegate->OnRendezvousStopped(); + } break; + default: break; }; @@ -88,5 +119,4 @@ void RendezvousServer::OnRendezvousStatusUpdate(Status status, CHIP_ERROR err) exit: return; } - } // namespace chip diff --git a/examples/common/chip-app-server/Server.cpp b/examples/common/chip-app-server/Server.cpp index 67ddad791e7f41..77c12326b7e14e 100644 --- a/examples/common/chip-app-server/Server.cpp +++ b/examples/common/chip-app-server/Server.cpp @@ -27,13 +27,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include using namespace ::chip; using namespace ::chip::Inet; @@ -42,6 +42,21 @@ using namespace ::chip::DeviceLayer; namespace { +bool isRendezvousBypassed() +{ + RendezvousInformationFlags rendezvousMode = RendezvousInformationFlags::kBLE; + +#ifdef CONFIG_RENDEZVOUS_MODE + rendezvousMode = static_cast(CONFIG_RENDEZVOUS_MODE); +#endif + +#ifdef CHIP_BYPASS_RENDEZVOUS + rendezvousMode = RendezvousInformationFlags::kNone; +#endif + + return rendezvousMode == RendezvousInformationFlags::kNone;; +} + class ServerCallback : public SecureSessionMgrDelegate { public: @@ -67,10 +82,24 @@ class ServerCallback : public SecureSessionMgrDelegate exit:; } + void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source, SecureSessionMgr * mgr) override + { + ChipLogProgress(AppServer, "Packet received error: %s", ErrorStr(error)); + if (mDelegate != nullptr) + { + mDelegate->OnReceiveError(); + } + } + void OnNewConnection(const Transport::PeerConnectionState * state, SecureSessionMgr * mgr) override { ChipLogProgress(AppServer, "Received a new connection."); } + + void SetDelegate(AppDelegate * delegate) { mDelegate = delegate; } + +private: + AppDelegate * mDelegate = nullptr; }; DemoTransportMgr gTransports; @@ -88,15 +117,22 @@ SecureSessionMgr & chip::SessionManager() // The function will initialize datamodel handler and then start the server // The server assumes the platform's networking has been setup already -void InitServer() +void InitServer(AppDelegate * delegate) { CHIP_ERROR err = CHIP_NO_ERROR; Optional peer(Transport::Type::kUndefined); InitDataModelHandler(); + gCallbacks.SetDelegate(delegate); + gRendezvousServer.SetDelegate(delegate); // Init transport before operations with secure session mgr. +#if INET_CONFIG_ENABLE_IPV4 + err = gTransports.Init(UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv6), + UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv4)); +#else err = gTransports.Init(UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv6)); +#endif SuccessOrExit(err); err = gSessions.Init(chip::kTestDeviceNodeId, &DeviceLayer::SystemLayer, &gTransports); @@ -104,7 +140,13 @@ void InitServer() // This flag is used to bypass BLE in the cirque test // Only in the cirque test this is enabled with --args='bypass_rendezvous=true' -#ifndef CHIP_BYPASS_RENDEZVOUS + if (isRendezvousBypassed()) + { + ChipLogProgress(AppServer, "Rendezvous and Secure Pairing skipped. Using test secret."); + err = gSessions.NewPairing(peer, chip::kTestControllerNodeId, &gTestPairing); + SuccessOrExit(err); + } + else { RendezvousParameters params; uint32_t pinCode; @@ -116,13 +158,13 @@ void InitServer() .SetPeerAddress(Transport::PeerAddress::BLE()); SuccessOrExit(err = gRendezvousServer.Init(params, &gTransports)); } -#endif err = gSessions.NewPairing(peer, chip::kTestControllerNodeId, &gTestPairing); SuccessOrExit(err); gSessions.SetDelegate(&gCallbacks); - chip::Mdns::DiscoveryManager::GetInstance().StartPublishDevice(chip::Inet::kIPAddressType_IPv6); + chip::Mdns::DiscoveryManager::GetInstance().StartPublishDevice(kIPAddressType_IPv6); + exit: if (err != CHIP_NO_ERROR) { diff --git a/examples/all-clusters-app/esp32/main/include/RendezvousDeviceDelegate.h b/examples/common/chip-app-server/include/AppDelegate.h similarity index 59% rename from examples/all-clusters-app/esp32/main/include/RendezvousDeviceDelegate.h rename to examples/common/chip-app-server/include/AppDelegate.h index 09e6895eccb758..dbeea37286d533 100644 --- a/examples/all-clusters-app/esp32/main/include/RendezvousDeviceDelegate.h +++ b/examples/common/chip-app-server/include/AppDelegate.h @@ -15,20 +15,18 @@ * limitations under the License. */ -#pragma once +/** + * @file + * This file defines the API for application specific callbacks. + */ -#include -#include +#pragma once -class RendezvousDeviceDelegate : public chip::RendezvousSessionDelegate +class AppDelegate { public: - RendezvousDeviceDelegate(); - - //////////// RendezvousSession callback Implementation /////////////// - void OnRendezvousComplete() override; - void OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err) override; - -private: - chip::RendezvousSession * mRendezvousSession; + virtual ~AppDelegate() {} + virtual void OnReceiveError(){}; + virtual void OnRendezvousStarted(){}; + virtual void OnRendezvousStopped(){}; }; diff --git a/examples/common/chip-app-server/include/RendezvousServer.h b/examples/common/chip-app-server/include/RendezvousServer.h index 027d367c9854d9..54d097620ce928 100644 --- a/examples/common/chip-app-server/include/RendezvousServer.h +++ b/examples/common/chip-app-server/include/RendezvousServer.h @@ -17,6 +17,7 @@ #pragma once +#include "AppDelegate.h" #include #include @@ -28,6 +29,7 @@ class RendezvousServer : public RendezvousSessionDelegate RendezvousServer(); CHIP_ERROR Init(const RendezvousParameters & params, TransportMgrBase * transportMgr); + void SetDelegate(AppDelegate * delegate) { mDelegate = delegate; }; //////////////// RendezvousSessionDelegate Implementation /////////////////// @@ -42,6 +44,7 @@ class RendezvousServer : public RendezvousSessionDelegate private: RendezvousSession mRendezvousSession; + AppDelegate * mDelegate; }; } // namespace chip diff --git a/examples/common/chip-app-server/include/Server.h b/examples/common/chip-app-server/include/Server.h index 6bd260b9f23b8e..c149bb4d5eeeeb 100644 --- a/examples/common/chip-app-server/include/Server.h +++ b/examples/common/chip-app-server/include/Server.h @@ -17,15 +17,21 @@ #pragma once +#include "AppDelegate.h" +#include #include #include +#if INET_CONFIG_ENABLE_IPV4 +using DemoTransportMgr = chip::TransportMgr; +#else using DemoTransportMgr = chip::TransportMgr; +#endif /** * Initialize DataModelHandler and start CHIP datamodel server, the server * assumes the platform's networking has been setup already. * - * @param [in] sessions The demo's session manager. + * @param [in] delegate An optional AppDelegate */ -void InitServer(); +void InitServer(AppDelegate * delegate = nullptr); diff --git a/examples/temperature-measurement-app/esp32/main/RendezvousDeviceDelegate.cpp b/examples/temperature-measurement-app/esp32/main/RendezvousDeviceDelegate.cpp deleted file mode 100644 index f95b23c6f480ee..00000000000000 --- a/examples/temperature-measurement-app/esp32/main/RendezvousDeviceDelegate.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * - * 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. - */ - -#include "RendezvousDeviceDelegate.h" - -#include "esp_log.h" -#include -#include -#include -#include - -using namespace ::chip; -using namespace ::chip::Inet; -using namespace ::chip::System; - -extern NodeId kLocalNodeId; -extern void PairingComplete(NodeId assignedNodeId, NodeId peerNodeId, SecurePairingSession * pairing); - -static const char * TAG = "rendezvous-devicedelegate"; - -RendezvousDeviceDelegate::RendezvousDeviceDelegate() -{ - CHIP_ERROR err = CHIP_NO_ERROR; - RendezvousParameters params; - - uint32_t setupPINCode; - err = DeviceLayer::ConfigurationMgr().GetSetupPinCode(setupPINCode); - SuccessOrExit(err); - - params.SetSetupPINCode(setupPINCode).SetLocalNodeId(kLocalNodeId).SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer()); - - mRendezvousSession = new RendezvousSession(this); - err = mRendezvousSession->Init(params, nullptr); - -exit: - if (err != CHIP_NO_ERROR) - { - ESP_LOGE(TAG, "RendezvousDeviceDelegate Init failure: %s", ErrorStr(err)); - } -} - -void RendezvousDeviceDelegate::OnRendezvousComplete() -{ - ESP_LOGI(TAG, "Device completed Rendezvous process\n"); - if (mRendezvousSession->GetLocalNodeId().HasValue() && mRendezvousSession->GetRemoteNodeId().HasValue()) - { - PairingComplete(mRendezvousSession->GetLocalNodeId().Value(), mRendezvousSession->GetRemoteNodeId().Value(), - &mRendezvousSession->GetPairingSession()); - } - else - { - ESP_LOGI(TAG, "Commissioner did not assign a node ID to the device!!!\n"); - } -} - -void RendezvousDeviceDelegate::OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err) -{ - if (err != CHIP_NO_ERROR) - { - ESP_LOGE(TAG, "OnRendezvousStatusUpdate: %s, status %d", ErrorStr(err), status); - } - - switch (status) - { - case RendezvousSessionDelegate::SecurePairingSuccess: - ESP_LOGI(TAG, "Device completed SPAKE2+ handshake\n"); - break; - - case RendezvousSessionDelegate::NetworkProvisioningSuccess: - - ESP_LOGI(TAG, "Device was assigned an ip address\n"); - break; - - default: - break; - }; -} diff --git a/examples/temperature-measurement-app/esp32/main/ResponseServer.cpp b/examples/temperature-measurement-app/esp32/main/ResponseServer.cpp deleted file mode 100644 index 99297da3c10df5..00000000000000 --- a/examples/temperature-measurement-app/esp32/main/ResponseServer.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * - * 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. - */ - -#include "esp_event.h" -#include "esp_log.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "nvs_flash.h" - -#include -#include -#include -#include -#include - -#include "lwip/err.h" -#include "lwip/sockets.h" -#include "lwip/sys.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "DataModelHandler.h" - -static const char * TAG = "echo_server"; - -using namespace ::chip; -using namespace ::chip::Inet; -using namespace ::chip::Transport; - -extern const NodeId kLocalNodeId = 12344321; - -namespace { - -class ResponseServerCallback : public SecureSessionMgrDelegate -{ -public: - void OnMessageReceived(const PacketHeader & header, const PayloadHeader & payloadHeader, - const Transport::PeerConnectionState * state, System::PacketBufferHandle buffer, - SecureSessionMgr * mgr) override - { - CHIP_ERROR err; - const size_t data_len = buffer->DataLength(); - - // as soon as a client connects, assume it is connected - VerifyOrExit(mgr != nullptr && !buffer.IsNull(), ESP_LOGE(TAG, "Received data but couldn't process it...")); - VerifyOrExit(state->GetPeerNodeId() != kUndefinedNodeId, ESP_LOGE(TAG, "Unknown source for received message")); - - { - char src_addr[Transport::PeerAddress::kMaxToStringSize]; - - state->GetPeerAddress().ToString(src_addr, sizeof(src_addr)); - - ESP_LOGI(TAG, "Packet received from %s: %zu bytes", src_addr, static_cast(data_len)); - } - - HandleDataModelMessage(header, std::move(buffer), mgr); - - exit:; - } - - void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source, SecureSessionMgr * mgr) override - { - ESP_LOGE(TAG, "ERROR: %s\n Got UDP error", ErrorStr(error)); - } - - void OnNewConnection(const Transport::PeerConnectionState * state, SecureSessionMgr * mgr) override - { - ESP_LOGI(TAG, "Received a new connection."); - } - -private: - /** - * A data model message has nonzero length and always has a first byte whose - * value is one of: 0x00, 0x01, 0x02, 0x03. See chipZclEncodeZclHeader for the - * construction of the message and in particular the first byte. - * - * Echo messages should generally not have a first byte with those values, so we - * can use that to try to distinguish between the two. - */ - bool ContentMayBeADataModelMessage(const System::PacketBufferHandle & buffer) - { - const size_t data_len = buffer->DataLength(); - const uint8_t * data = buffer->Start(); - bool maybeDataModelMessage = true; - - // Has to have nonzero length. - VerifyOrExit(data_len > 0, maybeDataModelMessage = false); - - // Has to have a valid first byte value. - VerifyOrExit(data[0] < 0x04, maybeDataModelMessage = false); - - exit: - return maybeDataModelMessage; - } -}; - -ResponseServerCallback gCallbacks; -TransportMgr - gTransports; -SecureSessionMgr sessions; - -} // namespace - -namespace chip { -SecureSessionMgr & SessionManager() -{ - return sessions; -} -} // namespace chip - -// The echo server assumes the platform's networking has been setup already -void startServer(NodeId localNodeId) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - err = gTransports.Init(UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv6).SetInterfaceId(nullptr), - UdpListenParameters(&DeviceLayer::InetLayer).SetAddressType(kIPAddressType_IPv4)); - SuccessOrExit(err); - err = sessions.Init(localNodeId, &DeviceLayer::SystemLayer, &gTransports); - SuccessOrExit(err); - - sessions.SetDelegate(&gCallbacks); - -exit: - if (err != CHIP_NO_ERROR) - { - ESP_LOGE(TAG, "ERROR setting up transport: %s", ErrorStr(err)); - } - else - { - ESP_LOGI(TAG, "Echo Server Listening..."); - } -} - -void PairingComplete(NodeId assignedNodeId, NodeId peerNodeId, SecurePairingSession * pairing) -{ - Optional peer(Transport::Type::kUndefined); - startServer(assignedNodeId); - sessions.NewPairing(peer, peerNodeId, pairing); -} diff --git a/examples/temperature-measurement-app/esp32/main/include/RendezvousDeviceDelegate.h b/examples/temperature-measurement-app/esp32/main/include/RendezvousDeviceDelegate.h deleted file mode 100644 index b8ba36d382ca7c..00000000000000 --- a/examples/temperature-measurement-app/esp32/main/include/RendezvousDeviceDelegate.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * - * 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. - */ - -#ifndef __RENDEZVOUSDEVICEDELEGATE_H__ -#define __RENDEZVOUSDEVICEDELEGATE_H__ - -#include -#include - -class RendezvousDeviceDelegate : public chip::RendezvousSessionDelegate -{ -public: - RendezvousDeviceDelegate(); - - //////////// RendezvousSession callback Implementation /////////////// - void OnRendezvousComplete() override; - void OnRendezvousStatusUpdate(RendezvousSessionDelegate::Status status, CHIP_ERROR err) override; - -private: - chip::RendezvousSession * mRendezvousSession; -}; - -#endif // __RENDEZVOUSDEVICEDELEGATE_H__ diff --git a/examples/temperature-measurement-app/esp32/main/main.cpp b/examples/temperature-measurement-app/esp32/main/main.cpp index af940f026c2234..25d946d0b7db3e 100644 --- a/examples/temperature-measurement-app/esp32/main/main.cpp +++ b/examples/temperature-measurement-app/esp32/main/main.cpp @@ -18,7 +18,7 @@ #include "CHIPDeviceManager.h" #include "DataModelHandler.h" #include "DeviceCallbacks.h" -#include "RendezvousDeviceDelegate.h" +#include "Server.h" #include "esp_heap_caps_init.h" #include "esp_log.h" #include "esp_netif.h" @@ -34,41 +34,15 @@ #include #include -#include -#include -#include #include -#include using namespace ::chip; using namespace ::chip::DeviceManager; using namespace ::chip::DeviceLayer; -// Used to indicate that an IP address has been added to the QRCode -#define EXAMPLE_VENDOR_TAG_IP 1 - -extern void PairingComplete(NodeId assignedNodeId, NodeId peerNodeId, SecurePairingSession * pairing); - const char * TAG = "temperature-measurement-app"; static DeviceCallbacks EchoCallbacks; -RendezvousDeviceDelegate * rendezvousDelegate = nullptr; - -namespace { - -bool isRendezvousBLE() -{ - return static_cast(CONFIG_RENDEZVOUS_MODE) == RendezvousInformationFlags::kBLE; -} - -bool isRendezvousBypassed() -{ - return static_cast(CONFIG_RENDEZVOUS_MODE) == RendezvousInformationFlags::kNone; -} - -static SecurePairingUsingTestSecret gTestPairing; - -} // namespace extern "C" void app_main() { @@ -110,17 +84,7 @@ extern "C" void app_main() return; } - InitDataModelHandler(); - - if (isRendezvousBLE()) - { - rendezvousDelegate = new RendezvousDeviceDelegate(); - } - else if (isRendezvousBypassed()) - { - ChipLogProgress(Ble, "Rendezvous and Secure Pairing skipped. Using test secret."); - PairingComplete(chip::kTestDeviceNodeId, chip::kTestControllerNodeId, &gTestPairing); - } + InitServer(); // Run the UI Loop while (true)