Beispiel #1
0
static coap_status_t handle_request(lwm2m_context_t * contextP,
                                    void * fromSessionH,
                                    coap_packet_t * message,
                                    coap_packet_t * response)
{
    lwm2m_uri_t * uriP;
    coap_status_t result = NOT_FOUND_4_04;

    uriP = lwm2m_decode_uri(message->uri_path);
    if (uriP == NULL) return BAD_REQUEST_4_00;

    switch(uriP->flag & LWM2M_URI_MASK_TYPE)
    {
#ifdef LWM2M_CLIENT_MODE
    case LWM2M_URI_FLAG_DM:
        // TODO: Authentify server
        result = handle_dm_request(contextP, uriP, fromSessionH, message, response);
        break;

    case LWM2M_URI_FLAG_BOOTSTRAP:
        result = NOT_IMPLEMENTED_5_01;
        break;
#endif

#ifdef LWM2M_SERVER_MODE
   case LWM2M_URI_FLAG_REGISTRATION:
        result = handle_registration_request(contextP, uriP, fromSessionH, message, response);
        break;
#endif
    default:
        result = BAD_REQUEST_4_00;
        break;
    }

    coap_set_status_code(response, result);

    if (result < BAD_REQUEST_4_00)
    {
        result = NO_ERROR;
    }

    lwm2m_free( uriP);
    return result;
}
Beispiel #2
0
/**
 * \brief Block 1 support within a coap-ressource
 *
 *        This function will help you to use block 1. If target is null
 *        error handling and response configuration is active. On return
 *        value 0, the last block was recived, while on return value 1
 *        more blocks will follow. With target, len and maxlen this
 *        function will assemble the blocks.
 *
 *        You can find an example in:
 *        examples/er-rest-example/resources/res-b1-sep-b2.c
 *
 * \param request   Request pointer from the handler
 * \param response  Response pointer from the handler
 * \param target    Pointer to the buffer where the request payload can be assembled
 * \param len       Pointer to the variable, where the function stores the actual length
 * \param max_len   Length of the "target"-Buffer
 *
 * \return 0 if initialisation was successful
 *         -1 if initialisation failed
 */
int
coap_block1_handler(void *request, void *response, uint8_t *target, size_t *len, size_t max_len)
{
  const uint8_t *payload = 0;
  int pay_len = REST.get_request_payload(request, &payload);

  if(!pay_len || !payload) {
    erbium_status_code = REST.status.BAD_REQUEST;
    coap_error_message = "NoPayload";
    return -1;
  }

  coap_packet_t *packet = (coap_packet_t *)request;

  if(packet->block1_offset + pay_len > max_len) {
    erbium_status_code = REST.status.REQUEST_ENTITY_TOO_LARGE;
    coap_error_message = "Message to big";
    return -1;
  }

  if(target && len) {
    memcpy(target + packet->block1_offset, payload, pay_len);
    *len = packet->block1_offset + pay_len;
  }

  if(IS_OPTION(packet, COAP_OPTION_BLOCK1)) {
    PRINTF("Blockwise: block 1 request: Num: %u, More: %u, Size: %u, Offset: %u\n",
           packet->block1_num,
           packet->block1_more,
           packet->block1_size,
           packet->block1_offset);

    coap_set_header_block1(response, packet->block1_num, packet->block1_more, packet->block1_size);
    if(packet->block1_more) {
      coap_set_status_code(response, CONTINUE_2_31);
      return 1;
    }
  }

  return 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;
    }
}
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;
    }
}
Beispiel #5
0
/* This function is an adaptation of function coap_receive() from Erbium's er-coap-13-engine.c.
 * Erbium is Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
 * All rights reserved.
 */
void lwm2m_handle_packet(lwm2m_context_t * contextP,
                         uint8_t * buffer,
                         int length,
                         void * fromSessionH)
{
    uint8_t coap_error_code = NO_ERROR;
    static coap_packet_t message[1];
    static coap_packet_t response[1];

    LOG("Entering");
    coap_error_code = coap_parse_message(message, buffer, (uint16_t)length);
    if (coap_error_code == NO_ERROR)
    {
        LOG_ARG("Parsed: ver %u, type %u, tkl %u, code %u.%.2u, mid %u, Content type: %d",
                message->version, message->type, message->token_len, message->code >> 5, message->code & 0x1F, message->mid, message->content_type);
        LOG_ARG("Payload: %.*s", message->payload_len, message->payload);
        if (message->code >= COAP_GET && message->code <= COAP_DELETE)
        {
            uint32_t block_num = 0;
            uint16_t block_size = REST_MAX_CHUNK_SIZE;
            uint32_t block_offset = 0;
            int64_t new_offset = 0;

            /* prepare response */
            if (message->type == COAP_TYPE_CON)
            {
                /* Reliable CON requests are answered with an ACK. */
                coap_init_message(response, COAP_TYPE_ACK, COAP_205_CONTENT, message->mid);
            }
            else
            {
                /* Unreliable NON requests are answered with a NON as well. */
                coap_init_message(response, COAP_TYPE_NON, COAP_205_CONTENT, contextP->nextMID++);
            }

            /* mirror token */
            if (message->token_len)
            {
                coap_set_header_token(response, message->token, message->token_len);
            }

            /* get offset for blockwise transfers */
            if (coap_get_header_block2(message, &block_num, NULL, &block_size, &block_offset))
            {
                LOG_ARG("Blockwise: block request %u (%u/%u) @ %u bytes", block_num, block_size, REST_MAX_CHUNK_SIZE, block_offset);
                block_size = MIN(block_size, REST_MAX_CHUNK_SIZE);
                new_offset = block_offset;
            }

            /* handle block1 option */
            if (IS_OPTION(message, COAP_OPTION_BLOCK1))
            {
#ifdef LWM2M_CLIENT_MODE
                // get server
                lwm2m_server_t * serverP;
                serverP = utils_findServer(contextP, fromSessionH);
#ifdef LWM2M_BOOTSTRAP
                if (serverP == NULL)
                {
                    serverP = utils_findBootstrapServer(contextP, fromSessionH);
                }
#endif
                if (serverP == NULL)
                {
                    coap_error_code = COAP_500_INTERNAL_SERVER_ERROR;
                }
                else
                {
                    uint32_t block1_num;
                    uint8_t  block1_more;
                    uint16_t block1_size;
                    uint8_t * complete_buffer = NULL;
                    size_t complete_buffer_size;

                    // parse block1 header
                    coap_get_header_block1(message, &block1_num, &block1_more, &block1_size, NULL);
                    LOG_ARG("Blockwise: block1 request NUM %u (SZX %u/ SZX Max%u) MORE %u", block1_num, block1_size, REST_MAX_CHUNK_SIZE, block1_more);

                    // handle block 1
                    coap_error_code = coap_block1_handler(&serverP->block1Data, message->mid, message->payload, message->payload_len, block1_size, block1_num, block1_more, &complete_buffer, &complete_buffer_size);

                    // if payload is complete, replace it in the coap message.
                    if (coap_error_code == NO_ERROR)
                    {
                        message->payload = complete_buffer;
                        message->payload_len = complete_buffer_size;
                    }
                    else if (coap_error_code == COAP_231_CONTINUE)
                    {
                        block1_size = MIN(block1_size, REST_MAX_CHUNK_SIZE);
                        coap_set_header_block1(response,block1_num, block1_more,block1_size);
                    }
                }
#else
                coap_error_code = COAP_501_NOT_IMPLEMENTED;
#endif
            }
            if (coap_error_code == NO_ERROR)
            {
                coap_error_code = handle_request(contextP, fromSessionH, message, response);
            }
            if (coap_error_code==NO_ERROR)
            {
                /* Save original payload pointer for later freeing. Payload in response may be updated. */
                uint8_t *payload = response->payload;
                if ( IS_OPTION(message, COAP_OPTION_BLOCK2) )
                {
                    /* unchanged new_offset indicates that resource is unaware of blockwise transfer */
                    if (new_offset==block_offset)
                    {
                        LOG_ARG("Blockwise: unaware resource with payload length %u/%u", response->payload_len, block_size);
                        if (block_offset >= response->payload_len)
                        {
                            LOG("handle_incoming_data(): block_offset >= response->payload_len");

                            response->code = COAP_402_BAD_OPTION;
                            coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */
                        }
                        else
                        {
                            coap_set_header_block2(response, block_num, response->payload_len - block_offset > block_size, block_size);
                            coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size));
                        } /* if (valid offset) */
                    }
                    else
                    {
                        /* resource provides chunk-wise data */
                        LOG_ARG("Blockwise: blockwise resource, new offset %d", (int) new_offset);
                        coap_set_header_block2(response, block_num, new_offset!=-1 || response->payload_len > block_size, block_size);
                        if (response->payload_len > block_size) coap_set_payload(response, response->payload, block_size);
                    } /* if (resource aware of blockwise) */
                }
                else if (new_offset!=0)
                {
                    LOG_ARG("Blockwise: no block option for blockwise resource, using block size %u", REST_MAX_CHUNK_SIZE);

                    coap_set_header_block2(response, 0, new_offset!=-1, REST_MAX_CHUNK_SIZE);
                    coap_set_payload(response, response->payload, MIN(response->payload_len, REST_MAX_CHUNK_SIZE));
                } /* if (blockwise request) */

                coap_error_code = message_send(contextP, response, fromSessionH);

                lwm2m_free(payload);
                response->payload = NULL;
                response->payload_len = 0;
            }
            else if (coap_error_code != COAP_IGNORE)
            {
                if (1 == coap_set_status_code(response, coap_error_code))
                {
                    coap_error_code = message_send(contextP, response, fromSessionH);
                }
            }
        }
        else
        {
            /* Responses */
            switch (message->type)
            {
            case COAP_TYPE_NON:
            case COAP_TYPE_CON:
                {
                    bool done = transaction_handleResponse(contextP, fromSessionH, message, response);

#ifdef LWM2M_SERVER_MODE
                    if (!done && IS_OPTION(message, COAP_OPTION_OBSERVE) &&
                        ((message->code == COAP_204_CHANGED) || (message->code == COAP_205_CONTENT)))
                    {
                        done = observe_handleNotify(contextP, fromSessionH, message, response);
                    }
#endif
                    if (!done && message->type == COAP_TYPE_CON )
                    {
                        coap_init_message(response, COAP_TYPE_ACK, 0, message->mid);
                        coap_error_code = message_send(contextP, response, fromSessionH);
                    }
                }
                break;

            case COAP_TYPE_RST:
                /* Cancel possible subscriptions. */
                handle_reset(contextP, fromSessionH, message);
                transaction_handleResponse(contextP, fromSessionH, message, NULL);
                break;

            case COAP_TYPE_ACK:
                transaction_handleResponse(contextP, fromSessionH, message, NULL);
                break;

            default:
                break;
            }
        } /* Request or Response */
        coap_free_header(message);
    } /* if (parsed correctly) */
Beispiel #6
0
static uint8_t handle_request(lwm2m_context_t * contextP,
                              void * fromSessionH,
                              coap_packet_t * message,
                              coap_packet_t * response)
{
    lwm2m_uri_t uri;
    lwm2m_request_type_t requestType;
    uint8_t result = COAP_IGNORE;

    LOG("Entering");
	
#ifdef LWM2M_CLIENT_MODE
    requestType = uri_decode(contextP->altPath, message->uri_path, &uri);
#else
    requestType = uri_decode(NULL, message->uri_path, &uri);
#endif

    switch(requestType)
    {
    case LWM2M_REQUEST_TYPE_UNKNOWN:
        return COAP_400_BAD_REQUEST;

#ifdef LWM2M_CLIENT_MODE
    case LWM2M_REQUEST_TYPE_DM:
    {
        lwm2m_server_t * serverP;

        serverP = utils_findServer(contextP, fromSessionH);
        if (serverP != NULL)
        {
            result = dm_handleRequest(contextP, &uri, serverP, message, response);
        }
#ifdef LWM2M_BOOTSTRAP
        else
        {
            serverP = utils_findBootstrapServer(contextP, fromSessionH);
            if (serverP != NULL)
            {
                result = bootstrap_handleCommand(contextP, &uri, serverP, message, response);
            }
        }
#endif
    }
    break;

#ifdef LWM2M_BOOTSTRAP
    case LWM2M_REQUEST_TYPE_DELETE_ALL:
        if (COAP_DELETE != message->code)
        {
            result = COAP_400_BAD_REQUEST;
        }
        else
        {
            result = bootstrap_handleDeleteAll(contextP, fromSessionH);
        }
        break;

    case LWM2M_REQUEST_TYPE_BOOTSTRAP:
        if (message->code == COAP_POST)
        {
            result = bootstrap_handleFinish(contextP, fromSessionH);
        }
        break;
#endif
#endif

#ifdef LWM2M_SERVER_MODE
    case LWM2M_REQUEST_TYPE_REGISTRATION:
        result = registration_handleRequest(contextP, &uri, fromSessionH, message, response);
        break;
#endif
#ifdef LWM2M_BOOTSTRAP_SERVER_MODE
    case LWM2M_REQUEST_TYPE_BOOTSTRAP:
        result = bootstrap_handleRequest(contextP, &uri, fromSessionH, message, response);
        break;
#endif
    default:
        result = COAP_IGNORE;
        break;
    }

    coap_set_status_code(response, result);

    if (COAP_IGNORE < result && result < COAP_400_BAD_REQUEST)
    {
        result = NO_ERROR;
    }

    return result;
}
Beispiel #7
0
/* This function is an adaptation of function coap_receive() from Erbium's er-coap-13-engine.c.
 * Erbium is Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
 * All rights reserved.
 */
void lwm2m_handle_packet(lwm2m_context_t * contextP,
                        uint8_t * buffer,
                        int length,
                        void * fromSessionH)
{
    coap_status_t coap_error_code = NO_ERROR;
    static coap_packet_t message[1];
    static coap_packet_t response[1];

    coap_error_code = coap_parse_message(message, buffer, (uint16_t)length);

    if (message[0].uri_path && message[0].uri_path->next &&
            (message[0].uri_path->next->is_static != 0 && message[0].uri_path->next->is_static != 1)) {
        printf("BLA\n");
    }

    if (coap_error_code == NO_ERROR)
    {
        LOG("  Parsed: ver %u, type %u, tkl %u, code %u.%.2u, mid %u\r\n", message->version, message->type, message->token_len, message->code >> 5, message->code & 0x1F, message->mid);
        LOG("  Content type: %d\r\n  Payload: %.*s\r\n\n", message->content_type, message->payload_len, message->payload);
        if (message->code >= COAP_GET && message->code <= COAP_DELETE)
        {
            uint32_t block_num = 0;
            uint16_t block_size = REST_MAX_CHUNK_SIZE;
            uint32_t block_offset = 0;
            int64_t new_offset = 0;

            /* prepare response */
            if (message->type == COAP_TYPE_CON)
            {
                /* Reliable CON requests are answered with an ACK. */
                coap_init_message(response, COAP_TYPE_ACK, COAP_205_CONTENT, message->mid);
            }
            else
            {
                /* Unreliable NON requests are answered with a NON as well. */
                coap_init_message(response, COAP_TYPE_NON, COAP_205_CONTENT, contextP->nextMID++);
            }

            /* mirror token */
            if (message->token_len)
            {
                coap_set_header_token(response, message->token, message->token_len);
            }

            /* get offset for blockwise transfers */
            if (coap_get_header_block2(message, &block_num, NULL, &block_size, &block_offset))
            {
                LOG("Blockwise: block request %u (%u/%u) @ %u bytes\n", block_num, block_size, REST_MAX_CHUNK_SIZE, block_offset);
                block_size = MIN(block_size, REST_MAX_CHUNK_SIZE);
                new_offset = block_offset;
            }

            coap_error_code = handle_request(contextP, fromSessionH, message, response);
            if (coap_error_code==NO_ERROR)
            {
                /* Apply blockwise transfers. */
                if ( IS_OPTION(message, COAP_OPTION_BLOCK1) && response->code<COAP_400_BAD_REQUEST && !IS_OPTION(response, COAP_OPTION_BLOCK1) )
                {
                    LOG("Block1 NOT IMPLEMENTED\n");

                    coap_error_code = COAP_501_NOT_IMPLEMENTED;
                    coap_error_message = "NoBlock1Support";
                }
                else if ( IS_OPTION(message, COAP_OPTION_BLOCK2) )
                {
                    /* unchanged new_offset indicates that resource is unaware of blockwise transfer */
                    if (new_offset==block_offset)
                    {
                        LOG("Blockwise: unaware resource with payload length %u/%u\n", response->payload_len, block_size);
                        if (block_offset >= response->payload_len)
                        {
                            LOG("handle_incoming_data(): block_offset >= response->payload_len\n");

                            response->code = COAP_402_BAD_OPTION;
                            coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */
                        }
                        else
                        {
                            coap_set_header_block2(response, block_num, response->payload_len - block_offset > block_size, block_size);
                            coap_set_payload(response, response->payload+block_offset, MIN(response->payload_len - block_offset, block_size));
                        } /* if (valid offset) */
                    }
                    else
                    {
                        /* resource provides chunk-wise data */
                        LOG("Blockwise: blockwise resource, new offset %d\n", (int) new_offset);
                        coap_set_header_block2(response, block_num, new_offset!=-1 || response->payload_len > block_size, block_size);
                        if (response->payload_len > block_size) coap_set_payload(response, response->payload, block_size);
                    } /* if (resource aware of blockwise) */
                }
                else if (new_offset!=0)
                {
                    LOG("Blockwise: no block option for blockwise resource, using block size %u\n", REST_MAX_CHUNK_SIZE);

                    coap_set_header_block2(response, 0, new_offset!=-1, REST_MAX_CHUNK_SIZE);
                    coap_set_payload(response, response->payload, MIN(response->payload_len, REST_MAX_CHUNK_SIZE));
                } /* if (blockwise request) */

                coap_error_code = message_send(contextP, response, fromSessionH);

                lwm2m_free(response->payload);
                response->payload = NULL;
                response->payload_len = 0;
            }
            else if (coap_error_code != COAP_IGNORE)
            {
                if (1 == coap_set_status_code(response, coap_error_code))
                {
                    coap_error_code = message_send(contextP, response, fromSessionH);
                }
            }
        }
        else
        {
            /* Responses */
            switch (message->type)
            {
            case COAP_TYPE_NON:
            case COAP_TYPE_CON:
                {
                    bool done = transaction_handleResponse(contextP, fromSessionH, message, response);

#ifdef LWM2M_SERVER_MODE
                    if (!done && IS_OPTION(message, COAP_OPTION_OBSERVE) &&
                        ((message->code == COAP_204_CHANGED) || (message->code == COAP_205_CONTENT)))
                    {
                        done = observe_handleNotify(contextP, fromSessionH, message, response);
                    }
#endif
                    if (!done && message->type == COAP_TYPE_CON )
                    {
                        coap_init_message(response, COAP_TYPE_ACK, 0, message->mid);
                        coap_error_code = message_send(contextP, response, fromSessionH);
                    }
                }
                break;

            case COAP_TYPE_RST:
                /* Cancel possible subscriptions. */
                handle_reset(contextP, fromSessionH, message);
                transaction_handleResponse(contextP, fromSessionH, message, NULL);
                break;

            case COAP_TYPE_ACK:
                transaction_handleResponse(contextP, fromSessionH, message, NULL);
                break;

            default:
                break;
            }
        } /* Request or Response */
        coap_free_header(message);
    } /* if (parsed correctly) */
Beispiel #8
0
static coap_status_t handle_request(lwm2m_context_t * contextP,
                                    void * fromSessionH,
                                    coap_packet_t * message,
                                    coap_packet_t * response)
{
    lwm2m_uri_t * uriP;
    coap_status_t result = COAP_IGNORE;

#ifdef LWM2M_CLIENT_MODE
    uriP = uri_decode(contextP->altPath, message->uri_path);
#else
    uriP = uri_decode(NULL, message->uri_path);
#endif

    if (uriP == NULL) return COAP_400_BAD_REQUEST;

    switch(uriP->flag & LWM2M_URI_MASK_TYPE)
    {
#ifdef LWM2M_CLIENT_MODE
    case LWM2M_URI_FLAG_DM:
    {
        lwm2m_server_t * serverP;

        serverP = utils_findServer(contextP, fromSessionH);
        if (serverP != NULL)
        {
            result = dm_handleRequest(contextP, uriP, serverP, message, response);
        }
#ifdef LWM2M_BOOTSTRAP
        else
        {
            serverP = utils_findBootstrapServer(contextP, fromSessionH);
            if (serverP != NULL)
            {
                result = bootstrap_handleCommand(contextP, uriP, serverP, message, response);
            }
        }
#endif
    }
    break;

#ifdef LWM2M_BOOTSTRAP
    case LWM2M_URI_FLAG_DELETE_ALL:
        if (COAP_DELETE != message->code)
        {
            result = COAP_400_BAD_REQUEST;
        }
        else
        {
            result = bootstrap_handleDeleteAll(contextP, fromSessionH);
        }
        break;

    case LWM2M_URI_FLAG_BOOTSTRAP:
        if (message->code == COAP_POST)
        {
            result = bootstrap_handleFinish(contextP, fromSessionH);
        }
        break;
#endif
#endif

#ifdef LWM2M_SERVER_MODE
    case LWM2M_URI_FLAG_REGISTRATION:
        result = registration_handleRequest(contextP, uriP, fromSessionH, message, response);
        break;
#endif
#ifdef LWM2M_BOOTSTRAP_SERVER_MODE
    case LWM2M_URI_FLAG_BOOTSTRAP:
        result = bootstrap_handleRequest(contextP, uriP, fromSessionH, message, response);
        break;
#endif
    default:
        result = COAP_IGNORE;
        break;
    }

    coap_set_status_code(response, result);

    if (COAP_IGNORE < result && result < COAP_400_BAD_REQUEST)
    {
        result = NO_ERROR;
    }

    lwm2m_free(uriP);
    return result;
}
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;
}
Beispiel #10
0
void device_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) {
    const char *uri_path = NULL;
    uint8_t uri_len = REST.get_url(request, &uri_path);

    if (uri_len == 1) {
        if (*offset >= LEN_D_CORE) {
            coap_set_status_code(response, BAD_OPTION_4_02);
            coap_set_payload(response, "BlockOutOfScope", 15);
            return;
        }

        flash_getVar(buffer, RES_D_CORE + *offset, preferred_size);
        if (LEN_D_CORE - *offset < preferred_size) {
            preferred_size = LEN_D_CORE - *offset;
            *offset = -1;
        } else {
            *offset += preferred_size;
        }

        REST.set_header_content_type(response, APPLICATION_LINK_FORMAT);
        REST.set_response_payload(response, buffer, preferred_size);
        return;
    }

    //*************************************************************************
    //*  DEVICE NAME                                                          *
    //*************************************************************************
    if (uri_path[2] == 'n' && uri_path[3] == 'a') {
        flash_getVar(buffer, RES_NAME, LEN_NAME);
        REST.set_header_content_type(response, TEXT_PLAIN);
        REST.set_response_payload(response, buffer, strlen(buffer));
    }

    //*************************************************************************
    //*  DEVICE MODEL                                                         *
    //*************************************************************************
    if (uri_path[2] == 'm') {
        flash_getVar(buffer, RES_MODEL, LEN_MODEL);
        REST.set_header_content_type(response, TEXT_PLAIN);
        REST.set_response_payload(response, buffer, strlen(buffer));
        return;
    }

    //*************************************************************************
    //*  DEVICE IDENTIFIER                                                    *
    //*************************************************************************
    if (uri_path[2] == 'u') {
        leds_on(LEDS_GREEN);
        send_hello = 0;

        flash_getVar(buffer, RES_UUID, LEN_UUID);
        REST.set_header_content_type(response, APPLICATION_OCTET_STREAM);
        REST.set_response_payload(response, buffer, LEN_UUID);
    }

    //*************************************************************************
    //*  DEVICE TIME                                                          *
    //*************************************************************************
    if (uri_path[2] == 't') {
        uint32_t time = uip_htonl(clock_seconds());
        memcpy(buffer, &time, 4);
        REST.set_header_content_type(response, APPLICATION_OCTET_STREAM);
        REST.set_response_payload(response, buffer, 4);
    }

    //*************************************************************************
    //*  DEVICE PSK                                                           *
    //*************************************************************************
    if (uri_path[2] == 'p') {
        getPSK(buffer);
        REST.set_header_content_type(response, APPLICATION_OCTET_STREAM);
        REST.set_response_payload(response, buffer, LEN_PSK);
    }

    //*************************************************************************
    //*  DEVICE DEFAULT ROUTE                                                 *
    //*************************************************************************
    if (uri_path[2] == 'r') {
        uip_ipaddr_t *addr = uip_ds6_defrt_choose();
        memcpy(buffer, addr, 16);
        REST.set_header_content_type(response, APPLICATION_OCTET_STREAM);
        REST.set_response_payload(response, buffer, 16);
    }

    //*************************************************************************
    //*  DEVICE NEIGHBOURS                                                    *
    //*************************************************************************
    if (uri_path[2] == 'n' && uri_path[3] == 'b') {
        uint32_t o = *offset / 16;
        uint32_t bfr_ptr = 0;
        uint32_t i;
        uip_ds6_nbr_t *nbr = nbr_table_head(ds6_neighbors);
        for (i = 0; i < (o+2); i++) {
            if (i >= o) {
                memcpy(buffer + bfr_ptr, &nbr->ipaddr, 16);
                bfr_ptr += 16;
            }

            nbr = nbr_table_next(ds6_neighbors, nbr);
            if (nbr == NULL) {
                if (bfr_ptr == 0) {
                  coap_set_status_code(response, BAD_OPTION_4_02);
                  coap_set_payload(response, "BlockOutOfScope", 15);
                  return;
                }
                break;
            }
        }
        if (nbr == NULL) {
            *offset = -1;
        } else {
           *offset += bfr_ptr;
        }
        REST.set_header_content_type(response, APPLICATION_OCTET_STREAM);
        REST.set_response_payload(response, buffer, bfr_ptr);
    }
}