Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / examples / chip-tool / config / PersistentStorage.cpp
1 /*
2  *   Copyright (c) 2020 Project CHIP Authors
3  *   All rights reserved.
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  *
17  */
18 #include "PersistentStorage.h"
19
20 #include <fstream>
21
22 using String   = std::basic_string<char>;
23 using Section  = std::map<String, String>;
24 using Sections = std::map<String, Section>;
25
26 using namespace ::chip;
27 using namespace ::chip::Controller;
28 using namespace ::chip::Logging;
29
30 constexpr const char kFilename[]           = "/tmp/chip_tool_config.ini";
31 constexpr const char kDefaultSectionName[] = "Default";
32 constexpr const char kPortKey[]            = "ListenPort";
33 constexpr const char kLoggingKey[]         = "LoggingLevel";
34 constexpr LogCategory kDefaultLoggingLevel = kLogCategory_Detail;
35
36 CHIP_ERROR PersistentStorage::Init()
37 {
38     CHIP_ERROR err = CHIP_NO_ERROR;
39
40     std::ifstream ifs;
41     ifs.open(kFilename, std::ifstream::in);
42     if (!ifs.good())
43     {
44         CommitConfig();
45         ifs.open(kFilename, std::ifstream::in);
46     }
47     VerifyOrExit(ifs.is_open(), err = CHIP_ERROR_OPEN_FAILED);
48
49     mConfig.parse(ifs);
50     ifs.close();
51
52 exit:
53     return err;
54 }
55
56 void PersistentStorage::SetStorageDelegate(PersistentStorageResultDelegate * delegate) {}
57
58 CHIP_ERROR PersistentStorage::SyncGetKeyValue(const char * key, char * value, uint16_t & size)
59 {
60     CHIP_ERROR err = CHIP_NO_ERROR;
61     std::string iniValue;
62     size_t iniValueLength = 0;
63
64     auto section = mConfig.sections[kDefaultSectionName];
65     auto it      = section.find(key);
66     VerifyOrExit(it != section.end(), err = CHIP_ERROR_KEY_NOT_FOUND);
67
68     VerifyOrExit(inipp::extract(section[key], iniValue), err = CHIP_ERROR_INVALID_ARGUMENT);
69
70     iniValueLength = iniValue.size();
71     VerifyOrExit(iniValueLength <= static_cast<size_t>(size) - 1, err = CHIP_ERROR_BUFFER_TOO_SMALL);
72
73     iniValueLength        = iniValue.copy(value, iniValueLength);
74     value[iniValueLength] = '\0';
75
76 exit:
77     return err;
78 }
79
80 void PersistentStorage::AsyncSetKeyValue(const char * key, const char * value)
81 {
82     auto section = mConfig.sections[kDefaultSectionName];
83     section[key] = std::string(value);
84
85     mConfig.sections[kDefaultSectionName] = section;
86     CommitConfig();
87 }
88
89 void PersistentStorage::AsyncDeleteKeyValue(const char * key)
90 {
91     auto section = mConfig.sections[kDefaultSectionName];
92     section.erase(key);
93
94     mConfig.sections[kDefaultSectionName] = section;
95     CommitConfig();
96 }
97
98 CHIP_ERROR PersistentStorage::CommitConfig()
99 {
100     CHIP_ERROR err = CHIP_NO_ERROR;
101
102     std::ofstream ofs;
103     std::string tmpPath = kFilename;
104     tmpPath.append(".tmp");
105     ofs.open(tmpPath, std::ofstream::out | std::ofstream::trunc);
106     VerifyOrExit(ofs.good(), err = CHIP_ERROR_WRITE_FAILED);
107
108     mConfig.generate(ofs);
109     ofs.close();
110     VerifyOrExit(ofs.good(), err = CHIP_ERROR_WRITE_FAILED);
111
112     VerifyOrExit(rename(tmpPath.c_str(), kFilename) == 0, err = CHIP_ERROR_WRITE_FAILED);
113
114 exit:
115     return err;
116 }
117
118 uint16_t PersistentStorage::GetListenPort()
119 {
120     CHIP_ERROR err = CHIP_NO_ERROR;
121     // By default chip-tool listens on CHIP_PORT + 1. This is done in order to avoid
122     // having 2 servers listening on CHIP_PORT when one runs an accessory server locally.
123     uint16_t chipListenPort = CHIP_PORT + 1;
124
125     char value[6];
126     uint16_t size = static_cast<uint16_t>(sizeof(value));
127     err           = SyncGetKeyValue(kPortKey, value, size);
128     if (CHIP_NO_ERROR == err)
129     {
130         uint16_t tmpValue;
131         std::stringstream ss(value);
132         ss >> tmpValue;
133         if (!ss.fail() && ss.eof())
134         {
135             chipListenPort = tmpValue;
136         }
137     }
138
139     return chipListenPort;
140 }
141
142 LogCategory PersistentStorage::GetLoggingLevel()
143 {
144     CHIP_ERROR err           = CHIP_NO_ERROR;
145     LogCategory chipLogLevel = kDefaultLoggingLevel;
146
147     char value[9];
148     uint16_t size = static_cast<uint16_t>(sizeof(value));
149     err           = SyncGetKeyValue(kLoggingKey, value, size);
150     if (CHIP_NO_ERROR == err)
151     {
152         if (strcasecmp(value, "none") == 0)
153         {
154             chipLogLevel = kLogCategory_None;
155         }
156         else if (strcasecmp(value, "error") == 0)
157         {
158             chipLogLevel = kLogCategory_Error;
159         }
160         else if (strcasecmp(value, "progress") == 0)
161         {
162             chipLogLevel = kLogCategory_Progress;
163         }
164         else if (strcasecmp(value, "detail") == 0)
165         {
166             chipLogLevel = kLogCategory_Detail;
167         }
168     }
169
170     return chipLogLevel;
171 }