This is CoAP library with a focus on simplicity. It offers minimal CoAP PDU construction and decoding to and from byte buffers.
Fork of cantcoap by
Diff: cantcoap.cpp
- Revision:
- 1:5eec2844ad47
- Parent:
- 0:3d62a105fd34
- Child:
- 2:1544f4758e0a
--- a/cantcoap.cpp Tue Oct 08 14:36:01 2013 +0000 +++ b/cantcoap.cpp Thu Jan 30 14:07:56 2014 +0000 @@ -36,12 +36,26 @@ #include <stdlib.h> #include <stdint.h> #include <string.h> +#include <inet.h> #include "cantcoap.h" -#ifndef MBED -#include "arpa/inet.h" -#include "netdb.h" + +// for debugging output you need https://mbed.org/users/donatien/code/DebugLib/ +#define __DEBUG__ 3 // INFO +#ifndef __MODULE__ + #define __MODULE__ "cantcoap.cpp" +#endif +#include "dbg.h" +// some extra debug stuff +#if __DEBUG__ > 0 + #define INFOX(...) do { fprintf(stderr,__VA_ARGS__); } while(0) + #define INFOLX(...) do { fprintf(stderr,"[INFO] %s:%d ",__MODULE__,__LINE__); fprintf(stderr,__VA_ARGS__); } while(0) + #define DBGLX(...) do { fprintf(stderr,"[DBG] %s:%d ",__MODULE__,__LINE__); fprintf(stderr,__VA_ARGS__); } while(0) + #define DBG_PDU() do { printBin(); } while(0) #else -#include "bsd_socket.h" + #define INFOX(...) do{} while(0) + #define INFOLX(...) do{} while(0) + #define DBGLX(...) do{} while(0) + #define DBG_PDU() do{} while(0) #endif @@ -108,11 +122,25 @@ * \sa CoapPDU::CoapPDU(), CoapPDU::CoapPDU(uint8_t *buffer, int bufferLength, int pduLength) */ CoapPDU::CoapPDU(uint8_t *pdu, int pduLength) { + int bufferLength = pduLength; + // sanity + if(pduLength<4&&pduLength!=0) { + DBG("PDU cannot have a length less than 4"); + } + // pdu _pdu = pdu; - _bufferLength = pduLength; - _pduLength = pduLength; - + _bufferLength = bufferLength; + if(pduLength==0) { + // this is actually a fresh pdu, header always exists + _pduLength = 4; + // make sure header is zeroed + _pdu[0] = 0x00; _pdu[1] = 0x00; _pdu[2] = 0x00; _pdu[3] = 0x00; + setVersion(1); + } else { + _pduLength = pduLength; + } + _constructedFromBuffer = 1; // options @@ -419,6 +447,13 @@ _pduLength = len; } +/// Shorthand function for setting a resource URI. +/** + * Calls CoapPDU::setURI(uri,strlen(uri). + */ +int CoapPDU::setURI(char *uri) { + return setURI(uri,strlen(uri)); +} /// Shorthand function for setting a resource URI. /** @@ -513,10 +548,21 @@ free(uriBuf); return 0; } +/// Shorthand for adding a URI QUERY to the option list. +/** + * Adds a new option to the CoAP PDU that encodes a URI_QUERY. + * + * \param query The uri query to encode. + * \return 0 on success, 1 on failure. + */ +int CoapPDU::addURIQuery(char *query) { + return addOption(COAP_OPTION_URI_QUERY,strlen(query),(uint8_t*)query); +} /// Concatenates any URI_PATH elements into a single string. /** * Parses the PDU options and extracts all URI_PATH elements, concatenating them into a single string with slash separators. + * The produced string will be null terminated. * * \param dst Buffer into which to copy the concatenated path elements. * \param dstlen Length of buffer. @@ -785,6 +831,71 @@ CoapPDU::Code CoapPDU::getCode() { return (CoapPDU::Code)_pdu[1]; } + + +/// Converts a http status code as an integer, to a CoAP code. +/** + * \param httpStatus the HTTP status code as an integer (e.g 200) + * \return The correct corresponding CoapPDU::Code on success, + * CoapPDU::COAP_UNDEFINED_CODE on failure. + */ +CoapPDU::Code CoapPDU::httpStatusToCode(int httpStatus) { + switch(httpStatus) { + case 1: + return CoapPDU::COAP_GET; + case 2: + return CoapPDU::COAP_POST; + case 3: + return CoapPDU::COAP_PUT; + case 4: + return CoapPDU::COAP_DELETE; + case 201: + return CoapPDU::COAP_CREATED; + case 202: + return CoapPDU::COAP_DELETED; + case 203: + return CoapPDU::COAP_VALID; + case 204: + return CoapPDU::COAP_CHANGED; + case 205: + return CoapPDU::COAP_CONTENT; + case 400: + return CoapPDU::COAP_BAD_REQUEST; + case 401: + return CoapPDU::COAP_UNAUTHORIZED; + case 402: + return CoapPDU::COAP_BAD_OPTION; + case 403: + return CoapPDU::COAP_FORBIDDEN; + case 404: + return CoapPDU::COAP_NOT_FOUND; + case 405: + return CoapPDU::COAP_METHOD_NOT_ALLOWED; + case 406: + return CoapPDU::COAP_NOT_ACCEPTABLE; + case 412: + return CoapPDU::COAP_PRECONDITION_FAILED; + case 413: + return CoapPDU::COAP_REQUEST_ENTITY_TOO_LARGE; + case 415: + return CoapPDU::COAP_UNSUPPORTED_CONTENT_FORMAT; + case 500: + return CoapPDU::COAP_INTERNAL_SERVER_ERROR; + case 501: + return CoapPDU::COAP_NOT_IMPLEMENTED; + case 502: + return CoapPDU::COAP_BAD_GATEWAY; + case 503: + return CoapPDU::COAP_SERVICE_UNAVAILABLE; + case 504: + return CoapPDU::COAP_GATEWAY_TIMEOUT; + case 505: + return CoapPDU::COAP_PROXYING_NOT_SUPPORTED; + default: + return CoapPDU::COAP_UNDEFINED_CODE; + } +} + /// Set messageID to the supplied value. /** * \param messageID A 16bit message id. @@ -1452,200 +1563,205 @@ /// Prints the PDU in human-readable format. void CoapPDU::printHuman() { - INFO("__________________"); + INFOX("__________________\r\n"); if(_constructedFromBuffer) { - INFO("PDU was constructed from buffer of %d bytes",_bufferLength); + INFOX("PDU was constructed from buffer of %d bytes\r\n",_bufferLength); } - INFO("PDU is %d bytes long",_pduLength); - INFO("CoAP Version: %d",getVersion()); + INFOX("PDU is %d bytes long\r\n",_pduLength); + INFOX("CoAP Version: %d\r\n",getVersion()); INFOX("Message Type: "); switch(getType()) { case COAP_CONFIRMABLE: - INFO("Confirmable"); + INFOX("Confirmable\r\n"); break; case COAP_NON_CONFIRMABLE: - INFO("Non-Confirmable"); + INFOX("Non-Confirmable\r\n"); break; case COAP_ACKNOWLEDGEMENT: - INFO("Acknowledgement"); + INFOX("Acknowledgement\r\n"); break; case COAP_RESET: - INFO("Reset"); + INFOX("Reset\r\n"); break; } - INFO("Token length: %d",getTokenLength()); + INFOX("Token length: %d\r\n",getTokenLength()); INFOX("Code: "); switch(getCode()) { case COAP_EMPTY: - INFO("0.00 Empty"); + INFOX("0.00 Empty"); break; case COAP_GET: - INFO("0.01 GET"); + INFOX("0.01 GET"); break; case COAP_POST: - INFO("0.02 POST"); + INFOX("0.02 POST"); break; case COAP_PUT: - INFO("0.03 PUT"); + INFOX("0.03 PUT"); break; case COAP_DELETE: - INFO("0.04 DELETE"); + INFOX("0.04 DELETE"); break; case COAP_CREATED: - INFO("2.01 Created"); + INFOX("2.01 Created"); break; case COAP_DELETED: - INFO("2.02 Deleted"); + INFOX("2.02 Deleted"); break; case COAP_VALID: - INFO("2.03 Valid"); + INFOX("2.03 Valid"); break; case COAP_CHANGED: - INFO("2.04 Changed"); + INFOX("2.04 Changed"); break; case COAP_CONTENT: - INFO("2.05 Content"); + INFOX("2.05 Content"); break; case COAP_BAD_REQUEST: - INFO("4.00 Bad Request"); + INFOX("4.00 Bad Request"); break; case COAP_UNAUTHORIZED: - INFO("4.01 Unauthorized"); + INFOX("4.01 Unauthorized"); break; case COAP_BAD_OPTION: - INFO("4.02 Bad Option"); + INFOX("4.02 Bad Option"); break; case COAP_FORBIDDEN: - INFO("4.03 Forbidden"); + INFOX("4.03 Forbidden"); break; case COAP_NOT_FOUND: - INFO("4.04 Not Found"); + INFOX("4.04 Not Found"); break; case COAP_METHOD_NOT_ALLOWED: - INFO("4.05 Method Not Allowed"); + INFOX("4.05 Method Not Allowed"); break; case COAP_NOT_ACCEPTABLE: - INFO("4.06 Not Acceptable"); + INFOX("4.06 Not Acceptable"); break; case COAP_PRECONDITION_FAILED: - INFO("4.12 Precondition Failed"); + INFOX("4.12 Precondition Failed"); break; case COAP_REQUEST_ENTITY_TOO_LARGE: - INFO("4.13 Request Entity Too Large"); + INFOX("4.13 Request Entity Too Large"); break; case COAP_UNSUPPORTED_CONTENT_FORMAT: - INFO("4.15 Unsupported Content-Format"); + INFOX("4.15 Unsupported Content-Format"); break; case COAP_INTERNAL_SERVER_ERROR: - INFO("5.00 Internal Server Error"); + INFOX("5.00 Internal Server Error"); break; case COAP_NOT_IMPLEMENTED: - INFO("5.01 Not Implemented"); + INFOX("5.01 Not Implemented"); break; case COAP_BAD_GATEWAY: - INFO("5.02 Bad Gateway"); + INFOX("5.02 Bad Gateway"); break; case COAP_SERVICE_UNAVAILABLE: - INFO("5.03 Service Unavailable"); + INFOX("5.03 Service Unavailable"); break; case COAP_GATEWAY_TIMEOUT: - INFO("5.04 Gateway Timeout"); + INFOX("5.04 Gateway Timeout"); break; case COAP_PROXYING_NOT_SUPPORTED: - INFO("5.05 Proxying Not Supported"); + INFOX("5.05 Proxying Not Supported"); + break; + case COAP_UNDEFINED_CODE: + INFOX("Undefined Code"); break; } + INFOX("\r\n"); // print message ID - INFO("Message ID: %u",getMessageID()); + INFOX("Message ID: %u\r\n",getMessageID()); // print token value int tokenLength = getTokenLength(); uint8_t *tokenPointer = getPDUPointer()+COAP_HDR_SIZE; if(tokenLength==0) { - INFO("No token."); + INFOX("No token.\r\n"); } else { - INFO("Token of %d bytes.",tokenLength); + INFOX("Token of %d bytes.\r\n",tokenLength); INFOX(" Value: 0x"); for(int j=0; j<tokenLength; j++) { INFOX("%.2x",tokenPointer[j]); } - INFO(" "); + INFOX("\r\n"); } // print options CoapPDU::CoapOption* options = getOptions(); - INFO("%d options:",_numOptions); + INFOX("%d options:\r\n",_numOptions); for(int i=0; i<_numOptions; i++) { - INFO("OPTION (%d/%d)",i,_numOptions); - INFO(" Option number (delta): %hu (%hu)",options[i].optionNumber,options[i].optionDelta); + INFOX("OPTION (%d/%d)\r\n",i,_numOptions); + INFOX(" Option number (delta): %hu (%hu)\r\n",options[i].optionNumber,options[i].optionDelta); INFOX(" Name: "); switch(options[i].optionNumber) { case COAP_OPTION_IF_MATCH: - INFO("IF_MATCH"); + INFOX("IF_MATCH"); break; case COAP_OPTION_URI_HOST: - INFO("URI_HOST"); + INFOX("URI_HOST"); break; case COAP_OPTION_ETAG: - INFO("ETAG"); + INFOX("ETAG"); break; case COAP_OPTION_IF_NONE_MATCH: - INFO("IF_NONE_MATCH"); + INFOX("IF_NONE_MATCH"); break; case COAP_OPTION_OBSERVE: - INFO("OBSERVE"); + INFOX("OBSERVE"); break; case COAP_OPTION_URI_PORT: - INFO("URI_PORT"); + INFOX("URI_PORT"); break; case COAP_OPTION_LOCATION_PATH: - INFO("LOCATION_PATH"); + INFOX("LOCATION_PATH"); break; case COAP_OPTION_URI_PATH: - INFO("URI_PATH"); + INFOX("URI_PATH"); break; case COAP_OPTION_CONTENT_FORMAT: - INFO("CONTENT_FORMAT"); + INFOX("CONTENT_FORMAT"); break; case COAP_OPTION_MAX_AGE: - INFO("MAX_AGE"); + INFOX("MAX_AGE"); break; case COAP_OPTION_URI_QUERY: - INFO("URI_QUERY"); + INFOX("URI_QUERY"); break; case COAP_OPTION_ACCEPT: - INFO("ACCEPT"); + INFOX("ACCEPT"); break; case COAP_OPTION_LOCATION_QUERY: - INFO("LOCATION_QUERY"); + INFOX("LOCATION_QUERY"); break; case COAP_OPTION_PROXY_URI: - INFO("PROXY_URI"); + INFOX("PROXY_URI"); break; case COAP_OPTION_PROXY_SCHEME: - INFO("PROXY_SCHEME"); + INFOX("PROXY_SCHEME"); break; case COAP_OPTION_BLOCK1: - INFO("BLOCK1"); + INFOX("BLOCK1"); break; case COAP_OPTION_BLOCK2: - INFO("BLOCK2"); + INFOX("BLOCK2"); break; case COAP_OPTION_SIZE1: - INFO("SIZE1"); + INFOX("SIZE1"); break; case COAP_OPTION_SIZE2: - INFO("SIZE2"); + INFOX("SIZE2"); break; default: - INFO("Unknown option"); + INFOX("Unknown option"); break; } - INFO(" Value length: %u",options[i].optionValueLength); + INFOX("\r\n"); + INFOX(" Value length: %u\r\n",options[i].optionValueLength); INFOX(" Value: \""); for(int j=0; j<options[i].optionValueLength; j++) { char c = options[i].optionValuePointer[j]; @@ -1655,14 +1771,14 @@ INFOX("\\%.2d",c); } } - INFO("\""); + INFOX("\"\r\n"); } // print payload if(_payloadLength==0) { - INFO("No payload."); + INFOX("No payload.\r\n"); } else { - INFO("Payload of %d bytes",_payloadLength); + INFOX("Payload of %d bytes\r\n",_payloadLength); INFOX(" Value: \""); for(int j=0; j<_payloadLength; j++) { char c = _payloadPointer[j]; @@ -1672,9 +1788,9 @@ INFOX("\\%.2x",c); } } - INFO("\""); + INFO("\"\r\n"); } - INFO("__________________"); + INFOX("__________________\r\n"); } /// Prints the PDU as a c array (useful for debugging or hardcoding PDUs) @@ -1795,4 +1911,4 @@ /// Dumps the PDU as a byte sequence to stdout. void CoapPDU::print() { fwrite(_pdu,1,_pduLength,stdout); -} +} \ No newline at end of file