diff --git a/option.h b/option.h index 57088a01..95772119 100644 --- a/option.h +++ b/option.h @@ -18,59 +18,38 @@ #include "bits.h" #include "pdu.h" -#ifdef WORDS_BIGENDIAN -typedef union { - struct { /* short form, to be used when length < 15 */ - unsigned int delta:4; /* option type (expressed as delta) */ - unsigned int length:4; /* number of option bytes (15 indicates extended form) */ - /* 0--14 bytes options */ - } sval; - struct { /* extended form, to be used when lengt==15 */ - unsigned int delta:4; /* option type (expressed as delta) */ - unsigned int flag:4; /* must be 15! */ - unsigned int length:8; /* length - 15 */ - /* 15--270 bytes options */ - } lval; -} coap_opt_t; -#else -typedef union { - struct { /* short form, to be used when length < 15 */ - unsigned int length:4; /* number of option bytes (15 indicates extended form) */ - unsigned int delta:4; /* option type (expressed as delta) */ - /* 0--14 bytes options */ - } sval; - struct { /* extended form, to be used when lengt==15 */ - unsigned int flag:4; /* must be 15! */ - unsigned int delta:4; /* option type (expressed as delta) */ - unsigned int length:8; /* length - 15 */ - /* 15--270 bytes options */ - } lval; -} coap_opt_t; -#endif +/** + * Use byte-oriented access methods here because sliding a complex + * struct coap_opt_t over the data buffer may cause bus error on + * certain platforms. + */ +typedef unsigned char coap_opt_t; +#define PCHAR(p) ((coap_opt_t *)(p)) -#define COAP_OPT_SVAL(opt) ((coap_opt_t *)(opt))->sval -#define COAP_OPT_LVAL(opt) ((coap_opt_t *)(opt))->lval -#define COAP_OPT_ISEXTENDED(opt) (COAP_OPT_LVAL(opt).flag == 15) +#define COAP_OPT_ISEXTENDED(opt) ((*PCHAR(opt) & 0x0f) == 0x0f) /* these macros should be used to access fields from coap_opt_t */ -#define COAP_OPT_DELTA(opt) COAP_OPT_SVAL(opt).delta -#define COAP_OPT_SETDELTA(opt,val) COAP_OPT_SVAL(opt).delta = (val) +#define COAP_OPT_DELTA(opt) (*PCHAR(opt) >> 4) +#define COAP_OPT_SETDELTA(opt,val) \ + (*PCHAR(opt) = (*PCHAR(opt) & 0x0f) | ((val) << 4)) -#define COAP_OPT_LENGTH(opt) \ - ( COAP_OPT_ISEXTENDED(opt) ? COAP_OPT_LVAL(opt).length + 15 : COAP_OPT_SVAL(opt).length ) +#define COAP_OPT_LENGTH(opt) \ + ( COAP_OPT_ISEXTENDED(opt) \ + ? (*(PCHAR(opt) + 1) + 15) \ + : (*PCHAR(opt) & 0x0f)) -#define COAP_OPT_SETLENGTH(opt,val) \ - if ( (val) < 15 ) \ - COAP_OPT_SVAL(opt).length = (val) & 0x0f; \ +#define COAP_OPT_SETLENGTH(opt,val) \ + if ( ((val) & 0xff) < 15 ) \ + *PCHAR(opt) = ((*PCHAR(opt) & 0xf0) | ((val) & 0x0f)); \ else { \ - COAP_OPT_LVAL(opt).length = ((val) - 15) & 0xff; \ - COAP_OPT_LVAL(opt).flag = 15; \ + *PCHAR(opt) |= 0x0f; \ + *(PCHAR(opt) + 1) = ((val) & 0xff) - 15; \ } -#define COAP_OPT_VALUE(opt) \ - ( (unsigned char *)(opt) + ( COAP_OPT_ISEXTENDED(opt) ? 2 : 1 ) ) +#define COAP_OPT_VALUE(opt) \ + (PCHAR(opt) + (COAP_OPT_ISEXTENDED(opt) ? 2 : 1)) -/* do not forget to adjust this when coap_opt_t is changed! */ +/* Do not forget to adjust this when coap_opt_t is changed! */ #define COAP_OPT_SIZE(opt) ( COAP_OPT_LENGTH(opt) + ( COAP_OPT_ISEXTENDED(opt) ? 2: 1 ) ) /**