Skip to content

Commit

Permalink
Add API to send response to request based on Message ID (ARMmbed#78)
Browse files Browse the repository at this point in the history
API to send response to request, using request's message ID as a identifier.
  • Loading branch information
Tero Heinonen authored Nov 1, 2017
1 parent 58f0ed5 commit adc04c4
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 48 deletions.
74 changes: 44 additions & 30 deletions coap-service/coap_service_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ extern const uint8_t COAP_MULTICAST_ADDR_SITE_LOCAL[16]; //!> ff05::fd, COAP sit
*
* Function that handles CoAP service message receiving and parsing
*
* \param msg_id Id number of the current message.
* \param service_id Service handle.
* \param source_address IPv6 source address.
* \param source_port Source port
* \param source_port Source port.
* \param response_ptr Pointer to CoAP header structure.
*
* \return 0 for success / -1 for failure
Expand All @@ -85,7 +85,7 @@ typedef int coap_service_response_recv(int8_t service_id, uint8_t source_address
*
* \param service_id Id number of the current service.
* \param source_address IPv6 source address.
* \param source_port Source port
* \param source_port Source port.
* \param request_ptr Pointer to CoAP header structure.
*
* \return Status
Expand All @@ -98,8 +98,10 @@ typedef int coap_service_request_recv_cb(int8_t service_id, uint8_t source_addre
* Starts security service handling and fetches device password.
*
* \param service_id Id number of the current service.
* \param address Address of sender
* \param port Port of the device
* \param address Address of sender.
* \param port Port of the device.
* \param pw Pointer where to write the ecjpake password.
* \param pw_len Pointer where to write length of the ecjpake password.
*
* \return 0 for success / -1 for failure
*/
Expand All @@ -111,8 +113,8 @@ typedef int coap_service_security_start_cb(int8_t service_id, uint8_t address[st
* CoAP service security done callback function.
*
* \param service_id Id number of the current service.
* \param address Address of sender
* \param keyblock Security key (40 bits)
* \param address Address of sender.
* \param keyblock Security key (40 bits).
*
* \return 0 for success / -1 for failure
*/
Expand Down Expand Up @@ -147,23 +149,12 @@ extern void coap_service_delete( int8_t service_id );
*
* Closes secure connection (if present), but leaves socket open.
*
* \param service_id Id number of the current service.
* \param service_id Id number of the current service.
* \param destimation_addr_ptr Connection destination address.
* \param port Connection destination port.
*/
extern void coap_service_close_secure_connection(int8_t service_id, uint8_t destination_addr_ptr[static 16], uint16_t port);

/**
* \brief Sets password for device
*
* \param service_id Service id
* \param address Device address
* \param port Device port
* \param pw_ptr Pointer to password.
* \param pw_len Lenght of password.
*
* \return 0 for success / -1 for failure
*/
//int coap_service_security_key_set(int8_t service_id, uint8_t address[static 16], uint16_t port, uint8_t *pw_ptr, uint8_t pw_len);

/**
* \brief Virtual socket sent callback.
*
Expand Down Expand Up @@ -213,7 +204,6 @@ extern int16_t coap_service_virtual_socket_set_cb(int8_t service_id, coap_servic
*
* \param service_id Id number of the current service.
* \param *uri Uri address.
* \param port port that Application wants to use for communicate with coap server.
* \param allowed_method Informs method that is allowed to use (used defines described above).
* \param *request_recv_cb CoAP service request receive callback function pointer.
*
Expand All @@ -240,7 +230,7 @@ extern int8_t coap_service_unregister_uri(int8_t service_id, const char *uri);
*
* \param service_id Id number of the current service.
* \param options Options defined above.
* \param destination_addr IPv6 address.
* \param destination_addr IPv6 address.
* \param destination_port Destination port
* \param msg_type Message type can be found from sn_coap_header.
* \param msg_code Message code can be found from sn_coap_header.
Expand All @@ -261,15 +251,39 @@ extern uint16_t coap_service_request_send(int8_t service_id, uint8_t options, co
* Build and sends CoAP service response message.
*
* \param service_id Id number of the current service.
* \param msg_id Message ID number.
* \param options Options defined above.
* \param response_ptr Pointer to CoAP header structure.
* \param request_ptr Pointer to CoAP request message header structure.
* \param message_code Message code can be found from sn_coap_header.
* \param content_type Content type can be found from sn_coap_header.
* \param payload_ptr Pointer to message content.
* \param payload_len Lenght of the message.
*
* \return -1 For failure
*- 0 For success
*/
extern int8_t coap_service_response_send(int8_t service_id, uint8_t options, sn_coap_hdr_s *request_ptr, sn_coap_msg_code_e message_code, sn_coap_content_format_e content_type, const uint8_t *payload_ptr,uint16_t payload_len);

/**
* \brief Sends CoAP service response
*
* Build and sends CoAP service response message based on CoAP request message id.
*
* \param service_id Id number of the current service.
* \param options Options defined above.
* \param msg_id Request messages ID.
* \param msg_type Message type can be found from sn_coap_header.
* \param message_code Message code can be found from sn_coap_header.
* \param content_type Content type can be found from sn_coap_header.
* \param payload_ptr Pointer to message content.
* \param payload_len Lenght of the message.
*
* \return -1 For failure
*- 0 For success
*/
extern int8_t coap_service_response_send_by_msg_id(int8_t service_id, uint8_t options, uint16_t msg_id, sn_coap_msg_code_e message_code, sn_coap_content_format_e content_type, const uint8_t *payload_ptr,uint16_t payload_len);



/**
* \brief Delete CoAP request transaction
*
Expand Down Expand Up @@ -316,7 +330,7 @@ extern int8_t coap_service_handshake_limits_set(uint8_t handshakes_max, uint8_t
* Configures the CoAP duplication message buffer size.
*
* \param service_id Id number of the current service.
* \param size Buffer size (messages)
* \param size Buffer size (messages).
*
* \return -1 For failure
*- 0 For success
Expand All @@ -329,10 +343,10 @@ extern int8_t coap_service_set_duplicate_message_buffer(int8_t service_id, uint8
* Set DTLS certificates.
*
* \param service_id Id number of the current service.
* \param cert Pointer to certificate chain
* \param cert_len Certificate length
* \param priv_key pointer to private key
* \param priv_key_len length of private key
* \param cert Pointer to certificate chain.
* \param cert_len Certificate length.
* \param priv_key pointer to private key.
* \param priv_key_len length of private key.
*
* \return -1 For failure
*- 0 For success
Expand Down
87 changes: 69 additions & 18 deletions source/coap_message_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,18 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
transaction_ptr->service_id = coap_service_id_find_by_socket(socket_id);
transaction_ptr->msg_id = coap_message->msg_id;
transaction_ptr->client_request = false;// this is server transaction
transaction_ptr->req_msg_type = coap_message->msg_type;
memcpy(transaction_ptr->local_address, *(dst_addr_ptr) == 0xFF ? ns_in6addr_any : dst_addr_ptr, 16);
memcpy(transaction_ptr->remote_address, source_addr_ptr, 16);
if (coap_message->token_len) {
memcpy(transaction_ptr->token, coap_message->token_ptr, coap_message->token_len);
}
transaction_ptr->remote_port = port;

int ret = cb(socket_id, coap_message, transaction_ptr);
if (ret != 0) {
tr_debug("Service %d, no response expected", transaction_ptr->service_id);
sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message);
transaction_delete(transaction_ptr);
return -1;
}
} else {
Expand Down Expand Up @@ -358,13 +361,37 @@ uint16_t coap_message_handler_request_send(coap_msg_handler_t *handle, int8_t se
return transaction_ptr->msg_id;
}

int8_t coap_message_handler_response_send(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, sn_coap_hdr_s *request_ptr, sn_coap_msg_code_e message_code, sn_coap_content_format_e content_type, const uint8_t *payload_ptr, uint16_t payload_len)
static int8_t coap_message_handler_resp_build_and_send(coap_msg_handler_t *handle, sn_coap_hdr_s *coap_msg_ptr, coap_transaction_t *transaction_ptr)
{
coap_transaction_t *transaction_ptr;
sn_coap_hdr_s *response;
sn_nsdl_addr_s dst_addr;
uint16_t data_len;
uint8_t *data_ptr;


dst_addr.addr_ptr = transaction_ptr->remote_address;
dst_addr.addr_len = 16;
dst_addr.type = SN_NSDL_ADDRESS_TYPE_IPV6;
dst_addr.port = transaction_ptr->remote_port;

data_len = sn_coap_builder_calc_needed_packet_data_size(coap_msg_ptr);
data_ptr = own_alloc(data_len);
if (data_len > 0 && !data_ptr) {
return -1;
}
sn_coap_protocol_build(handle->coap, &dst_addr, data_ptr, coap_msg_ptr, transaction_ptr);

handle->sn_coap_tx_callback(data_ptr, data_len, &dst_addr, transaction_ptr);
own_free(data_ptr);

return 0;

}

int8_t coap_message_handler_response_send(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, sn_coap_hdr_s *request_ptr, sn_coap_msg_code_e message_code, sn_coap_content_format_e content_type, const uint8_t *payload_ptr, uint16_t payload_len)
{
sn_coap_hdr_s *response;
coap_transaction_t *transaction_ptr;
int8_t ret_val = 0;
(void) options;
(void)service_id;

Expand All @@ -380,10 +407,6 @@ int8_t coap_message_handler_response_send(coap_msg_handler_t *handle, int8_t ser
tr_error("response transaction not found");
return -2;
}
dst_addr.addr_ptr = transaction_ptr->remote_address;
dst_addr.addr_len = 16;
dst_addr.type = SN_NSDL_ADDRESS_TYPE_IPV6;
dst_addr.port = transaction_ptr->remote_port;

response = sn_coap_build_response(handle->coap, request_ptr, message_code);
if( !response ){
Expand All @@ -393,18 +416,46 @@ int8_t coap_message_handler_response_send(coap_msg_handler_t *handle, int8_t ser
response->payload_ptr = (uint8_t *) payload_ptr; // Cast away const and trust that nsdl doesn't modify...
response->content_format = content_type;

data_len = sn_coap_builder_calc_needed_packet_data_size(response);
data_ptr = own_alloc(data_len);
if (data_len > 0 && !data_ptr) {
sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response);

ret_val = coap_message_handler_resp_build_and_send(handle, response, transaction_ptr);
sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response);
if (ret_val == 0) {
sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, request_ptr);
}

return ret_val;
}

int8_t coap_message_handler_response_send_by_msg_id(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, uint16_t msg_id, sn_coap_msg_code_e message_code, sn_coap_content_format_e content_type, const uint8_t *payload_ptr,uint16_t payload_len)
{
sn_coap_hdr_s response;
coap_transaction_t *transaction_ptr;
(void) options;
(void)service_id;

transaction_ptr = transaction_find_server(msg_id);
if (!transaction_ptr || !handle) {
return -1;
}
sn_coap_protocol_build(handle->coap, &dst_addr, data_ptr, response, transaction_ptr);
sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response);
handle->sn_coap_tx_callback(data_ptr, data_len, &dst_addr, transaction_ptr);
sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, request_ptr);
own_free(data_ptr);
return 0;

tr_debug("Service %d, send CoAP response", service_id);

memset(&response, 0, sizeof(sn_coap_hdr_s));

response.payload_len = payload_len;
response.payload_ptr = (uint8_t *) payload_ptr; // Cast away const and trust that nsdl doesn't modify...
response.content_format = content_type;
response.token_len = 4;
response.token_ptr = transaction_ptr->token;
response.msg_code = message_code;
if (transaction_ptr->req_msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
response.msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
response.msg_id = msg_id;
} else {
response.msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE;
}

return coap_message_handler_resp_build_and_send(handle, &response, transaction_ptr);
}

int8_t coap_message_handler_request_delete(coap_msg_handler_t *handle, int8_t service_id, uint16_t msg_id)
Expand Down
4 changes: 4 additions & 0 deletions source/coap_service_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,10 @@ int8_t coap_service_response_send(int8_t service_id, uint8_t options, sn_coap_hd
return coap_message_handler_response_send(coap_service_handle, service_id, options, request_ptr, message_code, content_type, payload_ptr, payload_len);
}

int8_t coap_service_response_send_by_msg_id(int8_t service_id, uint8_t options, uint16_t msg_id, sn_coap_msg_code_e message_code, sn_coap_content_format_e content_type, const uint8_t *payload_ptr,uint16_t payload_len) {
return coap_message_handler_response_send_by_msg_id(coap_service_handle, service_id, options, msg_id, message_code, content_type, payload_ptr, payload_len);
}

int8_t coap_service_request_delete(int8_t service_id, uint16_t msg_id)
{
return coap_message_handler_request_delete(coap_service_handle, service_id, msg_id);
Expand Down
4 changes: 4 additions & 0 deletions source/include/coap_message_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ typedef struct coap_transaction {
int8_t service_id;
uint8_t options;
uint8_t *data_ptr;
sn_coap_msg_type_e req_msg_type;
bool client_request: 1;

coap_message_handler_response_recv *resp_cb;
Expand Down Expand Up @@ -93,4 +94,7 @@ extern void transaction_delete(coap_transaction_t *this);

extern void transactions_delete_all(uint8_t *address_ptr, uint16_t port);

extern int8_t coap_message_handler_response_send_by_msg_id(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, uint16_t msg_id, sn_coap_msg_code_e message_code,
sn_coap_content_format_e content_type, const uint8_t *payload_ptr,uint16_t payload_len);

#endif
5 changes: 5 additions & 0 deletions test/coap-service/unittest/stub/coap_message_handler_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,8 @@ int8_t coap_message_handler_exec(coap_msg_handler_t *handle, uint32_t current_ti
return coap_message_handler_stub.int8_value;
}

int8_t coap_message_handler_response_send_by_msg_id(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, uint16_t msg_id, sn_coap_msg_code_e message_code,
sn_coap_content_format_e content_type, const uint8_t *payload_ptr,uint16_t payload_len)
{
return coap_message_handler_stub.int8_value;
}

0 comments on commit adc04c4

Please sign in to comment.