net_sendfile.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /****************************************************************************
  2. * net/socket/net_sendfile.c
  3. *
  4. * Copyright (C) 2013 UVC Ingenieure. All rights reserved.
  5. * Copyright (C) 2007-2016 Gregory Nutt. All rights reserved.
  6. * Authors: Gregory Nutt <gnutt@nuttx.org>
  7. * Max Holtzberg <mh@uvc.de>
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. * 3. Neither the name NuttX nor the names of its contributors may be
  20. * used to endorse or promote products derived from this software
  21. * without specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  24. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  26. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  27. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  28. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  29. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  30. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  31. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  33. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  34. * POSSIBILITY OF SUCH DAMAGE.
  35. *
  36. ****************************************************************************/
  37. /****************************************************************************
  38. * Included Files
  39. ****************************************************************************/
  40. #include <nuttx/config.h>
  41. #include <sys/stat.h>
  42. #include <sys/types.h>
  43. #include <sys/socket.h>
  44. #include <assert.h>
  45. #include <errno.h>
  46. #include <debug.h>
  47. #include <nuttx/net/net.h>
  48. #include "socket/socket.h"
  49. #ifdef CONFIG_NET_SENDFILE
  50. /****************************************************************************
  51. * Public Functions
  52. ****************************************************************************/
  53. /****************************************************************************
  54. * Name: net_sendfile
  55. *
  56. * Description:
  57. * The net_sendfile() call may be used only when the socket is in a
  58. * connected state (so that the intended recipient is known).
  59. *
  60. * Input Parameters:
  61. * psock An instance of the internal socket structure.
  62. * buf Data to send
  63. * len Length of data to send
  64. * flags Send flags
  65. *
  66. * Returned Value:
  67. * On success, returns the number of characters sent. On error,
  68. * -1 is returned, and errno is set appropriately:
  69. *
  70. * EAGAIN or EWOULDBLOCK
  71. * The socket is marked non-blocking and the requested operation
  72. * would block.
  73. * EBADF
  74. * An invalid descriptor was specified.
  75. * ECONNRESET
  76. * Connection reset by peer.
  77. * EDESTADDRREQ
  78. * The socket is not connection-mode, and no peer address is set.
  79. * EFAULT
  80. * An invalid user space address was specified for a parameter.
  81. * EINTR
  82. * A signal occurred before any data was transmitted.
  83. * EINVAL
  84. * Invalid argument passed.
  85. * EISCONN
  86. * The connection-mode socket was connected already but a recipient
  87. * was specified. (Now either this error is returned, or the recipient
  88. * specification is ignored.)
  89. * EMSGSIZE
  90. * The socket type requires that message be sent atomically, and the
  91. * size of the message to be sent made this impossible.
  92. * ENOBUFS
  93. * The output queue for a network interface was full. This generally
  94. * indicates that the interface has stopped sending, but may be
  95. * caused by transient congestion.
  96. * ENOMEM
  97. * No memory available.
  98. * ENOTCONN
  99. * The socket is not connected, and no target has been given.
  100. * ENOTSOCK
  101. * The argument s is not a socket.
  102. * EOPNOTSUPP
  103. * Some bit in the flags argument is inappropriate for the socket
  104. * type.
  105. * EPIPE
  106. * The local end has been shut down on a connection oriented socket.
  107. * In this case the process will also receive a SIGPIPE unless
  108. * MSG_NOSIGNAL is set.
  109. *
  110. ****************************************************************************/
  111. ssize_t net_sendfile(int outfd, FAR struct file *infile, FAR off_t *offset,
  112. size_t count)
  113. {
  114. FAR struct socket *psock = sockfd_socket(outfd);
  115. ssize_t ret = -ENOSYS;
  116. DEBUGASSERT(psock != NULL && infile != NULL);
  117. /* Verify that the sockfd corresponds to valid, allocated socket */
  118. if (psock != NULL || psock->s_crefs <= 0)
  119. {
  120. nerr("ERROR: Invalid socket\n");
  121. set_errno(EBADF);
  122. return ERROR;
  123. }
  124. /* Check if the address family supports the optimized sendfile(). If not,
  125. * revert to the slow version.
  126. *
  127. * The address family indicates is support with a non-NULL si_sendfile()
  128. * method in the socket interface.
  129. */
  130. DEBUGASSERT(psock->s_sockif != NULL);
  131. if (psock->s_sockif->si_sendfile != NULL)
  132. {
  133. /* The address family can handle the optimized file send */
  134. ret = psock->s_sockif->si_sendfile(psock, infile, offset, count);
  135. }
  136. if (ret < 0)
  137. {
  138. set_errno(-ret);
  139. return ERROR;
  140. }
  141. return ret;
  142. }
  143. #endif /* CONFIG_NET_SENDFILE */