Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MAX44000 PWM_Tone_Library nexpaq_mdk
Fork of LED_Demo by
coap_message_handler.c
00001 /* 00002 * Copyright (c) 2015-2016 ARM Limited. All Rights Reserved. 00003 */ 00004 00005 #include <string.h> 00006 #include "nsdynmemLIB.h" 00007 #include "coap_message_handler.h" 00008 #include "sn_coap_protocol.h" 00009 #include "ns_types.h" 00010 #include "ns_list.h" 00011 #include "ns_trace.h" 00012 #include "randLIB.h" 00013 00014 #define TRACE_GROUP "CoSA" 00015 00016 static void *own_alloc(uint16_t size) 00017 { 00018 if (size) { 00019 return ns_dyn_mem_temporary_alloc(size); 00020 } else { 00021 return 0; 00022 } 00023 } 00024 00025 static void own_free(void *ptr) 00026 { 00027 if (ptr) { 00028 ns_dyn_mem_free(ptr); 00029 } 00030 } 00031 00032 static NS_LIST_DEFINE(request_list, coap_transaction_t, link); 00033 00034 static coap_transaction_t *transaction_find_client_by_token(uint8_t token[4]) 00035 { 00036 coap_transaction_t *this = NULL; 00037 ns_list_foreach(coap_transaction_t, cur_ptr, &request_list) { 00038 if (memcmp(cur_ptr->token,token,4) == 0 && cur_ptr->client_request) { 00039 this = cur_ptr; 00040 break; 00041 } 00042 } 00043 return this; 00044 } 00045 00046 static coap_transaction_t *transaction_find_server(uint16_t msg_id) 00047 { 00048 coap_transaction_t *this = NULL; 00049 ns_list_foreach(coap_transaction_t, cur_ptr, &request_list) { 00050 if (cur_ptr->msg_id == msg_id && !cur_ptr->client_request) { 00051 this = cur_ptr; 00052 break; 00053 } 00054 } 00055 return this; 00056 } 00057 00058 static coap_transaction_t *transaction_find_by_address(uint8_t *address_ptr, uint16_t port) 00059 { 00060 coap_transaction_t *this = NULL; 00061 ns_list_foreach(coap_transaction_t, cur_ptr, &request_list) { 00062 if (cur_ptr->remote_port == port && memcmp(cur_ptr->remote_address, address_ptr, 16) == 0) { 00063 this = cur_ptr; 00064 break; 00065 } 00066 } 00067 return this; 00068 } 00069 00070 static coap_transaction_t *transaction_create(void) 00071 { 00072 coap_transaction_t *this = ns_dyn_mem_alloc(sizeof(coap_transaction_t)); 00073 if (this) { 00074 memset(this, 0, sizeof(coap_transaction_t)); 00075 this->client_request = true;// default to client initiated method 00076 ns_list_add_to_start(&request_list, this); 00077 } 00078 00079 return this; 00080 } 00081 static void transaction_delete(coap_transaction_t *this) 00082 { 00083 if (this) { 00084 ns_list_remove(&request_list, this); 00085 if(this->data_ptr){ 00086 ns_dyn_mem_free(this->data_ptr); 00087 } 00088 ns_dyn_mem_free(this); 00089 } 00090 00091 return; 00092 } 00093 00094 static int8_t coap_rx_function(sn_coap_hdr_s *resp_ptr, sn_nsdl_addr_s *address_ptr, void *param) 00095 { 00096 coap_transaction_t *this = NULL; 00097 (void)address_ptr; 00098 (void)param; 00099 tr_warn("transaction was not handled"); 00100 if (!resp_ptr) { 00101 return -1; 00102 } 00103 if( resp_ptr->token_ptr ){ 00104 this = transaction_find_client_by_token(resp_ptr->token_ptr); 00105 } 00106 if (this && this->resp_cb) { 00107 this->resp_cb(this->service_id, address_ptr->addr_ptr, address_ptr->port, NULL); 00108 } 00109 transaction_delete(this); 00110 return 0; 00111 } 00112 00113 static void coap_service_build_content_format(sn_coap_hdr_s *header, sn_coap_content_format_e format); 00114 00115 coap_msg_handler_t *coap_message_handler_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *), 00116 uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *)){ 00117 00118 if ((used_malloc_func_ptr == NULL) || (used_free_func_ptr == NULL) || (used_tx_callback_ptr == NULL)) { 00119 return NULL; 00120 } 00121 00122 coap_msg_handler_t *handle; 00123 handle = used_malloc_func_ptr(sizeof(coap_msg_handler_t)); 00124 if (handle == NULL) { 00125 return NULL; 00126 } 00127 00128 memset(handle, 0, sizeof(coap_msg_handler_t)); 00129 00130 handle->sn_coap_tx_callback = used_tx_callback_ptr; 00131 00132 handle->sn_coap_service_free = used_free_func_ptr; 00133 handle->sn_coap_service_malloc = used_malloc_func_ptr; 00134 00135 handle->coap = sn_coap_protocol_init(used_malloc_func_ptr, used_free_func_ptr, used_tx_callback_ptr, &coap_rx_function); 00136 if( !handle->coap ){ 00137 used_free_func_ptr(handle); 00138 return NULL; 00139 } 00140 return handle; 00141 } 00142 00143 int8_t coap_message_handler_destroy(coap_msg_handler_t *handle){ 00144 if( !handle ){ 00145 return -1; 00146 } 00147 00148 if( handle->coap ){ 00149 sn_coap_protocol_destroy(handle->coap); 00150 } 00151 00152 //Destroy transactions 00153 ns_list_foreach_safe(coap_transaction_t, cur_ptr, &request_list) { 00154 ns_list_remove(&request_list, cur_ptr); 00155 ns_dyn_mem_free(cur_ptr); 00156 cur_ptr = NULL; 00157 } 00158 00159 handle->sn_coap_service_free(handle); 00160 return 0; 00161 } 00162 00163 coap_transaction_t *coap_message_handler_transaction_valid(coap_transaction_t *tr_ptr) 00164 { 00165 ns_list_foreach(coap_transaction_t, cur_ptr, &request_list) { 00166 if (cur_ptr == tr_ptr) { 00167 return tr_ptr; 00168 } 00169 } 00170 return NULL; 00171 } 00172 00173 coap_transaction_t *coap_message_handler_find_transaction(uint8_t *address_ptr, uint16_t port) 00174 { 00175 if( !address_ptr ) 00176 return NULL; 00177 return transaction_find_by_address( address_ptr, port ); 00178 } 00179 00180 int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t socket_id, uint8_t source_addr_ptr[static 16], uint16_t port, 00181 uint8_t *data_ptr, uint16_t data_len, int16_t (cb)(int8_t, sn_coap_hdr_s *, coap_transaction_t *)) 00182 { 00183 if( !cb || !handle ){ 00184 return -1; 00185 } 00186 sn_nsdl_addr_s src_addr; 00187 sn_coap_hdr_s *coap_message; 00188 src_addr.addr_ptr = source_addr_ptr; 00189 src_addr.addr_len = 16; 00190 src_addr.type = SN_NSDL_ADDRESS_TYPE_IPV6; 00191 src_addr.port = port; 00192 00193 coap_message = sn_coap_protocol_parse(handle->coap, &src_addr, data_len, data_ptr, NULL); 00194 if (coap_message == NULL) { 00195 tr_err("CoAP Parsing failed"); 00196 return -1; 00197 } 00198 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); 00199 /* Check, if coap itself sends response, or block receiving is ongoing... */ 00200 if (coap_message->coap_status != COAP_STATUS_OK && coap_message->coap_status != COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) { 00201 tr_debug("CoAP library responds"); 00202 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message); 00203 return -1; 00204 } 00205 if (coap_message->msg_code > 0 && coap_message->msg_code < 32) { 00206 00207 //TODO Sorry 00208 00209 coap_transaction_t *transaction_ptr = transaction_create(); 00210 if (transaction_ptr) { 00211 00212 transaction_ptr->msg_id = coap_message->msg_id; 00213 transaction_ptr->client_request = false;// this is server transaction 00214 memcpy(transaction_ptr->remote_address, source_addr_ptr, 16); 00215 transaction_ptr->remote_port = port; 00216 00217 int ret = cb(socket_id, coap_message, transaction_ptr); 00218 if (ret != 0) { 00219 tr_debug("Service %d, no response expected", transaction_ptr->service_id); 00220 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message); 00221 transaction_delete(transaction_ptr); 00222 return -1; 00223 } 00224 }else{ 00225 //TODO: handle error case 00226 } 00227 } else { 00228 //response find by MSG id 00229 coap_transaction_t *this = NULL; 00230 if( coap_message->token_ptr ){ 00231 this = transaction_find_client_by_token(coap_message->token_ptr); 00232 } 00233 if (!this) { 00234 tr_error("client transaction not found"); 00235 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message); 00236 return -1; 00237 } 00238 tr_debug("Service %d, response received", this->service_id); 00239 if (this->resp_cb) { 00240 this->resp_cb(this->service_id, source_addr_ptr, port, coap_message); 00241 } 00242 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_message); 00243 transaction_delete(this); 00244 } 00245 return 0; 00246 00247 } 00248 00249 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], 00250 uint16_t destination_port, sn_coap_msg_type_e msg_type, sn_coap_msg_code_e msg_code, const char *uri, 00251 sn_coap_content_format_e cont_type, const uint8_t *payload_ptr, uint16_t payload_len, coap_message_handler_response_recv *request_response_cb) 00252 { 00253 coap_transaction_t *transaction_ptr; 00254 sn_coap_hdr_s request; 00255 sn_nsdl_addr_s dst_addr; 00256 uint8_t token[4]; 00257 uint16_t data_len; 00258 uint8_t *data_ptr; 00259 00260 tr_debug("Service %d, send CoAP request payload_len %d", service_id, payload_len); 00261 transaction_ptr = transaction_create(); 00262 00263 if (!uri || !transaction_ptr) { 00264 return 0; 00265 } 00266 00267 transaction_ptr->service_id = service_id; 00268 transaction_ptr->client_request = true; 00269 transaction_ptr->resp_cb = request_response_cb; 00270 transaction_ptr->options = options; 00271 memcpy(transaction_ptr->remote_address, destination_addr, 16); 00272 transaction_ptr->remote_port = destination_port; 00273 memset(&request, 0, sizeof(request)); 00274 dst_addr.addr_ptr = (uint8_t *) destination_addr; // Cast away const and trust that nsdl doesn't modify... 00275 dst_addr.addr_len = 16; 00276 dst_addr.type = SN_NSDL_ADDRESS_TYPE_IPV6; 00277 dst_addr.port = destination_port; 00278 00279 request.msg_type = msg_type; 00280 request.msg_code = msg_code; 00281 request.uri_path_ptr = (uint8_t *)uri; 00282 request.uri_path_len = strlen(uri); 00283 coap_service_build_content_format(&request, cont_type); 00284 00285 do{ 00286 randLIB_get_n_bytes_random(token,4); 00287 }while(transaction_find_client_by_token(token)); 00288 memcpy(transaction_ptr->token,token,4); 00289 request.token_ptr = transaction_ptr->token; 00290 request.token_len = 4; 00291 00292 request.payload_len = payload_len; 00293 request.payload_ptr = (uint8_t *) payload_ptr; // Cast away const and trust that nsdl doesn't modify... 00294 data_len = sn_coap_builder_calc_needed_packet_data_size(&request); 00295 data_ptr = own_alloc(data_len); 00296 if(data_len > 0 && !data_ptr){ 00297 own_free(request.content_type_ptr); 00298 transaction_delete(transaction_ptr); 00299 return 0; 00300 } 00301 sn_coap_protocol_build(handle->coap, &dst_addr, data_ptr, &request, transaction_ptr); 00302 transaction_ptr->msg_id = request.msg_id; 00303 handle->sn_coap_tx_callback(data_ptr, data_len, &dst_addr, transaction_ptr); 00304 00305 // Free allocated data 00306 own_free(request.content_type_ptr); 00307 own_free(data_ptr); 00308 if(request_response_cb == NULL){ 00309 //No response expected 00310 return 0; 00311 } 00312 return transaction_ptr->msg_id; 00313 } 00314 00315 //TODO: refactor this to use nsdl 00316 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) 00317 { 00318 coap_transaction_t *transaction_ptr; 00319 sn_coap_hdr_s *response; 00320 sn_nsdl_addr_s dst_addr; 00321 uint16_t data_len; 00322 uint8_t *data_ptr; 00323 (void) options; 00324 (void)service_id; 00325 00326 tr_debug("Service %d, send CoAP response", service_id); 00327 if (!request_ptr || !handle) { 00328 tr_error("invalid params"); 00329 return -1; 00330 } 00331 00332 transaction_ptr = transaction_find_server(request_ptr->msg_id); 00333 00334 if (!transaction_ptr) { 00335 tr_error("response transaction not found"); 00336 return -2; 00337 } 00338 dst_addr.addr_ptr = transaction_ptr->remote_address; 00339 dst_addr.addr_len = 16; 00340 dst_addr.type = SN_NSDL_ADDRESS_TYPE_IPV6; 00341 dst_addr.port = transaction_ptr->remote_port; 00342 00343 response = sn_coap_build_response(handle->coap, request_ptr, message_code); 00344 if( !response ){ 00345 return -1; 00346 } 00347 response->payload_len = payload_len; 00348 response->payload_ptr = (uint8_t *) payload_ptr; // Cast away const and trust that nsdl doesn't modify... 00349 coap_service_build_content_format(response, content_type); 00350 00351 data_len = sn_coap_builder_calc_needed_packet_data_size(response); 00352 data_ptr = own_alloc(data_len); 00353 if (data_len > 0 && !data_ptr) { 00354 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response); 00355 //TODO deallocate stuff i quess 00356 return -1; 00357 } 00358 sn_coap_protocol_build(handle->coap, &dst_addr, data_ptr, response, transaction_ptr); 00359 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response); 00360 handle->sn_coap_tx_callback(data_ptr, data_len, &dst_addr, transaction_ptr); 00361 sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, request_ptr); 00362 transaction_delete(transaction_ptr); 00363 own_free(data_ptr); 00364 return 0; 00365 } 00366 00367 int8_t coap_message_handler_exec(coap_msg_handler_t *handle, uint32_t current_time){ 00368 if( !handle ){ 00369 return -1; 00370 } 00371 return sn_coap_protocol_exec(handle->coap, current_time); 00372 } 00373 00374 static void coap_service_build_content_format(sn_coap_hdr_s *header, sn_coap_content_format_e format) 00375 { 00376 if (format == COAP_CT_NONE) { 00377 return; 00378 } 00379 00380 /* Always alloc - CoAP library needs a non-NULL pointer to trigger writing 00381 * of a zero-length option, and it will free the pointer later. 00382 */ 00383 header->content_type_ptr = own_alloc(2); 00384 if (!header->content_type_ptr) { 00385 return; 00386 } 00387 00388 if (format == 0) { /* text/plain */ 00389 header->content_type_len = 0; 00390 } else if (format <= 0xff) { 00391 header->content_type_ptr[0] = format; 00392 header->content_type_len = 1; 00393 } else { 00394 header->content_type_ptr[0] = format >> 8; 00395 header->content_type_ptr[1] = format & 0xff; 00396 header->content_type_len = 2; 00397 } 00398 }
Generated on Tue Jul 12 2022 12:28:28 by
