Fixed bug in well-known/core resource for small block sizes

This commit is contained in:
Matthias Kovatsch 2011-10-10 14:17:56 +02:00
parent ce6f8de078
commit 65955ca477

View file

@ -169,7 +169,7 @@ handle_incoming_data(void)
PRINTF("handle_incoming_data(): block_offset >= response->payload_len\n"); PRINTF("handle_incoming_data(): block_offset >= response->payload_len\n");
response->code = BAD_OPTION_4_02; response->code = BAD_OPTION_4_02;
coap_set_payload(response, (uint8_t*)"Block out of scope", 18); coap_set_payload(response, (uint8_t*)"BlockOutOfScope", 15);
} }
else else
{ {
@ -308,55 +308,82 @@ RESOURCE(well_known_core, METHOD_GET, ".well-known/core", "");
void void
well_known_core_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) well_known_core_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{ {
/* Response might be NULL for non-confirmable requests. */
if (response)
{
size_t strpos = 0; size_t strpos = 0;
size_t bufpos = 0; size_t bufpos = 0;
size_t tmplen = 0;
resource_t* resource = NULL; resource_t* resource = NULL;
for (resource = (resource_t*)list_head(rest_get_resources()); resource; resource = resource->next) for (resource = (resource_t*)list_head(rest_get_resources()); resource; resource = resource->next)
{ {
strpos += snprintf((char *) buffer + bufpos, REST_MAX_CHUNK_SIZE - bufpos + 1, PRINTF("res: /%s (%p)\n", resource->url, resource);
"</%s>%s%s%s",
resource->url,
resource->attributes[0] ? ";" : "",
resource->attributes,
resource->next ? "," : "" );
PRINTF("discover: %s\n", resource->url); if (strpos >= *offset && bufpos < preferred_size)
if (strpos <= *offset)
{ {
/* Discard output before current block */ buffer[bufpos++] = '<';
PRINTF(" if %d <= %ld B\n", strpos, *offset);
PRINTF(" %s\n", buffer);
bufpos = 0;
} }
else /* (strpos > *offset) */ ++strpos;
if (strpos >= *offset && bufpos < preferred_size)
{ {
/* output partly in block */ buffer[bufpos++] = '/';
size_t len = MIN(strpos - *offset, preferred_size); }
++strpos;
PRINTF(" el %d/%d @ %ld B\n", len, preferred_size, *offset); tmplen = strlen(resource->url);
if (strpos+tmplen > *offset)
{
bufpos += snprintf((char *) buffer + bufpos, preferred_size - bufpos + 1,
"%s", resource->url + (*offset-strpos > 0 ? *offset-strpos : 0));
}
strpos += tmplen;
/* Block might start in the middle of the output; align with buffer start. */ if (strpos >= *offset && bufpos < preferred_size)
if (bufpos == 0) {
buffer[bufpos++] = '>';
}
++strpos;
if (resource->attributes[0])
{
if (strpos >= *offset && bufpos < preferred_size)
{ {
memmove(buffer, buffer+strlen((char *)buffer)-strpos+*offset, len); buffer[bufpos++] = ';';
} }
++strpos;
bufpos = len; tmplen = strlen(resource->attributes);
PRINTF(" %s\n", buffer); if (strpos+tmplen > *offset)
if (bufpos >= preferred_size)
{ {
break; bufpos += snprintf((char *) buffer + bufpos, preferred_size - bufpos + 1,
"%s", resource->attributes + (*offset-strpos > 0 ? *offset-strpos : 0));
} }
strpos += tmplen;
}
if (resource->next)
{
if (strpos >= *offset && bufpos < preferred_size)
{
buffer[bufpos++] = ',';
}
if (bufpos <= preferred_size)
{
++strpos;
}
}
/* buffer full, but resource not completed yet; or: do not break if resource exactly fills buffer. */
if (bufpos >= preferred_size && strpos-bufpos > *offset)
{
PRINTF("res: BREAK at %s (%p)\n", resource->url, resource);
break;
} }
} }
if (bufpos>0) { if (bufpos>0) {
PRINTF("BUF %d: %.*s\n", bufpos, bufpos, (char *) buffer);
coap_set_payload(response, buffer, bufpos ); coap_set_payload(response, buffer, bufpos );
coap_set_header_content_type(response, APPLICATION_LINK_FORMAT); coap_set_header_content_type(response, APPLICATION_LINK_FORMAT);
} }
@ -365,17 +392,18 @@ well_known_core_handler(void* request, void* response, uint8_t *buffer, uint16_t
PRINTF("well_known_core_handler(): bufpos<=0\n"); PRINTF("well_known_core_handler(): bufpos<=0\n");
coap_set_rest_status(response, BAD_OPTION_4_02); coap_set_rest_status(response, BAD_OPTION_4_02);
coap_set_payload(response, (uint8_t*)"Block out of scope", 18); coap_set_payload(response, (uint8_t*)"BlockOutOfScope", 15);
} }
if (resource==NULL) { if (resource==NULL) {
PRINTF("res: DONE\n");
*offset = -1; *offset = -1;
} }
else else
{ {
PRINTF("res: MORE at %s (%p)\n", resource->url, resource);
*offset += bufpos; *offset += bufpos;
} }
}
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
PROCESS_THREAD(coap_receiver, ev, data) PROCESS_THREAD(coap_receiver, ev, data)