/* * * Copyright (c) 2021 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 #include #include #include #include #include using namespace chip; using namespace chip::Dnssd; namespace { // callback types shared with python code (see ptyhon code in chip.discovery.types) using DiscoverSuccessCallback = void (*)(uint64_t fabricId, uint64_t nodeId, uint32_t interfaceId, const char * ip, uint16_t port); using DiscoverFailureCallback = void (*)(uint64_t fabricId, uint64_t nodeId, PyChipError error_code); class PythonResolverDelegate : public OperationalResolveDelegate { public: void OnOperationalNodeResolved(const ResolvedNodeData & nodeData) override { Resolver::Instance().NodeIdResolutionNoLongerNeeded(nodeData.operationalData.peerId); if (mSuccessCallback != nullptr) { char ipAddressBuffer[128]; // TODO: For now, just provide addr 0, but this should really provide all and // allow the caller to choose. mSuccessCallback( // nodeData.operationalData.peerId.GetCompressedFabricId(), // nodeData.operationalData.peerId.GetNodeId(), // nodeData.resolutionData.interfaceId.GetPlatformInterface(), // nodeData.resolutionData.ipAddress[0].ToString(ipAddressBuffer, sizeof(ipAddressBuffer)), // nodeData.resolutionData.port // ); } else { ChipLogError(Controller, "Discovery success without any python callback set."); } } void OnOperationalNodeResolutionFailed(const PeerId & peerId, CHIP_ERROR error) override { Resolver::Instance().NodeIdResolutionNoLongerNeeded(peerId); if (mFailureCallback != nullptr) { mFailureCallback(peerId.GetCompressedFabricId(), peerId.GetNodeId(), ToPyChipError(error)); } else { ChipLogError(Controller, "Discovery failure without any python callback set."); } } void SetSuccessCallback(DiscoverSuccessCallback cb) { mSuccessCallback = cb; } void SetFailureCallback(DiscoverFailureCallback cb) { mFailureCallback = cb; } private: DiscoverSuccessCallback mSuccessCallback = nullptr; DiscoverFailureCallback mFailureCallback = nullptr; }; // namespace PythonResolverDelegate gPythonResolverDelegate; } // namespace extern "C" void pychip_discovery_set_callbacks(DiscoverSuccessCallback success, DiscoverFailureCallback failure) { gPythonResolverDelegate.SetSuccessCallback(success); gPythonResolverDelegate.SetFailureCallback(failure); } extern "C" PyChipError pychip_discovery_resolve(uint64_t fabricId, uint64_t nodeId) { CHIP_ERROR result = CHIP_NO_ERROR; chip::python::ChipMainThreadScheduleAndWait([&] { result = Resolver::Instance().Init(chip::DeviceLayer::UDPEndPointManager()); ReturnOnFailure(result); Resolver::Instance().SetOperationalDelegate(&gPythonResolverDelegate); result = Resolver::Instance().ResolveNodeId(chip::PeerId().SetCompressedFabricId(fabricId).SetNodeId(nodeId)); }); return ToPyChipError(result); }