KNX IoT
KNX IoT Point API stack implementation
oc_log.h
Go to the documentation of this file.
1 /*
2 // Copyright (c) 2016 Intel Corporation
3 // Copyright (c) 2022 Cascoda Ltd.
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 */
42 #ifndef OC_LOG_H
43 #define OC_LOG_H
44 
45 #include <stdio.h>
46 #include <string.h>
47 #ifdef WIN32
48 #define __FILENAME__ \
49  (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
50 #else
51 #define __FILENAME__ \
52  (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
53 #endif
54 
55 #ifdef __ANDROID__
56 #include "android/oc_log_android.h"
57 #endif
58 
59 #ifdef __cplusplus
60 extern "C" {
61 #endif
62 
63 #ifdef OC_PRINT
64 #ifdef __ANDROID__
65 #define TAG "OC-JNI"
66 #define PRINT(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
67 #else
68 #ifdef OC_LOG_TO_FILE
69 // logging to file
70 #define PRINT(...) oc_file_print(__VA_ARGS__)
71 #else
72 #define PRINT(...) printf(__VA_ARGS__)
73 #endif
74 #endif
75 #else
76 #define PRINT(...)
77 #endif
78 
79 #ifdef OC_PRINT_APP
80 #define PRINT_APP(...) printf(__VA_ARGS__)
81 #else
82 #define PRINT_APP(...)
83 #endif
84 
85 #define SPRINTF(...) sprintf(__VA_ARGS__)
86 #define SNPRINTF(...) snprintf(__VA_ARGS__)
87 
88 #define PRINTipaddr(endpoint) \
89  do { \
90  const char *scheme = "coap"; \
91  if ((endpoint).flags & SECURED) \
92  scheme = "coaps"; \
93  if ((endpoint).flags & TCP) \
94  scheme = "coap+tcp"; \
95  if ((endpoint).flags & TCP && (endpoint).flags & SECURED) \
96  scheme = "coaps+tcp"; \
97  if ((endpoint).flags & IPV4) { \
98  PRINT("%s://%d.%d.%d.%d:%d", scheme, ((endpoint).addr.ipv4.address)[0], \
99  ((endpoint).addr.ipv4.address)[1], \
100  ((endpoint).addr.ipv4.address)[2], \
101  ((endpoint).addr.ipv4.address)[3], (endpoint).addr.ipv4.port); \
102  } else { \
103  PRINT( \
104  "%s://[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%" \
105  "02x:%" \
106  "02x%" \
107  "02x]:%d", \
108  scheme, ((endpoint).addr.ipv6.address)[0], \
109  ((endpoint).addr.ipv6.address)[1], ((endpoint).addr.ipv6.address)[2], \
110  ((endpoint).addr.ipv6.address)[3], ((endpoint).addr.ipv6.address)[4], \
111  ((endpoint).addr.ipv6.address)[5], ((endpoint).addr.ipv6.address)[6], \
112  ((endpoint).addr.ipv6.address)[7], ((endpoint).addr.ipv6.address)[8], \
113  ((endpoint).addr.ipv6.address)[9], ((endpoint).addr.ipv6.address)[10], \
114  ((endpoint).addr.ipv6.address)[11], \
115  ((endpoint).addr.ipv6.address)[12], \
116  ((endpoint).addr.ipv6.address)[13], \
117  ((endpoint).addr.ipv6.address)[14], \
118  ((endpoint).addr.ipv6.address)[15], (endpoint).addr.ipv6.port); \
119  } \
120  } while (0)
121 
122 #define PRINTipaddr_flags(endpoint) \
123  do { \
124  if ((endpoint).flags & SECURED) { \
125  PRINT(" Secured "); \
126  }; \
127  if ((endpoint).flags & MULTICAST) { \
128  PRINT(" MULTICAST "); \
129  }; \
130  if ((endpoint).flags & TCP) { \
131  PRINT(" TCP "); \
132  }; \
133  if ((endpoint).flags & IPV4) { \
134  PRINT(" IPV4 "); \
135  }; \
136  if ((endpoint).flags & IPV6) { \
137  PRINT(" IPV6 "); \
138  }; \
139  if ((endpoint).flags & OSCORE) { \
140  PRINT(" OSCORE "); \
141  }; \
142  if ((endpoint).flags & ACCEPTED) { \
143  PRINT(" ACCEPTED "); \
144  }; \
145  if ((endpoint).flags & OSCORE_DECRYPTED) { \
146  PRINT(" OSCORE_DECRYPTED "); \
147  }; \
148  PRINT(" \n"); \
149  } while (0)
150 
151 #define PRINTipaddr_local(endpoint) \
152  do { \
153  const char *scheme = "coap"; \
154  if ((endpoint).flags & SECURED) \
155  scheme = "coaps"; \
156  if ((endpoint).flags & TCP) \
157  scheme = "coap+tcp"; \
158  if ((endpoint).flags & TCP && (endpoint).flags & SECURED) \
159  scheme = "coaps+tcp"; \
160  if ((endpoint).flags & IPV4) { \
161  PRINT("%s://%d.%d.%d.%d:%d", scheme, \
162  ((endpoint).addr_local.ipv4.address)[0], \
163  ((endpoint).addr_local.ipv4.address)[1], \
164  ((endpoint).addr_local.ipv4.address)[2], \
165  ((endpoint).addr_local.ipv4.address)[3], \
166  (endpoint).addr_local.ipv4.port); \
167  } else { \
168  PRINT( \
169  "%s://[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%" \
170  "02x:%" \
171  "02x%" \
172  "02x]:%d", \
173  scheme, ((endpoint).addr_local.ipv6.address)[0], \
174  ((endpoint).addr_local.ipv6.address)[1], \
175  ((endpoint).addr_local.ipv6.address)[2], \
176  ((endpoint).addr_local.ipv6.address)[3], \
177  ((endpoint).addr_local.ipv6.address)[4], \
178  ((endpoint).addr_local.ipv6.address)[5], \
179  ((endpoint).addr_local.ipv6.address)[6], \
180  ((endpoint).addr_local.ipv6.address)[7], \
181  ((endpoint).addr_local.ipv6.address)[8], \
182  ((endpoint).addr_local.ipv6.address)[9], \
183  ((endpoint).addr_local.ipv6.address)[10], \
184  ((endpoint).addr_local.ipv6.address)[11], \
185  ((endpoint).addr_local.ipv6.address)[12], \
186  ((endpoint).addr_local.ipv6.address)[13], \
187  ((endpoint).addr_local.ipv6.address)[14], \
188  ((endpoint).addr_local.ipv6.address)[15], \
189  (endpoint).addr_local.ipv6.port); \
190  } \
191  } while (0)
192 
193 #define IPADDR_BUFF_SIZE 64 // max size : scheme://[ipv6]:port = 59 bytes
194 
195 #define SNPRINTFipaddr(str, size, endpoint) \
196  do { \
197  const char *scheme = "coap"; \
198  if ((endpoint).flags & SECURED) \
199  scheme = "coaps"; \
200  if ((endpoint).flags & TCP) \
201  scheme = "coap+tcp"; \
202  if ((endpoint).flags & TCP && (endpoint).flags & SECURED) \
203  scheme = "coaps+tcp"; \
204  memset(str, 0, size); \
205  if ((endpoint).flags & IPV4) { \
206  SNPRINTF(str, size, "%s://%d.%d.%d.%d:%d", scheme, \
207  ((endpoint).addr.ipv4.address)[0], \
208  ((endpoint).addr.ipv4.address)[1], \
209  ((endpoint).addr.ipv4.address)[2], \
210  ((endpoint).addr.ipv4.address)[3], (endpoint).addr.ipv4.port); \
211  } else { \
212  SNPRINTF( \
213  str, size, \
214  "%s://" \
215  "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:" \
216  "%02x%02x]:%d", \
217  scheme, ((endpoint).addr.ipv6.address)[0], \
218  ((endpoint).addr.ipv6.address)[1], ((endpoint).addr.ipv6.address)[2], \
219  ((endpoint).addr.ipv6.address)[3], ((endpoint).addr.ipv6.address)[4], \
220  ((endpoint).addr.ipv6.address)[5], ((endpoint).addr.ipv6.address)[6], \
221  ((endpoint).addr.ipv6.address)[7], ((endpoint).addr.ipv6.address)[8], \
222  ((endpoint).addr.ipv6.address)[9], ((endpoint).addr.ipv6.address)[10], \
223  ((endpoint).addr.ipv6.address)[11], \
224  ((endpoint).addr.ipv6.address)[12], \
225  ((endpoint).addr.ipv6.address)[13], \
226  ((endpoint).addr.ipv6.address)[14], \
227  ((endpoint).addr.ipv6.address)[15], (endpoint).addr.ipv6.port); \
228  } \
229  } while (0)
230 
231 #define SNPRINTFbytes(buff, size, data, len) \
232  do { \
233  char *beg = (buff); \
234  char *end = (buff) + (size); \
235  for (size_t i = 0; beg <= (end - 3) && i < (len); i++) { \
236  beg += (i == 0) ? SPRINTF(beg, "%02x", (data)[i]) \
237  : SPRINTF(beg, ":%02x", (data)[i]); \
238  } \
239  } while (0)
240 
241 #define OC_LOG(level, ...) \
242  do { \
243  PRINT("%s: %s <%s:%d>: ", level, __FILENAME__, __func__, __LINE__); \
244  PRINT(__VA_ARGS__); \
245  PRINT("\n"); \
246  } while (0)
247 
248 #define OC_LOGbytes_internalxx(prefix, bytes, length) \
249  do { \
250  PRINT("%s: %s <%s:%d>:\n", prefix, __FILENAME__, __func__, __LINE__); \
251  uint16_t i; \
252  for (i = 0; i < (length); i++) \
253  PRINT(" %02X", (bytes)[i]); \
254  PRINT("\n"); \
255  } while (0)
256 
257 #define OC_LOGbytes_internal(prefix, bytes, length) \
258  do { \
259  uint16_t i; \
260  for (i = 0; i < (length); i++) \
261  PRINT(" %02X", (bytes)[i]); \
262  PRINT("\n"); \
263  } while (0)
264 
265 #ifdef OC_DEBUG
266 #ifdef __ANDROID__
267 #define OC_LOG(level, ...) \
268  android_log(level, __FILE__, __func__, __LINE__, __VA_ARGS__)
269 #define OC_LOGipaddr(endpoint) \
270  android_log_ipaddr("DEBUG", __FILE__, __func__, __LINE__, endpoint)
271 #define OC_LOGbytes(bytes, length) \
272  android_log_bytes("DEBUG", __FILE__, __func__, __LINE__, bytes, length)
273 #else /* ! __ANDROID */
274 /*
275 #define OC_LOG(level, ...) \
276  do { \
277  PRINT("%s: %s <%s:%d>: ", level, __FILENAME__, __func__, __LINE__); \
278  PRINT(__VA_ARGS__); \
279  PRINT("\n"); \
280  } while (0)
281 */
282 
283 #define OC_LOGipaddr(endpoint) \
284  do { \
285  PRINT("DEBUG: %s <%s:%d>: ", __FILENAME__, __func__, __LINE__); \
286  PRINTipaddr(endpoint); \
287  PRINT("\n"); \
288  } while (0)
289 
290 #ifndef OC_NO_LOG_BYTES
291 #define OC_LOGbytes(bytes, length) \
292  do { \
293  PRINT("D: %s <%s:%d>: ", __FILENAME__, __func__, __LINE__); \
294  uint16_t i; \
295  for (i = 0; i < (length); i++) \
296  PRINT(" %02X", (bytes)[i]); \
297  PRINT("\n"); \
298  } while (0)
299 #else
300 #endif /* NO_LOG_BYTES */
301 #endif /* __ANDROID__ */
302 
303 #define OC_DBG(...) OC_LOG("D", __VA_ARGS__)
304 #define OC_WRN(...) OC_LOG("W", __VA_ARGS__)
305 #define OC_ERR(...) OC_LOG("E", __VA_ARGS__)
306 
307 #else
308 // #define OC_LOG(...)
309 #define OC_DBG(...)
310 //#define OC_WRN(...)
311 //#define OC_ERR(...)
312 #define OC_LOGipaddr(endpoint)
313 #define OC_LOGbytes(bytes, length)
314 #endif
315 
316 // always do OC_ERR and OC_WRN logs
317 #define OC_ERR(...) OC_LOG("E", __VA_ARGS__)
318 #define OC_WRN(...) OC_LOG("W", __VA_ARGS__)
319 
320 #ifdef OC_DEBUG_OSCORE
321 #define OC_DBG_OSCORE(...) OC_LOG("OSCORE", __VA_ARGS__)
322 #define OC_DBG_SPAKE(...) OC_LOG("SPAKE", __VA_ARGS__)
323 #define OC_LOGbytes_OSCORE(bytes, length) \
324  OC_LOGbytes_internal("OSCORE", bytes, length)
325 #define OC_LOGbytes_SPAKE(bytes, length) \
326  OC_LOGbytes_internal("SPAKE", bytes, length)
327 #else
328 #define OC_DBG_OSCORE(...)
329 #define OC_DBG_SPAKE(...)
330 #define OC_LOGbytes_OSCORE(bytes, length)
331 #define OC_LOGbytes_SPAKE(bytes, length)
332 #endif
333 
334 #ifdef __cplusplus
335 }
336 #endif
337 
338 #endif /* OC_LOG_H */