blob: 105bb6ed468a38f72a8c2a60b13c9d3ef9dedc14 [file] [log] [blame]
/**
*
* 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.
*/
#import "MTRThreadOperationalDataset.h"
#import "NSDataSpanConversion.h"
#include "MTRLogging_Internal.h"
#include <lib/support/Span.h>
#include <lib/support/ThreadOperationalDataset.h>
size_t const MTRSizeThreadNetworkName = chip::Thread::kSizeNetworkName;
size_t const MTRSizeThreadExtendedPANID = chip::Thread::kSizeExtendedPanId;
size_t const MTRSizeThreadExtendedPanId = MTRSizeThreadExtendedPANID;
size_t const MTRSizeThreadMasterKey = chip::Thread::kSizeMasterKey;
size_t const MTRSizeThreadPSKc = chip::Thread::kSizePSKc;
size_t const MTRSizeThreadPANID = 2; // Thread's PAN ID is 2 bytes
@implementation MTRThreadOperationalDataset {
chip::Thread::OperationalDataset _cppThreadOperationalDataset;
}
- (instancetype _Nullable)initWithNetworkName:(NSString *)networkName
extendedPANID:(NSData *)extendedPANID
masterKey:(NSData *)masterKey
PSKc:(NSData *)PSKc
channelNumber:(NSNumber *)channelNumber
panID:(NSData *)panID
{
if (self = [super init]) {
_networkName = [networkName copy];
_extendedPANID = [extendedPANID copy];
_masterKey = [masterKey copy];
_PSKc = [PSKc copy];
_channelNumber = [channelNumber copy];
_panID = [panID copy];
_cppThreadOperationalDataset = chip::Thread::OperationalDataset();
if ([self _populateCppOperationalDataset]) {
return self;
}
}
return nil;
}
- (BOOL)_populateCppOperationalDataset
{
_cppThreadOperationalDataset.Clear();
ReturnValueOnFailure(_cppThreadOperationalDataset.SetNetworkName(self.networkName.UTF8String), NO);
if (![self _checkDataLength:self.extendedPANID expectedLength:MTRSizeThreadExtendedPANID]) {
MTR_LOG_ERROR("Invalid ExtendedPANID");
return NO;
}
uint8_t extendedPanId[MTRSizeThreadExtendedPANID];
[self.extendedPANID getBytes:&extendedPanId length:MTRSizeThreadExtendedPANID];
ReturnValueOnFailure(_cppThreadOperationalDataset.SetExtendedPanId(extendedPanId), NO);
if (![self _checkDataLength:self.masterKey expectedLength:MTRSizeThreadMasterKey]) {
MTR_LOG_ERROR("Invalid MasterKey");
return NO;
}
uint8_t masterKey[MTRSizeThreadMasterKey];
[self.masterKey getBytes:&masterKey length:MTRSizeThreadMasterKey];
ReturnValueOnFailure(_cppThreadOperationalDataset.SetMasterKey(masterKey), NO);
if (![self _checkDataLength:self.PSKc expectedLength:MTRSizeThreadPSKc]) {
MTR_LOG_ERROR("Invalid PKSc");
return NO;
}
uint8_t PSKc[MTRSizeThreadPSKc];
[self.PSKc getBytes:&PSKc length:MTRSizeThreadPSKc];
ReturnValueOnFailure(_cppThreadOperationalDataset.SetPSKc(PSKc), NO);
ReturnValueOnFailure(_cppThreadOperationalDataset.SetChannel([self.channelNumber unsignedShortValue]), NO);
// Thread's PAN ID is 2 bytes
if (![self _checkDataLength:self.panID expectedLength:MTRSizeThreadPANID]) {
MTR_LOG_ERROR("Invalid PAN ID");
return NO;
}
uint16_t panID;
memcpy(&panID, [self.panID bytes], MTRSizeThreadPANID);
// The underlying CPP class assumes Big Endianness for the panID
ReturnValueOnFailure(_cppThreadOperationalDataset.SetPanId(panID), NO);
return YES;
}
- (BOOL)_checkDataLength:(NSData *)data expectedLength:(size_t)expectedLength
{
if (data.length != expectedLength) {
MTR_LOG_ERROR("Length Check Failed. Length:%lu is incorrect, must be %tu", static_cast<unsigned long>(data.length), expectedLength);
return NO;
}
return YES;
}
- (instancetype _Nullable)initWithData:(NSData *)data
{
CHIP_ERROR err;
chip::Thread::OperationalDataset dataset;
SuccessOrExit(err = dataset.Init(AsByteSpan(data)));
// len+1 for null termination
char networkName[MTRSizeThreadNetworkName + 1];
uint8_t pskc[MTRSizeThreadPSKc];
uint8_t extendedPANID[MTRSizeThreadExtendedPANID];
uint8_t masterKey[MTRSizeThreadMasterKey];
uint16_t panID;
uint16_t channel;
SuccessOrExit(err = dataset.GetNetworkName(networkName));
SuccessOrExit(err = dataset.GetExtendedPanId(extendedPANID));
SuccessOrExit(err = dataset.GetMasterKey(masterKey));
SuccessOrExit(err = dataset.GetPSKc(pskc));
SuccessOrExit(err = dataset.GetPanId(panID));
SuccessOrExit(err = dataset.GetChannel(channel));
return [self initWithNetworkName:[NSString stringWithUTF8String:networkName]
extendedPANID:AsData(chip::ByteSpan(extendedPANID))
masterKey:AsData(chip::ByteSpan(masterKey))
PSKc:AsData(chip::ByteSpan(pskc))
channelNumber:@(channel)
panID:[NSData dataWithBytes:&panID length:sizeof(uint16_t)]];
exit:
MTR_LOG_ERROR("Error(%" CHIP_ERROR_FORMAT "): Invalid Thread Operational Dataset", err.Format());
return nil;
}
- (NSData *)data
{
chip::ByteSpan span = _cppThreadOperationalDataset.AsByteSpan();
return AsData(span);
}
@end
@implementation MTRThreadOperationalDataset (Deprecated)
- (void)setChannel:(uint16_t)channel
{
_channelNumber = @(channel);
}
- (uint16_t)channel
{
return [self.channelNumber unsignedShortValue];
}
- (nullable instancetype)initWithNetworkName:(NSString *)networkName
extendedPANID:(NSData *)extendedPANID
masterKey:(NSData *)masterKey
PSKc:(NSData *)PSKc
channel:(uint16_t)channel
panID:(NSData *)panID
{
return [self initWithNetworkName:networkName
extendedPANID:extendedPANID
masterKey:masterKey
PSKc:PSKc
channelNumber:@(channel)
panID:panID];
}
@end