| /* |
| * Copyright (c) 2024, The OpenThread Authors. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the copyright holder nor the |
| * names of its contributors may be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /** |
| * @file This file implements spinel property encoding and decoding functions. |
| */ |
| |
| #include "lib/spinel/spinel_prop_codec.hpp" |
| #include "common/code_utils.hpp" |
| |
| namespace ot { |
| namespace Spinel { |
| |
| template <> |
| otError EncodeDnssd<otPlatDnssdHost>(Encoder &aEncoder, |
| const otPlatDnssdHost &aObj, |
| otPlatDnssdRequestId aRequestId, |
| otPlatDnssdRegisterCallback aCallback) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aEncoder.WriteUintPacked(SPINEL_PROP_DNSSD_HOST)); |
| SuccessOrExit(error = aEncoder.WriteUtf8(aObj.mHostName == nullptr ? "" : aObj.mHostName)); |
| SuccessOrExit(error = aEncoder.WriteUint16(aObj.mAddressesLength)); |
| for (uint16_t i = 0; i < aObj.mAddressesLength; i++) |
| { |
| SuccessOrExit(error = aEncoder.WriteIp6Address(aObj.mAddresses[i])); |
| } |
| SuccessOrExit(error = aEncoder.WriteUint32(aRequestId)); |
| SuccessOrExit(error = aEncoder.WriteData(reinterpret_cast<const uint8_t *>(&aCallback), sizeof(aCallback))); |
| |
| exit: |
| return error; |
| } |
| |
| template <> |
| otError EncodeDnssd<otPlatDnssdService>(Encoder &aEncoder, |
| const otPlatDnssdService &aObj, |
| otPlatDnssdRequestId aRequestId, |
| otPlatDnssdRegisterCallback aCallback) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aEncoder.WriteUintPacked(SPINEL_PROP_DNSSD_SERVICE)); |
| SuccessOrExit(error = aEncoder.WriteUtf8(aObj.mHostName == nullptr ? "" : aObj.mHostName)); |
| SuccessOrExit(error = aEncoder.WriteUtf8(aObj.mServiceInstance == nullptr ? "" : aObj.mServiceInstance)); |
| SuccessOrExit(error = aEncoder.WriteUtf8(aObj.mServiceType == nullptr ? "" : aObj.mServiceType)); |
| SuccessOrExit(error = aEncoder.OpenStruct()); |
| for (uint16_t i = 0; i < aObj.mSubTypeLabelsLength; i++) |
| { |
| SuccessOrExit(error = aEncoder.WriteUtf8(aObj.mSubTypeLabels[i])); |
| } |
| SuccessOrExit(error = aEncoder.CloseStruct()); |
| SuccessOrExit(error = aEncoder.WriteDataWithLen(aObj.mTxtData, aObj.mTxtDataLength)); |
| SuccessOrExit(error = aEncoder.WriteUint16(aObj.mPort)); |
| SuccessOrExit(error = aEncoder.WriteUint16(aObj.mPriority)); |
| SuccessOrExit(error = aEncoder.WriteUint16(aObj.mWeight)); |
| SuccessOrExit(error = aEncoder.WriteUint32(aObj.mTtl)); |
| SuccessOrExit(error = aEncoder.WriteUint32(aRequestId)); |
| SuccessOrExit(error = aEncoder.WriteData(reinterpret_cast<const uint8_t *>(&aCallback), sizeof(aCallback))); |
| |
| exit: |
| return error; |
| } |
| |
| template <> |
| otError EncodeDnssd<otPlatDnssdKey>(Encoder &aEncoder, |
| const otPlatDnssdKey &aObj, |
| otPlatDnssdRequestId aRequestId, |
| otPlatDnssdRegisterCallback aCallback) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aEncoder.WriteUintPacked(SPINEL_PROP_DNSSD_KEY_RECORD)); |
| SuccessOrExit(error = aEncoder.WriteUtf8(aObj.mName == nullptr ? "" : aObj.mName)); |
| SuccessOrExit(error = aEncoder.OpenStruct()); |
| if (aObj.mServiceType != nullptr) |
| { |
| SuccessOrExit(error = aEncoder.WriteUtf8(aObj.mServiceType)); |
| } |
| SuccessOrExit(error = aEncoder.CloseStruct()); |
| SuccessOrExit(error = aEncoder.WriteDataWithLen(aObj.mKeyData, aObj.mKeyDataLength)); |
| SuccessOrExit(error = aEncoder.WriteUint16(aObj.mClass)); |
| SuccessOrExit(error = aEncoder.WriteUint32(aObj.mTtl)); |
| SuccessOrExit(error = aEncoder.WriteUint32(aRequestId)); |
| SuccessOrExit(error = aEncoder.WriteData(reinterpret_cast<const uint8_t *>(&aCallback), sizeof(aCallback))); |
| |
| exit: |
| return error; |
| } |
| |
| otError DecodeDnssdHost(Decoder &aDecoder, |
| otPlatDnssdHost &aHost, |
| otPlatDnssdRequestId &aRequestId, |
| const uint8_t *&aCallbackData, |
| uint16_t &aCallbackDataLen) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aDecoder.ReadUtf8(aHost.mHostName)); |
| SuccessOrExit(error = aDecoder.ReadUint16(aHost.mAddressesLength)); |
| |
| if (aHost.mAddressesLength == 0) |
| { |
| aHost.mAddresses = nullptr; |
| } |
| else |
| { |
| SuccessOrExit(error = aDecoder.ReadIp6Address(aHost.mAddresses)); |
| |
| for (uint16_t i = 1; i < aHost.mAddressesLength; i++) |
| { |
| const otIp6Address *address; |
| |
| SuccessOrExit(error = aDecoder.ReadIp6Address(address)); |
| } |
| } |
| |
| SuccessOrExit(error = aDecoder.ReadUint32(aRequestId)); |
| SuccessOrExit(error = aDecoder.ReadData(aCallbackData, aCallbackDataLen)); |
| |
| exit: |
| return error; |
| } |
| |
| otError DecodeDnssdService(Decoder &aDecoder, |
| otPlatDnssdService &aService, |
| const char **aSubTypeLabels, |
| uint16_t &aSubTypeLabelsCount, |
| otPlatDnssdRequestId &aRequestId, |
| const uint8_t *&aCallbackData, |
| uint16_t &aCallbackDataLen) |
| { |
| otError error = OT_ERROR_NONE; |
| uint8_t index = 0; |
| |
| SuccessOrExit(error = aDecoder.ReadUtf8(aService.mHostName)); |
| SuccessOrExit(error = aDecoder.ReadUtf8(aService.mServiceInstance)); |
| SuccessOrExit(error = aDecoder.ReadUtf8(aService.mServiceType)); |
| SuccessOrExit(error = aDecoder.OpenStruct()); |
| while (!aDecoder.IsAllReadInStruct()) |
| { |
| VerifyOrExit(index < aSubTypeLabelsCount, error = OT_ERROR_NO_BUFS); |
| SuccessOrExit(error = aDecoder.ReadUtf8(aSubTypeLabels[index])); |
| index++; |
| } |
| aSubTypeLabelsCount = index; |
| SuccessOrExit(error = aDecoder.CloseStruct()); |
| SuccessOrExit(error = aDecoder.ReadDataWithLen(aService.mTxtData, aService.mTxtDataLength)); |
| SuccessOrExit(error = aDecoder.ReadUint16(aService.mPort)); |
| SuccessOrExit(error = aDecoder.ReadUint16(aService.mPriority)); |
| SuccessOrExit(error = aDecoder.ReadUint16(aService.mWeight)); |
| SuccessOrExit(error = aDecoder.ReadUint32(aService.mTtl)); |
| SuccessOrExit(error = aDecoder.ReadUint32(aRequestId)); |
| SuccessOrExit(error = aDecoder.ReadData(aCallbackData, aCallbackDataLen)); |
| |
| exit: |
| return error; |
| } |
| |
| otError DecodeDnssdKey(Decoder &aDecoder, |
| otPlatDnssdKey &aKey, |
| otPlatDnssdRequestId &aRequestId, |
| const uint8_t *&aCallbackData, |
| uint16_t &aCallbackDataLen) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aDecoder.ReadUtf8(aKey.mName)); |
| SuccessOrExit(error = aDecoder.OpenStruct()); |
| if (!aDecoder.IsAllReadInStruct()) |
| { |
| SuccessOrExit(error = aDecoder.ReadUtf8(aKey.mServiceType)); |
| } |
| else |
| { |
| aKey.mServiceType = nullptr; |
| } |
| SuccessOrExit(error = aDecoder.CloseStruct()); |
| SuccessOrExit(error = aDecoder.ReadDataWithLen(aKey.mKeyData, aKey.mKeyDataLength)); |
| SuccessOrExit(error = aDecoder.ReadUint16(aKey.mClass)); |
| SuccessOrExit(error = aDecoder.ReadUint32(aKey.mTtl)); |
| SuccessOrExit(error = aDecoder.ReadUint32(aRequestId)); |
| SuccessOrExit(error = aDecoder.ReadData(aCallbackData, aCallbackDataLen)); |
| |
| exit: |
| return error; |
| } |
| |
| template <> otError EncodeDnssdDiscovery<otPlatDnssdBrowser>(Encoder &aEncoder, const otPlatDnssdBrowser &aDiscovery) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aEncoder.WriteUtf8(aDiscovery.mServiceType)); |
| SuccessOrExit(error = aEncoder.OpenStruct()); |
| if (aDiscovery.mSubTypeLabel != nullptr) |
| { |
| SuccessOrExit(error = aEncoder.WriteUtf8(aDiscovery.mSubTypeLabel)); |
| } |
| SuccessOrExit(error = aEncoder.CloseStruct()); |
| SuccessOrExit(error = aEncoder.WriteUint32(aDiscovery.mInfraIfIndex)); |
| SuccessOrExit(error = aEncoder.WriteData(reinterpret_cast<const uint8_t *>(&aDiscovery.mCallback), |
| sizeof(aDiscovery.mCallback))); |
| |
| exit: |
| return error; |
| } |
| |
| otError EncodeDnssdBrowseResult(Encoder &aEncoder, |
| const otPlatDnssdBrowseResult &aBrowseResult, |
| const uint8_t *aCallbackData, |
| uint16_t aCallbackDataLen) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aEncoder.WriteUtf8(aBrowseResult.mServiceType)); |
| SuccessOrExit(error = aEncoder.OpenStruct()); |
| if (aBrowseResult.mSubTypeLabel != nullptr) |
| { |
| SuccessOrExit(error = aEncoder.WriteUtf8(aBrowseResult.mSubTypeLabel)); |
| } |
| SuccessOrExit(error = aEncoder.CloseStruct()); |
| SuccessOrExit(error = aEncoder.WriteUtf8(aBrowseResult.mServiceInstance)); |
| SuccessOrExit(error = aEncoder.WriteUint32(aBrowseResult.mTtl)); |
| SuccessOrExit(error = aEncoder.WriteUint32(aBrowseResult.mInfraIfIndex)); |
| SuccessOrExit(error = aEncoder.WriteData(aCallbackData, aCallbackDataLen)); |
| |
| exit: |
| return error; |
| } |
| |
| otError DecodeDnssdBrowser(Decoder &aDecoder, |
| otPlatDnssdBrowser &aBrowser, |
| const uint8_t *&aCallbackData, |
| uint16_t &aCallbackDataLen) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aDecoder.ReadUtf8(aBrowser.mServiceType)); |
| SuccessOrExit(error = aDecoder.OpenStruct()); |
| if (!aDecoder.IsAllReadInStruct()) |
| { |
| SuccessOrExit(error = aDecoder.ReadUtf8(aBrowser.mSubTypeLabel)); |
| } |
| else |
| { |
| aBrowser.mSubTypeLabel = nullptr; |
| } |
| SuccessOrExit(error = aDecoder.CloseStruct()); |
| SuccessOrExit(error = aDecoder.ReadUint32(aBrowser.mInfraIfIndex)); |
| SuccessOrExit(error = aDecoder.ReadData(aCallbackData, aCallbackDataLen)); |
| |
| exit: |
| return error; |
| } |
| |
| otError DecodeDnssdBrowseResult(Decoder &aDecoder, |
| otPlatDnssdBrowseResult &aBrowseResult, |
| const uint8_t *&aCallbackData, |
| uint16_t &aCallbackDataLen) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aDecoder.ReadUtf8(aBrowseResult.mServiceType)); |
| SuccessOrExit(error = aDecoder.OpenStruct()); |
| if (!aDecoder.IsAllReadInStruct()) |
| { |
| SuccessOrExit(error = aDecoder.ReadUtf8(aBrowseResult.mSubTypeLabel)); |
| } |
| else |
| { |
| aBrowseResult.mSubTypeLabel = nullptr; |
| } |
| SuccessOrExit(error = aDecoder.CloseStruct()); |
| SuccessOrExit(error = aDecoder.ReadUtf8(aBrowseResult.mServiceInstance)); |
| SuccessOrExit(error = aDecoder.ReadUint32(aBrowseResult.mTtl)); |
| SuccessOrExit(error = aDecoder.ReadUint32(aBrowseResult.mInfraIfIndex)); |
| SuccessOrExit(error = aDecoder.ReadData(aCallbackData, aCallbackDataLen)); |
| |
| exit: |
| return error; |
| } |
| |
| template <> |
| otError EncodeDnssdDiscovery<otPlatDnssdSrvResolver>(Encoder &aEncoder, const otPlatDnssdSrvResolver &aDiscovery) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aEncoder.WriteUtf8(aDiscovery.mServiceInstance)); |
| SuccessOrExit(error = aEncoder.WriteUtf8(aDiscovery.mServiceType)); |
| SuccessOrExit(error = aEncoder.WriteUint32(aDiscovery.mInfraIfIndex)); |
| SuccessOrExit(error = aEncoder.WriteData(reinterpret_cast<const uint8_t *>(&aDiscovery.mCallback), |
| sizeof(aDiscovery.mCallback))); |
| |
| exit: |
| return error; |
| } |
| |
| otError EncodeDnssdSrvResult(Encoder &aEncoder, |
| const otPlatDnssdSrvResult &aSrvResult, |
| const uint8_t *aCallbackData, |
| uint16_t aCallbackDataLen) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aEncoder.WriteUtf8(aSrvResult.mServiceInstance)); |
| SuccessOrExit(error = aEncoder.WriteUtf8(aSrvResult.mServiceType)); |
| SuccessOrExit(error = aEncoder.OpenStruct()); |
| if (aSrvResult.mHostName != nullptr) |
| { |
| SuccessOrExit(error = aEncoder.WriteUtf8(aSrvResult.mHostName)); |
| } |
| SuccessOrExit(error = aEncoder.CloseStruct()); |
| SuccessOrExit(error = aEncoder.WriteUint16(aSrvResult.mPort)); |
| SuccessOrExit(error = aEncoder.WriteUint16(aSrvResult.mPriority)); |
| SuccessOrExit(error = aEncoder.WriteUint16(aSrvResult.mWeight)); |
| SuccessOrExit(error = aEncoder.WriteUint32(aSrvResult.mTtl)); |
| SuccessOrExit(error = aEncoder.WriteUint32(aSrvResult.mInfraIfIndex)); |
| SuccessOrExit(error = aEncoder.WriteData(aCallbackData, aCallbackDataLen)); |
| |
| exit: |
| return error; |
| } |
| |
| otError DecodeDnssdSrvResolver(Decoder &aDecoder, |
| otPlatDnssdSrvResolver &aSrvResolver, |
| const uint8_t *&aCallbackData, |
| uint16_t &aCallbackDataLen) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aDecoder.ReadUtf8(aSrvResolver.mServiceInstance)); |
| SuccessOrExit(error = aDecoder.ReadUtf8(aSrvResolver.mServiceType)); |
| SuccessOrExit(error = aDecoder.ReadUint32(aSrvResolver.mInfraIfIndex)); |
| SuccessOrExit(error = aDecoder.ReadData(aCallbackData, aCallbackDataLen)); |
| |
| exit: |
| return error; |
| } |
| |
| otError DecodeDnssdSrvResult(Decoder &aDecoder, |
| otPlatDnssdSrvResult &aSrvResult, |
| const uint8_t *&aCallbackData, |
| uint16_t &aCallbackDataLen) |
| { |
| otError error = OT_ERROR_NONE; |
| |
| SuccessOrExit(error = aDecoder.ReadUtf8(aSrvResult.mServiceInstance)); |
| SuccessOrExit(error = aDecoder.ReadUtf8(aSrvResult.mServiceType)); |
| SuccessOrExit(error = aDecoder.OpenStruct()); |
| if (!aDecoder.IsAllReadInStruct()) |
| { |
| SuccessOrExit(error = aDecoder.ReadUtf8(aSrvResult.mHostName)); |
| } |
| else |
| { |
| aSrvResult.mHostName = nullptr; |
| } |
| SuccessOrExit(error = aDecoder.CloseStruct()); |
| SuccessOrExit(error = aDecoder.ReadUint16(aSrvResult.mPort)); |
| SuccessOrExit(error = aDecoder.ReadUint16(aSrvResult.mPriority)); |
| SuccessOrExit(error = aDecoder.ReadUint16(aSrvResult.mWeight)); |
| SuccessOrExit(error = aDecoder.ReadUint32(aSrvResult.mTtl)); |
| SuccessOrExit(error = aDecoder.ReadUint32(aSrvResult.mInfraIfIndex)); |
| SuccessOrExit(error = aDecoder.ReadData(aCallbackData, aCallbackDataLen)); |
| |
| exit: |
| return error; |
| } |
| |
| } // namespace Spinel |
| } // namespace ot |