blob: 3e6e7904145ec57dad8166c23a8eb679304f901f [file] [edit]
/*
* 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