void well_known_core_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t strpos = 0; /* position in overall string (which is larger than the buffer) */ size_t bufpos = 0; /* position within buffer (bytes written) */ size_t tmplen = 0; resource_t* resource = NULL; /* For filtering. */ const char *filter = NULL; int len = coap_get_query_variable(request, "rt", &filter); char *rt = NULL; for (resource = (resource_t*)list_head(rest_get_resources()); resource; resource = resource->next) { /* Filtering */ if (len && ((rt=strstr(resource->attributes, "rt=\""))==NULL || memcmp(rt+4, filter, len-1)!=0 || (filter[len-1]!='*' && (filter[len-1]!=rt[3+len] || rt[4+len]!='"')))) { continue; } PRINTF("res: /%s (%p)\npos: s%d, o%d, b%d\n", resource->url, resource, strpos, *offset, bufpos); if (strpos >= *offset && bufpos < preferred_size) { buffer[bufpos++] = '<'; } ++strpos; if (strpos >= *offset && bufpos < preferred_size) { buffer[bufpos++] = '/'; } ++strpos; tmplen = strlen(resource->url); if (strpos+tmplen > *offset) { bufpos += snprintf((char *) buffer + bufpos, preferred_size - bufpos + 1, "%s", resource->url + ((*offset-(int32_t)strpos > 0) ? (*offset-(int32_t)strpos) : 0)); /* minimal-net requires these casts */ if (bufpos >= preferred_size) { break; } } strpos += tmplen; if (strpos >= *offset && bufpos < preferred_size) { buffer[bufpos++] = '>'; } ++strpos; if (resource->attributes[0]) { if (strpos >= *offset && bufpos < preferred_size) { buffer[bufpos++] = ';'; } ++strpos; tmplen = strlen(resource->attributes); if (strpos+tmplen > *offset) { bufpos += snprintf((char *) buffer + bufpos, preferred_size - bufpos + 1, "%s", resource->attributes + (*offset-(int32_t)strpos > 0 ? *offset-(int32_t)strpos : 0)); if (bufpos >= preferred_size) { break; } } strpos += tmplen; } if (resource->next) { if (strpos >= *offset && bufpos < preferred_size) { buffer[bufpos++] = ','; } ++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) { PRINTF("BUF %d: %.*s\n", bufpos, bufpos, (char *) buffer); coap_set_payload(response, buffer, bufpos ); coap_set_header_content_type(response, APPLICATION_LINK_FORMAT); } else if (strpos>0) { PRINTF("well_known_core_handler(): bufpos<=0\n"); coap_set_status_code(response, BAD_OPTION_4_02); coap_set_payload(response, "BlockOutOfScope", 15); } if (resource==NULL) { PRINTF("res: DONE\n"); *offset = -1; } else { PRINTF("res: MORE at %s (%p)\n", resource->url, resource); *offset += preferred_size; } }
void well_known_core_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t strpos = 0; /* position in overall string (which is larger than the buffer) */ size_t bufpos = 0; /* position within buffer (bytes written) */ size_t tmplen = 0; resource_t* resource = NULL; #if COAP_LINK_FORMAT_FILTERING /* For filtering. */ const char *filter = NULL; const char *attrib = NULL; const char *found = NULL; const char *end = NULL; char *value = NULL; char lastchar = '\0'; int len = coap_get_header_uri_query(request, &filter); if (len) { value = strchr(filter, '='); value[0] = '\0'; ++value; len -= strlen(filter)+1; PRINTF("Filter %s = %.*s\n", filter, len, value); if (strcmp(filter,"href")==0 && value[0]=='/') { ++value; --len; } lastchar = value[len-1]; value[len-1] = '\0'; } #endif for (resource = (resource_t*)list_head(rest_get_resources()); resource; resource = resource->next) { #if COAP_LINK_FORMAT_FILTERING /* Filtering */ if (len) { if (strcmp(filter,"href")==0) { attrib=strstr(resource->url, value); if (attrib==NULL || (value[-1]=='/' && attrib!=resource->url)) continue; end = attrib + strlen(attrib); } else { attrib=strstr(resource->attributes, filter); if (attrib==NULL || (attrib[strlen(filter)]!='=' && attrib[strlen(filter)]!='"')) continue; attrib += strlen(filter)+2; end = strchr(attrib, '"'); } PRINTF("Filter: res has attrib %s (%s)\n", attrib, value); found = attrib; while ((found=strstr(found, value))!=NULL) { if (found > end) { found = NULL; break; } if (lastchar==found[len-1] || lastchar=='*') { break; } ++found; } if (found==NULL) { continue; } PRINTF("Filter: res has prefix %s\n", found); if (lastchar!='*' && (found[len]!='"' && found[len]!=' ' && found[len]!='\0')) continue; PRINTF("Filter: res has match\n"); } #endif PRINTF("res: /%s (%p)\npos: s%d, o%ld, b%d\n", resource->url, resource, strpos, *offset, bufpos); if (strpos>0) { if (strpos >= *offset && bufpos < preferred_size) { buffer[bufpos++] = ','; } ++strpos; } if (strpos >= *offset && bufpos < preferred_size) { buffer[bufpos++] = '<'; } ++strpos; if (strpos >= *offset && bufpos < preferred_size) { buffer[bufpos++] = '/'; } ++strpos; tmplen = strlen(resource->url); if (strpos+tmplen > *offset) { bufpos += snprintf((char *) buffer + bufpos, preferred_size - bufpos + 1, "%s", resource->url + ((*offset-(int32_t)strpos > 0) ? (*offset-(int32_t)strpos) : 0)); /* minimal-net requires these casts */ if (bufpos >= preferred_size) { break; } } strpos += tmplen; if (strpos >= *offset && bufpos < preferred_size) { buffer[bufpos++] = '>'; } ++strpos; if (resource->attributes[0]) { if (strpos >= *offset && bufpos < preferred_size) { buffer[bufpos++] = ';'; } ++strpos; tmplen = strlen(resource->attributes); if (strpos+tmplen > *offset) { bufpos += snprintf((char *) buffer + bufpos, preferred_size - bufpos + 1, "%s", resource->attributes + (*offset-(int32_t)strpos > 0 ? *offset-(int32_t)strpos : 0)); if (bufpos >= preferred_size) { break; } } strpos += tmplen; } /* 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) { PRINTF("BUF %d: %.*s\n", bufpos, bufpos, (char *) buffer); coap_set_payload(response, buffer, bufpos ); coap_set_header_content_type(response, APPLICATION_LINK_FORMAT); } else if (strpos>0) { PRINTF("well_known_core_handler(): bufpos<=0\n"); coap_set_status_code(response, BAD_OPTION_4_02); coap_set_payload(response, "BlockOutOfScope", 15); } if (resource==NULL) { PRINTF("res: DONE\n"); *offset = -1; } else { PRINTF("res: MORE at %s (%p)\n", resource->url, resource); *offset += preferred_size; } }
/*---------------------------------------------------------------------------*/ void well_known_core_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { size_t strpos = 0; /* position in overall string (which is larger than the buffer) */ size_t bufpos = 0; /* position within buffer (bytes written) */ resource_t *resource = NULL; #if COAP_LINK_FORMAT_FILTERING /* For filtering. */ const char *filter = NULL; const char *attrib = NULL; const char *found = NULL; const char *end = NULL; char *value = NULL; char lastchar = '\0'; int len = coap_get_header_uri_query(request, &filter); if(len) { value = strchr(filter, '='); value[0] = '\0'; ++value; len -= strlen(filter) + 1; PRINTF("Filter %s = %.*s\n", filter, len, value); if(strcmp(filter, "href") == 0 && value[0] == '/') { ++value; --len; } lastchar = value[len - 1]; value[len - 1] = '\0'; } #endif for(resource = (resource_t *)list_head(rest_get_resources()); resource; resource = resource->next) { size_t tmplen = 0; #if COAP_LINK_FORMAT_FILTERING /* Filtering */ if(len) { if(strcmp(filter, "href") == 0) { attrib = strstr(resource->url, value); if(attrib == NULL || (value[-1] == '/' && attrib != resource->url)) { continue; } end = attrib + strlen(attrib); } else if(resource->attributes != NULL) { attrib = strstr(resource->attributes, filter); if(attrib == NULL || (attrib[strlen(filter)] != '=' && attrib[strlen(filter)] != '"')) { continue; } attrib += strlen(filter) + 2; end = strchr(attrib, '"'); } PRINTF("Filter: res has attrib %s (%s)\n", attrib, value); found = attrib; while((found = strstr(found, value)) != NULL) { if(found > end) { found = NULL; break; } if(lastchar == found[len - 1] || lastchar == '*') { break; } ++found; } if(found == NULL) { continue; } PRINTF("Filter: res has prefix %s\n", found); if(lastchar != '*' && (found[len] != '"' && found[len] != ' ' && found[len] != '\0')) { continue; } PRINTF("Filter: res has match\n"); } #endif PRINTF("res: /%s (%p)\npos: s%zu, o%ld, b%zu\n", resource->url, resource, strpos, (long)*offset, bufpos); if(strpos > 0) { ADD_CHAR_IF_POSSIBLE(','); } ADD_CHAR_IF_POSSIBLE('<'); ADD_CHAR_IF_POSSIBLE('/'); ADD_STRING_IF_POSSIBLE(resource->url, >=); ADD_CHAR_IF_POSSIBLE('>'); if(resource->attributes != NULL && resource->attributes[0]) { ADD_CHAR_IF_POSSIBLE(';'); ADD_STRING_IF_POSSIBLE(resource->attributes, >); } /* 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; } }
void 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 bufpos = 0; resource_t* resource = NULL; for (resource = (resource_t*)list_head(rest_get_resources()); resource; resource = resource->next) { strpos += snprintf((char *) buffer + bufpos, REST_MAX_CHUNK_SIZE - bufpos + 1, "</%s>%s%s%s", resource->url, resource->attributes[0] ? ";" : "", resource->attributes, resource->next ? "," : "" ); PRINTF("discover: %s\n", resource->url); if (strpos <= *offset) { /* Discard output before current block */ PRINTF(" if %d <= %ld B\n", strpos, *offset); PRINTF(" %s\n", buffer); bufpos = 0; } else /* (strpos > *offset) */ { /* output partly in block */ size_t len = MIN(strpos - *offset, preferred_size); PRINTF(" el %d/%d @ %ld B\n", len, preferred_size, *offset); /* Block might start in the middle of the output; align with buffer start. */ if (bufpos == 0) { memmove(buffer, buffer+strlen((char *)buffer)-strpos+*offset, len); } bufpos = len; PRINTF(" %s\n", buffer); if (bufpos >= preferred_size) { break; } } } if (bufpos>0) { coap_set_payload(response, buffer, bufpos ); coap_set_header_content_type(response, APPLICATION_LINK_FORMAT); } else { coap_set_rest_status(response, BAD_REQUEST_400); coap_set_payload(response, (uint8_t*)"Block out of scope", 18); } if (resource==NULL) { *offset = -1; } else { *offset += bufpos; } } }