diff --git a/ChangeLog b/ChangeLog index 0ded46d2..69691724 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2012-10-25 Olaf Bergmann + + * option.c (coap_opt_encode): new function for option encoding + with option jumps + 2012-03-23 Olaf Bergmann * examples/client.c (clear_obs): clear observation relationship after diff --git a/option.c b/option.c index 7600d8ca..28df97e2 100644 --- a/option.c +++ b/option.c @@ -15,6 +15,7 @@ #endif #include +#include #include "option.h" @@ -91,3 +92,119 @@ coap_check_option(coap_pdu_t *pdu, unsigned char type, return oi->option && oi->type == type ? oi->option : NULL; } + +size_t +coap_opt_encode(coap_opt_t *opt, size_t n, unsigned short delta, + unsigned char *val, unsigned short len) { + size_t l = 1; + size_t length = len; + unsigned int D = delta; + coap_opt_t *O = opt; + unsigned short N; + + /* option length must not exceed 1034 bytes */ + if (length > 1034) + return 0; + + /* check for option jumps */ + + if (delta < 15) { + /* no option jump required, proceed with normal encoding if + sufficient space is available */ + if (n < length + 1) + return 0; + + goto encode; + } + + if (delta < 30) { /* encode with short option jump */ + /* check if sufficient storage space is available */ + if (n < length + 2) + return 0; + + delta -= 15; + l++; /* need one additional byte for 0xf1 */ + *opt++ = 0xf1; + + goto encode; + } + + /* Values up to 2070 can be encoded with a single jump value + * (((0xff + 2) << 3) + 14) == 257 * 8 + 14 = 2070). For values + * below 2064, we use the last three bits from delta as the + * delta value and always encode N as (delta >> 3) - 2. Above + * 2064, N will be (delta >> 3) - 3, and + * delta = delta - ((N + 2) << 3). + */ + if (delta < 2071) { /* longer option jump */ + /* check if sufficient storage space is available */ + if (n < length + 2) + return 0; + + N = (delta >> 3) - 2; + + if (N > 255) { + N--; + delta = (delta + 8) & 0x0f; + } else + delta = (delta & 0x07); + + l += 2; /* need two additional bytes for 0xf2 nn */ + *opt++ = 0xf2; + *opt++ = N & 0xff; + + goto encode; + } + + /* longest option jump (delta <= 65535) */ + + /* check if sufficient storage space is available */ + if (n < length + 3) + return 0; + + N = (delta >> 3) - 258; + delta = (delta & 0x07); + + l += 3; /* need three additional bytes for 0xf3 nn nn */ + *opt++ = 0xf3; + *opt++ = (N >> 8) & 0xff; + *opt++ = N & 0xff; + + encode: + { + size_t k; + + printf("delta(%d) = ", D); + + for (k = 0; k < l-1; ++k) { + printf("%02x ", O[k]); + } + printf("%xx\n", delta & 0x0f); + } + return 0; + if (length < 15) { + *opt++ = (delta << 4) | (length & 0x0f); + n--; + } else { + *opt = ((delta & 0x0f) << 4) | 0x0f; + opt++; n--; + length -= 15; + + while (255 <= length && len < n) { + ++l; + *opt++ = 0xff; + length -= 255; + n--; + } + + if (len < n) { + ++l; + *opt++ = length & 0xff; + n--; + } else + return 0; + } + + memcpy(opt, val, len); + return l + len; +} diff --git a/option.h b/option.h index 55de98ff..e4e03201 100644 --- a/option.h +++ b/option.h @@ -38,6 +38,20 @@ typedef unsigned char coap_opt_t; ? (*(PCHAR(opt) + 1) + 15) \ : (*PCHAR(opt) & 0x0f))) +/** + * Encodes the option delta, length and value. + * + * @param opt start of the given option + * @param n maximum length of the option + * @param delta the option delta + * @param val the value to write + * @param length option length + * @return the number of bytes that are used to encode the option length + * or @c 0 in case of error. + */ +size_t coap_opt_encode(coap_opt_t *opt, size_t n, unsigned char delta, + unsigned char *val, unsigned short len); + #define COAP_OPT_SETLENGTH(opt,val) \ if ((val) < 15) \ *PCHAR(opt) = ((*PCHAR(opt) & 0xf0) | ((val) & 0x0f)); \ @@ -217,6 +231,23 @@ coap_opt_t *coap_check_option(coap_pdu_t *pdu, unsigned char type, coap_opt_iterator_t *oi); +/** + * Encodes option with given @p delta into @p opt. This function returns + * the number of bytes written to @p opt or @c 0 on error. This happens + * especially when @p opt does not provide sufficient space to store + * the option value, delta, and option jumps when required. + * + * @param opt The option buffer space where @p val is written + * @param n Maximum length of @p opt. + * @param delta The option delta. + * @param val The option value to copy into @p opt. + * @param len The actual length of @p val. + * @return The number of bytes that have been written to @p opt or + * @c 0 on error. The return value will always be less than @p n. + */ +size_t coap_opt_encode(coap_opt_t *opt, size_t n, unsigned short delta, + unsigned char *val, unsigned short len); + /** @} */ #endif /* _OPTION_H_ */