blob: 37eb23175966dacd2d87c4f41f99c99b076904ef [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 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;
@end
@implementation MTRThreadOperationalDataset
- (instancetype _Nullable)initWithNetworkName:(NSString *)networkName
extendedPANID:(NSData *)extendedPANID
masterKey:(NSData *)masterKey
PSKc:(NSData *)PSKc
channel:(NSNumber *)channel
panID:(NSData *)panID
{
if (self = [super init]) {
_networkName = networkName;
_extendedPANID = extendedPANID;
_masterKey = masterKey;
_PSKc = PSKc;
_channel = channel;
_panID = panID;
_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.channel 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]
channel:@(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