Skip to content

Commit 1599c6b

Browse files
author
Tero Heinonen
authored
CoAP blockwise transfer support (ARMmbed#94)
- sn_coap_protocol_parse() might call tx-callback. Create transaction before calling that. - Call prepare_blockwise_message() before sending CoAP message. This adds dependency to internal coap header file, and anyhow needs to be done inside the coap protocol library. - API to set blockwise message size
1 parent 40abace commit 1599c6b

File tree

7 files changed

+116
-43
lines changed

7 files changed

+116
-43
lines changed

coap-service/coap_service_api.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,19 @@ extern int8_t coap_service_set_duplicate_message_buffer(int8_t service_id, uint8
353353
*/
354354

355355
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);
356+
357+
/**
358+
* \brief Set CoAP blockwise payload size
359+
*
360+
* Set CoAP blockwise payload limit. If payload is bigger than configured limit, CoAP message will use blockwise option when sending.
361+
*
362+
* \param service_id Id number of the current service.
363+
* \param size Blockwise size. Valid sizes are 16, 32, 64, 128, 256, 512 and 1024 bytes
364+
*
365+
* \return -1 For failure
366+
*- 0 For success
367+
*/
368+
extern int8_t coap_service_blockwise_size_set(int8_t service_id, uint16_t size);
356369
#ifdef __cplusplus
357370
}
358371
#endif

source/coap_message_handler.c

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "coap_service_api_internal.h"
2121
#include "coap_message_handler.h"
2222
#include "mbed-coap/sn_coap_protocol.h"
23+
#include "source/include/sn_coap_protocol_internal.h"
2324
#include "socket_api.h"
2425
#include "ns_types.h"
2526
#include "ns_list.h"
@@ -138,7 +139,6 @@ void transaction_delete(coap_transaction_t *this)
138139
if (!coap_message_handler_transaction_valid(this)) {
139140
return;
140141
}
141-
142142
ns_list_remove(&request_list, this);
143143
transaction_free(this);
144144

@@ -163,11 +163,14 @@ void transactions_delete_all(uint8_t *address_ptr, uint16_t port)
163163
static int8_t coap_rx_function(sn_coap_hdr_s *resp_ptr, sn_nsdl_addr_s *address_ptr, void *param)
164164
{
165165
coap_transaction_t *this = NULL;
166-
(void)address_ptr;
167166
(void)param;
168167

169-
tr_warn("transaction not handled %d", resp_ptr->msg_id);
170-
if (!resp_ptr) {
168+
if (resp_ptr->coap_status == COAP_STATUS_BUILDER_BLOCK_SENDING_DONE) {
169+
return 0;
170+
}
171+
172+
tr_warn("transaction was not handled %d", resp_ptr->msg_id);
173+
if (!resp_ptr || !address_ptr) {
171174
return -1;
172175
}
173176
if(resp_ptr->token_ptr){
@@ -214,6 +217,9 @@ coap_msg_handler_t *coap_message_handler_init(void *(*used_malloc_func_ptr)(uint
214217
/* Set default buffer size for CoAP duplicate message detection */
215218
sn_coap_protocol_set_duplicate_buffer_size(handle->coap, DUPLICATE_MESSAGE_BUFFER_SIZE);
216219

220+
/* Set default blockwise message size. */
221+
sn_coap_protocol_set_block_size(handle->coap, DEFAULT_BLOCKWISE_DATA_SIZE);
222+
217223
/* Set default CoAP retransmission paramters */
218224
sn_coap_protocol_set_retransmission_parameters(handle->coap, COAP_RESENDING_COUNT, COAP_RESENDING_INTERVAL);
219225

@@ -263,6 +269,7 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
263269
sn_nsdl_addr_s src_addr;
264270
sn_coap_hdr_s *coap_message;
265271
int16_t ret_val = 0;
272+
coap_transaction_t *this = NULL;
266273

267274
if (!cb || !handle) {
268275
return -1;
@@ -273,8 +280,19 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
273280
src_addr.type = SN_NSDL_ADDRESS_TYPE_IPV6;
274281
src_addr.port = port;
275282

276-
coap_message = sn_coap_protocol_parse(handle->coap, &src_addr, data_len, data_ptr, NULL);
283+
coap_transaction_t *transaction_ptr = transaction_create();
284+
if (!transaction_ptr) {
285+
return -1;
286+
}
287+
transaction_ptr->service_id = coap_service_id_find_by_socket(socket_id);
288+
transaction_ptr->client_request = false;// this is server transaction
289+
memcpy(transaction_ptr->local_address, *(dst_addr_ptr) == 0xFF ? ns_in6addr_any : dst_addr_ptr, 16);
290+
memcpy(transaction_ptr->remote_address, source_addr_ptr, 16);
291+
transaction_ptr->remote_port = port;
292+
293+
coap_message = sn_coap_protocol_parse(handle->coap, &src_addr, data_len, data_ptr, transaction_ptr);
277294
if (coap_message == NULL) {
295+
transaction_delete(transaction_ptr);
278296
tr_err("CoAP Parsing failed");
279297
return -1;
280298
}
@@ -284,36 +302,26 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
284302
/* Check, if coap itself sends response, or block receiving is ongoing... */
285303
if (coap_message->coap_status != COAP_STATUS_OK && coap_message->coap_status != COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) {
286304
tr_debug("CoAP library responds");
305+
transaction_delete(transaction_ptr);
287306
ret_val = -1;
288307
goto exit;
289308
}
290309

291310
/* Request received */
292311
if (coap_message->msg_code > 0 && coap_message->msg_code < 32) {
293-
coap_transaction_t *transaction_ptr = transaction_create();
294-
if (transaction_ptr) {
295-
transaction_ptr->service_id = coap_service_id_find_by_socket(socket_id);
296-
transaction_ptr->msg_id = coap_message->msg_id;
297-
transaction_ptr->client_request = false;// this is server transaction
298-
transaction_ptr->req_msg_type = coap_message->msg_type;
299-
memcpy(transaction_ptr->local_address, *(dst_addr_ptr) == 0xFF ? ns_in6addr_any : dst_addr_ptr, 16);
300-
memcpy(transaction_ptr->remote_address, source_addr_ptr, 16);
301-
if (coap_message->token_len) {
302-
memcpy(transaction_ptr->token, coap_message->token_ptr, coap_message->token_len);
303-
transaction_ptr->token_len = coap_message->token_len;
304-
}
305-
transaction_ptr->remote_port = port;
306-
if (cb(socket_id, coap_message, transaction_ptr) < 0) {
307-
// negative return value = message ignored -> delete transaction
308-
transaction_delete(transaction_ptr);
309-
}
310-
goto exit;
311-
} else {
312-
ret_val = -1;
312+
transaction_ptr->msg_id = coap_message->msg_id;
313+
transaction_ptr->req_msg_type = coap_message->msg_type;
314+
if (coap_message->token_len) {
315+
memcpy(transaction_ptr->token, coap_message->token_ptr, coap_message->token_len);
316+
transaction_ptr->token_len = coap_message->token_len;
313317
}
318+
if (cb(socket_id, coap_message, transaction_ptr) < 0) {
319+
// negative return value = message ignored -> delete transaction
320+
transaction_delete(transaction_ptr);
321+
}
322+
goto exit;
314323
/* Response received */
315324
} else {
316-
coap_transaction_t *this = NULL;
317325
if (coap_message->token_ptr) {
318326
this = transaction_find_client_by_token(coap_message->token_ptr, coap_message->token_len, source_addr_ptr, port);
319327
}
@@ -331,6 +339,10 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
331339
}
332340

333341
exit:
342+
if (coap_message->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) {
343+
handle->sn_coap_service_free(coap_message->payload_ptr);
344+
}
345+
334346
sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message);
335347

336348
return ret_val;
@@ -350,7 +362,7 @@ uint16_t coap_message_handler_request_send(coap_msg_handler_t *handle, int8_t se
350362
tr_debug("Service %d, send CoAP request payload_len %d", service_id, payload_len);
351363
transaction_ptr = transaction_create();
352364

353-
if (!uri || !transaction_ptr) {
365+
if (!uri || !transaction_ptr || !handle) {
354366
return 0;
355367
}
356368

@@ -383,7 +395,10 @@ uint16_t coap_message_handler_request_send(coap_msg_handler_t *handle, int8_t se
383395

384396
request.payload_len = payload_len;
385397
request.payload_ptr = (uint8_t *) payload_ptr; // Cast away const and trust that nsdl doesn't modify...
386-
data_len = sn_coap_builder_calc_needed_packet_data_size(&request);
398+
399+
prepare_blockwise_message(handle->coap, &request);
400+
401+
data_len = sn_coap_builder_calc_needed_packet_data_size_2(&request, sn_coap_protocol_get_configured_blockwise_size(handle->coap));
387402
data_ptr = own_alloc(data_len);
388403
if(data_len > 0 && !data_ptr){
389404
transaction_delete(transaction_ptr);
@@ -408,6 +423,10 @@ uint16_t coap_message_handler_request_send(coap_msg_handler_t *handle, int8_t se
408423

409424
// Free allocated data
410425
own_free(data_ptr);
426+
if(request.options_list_ptr) {
427+
own_free(request.options_list_ptr);
428+
}
429+
411430
if(request_response_cb == NULL){
412431
//No response expected
413432
return 0;
@@ -426,8 +445,10 @@ static int8_t coap_message_handler_resp_build_and_send(coap_msg_handler_t *handl
426445
dst_addr.addr_len = 16;
427446
dst_addr.type = SN_NSDL_ADDRESS_TYPE_IPV6;
428447
dst_addr.port = transaction_ptr->remote_port;
429-
430-
data_len = sn_coap_builder_calc_needed_packet_data_size(coap_msg_ptr);
448+
#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
449+
prepare_blockwise_message(handle->coap, coap_msg_ptr);
450+
#endif
451+
data_len = sn_coap_builder_calc_needed_packet_data_size_2(coap_msg_ptr, sn_coap_protocol_get_configured_blockwise_size(handle->coap));
431452
data_ptr = own_alloc(data_len);
432453
if (data_len > 0 && !data_ptr) {
433454
return -1;

source/coap_service_api.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,3 +606,12 @@ int8_t coap_service_certificate_set(int8_t service_id, const unsigned char *cert
606606

607607
return 0;
608608
}
609+
610+
int8_t coap_service_blockwise_size_set(int8_t service_id, uint16_t size)
611+
{
612+
if (!coap_service_handle) {
613+
return -1;
614+
}
615+
616+
return sn_coap_protocol_set_block_size(coap_service_handle->coap, size);
617+
}

source/include/coap_message_handler.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@
2323
#include "ns_list.h"
2424

2525
#define TRANSACTION_LIFETIME 180
26+
2627
/* Default value for CoAP duplicate message buffer (0 = disabled) */
2728
#define DUPLICATE_MESSAGE_BUFFER_SIZE 0
2829

30+
/* Default value for CoAP blockwise data size (0 = disabled) */
31+
#define DEFAULT_BLOCKWISE_DATA_SIZE 0
32+
2933
/* Default values for CoAP resendings */
3034
#define COAP_RESENDING_COUNT 3
3135
#define COAP_RESENDING_INTERVAL 10

test/coap-service/unittest/coap_message_handler/test_coap_message_handler.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ bool test_coap_message_handler_init()
8181
retCounter = 1;
8282
sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s));
8383
memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s));
84+
nsdynmemlib_stub.returnCounter = 1;
8485
coap_msg_handler_t *handle = coap_message_handler_init(&test_own_alloc, &test_own_free, &coap_tx_function);
8586
if( NULL == handle )
8687
return false;
@@ -97,6 +98,7 @@ bool test_coap_message_handler_destroy()
9798
retCounter = 1;
9899
sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s));
99100
memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s));
101+
nsdynmemlib_stub.returnCounter = 1;
100102
coap_msg_handler_t *handle = coap_message_handler_init(&test_own_alloc, &test_own_free, &coap_tx_function);
101103

102104
if( 0 != coap_message_handler_destroy(handle) )
@@ -113,6 +115,7 @@ bool test_coap_message_handler_find_transaction()
113115
retCounter = 1;
114116
sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s));
115117
memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s));
118+
nsdynmemlib_stub.returnCounter = 1;
116119
coap_msg_handler_t *handle = coap_message_handler_init(&test_own_alloc, &test_own_free, &coap_tx_function);
117120

118121
uint8_t buf[16];
@@ -140,35 +143,39 @@ bool test_coap_message_handler_coap_msg_process()
140143
{
141144
uint8_t buf[16];
142145
memset(&buf, 1, 16);
146+
bool ret_val = false;
143147
/*Handler is null*/
144148
if( -1 != coap_message_handler_coap_msg_process(NULL, 0, buf, 22, ns_in6addr_any, NULL, 0, NULL))
145-
return false;
149+
goto exit;
146150

147151
retCounter = 1;
148152
sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s));
149153
memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s));
154+
nsdynmemlib_stub.returnCounter = 1;
150155
coap_msg_handler_t *handle = coap_message_handler_init(&test_own_alloc, &test_own_free, &coap_tx_function);
151156

152157
sn_coap_protocol_stub.expectedHeader = NULL;
153158
/* Coap parse returns null */
154159
if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, ns_in6addr_any, NULL, 0, process_cb))
155-
return false;
160+
goto exit;
156161

157162
sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s));
158163
memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s));
159164
sn_coap_protocol_stub.expectedHeader->coap_status = 66;
165+
nsdynmemlib_stub.returnCounter = 1;
160166
/* Coap library responds */
161167
if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, ns_in6addr_any, NULL, 0, process_cb))
162-
return false;
168+
goto exit;
163169

164170
sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s));
165171
memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s));
166172
sn_coap_protocol_stub.expectedHeader->coap_status = COAP_STATUS_OK;
167173
sn_coap_protocol_stub.expectedHeader->msg_code = 1;
168174
retValue = 0;
169175
/* request received */
176+
nsdynmemlib_stub.returnCounter = 1;
170177
if( 0 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, ns_in6addr_any, NULL, 0, process_cb))
171-
return false;
178+
goto exit;
172179

173180
sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s));
174181
memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s));
@@ -177,15 +184,16 @@ bool test_coap_message_handler_coap_msg_process()
177184
nsdynmemlib_stub.returnCounter = 1;
178185
retValue = -1;
179186
if( 0 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, ns_in6addr_any, NULL, 0, process_cb))
180-
return false;
187+
goto exit;
181188

182189
sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s));
183190
memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s));
184191
sn_coap_protocol_stub.expectedHeader->coap_status = COAP_STATUS_OK;
185192
sn_coap_protocol_stub.expectedHeader->msg_code = 333;
193+
nsdynmemlib_stub.returnCounter = 1;
186194

187195
if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, ns_in6addr_any, NULL, 0, process_cb))
188-
return false;
196+
goto exit;
189197

190198
sn_coap_protocol_stub.expectedHeader = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s));
191199
memset(sn_coap_protocol_stub.expectedHeader, 0, sizeof(sn_coap_hdr_s));
@@ -200,27 +208,27 @@ bool test_coap_message_handler_coap_msg_process()
200208
sn_coap_builder_stub.expectedUint16 = 1;
201209
nsdynmemlib_stub.returnCounter = 3;
202210
if( 2 != coap_message_handler_request_send(handle, 3, 0, buf, 24, 1, 2, &uri, 4, NULL, 0, &resp_recv))
203-
return false;
211+
goto exit;
204212

205213
sn_coap_protocol_stub.expectedHeader->msg_id = 2;
206-
// sn_coap_protocol_stub.expectedHeader->token_ptr = (uint8_t*)malloc(4);
207-
// memset(sn_coap_protocol_stub.expectedHeader->token_ptr, 1, 4);
208-
if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, ns_in6addr_any, NULL, 0, process_cb))
209-
return false;
210214

211-
// free(sn_coap_protocol_stub.expectedHeader->token_ptr);
215+
if( -1 != coap_message_handler_coap_msg_process(handle, 0, buf, 22, ns_in6addr_any, NULL, 0, process_cb))
216+
goto exit;
212217

218+
ret_val = true;
219+
exit:
213220
free(sn_coap_protocol_stub.expectedCoap);
214221
sn_coap_protocol_stub.expectedCoap = NULL;
215222
coap_message_handler_destroy(handle);
216-
return true;
223+
return ret_val;
217224
}
218225

219226
bool test_coap_message_handler_request_send()
220227
{
221228
retCounter = 1;
222229
sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s));
223230
memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s));
231+
nsdynmemlib_stub.returnCounter = 1;
224232
coap_msg_handler_t *handle = coap_message_handler_init(&test_own_alloc, &test_own_free, &coap_tx_function);
225233

226234
uint8_t buf[16];
@@ -293,6 +301,7 @@ bool test_coap_message_handler_request_delete()
293301
retCounter = 1;
294302
sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s));
295303
memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s));
304+
nsdynmemlib_stub.returnCounter = 1;
296305
coap_msg_handler_t *handle = coap_message_handler_init(&test_own_alloc, &test_own_free, &coap_tx_function);
297306

298307
uint8_t buf[16];
@@ -329,6 +338,7 @@ bool test_coap_message_handler_response_send()
329338
retCounter = 1;
330339
sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s));
331340
memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s));
341+
nsdynmemlib_stub.returnCounter = 1;
332342
coap_msg_handler_t *handle = coap_message_handler_init(&test_own_alloc, &test_own_free, &coap_tx_function);
333343
sn_coap_hdr_s *header = (sn_coap_hdr_s *)malloc(sizeof(sn_coap_hdr_s));
334344
memset(header, 0, sizeof(sn_coap_hdr_s));
@@ -385,6 +395,7 @@ bool test_coap_message_handler_exec()
385395
retCounter = 1;
386396
sn_coap_protocol_stub.expectedCoap = (struct coap_s*)malloc(sizeof(struct coap_s));
387397
memset(sn_coap_protocol_stub.expectedCoap, 0, sizeof(struct coap_s));
398+
nsdynmemlib_stub.returnCounter = 1;
388399
coap_msg_handler_t *handle = coap_message_handler_init(&test_own_alloc, &test_own_free, &coap_tx_function);
389400

390401
if( 0 != coap_message_handler_exec(handle, 0))

test/coap-service/unittest/stub/sn_coap_builder_stub.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_ms
4949
return sn_coap_builder_stub.expectedUint16;
5050
}
5151

52+
uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size)
53+
{
54+
return sn_coap_builder_stub.expectedUint16;
55+
}
56+
5257
int16_t sn_coap_builder_options_build_add_zero_length_option(uint8_t **dst_packet_data_pptr, uint8_t option_length, uint8_t option_exist, sn_coap_option_numbers_e option_number)
5358
{
5459
return sn_coap_builder_stub.expectedInt16;

test/coap-service/unittest/stub/sn_coap_protocol_stub.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,13 @@ int8_t sn_coap_protocol_delete_retransmission(struct coap_s *handle, uint16_t ms
110110
{
111111
return 0;
112112
}
113+
114+
uint16_t sn_coap_protocol_get_configured_blockwise_size(struct coap_s *handle)
115+
{
116+
return 0;
117+
}
118+
119+
int8_t prepare_blockwise_message(struct coap_s *handle, sn_coap_hdr_s *src_coap_msg_ptr)
120+
{
121+
return 0;
122+
}

0 commit comments

Comments
 (0)