Skip to content

Commit a0faabb

Browse files
author
Tero Heinonen
committed
Merge pull request #15 from ARMmbed/timer_refactor
CoAP service refactoring:
2 parents d7dca8a + 6dd666a commit a0faabb

File tree

8 files changed

+133
-83
lines changed

8 files changed

+133
-83
lines changed

source/coap_connection_handler.c

Lines changed: 86 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include "nsdynmemLIB.h"
1111
#include "socket_api.h"
1212
#include "net_interface.h"
13-
#include "eventOS_callback_timer.h"
13+
#include "eventOS_event_timer.h"
1414

1515
#define TRACE_GROUP "ThCH"
1616

@@ -35,17 +35,19 @@ typedef struct internal_socket_s {
3535

3636
static NS_LIST_DEFINE(socket_list, internal_socket_t, link);
3737

38-
static void timer_cb(int8_t timer_id, uint16_t slots);
39-
#define TIMER_FACTOR 20 /* mbedtls timer in ms, our timer in slots (50us), therefore 20 slots per ms */
38+
static void timer_cb(void* param);
39+
4040
#define TIMER_STATE_CANCELLED -1 /* cancelled */
4141
#define TIMER_STATE_NO_EXPIRY 0 /* none of the delays is expired */
4242
#define TIMER_STATE_INT_EXPIRY 1 /* the intermediate delay only is expired */
4343
#define TIMER_STATE_FIN_EXPIRY 2 /* the final delay is expired */
44+
4445
typedef struct secure_timer_s {
45-
int8_t id;
46+
uint8_t id;
47+
timeout_t *timer;
4648
int8_t state;
47-
uint8_t cycles;
48-
uint8_t cycle_count;
49+
uint32_t fin_ms;
50+
uint32_t int_ms;
4951
} secure_timer_t;
5052

5153
typedef struct secure_session {
@@ -64,6 +66,18 @@ static int receive_from_socket(int8_t socket_id, unsigned char *buf, size_t len)
6466
static void start_timer(int8_t timer_id, uint32_t int_ms, uint32_t fin_ms);
6567
static int timer_status(int8_t timer_id);
6668

69+
static secure_session_t *secure_session_find_by_timer_id(int8_t timer_id)
70+
{
71+
secure_session_t *this = NULL;
72+
ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) {
73+
if (cur_ptr->timer.id == timer_id) {
74+
this = cur_ptr;
75+
break;
76+
}
77+
}
78+
return this;
79+
}
80+
6781
static secure_session_t *secure_session_create(internal_socket_t *parent, uint8_t *address_ptr, uint16_t port)
6882
{
6983
secure_session_t *this = ns_dyn_mem_alloc(sizeof(secure_session_t));
@@ -72,12 +86,16 @@ static secure_session_t *secure_session_create(internal_socket_t *parent, uint8_
7286
}
7387
memset(this, 0, sizeof(secure_session_t));
7488

75-
this->timer.id = eventOS_callback_timer_register(timer_cb);
76-
if (this->timer.id == -1) {
77-
tr_error("tasklet alloc failed");
78-
ns_dyn_mem_free(this);
79-
return NULL;
89+
uint8_t timer_id = 1;
90+
91+
while(secure_session_find_by_timer_id(timer_id)){
92+
if(timer_id == 0xff){
93+
ns_dyn_mem_free(this);
94+
return NULL;
95+
}
96+
timer_id++;
8097
}
98+
this->timer.id = timer_id;
8199

82100
this->sec_handler = coap_security_create(parent->listen_socket, this->timer.id, address_ptr, port, ECJPAKE,
83101
&send_to_socket, &receive_from_socket, &start_timer, &timer_status);
@@ -101,6 +119,9 @@ static void secure_session_delete(secure_session_t *this)
101119
coap_security_destroy(this->sec_handler);
102120
this->sec_handler = NULL;
103121
}
122+
if(this->timer.timer){
123+
eventOS_timeout_cancel(this->timer.timer);
124+
}
104125
ns_dyn_mem_free(this);
105126
this = NULL;
106127
}
@@ -119,32 +140,6 @@ static void clear_secure_sessions(internal_socket_t *this){
119140
}
120141
}
121142

122-
static secure_session_t *secure_session_find_by_timer_id(int8_t timer_id)
123-
{
124-
secure_session_t *this = NULL;
125-
ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) {
126-
if (cur_ptr->timer.id == timer_id) {
127-
this = cur_ptr;
128-
break;
129-
}
130-
}
131-
return this;
132-
}
133-
134-
static secure_session_t *secure_session_find_by_parent(internal_socket_t *parent)
135-
{
136-
secure_session_t *this = NULL;
137-
ns_list_foreach(secure_session_t, cur_ptr, &secure_session_list) {
138-
if( cur_ptr->sec_handler ){
139-
if (cur_ptr->parent == parent ) {
140-
this = cur_ptr;
141-
break;
142-
}
143-
}
144-
}
145-
return this;
146-
}
147-
148143
static secure_session_t *secure_session_find(internal_socket_t *parent, uint8_t *address_ptr, uint16_t port)
149144
{
150145
secure_session_t *this = NULL;
@@ -305,29 +300,36 @@ static int receive_from_socket(int8_t socket_id, unsigned char *buf, size_t len)
305300
* TODO - might be better to use an event timer in conjunction with
306301
* CoAP tasklet
307302
*/
308-
static void timer_cb(int8_t timer_id, uint16_t slots)
303+
static void timer_cb(void *param)
309304
{
310-
(void)slots; /* No need to look at slots */
311-
312-
secure_session_t *sec = secure_session_find_by_timer_id(timer_id);
305+
secure_session_t *sec = param;
313306
if( sec ){
314-
if (++sec->timer.cycle_count == sec->timer.cycles) {
307+
if(sec->timer.fin_ms > sec->timer.int_ms){
308+
/* Intermediate expiry */
309+
sec->timer.fin_ms -= sec->timer.int_ms;
310+
sec->timer.state = TIMER_STATE_INT_EXPIRY;
311+
int error = coap_security_handler_continue_connecting(sec->sec_handler);
312+
if(MBEDTLS_ERR_SSL_TIMEOUT == error) {
313+
//TODO: How do we handle timeouts?
314+
secure_session_delete(sec);
315+
}
316+
else{
317+
sec->timer.timer = eventOS_timeout_ms(timer_cb, sec->timer.int_ms, (void*)sec);
318+
}
319+
}
320+
else{
315321
/* We have counted the number of cycles - finish */
322+
eventOS_timeout_cancel(sec->timer.timer);
323+
sec->timer.fin_ms = 0;
324+
sec->timer.int_ms = 0;
325+
sec->timer.timer = NULL;
316326
sec->timer.state = TIMER_STATE_FIN_EXPIRY;
317-
/* Stop the timer as we no longer need it */
318-
(void)eventOS_callback_timer_stop(sec->timer.id); /* We can ignore return; ID is valid */
319327
int error = coap_security_handler_continue_connecting(sec->sec_handler);
320328
if(MBEDTLS_ERR_SSL_TIMEOUT == error) {
321329
//TODO: How do we handle timeouts?
322330
secure_session_delete(sec);
323331
}
324-
} else {
325-
/* Intermediate expiry */
326-
sec->timer.state = TIMER_STATE_INT_EXPIRY;
327332
}
328-
//TODO: In case of DTLS and count == 1 || 4 we must call continue connecting of security so
329-
//that mbedtls can handle timeout logic: resending etc...
330-
//Not done, because timer should be refactored to be platform specific!
331333
}
332334
}
333335

@@ -336,15 +338,20 @@ static void start_timer(int8_t timer_id, uint32_t int_ms, uint32_t fin_ms)
336338
secure_session_t *sec = secure_session_find_by_timer_id(timer_id);
337339
if( sec ){
338340
if ((int_ms > 0) && (fin_ms > 0)) {
339-
/* Note: as it stands, fin_ms is always 4 * int_ms, so cycles is always 4 but this may change */
340-
sec->timer.cycles = fin_ms/int_ms;
341-
sec->timer.cycle_count = 0;
341+
sec->timer.int_ms = int_ms;
342+
sec->timer.fin_ms = fin_ms;
342343
sec->timer.state = TIMER_STATE_NO_EXPIRY;
343-
eventOS_callback_timer_start(sec->timer.id, int_ms * TIMER_FACTOR);
344+
if(sec->timer.timer){
345+
eventOS_timeout_cancel(sec->timer.timer);
346+
}
347+
sec->timer.timer = eventOS_timeout_ms(timer_cb, int_ms, sec);
344348
} else if (fin_ms == 0) {
345349
/* fin_ms == 0 means cancel the timer */
346350
sec->timer.state = TIMER_STATE_CANCELLED;
347-
(void)eventOS_callback_timer_stop(sec->timer.id); /* We can ignore return; ID will be valid */
351+
eventOS_timeout_cancel(sec->timer.timer);
352+
sec->timer.fin_ms = 0;
353+
sec->timer.int_ms = 0;
354+
sec->timer.timer = NULL;
348355
}
349356
}
350357
}
@@ -390,17 +397,20 @@ static void secure_recv_sckt_msg(void *cb_res)
390397

391398
if( sock && read_data(sckt_data, sock, &src_address) == 0 ){
392399
secure_session_t *session = secure_session_find(sock, src_address.address, src_address.identifier);
400+
401+
// Create session
393402
if( !session ){
394403
memcpy( sock->dest_addr.address, src_address.address, 16 );
395404
sock->dest_addr.identifier = src_address.identifier;
396405
sock->dest_addr.type = src_address.type;
397406
session = secure_session_create(sock, src_address.address, src_address.identifier);
398407
}
399-
400408
if( !session ){
401409
tr_err("secure_recv_sckt_msg session creation failed - OOM");
402410
return;
403411
}
412+
413+
// Start handshake
404414
if( !session->sec_handler->_is_started ){
405415
uint8_t *pw = (uint8_t *)ns_dyn_mem_alloc(64);
406416
uint8_t pw_len;
@@ -414,27 +424,34 @@ static void secure_recv_sckt_msg(void *cb_res)
414424
}
415425
ns_dyn_mem_free(pw);
416426
}else{
427+
//Continue handshake
417428
if( !session->secure_done ){
418-
if( coap_security_handler_continue_connecting(session->sec_handler) == 0){
429+
int ret = coap_security_handler_continue_connecting(session->sec_handler);
430+
// Handshake done
431+
if(ret == 0){
432+
eventOS_timeout_cancel(session->timer.timer);
433+
session->timer.timer = NULL;
419434
session->secure_done = true;
420435
if( sock->parent->_security_done_cb ){
421436
sock->parent->_security_done_cb(sock->listen_socket, src_address.address,
422437
src_address.identifier,
423438
session->sec_handler->_keyblk.value);
424439
}
425440
}
426-
//TODO: error handling
441+
else if (ret < 0){
442+
// error handling
443+
// TODO: here we also should clear CoAP retransmission buffer and inform that CoAP request sending is failed.
444+
secure_session_delete(session);
445+
}
446+
//Session valid
427447
}else{
428448
unsigned char *data = ns_dyn_mem_temporary_alloc(sock->data_len);
429449
int len = 0;
430450
len = coap_security_handler_read(session->sec_handler, data, sock->data_len);
431451
if( len < 0 ){
432452
ns_dyn_mem_free(data);
433453
if( len == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ){
434-
// if( sock->parent->sec_conn_closed_cb ){
435-
// sock->parent->sec_conn_closed_cb(sock->listen_socket);
436454
secure_session_delete( session );
437-
// }
438455
}
439456
}else{
440457
if( sock->parent->_recv_cb ){
@@ -512,7 +529,8 @@ int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t a
512529
}
513530
}else{
514531
if( !session->secure_done ){
515-
if( coap_security_handler_continue_connecting(session->sec_handler) == 0){
532+
int ret = coap_security_handler_continue_connecting(session->sec_handler);
533+
if(ret == 0){
516534
session->secure_done = true;
517535
if( handler->_security_done_cb ){
518536
handler->_security_done_cb(sock->listen_socket,
@@ -521,6 +539,12 @@ int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t a
521539
}
522540
return 0;
523541
}
542+
else if(ret < 0)
543+
{
544+
// error handling
545+
// TODO: here we also should clear CoAP retransmission buffer and inform that CoAP request sending is failed.
546+
secure_session_delete(session);
547+
}
524548
//TODO: error handling
525549
}else{
526550
unsigned char *data = ns_dyn_mem_temporary_alloc(sock->data_len);

source/coap_security_handler.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@ static int coap_security_handler_init(coap_security_t *sec){
6060

6161
sec->_is_started = false;
6262

63+
//TODO: Must have at least 1 strong entropy source, otherwise DTLS will fail.
64+
//This is NOT strong even we say it is!
6365
if( mbedtls_entropy_add_source( &sec->_entropy, entropy_poll, NULL,
64-
128, 0 ) < 0 ){
66+
128, 1 ) < 0 ){
6567
return -1;
6668
}
6769

@@ -433,7 +435,8 @@ int coap_security_handler_connect_non_blocking(coap_security_t *sec, bool is_ser
433435
}
434436

435437
int coap_security_handler_continue_connecting(coap_security_t *sec){
436-
int ret=-1;
438+
int ret = -1;
439+
437440
while( ret != MBEDTLS_ERR_SSL_WANT_READ ){
438441
ret = mbedtls_ssl_handshake_step( &sec->_ssl );
439442

@@ -446,22 +449,20 @@ int coap_security_handler_continue_connecting(coap_security_t *sec){
446449
#endif
447450
return 1;
448451
}
449-
if(MBEDTLS_ERR_SSL_TIMEOUT == ret ||
450-
MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO == ret ||
451-
MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE == ret ||
452-
MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST == ret ||
453-
MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE == ret ||
454-
MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE == ret ||
455-
MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC == ret ||
456-
MBEDTLS_ERR_SSL_BAD_HS_FINISHED == ret) {
457-
return MBEDTLS_ERR_SSL_TIMEOUT;
452+
else if(ret && (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)){
453+
return ret;
458454
}
459-
if( sec->_ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER ){
460455

456+
if( sec->_ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER ){
461457
return 0;
462458
}
463459
}
464-
return ret;
460+
461+
if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE){
462+
return 1;
463+
}
464+
465+
return -1;
465466
}
466467

467468

@@ -500,7 +501,6 @@ int coap_security_handler_read(coap_security_t *sec, unsigned char* buffer, size
500501
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
501502
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
502503
}
503-
504504
return ret; //bytes read
505505
}
506506

test/coap-service/unittest/coap_connection_handler/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ TEST_SRC_FILES = \
1313
../stub/ns_trace_stub.c \
1414
../stub/ns_list_stub.c \
1515
../stub/ns_timer_stub.c \
16+
../stub/timeout_stub.c \
1617
../stub/nsdynmemLIB_stub.c \
1718
../stub/socket_api_stub.c \
1819
../stub/coap_security_handler_stub.c \

test/coap-service/unittest/coap_connection_handler/test_coap_connection_handler.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ bool test_coap_connection_handler_virtual_recv()
227227
return false;
228228

229229
nsdynmemlib_stub.returnCounter = 1;
230+
coap_security_handler_stub.int_value = 0;
230231
coap_security_handler_stub.sec_obj->_remote_port = 12;
231232
memset(coap_security_handler_stub.sec_obj->_remote_address, 1, 16 );
232233
if( 0 != coap_connection_handler_virtual_recv(handler2,buf, 12, &buf, 1) )
@@ -312,16 +313,16 @@ bool test_timer_callbacks()
312313

313314
//Note next tests will affect ns_timer test (cycle & cycle_count
314315
if( coap_security_handler_stub.start_timer_cb ){
315-
coap_security_handler_stub.start_timer_cb(5, 0, 0);
316+
coap_security_handler_stub.start_timer_cb(1, 0, 0);
316317

317-
coap_security_handler_stub.start_timer_cb(5, 1, 2);
318+
coap_security_handler_stub.start_timer_cb(1, 1, 2);
318319
}
319320

320321
if( coap_security_handler_stub.timer_status_cb ){
321322
if( -1 != coap_security_handler_stub.timer_status_cb(4) )
322323
return false;
323324

324-
if( 0 != coap_security_handler_stub.timer_status_cb(5) )
325+
if( 0 != coap_security_handler_stub.timer_status_cb(1) )
325326
return false;
326327
}
327328

test/coap-service/unittest/coap_security_handler/test_coap_security_handler.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,17 +203,17 @@ bool test_coap_security_handler_continue_connecting()
203203
mbedtls_stub.counter = 0;
204204
mbedtls_stub.retArray[0] = MBEDTLS_ERR_SSL_BAD_HS_FINISHED;
205205

206-
if( MBEDTLS_ERR_SSL_TIMEOUT != coap_security_handler_continue_connecting(handle) )
206+
if( MBEDTLS_ERR_SSL_BAD_HS_FINISHED != coap_security_handler_continue_connecting(handle) )
207207
return false;
208208

209209
mbedtls_stub.counter = 0;
210210
mbedtls_stub.retArray[0] = MBEDTLS_ERR_SSL_WANT_READ;
211211

212-
if( MBEDTLS_ERR_SSL_WANT_READ != coap_security_handler_continue_connecting(handle) )
212+
if( 1 != coap_security_handler_continue_connecting(handle) )
213213
return false;
214214

215215
mbedtls_stub.counter = 0;
216-
mbedtls_stub.retArray[0] = HANDSHAKE_FINISHED_VALUE;
216+
mbedtls_stub.retArray[0] = HANDSHAKE_FINISHED_VALUE_RETURN_ZERO;
217217

218218
if( 0 != coap_security_handler_continue_connecting(handle) )
219219
return false;

0 commit comments

Comments
 (0)