socket.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. /**
  2. * Copyright (c) 2015 - 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 "nordic_common.h"
  41. #include "sdk_common.h"
  42. #include "sdk_config.h"
  43. #include "nrf_sdm.h"
  44. #include "app_scheduler.h"
  45. #include "app_timer.h"
  46. #include "iot_common.h"
  47. #include "app_error.h"
  48. #include "socket_api.h"
  49. #include "socket_common.h"
  50. #include "socket_trace.h"
  51. #include "sdk_os.h"
  52. #include "transport_if.h"
  53. #include "portdb.h"
  54. #include "errno.h"
  55. #include "mem_manager.h"
  56. #include "ipv6_parse.h"
  57. #include "netinet/in.h"
  58. #include "unistd.h"
  59. #include "sdk_os.h"
  60. #include "nrf_log_ctrl.h"
  61. #include "nrf_log_default_backends.h"
  62. #ifndef SOCKET_ENABLE_API_PARAM_CHECK
  63. #define SOCKET_ENABLE_API_PARAM_CHECK 0
  64. #endif
  65. #include "socket_config.h"
  66. #if SOCKET_CONFIG_LOG_ENABLED == 1
  67. NRF_LOG_MODULE_REGISTER();
  68. #endif
  69. /**
  70. * @defgroup api_param_check API Parameters check macros.
  71. *
  72. * @details Macros that verify parameters passed to the module in the APIs. These macros
  73. * could be mapped to nothing in final versions of code to save execution and size.
  74. * SOCKET_ENABLE_API_PARAM_CHECK should be set to 0 to disable these checks.
  75. *
  76. * @{
  77. */
  78. #if SOCKET_ENABLE_API_PARAM_CHECK == 1
  79. /**@brief Macro to check is module is initialized before requesting one of the module procedures. */
  80. #define VERIFY_MODULE_IS_INITIALIZED() \
  81. do { \
  82. if (m_initialization_state == false) \
  83. { \
  84. return (SDK_ERR_MODULE_NOT_INITIALIZED | IOT_SOCKET_ERR_BASE);\
  85. } \
  86. } while (0)
  87. /**
  88. * @brief Verify NULL parameters are not passed to API by application.
  89. */
  90. #define NULL_PARAM_CHECK(PARAM) \
  91. do { \
  92. if ((PARAM) == NULL) \
  93. { \
  94. set_errno(EFAULT); \
  95. return -1; \
  96. } \
  97. } while (0)
  98. /**
  99. * @brief Verify socket id passed on the API by application is valid.
  100. */
  101. #define VERIFY_SOCKET_ID(ID) \
  102. do { \
  103. if (((ID) < 0) || ((ID) >= NUM_SOCKETS)) \
  104. { \
  105. set_errno(EBADF); \
  106. return -1; \
  107. } \
  108. } while (0)
  109. #else
  110. #define VERIFY_MODULE_IS_INITIALIZED()
  111. #define NULL_PARAM_CHECK(PARAM)
  112. #define VERIFY_SOCKET_ID(ID)
  113. #endif
  114. /** @} */
  115. #define SOCKET_MUTEX_INIT() SDK_MUTEX_INIT(m_socket_mtx);
  116. #define SOCKET_MUTEX_LOCK() SDK_MUTEX_LOCK(m_socket_mtx)
  117. #define SOCKET_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_socket_mtx)
  118. // note: one extra for configuration socket
  119. #define NUM_SOCKETS SOCKET_MAX_SOCKET_COUNT + 1
  120. SDK_MUTEX_DEFINE(m_socket_mtx) /**< Mutex for protecting m_socket_table (not individual entries). */
  121. #define SCHED_QUEUE_SIZE 16 /**< Maximum number of events in the scheduler queue. */
  122. #define SCHED_MAX_EVENT_DATA_SIZE 192 /**< Maximum size of scheduler events. */
  123. static bool m_initialization_state = false; /**< Variable to maintain module initialization state. */
  124. static volatile bool m_interface_up = false; /**< Interface state. */
  125. static socket_t m_socket_table[NUM_SOCKETS]; /**< Socket table. */
  126. const struct in6_addr in6addr_any = { {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /**< IPv6 anycast address. */
  127. 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u} };
  128. #if defined (NRF_LOG_ENABLED) && (NRF_LOG_ENABLED == 1)
  129. void log_init(void)
  130. {
  131. ret_code_t err_code = NRF_LOG_INIT(NULL);
  132. APP_ERROR_CHECK(err_code);
  133. NRF_LOG_DEFAULT_BACKENDS_INIT();
  134. }
  135. #else // defined (NRF_LOG_ENABLED) && (NRF_LOG_ENABLED == 1)
  136. void log_init(void)
  137. {
  138. ;
  139. }
  140. #endif // defined (NRF_LOG_ENABLED) && (NRF_LOG_ENABLED == 1)
  141. uint32_t socket_init(void)
  142. {
  143. memset(m_socket_table, 0, sizeof(m_socket_table));
  144. SOCKET_MUTEX_INIT();
  145. log_init();
  146. uint32_t err_code = nrf_mem_init();
  147. APP_ERROR_CHECK(err_code);
  148. APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
  149. err_code = app_timer_init();
  150. APP_ERROR_CHECK(err_code);
  151. err_code = config_socket_init();
  152. APP_ERROR_CHECK(err_code);
  153. #if SOCKET_TRANSPORT_ENABLE == 1
  154. err_code = portdb_init(SOCKET_MAX_SOCKET_COUNT);
  155. APP_ERROR_CHECK(err_code);
  156. transport_handler_init();
  157. #endif
  158. config_socket_start();
  159. m_initialization_state = true;
  160. SOCKET_TRACE("Socket init complete");
  161. return NRF_SUCCESS;
  162. }
  163. /**
  164. * Finds a free entry in the socket table, marks it as used and returns it. Returns -1 if no entry
  165. * was found.
  166. */
  167. static int socket_allocate(socket_t ** pp_socket)
  168. {
  169. int ret_sock = -1;
  170. SOCKET_MUTEX_LOCK();
  171. for (int sock = 0; sock < NUM_SOCKETS; sock++)
  172. {
  173. SOCKET_TRACE("Looking at socket %d with state %d", (int)sock, m_socket_table[sock].so_state);
  174. if (m_socket_table[sock].so_state == STATE_CLOSED)
  175. {
  176. m_socket_table[sock].so_state = STATE_OPEN;
  177. ret_sock = sock;
  178. *pp_socket = &m_socket_table[sock];
  179. break;
  180. }
  181. }
  182. if (ret_sock < 0)
  183. {
  184. set_errno(EMFILE);
  185. }
  186. SOCKET_MUTEX_UNLOCK();
  187. return ret_sock;
  188. }
  189. static socket_t * socket_find(int sock)
  190. {
  191. SOCKET_MUTEX_LOCK();
  192. socket_t * p_socket = &m_socket_table[sock];
  193. SOCKET_MUTEX_UNLOCK();
  194. return p_socket;
  195. }
  196. static void socket_free(int sock)
  197. {
  198. SOCKET_TRACE("Freeing socket %d", (int)sock);
  199. SOCKET_MUTEX_LOCK();
  200. memset(&m_socket_table[sock], 0, sizeof(m_socket_table[sock]));
  201. m_socket_table[sock].so_state = STATE_CLOSED;
  202. SOCKET_MUTEX_UNLOCK();
  203. }
  204. #if SOCKET_TRANSPORT_ENABLE == 1
  205. void transport_interface_up(void)
  206. {
  207. m_interface_up = true;
  208. }
  209. void transport_interface_down(void)
  210. {
  211. m_interface_up = false;
  212. for (int sock = 0; sock < NUM_SOCKETS; sock++)
  213. {
  214. (void) close(sock);
  215. }
  216. }
  217. #endif
  218. int fcntl(int fd, int cmd, int flags)
  219. {
  220. VERIFY_MODULE_IS_INITIALIZED();
  221. VERIFY_SOCKET_ID(fd);
  222. if (!((cmd == F_SETFL) || (cmd == F_GETFL)))
  223. {
  224. set_errno(EINVAL);
  225. return -1;
  226. }
  227. socket_t * p_socket = socket_find(fd);
  228. if (cmd == F_SETFL)
  229. {
  230. p_socket->so_flags = flags;
  231. }
  232. else if (cmd == F_GETFL)
  233. {
  234. return p_socket->so_flags;
  235. }
  236. return 0;
  237. }
  238. static void socket_set_errno(uint32_t err_code)
  239. {
  240. switch (err_code) {
  241. case UDP_INTERFACE_NOT_READY: // fallthrough
  242. case SOCKET_INTERFACE_NOT_READY:
  243. set_errno(ENETDOWN);
  244. break;
  245. case SOCKET_WOULD_BLOCK:
  246. set_errno(EAGAIN);
  247. break;
  248. case SOCKET_NO_ROUTE:
  249. set_errno(ENETUNREACH);
  250. break;
  251. case NRF_ERROR_NO_MEM: // fallthrough
  252. case SOCKET_NO_MEM:
  253. set_errno(ENOMEM);
  254. break;
  255. case SOCKET_TIMEOUT:
  256. set_errno(ETIMEDOUT);
  257. break;
  258. case SOCKET_NO_AVAILABLE_PORTS:
  259. set_errno(EMFILE);
  260. break;
  261. case SOCKET_PORT_IN_USE: // fallthrough
  262. case SOCKET_ADDRESS_IN_USE:
  263. set_errno(EADDRINUSE);
  264. break;
  265. case SOCKET_INVALID_PARAM:
  266. set_errno(EINVAL);
  267. break;
  268. case SOCKET_UNSUPPORTED_PROTOCOL:
  269. set_errno(EPROTONOSUPPORT);
  270. break;
  271. case SOCKET_NOT_CONNECTED:
  272. set_errno(ENOTCONN);
  273. break;
  274. }
  275. }
  276. int socket(socket_family_t family, socket_type_t type, socket_protocol_t protocol)
  277. {
  278. if (m_initialization_state == false)
  279. {
  280. (void) socket_init();
  281. }
  282. VERIFY_MODULE_IS_INITIALIZED();
  283. int ret_sock = -1;
  284. socket_t * p_socket = NULL;
  285. int sock = socket_allocate(&p_socket);
  286. SOCKET_TRACE("Got value %d from allocate", (int)sock);
  287. if (sock >= 0)
  288. {
  289. p_socket->so_params.so_family = family;
  290. p_socket->so_params.so_protocol = protocol;
  291. p_socket->so_params.so_type = type;
  292. p_socket->so_transport = NULL;
  293. if (family == AF_INET6)
  294. {
  295. #if SOCKET_TRANSPORT_ENABLE == 1
  296. p_socket->so_transport = &transport_impl;
  297. #else
  298. set_errno(EAFNOSUPPORT);
  299. #endif
  300. }
  301. else if (family == AF_NRF_CFG || family == AF_NRF_CFG_INTERNAL)
  302. {
  303. p_socket->so_transport = &config_socket_transport;
  304. }
  305. else
  306. {
  307. set_errno(EAFNOSUPPORT);
  308. }
  309. if (p_socket->so_transport != NULL)
  310. {
  311. uint32_t err_code = p_socket->so_transport->open(p_socket);
  312. socket_set_errno(err_code);
  313. ret_sock = (err_code == NRF_SUCCESS) ? sock : ret_sock;
  314. }
  315. if (ret_sock < 0)
  316. {
  317. socket_free(sock);
  318. }
  319. }
  320. SOCKET_TRACE("Returning socket value %d", (int)ret_sock);
  321. return ret_sock;
  322. }
  323. static uint32_t wait_interface_up(void)
  324. {
  325. SOCKET_TRACE("Waiting for interface to come up");
  326. uint32_t err_code = NRF_SUCCESS;
  327. while (err_code == NRF_SUCCESS && m_interface_up == false)
  328. {
  329. err_code = socket_wait();
  330. }
  331. if (m_interface_up == true)
  332. {
  333. SOCKET_TRACE("Interface is up!");
  334. }
  335. return err_code;
  336. }
  337. static uint32_t socket_interface_up(bool is_blocking)
  338. {
  339. uint32_t err_code = NRF_SUCCESS;
  340. if (m_interface_up == false)
  341. {
  342. if (is_blocking)
  343. {
  344. (void) wait_interface_up();
  345. }
  346. }
  347. if (m_interface_up == false)
  348. {
  349. err_code = SOCKET_INTERFACE_NOT_READY;
  350. }
  351. return err_code;
  352. }
  353. int connect(int sock, const void * p_addr, socklen_t addrlen)
  354. {
  355. VERIFY_MODULE_IS_INITIALIZED();
  356. VERIFY_SOCKET_ID(sock);
  357. NULL_PARAM_CHECK(p_addr);
  358. socket_t * p_socket = socket_find(sock);
  359. bool is_blocking = ((p_socket->so_flags & O_NONBLOCK) == 0);
  360. int ret = -1;
  361. uint32_t err_code = socket_interface_up(is_blocking);
  362. if (err_code != NRF_SUCCESS)
  363. {
  364. socket_set_errno(err_code);
  365. }
  366. else if (p_socket->so_state == STATE_OPEN)
  367. {
  368. err_code = p_socket->so_transport->connect(p_socket, p_addr, addrlen);
  369. if (err_code == NRF_SUCCESS)
  370. {
  371. p_socket->so_state = STATE_CONNECTED;
  372. ret = 0;
  373. }
  374. socket_set_errno(err_code);
  375. }
  376. else if (p_socket->so_state == STATE_CONNECTED)
  377. {
  378. set_errno(EISCONN);
  379. }
  380. else if (p_socket->so_state == STATE_CLOSED)
  381. {
  382. set_errno(EBADF);
  383. }
  384. return ret;
  385. }
  386. ssize_t sendto(int sock,
  387. const void * p_buf,
  388. size_t buflen,
  389. int flags,
  390. const void * p_servaddr,
  391. socklen_t addrlen)
  392. {
  393. VERIFY_MODULE_IS_INITIALIZED();
  394. VERIFY_SOCKET_ID(sock);
  395. NULL_PARAM_CHECK(p_buf);
  396. socket_t * p_socket = socket_find(sock);
  397. if ((p_socket->so_flags & O_NONBLOCK) != 0 &&
  398. (flags & MSG_WAITALL) == 0)
  399. {
  400. flags |= MSG_DONTWAIT;
  401. }
  402. uint32_t err_code = socket_interface_up(((p_socket->so_flags & O_NONBLOCK) == 0) || ((flags & MSG_DONTWAIT) == 0));
  403. ssize_t ret = -1;
  404. if (err_code == NRF_SUCCESS)
  405. {
  406. err_code = p_socket->so_transport->send(p_socket, p_buf, buflen, flags, p_servaddr, addrlen);
  407. if (err_code == NRF_SUCCESS)
  408. {
  409. ret = (ssize_t) buflen;
  410. }
  411. }
  412. socket_set_errno(err_code);
  413. return ret;
  414. }
  415. ssize_t send(int sock, const void * p_buf, size_t buflen, int flags)
  416. {
  417. return sendto(sock, p_buf, buflen, flags, NULL, 0);
  418. }
  419. ssize_t write(int sock, const void * p_buf, size_t buflen)
  420. {
  421. return send(sock, p_buf, buflen, 0);
  422. }
  423. ssize_t recvfrom(int sock,
  424. void * p_buf,
  425. size_t buf_size,
  426. int flags,
  427. void * p_cliaddr,
  428. socklen_t * p_addrlen)
  429. {
  430. VERIFY_MODULE_IS_INITIALIZED();
  431. VERIFY_SOCKET_ID(sock);
  432. NULL_PARAM_CHECK(p_buf);
  433. socket_t * p_socket = socket_find(sock);
  434. ssize_t ret = -1;
  435. uint32_t recv_size = buf_size;
  436. uint32_t err_code = p_socket->so_transport->recv(p_socket,
  437. p_buf,
  438. &recv_size,
  439. flags,
  440. p_cliaddr,
  441. p_addrlen);
  442. if (err_code == NRF_SUCCESS)
  443. {
  444. ret = (ssize_t) recv_size;
  445. }
  446. socket_set_errno(err_code);
  447. return ret;
  448. }
  449. ssize_t recv(int sock, void * p_buf, size_t buf_size, int flags)
  450. {
  451. return recvfrom(sock, p_buf, buf_size, flags, NULL, NULL);
  452. }
  453. ssize_t read(int sock, void * p_buf, size_t buf_size)
  454. {
  455. return recv(sock, p_buf, buf_size, 0);
  456. }
  457. int setsockopt(int sock,
  458. socket_opt_lvl_t level,
  459. int optname,
  460. const void * p_optval,
  461. socklen_t optlen)
  462. {
  463. VERIFY_MODULE_IS_INITIALIZED();
  464. VERIFY_SOCKET_ID(sock);
  465. socket_t * p_socket = socket_find(sock);
  466. uint32_t err_code = p_socket->so_transport->setsockopt(p_socket,
  467. level,
  468. optname,
  469. p_optval,
  470. optlen);
  471. socket_set_errno(err_code);
  472. return (err_code == NRF_SUCCESS ? 0 : -1);
  473. }
  474. int getsockopt(int sock, socket_opt_lvl_t level, int optname, void * p_optval, socklen_t * p_optlen)
  475. {
  476. VERIFY_MODULE_IS_INITIALIZED();
  477. VERIFY_SOCKET_ID(sock);
  478. socket_t * p_socket = socket_find(sock);
  479. uint32_t err_code = p_socket->so_transport->getsockopt(p_socket,
  480. level,
  481. optname,
  482. p_optval,
  483. p_optlen);
  484. socket_set_errno(err_code);
  485. return (err_code == NRF_SUCCESS ? 0 : -1);
  486. }
  487. int bind(int sock, const void * p_addr, socklen_t addrlen)
  488. {
  489. VERIFY_MODULE_IS_INITIALIZED();
  490. VERIFY_SOCKET_ID(sock);
  491. NULL_PARAM_CHECK(p_addr);
  492. socket_t * p_socket = socket_find(sock);
  493. bool is_blocking = ((p_socket->so_flags & O_NONBLOCK) == 0);
  494. int ret = -1;
  495. uint32_t err_code = socket_interface_up(is_blocking);
  496. if (err_code == NRF_SUCCESS)
  497. {
  498. err_code = p_socket->so_transport->bind(p_socket, p_addr, addrlen);
  499. }
  500. if (err_code == NRF_SUCCESS)
  501. {
  502. ret = 0;
  503. }
  504. socket_set_errno(err_code);
  505. return ret;
  506. }
  507. int listen(int sock, int backlog)
  508. {
  509. VERIFY_MODULE_IS_INITIALIZED();
  510. VERIFY_SOCKET_ID(sock);
  511. socket_t * p_socket = socket_find(sock);
  512. uint32_t err_code = p_socket->so_transport->listen(p_socket, backlog);
  513. return (err_code == NRF_SUCCESS ? 0 : -1);
  514. }
  515. int accept(int sock, void * p_cliaddr, socklen_t * p_addrlen)
  516. {
  517. VERIFY_MODULE_IS_INITIALIZED();
  518. VERIFY_SOCKET_ID(sock);
  519. NULL_PARAM_CHECK(p_cliaddr);
  520. NULL_PARAM_CHECK(p_addrlen);
  521. socket_t * p_socket = socket_find(sock);
  522. int ret = -1;
  523. if (p_socket->so_params.so_type != SOCK_STREAM)
  524. {
  525. set_errno(EOPNOTSUPP);
  526. }
  527. else
  528. {
  529. uint32_t err_code = NRF_SUCCESS;
  530. socket_t * p_client = NULL;
  531. int sock_cli = socket_allocate(&p_client);
  532. if (sock_cli >= 0)
  533. {
  534. p_client->so_params = p_socket->so_params;
  535. p_client->so_state = STATE_CONNECTED;
  536. p_client->so_transport = p_socket->so_transport;
  537. err_code = p_socket->so_transport->accept(p_socket, p_client, p_cliaddr, p_addrlen);
  538. }
  539. if (err_code == NRF_SUCCESS)
  540. {
  541. ret = sock_cli;
  542. }
  543. else
  544. {
  545. socket_set_errno(err_code);
  546. socket_free(sock_cli);
  547. }
  548. }
  549. return ret;
  550. }
  551. int close(int sock)
  552. {
  553. VERIFY_MODULE_IS_INITIALIZED();
  554. VERIFY_SOCKET_ID(sock);
  555. socket_t * p_socket = socket_find(sock);
  556. int ret = 0;
  557. if (p_socket->so_state != STATE_CLOSED)
  558. {
  559. uint32_t err_code = p_socket->so_transport->close(p_socket);
  560. ret = (err_code == NRF_SUCCESS) ? 0 : -1;
  561. SOCKET_TRACE("Close socket %d: ret: %d", (int)sock, ret);
  562. socket_free(sock);
  563. }
  564. return ret;
  565. }
  566. int fd_set_cmp(fd_set * set_a, fd_set * set_b)
  567. {
  568. int ret = 0;
  569. if (set_a != NULL && set_b != NULL)
  570. {
  571. for (uint32_t i = 0; i < FD_SETSIZE; i++)
  572. {
  573. if (FD_ISSET(i, set_a) != FD_ISSET(i, set_b))
  574. {
  575. ret = 1;
  576. break;
  577. }
  578. }
  579. }
  580. return ret;
  581. }
  582. int select(int nfds,
  583. fd_set * p_readset,
  584. fd_set * p_writeset,
  585. fd_set * p_exceptset,
  586. const struct timeval * p_timeout)
  587. {
  588. VERIFY_SOCKET_ID(nfds - 1);
  589. // Approximately 10 ms sleep between each iteration
  590. uint32_t timestep = 10000;
  591. uint32_t endtime = 0;
  592. if (p_timeout != NULL)
  593. {
  594. endtime = (p_timeout->tv_sec * 1000000) + p_timeout->tv_usec;
  595. }
  596. fd_set readset;
  597. FD_ZERO(&readset);
  598. fd_set writeset;
  599. FD_ZERO(&writeset);
  600. fd_set exceptset;
  601. FD_ZERO(&exceptset);
  602. #define SELECT_CHECK_SET(in_set, out_set, evt_var) \
  603. if ((in_set) != NULL) \
  604. { \
  605. if (FD_ISSET(sock, (in_set)) && (evt_var) > 0) \
  606. { \
  607. FD_SET(sock, (out_set)); \
  608. num_ready++; \
  609. } \
  610. else \
  611. { \
  612. FD_CLR(sock, (out_set)); \
  613. } \
  614. }
  615. int num_ready = 0;
  616. uint32_t err_code = NRF_SUCCESS;
  617. while (err_code == NRF_SUCCESS)
  618. {
  619. for (int sock = 0; sock < nfds; sock++)
  620. {
  621. socket_t * p_socket = socket_find(sock);
  622. SELECT_CHECK_SET(p_readset, &readset, p_socket->so_read_evt);
  623. SELECT_CHECK_SET(p_writeset, &writeset, p_socket->so_write_evt);
  624. SELECT_CHECK_SET(p_exceptset, &exceptset, p_socket->so_except_evt);
  625. }
  626. // TODO: Check out how app events queue up while we checked the socket
  627. if (fd_set_cmp(p_readset, &readset) == 0 &&
  628. fd_set_cmp(p_writeset, &writeset) == 0 &&
  629. fd_set_cmp(p_exceptset, &exceptset) == 0)
  630. {
  631. break;
  632. }
  633. else
  634. {
  635. if (p_timeout == NULL)
  636. {
  637. err_code = socket_wait();
  638. }
  639. else if (endtime - timestep < endtime)
  640. {
  641. (void) usleep(timestep);
  642. endtime -= timestep;
  643. }
  644. else
  645. {
  646. break;
  647. }
  648. }
  649. }
  650. return num_ready;
  651. }