Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020 Project CHIP Authors
4 : * Copyright (c) 2016-2017 Nest Labs, Inc.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : /**
20 : * @file
21 : * This file contains free functions for mapping OS and LwIP
22 : * stack-specific errors into CHIP System Layer-specific errors
23 : * and for converting those mapped errors into descriptive
24 : * error strings.
25 : */
26 :
27 : // Include module header
28 : #include <system/SystemError.h>
29 :
30 : #include <lib/core/ErrorStr.h>
31 : #include <lib/support/CHIPMemString.h>
32 : #include <lib/support/DLLUtil.h>
33 :
34 : #include <lib/core/CHIPConfig.h>
35 :
36 : // Include local headers
37 : #if CHIP_SYSTEM_CONFIG_USE_LWIP
38 : #include <lwip/err.h>
39 : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
40 :
41 : #include <limits>
42 : #include <stddef.h>
43 : #include <string.h>
44 :
45 : namespace chip {
46 : namespace System {
47 :
48 : namespace Internal {
49 : /**
50 : * This implements a mapping function for CHIP System Layer errors that allows mapping integers in the number space of the
51 : * underlying POSIX network and OS stack errors into a platform- or system-specific range. Error codes beyond those currently
52 : * defined by POSIX or the ISO C/C++ standards are mapped similar to the standard ones.
53 : *
54 : * @param[in] aError The POSIX network or OS error to map.
55 : *
56 : * @return The mapped POSIX network or OS error.
57 : */
58 : #if CHIP_CONFIG_ERROR_SOURCE && CHIP_CONFIG_ERROR_STD_SOURCE_LOCATION
59 : DLL_EXPORT CHIP_ERROR MapErrorPOSIX(int aError, std::source_location location)
60 : {
61 : return (aError == 0 ? CHIP_NO_ERROR : CHIP_ERROR(ChipError::Range::kPOSIX, aError, location));
62 : }
63 : #elif CHIP_CONFIG_ERROR_SOURCE
64 21934 : DLL_EXPORT CHIP_ERROR MapErrorPOSIX(int aError, const char * file, unsigned int line)
65 : {
66 21934 : return (aError == 0 ? CHIP_NO_ERROR : CHIP_ERROR(ChipError::Range::kPOSIX, aError, file, line));
67 : }
68 : #else
69 : DLL_EXPORT CHIP_ERROR MapErrorPOSIX(int aError)
70 : {
71 : return (aError == 0 ? CHIP_NO_ERROR : CHIP_ERROR(ChipError::Range::kPOSIX, aError));
72 : }
73 : #endif
74 : } // namespace Internal
75 :
76 : /**
77 : * This implements a function to return an NULL-terminated OS-specific descriptive C string, associated with the specified, mapped
78 : * OS error.
79 : *
80 : * @param[in] aError The mapped OS-specific error to describe.
81 : *
82 : * @return A NULL-terminated, OS-specific descriptive C string describing the error.
83 : */
84 17 : DLL_EXPORT const char * DescribeErrorPOSIX(CHIP_ERROR aError)
85 : {
86 17 : const int lError = static_cast<int>(aError.GetValue());
87 : #if CHIP_SYSTEM_CONFIG_THREAD_LOCAL_STORAGE
88 : static thread_local char errBuf[128];
89 : #else
90 : static char errBuf[128];
91 : #endif // CHIP_SYSTEM_CONFIG_THREAD_LOCAL_STORAGE
92 :
93 : // Use thread-safe strerror_r when available
94 : #if defined(_GNU_SOURCE) && !defined(__ANDROID__)
95 : // GNU version returns char*
96 17 : const char * s = strerror_r(lError, errBuf, sizeof(errBuf));
97 17 : if (s != nullptr)
98 : {
99 17 : if (s != errBuf)
100 : {
101 17 : chip::Platform::CopyString(errBuf, sizeof(errBuf), s);
102 : }
103 17 : return errBuf;
104 : }
105 : #elif defined(_POSIX_C_SOURCE)
106 : // POSIX version returns int (0 on success)
107 : if (strerror_r(lError, errBuf, sizeof(errBuf)) == 0)
108 : {
109 : return errBuf;
110 : }
111 : #else
112 : // Fallback for platforms without strerror_r
113 : const char * s = strerror(lError);
114 : if (s != nullptr)
115 : {
116 : chip::Platform::CopyString(errBuf, sizeof(errBuf), s);
117 : return errBuf;
118 : }
119 : #endif
120 :
121 0 : return "Unknown POSIX error";
122 : }
123 :
124 : /**
125 : * Register a text error formatter for POSIX errors.
126 : */
127 128 : void RegisterPOSIXErrorFormatter()
128 : {
129 : static ErrorFormatter sPOSIXErrorFormatter = { FormatPOSIXError, nullptr };
130 : static bool sRegistered = false;
131 128 : if (sRegistered)
132 : {
133 60 : return;
134 : }
135 68 : RegisterErrorFormatter(&sPOSIXErrorFormatter);
136 68 : sRegistered = true;
137 : }
138 :
139 : /**
140 : * Given a POSIX error, returns a human-readable NULL-terminated C string
141 : * describing the error.
142 : *
143 : * @param[in] buf Buffer into which the error string will be placed.
144 : * @param[in] bufSize Size of the supplied buffer in bytes.
145 : * @param[in] err The error to be described.
146 : *
147 : * @return true If a description string was written into the supplied buffer.
148 : * @return false If the supplied error was not a POSIX error.
149 : *
150 : */
151 71 : bool FormatPOSIXError(char * buf, uint16_t bufSize, CHIP_ERROR err)
152 : {
153 71 : if (err.IsRange(ChipError::Range::kPOSIX))
154 : {
155 : const char * desc =
156 : #if CHIP_CONFIG_SHORT_ERROR_STR
157 : nullptr;
158 : #else
159 16 : DescribeErrorPOSIX(err);
160 : #endif
161 16 : FormatError(buf, bufSize, "OS", err, desc);
162 16 : return true;
163 : }
164 :
165 55 : return false;
166 : }
167 :
168 : /**
169 : * This implements a mapping function for CHIP System Layer errors that allows mapping integers in the number space of the
170 : * Zephyr OS user API stack errors into the POSIX range.
171 : *
172 : * @param[in] aError The native Zephyr API error to map.
173 : *
174 : * @return The mapped POSIX error.
175 : */
176 0 : DLL_EXPORT CHIP_ERROR MapErrorZephyr(int aError)
177 : {
178 0 : return Internal::MapErrorPOSIX(-aError CHIP_ERROR_SOURCE_LOCATION_NULL);
179 : }
180 :
181 : #if CHIP_SYSTEM_CONFIG_USE_LWIP
182 :
183 : /**
184 : * This implements a mapping function for CHIP System Layer errors that allows mapping underlying LwIP network stack errors into a
185 : * platform- or system-specific range.
186 : *
187 : * @param[in] aError The LwIP error to map.
188 : *
189 : * @return The mapped LwIP network or OS error.
190 : *
191 : */
192 : DLL_EXPORT CHIP_ERROR MapErrorLwIP(err_t aError)
193 : {
194 : static_assert(ChipError::CanEncapsulate(ChipError::Range::kLwIP, err_t{}), "Can't represent all LWIP errors");
195 : return (aError == ERR_OK ? CHIP_NO_ERROR : CHIP_ERROR(ChipError::Range::kLwIP, static_cast<int>(-aError)));
196 : }
197 :
198 : /**
199 : * This implements a function to return an NULL-terminated LwIP-specific descriptive C string, associated with the specified,
200 : * mapped LwIP error.
201 : *
202 : * @param[in] aError The mapped LwIP-specific error to describe.
203 : *
204 : * @return A NULL-terminated, LwIP-specific descriptive C string describing the error.
205 : *
206 : */
207 : DLL_EXPORT const char * DescribeErrorLwIP(CHIP_ERROR aError)
208 : {
209 : if (!aError.IsRange(ChipError::Range::kLwIP))
210 : {
211 : return nullptr;
212 : }
213 :
214 : const err_t lError = static_cast<err_t>(-static_cast<err_t>(aError.GetValue()));
215 :
216 : // If we are not compiling with LWIP_DEBUG asserted, the unmapped
217 : // local value may go unused.
218 :
219 : (void) lError;
220 :
221 : return lwip_strerr(lError);
222 : }
223 :
224 : /**
225 : * Register a text error formatter for LwIP errors.
226 : */
227 : void RegisterLwIPErrorFormatter()
228 : {
229 : static ErrorFormatter sLwIPErrorFormatter = { FormatLwIPError, nullptr };
230 :
231 : RegisterErrorFormatter(&sLwIPErrorFormatter);
232 : }
233 :
234 : /**
235 : * Given an LwIP error, returns a human-readable NULL-terminated C string
236 : * describing the error.
237 : *
238 : * @param[in] buf Buffer into which the error string will be placed.
239 : * @param[in] bufSize Size of the supplied buffer in bytes.
240 : * @param[in] err The error to be described.
241 : *
242 : * @return true If a description string was written into the supplied buffer.
243 : * @return false If the supplied error was not an LwIP error.
244 : *
245 : */
246 : bool FormatLwIPError(char * buf, uint16_t bufSize, CHIP_ERROR err)
247 : {
248 : if (err.IsRange(ChipError::Range::kLwIP))
249 : {
250 : const char * desc =
251 : #if CHIP_CONFIG_SHORT_ERROR_STR
252 : nullptr;
253 : #else
254 : DescribeErrorLwIP(err);
255 : #endif
256 : chip::FormatError(buf, bufSize, "LwIP", err, desc);
257 : return true;
258 : }
259 : return false;
260 : }
261 :
262 : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
263 :
264 : } // namespace System
265 : } // namespace chip
|