Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: wakaama/packet.c
- Revision:
- 3:a280069151ac
- Parent:
- 0:f9d13e09cf11
- Child:
- 14:ec9e195830ff
--- a/wakaama/packet.c Fri Apr 28 09:53:26 2017 +0000 +++ b/wakaama/packet.c Fri Apr 28 18:13:27 2017 +0800 @@ -17,6 +17,8 @@ * Fabien Fleutot - Please refer to git log * Simon Bernard - Please refer to git log * Toby Jaffey - Please refer to git log + * Pascal Rieux - Please refer to git log + * Bosch Software Innovations GmbH - Please refer to git log * *******************************************************************************/ @@ -96,7 +98,8 @@ coap_packet_t * message) { #ifdef LWM2M_CLIENT_MODE - cancel_observe(contextP, message->mid, fromSessionH); + LOG("Entering"); + observe_cancel(contextP, message->mid, fromSessionH); #endif } @@ -106,42 +109,87 @@ coap_packet_t * response) { lwm2m_uri_t * uriP; - coap_status_t result = NOT_FOUND_4_04; + coap_status_t result = COAP_IGNORE; - uriP = lwm2m_decode_uri(message->uri_path); - if (uriP == NULL) return BAD_REQUEST_4_00; + LOG("Entering"); + +#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: - // TODO: Authentify server - result = handle_dm_request(contextP, uriP, fromSessionH, message, response); + { + 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: - result = NOT_IMPLEMENTED_5_01; + if (message->code == COAP_POST) + { + result = bootstrap_handleFinish(contextP, fromSessionH); + } break; #endif +#endif #ifdef LWM2M_SERVER_MODE - case LWM2M_URI_FLAG_REGISTRATION: - result = handle_registration_request(contextP, uriP, fromSessionH, message, response); + 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 = BAD_REQUEST_4_00; + result = COAP_IGNORE; break; } coap_set_status_code(response, result); - if (result < BAD_REQUEST_4_00) + if (COAP_IGNORE < result && result < COAP_400_BAD_REQUEST) { result = NO_ERROR; } - lwm2m_free( uriP); + lwm2m_free(uriP); return result; } @@ -158,29 +206,30 @@ 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) + if (coap_error_code == NO_ERROR) { - LOG(" Parsed: ver %u, type %u, tkl %u, code %u, mid %u\r\n", message->version, message->type, message->token_len, message->code, message->mid); - LOG(" Payload: %.*s\r\n\n", message->payload_len, message->payload); - + 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; - int32_t new_offset = 0; + int64_t new_offset = 0; /* prepare response */ - if (message->type==COAP_TYPE_CON) + if (message->type == COAP_TYPE_CON) { /* Reliable CON requests are answered with an ACK. */ - coap_init_message(response, COAP_TYPE_ACK, CONTENT_2_05, message->mid); + 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, CONTENT_2_05, contextP->nextMID++); + coap_init_message(response, COAP_TYPE_NON, COAP_205_CONTENT, contextP->nextMID++); } /* mirror token */ @@ -192,33 +241,76 @@ /* 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); + 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; } - coap_error_code = handle_request(contextP, fromSessionH, message, response); + /* 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) { - /* Apply blockwise transfers. */ - if ( IS_OPTION(message, COAP_OPTION_BLOCK1) && response->code<BAD_REQUEST_4_00 && !IS_OPTION(response, COAP_OPTION_BLOCK1) ) - { - LOG("Block1 NOT IMPLEMENTED\n"); - - coap_error_code = NOT_IMPLEMENTED_5_01; - coap_error_message = "NoBlock1Support"; - } - else if ( IS_OPTION(message, COAP_OPTION_BLOCK2) ) + 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); + 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\n"); + LOG("handle_incoming_data(): block_offset >= response->payload_len"); - response->code = BAD_OPTION_4_02; + response->code = COAP_402_BAD_OPTION; coap_set_payload(response, "BlockOutOfScope", 15); /* a const char str[] and sizeof(str) produces larger code size */ } else @@ -230,14 +322,14 @@ else { /* resource provides chunk-wise data */ - LOG("Blockwise: blockwise resource, new offset %d\n", new_offset); + 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("Blockwise: no block option for blockwise resource, using block size %u\n", REST_MAX_CHUNK_SIZE); + 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)); @@ -249,56 +341,68 @@ response->payload = NULL; response->payload_len = 0; } - else + else if (coap_error_code != COAP_IGNORE) { - coap_error_code = message_send(contextP, response, fromSessionH); + if (1 == coap_set_status_code(response, coap_error_code)) + { + coap_error_code = message_send(contextP, response, fromSessionH); + } } } else { /* Responses */ - lwm2m_transaction_t * transaction; - - if (message->type==COAP_TYPE_ACK) + switch (message->type) { - LOG("Received ACK\n"); - } - else if (message->type==COAP_TYPE_RST) - { - LOG("Received RST\n"); - /* Cancel possible subscriptions. */ - handle_reset(contextP, fromSessionH, message); - } + case COAP_TYPE_NON: + case COAP_TYPE_CON: + { + bool done = transaction_handleResponse(contextP, fromSessionH, message, response); #ifdef LWM2M_SERVER_MODE - if (message->code == COAP_204_CHANGED - && IS_OPTION(message, COAP_OPTION_OBSERVE)) - { - handle_observe_notify(contextP, fromSessionH, message); - } - else + 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 - { - transaction_handle_response(contextP, fromSessionH, message); + 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) */ else { - LOG("Message parsing failed %d\r\n", coap_error_code); + LOG_ARG("Message parsing failed %u.%2u", coap_error_code >> 5, coap_error_code & 0x1F); } - if (coap_error_code != NO_ERROR) + if (coap_error_code != NO_ERROR && coap_error_code != COAP_IGNORE) { - LOG("ERROR %u: %s\n", coap_error_code, coap_error_message); + LOG_ARG("ERROR %u: %s", coap_error_code, coap_error_message); /* Set to sendable error code. */ if (coap_error_code >= 192) { - coap_error_code = INTERNAL_SERVER_ERROR_5_00; + coap_error_code = COAP_500_INTERNAL_SERVER_ERROR; } /* Reuse input buffer for error message. */ coap_init_message(message, COAP_TYPE_ACK, coap_error_code, message->mid); @@ -312,14 +416,26 @@ coap_packet_t * message, void * sessionH) { - coap_status_t result = INTERNAL_SERVER_ERROR_5_00; - uint8_t pktBuffer[COAP_MAX_PACKET_SIZE+1]; + coap_status_t result = COAP_500_INTERNAL_SERVER_ERROR; + uint8_t * pktBuffer; size_t pktBufferLen = 0; + size_t allocLen; + + LOG("Entering"); + allocLen = coap_serialize_get_size(message); + LOG_ARG("Size to allocate: %d", allocLen); + if (allocLen == 0) return COAP_500_INTERNAL_SERVER_ERROR; - pktBufferLen = coap_serialize_message(message, pktBuffer); - if (0 != pktBufferLen) + pktBuffer = (uint8_t *)lwm2m_malloc(allocLen); + if (pktBuffer != NULL) { - result = contextP->bufferSendCallback(sessionH, pktBuffer, pktBufferLen, contextP->bufferSendUserData); + pktBufferLen = coap_serialize_message(message, pktBuffer); + LOG_ARG("coap_serialize_message() returned %d", pktBufferLen); + if (0 != pktBufferLen) + { + result = lwm2m_buffer_send(sessionH, pktBuffer, pktBufferLen, contextP->userData); + } + lwm2m_free(pktBuffer); } return result;