Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ota-requestor-app - initial set of changes of development branch #9474

Merged
merged 4 commits into from
Sep 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions examples/ota-requestor-app/linux/.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# 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("//build_overrides/build.gni")

# The location of the build configuration file.
buildconfig = "${build_root}/config/BUILDCONFIG.gn"

# CHIP uses angle bracket includes.
check_system_includes = true

default_args = {
import("//args.gni")
}
37 changes: 37 additions & 0 deletions examples/ota-requestor-app/linux/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# 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("//build_overrides/build.gni")
import("//build_overrides/chip.gni")

executable("chip-ota-requestor-app") {
sources = [
"PersistentStorage.cpp",
"main.cpp",
]

deps = [
"${chip_root}/examples/ota-requestor-app/ota-requestor-common",
"${chip_root}/examples/platform/linux:app-main",
"${chip_root}/src/lib",
]

cflags = [ "-Wconversion" ]

output_dir = root_out_dir
}

group("linux") {
deps = [ ":chip-ota-requestor-app" ]
}
251 changes: 251 additions & 0 deletions examples/ota-requestor-app/linux/PersistentStorage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
/*
* Copyright (c) 2021 Project CHIP Authors
* All rights reserved.
*
* 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.
*
*/
#include "PersistentStorage.h"

#include <lib/core/CHIPEncoding.h>
#include <lib/support/Base64.h>
#include <protocols/secure_channel/PASESession.h>

#include <fstream>
#include <memory>

using String = std::basic_string<char>;
using Section = std::map<String, String>;
using Sections = std::map<String, Section>;

using namespace ::chip;
using namespace ::chip::Controller;
using namespace ::chip::Logging;

constexpr const char kFilename[] = "/tmp/chip_tool_config.ini";
constexpr const char kDefaultSectionName[] = "Default";
constexpr const char kPortKey[] = "ListenPort";
constexpr const char kLoggingKey[] = "LoggingLevel";
constexpr const char kLocalNodeIdKey[] = "LocalNodeId";
constexpr const char kRemoteNodeIdKey[] = "RemoteNodeId";
constexpr LogCategory kDefaultLoggingLevel = kLogCategory_Detail;

namespace {

std::string StringToBase64(const std::string & value)
{
std::unique_ptr<char[]> buffer(new char[BASE64_ENCODED_LEN(value.length())]);

uint32_t len =
chip::Base64Encode32(reinterpret_cast<const uint8_t *>(value.data()), static_cast<uint32_t>(value.length()), buffer.get());
if (len == UINT32_MAX)
{
return "";
}

return std::string(buffer.get(), len);
}

std::string Base64ToString(const std::string & b64Value)
{
std::unique_ptr<uint8_t[]> buffer(new uint8_t[BASE64_MAX_DECODED_LEN(b64Value.length())]);

uint32_t len = chip::Base64Decode32(b64Value.data(), static_cast<uint32_t>(b64Value.length()), buffer.get());
if (len == UINT32_MAX)
{
return "";
}

return std::string(reinterpret_cast<const char *>(buffer.get()), len);
}

} // namespace

CHIP_ERROR PersistentStorage::Init()
{
CHIP_ERROR err = CHIP_NO_ERROR;

std::ifstream ifs;
ifs.open(kFilename, std::ifstream::in);
if (!ifs.good())
{
CommitConfig();
ifs.open(kFilename, std::ifstream::in);
}
VerifyOrExit(ifs.is_open(), err = CHIP_ERROR_OPEN_FAILED);
holbrookt marked this conversation as resolved.
Show resolved Hide resolved

mConfig.parse(ifs);
ifs.close();

exit:
return err;
}

CHIP_ERROR PersistentStorage::SyncGetKeyValue(const char * key, void * value, uint16_t & size)
{
std::string iniValue;

auto section = mConfig.sections[kDefaultSectionName];
auto it = section.find(key);
ReturnErrorCodeIf(it == section.end(), CHIP_ERROR_KEY_NOT_FOUND);

ReturnErrorCodeIf(!inipp::extract(section[key], iniValue), CHIP_ERROR_INVALID_ARGUMENT);

iniValue = Base64ToString(iniValue);

uint16_t dataSize = static_cast<uint16_t>(iniValue.size());
if (dataSize > size)
{
size = dataSize;
return CHIP_ERROR_BUFFER_TOO_SMALL;
}

size = dataSize;
memcpy(value, iniValue.data(), dataSize);

return CHIP_NO_ERROR;
}

CHIP_ERROR PersistentStorage::SyncSetKeyValue(const char * key, const void * value, uint16_t size)
{
auto section = mConfig.sections[kDefaultSectionName];
section[key] = StringToBase64(std::string(static_cast<const char *>(value), size));

mConfig.sections[kDefaultSectionName] = section;
return CommitConfig();
}

CHIP_ERROR PersistentStorage::SyncDeleteKeyValue(const char * key)
{
auto section = mConfig.sections[kDefaultSectionName];
section.erase(key);

mConfig.sections[kDefaultSectionName] = section;
return CommitConfig();
}

CHIP_ERROR PersistentStorage::CommitConfig()
{
CHIP_ERROR err = CHIP_NO_ERROR;

std::ofstream ofs;
std::string tmpPath = kFilename;
tmpPath.append(".tmp");
ofs.open(tmpPath, std::ofstream::out | std::ofstream::trunc);
VerifyOrExit(ofs.good(), err = CHIP_ERROR_WRITE_FAILED);

mConfig.generate(ofs);
ofs.close();
VerifyOrExit(ofs.good(), err = CHIP_ERROR_WRITE_FAILED);

VerifyOrExit(rename(tmpPath.c_str(), kFilename) == 0, err = CHIP_ERROR_WRITE_FAILED);

exit:
return err;
}

uint16_t PersistentStorage::GetListenPort()
{
CHIP_ERROR err = CHIP_NO_ERROR;
// By default chip-tool listens on CHIP_PORT + 1. This is done in order to avoid
// having 2 servers listening on CHIP_PORT when one runs an accessory server locally.
uint16_t chipListenPort = CHIP_PORT + 1;

char value[6];
uint16_t size = static_cast<uint16_t>(sizeof(value));
err = SyncGetKeyValue(kPortKey, value, size);
if (CHIP_NO_ERROR == err)
{
uint16_t tmpValue;
std::stringstream ss(value);
ss >> tmpValue;
if (!ss.fail() && ss.eof())
{
chipListenPort = tmpValue;
}
}

return chipListenPort;
}

LogCategory PersistentStorage::GetLoggingLevel()
{
CHIP_ERROR err = CHIP_NO_ERROR;
LogCategory chipLogLevel = kDefaultLoggingLevel;

char value[9];
uint16_t size = static_cast<uint16_t>(sizeof(value));
err = SyncGetKeyValue(kLoggingKey, value, size);
if (CHIP_NO_ERROR == err)
{
if (strcasecmp(value, "none") == 0)
{
chipLogLevel = kLogCategory_None;
}
else if (strcasecmp(value, "error") == 0)
{
chipLogLevel = kLogCategory_Error;
}
else if (strcasecmp(value, "progress") == 0)
{
chipLogLevel = kLogCategory_Progress;
}
else if (strcasecmp(value, "detail") == 0)
{
chipLogLevel = kLogCategory_Detail;
}
}

return chipLogLevel;
}

NodeId PersistentStorage::GetNodeId(const char * key, NodeId defaultVal)
{
CHIP_ERROR err = CHIP_NO_ERROR;

uint64_t nodeId;
uint16_t size = static_cast<uint16_t>(sizeof(nodeId));
err = SyncGetKeyValue(key, &nodeId, size);
if (err == CHIP_NO_ERROR)
{
return static_cast<NodeId>(Encoding::LittleEndian::HostSwap64(nodeId));
}

return defaultVal;
}

NodeId PersistentStorage::GetLocalNodeId()
{
return GetNodeId(kLocalNodeIdKey, kTestControllerNodeId);
}

NodeId PersistentStorage::GetRemoteNodeId()
{
return GetNodeId(kRemoteNodeIdKey, kTestDeviceNodeId);
}

CHIP_ERROR PersistentStorage::SetNodeId(const char * key, NodeId value)
{
uint64_t nodeId = Encoding::LittleEndian::HostSwap64(value);
return SyncSetKeyValue(key, &nodeId, sizeof(nodeId));
}

CHIP_ERROR PersistentStorage::SetLocalNodeId(NodeId nodeId)
{
return SetNodeId(kLocalNodeIdKey, nodeId);
}

CHIP_ERROR PersistentStorage::SetRemoteNodeId(NodeId nodeId)
{
return SetNodeId(kRemoteNodeIdKey, nodeId);
}
54 changes: 54 additions & 0 deletions examples/ota-requestor-app/linux/PersistentStorage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2021 Project CHIP Authors
* All rights reserved.
*
* 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.
*
*/

#pragma once

#include <app/util/basic-types.h>
#include <controller/CHIPDeviceController.h>
#include <inipp/inipp.h>
#include <lib/support/logging/CHIPLogging.h>

class PersistentStorage : public chip::PersistentStorageDelegate
{
public:
CHIP_ERROR Init();

/////////// PersistentStorageDelegate Interface /////////
CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override;
CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override;
CHIP_ERROR SyncDeleteKeyValue(const char * key) override;

uint16_t GetListenPort();
chip::Logging::LogCategory GetLoggingLevel();

// Return the stored node ids, or the default ones if nothing is stored.
chip::NodeId GetLocalNodeId();
chip::NodeId GetRemoteNodeId();

// Store node ids.
CHIP_ERROR SetLocalNodeId(chip::NodeId nodeId);
CHIP_ERROR SetRemoteNodeId(chip::NodeId nodeId);

private:
// Helpers for node ids.
chip::NodeId GetNodeId(const char * key, chip::NodeId defaultVal);
CHIP_ERROR SetNodeId(const char * key, chip::NodeId value);

CHIP_ERROR CommitConfig();
inipp::Ini<char> mConfig;
};
Loading