blob: fb50d87981b845f3ace786721323dcb810c41b67 [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"
#include "MTRLogging.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
@interface MTRThreadOperationalDataset ()
@property (readonly) chip::Thread::OperationalDataset cppThreadOperationalDataset;
@property (nonatomic, copy) NSNumber * channelNumber;
@end
@implementation MTRThreadOperationalDataset
- (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();
_cppThreadOperationalDataset.SetNetworkName([self.networkName cStringUsingEncoding:NSUTF8StringEncoding]);
if (![self _checkDataLength:self.extendedPANID expectedLength:MTRSizeThreadExtendedPANID]) {
MTR_LOG_ERROR("Invalid ExtendedPANID");
return NO;
}
uint8_t extendedPanId[MTRSizeThreadExtendedPANID];
[self.extendedPANID getBytes:&extendedPanId length:MTRSizeThreadExtendedPANID];
_cppThreadOperationalDataset.SetExtendedPanId(extendedPanId);
if (![self _checkDataLength:self.masterKey expectedLength:MTRSizeThreadMasterKey]) {
MTR_LOG_ERROR("Invalid MasterKey");
return NO;
}
uint8_t masterKey[MTRSizeThreadMasterKey];
[self.masterKey getBytes:&masterKey length:MTRSizeThreadMasterKey];
_cppThreadOperationalDataset.SetMasterKey(masterKey);
if (![self _checkDataLength:self.PSKc expectedLength:MTRSizeThreadPSKc]) {
MTR_LOG_ERROR("Invalid PKSc");
return NO;
}
uint8_t PSKc[MTRSizeThreadPSKc];
[self.PSKc getBytes:&PSKc length:MTRSizeThreadPSKc];
_cppThreadOperationalDataset.SetPSKc(PSKc);
_cppThreadOperationalDataset.SetChannel([self.channelNumber unsignedShortValue]);
// 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
_cppThreadOperationalDataset.SetPanId(CFSwapInt16HostToBig(panID));
return YES;
}
- (BOOL)_checkDataLength:(NSData *)data expectedLength:(size_t)expectedLength
{
if (data.length != expectedLength) {
MTR_LOG_ERROR("Length Check Failed. Length:%tu is incorrect, must be %tu", data.length, expectedLength);
return NO;
}
return YES;
}
- (instancetype _Nullable)initWithData:(NSData *)data
{
chip::ByteSpan span = chip::ByteSpan((uint8_t *) data.bytes, data.length);
auto dataset = chip::Thread::OperationalDataset();
CHIP_ERROR error = dataset.Init(span);
if (error != CHIP_NO_ERROR) {
MTR_LOG_ERROR("Failed to parse data, cannot construct Operational Dataset. %s", chip::ErrorStr(error));
return nil;
}
// 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;
dataset.GetNetworkName(networkName);
dataset.GetExtendedPanId(extendedPANID);
dataset.GetMasterKey(masterKey);
dataset.GetPSKc(pskc);
dataset.GetPanId(panID);
dataset.GetChannel(channel);
panID = CFSwapInt16BigToHost(panID);
return [self initWithNetworkName:[NSString stringWithUTF8String:networkName]
extendedPANID:[NSData dataWithBytes:extendedPANID length:MTRSizeThreadExtendedPANID]
masterKey:[NSData dataWithBytes:masterKey length:MTRSizeThreadMasterKey]
PSKc:[NSData dataWithBytes:pskc length:MTRSizeThreadPSKc]
channelNumber:@(channel)
panID:[NSData dataWithBytes:&panID length:sizeof(uint16_t)]];
}
- (NSData *)data
{
chip::ByteSpan span = _cppThreadOperationalDataset.AsByteSpan();
return [NSData dataWithBytes:span.data() length:span.size()];
}
@end
@implementation MTRThreadOperationalDataset (Deprecated)
- (void)setChannel:(uint16_t)channel
{
self.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