Merge pull request #20 from ARMmbed/thread_iop_10

Thread iop 10
pull/3240/head
Tero Heinonen 2016-03-14 12:21:26 +02:00
commit 78f1029a64
9 changed files with 169 additions and 67 deletions

View File

@ -11,9 +11,16 @@
#include "socket_api.h"
#include "net_interface.h"
#include "eventOS_event_timer.h"
#include "coap_service_api_internal.h"
#define TRACE_GROUP "ThCH"
typedef enum session_state_e {
SECURE_SESSION_HANDSHAKE_ONGOING = 0,
SECURE_SESSION_OK,
SECURE_SESSION_CLOSED
}session_state_t;
typedef struct internal_socket_s {
coap_conn_handler_t *parent;
@ -59,7 +66,8 @@ typedef struct secure_session {
secure_timer_t timer;
bool secure_done;
session_state_t session_state;
uint32_t last_contact_time;
ns_list_link_t link;
} secure_session_t;
@ -81,10 +89,49 @@ static secure_session_t *secure_session_find_by_timer_id(int8_t timer_id)
return this;
}
static void secure_session_delete(secure_session_t *this)
{
if (this) {
ns_list_remove(&secure_session_list, this);
if( this->sec_handler ){
coap_security_destroy(this->sec_handler);
this->sec_handler = NULL;
}
if(this->timer.timer){
eventOS_timeout_cancel(this->timer.timer);
}
ns_dyn_mem_free(this);
this = NULL;
}
return;
}
static secure_session_t *secure_session_create(internal_socket_t *parent, uint8_t *address_ptr, uint16_t port)
{
if(!address_ptr){
return NULL;
}
if(MAX_SECURE_SESSION_COUNT <= 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) {
if(cur_ptr->session_state == SECURE_SESSION_CLOSED){
if(!to_be_removed || cur_ptr->last_contact_time < to_be_removed->last_contact_time){
to_be_removed = cur_ptr;
}
}
}
if(!to_be_removed){
return NULL;
}
secure_session_delete(to_be_removed);
}
secure_session_t *this = ns_dyn_mem_alloc(sizeof(secure_session_t));
if (!this || !address_ptr) {
if (!this) {
return NULL;
}
memset(this, 0, sizeof(secure_session_t));
@ -108,29 +155,12 @@ static secure_session_t *secure_session_create(internal_socket_t *parent, uint8_
}
this->parent = parent;
this->secure_done = false;
this->session_state = SECURE_SESSION_HANDSHAKE_ONGOING;
ns_list_add_to_start(&secure_session_list, this);
// hack_save_remote_address(address_ptr, port); //TODO not bad hack
return this;
}
static void secure_session_delete(secure_session_t *this)
{
if (this) {
ns_list_remove(&secure_session_list, this);
if( this->sec_handler ){
coap_security_destroy(this->sec_handler);
this->sec_handler = NULL;
}
if(this->timer.timer){
eventOS_timeout_cancel(this->timer.timer);
}
ns_dyn_mem_free(this);
this = NULL;
}
return;
}
static void clear_secure_sessions(internal_socket_t *this){
if( this ){
@ -220,12 +250,12 @@ static void int_socket_delete(internal_socket_t *this)
ns_dyn_mem_free(this->data);
this->data = NULL;
}
if(this->parent){
ns_dyn_mem_free(this->parent);
}
ns_dyn_mem_free(this);
this = NULL;
}
}
return;
}
static internal_socket_t *int_socket_find_by_socket_id(int8_t id)
@ -414,7 +444,7 @@ static void secure_recv_sckt_msg(void *cb_res)
tr_err("secure_recv_sckt_msg session creation failed - OOM");
return;
}
session->last_contact_time = coap_service_get_internal_timer_ticks();
// Start handshake
if( !session->sec_handler->_is_started ){
uint8_t *pw = (uint8_t *)ns_dyn_mem_alloc(64);
@ -430,13 +460,13 @@ static void secure_recv_sckt_msg(void *cb_res)
ns_dyn_mem_free(pw);
}else{
//Continue handshake
if( !session->secure_done ){
if(session->session_state == SECURE_SESSION_HANDSHAKE_ONGOING){
int ret = coap_security_handler_continue_connecting(session->sec_handler);
// Handshake done
if(ret == 0){
eventOS_timeout_cancel(session->timer.timer);
session->timer.timer = NULL;
session->secure_done = true;
session->session_state = SECURE_SESSION_OK;
if( sock->parent->_security_done_cb ){
sock->parent->_security_done_cb(sock->listen_socket, src_address.address,
src_address.identifier,
@ -473,7 +503,7 @@ static void recv_sckt_msg(void *cb_res)
internal_socket_t *sock = int_socket_find_by_socket_id(sckt_data->socket_id);
ns_address_t src_address;
if( sock && read_data(sckt_data, sock, &src_address) == 0 ){
if( sock->parent->_recv_cb ){
if(sock->parent && sock->parent->_recv_cb){
sock->parent->_recv_cb(sock->listen_socket, src_address.address, src_address.identifier, sock->data, sock->data_len);
}
ns_dyn_mem_free(sock->data);
@ -514,6 +544,9 @@ int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t a
tr_err("coap_connection_handler_virtual_recv session creation failed - OOM");
return -1;
}
session->last_contact_time = coap_service_get_internal_timer_ticks();
if( !session->sec_handler->_is_started ){
uint8_t *pw = (uint8_t *)ns_dyn_mem_alloc(64);
uint8_t pw_len;
@ -531,10 +564,10 @@ int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t a
return -1;
}
}else{
if( !session->secure_done ){
if(session->session_state == SECURE_SESSION_HANDSHAKE_ONGOING){
int ret = coap_security_handler_continue_connecting(session->sec_handler);
if(ret == 0){
session->secure_done = true;
session->session_state = SECURE_SESSION_OK;
if( handler->_security_done_cb ){
handler->_security_done_cb(sock->listen_socket,
address, port,
@ -598,19 +631,16 @@ coap_conn_handler_t *connection_handler_create(receive_from_socket_cb *recv_from
handler->_recv_cb = recv_from_cb;
handler->_send_cb = send_to_cb;
// handler->sec_conn_closed_cb = sec_conn_closed_cb;
handler->_get_password_cb = pw_cb;
handler->_security_done_cb = done_cb;
return handler;
}
void connection_handler_destroy(coap_conn_handler_t *handler)
{
if(handler){
int_socket_delete(handler->socket);
handler->socket = NULL;
ns_dyn_mem_free(handler);
int_socket_delete(handler->socket);
ns_dyn_mem_free(handler);
}
}
@ -621,6 +651,8 @@ void connection_handler_close_secure_connection( coap_conn_handler_t *handler, u
secure_session_t *session = secure_session_find( handler->socket, destination_addr_ptr, port);
if( session ){
coap_security_send_close_alert( session->sec_handler );
session->session_state = SECURE_SESSION_CLOSED;
session->last_contact_time = coap_service_get_internal_timer_ticks();
}
}
}
@ -642,15 +674,18 @@ int coap_connection_handler_open_connection(coap_conn_handler_t *handler, uint16
internal_socket_t *current = !use_ephemeral_port?int_socket_find(listen_port, is_secure, is_real_socket, bypassSec):NULL;
if(!current){
handler->socket = int_socket_create(listen_port, use_ephemeral_port, is_secure, is_real_socket, bypassSec);
if( !handler->socket ){
if(!handler->socket){
return -1;
}
handler->socket->parent = handler;
handler->socket->parent = ns_dyn_mem_alloc(sizeof(coap_conn_handler_t));
if(!handler->socket->parent){
int_socket_delete(handler->socket);
return -1;
}
*handler->socket->parent = *handler;
}else{
current->usage_counter++;
handler->socket = current;
//handler->parent cannot be set here!
//this will be always problematic if 2 or more secure sockets try to share a same port!
}
return 0;
}
@ -665,12 +700,13 @@ int coap_connection_handler_send_data(coap_conn_handler_t *handler, ns_address_t
memcpy(handler->socket->dest_addr.address, dest_addr->address, 16);
handler->socket->dest_addr.identifier = dest_addr->identifier;
handler->socket->dest_addr.type = dest_addr->type;
secure_session_t *session = secure_session_find( handler->socket, dest_addr->address, dest_addr->identifier);
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 ){
return -1;
}
session->last_contact_time = coap_service_get_internal_timer_ticks();
memcpy( handler->socket->dest_addr.address, dest_addr->address, 16 );
handler->socket->dest_addr.identifier = dest_addr->identifier;
handler->socket->dest_addr.type = dest_addr->type;
@ -693,8 +729,9 @@ int coap_connection_handler_send_data(coap_conn_handler_t *handler, ns_address_t
ns_dyn_mem_free(pw);
return -1;
}
}else if( session->secure_done ){
}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;
}
}
@ -736,3 +773,24 @@ int8_t coap_connection_handler_set_timeout(coap_conn_handler_t *handler, uint32_
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->last_contact_time + CLOSED_SECURE_SESSION_TIMEOUT) <= time){
secure_session_delete(cur_ptr);
}
}
if(cur_ptr->session_state == SECURE_SESSION_OK){
if((cur_ptr->last_contact_time + OPEN_SECURE_SESSION_TIMEOUT) <= time){
secure_session_delete(cur_ptr);
}
}
}
}
}

View File

@ -491,8 +491,6 @@ int coap_security_send_close_alert(coap_security_t *sec)
}
if(!mbedtls_ssl_close_notify(&sec->_ssl)){
coap_security_handler_reset(sec);
coap_security_handler_init(sec);
return 0;
}
return -1;

View File

@ -20,6 +20,7 @@
#include "common_functions.h"
#include "coap_connection_handler.h"
#include "net_interface.h"
#include "coap_service_api_internal.h"
static int16_t coap_service_coap_msg_process(int8_t socket_id, uint8_t source_addr_ptr[static 16], uint16_t port, uint8_t *data_ptr, uint16_t data_len);
static int16_t coap_msg_process_callback(int8_t socket_id, sn_coap_hdr_s *coap_message, coap_transaction_t *transaction_ptr);
@ -159,12 +160,14 @@ static void service_event_handler(arm_event_s *event)
if (event->event_type == ARM_LIB_TASKLET_INIT_EVENT) {
tr_debug("service tasklet initialised");
/*initialize coap service and listen socket*/
eventOS_event_timer_request((uint8_t)COAP_TICK_TIMER, ARM_LIB_SYSTEM_TIMER_EVENT, tasklet_id, 1000);
}
if (event->event_type == ARM_LIB_SYSTEM_TIMER_EVENT && event->event_id == COAP_TICK_TIMER) {
coap_message_handler_exec(coap_service_handle, coap_ticks++);
eventOS_event_timer_request((uint8_t)COAP_TICK_TIMER, ARM_LIB_SYSTEM_TIMER_EVENT, tasklet_id, 1000);
if(coap_ticks && !coap_ticks % SECURE_SESSION_CLEAN_INTERVAL){
coap_connection_handler_exec(coap_ticks);
}
}
eventOS_event_timer_request((uint8_t)COAP_TICK_TIMER, ARM_LIB_SYSTEM_TIMER_EVENT, tasklet_id, 1000);
}
static int16_t coap_msg_process_callback(int8_t socket_id, sn_coap_hdr_s *coap_message, coap_transaction_t *transaction_ptr)
@ -299,11 +302,12 @@ 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/*, sec_conn_closed_cb*/, get_passwd_cb, sec_done_cb);
this->conn_handler = connection_handler_create(recv_cb, send_cb, get_passwd_cb, sec_done_cb);
if(!this->conn_handler){
ns_dyn_mem_free(this);
return -1;
}
if (0 > coap_connection_handler_open_connection(this->conn_handler, listen_port, ((this->service_options & COAP_SERVICE_OPTIONS_EPHEMERAL_PORT) == COAP_SERVICE_OPTIONS_EPHEMERAL_PORT),
((this->service_options & COAP_SERVICE_OPTIONS_SECURE) == COAP_SERVICE_OPTIONS_SECURE),
((this->service_options & COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET) != COAP_SERVICE_OPTIONS_VIRTUAL_SOCKET),
@ -333,10 +337,8 @@ void coap_service_delete(int8_t service_id)
return;
}
//TODO: There might be an issue with shared sockets, when deleting!!
if (this->conn_handler){
connection_handler_destroy(this->conn_handler);
this->conn_handler = NULL;
}
//TODO clear all transactions
@ -464,3 +466,8 @@ 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);
}
uint32_t coap_service_get_internal_timer_ticks(void)
{
return coap_ticks;
}

View File

@ -23,6 +23,12 @@
#include <stddef.h>
#include <stdbool.h>
#include "ns_address.h"
#include "coap_service_api_internal.h"
#define MAX_SECURE_SESSION_COUNT 3
#define CLOSED_SECURE_SESSION_TIMEOUT 3600 // Seconds
#define OPEN_SECURE_SESSION_TIMEOUT 18000 // Seconds
#define SECURE_SESSION_CLEAN_INTERVAL 60 // Seconds
struct internal_socket_s;
@ -60,4 +66,6 @@ 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);
void coap_connection_handler_exec(uint32_t time);
#endif

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2016 ARM Limited. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __COAP_SERVICE_API_INTERNAL_H__
#define __COAP_SERVICE_API_INTERNAL_H__
uint32_t coap_service_get_internal_timer_ticks(void);
#endif

View File

@ -17,8 +17,9 @@ TEST_SRC_FILES = \
../stub/nsdynmemLIB_stub.c \
../stub/socket_api_stub.c \
../stub/coap_security_handler_stub.c \
../stub/coap_service_api_stub.c \
include ../MakefileWorker.mk
CPPUTESTFLAGS += -DFEA_TRACE_SUPPORT
CPPUTESTFLAGS += -DFEA_TRACE_SUPPORT -DHAVE_THREAD

View File

@ -82,14 +82,14 @@ bool test_coap_connection_handler_open_connection()
if( 0 != coap_connection_handler_open_connection(handler, 0,true,true,true,false) )
return false;
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,true,true) )
return false;
//open second one
nsdynmemlib_stub.returnCounter = 1;
coap_conn_handler_t *handler2 = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL);
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler2, 22,false,true,true,true) )
return false;
@ -113,7 +113,7 @@ bool test_coap_connection_handler_send_data()
nsdynmemlib_stub.returnCounter = 1;
coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL);
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,false,false) )
return false;
@ -129,7 +129,7 @@ bool test_coap_connection_handler_send_data()
nsdynmemlib_stub.returnCounter = 1;
handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL);
nsdynmemlib_stub.returnCounter = 3;
nsdynmemlib_stub.returnCounter = 4;
if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,false,false) )
return false;
@ -147,7 +147,7 @@ bool test_coap_connection_handler_send_data()
//NON SECURE HERE -->
nsdynmemlib_stub.returnCounter = 1;
handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL);
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler, 22,false,false,false,false) )
return false;
@ -158,7 +158,7 @@ bool test_coap_connection_handler_send_data()
nsdynmemlib_stub.returnCounter = 1;
handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL);
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler, 22,false,false,true,false) )
return false;
@ -182,7 +182,7 @@ bool test_coap_connection_handler_virtual_recv()
nsdynmemlib_stub.returnCounter = 1;
coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL);
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,true,false) )
return false;
@ -218,7 +218,7 @@ bool test_coap_connection_handler_virtual_recv()
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);
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler2, 24,false,true,true,false) )
return false;
@ -249,7 +249,7 @@ bool test_coap_connection_handler_virtual_recv()
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);
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler3, 26,false,false,true,false) )
return false;
@ -271,7 +271,7 @@ bool test_coap_connection_handler_socket_belongs_to()
socket_api_stub.int8_value = 0;
nsdynmemlib_stub.returnCounter = 1;
coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL);
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,true,false) )
return false;
@ -294,7 +294,7 @@ bool test_timer_callbacks()
nsdynmemlib_stub.returnCounter = 1;
coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL);
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,true,false) )
return false;
@ -358,7 +358,7 @@ bool test_socket_api_callbacks()
socket_api_stub.int8_value = 0;
nsdynmemlib_stub.returnCounter = 1;
coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL);
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler, 22,false,false,true,false) )
return false;
@ -380,7 +380,7 @@ bool test_socket_api_callbacks()
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);
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler2, 22,false,true,true,false) )
return false;
@ -437,7 +437,7 @@ bool test_security_callbacks()
nsdynmemlib_stub.returnCounter = 1;
coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL);
nsdynmemlib_stub.returnCounter = 1;
nsdynmemlib_stub.returnCounter = 2;
if( 0 != coap_connection_handler_open_connection(handler, 22,false,true,true,false) )
return false;

View File

@ -60,3 +60,8 @@ int8_t coap_connection_handler_set_timeout(coap_conn_handler_t *handler, uint32_
{
return 0;
}
void coap_connection_handler_exec(uint32_t time)
{
}

View File

@ -2,9 +2,6 @@
* Copyright (c) 2015-2016 ARM Limited. All Rights Reserved.
*/
#include "config.h"
#ifdef HAVE_THREAD
#include <string.h>
#include "ns_types.h"
@ -60,4 +57,7 @@ int8_t coap_service_response_send(int8_t service_id, uint8_t options, sn_coap_hd
return 0;
}
#endif
uint32_t coap_service_get_internal_timer_ticks(void)
{
return 1;
}