Lines Matching refs:block

1 /* coap_block.c -- block transfer
59 coap_option_num_t number, coap_block_b_t *block) {
63 assert(block);
64 memset(block, 0, sizeof(coap_block_b_t));
70 block->m = 1;
71 block->aszx = block->szx = COAP_OPT_BLOCK_SZX(option);
72 if (block->szx == 7) {
81 block->szx = 6; /* BERT is 1024 block chunks */
82 block->bert = 1;
84 if (block->m && (length % 1024) != 0) {
85 coap_log_debug("block: Oversized packet - reduced to %zu from %zu\n",
89 block->chunk_size = (uint32_t)length;
91 block->chunk_size = 0;
93 block->chunk_size = (size_t)1 << (block->szx + 4);
95 block->defined = 1;
97 /* The block number is at most 20 bits, so values above 2^20 - 1
103 block->num = num;
112 coap_block_t *block) {
115 assert(block);
116 memset(block, 0, sizeof(coap_block_t));
119 block->num = block_b.num;
120 block->m = block_b.m;
121 block->szx = block_b.szx;
128 setup_block_b(coap_session_t *session, coap_pdu_t *pdu, coap_block_b_t *block,
134 unsigned int can_use_bert = block->defined == 0 || block->bert;
137 memset(block, 0, sizeof(*block));
138 block->num = num;
139 block->szx = block->aszx = blk_size;
143 block->bert = 1;
144 block->aszx = 7;
145 block->chunk_size = (uint32_t)((avail / 1024) * 1024);
147 block->chunk_size = (size_t)1 << (blk_size + 4);
148 if (avail < block->chunk_size && (total - start) >= avail) {
149 /* Need to reduce block size */
153 if (avail < 16) { /* bad luck, this is the smallest block size */
154 coap_log_debug("not enough space, even the smallest block does not fit (1)\n");
158 coap_log_debug("decrease block size for %zu to %d\n", avail, new_blk_size);
159 szx = block->szx;
160 block->szx = new_blk_size;
161 block->num <<= szx - block->szx;
162 block->chunk_size = (size_t)1 << (new_blk_size + 4);
165 block->m = block->chunk_size < total - start;
170 coap_write_block_opt(coap_block_t *block, coap_option_num_t number,
178 start = block->num << (block->szx + 4);
179 if (block->num != 0 && data_length <= start) {
180 coap_log_debug("illegal block requested\n");
188 if (!setup_block_b(NULL, pdu, &block_b, block->num,
189 block->szx, data_length))
192 /* to re-encode the block option */
203 coap_write_block_b_opt(coap_session_t *session, coap_block_b_t *block,
211 start = block->num << (block->szx + 4);
212 if (block->num != 0 && data_length <= start) {
213 coap_log_debug("illegal block requested\n");
219 if (!setup_block_b(session, pdu, block, block->num,
220 block->szx, data_length))
223 /* to re-encode the block option */
225 ((block->num << 4) |
226 (block->m << 3) |
227 block->aszx)),
249 coap_block_b_t *block) {
250 unsigned int start = block->num << (block->szx + 4);
256 if (block->bert) {
260 max_size = (size_t)1 << (block->szx + 4);
262 block->chunk_size = (uint32_t)max_size;
287 * Need to check that a valid block is getting asked for so that the
294 coap_log_debug("Illegal block requested (%d > last = %zu)\n",
326 case -2: /* illegal block (caught above) */
354 * Insufficient space to add in data - use block mode
355 * set initial block size, will be lowered by
428 coap_block_b_t block;
430 COAP_OPTION_Q_BLOCK1, &block);
476 mid = coap_send_q_block1(session, block, pdu, COAP_SEND_INC_PDU);
507 coap_block_b_t block;
532 if (coap_get_block_b(session, resend_pdu, COAP_OPTION_BLOCK1, &block)) {
533 if (data_len > block.chunk_size && block.chunk_size != 0) {
534 data_len = block.chunk_size;
606 coap_block_b_t block;
641 /* Block NUM max 20 bits and block size is "2**(SZX + 4)"
653 /* Determine the block size to use, adding in sensible options if needed */
666 if (coap_get_block_b(session, pdu, COAP_OPTION_Q_BLOCK1, &block)) {
695 if (coap_get_block_b(session, pdu, COAP_OPTION_Q_BLOCK2, &block)) {
737 if (coap_get_block_b(session, pdu, option, &block)) {
738 if (block.szx < blk_size)
739 blk_size = block.szx;
750 block = alt_block;
751 if (block.szx < blk_size)
752 blk_size = block.szx;
760 /* bad luck, this is the smallest block size */
761 coap_log_debug("not enough space, even the smallest block does not fit (2)\n");
767 (block.num != 0 || single_request)) {
768 /* App is defining a single block to send */
771 if (length >= block.num * chunk) {
773 if (chunk > length - block.num * chunk)
774 rem = length - block.num * chunk;
775 if (!coap_add_data(pdu, rem, &data[block.num * chunk]))
781 /* Only add in lg_xmit if more than one block needs to be handled */
891 if (!setup_block_b(session, pdu, &block, block.num,
895 /* Add in with requested block num, more bit and block size */
899 (block.num << 4) | (block.m << 3) | block.aszx),
931 coap_log_warn("not enough space, even the smallest block does not fit (3)\n");
935 block.num = block.num << (lg_xmit->blk_size - blk_size);
938 block.chunk_size = (uint32_t)chunk;
939 block.bert = 0;
943 (block.num << 4) | (block.m << 3) | lg_xmit->blk_size),
947 rem = block.chunk_size;
948 if (rem > lg_xmit->length - block.num * chunk)
949 rem = lg_xmit->length - block.num * chunk;
950 if (!coap_add_data(pdu, rem, &data[block.num * chunk]))
1002 * E.g. Reliable and CSM not in yet for checking block support
1030 coap_block_b_t block;
1040 memset(&block, 0, sizeof(block));
1042 * Need to check that a valid block is getting asked for so that the
1046 if (coap_get_block_b(session, request, COAP_OPTION_BLOCK2, &block)) {
1048 if (block.num != 0 && length <= (block.num << (block.szx + 4))) {
1049 coap_log_debug("Illegal block requested (%d > last = %zu)\n",
1050 block.num,
1051 length >> (block.szx + 4));
1057 else if (coap_get_block_b(session, request, COAP_OPTION_Q_BLOCK2, &block)) {
1059 if (block.num != 0 && length <= (block.num << (block.szx + 4))) {
1060 coap_log_debug("Illegal block requested (%d > last = %zu)\n",
1061 block.num,
1062 length >> (block.szx + 4));
1070 if (block.m == 0)
1090 res = coap_write_block_b_opt(session, &block, block_opt, response,
1094 case -2: /* illegal block (caught above) */
1208 int block = -1; /* Last one seen */
1216 * See if it is safe to use the single 'M' block variant of request
1219 * terminate on the last block or before range[1].begin if set.
1227 block = lg_crcv->rec_blocks.range[0].end + 1;
1229 sofar = block * block_size;
1239 (block << 4) | (1 << 3) | lg_crcv->szx),
1241 block_payload_set = block / COAP_MAX_PAYLOADS(session);
1246 block = -1;
1248 if (block < (int)lg_crcv->rec_blocks.range[i].begin &&
1256 block++;
1258 block_payload_set = block / COAP_MAX_PAYLOADS(session);
1259 for (; block < (int)lg_crcv->rec_blocks.range[i].begin &&
1260 block_payload_set == (block / COAP_MAX_PAYLOADS(session)); block++) {
1263 (block << 4) | (0 << 3) | lg_crcv->szx),
1267 if (block < (int)lg_crcv->rec_blocks.range[i].end) {
1268 block = lg_crcv->rec_blocks.range[i].end;
1272 sofar = (block + 1) * block_size;
1281 block++;
1283 block_payload_set = block / COAP_MAX_PAYLOADS(session);
1284 for (; block < (ssize_t)sofar &&
1285 block_payload_set == (block / COAP_MAX_PAYLOADS(session)); block++) {
1288 (block << 4) | (0 << 3) | lg_crcv->szx),
1399 add_408_block(coap_pdu_t *pdu, int block) {
1403 assert(block >= 0 && block < (1 << 20));
1405 if (block < 0 || block >= (1 << 20)) {
1407 } else if (block < 24) {
1409 val[0] = block;
1410 } else if (block < 0x100) {
1413 val[1] = block;
1414 } else if (block < 0x10000) {
1417 val[1] = block >> 8;
1418 val[2] = block & 0xff;
1419 } else { /* Largest block number is 2^^20 - 1 */
1422 val[1] = block >> 16;
1423 val[2] = (block >> 8) & 0xff;
1424 val[3] = block & 0xff;
1452 uint32_t block = 0;
1455 if (block < rec_blocks->range[i].begin)
1457 if (block < rec_blocks->range[i].end)
1458 block = rec_blocks->range[i].end;
1461 if (block + 1 < total_blocks)
1530 int block = -1; /* Last one seen */
1540 if (block < (int)p->rec_blocks.range[i].begin &&
1542 block++;
1543 no_blocks += p->rec_blocks.range[i].begin - block;
1545 if (block < (int)p->rec_blocks.range[i].end) {
1546 block = p->rec_blocks.range[i].end;
1549 if (no_blocks == 0 && block == (int)final_block)
1553 cur_payload = block / COAP_MAX_PAYLOADS(session);
1558 no_blocks += final_block - block;
1566 no_blocks += final_block - block;
1569 block = -1;
1571 if (block < (int)p->rec_blocks.range[i].begin &&
1579 block++;
1580 for (; block < (int)p->rec_blocks.range[i].begin; block++) {
1581 if (!add_408_block(pdu, block)) {
1586 if (block < (int)p->rec_blocks.range[i].end) {
1587 block = p->rec_blocks.range[i].end;
1590 block++;
1591 for (; block <= (int)final_block; block++) {
1597 if (!add_408_block(pdu, block)) {
1640 coap_block_b_t block,
1669 if (block.m &&
1671 ((block.num + 1) % COAP_MAX_PAYLOADS(session)) + 1 !=
1710 block.num++;
1711 lg_xmit->offset = block.num * chunk;
1712 block.m = lg_xmit->offset + chunk < lg_xmit->length;
1713 if (block.m && ((block_pdu->type == COAP_MESSAGE_NON &&
1714 (block.num % COAP_MAX_PAYLOADS(session)) + 1 !=
1720 * Send following block if
1739 ((block.num) << 4) |
1740 (block.m << 3) |
1741 block.szx),
1752 block.num,
1753 block.szx)) {
1760 lg_xmit->last_block = block.num;
1770 if (!block.m) {
1796 coap_block_b_t block;
1799 memset(&block, 0, sizeof(block));
1800 block.num = (uint32_t)(lg_xmit->offset / chunk);
1801 block.m = lg_xmit->offset + chunk < lg_xmit->length;
1802 block.szx = lg_xmit->blk_size;
1803 coap_send_q_blocks(session, lg_xmit, block, &lg_xmit->pdu, COAP_SEND_SKIP_PDU);
1846 coap_block_b_t block;
1849 memset(&block, 0, sizeof(block));
1850 block.num = (uint32_t)(lg_xmit->offset / chunk);
1851 block.m = lg_xmit->offset + chunk < lg_xmit->length;
1852 block.szx = lg_xmit->blk_size;
1853 if (block.num == (uint32_t)lg_xmit->last_block)
1854 coap_send_q_blocks(session, lg_xmit, block, &lg_xmit->pdu, COAP_SEND_SKIP_PDU);
1883 * Else If Observe = 1, return the saved token for this block
1930 coap_block_b_t block,
1948 return coap_send_q_blocks(session, lg_xmit, block, request, send_request);
1963 coap_block_b_t block,
1978 return coap_send_q_blocks(session, lg_xmit, block, response, send_response);
2014 /* M needs to be unset as 'asking' for only the first block */
2196 * Need to see if this is a request for the next block of a large body
2219 coap_block_b_t block;
2235 if (coap_get_block_b(session, pdu, COAP_OPTION_Q_BLOCK2, &block)) {
2249 block = alt_block;
2254 if (block.num == 0) {
2292 if (block.bert) {
2293 coap_log_debug("found Block option, block is BERT, block nr. %u, M %d\n",
2294 block.num, block.m);
2296 coap_log_debug("found Block option, block size is %u, block nr. %u, M %d\n",
2297 1 << (block.szx + 4), block.num, block.m);
2299 if (block.bert == 0 && block.szx != p->blk_size) {
2300 if ((p->offset + chunk) % ((size_t)1 << (block.szx + 4)) == 0) {
2302 * Recompute the block number of the previous packet given
2303 * the new block size
2305 block.num = (uint32_t)(((p->offset + chunk) >> (block.szx + 4)) - 1);
2306 p->blk_size = block.szx;
2308 p->offset = block.num * chunk;
2309 coap_log_debug("new Block size is %u, block number %u completed\n",
2310 1 << (block.szx + 4), block.num);
2313 "next block is not aligned on requested block size "
2316 (1 << (block.szx + 4)),
2317 (p->offset + chunk) % ((size_t)1 << (block.szx + 4)));
2339 if (block.aszx != COAP_OPT_BLOCK_SZX(option)) {
2378 /* Block2 or Q-Block2 not found - give them the first block */
2379 block.szx = p->blk_size;
2389 block.num = out_blocks[i].num;
2390 p->offset = block.num * chunk;
2397 if (block.num != 0)
2414 * Copy the options across and then fix the block option
2416 * Need to drop Observe option if Block2 and block.num != 0
2420 if (opt_iter.number == COAP_OPTION_OBSERVE && block.num != 0)
2432 if (block.bert) {
2434 block.m = (p->length - p->offset) >
2437 block.m = (p->offset + chunk) < p->length;
2442 (block.num << 4) |
2443 (block.m << 3) |
2444 block.aszx),
2449 /* Last block - keep in cache for 4 * ACK_TIMOUT */
2457 /* Last block - keep in cache for 4 * ACK_TIMOUT */
2481 &block)) {
2589 coap_block_b_t block;
2599 if (coap_get_block_b(session, pdu, COAP_OPTION_BLOCK1, &block)) {
2612 else if (coap_get_block_b(session, pdu, COAP_OPTION_Q_BLOCK1, &block)) {
2634 if (length > block.chunk_size) {
2635 coap_log_debug("block: Oversized packet - reduced to %"PRIu32" from %zu\n",
2636 block.chunk_size, length);
2637 length = block.chunk_size;
2641 offset = block.num << (block.szx + 4);
2659 if (!p && block.num != 0) {
2664 pdu->body_total = length + offset + (block.m ? 1 : 0);
2666 /* Do not do this if this is a single block */
2667 else if (!p && !(offset == 0 && block.m == 0)) {
2686 p->szx = block.szx;
2731 block.bert) {
2732 size_t chunk = (size_t)1 << (block.szx + 4);
2734 unsigned int saved_num = block.num;
2738 if (!check_if_received_block(&p->rec_blocks, block.num)) {
2740 if (!update_received_blocks(&p->rec_blocks, block.num)) {
2749 block.num++;
2750 offset = block.num << (block.szx + 4);
2752 block.num--;
2756 block.num / COAP_MAX_PAYLOADS(session);
2768 if (block.m ||
2772 if (block.m) {
2785 block.num = p->rec_blocks.range[0].end;
2796 /* Ask for the next block */
2800 (block.m << 3) |
2801 block.aszx),
2833 /* Exact match if last block */
2834 if (block.m) {
2837 if (total > offset + length + block.m)
2840 pdu->body_total = offset + length + block.m;
2844 (block.num << 4) |
2845 (block.m << 3) |
2846 block.aszx),
2851 pdu->body_total = offset + length + block.m;
2855 if (block.m == 0) {
3009 * need to initiate the request containing the next block and not trouble the
3042 coap_block_b_t block;
3045 coap_get_block_b(session, rcvd, p->option, &block)) {
3047 if (block.bert) {
3048 coap_log_debug("found Block option, block is BERT, block nr. %u (%zu)\n",
3049 block.num, p->b.b1.bert_size);
3051 coap_log_debug("found Block option, block size is %u, block nr. %u\n",
3052 1 << (block.szx + 4), block.num);
3054 if (block.szx != p->blk_size) {
3055 if ((p->offset + chunk) % ((size_t)1 << (block.szx + 4)) == 0) {
3057 * Recompute the block number of the previous packet given the
3058 * new block size
3060 block.num = (uint32_t)(((p->offset + chunk) >> (block.szx + 4)) - 1);
3061 p->blk_size = block.szx;
3063 p->offset = block.num * chunk;
3064 coap_log_debug("new Block size is %u, block number %u completed\n",
3065 1 << (block.szx + 4), block.num);
3066 block.bert = 0;
3067 block.aszx = block.szx;
3070 "next block is not aligned on requested block size boundary. "
3073 (1 << (block.szx + 4)),
3074 (p->offset + chunk) % ((size_t)1 << (block.szx + 4)));
3078 if (p->last_block == (int)block.num &&
3085 * same block multiple times, or the server retransmitting the
3088 * Once a block has been ACKd, there is no need to retransmit it.
3092 if (block.bert)
3093 block.num += (unsigned int)(p->b.b1.bert_size / 1024 - 1);
3094 p->last_block = block.num;
3095 p->offset = (block.num + 1) * chunk;
3111 new_token = track_fetch_observe(&p->pdu, lg_crcv, block.num + 1,
3126 block.num++;
3127 if (block.bert) {
3130 block.m = (p->length - p->offset) >
3133 block.m = (p->offset + chunk) < p->length;
3137 (block.num << 4) |
3138 (block.m << 3) |
3139 block.aszx),
3145 &block))
3147 p->b.b1.bert_size = block.chunk_size;
3152 if (coap_send_q_block1(session, block, pdu,
3170 if (coap_get_block_b(session, rcvd, COAP_OPTION_Q_BLOCK2, &block) ||
3171 coap_get_block_b(session, rcvd, COAP_OPTION_Q_BLOCK1, &block))
3210 block.num = derive_cbor_value(&bp, data + length - bp);
3211 coap_log_debug("Q-Block1: Missing block %d\n", block.num);
3212 if (block.num > (1 << 20) -1)
3214 block.m = (block.num + 1) * chunk < p->length;
3215 block.szx = p->blk_size;
3227 (block.num << 4) |
3228 (block.m << 3) |
3229 block.szx),
3235 block.num,
3236 block.szx))
3325 * need to initiate the request for the next block and not trouble the
3341 coap_block_b_t block;
3353 memset(&block, 0, sizeof(block));
3383 if (coap_get_block_b(session, rcvd, COAP_OPTION_BLOCK2, &block)) {
3394 block = qblock;
3402 if (have_block && (block.m || length)) {
3416 if (length > block.chunk_size) {
3417 coap_log_debug("block: Oversized packet - reduced to %"PRIu32" from %zu\n",
3418 block.chunk_size, length);
3419 length = block.chunk_size;
3422 chunk = (size_t)1 << (block.szx + 4);
3423 offset = block.num * chunk;
3425 if (block.m)
3450 p->szx = block.szx;
3494 (0 << 4) | (0 << 3) | block.aszx),
3518 if (block.num == 0) {
3532 if (!check_if_received_block(&p->rec_blocks, block.num)) {
3534 uint32_t this_payload_set = block.num / COAP_MAX_PAYLOADS(session);
3537 coap_log_debug("found Block option, block size is %u, block nr. %u\n",
3538 1 << (block.szx + 4), block.num);
3548 if (!update_received_blocks(&p->rec_blocks, block.num)) {
3554 block.num++;
3555 offset = block.num << (block.szx + 4);
3556 if (!block.bert && block_opt != COAP_OPTION_Q_BLOCK2)
3559 block.num--;
3560 /* Only process if not duplicate block */
3562 if ((session->block_mode & COAP_SINGLE_BLOCK_OR_Q) || block.bert) {
3572 if (block.m || !check_all_blocks_in(&p->rec_blocks,
3579 if (block.m) {
3589 block.num = p->rec_blocks.range[0].end;
3592 block.num / COAP_MAX_PAYLOADS(session) + 1;
3610 block.m = 0;
3612 /* Ask for the next block */
3622 /* Only sent with the first block */
3627 ((block.num + 1) << 4) |
3628 (block.m << 3) | block.aszx),
3634 if ((session->block_mode & COAP_SINGLE_BLOCK_OR_Q) || block.bert)
3653 if ((session->block_mode & COAP_SINGLE_BLOCK_OR_Q) || block.bert) {
3654 /* Pretend that there is no block */
3744 if (!block.m && !p->observe_set) {
3760 /* Check if receiving a block response and if blocks can be set up */
3763 if (coap_get_block_b(session, rcvd, COAP_OPTION_BLOCK2, &block)
3766 coap_get_block_b(session, rcvd, COAP_OPTION_Q_BLOCK2, &block)
3774 if (coap_get_block_b(session, rcvd, COAP_OPTION_BLOCK2, &block)) {
3783 if (block.num != 0) {
3787 size_t chunk = (size_t)1 << (block.szx + 4);
3790 rcvd->body_offset = block.num*chunk;
3791 rcvd->body_total = block.num*chunk + length + (block.m ? 1 : 0);
3796 else if (coap_get_block_b(session, rcvd, COAP_OPTION_Q_BLOCK2, &block)) {