coap.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. /**
  2. * Copyright (c) 2014 - 2019, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include <stdbool.h>
  41. #include <string.h>
  42. #include "nordic_common.h"
  43. #include "nrf.h"
  44. #include "coap_api.h"
  45. #include "coap.h"
  46. #include "coap_queue.h"
  47. #include "coap_transport.h"
  48. #include "sdk_common.h"
  49. #include "iot_common.h"
  50. #include "mem_manager.h"
  51. #include "coap_resource.h"
  52. #include "coap_observe_api.h"
  53. #include "coap_observe.h"
  54. #if IOT_COAP_CONFIG_LOG_ENABLED
  55. #define NRF_LOG_MODULE_NAME coap
  56. #define NRF_LOG_LEVEL IOT_COAP_CONFIG_LOG_LEVEL
  57. #define NRF_LOG_INFO_COLOR IOT_COAP_CONFIG_INFO_COLOR
  58. #define NRF_LOG_DEBUG_COLOR IOT_COAP_CONFIG_DEBUG_COLOR
  59. #include "nrf_log.h"
  60. NRF_LOG_MODULE_REGISTER();
  61. #define COAP_TRC NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */
  62. #define COAP_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */
  63. #define COAP_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */
  64. #define COAP_ENTRY() COAP_TRC(">> %s", __func__)
  65. #define COAP_EXIT() COAP_TRC("<< %s", __func__)
  66. #define COAP_EXIT_WITH_RESULT(result) COAP_TRC("<< %s, result: %d", __func__, result)
  67. #else // IOT_COAP_CONFIG_LOG_ENABLED
  68. #define COAP_TRC(...) /**< Disables traces. */
  69. #define COAP_DUMP(...) /**< Disables dumping of octet streams. */
  70. #define COAP_ERR(...) /**< Disables error logs. */
  71. #define COAP_ENTRY(...)
  72. #define COAP_EXIT(...)
  73. #define COAP_EXIT_WITH_RESULT(...)
  74. #endif // IOT_COAP_CONFIG_LOG_ENABLED
  75. #define COAP_REQUEST_ENTITY_MAX_SIZE (BLE_IPSP_RX_BUFFER_SIZE - (IPV6_IP_HEADER_SIZE + \
  76. UDP_HEADER_SIZE)) /** Maximum request entity size. */
  77. SDK_MUTEX_DEFINE(m_coap_mutex) /**< Mutex variable. Currently unused, this declaration does not occupy any space in RAM. */
  78. static uint32_t m_token_seed; /**< Token seed provided by application to be used for generating token numbers. */
  79. static uint32_t m_message_id_counter; /**< Message ID counter, used to generate unique message IDs. */
  80. static coap_error_callback_t m_error_callback; /**< Function pointer to an application CoAP error handler. */
  81. static coap_request_handler_t m_request_handler = NULL; /**< Request handler where to forward all incoming requests. */
  82. #define COAP_MESSAGE_ACK_SET(REMOTE, LOCAL_PORT, MID) { \
  83. memcpy(&m_coap_empty_message.remote, (REMOTE), sizeof(coap_remote_t)); \
  84. m_coap_empty_message.port.port_number = (LOCAL_PORT); \
  85. m_coap_empty_message.header.id = (MID); \
  86. m_coap_empty_message.header.type = COAP_TYPE_ACK; \
  87. }
  88. #define COAP_MESSAGE_RST_SET(REMOTE, LOCAL_PORT, MID) { \
  89. memcpy(&m_coap_empty_message.remote, (REMOTE), sizeof(coap_remote_t)); \
  90. m_coap_empty_message.port.port_number = (LOCAL_PORT); \
  91. m_coap_empty_message.header.id = (MID); \
  92. m_coap_empty_message.header.type = COAP_TYPE_RST; \
  93. }
  94. static coap_message_t m_coap_empty_message = {
  95. .header = {
  96. .version = 1,
  97. .type = COAP_TYPE_ACK,
  98. .token_len = 0,
  99. .code = COAP_CODE_EMPTY_MESSAGE,
  100. .id = 0,
  101. },
  102. .p_payload = NULL,
  103. .payload_len = 0,
  104. .options_count = 0,
  105. .p_arg = NULL,
  106. .response_callback = NULL,
  107. .port = {
  108. .port_number = 0
  109. },
  110. .options_len = 0,
  111. .options_offset = 0,
  112. .p_data = NULL,
  113. .data_len = 0
  114. };
  115. static inline bool is_ping(coap_message_t * p_message)
  116. {
  117. return (p_message->header.code == COAP_CODE_EMPTY_MESSAGE) &&
  118. (p_message->header.type == COAP_TYPE_CON);
  119. }
  120. static inline bool is_ack(coap_message_t * p_message)
  121. {
  122. return (p_message->header.code == COAP_CODE_EMPTY_MESSAGE) &&
  123. (p_message->header.type == COAP_TYPE_ACK);
  124. }
  125. static inline bool is_reset(coap_message_t * p_message)
  126. {
  127. return (p_message->header.type == COAP_TYPE_RST);
  128. }
  129. static inline bool is_con(coap_message_t * p_message)
  130. {
  131. return (p_message->header.type == COAP_TYPE_CON);
  132. }
  133. static inline bool is_non(coap_message_t * p_message)
  134. {
  135. return (p_message->header.type == COAP_TYPE_NON);
  136. }
  137. static inline bool is_request(uint8_t message_code)
  138. {
  139. return (message_code >= 1) && (message_code < 32);
  140. }
  141. static inline bool is_response(uint8_t message_code)
  142. {
  143. return (message_code >= 64) && (message_code < 192);
  144. }
  145. static inline void app_error_notify(uint32_t err_code, coap_message_t * p_message)
  146. {
  147. if (m_error_callback != NULL)
  148. {
  149. COAP_MUTEX_UNLOCK();
  150. m_error_callback(err_code, p_message);
  151. COAP_MUTEX_LOCK();
  152. }
  153. }
  154. uint32_t coap_init(uint32_t token_rand_seed, coap_transport_init_t * p_transport_param)
  155. {
  156. COAP_ENTRY();
  157. uint32_t err_code;
  158. SDK_MUTEX_INIT(m_coap_mutex);
  159. COAP_MUTEX_LOCK();
  160. internal_coap_observe_init();
  161. m_error_callback = NULL;
  162. m_token_seed = token_rand_seed;
  163. (void)m_token_seed;
  164. m_message_id_counter = 1;
  165. err_code = coap_transport_init(p_transport_param);
  166. if (err_code != NRF_SUCCESS)
  167. {
  168. COAP_MUTEX_UNLOCK();
  169. return err_code;
  170. }
  171. err_code = coap_queue_init();
  172. if (err_code != NRF_SUCCESS)
  173. {
  174. COAP_MUTEX_UNLOCK();
  175. return err_code;
  176. }
  177. err_code = coap_resource_init();
  178. COAP_MUTEX_UNLOCK();
  179. COAP_EXIT();
  180. return err_code;
  181. }
  182. uint32_t coap_error_handler_register(coap_error_callback_t error_callback)
  183. {
  184. // TODO: error handling, null pointer, module initilized etc.
  185. COAP_MUTEX_LOCK();
  186. m_error_callback = error_callback;
  187. COAP_MUTEX_UNLOCK();
  188. return NRF_SUCCESS;
  189. }
  190. uint32_t internal_coap_message_send(uint32_t * p_handle, coap_message_t * p_message)
  191. {
  192. if (p_message == NULL)
  193. {
  194. return (NRF_ERROR_NULL | IOT_COAP_ERR_BASE);
  195. }
  196. // Compiled away if COAP_ENABLE_OBSERVE_CLIENT is not set to 1.
  197. coap_observe_client_send_handle(p_message);
  198. COAP_ENTRY();
  199. // Fetch the expected length of the packet serialized by passing length of 0.
  200. uint16_t expected_length = 0;
  201. uint32_t err_code = coap_message_encode(p_message, NULL, &expected_length);
  202. if (err_code != NRF_SUCCESS)
  203. {
  204. return err_code;
  205. }
  206. // Allocate a buffer to serialize the message into.
  207. uint8_t * p_buffer;
  208. uint32_t request_length = expected_length;
  209. err_code = nrf_mem_reserve(&p_buffer, &request_length);
  210. if (err_code != NRF_SUCCESS)
  211. {
  212. COAP_TRC("p_buffer alloc error = 0x%08lX!", err_code);
  213. return err_code;
  214. }
  215. memset(p_buffer, 0, request_length);
  216. COAP_TRC("Alloc mem, p_buffer = %p", (uint8_t *)p_buffer);
  217. // Serialize the message.
  218. uint16_t buffer_length = (uint16_t)request_length;
  219. err_code = coap_message_encode(p_message, p_buffer, &buffer_length);
  220. if (err_code != NRF_SUCCESS)
  221. {
  222. COAP_TRC("Encode error!");
  223. COAP_TRC("Free mem, p_buffer = %p", p_buffer);
  224. UNUSED_VARIABLE(nrf_free(p_buffer));
  225. return err_code;
  226. }
  227. err_code = coap_transport_write(&p_message->port, &p_message->remote, p_buffer, buffer_length);
  228. if (err_code == NRF_SUCCESS)
  229. {
  230. if (is_con(p_message) || (is_non(p_message) &&
  231. is_request(p_message->header.code) &&
  232. (p_message->response_callback != NULL)))
  233. {
  234. coap_queue_item_t item;
  235. item.p_arg = p_message->p_arg;
  236. item.mid = p_message->header.id;
  237. item.callback = p_message->response_callback;
  238. item.p_buffer = p_buffer;
  239. item.buffer_len = buffer_length;
  240. item.timeout_val = COAP_ACK_TIMEOUT * COAP_ACK_RANDOM_FACTOR;
  241. if (p_message->header.type == COAP_TYPE_CON)
  242. {
  243. item.timeout = item.timeout_val;
  244. item.retrans_count = 0;
  245. }
  246. else
  247. {
  248. item.timeout = COAP_MAX_TRANSMISSION_SPAN;
  249. item.retrans_count = COAP_MAX_RETRANSMIT_COUNT;
  250. }
  251. item.port = p_message->port;
  252. item.token_len = p_message->header.token_len;
  253. memcpy(&item.remote, &p_message->remote, sizeof(coap_remote_t));
  254. memcpy(item.token, p_message->token, p_message->header.token_len);
  255. err_code = coap_queue_add(&item);
  256. if (err_code != NRF_SUCCESS)
  257. {
  258. COAP_TRC("Message queue error = 0x%08lX!", err_code);
  259. COAP_TRC("Free mem, p_buffer = %p", p_buffer);
  260. UNUSED_VARIABLE(nrf_free(p_buffer));
  261. return err_code;
  262. }
  263. *p_handle = item.handle;
  264. }
  265. else
  266. {
  267. *p_handle = COAP_MESSAGE_QUEUE_SIZE;
  268. COAP_TRC("Free mem, p_buffer = %p", p_buffer);
  269. UNUSED_VARIABLE(nrf_free(p_buffer));
  270. }
  271. }
  272. else
  273. {
  274. COAP_TRC("Free mem, p_buffer = %p", p_buffer);
  275. UNUSED_VARIABLE(nrf_free(p_buffer));
  276. }
  277. COAP_EXIT();
  278. return err_code;
  279. }
  280. static uint32_t create_response(coap_message_t ** pp_response, coap_message_t * p_request, uint16_t data_size)
  281. {
  282. uint32_t err_code;
  283. // Allocate space for a new message.
  284. uint32_t size = sizeof(coap_message_t);
  285. err_code = nrf_mem_reserve((uint8_t **)pp_response, &size);
  286. if (err_code != NRF_SUCCESS)
  287. {
  288. return err_code;
  289. }
  290. coap_message_t * p_response = (*pp_response);
  291. memset(p_response, 0, sizeof(coap_message_t));
  292. COAP_TRC("Alloc mem, p_response = %p", (uint8_t *)p_response);
  293. if (data_size > 0)
  294. {
  295. // Allocate a scratch buffer for payload and options.
  296. size = data_size;
  297. err_code = nrf_mem_reserve(&(p_response->p_data), &size);
  298. if (err_code != NRF_SUCCESS)
  299. {
  300. return err_code;
  301. }
  302. memset(p_response->p_data, 0, size);
  303. p_response->data_len = size;
  304. COAP_TRC("Alloc mem, p_response->p_data = %p", p_response->p_data);
  305. }
  306. coap_message_conf_t config;
  307. memset (&config, 0, sizeof(coap_message_conf_t));
  308. config.token_len = p_request->header.token_len;
  309. config.id = p_request->header.id;
  310. config.code = COAP_CODE_404_NOT_FOUND;
  311. config.port.port_number = p_request->port.port_number;
  312. memcpy(config.token, p_request->token, p_request->header.token_len);
  313. if ((coap_msg_type_t)p_request->header.type == COAP_TYPE_CON)
  314. {
  315. config.type = COAP_TYPE_ACK;
  316. }
  317. else
  318. {
  319. config.type = (coap_msg_type_t)p_request->header.type;
  320. }
  321. err_code = coap_message_create(p_response, &config);
  322. if (err_code != NRF_SUCCESS)
  323. {
  324. return err_code;
  325. }
  326. (void)coap_message_remote_addr_set(p_response, &p_request->remote);
  327. return NRF_SUCCESS;
  328. }
  329. /**@brief Common function for sending response error message
  330. *
  331. * @param[in] p_message Pointer to the original request message.
  332. * @param[in] code CoAP message code to send in the reponse.
  333. *
  334. * @retval NRF_SUCCESS If the response was sent out successfully.
  335. */
  336. static uint32_t send_error_response(coap_message_t * p_message, uint8_t code)
  337. {
  338. coap_message_t * p_error_response = NULL;
  339. uint32_t err_code = create_response(&p_error_response, p_message, COAP_MESSAGE_DATA_MAX_SIZE);
  340. if (err_code != NRF_SUCCESS)
  341. {
  342. // If message could not be created, notify the application.
  343. app_error_notify(err_code, p_message);
  344. return err_code;
  345. }
  346. // Set the response code.
  347. p_error_response->header.code = code;
  348. if (p_error_response != NULL)
  349. {
  350. uint32_t handle;
  351. err_code = internal_coap_message_send(&handle, p_error_response);
  352. COAP_TRC("Free mem, p_response->p_data = %p", p_error_response->p_data);
  353. UNUSED_VARIABLE(nrf_free(p_error_response->p_data));
  354. COAP_TRC("Free mem, p_response = %p", (uint8_t *)p_error_response);
  355. UNUSED_VARIABLE(nrf_free((uint8_t *)p_error_response));
  356. }
  357. return err_code;
  358. }
  359. uint32_t coap_transport_read(const coap_port_t * p_port,
  360. const coap_remote_t * p_remote,
  361. const coap_remote_t * p_local,
  362. uint32_t result,
  363. const uint8_t * p_data,
  364. uint16_t datalen)
  365. {
  366. COAP_ENTRY();
  367. // Discard all packets if not success or truncated.
  368. if (!(result == NRF_SUCCESS || result == UDP_TRUNCATED_PACKET))
  369. {
  370. return NRF_SUCCESS;
  371. }
  372. uint32_t err_code;
  373. coap_message_t * p_message;
  374. // Allocate space for a new message.
  375. uint32_t size = sizeof(coap_message_t);
  376. err_code = nrf_mem_reserve((uint8_t **)&p_message, &size);
  377. if (err_code != NRF_SUCCESS)
  378. {
  379. return err_code;
  380. }
  381. memset(p_message, 0, sizeof(coap_message_t));
  382. COAP_TRC("Alloc mem, p_message = %p", (uint8_t *)p_message);
  383. err_code = coap_message_decode(p_message, p_data, datalen);
  384. if (err_code != NRF_SUCCESS)
  385. {
  386. app_error_notify(err_code, p_message);
  387. UNUSED_VARIABLE(nrf_free((uint8_t *)p_message));
  388. return err_code;
  389. }
  390. // Copy the remote address information.
  391. memcpy(&p_message->remote, p_remote, sizeof(coap_remote_t));
  392. // Copy the destination address information.
  393. if (p_local)
  394. {
  395. memcpy(&p_message->local, p_local, sizeof(coap_remote_t));
  396. }
  397. // Copy the local port information.
  398. memcpy(&p_message->port, p_port, sizeof(coap_port_t));
  399. if (result == UDP_TRUNCATED_PACKET)
  400. {
  401. app_error_notify(result, p_message);
  402. }
  403. else if (is_ping(p_message))
  404. {
  405. COAP_MESSAGE_RST_SET(&p_message->remote, p_message->port.port_number, p_message->header.id);
  406. uint32_t handle;
  407. err_code = internal_coap_message_send(&handle, &m_coap_empty_message);
  408. }
  409. else if (is_ack(p_message) ||
  410. is_reset(p_message))
  411. {
  412. // Populate the token with the one used sending, before passing it to the application.
  413. coap_queue_item_t * p_item = NULL;
  414. err_code = coap_queue_item_by_mid_get(&p_item, p_message->header.id);
  415. if (err_code == NRF_SUCCESS)
  416. {
  417. if (p_item->callback != NULL)
  418. {
  419. // As the token is missing from peer, it will be added before giving it to the application.
  420. memcpy(p_message->token, p_item->token, p_item->token_len);
  421. p_message->header.token_len = p_item->token_len;
  422. // Compiled away if COAP_ENABLE_OBSERVE_CLIENT is not set to 1.
  423. coap_observe_client_response_handle(p_message, p_item);
  424. COAP_TRC(">> application callback");
  425. COAP_MUTEX_UNLOCK();
  426. if (is_ack(p_message))
  427. {
  428. p_item->callback(NRF_SUCCESS, p_item->p_arg, p_message);
  429. }
  430. else
  431. {
  432. p_item->callback(COAP_TRANSMISSION_RESET_BY_PEER, p_item->p_arg, p_message);
  433. }
  434. COAP_MUTEX_LOCK();
  435. COAP_TRC("<< application callback");
  436. }
  437. COAP_TRC("Free mem, p_item->p_buffer = %p", p_item->p_buffer);
  438. UNUSED_VARIABLE(nrf_free(p_item->p_buffer));
  439. // Remove the queue element, as a match occured.
  440. err_code = coap_queue_remove(p_item);
  441. }
  442. }
  443. else if (is_response(p_message->header.code))
  444. {
  445. COAP_TRC("CoAP message type: RESPONSE");
  446. coap_queue_item_t * p_item;
  447. err_code = coap_queue_item_by_token_get(&p_item, p_message->token, p_message->header.token_len);
  448. if (err_code != NRF_SUCCESS)
  449. {
  450. // Compiled away if COAP_ENABLE_OBSERVE_CLIENT is not set to 1.
  451. coap_observe_client_response_handle(p_message, NULL);
  452. UNUSED_VARIABLE(nrf_free((uint8_t *)p_message));
  453. COAP_MUTEX_UNLOCK();
  454. return err_code;
  455. }
  456. if (p_item->callback != NULL)
  457. {
  458. // Compiled away if COAP_ENABLE_OBSERVE_CLIENT is not set to 1.
  459. coap_observe_client_response_handle(p_message, p_item);
  460. COAP_TRC(">> application callback");
  461. COAP_MUTEX_UNLOCK();
  462. p_item->callback(NRF_SUCCESS, p_item->p_arg, p_message);
  463. COAP_MUTEX_LOCK();
  464. COAP_TRC("<< application callback");
  465. }
  466. COAP_TRC("Free mem, p_item->p_buffer = %p", p_item->p_buffer);
  467. UNUSED_VARIABLE(nrf_free(p_item->p_buffer));
  468. err_code = coap_queue_remove(p_item);
  469. }
  470. else if (is_request(p_message->header.code))
  471. {
  472. COAP_TRC("CoAP message type: REQUEST");
  473. if (m_request_handler != NULL)
  474. {
  475. uint32_t return_code = m_request_handler(p_message);
  476. // If success, then all processing and any responses has been sent
  477. // by the application callback.
  478. // If not success, then send an appropriate error message back to the
  479. // origin with the return_code from the callback.
  480. if (return_code != NRF_SUCCESS)
  481. {
  482. if (return_code == NRF_ERROR_NOT_FOUND)
  483. {
  484. // Send response with provided CoAP code.
  485. (void)send_error_response(p_message, COAP_CODE_404_NOT_FOUND);
  486. }
  487. else if (return_code == NRF_ERROR_NULL)
  488. {
  489. (void)send_error_response(p_message, COAP_CODE_405_METHOD_NOT_ALLOWED);
  490. }
  491. else
  492. {
  493. (void)send_error_response(p_message, COAP_CODE_400_BAD_REQUEST);
  494. }
  495. }
  496. }
  497. else
  498. {
  499. uint8_t * uri_pointers[COAP_RESOURCE_MAX_DEPTH] = {0, };
  500. uint8_t uri_path_count = 0;
  501. uint16_t index;
  502. for (index = 0; index < p_message->options_count; index++)
  503. {
  504. if (p_message->options[index].number == COAP_OPT_URI_PATH)
  505. {
  506. uri_pointers[uri_path_count++] = p_message->options[index].p_data;
  507. }
  508. }
  509. coap_resource_t * found_resource;
  510. err_code = coap_resource_get(&found_resource, uri_pointers, uri_path_count);
  511. if (found_resource != NULL)
  512. {
  513. if (found_resource->callback != NULL)
  514. {
  515. if (((found_resource->permission) & (1 << ((p_message->header.code) - 1))) > 0) // Has permission for the requested CoAP method.
  516. {
  517. COAP_MUTEX_UNLOCK();
  518. found_resource->callback(found_resource, p_message);
  519. COAP_MUTEX_LOCK();
  520. }
  521. else
  522. {
  523. // Reply with Method Not Allowed.
  524. err_code = send_error_response(p_message, COAP_CODE_405_METHOD_NOT_ALLOWED);
  525. }
  526. }
  527. else
  528. {
  529. // Reply with Method Not Allowed.
  530. err_code = send_error_response(p_message, COAP_CODE_405_METHOD_NOT_ALLOWED);
  531. }
  532. }
  533. else
  534. {
  535. // Reply with NOT FOUND.
  536. err_code = send_error_response(p_message, COAP_CODE_404_NOT_FOUND);
  537. }
  538. }
  539. }
  540. COAP_TRC("Free mem, p_message = %p", (uint8_t *)p_message);
  541. UNUSED_VARIABLE(nrf_free((uint8_t *)p_message));
  542. COAP_EXIT();
  543. return err_code;
  544. }
  545. uint32_t coap_message_send(uint32_t * p_handle, coap_message_t * p_message)
  546. {
  547. COAP_MUTEX_LOCK();
  548. uint32_t err_code = internal_coap_message_send(p_handle, p_message);
  549. COAP_MUTEX_UNLOCK();
  550. return err_code;
  551. }
  552. uint32_t coap_message_abort(uint32_t handle)
  553. {
  554. return NRF_ERROR_NOT_SUPPORTED;
  555. }
  556. uint32_t coap_message_new(coap_message_t ** p_request, coap_message_conf_t * p_config)
  557. {
  558. COAP_ENTRY();
  559. uint32_t err_code;
  560. // If port is not configured, return error and skip initialization of the message.
  561. if (p_config->port.port_number == 0)
  562. {
  563. return (NRF_ERROR_INVALID_PARAM | IOT_COAP_ERR_BASE);
  564. }
  565. COAP_MUTEX_LOCK();
  566. // Allocate space for a new message.
  567. uint32_t size = sizeof(coap_message_t);
  568. err_code = nrf_mem_reserve((uint8_t **)p_request, &size);
  569. if (err_code != NRF_SUCCESS)
  570. {
  571. COAP_MUTEX_UNLOCK();
  572. return err_code;
  573. }
  574. memset(*p_request, 0, sizeof(coap_message_t));
  575. COAP_TRC("Alloc mem, *p_request = %p", (uint8_t *)(*p_request));
  576. // Allocate a scratch buffer for payload and options.
  577. size = COAP_MESSAGE_DATA_MAX_SIZE;
  578. err_code = nrf_mem_reserve(&((*p_request)->p_data), &size);
  579. if (err_code != NRF_SUCCESS)
  580. {
  581. COAP_TRC("Allocation of message data buffer failed!");
  582. COAP_TRC("Free mem, *p_request = %p", (uint8_t *)(*p_request));
  583. UNUSED_VARIABLE(nrf_free((uint8_t *)(*p_request)));
  584. COAP_MUTEX_UNLOCK();
  585. return err_code;
  586. }
  587. memset((*p_request)->p_data, 0, size);
  588. (*p_request)->data_len = size;
  589. COAP_TRC("Alloc mem, (*p_request)->p_data = %p", (uint8_t *)((*p_request)->p_data));
  590. if (p_config->id == 0) // Message id is not set, generate one.
  591. {
  592. p_config->id = m_message_id_counter++;
  593. }
  594. err_code = coap_message_create(*p_request, p_config);
  595. COAP_MUTEX_UNLOCK();
  596. COAP_EXIT_WITH_RESULT(err_code);
  597. return err_code;
  598. }
  599. uint32_t coap_message_delete(coap_message_t * p_message)
  600. {
  601. COAP_ENTRY();
  602. COAP_MUTEX_LOCK();
  603. //If this is a request free the coap_message_t and the data buffer.
  604. COAP_TRC("Free mem, p_message->p_data = %p", p_message->p_data);
  605. UNUSED_VARIABLE(nrf_free(p_message->p_data));
  606. COAP_TRC("Free mem, p_message = %p", (uint8_t *)p_message);
  607. UNUSED_VARIABLE(nrf_free((uint8_t *)p_message));
  608. COAP_MUTEX_UNLOCK();
  609. COAP_EXIT();
  610. return NRF_SUCCESS;
  611. }
  612. uint32_t coap_time_tick(void)
  613. {
  614. COAP_MUTEX_LOCK();
  615. coap_transport_process();
  616. // Loop through the message queue to see if any packets needs retransmission, or has timed out.
  617. coap_queue_item_t * p_item = NULL;
  618. while (coap_queue_item_next_get(&p_item, p_item) == NRF_SUCCESS)
  619. {
  620. if (p_item->timeout == 0)
  621. {
  622. // If there is still retransmission attempts left.
  623. if (p_item->retrans_count < COAP_MAX_RETRANSMIT_COUNT)
  624. {
  625. p_item->timeout = p_item->timeout_val * 2;
  626. p_item->timeout_val = p_item->timeout;
  627. p_item->retrans_count++;
  628. // Retransmit the message.
  629. uint32_t err_code = coap_transport_write(&p_item->port, &p_item->remote, p_item->p_buffer, p_item->buffer_len);
  630. if (err_code != NRF_SUCCESS)
  631. {
  632. app_error_notify(err_code, NULL);
  633. }
  634. }
  635. // No more retransmission attempts left, or max transmit span reached.
  636. if ((p_item->timeout > COAP_MAX_TRANSMISSION_SPAN) ||
  637. (p_item->retrans_count >= COAP_MAX_RETRANSMIT_COUNT))
  638. {
  639. COAP_MUTEX_UNLOCK();
  640. p_item->callback(COAP_TRANSMISSION_TIMEOUT, p_item->p_arg, NULL);
  641. COAP_MUTEX_LOCK();
  642. COAP_TRC("Free mem, p_item->p_buffer = %p", p_item->p_buffer);
  643. UNUSED_VARIABLE(nrf_free(p_item->p_buffer));
  644. (void)coap_queue_remove(p_item);
  645. }
  646. }
  647. else
  648. {
  649. p_item->timeout--;
  650. }
  651. }
  652. COAP_MUTEX_UNLOCK();
  653. return NRF_SUCCESS;
  654. }
  655. uint32_t coap_request_handler_register(coap_request_handler_t p_request_handler)
  656. {
  657. COAP_MUTEX_LOCK();
  658. m_request_handler = p_request_handler;
  659. COAP_MUTEX_UNLOCK();
  660. return NRF_SUCCESS;
  661. }
  662. __WEAK void coap_transport_input(void)
  663. {
  664. // By default not implemented. Transport specific.
  665. }
  666. void coap_input(void)
  667. {
  668. COAP_MUTEX_LOCK();
  669. coap_transport_input();
  670. COAP_MUTEX_UNLOCK();
  671. }