handling of long option lists

This commit is contained in:
Olaf Bergmann committed 2012-03-20 18:47:46 +01:00
1 parent 6f0a4550c7
commit 582e59f107
6 files changed
+129 -46

No files matched your search

+18
View File
@@ -1,3 +1,21 @@
2012-03-19 Olaf Bergmann <bergmann@tzi.org>
* pdu.c (coap_add_option): allow more than 15 options.
2012-03-15 Olaf Bergmann <bergmann@tzi.org>
* examples/client.c (cmdline_uri): split path and query here to
make it easier to include these options in subsequent requests for
block transfer.
2012-03-14 Olaf Bergmann <bergmann@tzi.org>
* examples/etsi_iot_01.c: Support for POST, PUT, DELETE on /test
2012-03-13 Olaf Bergmann <bergmann@tzi.org>
* encode.c (coap_encode_var_bytes): more efficient coding for 0
2012-03-11 Olaf Bergmann <bergmann@tzi.org>
* examples/etsi_iot_01.c: Test cases for 1st ETSI CoAP Plugtest,
+31 -3
View File
@@ -373,6 +373,25 @@ coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu,
*id = ((h[0] << 8) | h[1]) ^ ((h[2] << 8) | h[3]);
}
coap_tid_t
coap_send_ack(coap_context_t *context,
const coap_address_t *dst,
coap_pdu_t *request) {
coap_pdu_t *response;
coap_tid_t result = COAP_INVALID_TID;
if (request && request->hdr->type == COAP_MESSAGE_CON) {
response = coap_pdu_init(COAP_MESSAGE_ACK, 0, request->hdr->id,
sizeof(coap_pdu_t));
if (response) {
result = coap_send(context, dst, response);
if (result == COAP_INVALID_TID)
coap_delete_pdu(response);
}
}
return result;
}
#ifndef WITH_CONTIKI
/* releases space allocated by PDU if free_pdu is set */
coap_tid_t
@@ -653,12 +672,21 @@ coap_read( coap_context_t *ctx ) {
/* finally calculate beginning of data block */
{
coap_opt_t *opt = options_start(node->pdu);
unsigned char cnt;
unsigned char cnt = node->pdu->hdr->optcnt;
/* Note that we cannot use the official options iterator here as
* it eats up the fence posts. */
for (cnt = node->pdu->hdr->optcnt; cnt; --cnt)
while (cnt) {
if (node->pdu->hdr->optcnt == COAP_OPT_LONG) {
if (*opt == COAP_OPT_END) {
++opt;
break;
}
} else {
--cnt;
}
opt = options_next(opt);
}
node->pdu->data = (unsigned char *)opt;
}
@@ -780,7 +808,7 @@ coap_new_error_response(coap_pdu_t *request, unsigned char code,
coap_add_option(response, opt_iter.type,
COAP_OPT_LENGTH(opt_iter.option),
COAP_OPT_VALUE(opt_iter.option));
#if COAP_ERROR_PHRASE_LENGTH > 0
if (phrase)
coap_add_data(response, strlen(phrase), (unsigned char *)phrase);
+9 -9
View File
@@ -80,6 +80,12 @@ typedef void (*coap_response_handler_t)(struct coap_context_t *,
coap_pdu_t *received,
const coap_tid_t id);
#define COAP_MID_CACHE_SIZE 3
typedef struct {
unsigned char flags[COAP_MID_CACHE_SIZE];
coap_key_t item[COAP_MID_CACHE_SIZE];
} coap_mid_cache_t;
/** The CoAP stack's global state is stored in a coap_context_t object */
typedef struct coap_context_t {
coap_opt_filter_t known_options;
@@ -272,15 +278,9 @@ coap_send_message_type(coap_context_t *context,
* @return The transaction id if ACK was sent or @c COAP_INVALID_TID
* on error.
*/
static inline coap_tid_t
coap_send_ack(coap_context_t *context,
const coap_address_t *dst,
coap_pdu_t *request) {
if (request && request->hdr->type == COAP_MESSAGE_CON)
return coap_send_message_type(context, dst, request, COAP_MESSAGE_ACK);
else
return COAP_INVALID_TID;
}
coap_tid_t coap_send_ack(coap_context_t *context,
const coap_address_t *dst,
coap_pdu_t *request);
/**
* Sends an RST message with code @c 0 for the specified @p request to
+10 -7
View File
@@ -42,12 +42,18 @@ coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi,
#define IS_EMPTY_NOOP(Type,Option) \
((Type) % COAP_OPTION_NOOP == 0 && COAP_OPT_LENGTH(Option) == 0)
#define opt_finished(oi) ((oi)->optcnt == COAP_OPT_LONG \
? ((oi)->option && *((oi)->option) == COAP_OPT_END) \
: (oi->n > (oi)->optcnt))
coap_opt_t *
coap_option_next(coap_opt_iterator_t *oi) {
if (!oi || oi->n >= oi->optcnt)
assert(oi);
if (opt_finished(oi))
return NULL;
/* proceed to next option */
if (oi->n++) {
oi->option = options_next(oi->option);
oi->type += COAP_OPT_DELTA(oi->option);
@@ -55,22 +61,19 @@ coap_option_next(coap_opt_iterator_t *oi) {
/* Skip subsequent options if it is an empty no-op (used for
* fence-posting) or the filter bit is not set. */
while (oi->n <= oi->optcnt &&
while (!opt_finished(oi) &&
(IS_EMPTY_NOOP(oi->type, oi->option)
|| coap_option_getb(oi->filter, oi->type) == 0)) {
oi->n++;
oi->option = options_next(oi->option);
if (oi->n > oi->optcnt)
if (opt_finished(oi))
break;
oi->type += COAP_OPT_DELTA(oi->option);
}
if (oi->n > oi->optcnt)
oi->option = NULL;
return oi->option;
return opt_finished(oi) ? NULL : oi->option;
}
coap_opt_t *
+55 -26
View File
@@ -106,57 +106,67 @@ coap_delete_pdu(coap_pdu_t *pdu) {
}
int
coap_add_option(coap_pdu_t *pdu, unsigned char type, unsigned int len, const unsigned char *data) {
unsigned char cnt, optcnt;
coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len, const unsigned char *data) {
size_t optsize, cnt, optcnt, opt_code = 0;
unsigned char fence;
coap_opt_t *opt;
unsigned char opt_code = 0;
size_t old_optcnt; /* for restoring old values */
coap_opt_t *old_opt;
if (!pdu)
return -1;
/* get last option from pdu to calculate the delta */
opt = options_start( pdu );
for ( cnt = pdu->hdr->optcnt; cnt; --cnt ) {
/* Get last option from pdu to calculate the delta. For optcnt ==
* 0x0F, opt will point at the end marker, so the new option will
* overwrite it.
*/
opt = options_start(pdu);
cnt = pdu->hdr->optcnt;
while ((pdu->hdr->optcnt == COAP_OPT_LONG && *opt != COAP_OPT_END)
|| cnt--) {
opt_code += COAP_OPT_DELTA(opt);
opt = options_next(opt);
}
if ((unsigned char *)opt > (unsigned char *)pdu->hdr + pdu->max_size) {
debug("illegal option list\n");
return -1;
}
if ( type < opt_code ) {
#ifndef NDEBUG
coap_log(LOG_WARN, "options not added in correct order\n");
#endif
return -1;
}
optcnt = pdu->hdr->optcnt;
optcnt = old_optcnt = pdu->hdr->optcnt;
old_opt = opt;
optsize = len + (len > 14 ? 2 : 1);
/* Create new option after last existing option: First check if we
* need fence posts between type and last opt_code (i.e. delta >
* 15), and then add actual option.
*/
while (type - opt_code > 15) {
cnt = opt_code / COAP_OPTION_NOOP;
/* add fence post */
fence = ((COAP_OPTION_NOOP * ((opt_code / COAP_OPTION_NOOP) + 1))
- opt_code) << 4;
while (opt_code + 15 < type) {
if ((unsigned char *)opt + optsize + 1 >
(unsigned char *)pdu->hdr + pdu->max_size)
goto error;
if ((unsigned char *)opt + 1 > (unsigned char *)pdu->hdr + pdu->max_size) {
debug("cannot add fencepost option\n");
return -1;
}
/* add fence post */
optcnt += 1;
COAP_OPT_SETLENGTH( opt, 0 );
COAP_OPT_SETDELTA( opt, (COAP_OPTION_NOOP * (cnt+1)) - opt_code );
*opt = fence;
opt_code += COAP_OPT_DELTA(opt);
opt = options_next(opt);
fence = COAP_OPTION_NOOP << 4;
}
if ((unsigned char *)opt + len + (len > 14 ? 2 : 1) >
(unsigned char *)pdu->hdr + pdu->max_size) {
debug("cannot add option\n");
return -1;
}
if ((unsigned char *)opt + optsize + 1 >
(unsigned char *)pdu->hdr + pdu->max_size)
goto error;
/* here, the actual option is added (delta <= 15) */
optcnt += 1;
@@ -166,9 +176,28 @@ coap_add_option(coap_pdu_t *pdu, unsigned char type, unsigned int len, const uns
memcpy(COAP_OPT_VALUE(opt), data, len);
pdu->data = (unsigned char *)COAP_OPT_VALUE(opt) + len ;
pdu->hdr->optcnt = optcnt;
if (optcnt < COAP_OPT_LONG) {
pdu->hdr->optcnt = optcnt;
} else {
pdu->hdr->optcnt = COAP_OPT_LONG;
*pdu->data = COAP_OPT_END;
pdu->data++;
}
pdu->length = pdu->data - (unsigned char *)pdu->hdr;
return len;
error:
/* Restore state before we have tried to add fencepost options.
* Because pdu->data and pdu->length have not yet been updated,
* there is no need to touch them. Only the end marker must been
* written anew if optcnt == 15;
*/
pdu->hdr->optcnt = old_optcnt;
if (pdu->hdr->optcnt == COAP_OPT_LONG)
*old_opt = COAP_OPT_END;
return -1;
}
int
+6 -1
View File
@@ -175,6 +175,11 @@ typedef struct {
&& ((MSG)->code < 32))
#define COAP_MESSAGE_IS_RESPONSE(MSG) ((MSG)->code >= 64 && (MSG)->code <= 191)
#define COAP_OPT_LONG 0x0F /* OC == 0b1111 indicates that the option list in a
* CoAP message is limited by 0b11110000 marker */
#define COAP_OPT_END 0xF0 /* end marker */
/**
* Structures for more convenient handling of options. (To be used with ordered
* coap_list_t.) The option's data will be added to the end of the coap_option
@@ -244,7 +249,7 @@ void coap_delete_pdu(coap_pdu_t *);
* destroys the PDU's data, so coap_add_data must be called after all options have been
* added.
*/
int coap_add_option(coap_pdu_t *pdu, unsigned char type, unsigned int len, const unsigned char *data);
int coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len, const unsigned char *data);
/**
* Adds given data to the pdu that is passed as first parameter. Note that the PDU's