coap_debug.c
Go to the documentation of this file.
1 /**
2  * @file coap_debug.c
3  * @brief Data logging functions for debugging purpose (CoAP)
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL COAP_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/net.h"
34 #include "coap/coap_client.h"
35 //#include "coap/coap_server.h"
36 #include "coap/coap_debug.h"
37 #include "debug.h"
38 #include "error.h"
39 
40 //Check TCP/IP stack configuration
41 #if (COAP_CLIENT_SUPPORT == ENABLED || COAP_SERVER_SUPPORT == ENABLED)
42 
43 //CoAP message types
45 {
46  {COAP_TYPE_CON, "CON"},
47  {COAP_TYPE_NON, "NON"},
48  {COAP_TYPE_ACK, "ACK"},
49  {COAP_TYPE_RST, "RST"}
50 };
51 
52 //CoAP method and response codes
54 {
55  {COAP_CODE_EMPTY, "Empty"},
56  {COAP_CODE_GET, "GET"},
57  {COAP_CODE_POST, "POST"},
58  {COAP_CODE_PUT, "PUT"},
59  {COAP_CODE_DELETE, "DELETE"},
60  {COAP_CODE_FETCH, "FETCH"},
61  {COAP_CODE_PATCH, "PATCH"},
62  {COAP_CODE_IPATCH, "iPATCH"},
63  {COAP_CODE_CREATED, "Created"},
64  {COAP_CODE_DELETED, "Deleted"},
65  {COAP_CODE_VALID, "Valid"},
66  {COAP_CODE_CHANGED, "Changed"},
67  {COAP_CODE_CONTENT, "Content"},
68  {COAP_CODE_CONTINUE, "Continue"},
69  {COAP_CODE_BAD_REQUEST, "Bad Request"},
70  {COAP_CODE_UNAUTHOZED, "Unauthorized"},
71  {COAP_CODE_BAD_OPTION, "Bad Option"},
72  {COAP_CODE_FORBIDDEN, "Forbidden"},
73  {COAP_CODE_NOT_FOUND, "Not Found"},
74  {COAP_CODE_METHOD_NOT_ALLOWED, "Method Not Allowed"},
75  {COAP_CODE_NOT_ACCEPTABLE, "Not Acceptable"},
76  {COAP_CODE_REQUEST_ENTITY_INCOMPLETE, "Request Entity Incomplete"},
77  {COAP_CODE_CONFLICT, "Conflict"},
78  {COAP_CODE_PRECONDITION_FAILED, "Precondition Failed"},
79  {COAP_CODE_REQUEST_ENTITY_TO_LARGE, "Request Entity Too Large"},
80  {COAP_CODE_UNSUPPORTED_CONTENT_FORMAT, "Unsupported Content-Format"},
81  {COAP_CODE_UNPROCESSABLE_ENTITY, "Unprocessable Entity"},
82  {COAP_CODE_INTERNAL_SERVER, "Internal Server Error"},
83  {COAP_CODE_NOT_IMPLEMENTED, "Not Implemented"},
84  {COAP_CODE_BAD_GATEWAY, "Bad Gateway"},
85  {COAP_CODE_SERVICE_UNAVAILABLE, "Service Unavailable"},
86  {COAP_CODE_GATEWAY_TIMEOUT, "Gateway Timeout"},
87  {COAP_CODE_PROXYING_NOT_SUPPORTED, "Proxying Not Supported"},
88  {COAP_CODE_CSM, "CSM"},
89  {COAP_CODE_PING, "Ping"},
90  {COAP_CODE_PONG, "Pong"},
91  {COAP_CODE_RELEASE, "Release"},
92  {COAP_CODE_ABORT, "Abort"}
93 };
94 
95 //Observe option values
97 {
98  {COAP_OBSERVE_REGISTER, "Register"},
99  {COAP_OBSERVE_DEREGISTER, "Deregister"}
100 };
101 
102 //Content-Format option values
104 {
105  {COAP_CONTENT_FORMAT_TEXT_PLAIN, "text/plain"},
106  {COAP_CONTENT_FORMAT_APP_LINK_FORMAT, "application/link-format"},
107  {COAP_CONTENT_FORMAT_APP_XML, "application/xml"},
108  {COAP_CONTENT_FORMAT_APP_OCTET_STREAM, "application/octet-stream"},
109  {COAP_CONTENT_FORMAT_APP_EXI, "application/exi"},
110  {COAP_CONTENT_FORMAT_APP_JSON, "application/json"}
111 };
112 
113 
114 /**
115  * @brief Dump CoAP message for debugging purpose
116  * @param[in] message Pointer to the CoAP message
117  * @param[in] length Length of the message, in bytes
118  * @return Error code
119  **/
120 
121 error_t coapDumpMessage(const void *message, size_t length)
122 {
123 #if (COAP_TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
124  error_t error;
125  size_t n;
126  const uint8_t *p;
127 
128  //Point to the first byte of the CoAP message
129  p = message;
130 
131  //Dump message header
132  error = coapDumpMessageHeader(p, length, &n);
133  //Any error to report?
134  if(error)
135  return error;
136 
137  //Point to the first option of the message
138  p += n;
139  //Number of bytes left to process
140  length -= n;
141 
142  //Parse the list of options
143  error = coapDumpOptions(p, length, &n);
144  //Any error to report?
145  if(error)
146  return error;
147 
148  //Point to the payload
149  p += n;
150  //Number of bytes left to process
151  length -= n;
152 
153  //The payload is optional
154  if(length > 0)
155  {
156  //The payload is prefixed by a fixed, one-byte payload marker
157  p++;
158  //Retrieve the length of the payload
159  length--;
160 
161  //Dump payload
162  TRACE_DEBUG(" Payload (%" PRIuSIZE " bytes)\r\n", length);
163  TRACE_DEBUG_ARRAY(" ", p, length);
164  //TRACE_DEBUG(" %s\r\n", p);
165  }
166 #endif
167 
168  //Successful processing
169  return NO_ERROR;
170 }
171 
172 
173 /**
174  * @brief Dump CoAP message header
175  * @param[in] p Input stream where to read the CoAP message header
176  * @param[in] length Number of bytes available in the input stream
177  * @param[out] consumed Total number of bytes that have been consumed
178  * @return Error code
179  **/
180 
181 error_t coapDumpMessageHeader(const uint8_t *p, size_t length, size_t *consumed)
182 {
183  CoapMessageHeader *header;
184 
185  //Malformed CoAP message?
186  if(length < sizeof(CoapMessageHeader))
187  return ERROR_INVALID_MESSAGE;
188 
189  //Point to the CoAP message header
190  header = (CoapMessageHeader *) p;
191 
192  //Dump CoAP version number
193  TRACE_DEBUG(" Version = %" PRIu8 "\r\n", header->version);
194 
195  //Dump message type
196  TRACE_DEBUG(" Type = %" PRIu8 " (%s)\r\n", header->type,
198 
199  //Dump token length
200  TRACE_DEBUG(" Token Length = %" PRIu8 "\r\n", header->tokenLen);
201 
202  //Dump method or response code
203  TRACE_DEBUG(" Code = %" PRIu8 ".%02" PRIu8 " (%s)\r\n",
204  header->code / 32, header->code & 31,
206 
207  //Dump message identifier
208  TRACE_DEBUG(" Message ID = 0x%04" PRIX16 "\r\n", ntohs(header->mid));
209 
210  //Malformed CoAP message?
211  if(length < (sizeof(CoapMessageHeader) + header->tokenLen))
212  return ERROR_INVALID_LENGTH;
213 
214  //Dump token
215  TRACE_DEBUG_ARRAY(" Token = ", header->token, header->tokenLen);
216 
217  //Total number of bytes that have been consumed
218  *consumed = sizeof(CoapMessageHeader) + header->tokenLen;
219 
220  //Successful processing
221  return NO_ERROR;
222 }
223 
224 
225 /**
226  * @brief Dump the list of CoAP options
227  * @param[in] p Input stream where to read the CoAP options
228  * @param[in] length Number of bytes available in the input stream
229  * @param[out] consumed Total number of bytes that have been consumed
230  * @return Error code
231  **/
232 
233 error_t coapDumpOptions(const uint8_t *p, size_t length, size_t *consumed)
234 {
235  error_t error;
236  size_t n;
237  CoapOption option;
238 
239  //Initialize status code
240  error = NO_ERROR;
241 
242  //Total number of bytes that have been consumed
243  *consumed = 0;
244 
245  //For the first option in a message, a preceding option instance with
246  //Option Number zero is assumed
247  option.number = 0;
248 
249  //Loop through CoAP options
250  while(length > 0)
251  {
252  //Payload marker found?
253  if(*p == COAP_PAYLOAD_MARKER)
254  break;
255 
256  //Parse current option
257  error = coapParseOption(p, length, option.number, &option, &n);
258  //Any error to report?
259  if(error)
260  break;
261 
262  //Dump current option
263  error = coapDumpOption(&option);
264  //Any error to report?
265  if(error)
266  break;
267 
268  //Total number of bytes that have been consumed
269  *consumed += n;
270 
271  //Jump to the next option
272  p += n;
273  length -= n;
274  }
275 
276  //Return status code
277  return error;
278 }
279 
280 
281 /**
282  * @brief Dump CoAP option
283  * @param[out] option CoAP option content
284  * @return Error code
285  **/
286 
288 {
289 #if (COAP_TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
290  size_t i;
291  uint32_t value;
292  const char_t *name;
293  const CoapOptionParameters *optionParams;
294 
295  //Retrieve option parameters
296  optionParams = coapGetOptionParameters(option->number);
297 
298  //Check whether the specified option is supported
299  if(optionParams != NULL)
300  {
301  //Dump option number
302  TRACE_DEBUG(" Option %" PRIu16 " (%s)\r\n",
303  option->number, optionParams->name);
304 
305  //Check option type
306  if(optionParams->format == COAP_OPT_FORMAT_UINT)
307  {
308  //Initialize integer value
309  value = 0;
310 
311  //Convert the integer from network byte order
312  for(i = 0; i < option->length; i++)
313  {
314  value = (value << 8) + option->value[i];
315  }
316 
317  //Check option number
318  if(option->number == COAP_OPT_OBSERVE)
319  {
320  //Convert the Observe option to string representation
323 
324  //Dump the value of the option
325  if(strcmp(name, "Unknown"))
326  {
327  TRACE_DEBUG(" %" PRIu32 " (%s)\r\n", value, name);
328  }
329  else
330  {
331  TRACE_DEBUG(" %" PRIu32 "\r\n", value);
332  }
333  }
334  else if(option->number == COAP_OPT_CONTENT_FORMAT)
335  {
336  //Convert the Content-Format option to string representation
339 
340  //Dump the value of the option
341  TRACE_DEBUG(" %" PRIu32 " (%s)\r\n", value, name);
342  }
343  else if(option->number == COAP_OPT_BLOCK1 ||
344  option->number == COAP_OPT_BLOCK2)
345  {
346  //Dump the value of the Block option
347  TRACE_DEBUG(" %" PRIu32 "/%" PRIu32 "/%" PRIu32 "\r\n",
349  16 << COAP_GET_BLOCK_SZX(value));
350  }
351  else
352  {
353  //Dump the value of the option
354  TRACE_DEBUG(" %" PRIu32 "\r\n", value);
355  }
356  }
357  else if(optionParams->format == COAP_OPT_FORMAT_STRING)
358  {
359  //Append prefix
360  TRACE_DEBUG(" \"");
361 
362  //Dump string value
363  for(i = 0; i < option->length; i++)
364  TRACE_DEBUG("%c", option->value[i]);
365 
366  //Add a line feed
367  TRACE_DEBUG("\"\r\n");
368  }
369  else
370  {
371  //Dump option value
372  TRACE_DEBUG_ARRAY(" ", option->value, option->length);
373  }
374  }
375  else
376  {
377  //Dump option number
378  TRACE_DEBUG(" Option %" PRIu16 " (%" PRIu16 " bytes)\r\n",
379  option->number, option->length);
380 
381  //Dump option value
382  TRACE_DEBUG_ARRAY(" ", option->value, option->length);
383  }
384 #endif
385 
386  //Successful processing
387  return NO_ERROR;
388 }
389 
390 
391 /**
392  * @brief Convert a parameter to string representation
393  * @param[in] value Parameter value
394  * @param[in] paramList List of acceptable parameters
395  * @param[in] paramListLen Number of entries in the list
396  * @return NULL-terminated string describing the parameter
397  **/
398 
400  const CoapParamDesc *paramList, size_t paramListLen)
401 {
402  uint_t i;
403 
404  //Default name for unknown values
405  static const char_t defaultName[] = "Unknown";
406 
407  //Loop through the list of acceptable parameters
408  for(i = 0; i < paramListLen; i++)
409  {
410  if(paramList[i].value == value)
411  return paramList[i].name;
412  }
413 
414  //Unknown value
415  return defaultName;
416 }
417 
418 #endif
const CoapParamDesc coapTypeList[]
Definition: coap_debug.c:44
error_t coapDumpMessage(const void *message, size_t length)
Dump CoAP message for debugging purpose.
Definition: coap_debug.c:121
char char_t
Definition: compiler_port.h:41
const char_t * name
Definition: coap_debug.h:49
TCP/IP stack core.
CoAP value/string binding.
Definition: coap_debug.h:46
Reset message.
Definition: coap_common.h:95
Debugging facilities.
uint8_t p
Definition: ndp.h:295
const CoapParamDesc coapCodeList[]
Definition: coap_debug.c:53
uint8_t message[]
Definition: chap.h:150
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:99
#define COAP_GET_BLOCK_M(value)
Definition: coap_option.h:69
#define COAP_GET_BLOCK_NUM(value)
Definition: coap_option.h:67
#define arraysize(a)
Definition: os_port.h:68
const char_t * name
Option name.
Definition: coap_option.h:193
const CoapParamDesc coapContentFormatList[]
Definition: coap_debug.c:103
Error codes description.
uint16_t number
Definition: coap_option.h:176
#define ntohs(value)
Definition: cpu_endian.h:396
char_t name[]
Confirmable message.
Definition: coap_common.h:92
size_t length
Definition: coap_option.h:177
error_t coapDumpOption(const CoapOption *option)
Dump CoAP option.
Definition: coap_debug.c:287
const CoapOptionParameters * coapGetOptionParameters(uint16_t optionNum)
Retrieve parameters for a given option number.
Definition: coap_option.c:948
Non-negative integer.
Definition: coap_option.h:121
#define COAP_PAYLOAD_MARKER
Definition: coap_common.h:51
Success.
Definition: error.h:42
const uint8_t * value
Definition: coap_option.h:178
error_t
Error codes.
Definition: error.h:40
unsigned int uint_t
Definition: compiler_port.h:43
#define PRIuSIZE
Definition: compiler_port.h:72
uint8_t value[]
Definition: dtls_misc.h:141
Acknowledgment message.
Definition: coap_common.h:94
const CoapParamDesc coapObserveList[]
Definition: coap_debug.c:96
CoAP option.
Definition: coap_option.h:173
CoAP client.
error_t coapParseOption(const uint8_t *p, size_t length, uint16_t prevOptionNum, CoapOption *option, size_t *consumed)
Parse CoAP option.
Definition: coap_option.c:131
CoapOptionFormat format
Option format.
Definition: coap_option.h:194
Data logging functions for debugging purpose (CoAP)
error_t coapDumpMessageHeader(const uint8_t *p, size_t length, size_t *consumed)
Dump CoAP message header.
Definition: coap_debug.c:181
error_t coapDumpOptions(const uint8_t *p, size_t length, size_t *consumed)
Dump the list of CoAP options.
Definition: coap_debug.c:233
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
#define COAP_GET_BLOCK_SZX(value)
Definition: coap_option.h:71
__start_packed struct @110 CoapMessageHeader
CoAP message format.
const char_t * coapGetParamName(uint_t value, const CoapParamDesc *paramList, size_t paramListLen)
Convert a parameter to string representation.
Definition: coap_debug.c:399
UTF-8 string.
Definition: coap_option.h:122
Non-confirmable message.
Definition: coap_common.h:93
CoAP option parameters.
Definition: coap_option.h:186
#define TRACE_DEBUG(...)
Definition: debug.h:98