blob: 334301a92faa986585435da4431cb1386cb76881 [file] [log] [blame]
#ifndef __MBTK_COAP_H__
#define __MBTK_COAP_H__
#include <stdint.h>
//#include "ps_in.h"
#include "ds_ASBuffer.h"
#include "mbtk_type.h"
#define COAP_HDR_SIZE 4
#define COAP_OPTION_HDR_BYTE 1
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
//typedef unsigned long uint32_t;
typedef unsigned long long uint64_t;
/*
enum ds_appsrv_mem_e_type { APPSRV_MEM };
void* operator new(unsigned int size, void* alloc, ds_appsrv_mem_e_type mem_type) throw();
void operator delete(void* obj, void* alloc, ds_appsrv_mem_e_type mem_type) throw();
*/
#define ps_ntohs(x) \
(((((uint16)(x) & 0x00FF) << 8) | (((uint16)(x) & 0xFF00) >> 8)))
#define endian_be16(x) ps_ntohs(x)
#define endian_load16(cast, from) ((cast)( \
(((uint16_t)((uint8_t*)(from))[0]) << 8) | \
(((uint16_t)((uint8_t*)(from))[1]) ) ))
#define endian_load32(cast, from) ((cast)( \
(((uint32_t)((uint8_t*)(from))[0]) << 24) | \
(((uint32_t)((uint8_t*)(from))[1]) << 16) | \
(((uint32_t)((uint8_t*)(from))[2]) << 8) | \
(((uint32_t)((uint8_t*)(from))[3]) ) ))
#define endian_load64(cast, from) ((cast)( \
(((uint64_t)((uint8_t*)(from))[0]) << 56) | \
(((uint64_t)((uint8_t*)(from))[1]) << 48) | \
(((uint64_t)((uint8_t*)(from))[2]) << 40) | \
(((uint64_t)((uint8_t*)(from))[3]) << 32) | \
(((uint64_t)((uint8_t*)(from))[4]) << 24) | \
(((uint64_t)((uint8_t*)(from))[5]) << 16) | \
(((uint64_t)((uint8_t*)(from))[6]) << 8) | \
(((uint64_t)((uint8_t*)(from))[7]) ) ))
#define endian_store16(to, num) \
do { uint16_t val = endian_be16(num); memcpy(to, &val, 2); } while(0)
// CoAP PDU format
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |Ver| T | TKL | Code | Message ID |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Token (if any, TKL bytes) ...
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Options (if any) ...
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |1 1 1 1 1 1 1 1| Payload (if any) ...
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
class CoapPDU
{
public:
/// CoAP message types. Note, values only work as enum.
enum Type
{
COAP_CONFIRMABLE=0x00,
COAP_NON_CONFIRMABLE=0x10,
COAP_ACKNOWLEDGEMENT=0x20,
COAP_RESET=0x30
};
// CoAP response codes.
enum Code
{
COAP_EMPTY=0x00,
COAP_GET,
COAP_POST,
COAP_PUT,
COAP_DELETE,
COAP_LASTMETHOD=0x1F,
COAP_CREATED=0x41,
COAP_DELETED,
COAP_VALID,
COAP_CHANGED,
COAP_CONTENT,
COAP_CONTINUE=0x5F,
COAP_BAD_REQUEST=0x80,
COAP_UNAUTHORIZED,
COAP_BAD_OPTION,
COAP_FORBIDDEN,
COAP_NOT_FOUND,
COAP_METHOD_NOT_ALLOWED,
COAP_NOT_ACCEPTABLE,
COAP_PRECONDITION_FAILED=0x8C,
COAP_REQUEST_ENTITY_TOO_LARGE=0x8D,
COAP_UNSUPPORTED_CONTENT_FORMAT=0x8F,
COAP_INTERNAL_SERVER_ERROR=0xA0,
COAP_NOT_IMPLEMENTED,
COAP_BAD_GATEWAY,
COAP_SERVICE_UNAVAILABLE,
COAP_GATEWAY_TIMEOUT,
COAP_PROXYING_NOT_SUPPORTED,
COAP_UNDEFINED_CODE=0xFF
};
/// CoAP option numbers.
enum Option
{
COAP_OPTION_IF_MATCH=1,
COAP_OPTION_URI_HOST=3,
COAP_OPTION_ETAG,
COAP_OPTION_IF_NONE_MATCH,
COAP_OPTION_OBSERVE,
COAP_OPTION_URI_PORT,
COAP_OPTION_LOCATION_PATH,
COAP_OPTION_URI_PATH=11,
COAP_OPTION_CONTENT_FORMAT,
COAP_OPTION_MAX_AGE=14,
COAP_OPTION_URI_QUERY,
COAP_OPTION_ACCEPT=17,
COAP_OPTION_LOCATION_QUERY=20,
COAP_OPTION_BLOCK2=23,
COAP_OPTION_BLOCK1=27,
COAP_OPTION_SIZE2,
COAP_OPTION_PROXY_URI=35,
COAP_OPTION_PROXY_SCHEME=39,
COAP_OPTION_SIZE1=60
};
/// CoAP content-formats.
enum ContentFormat
{
COAP_CONTENT_FORMAT_TEXT_PLAIN = 0,
COAP_CONTENT_FORMAT_APP_LINK = 40,
COAP_CONTENT_FORMAT_APP_XML,
COAP_CONTENT_FORMAT_APP_OCTET,
COAP_CONTENT_FORMAT_APP_EXI = 47,
COAP_CONTENT_FORMAT_APP_JSON = 50
};
/// Sequence of these is returned by CoapPDU::getOptions()
struct CoapOption
{
uint16_t optionDelta;
uint16_t optionNumber;
uint16_t optionValueLength;
int totalLength;
uint8_t *optionPointer;
uint8_t *optionValuePointer;
};
// construction and destruction
CoapPDU();
CoapPDU(uint8_t *buffer, int bufferLength, int pduLength);
~CoapPDU();
int reset();
int validate();
// version
int setVersion(uint8_t version);
uint8_t getVersion();
// message type
void setType(int type);
int getType();
// tokens
int setTokenLength(uint8_t tokenLength);
int getTokenLength();
uint8_t* getTokenPointer();
int setToken(uint8_t *token, uint8_t tokenLength);
// message code
void setCode(int code);
int getCode();
int httpStatusToCode(int httpStatus);
// message ID
int setMessageID(uint16_t messageID);
uint16_t getMessageID();
// options
int addOption(uint16_t optionNumber, uint16_t optionLength, uint8_t *optionValue);
// gets a list of all options
CoapOption* getOptions();
int getNumOptions();
// shorthand helpers
int setURI(char *uri);
int setURI(char *uri, int urilen);
int getURI(char *dst, int dstlen, int *outLen);
int addURIQuery(char *query);
// content format helper
int setContentFormat(int format);
// payload
uint8_t* mallocPayload(int bytes);
int setPayload(uint8_t *value, int len);
uint8_t* getPayloadPointer();
int getPayloadLength();
uint8_t* getPayloadCopy();
// pdu
int getPDULength();
uint8_t* getPDUPointer();
void setPDULength(int len);
void getOptionValueById(uint16_t optionNumber, uint16_t *optionValueLength,uint8_t *optionValuePointer);
const char *printHuman();
const char * printHex();
int hasOption(uint16_t optionNumber);
private:
// variables
uint8_t *_pdu;
int _pduLength;
int _constructedFromBuffer;
int _bufferLength;
uint8_t *_payloadPointer;
int _payloadLength;
int _numOptions;
uint16_t _maxAddedOptionNumber;
ASBuffer content;
// functions
void shiftPDUUp(int shiftOffset, int shiftAmount);
void shiftPDUDown(int startLocation, int shiftOffset, int shiftAmount);
uint8_t codeToValue(int c);
// option stuff
int findInsertionPosition(uint16_t optionNumber, uint16_t *prevOptionNumber);
int computeExtraBytes(uint16_t n);
int insertOption(int insertionPosition, uint16_t optionDelta, uint16_t optionValueLength, uint8_t *optionValue);
uint16_t getOptionDelta(uint8_t *option);
void setOptionDelta(int optionPosition, uint16_t optionDelta);
uint16_t getOptionValueLength(uint8_t *option);
};
/*
#define COAP_CODE_EMPTY 0x00
// method codes 0.01-0.31
#define COAP_CODE_GET 0x01
#define COAP_CODE_POST 0x02
#define COAP_CODE_PUT 0x03
#define COAP_CODE_DELETE 0x04
// Response codes 2.00 - 5.31
// 2.00 - 2.05
#define COAP_CODE_CREATED 0x41
#define COAP_CODE_DELETED 0x42
#define COAP_CODE_VALID 0x43
#define COAP_CODE_CHANGED 0x44
#define COAP_CODE_CONTENT 0x45
// 4.00 - 4.15
#define COAP_CODE_BAD_REQUEST 0x80
#define COAP_CODE_UNAUTHORIZED 0x81
#define COAP_CODE_BAD_OPTION 0x82
#define COAP_CODE_FORBIDDEN 0x83
#define COAP_CODE_NOT_FOUND 0x84
#define COAP_CODE_METHOD_NOT_ALLOWED 0x85
#define COAP_CODE_NOT_ACCEPTABLE 0x86
#define COAP_CODE_PRECONDITION_FAILED 0x8C
#define COAP_CODE_REQUEST_ENTITY_TOO_LARGE 0x8D
#define COAP_CODE_UNSUPPORTED_CONTENT_FORMAT 0x8F
// 5.00 - 5.05
#define COAP_CODE_INTERNAL_SERVER_ERROR 0xA0
#define COAP_CODE_NOT_IMPLEMENTED 0xA1
#define COAP_CODE_BAD_GATEWAY 0xA2
#define COAP_CODE_SERVICE_UNAVAILABLE 0xA3
#define COAP_CODE_GATEWAY_TIMEOUT 0xA4
#define COAP_CODE_PROXYING_NOT_SUPPORTED 0xA5
*/
#endif