Esempio n. 1
0
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;
    }
}
Esempio n. 2
0
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;
    }
  }
}