Fixed klockwork memory leaks and modified the logs
[platform/upstream/iotivity.git] / resource / csdk / connectivity / common / src / logger.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "logger.h"
22 #include "string.h"
23 #include "oic_logger.h"
24 #include "oic_console_logger.h"
25
26 #ifndef __TIZEN__
27 static oic_log_ctx_t *logCtx = 0;
28
29 static oic_log_level LEVEL_XTABLE[] =
30 { OIC_LOG_DEBUG, OIC_LOG_INFO, OIC_LOG_WARNING, OIC_LOG_ERROR, OIC_LOG_FATAL };
31
32 #endif
33
34 static const uint16_t LINE_BUFFER_SIZE = (16 * 2) + 16 +
35         1; // Show 16 bytes, 2 chars/byte, spaces between bytes, null termination
36
37 // Convert LogLevel to platform-specific severity level.  Store in PROGMEM on Arduino
38 #ifdef __ANDROID__
39 #ifdef ADB_SHELL
40 static const char *LEVEL[] =
41 {   "DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
42
43 #else
44 static android_LogPriority LEVEL[] =
45 {   ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
46 #endif
47 #elif defined __linux__
48 static const char *LEVEL[] __attribute__ ((unused)) =
49 {   "DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
50 #elif defined ARDUINO
51 #include <stdarg.h>
52 #include "Arduino.h"
53
54 PROGMEM const char level0[] = "DEBUG";
55 PROGMEM const char level1[] = "INFO";
56 PROGMEM const char level2[] = "WARNING";
57 PROGMEM const char level3[] = "ERROR";
58 PROGMEM const char level4[] = "FATAL";
59
60 PROGMEM const char *const LEVEL[] =
61 {   level0, level1, level2, level3, level4};
62
63 static void OICLogString(LogLevel level, PROGMEM const char *tag, PROGMEM const char *logStr);
64 #ifdef ARDUINO_ARCH_AVR
65 //Mega2560 and other 8-bit AVR microcontrollers
66 #define GET_PROGMEM_BUFFER(buffer, addr) { strcpy_P(buffer, (char*)pgm_read_word(addr));}
67 #elif defined ARDUINO_ARCH_SAM
68 //Arduino Due and other 32-bit ARM micro-controllers
69 #define GET_PROGMEM_BUFFER(buffer, addr) { strcpy_P(buffer, (char*)pgm_read_dword(addr));}
70 #else
71 #define GET_PROGMEM_BUFFER(buffer, addr) { buffer[0] = '\0';}
72 #endif
73 #endif // __ANDROID__
74
75 #ifndef ARDUINO
76 #ifndef __TIZEN__
77 void OICLogConfig(oic_log_ctx_t *ctx)
78 {
79     logCtx = ctx;
80 }
81
82 void OICLogInit()
83 {
84
85 }
86
87 void OICLogShutdown()
88 {
89 #ifdef __linux__
90     if (logCtx && logCtx->destroy)
91     {
92         logCtx->destroy(logCtx);
93     }
94 #endif
95 }
96
97 /**
98  * Output a log string with the specified priority level.
99  * Only defined for Linux and Android
100  *
101  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
102  * @param tag    - Module name
103  * @param logStr - log string
104  */
105 void OICLog(LogLevel level, const char *tag, const char *logStr)
106 {
107     if (!logStr || !tag)
108     {
109         return;
110     }
111
112 #ifdef __ANDROID__
113
114 #ifdef ADB_SHELL
115     printf("%s: %s: %s\n", LEVEL[level], tag, logStr);
116 #else
117     __android_log_write(LEVEL[level], tag, logStr);
118 #endif
119
120 #elif defined __linux__
121     if (logCtx && logCtx->write_level)
122     {
123         logCtx->write_level(logCtx, LEVEL_XTABLE[level], logStr);
124
125     }
126     else
127     {
128         printf("%s: %s: %s\n", LEVEL[level], tag, logStr);
129     }
130 #endif
131 }
132
133 /**
134  * Output a variable argument list log string with the specified priority level.
135  * Only defined for Linux and Android
136  *
137  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
138  * @param tag    - Module name
139  * @param format - variadic log string
140  */
141 void OICLogv(LogLevel level, const char *tag, const char *format, ...)
142 {
143     if (!format || !tag)
144     {
145         return;
146     }
147     char buffer[MAX_LOG_V_BUFFER_SIZE];
148     memset(buffer, 0, sizeof buffer);
149     va_list args;
150     va_start(args, format);
151     vsnprintf(buffer, sizeof buffer - 1, format, args);
152     va_end(args);
153     OICLog(level, tag, buffer);
154 }
155
156 /**
157  * Output the contents of the specified buffer (in hex) with the specified priority level.
158  *
159  * @param level      - DEBUG, INFO, WARNING, ERROR, FATAL
160  * @param tag        - Module name
161  * @param buffer     - pointer to buffer of bytes
162  * @param bufferSize - max number of byte in buffer
163  */
164 void OICLogBuffer(LogLevel level, const char *tag, const uint8_t *buffer, uint16_t bufferSize)
165 {
166     if (!buffer || !tag || (bufferSize == 0))
167     {
168         return;
169     }
170
171     char lineBuffer[LINE_BUFFER_SIZE];
172     memset(lineBuffer, 0, sizeof lineBuffer);
173     int lineIndex = 0;
174     int i;
175     for (i = 0; i < bufferSize; i++)
176     {
177         // Format the buffer data into a line
178         sprintf(&lineBuffer[lineIndex++ * 3], "%02X ", buffer[i]);
179         // Output 16 values per line
180         if (((i + 1) % 16) == 0)
181         {
182             OICLog(level, tag, lineBuffer);
183             memset(lineBuffer, 0, sizeof lineBuffer);
184             lineIndex = 0;
185         }
186     }
187     // Output last values in the line, if any
188     if (bufferSize % 16)
189     {
190         OICLog(level, tag, lineBuffer);
191     }
192 }
193 #endif //__TIZEN__
194 #endif //ARDUINO
195 #ifdef ARDUINO
196 /**
197  * Initialize the serial logger for Arduino
198  * Only defined for Arduino
199  */
200 void OICLogInit()
201 {
202     Serial.begin(115200);
203 }
204
205 /**
206  * Output a log string with the specified priority level.
207  * Only defined for Arduino.  Only uses PROGMEM strings
208  * for the tag parameter
209  *
210  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
211  * @param tag    - Module name
212  * @param logStr - log string
213  */
214 /*
215  void OCLogString(LogLevel level, PROGMEM const char * tag, const char * logStr) {
216  if (!logStr || !tag) {
217  return;
218  }
219
220  char buffer[LINE_BUFFER_SIZE] = {0};
221  strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
222  Serial.print(buffer);
223
224  char c;
225  Serial.print(F(": "));
226  while ((c = pgm_read_byte(tag))) {
227  Serial.write(c);
228  tag++;
229  }
230  Serial.print(F(": "));
231
232  Serial.println(logStr);
233  }
234  */
235 /**
236  * Output the contents of the specified buffer (in hex) with the specified priority level.
237  *
238  * @param level      - DEBUG, INFO, WARNING, ERROR, FATAL
239  * @param tag        - Module name
240  * @param buffer     - pointer to buffer of bytes
241  * @param bufferSize - max number of byte in buffer
242  */
243
244 /*
245  void OCLogBuffer(LogLevel level, PROGMEM const char * tag, const uint8_t * buffer, uint16_t bufferSize) {
246  if (!buffer || !tag || (bufferSize == 0)) {
247  return;
248  }
249
250  char lineBuffer[LINE_BUFFER_SIZE] = {0};
251  uint8_t lineIndex = 0;
252  for (uint8_t i = 0; i < bufferSize; i++) {
253  // Format the buffer data into a line
254  sprintf(&lineBuffer[lineIndex++ * 3], "%02X ", buffer[i]);
255  // Output 16 values per line
256  if (((i+1)%16) == 0) {
257  OCLogString(level, tag, lineBuffer);
258  memset(lineBuffer, 0, sizeof lineBuffer);
259  lineIndex = 0;
260  }
261  }
262  // Output last values in the line, if any
263  if (bufferSize % 16) {
264  OCLogString(level, tag, lineBuffer);
265  }
266  }
267  */
268 /**
269  * Output a log string with the specified priority level.
270  * Only defined for Arduino.  Uses PROGMEM strings
271  *
272  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
273  * @param tag    - Module name
274  * @param logStr - log string
275  */
276 void OICLog(LogLevel level, PROGMEM const char *tag, const int16_t lineNum, PROGMEM const char *logStr)
277 {
278     if (!logStr || !tag)
279     {
280         return;
281     }
282     char buffer[LINE_BUFFER_SIZE] = {0};
283     strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
284     Serial.print(buffer);
285     char c;
286     Serial.print(F(": "));
287     while ((c = pgm_read_byte(tag)))
288     {
289         Serial.write(c);
290         tag++;
291     }
292     Serial.print(F(": "));
293     Serial.print(lineNum);
294     Serial.print(F(": "));
295     while ((c = pgm_read_byte(logStr)))
296     {
297         Serial.write(c);
298         logStr++;
299     }
300     Serial.println();
301 }
302
303 /**
304  * Output a variable argument list log string with the specified priority level.
305  * Only defined for Arduino as depicted below.
306  *
307  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
308  * @param tag    - Module name
309  * @param format - variadic log string
310  */
311 void OICLogv(LogLevel level, PROGMEM const char *tag, const int16_t lineNum, PROGMEM const char *format, ...)
312 {
313     char buffer[LINE_BUFFER_SIZE];
314     va_list ap;
315     va_start(ap, format);
316     strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
317     Serial.print(buffer);
318
319     char c;
320     Serial.print(F(": "));
321     while ((c = pgm_read_byte(tag))) {
322      Serial.write(c);
323      tag++;
324      }
325     Serial.print(F(": "));
326     Serial.print(lineNum);
327     Serial.print(F(": "));
328
329     vsnprintf_P(buffer, sizeof(buffer), format, ap);
330     for (char *p = &buffer[0]; *p; p++)
331     {
332         // emulate cooked mode for newlines
333         if (*p == '\n')
334         {
335             Serial.write('\r');
336         }
337         Serial.write(*p);
338     }
339     Serial.println();
340     va_end(ap);
341 }
342 /**
343  * Output a variable argument list log string with the specified priority level.
344  * Only defined for Arduino as depicted below.
345  *
346  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
347  * @param tag    - Module name
348  * @param format - variadic log string
349  */
350 void OICLogv(LogLevel level, const char *tag, const __FlashStringHelper *format, ...)
351 {
352     char buffer[LINE_BUFFER_SIZE];
353     va_list ap;
354     va_start(ap, format);
355     // strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
356     // Serial.print(buffer);
357
358     Serial.print(LEVEL[level]);
359     // char c;
360     Serial.print(F(": "));
361
362     /*while ((c = pgm_read_byte(tag))) {
363      Serial.write(c);
364      tag++;
365      }*/
366     Serial.print(tag);
367     Serial.print(F(": "));
368
369 #ifdef __AVR__
370     vsnprintf_P(buffer, sizeof(buffer), (const char *)format, ap); // progmem for AVR
371 #else
372     vsnprintf(buffer, sizeof(buffer), (const char *)format, ap); // for the rest of the world
373 #endif
374     for (char *p = &buffer[0]; *p; p++)
375     {
376         // emulate cooked mode for newlines
377         if (*p == '\n')
378         {
379             // Serial.write('\r');
380             Serial.print('\r');
381         }
382         //Serial.write(*p);
383         Serial.print(p);
384     }
385     Serial.println();
386     va_end(ap);
387 }
388
389 #endif //ARDUINO