1 /* block.c -- block transfer
3 * Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
5 * This file is part of the CoAP library libcoap. Please see
6 * README for terms of use.
11 #if defined(HAVE_ASSERT_H) && !defined(assert)
16 /* On Arduino the abort function, needed for assert, is defined in std lib */
23 #define min(a,b) ((a) < (b) ? (a) : (b))
26 unsigned int coap_opt_block_num(const coap_opt_t *block_opt)
31 len = coap_opt_length(block_opt);
40 num = coap_decode_var_bytes(COAP_OPT_VALUE(block_opt), COAP_OPT_LENGTH(block_opt) - 1);
43 return (num << 4) | ((*COAP_OPT_BLOCK_LAST(block_opt) & 0xF0) >> 4);
46 int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block)
48 coap_opt_iterator_t opt_iter;
52 memset(block, 0, sizeof(coap_block_t));
54 if (pdu && (option = coap_check_option(pdu, type, &opt_iter)))
56 block->szx = COAP_OPT_BLOCK_SZX(option);
57 if (COAP_OPT_BLOCK_MORE(option))
59 block->num = coap_opt_block_num(option);
66 int coap_write_block_opt(coap_block_t *block, unsigned short type, coap_pdu_t *pdu,
69 size_t start, want, avail;
75 if (type != COAP_OPTION_BLOCK2)
77 warn("coap_write_block_opt: skipped unknown option\n");
81 start = block->num << (block->szx + 4);
82 if (data_length <= start)
84 debug("illegal block requested\n");
88 avail = pdu->max_size - pdu->length - 4;
89 want = 1 << (block->szx + 4);
91 /* check if entire block fits in message */
94 block->m = want < data_length - start;
98 /* Sender has requested a block that is larger than the remaining
99 * space in pdu. This is ok if the remaining data fits into the pdu
100 * anyway. The block size needs to be adjusted only if there is more
101 * data left that cannot be delivered in this message. */
103 if (data_length - start <= avail)
106 /* it's the final block and everything fits in the message */
113 /* we need to decrease the block size */
115 { /* bad luck, this is the smallest block size */
116 debug("not enough space, even the smallest block does not fit");
119 debug("decrease block size for %d to %d\n", avail, coap_fls(avail) - 5);
121 block->szx = coap_fls(avail) - 5;
123 block->num <<= szx - block->szx;
127 /* to re-encode the block option */
128 coap_add_option(pdu, type,
129 coap_encode_var_bytes(buf, ((block->num << 4) | (block->m << 3) | block->szx)), buf);
134 int coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data,
135 unsigned int block_num, unsigned char block_szx)
138 start = block_num << (block_szx + 4);
143 return coap_add_data(pdu, min(len - start, (unsigned int)(1 << (block_szx + 4))), data + start);
145 #endif /* WITHOUT_BLOCK */