pkt_send.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /****************************************************************************
  2. * net/pkt/pkt_send.c
  3. *
  4. * Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  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_PKT)
  40. #include <sys/types.h>
  41. #include <sys/socket.h>
  42. #include <stdint.h>
  43. #include <stdbool.h>
  44. #include <string.h>
  45. #include <errno.h>
  46. #include <debug.h>
  47. #include <arch/irq.h>
  48. #include <nuttx/clock.h>
  49. #include <nuttx/semaphore.h>
  50. #include <nuttx/net/netdev.h>
  51. #include <nuttx/net/net.h>
  52. #include <nuttx/net/ip.h>
  53. #include "netdev/netdev.h"
  54. #include "devif/devif.h"
  55. #include "socket/socket.h"
  56. #include "pkt/pkt.h"
  57. /****************************************************************************
  58. * Private Types
  59. ****************************************************************************/
  60. /* This structure holds the state of the send operation until it can be
  61. * operated upon by the event handler.
  62. */
  63. struct send_s
  64. {
  65. FAR struct socket *snd_sock; /* Points to the parent socket structure */
  66. FAR struct devif_callback_s *snd_cb; /* Reference to callback instance */
  67. sem_t snd_sem; /* Used to wake up the waiting thread */
  68. FAR const uint8_t *snd_buffer; /* Points to the buffer of data to send */
  69. size_t snd_buflen; /* Number of bytes in the buffer to send */
  70. ssize_t snd_sent; /* The number of bytes sent */
  71. };
  72. /****************************************************************************
  73. * Private Functions
  74. ****************************************************************************/
  75. /****************************************************************************
  76. * Name: psock_send_eventhandler
  77. ****************************************************************************/
  78. static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
  79. FAR void *pvconn,
  80. FAR void *pvpriv, uint16_t flags)
  81. {
  82. FAR struct send_s *pstate = (FAR struct send_s *)pvpriv;
  83. ninfo("flags: %04x sent: %d\n", flags, pstate->snd_sent);
  84. if (pstate)
  85. {
  86. /* Check if the outgoing packet is available. It may have been claimed
  87. * by a send event handler serving a different thread -OR- if the
  88. * output buffer currently contains unprocessed incoming data. In
  89. * these cases we will just have to wait for the next polling cycle.
  90. */
  91. if (dev->d_sndlen > 0 || (flags & PKT_NEWDATA) != 0)
  92. {
  93. /* Another thread has beat us sending data or the buffer is busy,
  94. * Check for a timeout. If not timed out, wait for the next
  95. * polling cycle and check again.
  96. */
  97. /* No timeout. Just wait for the next polling cycle */
  98. return flags;
  99. }
  100. /* It looks like we are good to send the data */
  101. else
  102. {
  103. /* Copy the packet data into the device packet buffer and send it */
  104. devif_pkt_send(dev, pstate->snd_buffer, pstate->snd_buflen);
  105. pstate->snd_sent = pstate->snd_buflen;
  106. /* Make sure no ARP request overwrites this ARP request. This
  107. * flag will be cleared in arp_out().
  108. */
  109. IFF_SET_NOARP(dev->d_flags);
  110. }
  111. /* Don't allow any further call backs. */
  112. pstate->snd_cb->flags = 0;
  113. pstate->snd_cb->priv = NULL;
  114. pstate->snd_cb->event = NULL;
  115. /* Wake up the waiting thread */
  116. nxsem_post(&pstate->snd_sem);
  117. }
  118. return flags;
  119. }
  120. /****************************************************************************
  121. * Public Functions
  122. ****************************************************************************/
  123. /****************************************************************************
  124. * Name: psock_pkt_send
  125. *
  126. * Description:
  127. * The psock_pkt_send() call may be used only when the packet socket is in a
  128. * connected state (so that the intended recipient is known).
  129. *
  130. * Input Parameters:
  131. * psock An instance of the internal socket structure.
  132. * buf Data to send
  133. * len Length of data to send
  134. *
  135. * Returned Value:
  136. * On success, returns the number of characters sent. On error,
  137. * a negated errno value is retruend. See send() for the complete list
  138. * of return values.
  139. *
  140. ****************************************************************************/
  141. ssize_t psock_pkt_send(FAR struct socket *psock, FAR const void *buf,
  142. size_t len)
  143. {
  144. FAR struct net_driver_s *dev;
  145. struct send_s state;
  146. int ret = OK;
  147. /* Verify that the sockfd corresponds to valid, allocated socket */
  148. if (!psock || psock->s_crefs <= 0)
  149. {
  150. return -EBADF;
  151. }
  152. /* Get the device driver that will service this transfer */
  153. dev = pkt_find_device((FAR struct pkt_conn_s *)psock->s_conn);
  154. if (dev == NULL)
  155. {
  156. return -ENODEV;
  157. }
  158. /* Set the socket state to sending */
  159. psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
  160. /* Perform the send operation */
  161. /* Initialize the state structure. This is done with the network locked
  162. * because we don't want anything to happen until we are ready.
  163. */
  164. net_lock();
  165. memset(&state, 0, sizeof(struct send_s));
  166. /* This semaphore is used for signaling and, hence, should not have
  167. * priority inheritance enabled.
  168. */
  169. (void)nxsem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */
  170. (void)nxsem_setprotocol(&state.snd_sem, SEM_PRIO_NONE);
  171. state.snd_sock = psock; /* Socket descriptor to use */
  172. state.snd_buflen = len; /* Number of bytes to send */
  173. state.snd_buffer = buf; /* Buffer to send from */
  174. if (len > 0)
  175. {
  176. FAR struct pkt_conn_s *conn = (FAR struct pkt_conn_s *)psock->s_conn;
  177. /* Allocate resource to receive a callback */
  178. state.snd_cb = pkt_callback_alloc(dev, conn);
  179. if (state.snd_cb)
  180. {
  181. /* Set up the callback in the connection */
  182. state.snd_cb->flags = PKT_POLL;
  183. state.snd_cb->priv = (FAR void *)&state;
  184. state.snd_cb->event = psock_send_eventhandler;
  185. /* Notify the device driver that new TX data is available. */
  186. netdev_txnotify_dev(dev);
  187. /* Wait for the send to complete or an error to occur.
  188. * net_lockedwait will also terminate if a signal is received.
  189. */
  190. ret = net_lockedwait(&state.snd_sem);
  191. /* Make sure that no further events are processed */
  192. pkt_callback_free(dev, conn, state.snd_cb);
  193. }
  194. }
  195. nxsem_destroy(&state.snd_sem);
  196. net_unlock();
  197. /* Set the socket state to idle */
  198. psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
  199. /* Check for a errors, Errors are signalled by negative errno values
  200. * for the send length
  201. */
  202. if (state.snd_sent < 0)
  203. {
  204. return state.snd_sent;
  205. }
  206. /* If net_lockedwait failed, then we were probably reawakened by a signal. In
  207. * this case, net_lockedwait will have returned negated errno appropriately.
  208. */
  209. if (ret < 0)
  210. {
  211. return ret;
  212. }
  213. /* Return the number of bytes actually sent */
  214. return state.snd_sent;
  215. }
  216. #endif /* CONFIG_NET && CONFIG_NET_PKT */