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 Ashley Mills

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