usrsock_poll.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /****************************************************************************
  2. * net/usrsock/usrsock_poll.c
  3. *
  4. * Copyright (C) 2015, 2017 Haltian Ltd. All rights reserved.
  5. * Author: Jussi Kivilinna <jussi.kivilinna@haltian.com>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #if defined(CONFIG_NET) && defined(CONFIG_NET_USRSOCK) && \
  40. !defined(CONFIG_DISABLE_POLL)
  41. #include <stdint.h>
  42. #include <string.h>
  43. #include <assert.h>
  44. #include <errno.h>
  45. #include <poll.h>
  46. #include <debug.h>
  47. #include <arch/irq.h>
  48. #include <sys/socket.h>
  49. #include <nuttx/semaphore.h>
  50. #include <nuttx/net/net.h>
  51. #include <nuttx/net/usrsock.h>
  52. #include <nuttx/kmalloc.h>
  53. #include "usrsock/usrsock.h"
  54. /****************************************************************************
  55. * Private Data
  56. ****************************************************************************/
  57. struct usrsock_poll_s
  58. {
  59. FAR struct socket *psock; /* Needed to handle loss of connection */
  60. struct pollfd *fds; /* Needed to handle poll events */
  61. FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
  62. };
  63. /****************************************************************************
  64. * Private Functions
  65. ****************************************************************************/
  66. static uint16_t poll_event(FAR struct net_driver_s *dev, FAR void *pvconn,
  67. FAR void *pvpriv, uint16_t flags)
  68. {
  69. FAR struct usrsock_poll_s *info = (FAR struct usrsock_poll_s *)pvpriv;
  70. FAR struct usrsock_conn_s *conn = pvconn;
  71. pollevent_t eventset = 0;
  72. DEBUGASSERT(!info || (info->psock && info->fds));
  73. if (!info)
  74. return flags;
  75. if (flags & USRSOCK_EVENT_ABORT)
  76. {
  77. ninfo("socket aborted.\n");
  78. /* Socket forcefully terminated. */
  79. eventset |= (POLLERR | POLLHUP);
  80. }
  81. else if ((flags & USRSOCK_EVENT_CONNECT_READY) && !conn->connected)
  82. {
  83. ninfo("socket connect failed.\n");
  84. /* Non-blocking connect failed. */
  85. eventset |= (POLLERR | POLLHUP);
  86. }
  87. else if (flags & USRSOCK_EVENT_REMOTE_CLOSED)
  88. {
  89. ninfo("remote closed.\n");
  90. /* Remote closed. */
  91. eventset |= (POLLHUP | POLLIN);
  92. }
  93. else
  94. {
  95. /* Check data events. */
  96. if (flags & USRSOCK_EVENT_RECVFROM_AVAIL)
  97. {
  98. ninfo("socket recv avail.\n");
  99. eventset |= POLLIN;
  100. }
  101. if (flags & USRSOCK_EVENT_SENDTO_READY)
  102. {
  103. ninfo("socket send ready.\n");
  104. eventset |= POLLOUT;
  105. }
  106. }
  107. /* Filter I/O events depending on requested events. */
  108. eventset &= (~(POLLOUT | POLLIN) | info->fds->events);
  109. /* POLLOUT and PULLHUP are mutually exclusive. */
  110. if ((eventset & POLLOUT) && (eventset & POLLHUP))
  111. {
  112. eventset &= ~POLLOUT;
  113. }
  114. /* Awaken the caller of poll() is requested event occurred. */
  115. if (eventset)
  116. {
  117. info->fds->revents |= eventset;
  118. nxsem_post(info->fds->sem);
  119. }
  120. return flags;
  121. }
  122. /****************************************************************************
  123. * Name: usrsock_poll
  124. *
  125. * Description:
  126. * Setup to monitor events on an usrsock socket
  127. *
  128. * Input Parameters:
  129. * psock - An instance of the internal socket structure.
  130. * fds - The structure describing the events to be monitored.
  131. *
  132. * Returned Value:
  133. * 0: Success; Negated errno on failure
  134. *
  135. ****************************************************************************/
  136. static int usrsock_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds)
  137. {
  138. FAR struct usrsock_conn_s *conn = psock->s_conn;
  139. FAR struct usrsock_poll_s *info;
  140. FAR struct devif_callback_s *cb;
  141. int ret = OK;
  142. /* Sanity check */
  143. #ifdef CONFIG_DEBUG
  144. if (!conn || !fds)
  145. {
  146. return -EINVAL;
  147. }
  148. #endif
  149. /* Allocate a container to hold the poll information */
  150. info = (FAR struct usrsock_poll_s *)kmm_malloc(sizeof(struct usrsock_poll_s));
  151. if (!info)
  152. {
  153. return -ENOMEM;
  154. }
  155. net_lock();
  156. /* Allocate a usrsock callback structure */
  157. cb = devif_callback_alloc(NULL, &conn->list);
  158. if (cb == NULL)
  159. {
  160. ret = -EBUSY;
  161. kmm_free(info); /* fds->priv not set, so we need to free info here. */
  162. goto errout_unlock;
  163. }
  164. /* Initialize the poll info container */
  165. info->psock = psock;
  166. info->fds = fds;
  167. info->cb = cb;
  168. /* Initialize the callback structure. Save the reference to the info
  169. * structure as callback private data so that it will be available during
  170. * callback processing.
  171. */
  172. cb->flags = USRSOCK_EVENT_ABORT | USRSOCK_EVENT_CONNECT_READY |
  173. USRSOCK_EVENT_SENDTO_READY | USRSOCK_EVENT_RECVFROM_AVAIL |
  174. USRSOCK_EVENT_REMOTE_CLOSED;
  175. cb->priv = (FAR void *)info;
  176. cb->event = poll_event;
  177. /* Save the reference in the poll info structure as fds private as well
  178. * for use during poll teardown as well.
  179. */
  180. fds->priv = (FAR void *)info;
  181. /* Check if socket is in error state */
  182. if (conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ||
  183. conn->state == USRSOCK_CONN_STATE_ABORTED)
  184. {
  185. ninfo("socket %s.\n",
  186. conn->state == USRSOCK_CONN_STATE_UNINITIALIZED ?
  187. "uninitialized" : "aborted");
  188. fds->revents |= (POLLERR | POLLHUP);
  189. }
  190. /* Stream sockets need to be connected or connecting (or listening). */
  191. else if ((conn->type == SOCK_STREAM || conn->type == SOCK_SEQPACKET) &&
  192. !(conn->connected || conn->state == USRSOCK_CONN_STATE_CONNECTING))
  193. {
  194. ninfo("stream socket not connected and not connecting.\n");
  195. fds->revents |= (POLLOUT | POLLIN | POLLHUP);
  196. }
  197. else if (conn->flags & USRSOCK_EVENT_REMOTE_CLOSED)
  198. {
  199. ninfo("socket remote closed.\n");
  200. /* Remote closed. */
  201. fds->revents |= (POLLHUP | POLLIN);
  202. }
  203. else
  204. {
  205. /* Check if daemon has room for send data or has data to receive. */
  206. if (conn->flags & USRSOCK_EVENT_SENDTO_READY)
  207. {
  208. ninfo("socket send ready.\n");
  209. fds->revents |= (POLLOUT & fds->events);
  210. }
  211. if (conn->flags & USRSOCK_EVENT_RECVFROM_AVAIL)
  212. {
  213. ninfo("socket recv avail.\n");
  214. fds->revents |= (POLLIN & fds->events);
  215. }
  216. }
  217. /* Filter I/O events depending on requested events. */
  218. fds->revents &= (~(POLLOUT | POLLIN) | info->fds->events);
  219. /* POLLOUT and PULLHUP are mutually exclusive. */
  220. if ((fds->revents & POLLOUT) && (fds->revents & POLLHUP))
  221. {
  222. fds->revents &= ~POLLOUT;
  223. }
  224. /* Check if any requested events are already in effect */
  225. if (fds->revents != 0)
  226. {
  227. /* Yes.. then signal the poll logic */
  228. nxsem_post(fds->sem);
  229. }
  230. errout_unlock:
  231. net_unlock();
  232. return ret;
  233. }
  234. /****************************************************************************
  235. * Name: usrsock_pollteardown
  236. *
  237. * Description:
  238. * Teardown monitoring of events on an usrsock socket
  239. *
  240. * Input Parameters:
  241. * psock - An instance of the internal socket structure.
  242. * fds - The structure describing the events to be stopped being monitored.
  243. *
  244. * Returned Value:
  245. * 0: Success; Negated errno on failure
  246. *
  247. ****************************************************************************/
  248. static int usrsock_pollteardown(FAR struct socket *psock,
  249. FAR struct pollfd *fds)
  250. {
  251. FAR struct usrsock_conn_s *conn = psock->s_conn;
  252. FAR struct usrsock_poll_s *info;
  253. /* Sanity check */
  254. #ifdef CONFIG_DEBUG
  255. if (!conn || !fds->priv)
  256. {
  257. return -EINVAL;
  258. }
  259. #endif
  260. /* Recover the socket descriptor poll state info from the poll structure */
  261. info = (FAR struct usrsock_poll_s *)fds->priv;
  262. DEBUGASSERT(info && info->fds && info->cb);
  263. if (info)
  264. {
  265. /* Release the callback */
  266. net_lock();
  267. devif_conn_callback_free(NULL, info->cb, &conn->list);
  268. net_unlock();
  269. /* Release the poll/select data slot */
  270. info->fds->priv = NULL;
  271. /* Then free the poll info container */
  272. kmm_free(info);
  273. }
  274. return OK;
  275. }
  276. /****************************************************************************
  277. * Public Functions
  278. ****************************************************************************/
  279. /****************************************************************************
  280. * Name: usrsock_poll
  281. *
  282. * Description:
  283. * The standard poll() operation redirects operations on socket descriptors
  284. * to this function.
  285. *
  286. * Input Parameters:
  287. * psock - An instance of the internal socket structure.
  288. * fds - The structure describing the events to be monitored.
  289. * setup - true: Setup up the poll; false: Teardown the poll
  290. *
  291. * Returned Value:
  292. * 0: Success; Negated errno on failure
  293. *
  294. ****************************************************************************/
  295. int usrsock_poll(FAR struct socket *psock, FAR struct pollfd *fds, bool setup)
  296. {
  297. if (setup)
  298. {
  299. return usrsock_pollsetup(psock, fds);
  300. }
  301. else
  302. {
  303. return usrsock_pollteardown(psock, fds);
  304. }
  305. }
  306. #endif /* CONFIG_NET && CONFIG_NET_USRSOCK && !CONFIG_DISABLE_POLL */