AsyncUDPSocket.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * Copyright 2014-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <memory>
  18. #include <folly/ScopeGuard.h>
  19. #include <folly/SocketAddress.h>
  20. #include <folly/io/IOBuf.h>
  21. #include <folly/io/async/AsyncSocketBase.h>
  22. #include <folly/io/async/AsyncSocketException.h>
  23. #include <folly/io/async/EventBase.h>
  24. #include <folly/io/async/EventHandler.h>
  25. namespace folly {
  26. /**
  27. * UDP socket
  28. */
  29. class AsyncUDPSocket : public EventHandler {
  30. public:
  31. enum class FDOwnership { OWNS, SHARED };
  32. class ReadCallback {
  33. public:
  34. /**
  35. * Invoked when the socket becomes readable and we want buffer
  36. * to write to.
  37. *
  38. * NOTE: From socket we will end up reading at most `len` bytes
  39. * and if there were more bytes in datagram, we will end up
  40. * dropping them.
  41. */
  42. virtual void getReadBuffer(void** buf, size_t* len) noexcept = 0;
  43. /**
  44. * Invoked when a new datagraom is available on the socket. `len`
  45. * is the number of bytes read and `truncated` is true if we had
  46. * to drop few bytes because of running out of buffer space.
  47. */
  48. virtual void onDataAvailable(
  49. const folly::SocketAddress& client,
  50. size_t len,
  51. bool truncated) noexcept = 0;
  52. /**
  53. * Invoked when there is an error reading from the socket.
  54. *
  55. * NOTE: Since UDP is connectionless, you can still read from the socket.
  56. * But you have to re-register readCallback yourself after
  57. * onReadError.
  58. */
  59. virtual void onReadError(const AsyncSocketException& ex) noexcept = 0;
  60. /**
  61. * Invoked when socket is closed and a read callback is registered.
  62. */
  63. virtual void onReadClosed() noexcept = 0;
  64. virtual ~ReadCallback() = default;
  65. };
  66. class ErrMessageCallback {
  67. public:
  68. virtual ~ErrMessageCallback() = default;
  69. /**
  70. * errMessage() will be invoked when kernel puts a message to
  71. * the error queue associated with the socket.
  72. *
  73. * @param cmsg Reference to cmsghdr structure describing
  74. * a message read from error queue associated
  75. * with the socket.
  76. */
  77. virtual void errMessage(const cmsghdr& cmsg) noexcept = 0;
  78. /**
  79. * errMessageError() will be invoked if an error occurs reading a message
  80. * from the socket error stream.
  81. *
  82. * @param ex An exception describing the error that occurred.
  83. */
  84. virtual void errMessageError(const AsyncSocketException& ex) noexcept = 0;
  85. };
  86. /**
  87. * Create a new UDP socket that will run in the
  88. * given eventbase
  89. */
  90. explicit AsyncUDPSocket(EventBase* evb);
  91. ~AsyncUDPSocket() override;
  92. /**
  93. * Returns the address server is listening on
  94. */
  95. virtual const folly::SocketAddress& address() const {
  96. CHECK_NE(-1, fd_) << "Server not yet bound to an address";
  97. return localAddress_;
  98. }
  99. /**
  100. * Bind the socket to the following address. If port is not
  101. * set in the `address` an ephemeral port is chosen and you can
  102. * use `address()` method above to get it after this method successfully
  103. * returns.
  104. */
  105. virtual void bind(const folly::SocketAddress& address);
  106. /**
  107. * Use an already bound file descriptor. You can either transfer ownership
  108. * of this FD by using ownership = FDOwnership::OWNS or share it using
  109. * FDOwnership::SHARED. In case FD is shared, it will not be `close`d in
  110. * destructor.
  111. */
  112. virtual void setFD(int fd, FDOwnership ownership);
  113. /**
  114. * Send the data in buffer to destination. Returns the return code from
  115. * ::sendmsg.
  116. */
  117. virtual ssize_t write(
  118. const folly::SocketAddress& address,
  119. const std::unique_ptr<folly::IOBuf>& buf);
  120. /**
  121. * Send the data in buffer to destination. Returns the return code from
  122. * ::sendmsg.
  123. * gso is the generic segmentation offload value
  124. * writeGSO will return -1 if
  125. * buf->computeChainDataLength() <= gso
  126. * Before calling writeGSO with a positive value
  127. * verify GSO is supported on this platform by calling getGSO
  128. */
  129. virtual ssize_t writeGSO(
  130. const folly::SocketAddress& address,
  131. const std::unique_ptr<folly::IOBuf>& buf,
  132. int gso);
  133. /**
  134. * Send data in iovec to destination. Returns the return code from sendmsg.
  135. */
  136. virtual ssize_t writev(
  137. const folly::SocketAddress& address,
  138. const struct iovec* vec,
  139. size_t veclen,
  140. int gso);
  141. virtual ssize_t writev(
  142. const folly::SocketAddress& address,
  143. const struct iovec* vec,
  144. size_t veclen);
  145. /**
  146. * Start reading datagrams
  147. */
  148. virtual void resumeRead(ReadCallback* cob);
  149. /**
  150. * Pause reading datagrams
  151. */
  152. virtual void pauseRead();
  153. /**
  154. * Stop listening on the socket.
  155. */
  156. virtual void close();
  157. /**
  158. * Get internal FD used by this socket
  159. */
  160. virtual int getFD() const {
  161. CHECK_NE(-1, fd_) << "Need to bind before getting FD out";
  162. return fd_;
  163. }
  164. /**
  165. * Set reuse port mode to call bind() on the same address multiple times
  166. */
  167. virtual void setReusePort(bool reusePort) {
  168. reusePort_ = reusePort;
  169. }
  170. /**
  171. * Set SO_REUSEADDR flag on the socket. Default is ON.
  172. */
  173. virtual void setReuseAddr(bool reuseAddr) {
  174. reuseAddr_ = reuseAddr;
  175. }
  176. /**
  177. * Set SO_RCVBUF option on the socket, if not zero. Default is zero.
  178. */
  179. virtual void setRcvBuf(int rcvBuf) {
  180. rcvBuf_ = rcvBuf;
  181. }
  182. /**
  183. * Set SO_SNDBUG option on the socket, if not zero. Default is zero.
  184. */
  185. virtual void setSndBuf(int sndBuf) {
  186. sndBuf_ = sndBuf;
  187. }
  188. /**
  189. * Set SO_BUSY_POLL option on the socket, if not zero. Default is zero.
  190. * Caution! The feature is not available on Apple's systems.
  191. */
  192. virtual void setBusyPoll(int busyPollUs) {
  193. busyPollUs_ = busyPollUs;
  194. }
  195. EventBase* getEventBase() const {
  196. return eventBase_;
  197. }
  198. /**
  199. * Enable or disable fragmentation on the socket.
  200. *
  201. * On Linux, this sets IP(V6)_MTU_DISCOVER to IP(V6)_PMTUDISC_DO when enabled,
  202. * and to IP(V6)_PMTUDISC_WANT when disabled. IP(V6)_PMTUDISC_WANT will use
  203. * per-route setting to set DF bit. It may be more desirable to use
  204. * IP(V6)_PMTUDISC_PROBE as opposed to IP(V6)_PMTUDISC_DO for apps that has
  205. * its own PMTU Discovery mechanism.
  206. * Note this doesn't work on Apple.
  207. */
  208. virtual void dontFragment(bool df);
  209. /**
  210. * Callback for receiving errors on the UDP sockets
  211. */
  212. virtual void setErrMessageCallback(ErrMessageCallback* errMessageCallback);
  213. /**
  214. * Connects the UDP socket to a remote destination address provided in
  215. * address. This can speed up UDP writes on linux because it will cache flow
  216. * state on connects.
  217. * Using connect has many quirks, and you should be aware of them before using
  218. * this API:
  219. * 1. This must only be called after binding the socket.
  220. * 2. Normally UDP can use the 2 tuple (src ip, src port) to steer packets
  221. * sent by the peer to the socket, however after connecting the socket, only
  222. * packets destined to the destination address specified in connect() will be
  223. * forwarded and others will be dropped. If the server can send a packet
  224. * from a different destination port / IP then you probably do not want to use
  225. * this API.
  226. * 3. It can be called repeatedly on either the client or server however it's
  227. * normally only useful on the client and not server.
  228. *
  229. * Returns the result of calling the connect syscall.
  230. */
  231. virtual int connect(const folly::SocketAddress& address);
  232. virtual bool isBound() const {
  233. return fd_ != -1;
  234. }
  235. virtual void detachEventBase();
  236. virtual void attachEventBase(folly::EventBase* evb);
  237. // generic segmentation offload get/set
  238. // negative return value means GSO is not available
  239. int getGSO();
  240. bool setGSO(int val);
  241. protected:
  242. virtual ssize_t sendmsg(int socket, const struct msghdr* message, int flags) {
  243. return ::sendmsg(socket, message, flags);
  244. }
  245. size_t handleErrMessages() noexcept;
  246. void failErrMessageRead(const AsyncSocketException& ex);
  247. // Non-null only when we are reading
  248. ReadCallback* readCallback_;
  249. private:
  250. AsyncUDPSocket(const AsyncUDPSocket&) = delete;
  251. AsyncUDPSocket& operator=(const AsyncUDPSocket&) = delete;
  252. // EventHandler
  253. void handlerReady(uint16_t events) noexcept override;
  254. void handleRead() noexcept;
  255. bool updateRegistration() noexcept;
  256. EventBase* eventBase_;
  257. folly::SocketAddress localAddress_;
  258. int fd_;
  259. FDOwnership ownership_;
  260. // Temp space to receive client address
  261. folly::SocketAddress clientAddress_;
  262. bool reuseAddr_{true};
  263. bool reusePort_{false};
  264. int rcvBuf_{0};
  265. int sndBuf_{0};
  266. int busyPollUs_{0};
  267. // generic segmentation offload value, if available
  268. // See https://lwn.net/Articles/188489/ for more details
  269. folly::Optional<int> gso_;
  270. ErrMessageCallback* errMessageCallback_{nullptr};
  271. };
  272. } // namespace folly