mirror of https://github.com/ARMmbed/mbed-os.git
Squashed 'features/nanostack/FEATURE_NANOSTACK/coap-service/' changes from d65b6b0..b1c9efb
b1c9efb Fix coap_connection_handler_send_data() return values (#81) f9cb04f Delete transaction when not needed (#80) daf3694 Message transaction memory handling changes (#79) adc04c4 Add API to send response to request based on Message ID (#78) 58f0ed5 Limit number of ongoing handshakes (#77) 42c1169 Fix redefinition of mbed TLS error codes (#76) ba7a7c4 Added server mode certificate conf (#74) d108199 Certificate set API changed. (#73) 2d622e0 Support for certificate mode (#72) git-subtree-dir: features/nanostack/FEATURE_NANOSTACK/coap-service git-subtree-split: b1c9efb6a674f47f3a34e396bc0f57e8b1c27e19pull/5511/head
parent
9d5a9f5a29
commit
1bc6ddc3e8
|
@ -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
|
||||
|
@ -85,10 +85,11 @@ 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
|
||||
* \return -1 = Message ignored, no response will be sent. Transaction will be deleted.
|
||||
* 0 = Response is either already sent or will be send. Transaction is not deleted.
|
||||
*/
|
||||
typedef int coap_service_request_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr);
|
||||
|
||||
|
@ -98,8 +99,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
|
||||
*/
|
||||
|
@ -111,8 +114,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
|
||||
*/
|
||||
|
@ -147,23 +150,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.
|
||||
*
|
||||
|
@ -213,7 +205,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.
|
||||
*
|
||||
|
@ -240,7 +231,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.
|
||||
|
@ -261,15 +252,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
|
||||
*
|
||||
|
@ -297,18 +312,48 @@ extern int8_t coap_service_request_delete(int8_t service_id, uint16_t msg_id);
|
|||
*/
|
||||
extern int8_t coap_service_set_handshake_timeout(int8_t service_id, uint32_t min, uint32_t max);
|
||||
|
||||
/**
|
||||
* \brief Set DTLS handshake limit values
|
||||
*
|
||||
* Configures the limits for DTLS sessions. Values must be > 0.
|
||||
*
|
||||
* \param handshakes_max Maximum amount of simultaneous handshakes.
|
||||
* \param connections_max Maximum amount of sessions.
|
||||
*
|
||||
* \return -1 For failure
|
||||
*- 0 For success
|
||||
*/
|
||||
extern int8_t coap_service_handshake_limits_set(uint8_t handshakes_max, uint8_t connections_max);
|
||||
|
||||
/**
|
||||
* \brief Set CoAP duplication message buffer size
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
extern int8_t coap_service_set_duplicate_message_buffer(int8_t service_id, uint8_t size);
|
||||
|
||||
/**
|
||||
* \brief Set DTLS certificates
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* \return -1 For failure
|
||||
*- 0 For success
|
||||
*/
|
||||
|
||||
extern int8_t coap_service_certificate_set(int8_t service_id, const unsigned char *cert, uint16_t cert_len, const unsigned char *priv_key, uint8_t priv_key_len);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -48,6 +48,9 @@ const uint8_t COAP_MULTICAST_ADDR_SITE_LOCAL[16] = { 0xff, 0x05, [15] = 0xfd };
|
|||
|
||||
static NS_LIST_DEFINE(socket_list, internal_socket_t, link);
|
||||
|
||||
static uint8_t max_handshakes = MAX_ONGOING_HANDSHAKES;
|
||||
static uint8_t max_sessions = MAX_SECURE_SESSION_COUNT;
|
||||
|
||||
static void timer_cb(void* param);
|
||||
|
||||
static void recv_sckt_msg(void *cb_res);
|
||||
|
@ -141,13 +144,14 @@ static int8_t virtual_socket_id_allocate()
|
|||
return new_virtual_socket_id;
|
||||
}
|
||||
|
||||
static secure_session_t *secure_session_create(internal_socket_t *parent, const uint8_t *address_ptr, uint16_t port)
|
||||
static secure_session_t *secure_session_create(internal_socket_t *parent, const uint8_t *address_ptr, uint16_t port, SecureConnectionMode secure_mode)
|
||||
{
|
||||
uint8_t handshakes = 0;
|
||||
if(!address_ptr){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(MAX_SECURE_SESSION_COUNT <= ns_list_count(&secure_session_list)){
|
||||
if(max_sessions <= ns_list_count(&secure_session_list)){
|
||||
// Seek & destroy oldest session where close notify have been sent
|
||||
secure_session_t *to_be_removed = NULL;
|
||||
ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) {
|
||||
|
@ -164,6 +168,16 @@ static secure_session_t *secure_session_create(internal_socket_t *parent, const
|
|||
secure_session_delete(to_be_removed);
|
||||
}
|
||||
|
||||
// Count for ongoing handshakes
|
||||
ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) {
|
||||
if(cur_ptr->session_state == SECURE_SESSION_HANDSHAKE_ONGOING){
|
||||
handshakes++;
|
||||
}
|
||||
}
|
||||
if(handshakes >= max_handshakes) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
secure_session_t *this = ns_dyn_mem_alloc(sizeof(secure_session_t));
|
||||
if (!this) {
|
||||
return NULL;
|
||||
|
@ -179,12 +193,13 @@ static secure_session_t *secure_session_create(internal_socket_t *parent, const
|
|||
}
|
||||
timer_id++;
|
||||
}
|
||||
this->last_contact_time = coap_service_get_internal_timer_ticks();
|
||||
this->timer.id = timer_id;
|
||||
this->remote_host.type = ADDRESS_IPV6;
|
||||
memcpy(this->remote_host.address, address_ptr, 16);
|
||||
this->remote_host.identifier = port;
|
||||
|
||||
this->sec_handler = coap_security_create(parent->socket, this->timer.id, this, ECJPAKE,
|
||||
this->sec_handler = coap_security_create(parent->socket, this->timer.id, this, secure_mode,
|
||||
&secure_session_sendto, &secure_session_recvfrom, &start_timer, &timer_status);
|
||||
if( !this->sec_handler ){
|
||||
ns_dyn_mem_free(this);
|
||||
|
@ -595,31 +610,34 @@ static void secure_recv_sckt_msg(void *cb_res)
|
|||
|
||||
// Create session
|
||||
if (!session) {
|
||||
session = secure_session_create(sock, src_address.address, src_address.identifier);
|
||||
}
|
||||
if (!session) {
|
||||
tr_err("secure_recv_sckt_msg session creation failed - OOM");
|
||||
return;
|
||||
}
|
||||
// Record the destination. We are not strict on local address - all
|
||||
// session_find calls match only on remote address and port. But we
|
||||
// record the last-used destination address to use it as the source of
|
||||
// outgoing packets.
|
||||
memcpy(session->local_address, dst_address, 16);
|
||||
session->last_contact_time = coap_service_get_internal_timer_ticks();
|
||||
// Start handshake
|
||||
if (!coap_security_handler_is_started(session->sec_handler) ){
|
||||
uint8_t *pw = ns_dyn_mem_alloc(64);
|
||||
uint8_t pw_len;
|
||||
if( sock->parent->_get_password_cb && 0 == sock->parent->_get_password_cb(sock->socket, src_address.address, src_address.identifier, pw, &pw_len)){
|
||||
//TODO: get_password_cb should support certs and PSK also
|
||||
coap_security_keys_t keys;
|
||||
keys._priv = pw;
|
||||
keys._priv_len = pw_len;
|
||||
coap_security_handler_connect_non_blocking(session->sec_handler, true, DTLS, keys, sock->timeout_min, sock->timeout_max);
|
||||
coap_security_keys_t keys;
|
||||
memset(&keys, 0, sizeof(coap_security_keys_t));
|
||||
|
||||
if (sock->parent->_get_password_cb && 0 == sock->parent->_get_password_cb(sock->socket, src_address.address, src_address.identifier, &keys)) {
|
||||
session = secure_session_create(sock, src_address.address, src_address.identifier, keys.mode);
|
||||
if (!session) {
|
||||
tr_err("secure_recv_sckt_msg session creation failed - OOM");
|
||||
ns_dyn_mem_free(keys._key);
|
||||
return;
|
||||
}
|
||||
//TODO: error handling
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// Record the destination. We are not strict on local address - all
|
||||
// session_find calls match only on remote address and port. But we
|
||||
// record the last-used destination address to use it as the source of
|
||||
// outgoing packets.
|
||||
memcpy(session->local_address, dst_address, 16);
|
||||
|
||||
session->last_contact_time = coap_service_get_internal_timer_ticks();
|
||||
// Start handshake
|
||||
if (!coap_security_handler_is_started(session->sec_handler)) {
|
||||
coap_security_handler_connect_non_blocking(session->sec_handler, true, DTLS, keys, sock->timeout_min, sock->timeout_max);
|
||||
ns_dyn_mem_free(keys._key);
|
||||
|
||||
}
|
||||
ns_dyn_mem_free(pw);
|
||||
} else {
|
||||
//Continue handshake
|
||||
if (session->session_state == SECURE_SESSION_HANDSHAKE_ONGOING) {
|
||||
|
@ -703,34 +721,29 @@ int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t a
|
|||
}
|
||||
|
||||
if (handler->socket->is_secure) {
|
||||
coap_security_keys_t keys;
|
||||
memset(&keys, 0, sizeof(coap_security_keys_t));
|
||||
|
||||
secure_session_t *session = secure_session_find(sock, address, port);
|
||||
if (!session) {
|
||||
session = secure_session_create(sock, address, port);
|
||||
}
|
||||
if (!session) {
|
||||
tr_err("coap_connection_handler_virtual_recv session creation failed - OOM");
|
||||
return -1;
|
||||
if (sock->parent->_get_password_cb && 0 == sock->parent->_get_password_cb(sock->socket, address, port, &keys)) {
|
||||
session = secure_session_create(sock, address, port, keys.mode);
|
||||
if (!session) {
|
||||
tr_err("coap_connection_handler_virtual_recv session creation failed - OOM");
|
||||
ns_dyn_mem_free(keys._key);
|
||||
return -1;
|
||||
}
|
||||
coap_security_handler_connect_non_blocking(session->sec_handler, true, DTLS, keys, handler->socket->timeout_min, handler->socket->timeout_max);
|
||||
ns_dyn_mem_free(keys._key);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
session->last_contact_time = coap_service_get_internal_timer_ticks();
|
||||
|
||||
if (!coap_security_handler_is_started(session->sec_handler)) {
|
||||
uint8_t *pw = ns_dyn_mem_alloc(64);
|
||||
uint8_t pw_len;
|
||||
if (sock->parent->_get_password_cb && 0 == sock->parent->_get_password_cb(sock->socket, address, port, pw, &pw_len)) {
|
||||
//TODO: get_password_cb should support certs and PSK also
|
||||
coap_security_keys_t keys;
|
||||
keys._priv = pw;
|
||||
keys._priv_len = pw_len;
|
||||
coap_security_handler_connect_non_blocking(session->sec_handler, true, DTLS, keys, handler->socket->timeout_min, handler->socket->timeout_max);
|
||||
//TODO: error handling
|
||||
ns_dyn_mem_free(pw);
|
||||
return 0;
|
||||
} else {
|
||||
ns_dyn_mem_free(pw);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (coap_security_handler_is_started(session->sec_handler)) {
|
||||
if (session->session_state == SECURE_SESSION_HANDSHAKE_ONGOING) {
|
||||
int ret = coap_security_handler_continue_connecting(session->sec_handler);
|
||||
if(ret == 0){
|
||||
|
@ -813,6 +826,9 @@ void connection_handler_destroy(coap_conn_handler_t *handler, bool multicast_gro
|
|||
if (multicast_group_leave) {
|
||||
coap_multicast_group_join_or_leave(handler->socket->socket, SOCKET_IPV6_LEAVE_GROUP, handler->socket_interface_selection);
|
||||
}
|
||||
if (handler->security_keys) {
|
||||
ns_dyn_mem_free(handler->security_keys);
|
||||
}
|
||||
int_socket_delete(handler->socket);
|
||||
ns_dyn_mem_free(handler);
|
||||
}
|
||||
|
@ -869,56 +885,59 @@ int coap_connection_handler_send_data(coap_conn_handler_t *handler, const ns_add
|
|||
if (!handler || !handler->socket || !dest_addr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Secure send */
|
||||
if (handler->socket->is_secure) {
|
||||
handler->socket->bypass_link_sec = bypass_link_sec;
|
||||
secure_session_t *session = secure_session_find(handler->socket, dest_addr->address, dest_addr->identifier);
|
||||
if (!session) {
|
||||
session = secure_session_create(handler->socket, dest_addr->address, dest_addr->identifier);
|
||||
if (!session) {
|
||||
coap_security_keys_t security_material;
|
||||
int ret_val = 0;
|
||||
|
||||
memset(&security_material, 0, sizeof(coap_security_keys_t));
|
||||
|
||||
if (!handler->_get_password_cb || 0 != handler->_get_password_cb(handler->socket->socket, (uint8_t*)dest_addr->address, dest_addr->identifier, &security_material)) {
|
||||
return -1;
|
||||
}
|
||||
session->last_contact_time = coap_service_get_internal_timer_ticks();
|
||||
uint8_t *pw = ns_dyn_mem_alloc(64);
|
||||
if (!pw) {
|
||||
//todo: free secure session?
|
||||
return -1;
|
||||
}
|
||||
uint8_t pw_len;
|
||||
if (handler->_get_password_cb && 0 == handler->_get_password_cb(handler->socket->socket, (uint8_t*)dest_addr->address, dest_addr->identifier, pw, &pw_len)) {
|
||||
//TODO: get_password_cb should support certs and PSK also
|
||||
coap_security_keys_t keys;
|
||||
keys._priv = pw;
|
||||
keys._priv_len = pw_len;
|
||||
coap_security_handler_connect_non_blocking(session->sec_handler, false, DTLS, keys, handler->socket->timeout_min, handler->socket->timeout_max);
|
||||
ns_dyn_mem_free(pw);
|
||||
return -2;
|
||||
} else {
|
||||
//free secure session?
|
||||
ns_dyn_mem_free(pw);
|
||||
return -1;
|
||||
|
||||
session = secure_session_create(handler->socket, dest_addr->address, dest_addr->identifier, security_material.mode);
|
||||
if (!session || (0 > coap_security_handler_connect_non_blocking(session->sec_handler, false, DTLS, security_material, handler->socket->timeout_min, handler->socket->timeout_max))) {
|
||||
ret_val = -1;
|
||||
}
|
||||
|
||||
ns_dyn_mem_free(security_material._key);
|
||||
return ret_val;
|
||||
|
||||
} else if (session->session_state == SECURE_SESSION_OK) {
|
||||
if (coap_security_handler_send_message(session->sec_handler, data_ptr, data_len ) > 0 ) {
|
||||
session->last_contact_time = coap_service_get_internal_timer_ticks();
|
||||
return 0;
|
||||
session->last_contact_time = coap_service_get_internal_timer_ticks();
|
||||
if (0 > coap_security_handler_send_message(session->sec_handler, data_ptr, data_len )) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}else{
|
||||
/* Unsecure */
|
||||
} else {
|
||||
/* Virtual socket */
|
||||
if (!handler->socket->real_socket && handler->_send_cb) {
|
||||
return handler->_send_cb((int8_t)handler->socket->socket, dest_addr->address, dest_addr->identifier, data_ptr, data_len);
|
||||
}
|
||||
int opt_name = SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT;
|
||||
int8_t securityLinkLayer = 1;
|
||||
if (bypass_link_sec) {
|
||||
securityLinkLayer = 0;
|
||||
}
|
||||
if (handler->_send_cb((int8_t)handler->socket->socket, dest_addr->address, dest_addr->identifier, data_ptr, data_len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
int opt_name = SOCKET_IPV6_PREFER_SRC_6LOWPAN_SHORT;
|
||||
int8_t securityLinkLayer = 1;
|
||||
if (bypass_link_sec) {
|
||||
securityLinkLayer = 0;
|
||||
}
|
||||
|
||||
socket_setsockopt(handler->socket->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_ADDR_PREFERENCES, &opt_name, sizeof(int));
|
||||
socket_setsockopt(handler->socket->socket, SOCKET_IPPROTO_IPV6, SOCKET_LINK_LAYER_SECURITY, &securityLinkLayer, sizeof(int8_t));
|
||||
socket_setsockopt(handler->socket->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_ADDR_PREFERENCES, &opt_name, sizeof(int));
|
||||
socket_setsockopt(handler->socket->socket, SOCKET_IPPROTO_IPV6, SOCKET_LINK_LAYER_SECURITY, &securityLinkLayer, sizeof(int8_t));
|
||||
|
||||
return send_to_real_socket(handler->socket->socket, dest_addr, src_address, data_ptr, data_len);
|
||||
if (0 > send_to_real_socket(handler->socket->socket, dest_addr, src_address, data_ptr, data_len)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool coap_connection_handler_socket_belongs_to(coap_conn_handler_t *handler, int8_t socket_id)
|
||||
|
@ -944,22 +963,35 @@ int8_t coap_connection_handler_set_timeout(coap_conn_handler_t *handler, uint32_
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t coap_connection_handler_handshake_limits_set(uint8_t handshakes_limit, uint8_t connections_limit)
|
||||
{
|
||||
if (!handshakes_limit || !connections_limit) {
|
||||
return -1;
|
||||
}
|
||||
max_handshakes = handshakes_limit;
|
||||
max_sessions = connections_limit;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No need to call every second - call rather like every minute (SECURE_SESSION_CLEAN_INTERVAL sets this) */
|
||||
void coap_connection_handler_exec(uint32_t time)
|
||||
{
|
||||
if(ns_list_count(&secure_session_list)){
|
||||
// Seek & destroy old sessions where close notify have been sent
|
||||
ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) {
|
||||
if(cur_ptr->session_state == SECURE_SESSION_CLOSED ||
|
||||
cur_ptr->session_state == SECURE_SESSION_HANDSHAKE_ONGOING){
|
||||
if(cur_ptr->session_state == SECURE_SESSION_CLOSED) {
|
||||
if((cur_ptr->last_contact_time + CLOSED_SECURE_SESSION_TIMEOUT) <= time){
|
||||
secure_session_delete(cur_ptr);
|
||||
}
|
||||
}
|
||||
if(cur_ptr->session_state == SECURE_SESSION_OK){
|
||||
} else if(cur_ptr->session_state == SECURE_SESSION_OK){
|
||||
if((cur_ptr->last_contact_time + OPEN_SECURE_SESSION_TIMEOUT) <= time){
|
||||
secure_session_delete(cur_ptr);
|
||||
}
|
||||
} else if(cur_ptr->session_state == SECURE_SESSION_HANDSHAKE_ONGOING){
|
||||
if((cur_ptr->last_contact_time + ONGOING_HANDSHAKE_TIMEOUT) <= time){
|
||||
secure_session_delete(cur_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,10 +96,6 @@ static coap_transaction_t *transaction_create(void)
|
|||
|
||||
static void transaction_free(coap_transaction_t *this)
|
||||
{
|
||||
if (!this) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->data_ptr) {
|
||||
ns_dyn_mem_free(this->data_ptr);
|
||||
}
|
||||
|
@ -108,11 +104,13 @@ static void transaction_free(coap_transaction_t *this)
|
|||
|
||||
void transaction_delete(coap_transaction_t *this)
|
||||
{
|
||||
if (this) {
|
||||
ns_list_remove(&request_list, this);
|
||||
transaction_free(this);
|
||||
if (!coap_message_handler_transaction_valid(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ns_list_remove(&request_list, this);
|
||||
transaction_free(this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -227,11 +225,14 @@ coap_transaction_t *coap_message_handler_find_transaction(uint8_t *address_ptr,
|
|||
int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t socket_id, const uint8_t source_addr_ptr[static 16], uint16_t port, const uint8_t dst_addr_ptr[static 16],
|
||||
uint8_t *data_ptr, uint16_t data_len, int16_t (cb)(int8_t, sn_coap_hdr_s *, coap_transaction_t *))
|
||||
{
|
||||
sn_nsdl_addr_s src_addr;
|
||||
sn_coap_hdr_s *coap_message;
|
||||
int16_t ret_val = 0;
|
||||
|
||||
if (!cb || !handle) {
|
||||
return -1;
|
||||
}
|
||||
sn_nsdl_addr_s src_addr;
|
||||
sn_coap_hdr_s *coap_message;
|
||||
|
||||
src_addr.addr_ptr = (uint8_t *)source_addr_ptr;
|
||||
src_addr.addr_len = 16;
|
||||
src_addr.type = SN_NSDL_ADDRESS_TYPE_IPV6;
|
||||
|
@ -242,13 +243,16 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
|
|||
tr_err("CoAP Parsing failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_debug("CoAP status:%d, type:%d, code:%d, id:%d", coap_message->coap_status, coap_message->msg_type, coap_message->msg_code, coap_message->msg_id);
|
||||
|
||||
/* Check, if coap itself sends response, or block receiving is ongoing... */
|
||||
if (coap_message->coap_status != COAP_STATUS_OK && coap_message->coap_status != COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) {
|
||||
tr_debug("CoAP library responds");
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message);
|
||||
return -1;
|
||||
ret_val = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Request received */
|
||||
if (coap_message->msg_code > 0 && coap_message->msg_code < 32) {
|
||||
coap_transaction_t *transaction_ptr = transaction_create();
|
||||
|
@ -256,19 +260,20 @@ 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);
|
||||
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;
|
||||
if (coap_message->token_len) {
|
||||
memcpy(transaction_ptr->token, coap_message->token_ptr, coap_message->token_len);
|
||||
}
|
||||
transaction_ptr->remote_port = port;
|
||||
if (cb(socket_id, coap_message, transaction_ptr) < 0) {
|
||||
// negative return value = message ignored -> delete transaction
|
||||
transaction_delete(transaction_ptr);
|
||||
}
|
||||
goto exit;
|
||||
} else {
|
||||
//TODO: handle error case
|
||||
ret_val = -1;
|
||||
}
|
||||
/* Response received */
|
||||
} else {
|
||||
|
@ -278,20 +283,21 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
|
|||
}
|
||||
if (!this) {
|
||||
tr_error("client transaction not found");
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message);
|
||||
return -1;
|
||||
ret_val = -1;
|
||||
goto exit;
|
||||
}
|
||||
tr_debug("Service %d, response received", this->service_id);
|
||||
ns_list_remove(&request_list, this);
|
||||
if (this->resp_cb) {
|
||||
this->resp_cb(this->service_id, (uint8_t *)source_addr_ptr, port, coap_message);
|
||||
}
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message);
|
||||
transaction_free(this);
|
||||
}
|
||||
|
||||
return 0;
|
||||
exit:
|
||||
sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
uint16_t coap_message_handler_request_send(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, const uint8_t destination_addr[static 16],
|
||||
|
@ -358,13 +364,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;
|
||||
|
||||
|
@ -380,10 +410,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 ){
|
||||
|
@ -393,18 +419,53 @@ 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) {
|
||||
transaction_delete(transaction_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;
|
||||
int8_t ret_val;
|
||||
|
||||
(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;
|
||||
}
|
||||
|
||||
ret_val = coap_message_handler_resp_build_and_send(handle, &response, transaction_ptr);
|
||||
if(ret_val == 0) {
|
||||
transaction_delete(transaction_ptr);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int8_t coap_message_handler_request_delete(coap_msg_handler_t *handle, int8_t service_id, uint16_t msg_id)
|
||||
|
|
|
@ -69,10 +69,10 @@ static const int PSK_SUITES[] = {
|
|||
0
|
||||
};
|
||||
|
||||
#define TRACE_GROUP "CsSh"
|
||||
|
||||
static void set_timer( void *sec_obj, uint32_t int_ms, uint32_t fin_ms );
|
||||
static int get_timer( void *sec_obj );
|
||||
static int coap_security_handler_configure_keys( coap_security_t *sec, coap_security_keys_t keys );
|
||||
|
||||
int entropy_poll( void *data, unsigned char *output, size_t len, size_t *olen );
|
||||
|
||||
|
@ -276,37 +276,35 @@ static int export_key_block(void *ctx,
|
|||
}
|
||||
#endif
|
||||
|
||||
int coap_security_handler_configure_keys( coap_security_t *sec, coap_security_keys_t keys )
|
||||
static int coap_security_handler_configure_keys (coap_security_t *sec, coap_security_keys_t keys, bool is_server)
|
||||
{
|
||||
(void) is_server;
|
||||
|
||||
int ret = -1;
|
||||
switch( sec->_conn_mode ){
|
||||
case Certificate:{
|
||||
case CERTIFICATE:{
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
if( mbedtls_x509_crt_parse( &sec->_cacert, keys._server_cert,
|
||||
keys._server_cert_len ) < 0 ){
|
||||
if( keys._cert && mbedtls_x509_crt_parse( &sec->_owncert, keys._cert, keys._cert_len ) < 0 ){
|
||||
break;
|
||||
}
|
||||
if( mbedtls_x509_crt_parse( &sec->_owncert, keys._pub_cert_or_identifier,
|
||||
keys._pub_len ) < 0 ){
|
||||
|
||||
if( mbedtls_pk_parse_key(&sec->_pkey, keys._priv_key, keys._priv_key_len, NULL, 0) < 0){
|
||||
break;
|
||||
}
|
||||
if( mbedtls_pk_parse_key(&sec->_pkey, keys._priv, keys._priv_len, NULL, 0) < 0){
|
||||
|
||||
if (0 != mbedtls_ssl_conf_own_cert(&sec->_conf, &sec->_owncert, &sec->_pkey)) {
|
||||
break;
|
||||
}
|
||||
//TODO: If needed in server mode, this won't work
|
||||
if( 0 != mbedtls_ssl_conf_own_cert(&sec->_conf, &sec->_owncert, &sec->_pkey) ){
|
||||
break;
|
||||
}
|
||||
//TODO: use MBEDTLS_SSL_VERIFY_REQUIRED instead of optional
|
||||
mbedtls_ssl_conf_authmode( &sec->_conf, MBEDTLS_SSL_VERIFY_OPTIONAL );
|
||||
mbedtls_ssl_conf_ca_chain( &sec->_conf, &sec->_cacert, NULL );
|
||||
|
||||
mbedtls_ssl_conf_authmode( &sec->_conf, MBEDTLS_SSL_VERIFY_NONE );
|
||||
mbedtls_ssl_conf_ca_chain( &sec->_conf, &sec->_owncert, NULL );
|
||||
ret = 0;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case PSK: {
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
|
||||
if( 0 != mbedtls_ssl_conf_psk(&sec->_conf, keys._priv, keys._priv_len, keys._pub_cert_or_identifier, keys._pub_len) ){
|
||||
if( 0 != mbedtls_ssl_conf_psk(&sec->_conf, keys._priv_key, keys._priv_key_len, keys._cert, keys._cert_len) ){
|
||||
break;
|
||||
}
|
||||
mbedtls_ssl_conf_ciphersuites(&sec->_conf, PSK_SUITES);
|
||||
|
@ -316,7 +314,7 @@ int coap_security_handler_configure_keys( coap_security_t *sec, coap_security_ke
|
|||
}
|
||||
case ECJPAKE: {
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
if( mbedtls_ssl_set_hs_ecjpake_password(&sec->_ssl, keys._priv, keys._priv_len) != 0 ){
|
||||
if( mbedtls_ssl_set_hs_ecjpake_password(&sec->_ssl, keys._key, keys._key_len) != 0 ){
|
||||
return -1;
|
||||
}
|
||||
mbedtls_ssl_conf_ciphersuites(&sec->_conf, ECJPAKE_SUITES);
|
||||
|
@ -336,82 +334,8 @@ int coap_security_handler_configure_keys( coap_security_t *sec, coap_security_ke
|
|||
return ret;
|
||||
}
|
||||
|
||||
int coap_security_handler_connect(coap_security_t *sec, bool is_server, SecureSocketMode sock_mode, coap_security_keys_t keys){
|
||||
int ret = -1;
|
||||
|
||||
if( !sec ){
|
||||
return ret;
|
||||
}
|
||||
sec->_is_blocking = true;
|
||||
|
||||
int endpoint = MBEDTLS_SSL_IS_CLIENT;
|
||||
if( is_server ){
|
||||
endpoint = MBEDTLS_SSL_IS_SERVER;
|
||||
}
|
||||
|
||||
int mode = MBEDTLS_SSL_TRANSPORT_DATAGRAM;
|
||||
if( sock_mode == TLS ){
|
||||
mode = MBEDTLS_SSL_TRANSPORT_STREAM;
|
||||
}
|
||||
|
||||
if( ( mbedtls_ssl_config_defaults( &sec->_conf,
|
||||
endpoint,
|
||||
mode, 0 ) ) != 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
mbedtls_ssl_set_bio( &sec->_ssl, sec,
|
||||
f_send, f_recv, NULL );
|
||||
|
||||
mbedtls_ssl_set_timer_cb( &sec->_ssl, sec, set_timer,
|
||||
get_timer );
|
||||
|
||||
if( coap_security_handler_configure_keys( sec, keys ) != 0 ){
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef MBEDTLS_SSL_SRV_C
|
||||
mbedtls_ssl_conf_dtls_cookies(&sec->_conf, simple_cookie_write,
|
||||
simple_cookie_check,
|
||||
&sec->_cookie);
|
||||
#endif
|
||||
|
||||
sec->_is_started = true;
|
||||
|
||||
do {
|
||||
ret = mbedtls_ssl_handshake_step( &sec->_ssl );
|
||||
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ){ //cookie check failed
|
||||
if( is_server ){
|
||||
mbedtls_ssl_session_reset(&sec->_ssl);
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
if( mbedtls_ssl_set_hs_ecjpake_password(&sec->_ssl, keys._priv, keys._priv_len) != 0 ){
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
ret = MBEDTLS_ERR_SSL_WANT_READ; //needed to keep doing
|
||||
}else{
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
}while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
|
||||
if( ret != 0){
|
||||
ret = -1;
|
||||
}else{
|
||||
if( mbedtls_ssl_get_verify_result( &sec->_ssl ) != 0 )
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int coap_security_handler_connect_non_blocking(coap_security_t *sec, bool is_server, SecureSocketMode sock_mode, coap_security_keys_t keys, uint32_t timeout_min, uint32_t timeout_max)
|
||||
{
|
||||
|
||||
if( !sec ){
|
||||
return -1;
|
||||
}
|
||||
|
@ -457,13 +381,14 @@ int coap_security_handler_connect_non_blocking(coap_security_t *sec, bool is_ser
|
|||
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
//TODO: Figure out better way!!!
|
||||
//Password should never be stored in multiple places!!!
|
||||
if( is_server && keys._priv_len > 0){
|
||||
memcpy(sec->_pw, keys._priv, keys._priv_len);
|
||||
sec->_pw_len = keys._priv_len;
|
||||
if ((sec->_conn_mode == ECJPAKE) && is_server && keys._key_len > 0){
|
||||
memcpy(sec->_pw, keys._key, keys._key_len);
|
||||
sec->_pw_len = keys._key_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( coap_security_handler_configure_keys( sec, keys ) != 0 ){
|
||||
if (coap_security_handler_configure_keys(sec, keys, is_server) != 0) {
|
||||
tr_debug("security credential configure failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -499,7 +424,6 @@ int coap_security_handler_continue_connecting(coap_security_t *sec){
|
|||
|
||||
while( ret != MBEDTLS_ERR_SSL_WANT_READ ){
|
||||
ret = mbedtls_ssl_handshake_step( &sec->_ssl );
|
||||
|
||||
if( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED == ret){
|
||||
mbedtls_ssl_session_reset(&sec->_ssl);
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
|
|
|
@ -146,6 +146,7 @@ static uint8_t coap_tx_function(uint8_t *data_ptr, uint16_t data_len, sn_nsdl_ad
|
|||
coap_service_t *this;
|
||||
coap_transaction_t *transaction_ptr = coap_message_handler_transaction_valid(param);
|
||||
ns_address_t dest_addr;
|
||||
int ret_val;
|
||||
|
||||
if (!transaction_ptr || !data_ptr) {
|
||||
return 0;
|
||||
|
@ -162,17 +163,19 @@ static uint8_t coap_tx_function(uint8_t *data_ptr, uint16_t data_len, sn_nsdl_ad
|
|||
dest_addr.identifier = address_ptr->port;
|
||||
dest_addr.type = ADDRESS_IPV6;
|
||||
|
||||
if (-2 == coap_connection_handler_send_data(this->conn_handler, &dest_addr, transaction_ptr->local_address,
|
||||
data_ptr, data_len, (this->service_options & COAP_SERVICE_OPTIONS_SECURE_BYPASS) == COAP_SERVICE_OPTIONS_SECURE_BYPASS)) {
|
||||
transaction_ptr->data_ptr = ns_dyn_mem_alloc(data_len);
|
||||
ret_val = coap_connection_handler_send_data(this->conn_handler, &dest_addr, transaction_ptr->local_address,
|
||||
data_ptr, data_len, (this->service_options & COAP_SERVICE_OPTIONS_SECURE_BYPASS) == COAP_SERVICE_OPTIONS_SECURE_BYPASS);
|
||||
if (ret_val == 0) {
|
||||
if (!transaction_ptr->data_ptr) {
|
||||
tr_debug("coap tx out of memory");
|
||||
return 0;
|
||||
|
||||
transaction_ptr->data_ptr = ns_dyn_mem_alloc(data_len);
|
||||
if (!transaction_ptr->data_ptr) {
|
||||
tr_debug("coap tx out of memory");
|
||||
return 0;
|
||||
}
|
||||
memcpy(transaction_ptr->data_ptr, data_ptr, data_len);
|
||||
transaction_ptr->data_len = data_len;
|
||||
}
|
||||
memcpy(transaction_ptr->data_ptr, data_ptr, data_len);
|
||||
transaction_ptr->data_len = data_len;
|
||||
} else if (transaction_ptr->resp_cb == NULL ) {
|
||||
} else if ((ret_val == -1) || (transaction_ptr->resp_cb == NULL)) {
|
||||
transaction_delete(transaction_ptr);
|
||||
}
|
||||
|
||||
|
@ -252,7 +255,7 @@ static int recv_cb(int8_t socket_id, uint8_t src_address[static 16], uint16_t po
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int send_cb(int8_t socket_id, const uint8_t address[static 16], uint16_t port, const void *data_ptr, int data_len)
|
||||
static int virtual_send_cb(int8_t socket_id, const uint8_t address[static 16], uint16_t port, const void *data_ptr, int data_len)
|
||||
{
|
||||
coap_service_t *this = service_find_by_socket(socket_id);
|
||||
if (this && this->virtual_socket_send_cb) {
|
||||
|
@ -290,12 +293,34 @@ static void sec_done_cb(int8_t socket_id, uint8_t address[static 16], uint16_t p
|
|||
}
|
||||
}
|
||||
|
||||
static int get_passwd_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t *pw_ptr, uint8_t *pw_len)
|
||||
static int get_passwd_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, coap_security_keys_t *security_ptr)
|
||||
{
|
||||
uint8_t *pw_ptr = NULL;
|
||||
uint8_t pw_len = 0;
|
||||
coap_service_t *this = service_find_by_socket(socket_id);
|
||||
if (this && this->security_start_cb) {
|
||||
return this->security_start_cb(this->service_id, address, port, pw_ptr, pw_len);
|
||||
|
||||
if (!this || !security_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Certificates set */
|
||||
if (this->conn_handler->security_keys) {
|
||||
*security_ptr = *this->conn_handler->security_keys;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pw_ptr = ns_dyn_mem_alloc(64);
|
||||
if (!pw_ptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (this->security_start_cb && !this->security_start_cb(this->service_id, address, port, pw_ptr, &pw_len)) {
|
||||
security_ptr->mode = ECJPAKE;
|
||||
security_ptr->_key = pw_ptr;
|
||||
security_ptr->_key_len = pw_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -326,7 +351,7 @@ int8_t coap_service_initialize(int8_t interface_id, uint16_t listen_port, uint8_
|
|||
tasklet_id = eventOS_event_handler_create(&service_event_handler, ARM_LIB_TASKLET_INIT_EVENT);
|
||||
}
|
||||
|
||||
this->conn_handler = connection_handler_create(recv_cb, send_cb, get_passwd_cb, sec_done_cb);
|
||||
this->conn_handler = connection_handler_create(recv_cb, virtual_send_cb, get_passwd_cb, sec_done_cb);
|
||||
if(!this->conn_handler){
|
||||
ns_dyn_mem_free(this);
|
||||
return -1;
|
||||
|
@ -494,6 +519,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);
|
||||
|
@ -509,6 +538,11 @@ int8_t coap_service_set_handshake_timeout(int8_t service_id, uint32_t min, uint3
|
|||
return coap_connection_handler_set_timeout(this->conn_handler, min, max);
|
||||
}
|
||||
|
||||
int8_t coap_service_handshake_limits_set(uint8_t handshakes_max, uint8_t connections_max)
|
||||
{
|
||||
return coap_connection_handler_handshake_limits_set(handshakes_max, connections_max);
|
||||
}
|
||||
|
||||
int8_t coap_service_set_duplicate_message_buffer(int8_t service_id, uint8_t size)
|
||||
{
|
||||
(void) service_id;
|
||||
|
@ -531,3 +565,31 @@ uint16_t coap_service_id_find_by_socket(int8_t socket_id)
|
|||
|
||||
return this ? this->service_id:0;
|
||||
}
|
||||
|
||||
int8_t coap_service_certificate_set(int8_t service_id, const unsigned char *cert, uint16_t cert_len, const unsigned char *priv_key, uint8_t priv_key_len)
|
||||
{
|
||||
coap_service_t *this = service_find(service_id);
|
||||
if (!this) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!this->conn_handler->security_keys) {
|
||||
this->conn_handler->security_keys = ns_dyn_mem_alloc(sizeof(coap_security_keys_t));
|
||||
|
||||
if (!this->conn_handler->security_keys) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
memset(this->conn_handler->security_keys, 0, sizeof(coap_security_keys_t));
|
||||
|
||||
this->conn_handler->security_keys->_cert = cert;
|
||||
this->conn_handler->security_keys->_cert_len = cert_len;
|
||||
|
||||
this->conn_handler->security_keys->_priv_key = priv_key;
|
||||
this->conn_handler->security_keys->_priv_key_len = priv_key_len;
|
||||
|
||||
this->conn_handler->security_keys->mode = CERTIFICATE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -24,26 +24,31 @@
|
|||
#include <stdbool.h>
|
||||
#include "ns_address.h"
|
||||
#include "coap_service_api_internal.h"
|
||||
#include "coap_security_handler.h"
|
||||
|
||||
#define MAX_SECURE_SESSION_COUNT 3
|
||||
#define MAX_ONGOING_HANDSHAKES 2
|
||||
#define CLOSED_SECURE_SESSION_TIMEOUT 3600 // Seconds
|
||||
#define OPEN_SECURE_SESSION_TIMEOUT 18000 // Seconds
|
||||
#define ONGOING_HANDSHAKE_TIMEOUT 600 // Seconds
|
||||
#define OPEN_SECURE_SESSION_TIMEOUT 18000 // Seconds
|
||||
#define SECURE_SESSION_CLEAN_INTERVAL 60 // Seconds
|
||||
|
||||
struct internal_socket_s;
|
||||
|
||||
typedef int send_to_socket_cb(int8_t socket_id, const uint8_t address[static 16], uint16_t port, const void *, int);
|
||||
typedef int receive_from_socket_cb(int8_t socket_id, uint8_t src_address[static 16], uint16_t port, const uint8_t dst_address[static 16], unsigned char *, int);
|
||||
typedef int get_pw_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t *pw_ptr, uint8_t *pw_len);
|
||||
typedef int get_pw_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, coap_security_keys_t *security_ptr);
|
||||
typedef void security_done_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t keyblock[static 40]);
|
||||
|
||||
typedef struct coap_conn_handler_s{
|
||||
struct internal_socket_s *socket;
|
||||
|
||||
coap_security_keys_t *security_keys;
|
||||
receive_from_socket_cb *_recv_cb;
|
||||
send_to_socket_cb *_send_cb;
|
||||
get_pw_cb *_get_password_cb;
|
||||
security_done_cb *_security_done_cb;
|
||||
|
||||
int8_t socket_interface_selection;
|
||||
bool registered_to_multicast;
|
||||
} coap_conn_handler_t;
|
||||
|
@ -60,6 +65,11 @@ void connection_handler_close_secure_connection( coap_conn_handler_t *handler, u
|
|||
int coap_connection_handler_open_connection(coap_conn_handler_t *handler, uint16_t listen_port, bool use_ephemeral_port, bool is_secure, bool real_socket, bool bypassSec);
|
||||
|
||||
//If returns -2, it means security was started and data was not send
|
||||
/*
|
||||
* \return > 0 in OK
|
||||
* \return 0 Session started, data not send
|
||||
* \return -1 failure
|
||||
*/
|
||||
int coap_connection_handler_send_data(coap_conn_handler_t *handler, const ns_address_t *dest_addr, const uint8_t src_address[static 16], uint8_t *data_ptr, uint16_t data_len, bool bypass_link_sec);
|
||||
|
||||
int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t address[static 16], uint16_t port, uint8_t *data_ptr, uint16_t data_len);
|
||||
|
@ -68,6 +78,8 @@ bool coap_connection_handler_socket_belongs_to(coap_conn_handler_t *handler, int
|
|||
|
||||
int8_t coap_connection_handler_set_timeout(coap_conn_handler_t *handler, uint32_t min, uint32_t max);
|
||||
|
||||
int8_t coap_connection_handler_handshake_limits_set(uint8_t handshakes_limit, uint8_t connections_limit);
|
||||
|
||||
void coap_connection_handler_exec(uint32_t time);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
|
@ -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
|
||||
|
|
|
@ -52,18 +52,21 @@ typedef enum {
|
|||
}SecureSocketMode;
|
||||
|
||||
typedef enum {
|
||||
Certificate,
|
||||
CERTIFICATE,
|
||||
PSK,
|
||||
ECJPAKE
|
||||
}SecureConnectionMode;
|
||||
|
||||
typedef struct {
|
||||
unsigned char *_server_cert;
|
||||
uint8_t _server_cert_len;
|
||||
unsigned char *_pub_cert_or_identifier;
|
||||
uint8_t _pub_len;
|
||||
unsigned char *_priv;
|
||||
uint8_t _priv_len;
|
||||
SecureConnectionMode mode;
|
||||
/* Certificate pointers, not owned */
|
||||
const unsigned char *_cert;
|
||||
uint16_t _cert_len;
|
||||
const unsigned char *_priv_key;
|
||||
uint8_t _priv_key_len;
|
||||
/* Secure key pointer, owned */
|
||||
unsigned char *_key;
|
||||
uint8_t _key_len;
|
||||
} coap_security_keys_t;
|
||||
|
||||
typedef struct coap_security_s coap_security_t;
|
||||
|
@ -79,8 +82,6 @@ coap_security_t *coap_security_create(int8_t socket_id, int8_t timer_id, void *h
|
|||
|
||||
void coap_security_destroy(coap_security_t *sec);
|
||||
|
||||
int coap_security_handler_connect(coap_security_t *sec, bool is_server, SecureSocketMode sock_mode, coap_security_keys_t keys);
|
||||
|
||||
int coap_security_handler_connect_non_blocking(coap_security_t *sec, bool is_server, SecureSocketMode sock_mode, coap_security_keys_t keys, uint32_t timeout_min, uint32_t timeout_max);
|
||||
|
||||
int coap_security_handler_continue_connecting(coap_security_t *sec);
|
||||
|
@ -100,15 +101,25 @@ const void *coap_security_handler_keyblock(const coap_security_t *sec);
|
|||
NS_DUMMY_DEFINITIONS_OK
|
||||
|
||||
/* Dummy definitions, including needed error codes */
|
||||
#ifndef MBEDTLS_ERR_SSL_TIMEOUT
|
||||
#define MBEDTLS_ERR_SSL_TIMEOUT (-1)
|
||||
#endif
|
||||
|
||||
#ifndef MBEDTLS_ERR_SSL_WANT_READ
|
||||
#define MBEDTLS_ERR_SSL_WANT_READ (-2)
|
||||
#endif
|
||||
|
||||
#ifndef MBEDTLS_ERR_SSL_WANT_WRITE
|
||||
#define MBEDTLS_ERR_SSL_WANT_WRITE (-3)
|
||||
#endif
|
||||
|
||||
#ifndef MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE
|
||||
#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE (-4)
|
||||
#endif
|
||||
|
||||
#define coap_security_create(socket_id, timer_id, handle, \
|
||||
mode, send_cb, receive_cb, start_timer_cb, timer_status_cb) ((coap_security_t *) 0)
|
||||
#define coap_security_destroy(sec) ((void) 0)
|
||||
#define coap_security_handler_connect(sec, is_server, sock_mode, keys) (-1)
|
||||
#define coap_security_handler_connect_non_blocking(sec, is_server, sock_mode, keys, timeout_min, timeout_max) (-1)
|
||||
#define coap_security_handler_continue_connecting(sec) (-1)
|
||||
#define coap_security_handler_send_message(sec, message, len) (-1)
|
||||
|
|
|
@ -29,7 +29,7 @@ int get_passwd_cb(int8_t socket_id, uint8_t address, uint16_t port, uint8_t *pw_
|
|||
return 0;
|
||||
}
|
||||
|
||||
void sec_done_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t keyblock[static 40])
|
||||
void sec_done_cb_test(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t keyblock[static 40])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ bool test_coap_connection_handler_send_data()
|
|||
return false;
|
||||
|
||||
socket_api_stub.int8_value = 7;
|
||||
if( 7 != coap_connection_handler_send_data(handler, &addr, ns_in6addr_any, NULL, 0, true))
|
||||
if( 1 != coap_connection_handler_send_data(handler, &addr, ns_in6addr_any, NULL, 0, true))
|
||||
return false;
|
||||
connection_handler_destroy(handler, false);
|
||||
|
||||
|
@ -212,7 +212,7 @@ bool test_coap_connection_handler_virtual_recv()
|
|||
connection_handler_destroy(handler, false);
|
||||
|
||||
nsdynmemlib_stub.returnCounter = 1;
|
||||
coap_conn_handler_t *handler2 = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, &get_passwd_cb, &sec_done_cb);
|
||||
coap_conn_handler_t *handler2 = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, &get_passwd_cb, &sec_done_cb_test);
|
||||
nsdynmemlib_stub.returnCounter = 2;
|
||||
if( 0 != coap_connection_handler_open_connection(handler2, 24,false,true,true,false) )
|
||||
return false;
|
||||
|
@ -241,7 +241,7 @@ bool test_coap_connection_handler_virtual_recv()
|
|||
coap_security_handler_stub.sec_obj = NULL;
|
||||
|
||||
nsdynmemlib_stub.returnCounter = 1;
|
||||
coap_conn_handler_t *handler3 = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, &get_passwd_cb, &sec_done_cb);
|
||||
coap_conn_handler_t *handler3 = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, &get_passwd_cb, &sec_done_cb_test);
|
||||
nsdynmemlib_stub.returnCounter = 2;
|
||||
if( 0 != coap_connection_handler_open_connection(handler3, 26,false,false,true,false) )
|
||||
return false;
|
||||
|
@ -367,7 +367,7 @@ bool test_socket_api_callbacks()
|
|||
connection_handler_destroy(handler, false);
|
||||
|
||||
nsdynmemlib_stub.returnCounter = 1;
|
||||
coap_conn_handler_t *handler2 = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, &get_passwd_cb, &sec_done_cb);
|
||||
coap_conn_handler_t *handler2 = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, &get_passwd_cb, &sec_done_cb_test);
|
||||
nsdynmemlib_stub.returnCounter = 2;
|
||||
if( 0 != coap_connection_handler_open_connection(handler2, 22,false,true,true,false) )
|
||||
return false;
|
||||
|
|
|
@ -119,6 +119,7 @@ bool test_coap_message_handler_coap_msg_process()
|
|||
{
|
||||
uint8_t buf[16];
|
||||
memset(&buf, 1, 16);
|
||||
/*Handler is null*/
|
||||
if( -1 != coap_message_handler_coap_msg_process(NULL, 0, buf, 22, ns_in6addr_any, NULL, 0, NULL))
|
||||
return false;
|
||||
|
||||
|
@ -128,12 +129,14 @@ bool test_coap_message_handler_coap_msg_process()
|
|||
coap_msg_handler_t *handle = coap_message_handler_init(&own_alloc, &own_free, &coap_tx_function);
|
||||
|
||||
sn_coap_protocol_stub.expectedHeader = NULL;
|
||||
/* Coap parse returns null */
|
||||
if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, ns_in6addr_any, NULL, 0, process_cb))
|
||||
return false;
|
||||
|
||||
sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s));
|
||||
memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s));
|
||||
sn_coap_protocol_stub.expectedHeader->coap_status = 66;
|
||||
/* Coap library responds */
|
||||
if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, ns_in6addr_any, NULL, 0, process_cb))
|
||||
return false;
|
||||
|
||||
|
@ -142,12 +145,17 @@ bool test_coap_message_handler_coap_msg_process()
|
|||
sn_coap_protocol_stub.expectedHeader->coap_status = COAP_STATUS_OK;
|
||||
sn_coap_protocol_stub.expectedHeader->msg_code = 1;
|
||||
retValue = 0;
|
||||
/* request received */
|
||||
if( 0 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, ns_in6addr_any, NULL, 0, process_cb))
|
||||
return false;
|
||||
|
||||
sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s));
|
||||
memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s));
|
||||
sn_coap_protocol_stub.expectedHeader->coap_status = COAP_STATUS_OK;
|
||||
sn_coap_protocol_stub.expectedHeader->msg_code = 1;
|
||||
nsdynmemlib_stub.returnCounter = 1;
|
||||
retValue = -1;
|
||||
if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, ns_in6addr_any, NULL, 0, process_cb))
|
||||
if( 0 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, ns_in6addr_any, NULL, 0, process_cb))
|
||||
return false;
|
||||
|
||||
sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s));
|
||||
|
@ -310,7 +318,7 @@ bool test_coap_message_handler_response_send()
|
|||
if( 0 != coap_message_handler_response_send(handle, 2, 0, header, 1,3,NULL, 0))
|
||||
return false;
|
||||
|
||||
// free(header);
|
||||
free(header);
|
||||
free(sn_coap_protocol_stub.expectedCoap);
|
||||
sn_coap_protocol_stub.expectedCoap = NULL;
|
||||
coap_message_handler_destroy(handle);
|
||||
|
|
|
@ -80,8 +80,8 @@ bool test_coap_security_handler_connect()
|
|||
|
||||
unsigned char pw = "pwd";
|
||||
coap_security_keys_t keys;
|
||||
keys._priv = &pw;
|
||||
keys._priv_len = 3;
|
||||
keys._key = &pw;
|
||||
keys._key_len = 3;
|
||||
if( -1 != coap_security_handler_connect_non_blocking(NULL, true, DTLS, keys, 0, 1) )
|
||||
return false;
|
||||
mbedtls_stub.useCounter = true;
|
||||
|
|
|
@ -22,5 +22,5 @@ TEST_SRC_FILES = \
|
|||
|
||||
include ../MakefileWorker.mk
|
||||
|
||||
CPPUTESTFLAGS += -DFEA_TRACE_SUPPORT
|
||||
CPPUTESTFLAGS += -DFEA_TRACE_SUPPORT -I ../../../../source/
|
||||
|
||||
|
|
|
@ -75,3 +75,32 @@ TEST(coap_service_api, test_conn_handler_callbacks)
|
|||
CHECK(test_conn_handler_callbacks());
|
||||
}
|
||||
|
||||
TEST(coap_service_api, test_certificate_set)
|
||||
{
|
||||
CHECK(test_certificate_set());
|
||||
}
|
||||
|
||||
TEST(coap_service_api, test_handshake_timeout_set)
|
||||
{
|
||||
CHECK(test_handshake_timeout_set());
|
||||
}
|
||||
|
||||
TEST(coap_service_api, test_coap_duplcate_msg_buffer_set)
|
||||
{
|
||||
CHECK(test_coap_duplcate_msg_buffer_set());
|
||||
}
|
||||
|
||||
TEST(coap_service_api, test_coap_service_get_internal_timer_ticks)
|
||||
{
|
||||
CHECK(test_coap_service_get_internal_timer_ticks())
|
||||
}
|
||||
|
||||
TEST(coap_service_api, test_coap_service_if_find_by_socket)
|
||||
{
|
||||
CHECK(test_coap_service_if_find_by_socket())
|
||||
}
|
||||
|
||||
TEST(coap_service_api, test_coap_service_handshake_limit_set)
|
||||
{
|
||||
CHECK(test_coap_service_handshake_limit_set())
|
||||
}
|
||||
|
|
|
@ -10,14 +10,15 @@
|
|||
#include "eventOS_event_stub.h"
|
||||
#include "eventOS_event.h"
|
||||
#include "net_interface.h"
|
||||
#include "coap_service_api.c"
|
||||
|
||||
int sec_done_cb(int8_t service_id, uint8_t address[static 16], uint8_t keyblock[static 40]){
|
||||
int sec_done_cb_test(int8_t service_id, uint8_t address[static 16], uint8_t keyblock[static 40]){
|
||||
return 2;
|
||||
}
|
||||
|
||||
int sec_start_cb(int8_t service_id, uint8_t address[static 16], uint16_t port, uint8_t* pw, uint8_t *pw_len)
|
||||
{
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int request_recv_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *request_ptr)
|
||||
|
@ -284,6 +285,7 @@ bool test_coap_callbacks()
|
|||
|
||||
free( coap_message_handler_stub.coap_ptr );
|
||||
coap_message_handler_stub.coap_ptr = NULL;
|
||||
coap_service_handle = NULL;
|
||||
|
||||
free( thread_conn_handler_stub.handler_obj );
|
||||
thread_conn_handler_stub.handler_obj = NULL;
|
||||
|
@ -322,7 +324,7 @@ bool test_conn_handler_callbacks()
|
|||
thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t));
|
||||
memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t));
|
||||
nsdynmemlib_stub.returnCounter = 1;
|
||||
if( 1 != coap_service_initialize(1, 2, COAP_SERVICE_OPTIONS_SECURE_BYPASS, &sec_start_cb, &sec_done_cb ))
|
||||
if( 1 != coap_service_initialize(1, 2, COAP_SERVICE_OPTIONS_SECURE_BYPASS, &sec_start_cb, &sec_done_cb_test ))
|
||||
return false;
|
||||
|
||||
if( thread_conn_handler_stub.send_to_sock_cb ){
|
||||
|
@ -389,11 +391,15 @@ bool test_conn_handler_callbacks()
|
|||
}
|
||||
|
||||
if(thread_conn_handler_stub.get_passwd_cb){
|
||||
coap_security_keys_t security_ptr;
|
||||
memset(&security_ptr, 0, sizeof(coap_security_keys_t));
|
||||
nsdynmemlib_stub.returnCounter = 1;
|
||||
thread_conn_handler_stub.bool_value = true;
|
||||
if( 2 != thread_conn_handler_stub.get_passwd_cb(1, buf, 12, NULL, 0))
|
||||
if( 0 != thread_conn_handler_stub.get_passwd_cb(1, buf, 12, &security_ptr))
|
||||
return false;
|
||||
free(security_ptr._key);
|
||||
thread_conn_handler_stub.bool_value = false;
|
||||
if( -1 != thread_conn_handler_stub.get_passwd_cb(1, buf, 12, NULL, 0))
|
||||
if( -1 != thread_conn_handler_stub.get_passwd_cb(1, buf, 12, NULL))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -423,3 +429,150 @@ bool test_conn_handler_callbacks()
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_certificate_set()
|
||||
{
|
||||
/* Service not found, return failure */
|
||||
if (-1 != coap_service_certificate_set(1, NULL, 0, NULL, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Init service */
|
||||
thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t));
|
||||
memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t));
|
||||
|
||||
nsdynmemlib_stub.returnCounter = 1;
|
||||
if( 1 != coap_service_initialize(1, 2, 0, NULL, NULL ))
|
||||
return false;
|
||||
|
||||
/* Allocation fails */
|
||||
if (-1 != coap_service_certificate_set(1, NULL, 0, NULL, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* All OK */
|
||||
nsdynmemlib_stub.returnCounter = 1;
|
||||
if (0 != coap_service_certificate_set(1, NULL, 0, NULL, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Teardown */
|
||||
coap_service_delete(1);
|
||||
free(thread_conn_handler_stub.handler_obj->security_keys);
|
||||
free(thread_conn_handler_stub.handler_obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_handshake_timeout_set()
|
||||
{
|
||||
/* Service not found, return failure */
|
||||
if (-1 != coap_service_set_handshake_timeout(1, 0, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Init service */
|
||||
thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t));
|
||||
memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t));
|
||||
|
||||
nsdynmemlib_stub.returnCounter = 1;
|
||||
if( 1 != coap_service_initialize(1, 2, 0, NULL, NULL ))
|
||||
return false;
|
||||
|
||||
/* All OK */
|
||||
nsdynmemlib_stub.returnCounter = 1;
|
||||
if (0 != coap_service_set_handshake_timeout(1, 0, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Teardown */
|
||||
coap_service_delete(1);
|
||||
free(thread_conn_handler_stub.handler_obj->security_keys);
|
||||
free(thread_conn_handler_stub.handler_obj);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_coap_duplcate_msg_buffer_set()
|
||||
{
|
||||
bool ret = true;
|
||||
/* no coap handle - return failure */
|
||||
if (-1 != coap_service_set_duplicate_message_buffer(0, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Init service */
|
||||
thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t));
|
||||
memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t));
|
||||
coap_message_handler_stub.coap_ptr = (coap_msg_handler_t *)malloc(sizeof(coap_msg_handler_t));
|
||||
memset(coap_message_handler_stub.coap_ptr, 0, sizeof(coap_msg_handler_t));
|
||||
|
||||
nsdynmemlib_stub.returnCounter = 1;
|
||||
if( 1 != coap_service_initialize(1, 2, 0, NULL, NULL ))
|
||||
ret = false;
|
||||
|
||||
/* All OK */
|
||||
if(0 != coap_service_set_duplicate_message_buffer(0, 0)) {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
/* Teardown */
|
||||
coap_service_delete(1);
|
||||
free(coap_message_handler_stub.coap_ptr);
|
||||
coap_message_handler_stub.coap_ptr = NULL;
|
||||
coap_service_handle = NULL;
|
||||
free(thread_conn_handler_stub.handler_obj);
|
||||
thread_conn_handler_stub.handler_obj = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool test_coap_service_get_internal_timer_ticks()
|
||||
{
|
||||
coap_service_get_internal_timer_ticks();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_coap_service_if_find_by_socket()
|
||||
{
|
||||
/* No service ID - return failure */
|
||||
if (0 != coap_service_id_find_by_socket(1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Init service */
|
||||
thread_conn_handler_stub.handler_obj = (coap_conn_handler_t*)malloc(sizeof(coap_conn_handler_t));
|
||||
memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t));
|
||||
|
||||
nsdynmemlib_stub.returnCounter = 1;
|
||||
thread_conn_handler_stub.bool_value = 0;
|
||||
if( 1 != coap_service_initialize(1, 2, 0, NULL, NULL ))
|
||||
return false;
|
||||
|
||||
/* No matching service ID - return false */
|
||||
if(0 != coap_service_id_find_by_socket(1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
thread_conn_handler_stub.bool_value = 1;
|
||||
/* All OK */
|
||||
if(1 != coap_service_id_find_by_socket(1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Teardown */
|
||||
coap_service_delete(1);
|
||||
free(thread_conn_handler_stub.handler_obj);
|
||||
thread_conn_handler_stub.handler_obj = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_coap_service_handshake_limit_set()
|
||||
{
|
||||
if (0 != coap_service_handshake_limits_set(2, 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,18 @@ bool test_eventOS_callbacks();
|
|||
|
||||
bool test_conn_handler_callbacks();
|
||||
|
||||
bool test_certificate_set();
|
||||
|
||||
bool test_handshake_timeout_set();
|
||||
|
||||
bool test_coap_duplcate_msg_buffer_set();
|
||||
|
||||
bool test_coap_service_get_internal_timer_ticks();
|
||||
|
||||
bool test_coap_service_if_find_by_socket();
|
||||
|
||||
bool test_coap_service_handshake_limit_set();
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t a
|
|||
|
||||
coap_conn_handler_t *connection_handler_create(int (*recv_cb)(int8_t socket_id, uint8_t src_address[static 16], uint16_t port, const uint8_t dst_address[static 16], unsigned char *, int),
|
||||
int (*send_cb)(int8_t socket_id, uint8_t const address[static 16], uint16_t port, const void *, int),
|
||||
int (*pw_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t *pw_ptr, uint8_t *pw_len),
|
||||
int (*pw_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, coap_security_keys_t *security_ptr),
|
||||
void(*done_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t keyblock[static KEY_BLOCK_LEN]) )
|
||||
{
|
||||
thread_conn_handler_stub.send_to_sock_cb = send_cb;
|
||||
|
@ -61,6 +61,11 @@ int8_t coap_connection_handler_set_timeout(coap_conn_handler_t *handler, uint32_
|
|||
return 0;
|
||||
}
|
||||
|
||||
int8_t coap_connection_handler_handshake_limits_set(uint8_t handshakes_limit, uint8_t connections_limit)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void coap_connection_handler_exec(uint32_t time)
|
||||
{
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ typedef struct {
|
|||
|
||||
int (*send_to_sock_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, const void *, int);
|
||||
int (*receive_from_sock_cb)(int8_t socket_id, uint8_t src_address[static 16], uint16_t port, const uint8_t dst_address[static 16], unsigned char *data, int len);
|
||||
int (*get_passwd_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t *pw_ptr, uint8_t *pw_len);
|
||||
int (*get_passwd_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, coap_security_keys_t *security_ptr);
|
||||
void (*sec_done_cb)(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t keyblock[static 40]);
|
||||
|
||||
} thread_conn_handler_stub_def;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue