Beispiel #1
0
int
rest_get_query_variable(REQUEST* request, const char *name, char* output, uint16_t output_size)
{
#ifdef WITH_COAP
  return coap_get_query_variable(request, name, output, output_size);
#else
  return http_get_query_variable(request, name, output, output_size);
#endif /*WITH_COAP*/
}
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;
    }
}