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;

#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;
    }
  }
static int coap_HandleRequest(void *packet, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
{
    int result = 1;
    const char *url = NULL;
    int urlLen = 0;
    const uint8_t * payload = NULL;
    int payloadLen = 0;
    int content = -1;

    coap_packet_t * const request = (coap_packet_t *) packet;

    CoapResponse coapResponse =
    { .responseContent = buffer, .responseContentLen = preferred_size, .responseCode = 400, };

    payloadLen = coap_get_payload(request, &payload);

    if ((urlLen = coap_get_header_uri_path(request, &url)))
    {
        char uriBuf[MAX_COAP_PATH] = { 0 };
        rest_resource_flags_t method = (rest_resource_flags_t) (1 << (((coap_packet_t *) packet)->code - 1)); //coap_get_rest_method(request);

        uriBuf[0] = '/';
        memcpy(&uriBuf[1], url, urlLen);

        char queryBuf[128] = "?";
        const char * query = NULL;

        int queryLength = coap_get_header_uri_query(request, &query);
        if (queryLength > 0)
            memcpy(&queryBuf[1], query, queryLength);

        queryBuf[queryLength+1] = '\0';

        CoapRequest coapRequest =
        { .ctxt = context, .addr =
        { 0 }, .path = uriBuf, .query = queryBuf, .token = request->token, .tokenLength = request->token_len, .requestContent = payload,
                .requestContentLen = payloadLen, };

        NetworkAddress_SetAddressType(sourceAddress, &coapRequest.addr);

        switch (method)
        {
        case METHOD_GET:

            coap_get_header_accept(request, &content);
            coapRequest.contentType = content;

            int32_t observe;

            if (!coap_get_header_observe(request, &observe))
                observe = -1;

            switch (observe)
            {
            case -1:
                Lwm2m_Debug("Coap GET for %s\n", uriBuf);
                coapRequest.type = COAP_GET_REQUEST;
                requestHandler(&coapRequest, &coapResponse);
                break;
            case 0:
                Lwm2m_Debug("Coap OBSERVE for %s\n", uriBuf);

                coapRequest.type = COAP_OBSERVE_REQUEST;
                requestHandler(&coapRequest, &coapResponse);
                coap_set_header_observe(response, 1);
                break;
            case 1:
                Lwm2m_Debug("Coap CANCEL OBSERVE for %s\n", uriBuf);

                coapRequest.type = COAP_CANCEL_OBSERVE_REQUEST;
                requestHandler(&coapRequest, &coapResponse);
                break;
            default:
                break;
            }
            coap_set_header_content_format(response, coapResponse.responseContentType); /* text/plain is the default, hence this option could be omitted. */
            break;

        case METHOD_POST:
            coap_get_header_content_format(request, &content);
            coapRequest.contentType = content;
            coapRequest.type = COAP_POST_REQUEST;
            Lwm2m_Debug("Coap POST for %s\n", uriBuf);
            requestHandler(&coapRequest, &coapResponse);
            if (coapResponse.responseContentLen > 0 && coapResponse.responseCode == 201)
            {
                coap_set_header_location_path(response, coapResponse.responseContent);
            }
            break;

        case METHOD_PUT:
            coap_get_header_content_format(request, &content);
            coapRequest.contentType = content;
            coapRequest.type = COAP_PUT_REQUEST;

            Lwm2m_Debug("Coap PUT for %s\n", uriBuf);
            requestHandler(&coapRequest, &coapResponse);
            break;

        case METHOD_DELETE:
            coapRequest.contentType = ContentType_None;
            coapRequest.type = COAP_DELETE_REQUEST;

            Lwm2m_Debug("Coap DELETE for %s\n", uriBuf);
            requestHandler(&coapRequest, &coapResponse);
            break;

        default:
            break;
        }

        if (coapResponse.responseContentLen > 0 && coapResponse.responseCode == 205)
        {
            coap_set_payload(response, coapResponse.responseContent, coapResponse.responseContentLen);
        }
    }

    coap_set_status_code(response, COAP_RESPONSE_CODE(coapResponse.responseCode));
    return result;
}