proxygen
folly::AsyncUDPSocket Class Reference

#include <AsyncUDPSocket.h>

Inheritance diagram for folly::AsyncUDPSocket:
folly::EventHandler folly::test::MockAsyncUDPSocket TestAsyncUDPSocket

Classes

class  ErrMessageCallback
 
class  ReadCallback
 

Public Types

enum  FDOwnership { FDOwnership::OWNS, FDOwnership::SHARED }
 
- Public Types inherited from folly::EventHandler
enum  EventFlags {
  NONE = 0, READ = EV_READ, WRITE = EV_WRITE, READ_WRITE = (READ | WRITE),
  PERSIST = EV_PERSIST
}
 

Public Member Functions

 AsyncUDPSocket (EventBase *evb)
 
 ~AsyncUDPSocket () override
 
virtual const folly::SocketAddressaddress () const
 
virtual void bind (const folly::SocketAddress &address)
 
void setFD (int fd, FDOwnership ownership)
 
virtual void setFD (NetworkSocket fd, FDOwnership ownership)
 
virtual ssize_t write (const folly::SocketAddress &address, const std::unique_ptr< folly::IOBuf > &buf)
 
virtual ssize_t writeGSO (const folly::SocketAddress &address, const std::unique_ptr< folly::IOBuf > &buf, int gso)
 
virtual ssize_t writev (const folly::SocketAddress &address, const struct iovec *vec, size_t veclen, int gso)
 
virtual ssize_t writev (const folly::SocketAddress &address, const struct iovec *vec, size_t veclen)
 
virtual void resumeRead (ReadCallback *cob)
 
virtual void pauseRead ()
 
virtual void close ()
 
virtual int getFD () const
 
virtual void setReusePort (bool reusePort)
 
virtual void setReuseAddr (bool reuseAddr)
 
virtual void setRcvBuf (int rcvBuf)
 
virtual void setSndBuf (int sndBuf)
 
virtual void setBusyPoll (int busyPollUs)
 
EventBasegetEventBase () const
 
virtual void dontFragment (bool df)
 
virtual void setErrMessageCallback (ErrMessageCallback *errMessageCallback)
 
virtual int connect (const folly::SocketAddress &address)
 
virtual bool isBound () const
 
virtual void detachEventBase ()
 
virtual void attachEventBase (folly::EventBase *evb)
 
int getGSO ()
 
bool setGSO (int val)
 
- Public Member Functions inherited from folly::EventHandler
 EventHandler (EventBase *eventBase, int fd)
 
 EventHandler (EventBase *eventBase=nullptr, NetworkSocket fd=NetworkSocket())
 
virtual ~EventHandler ()
 
bool registerHandler (uint16_t events)
 
void unregisterHandler ()
 
bool isHandlerRegistered () const
 
void attachEventBase (EventBase *eventBase)
 
void detachEventBase ()
 
void changeHandlerFD (int fd)
 
void changeHandlerFD (NetworkSocket fd)
 
void initHandler (EventBase *eventBase, int fd)
 
void initHandler (EventBase *eventBase, NetworkSocket fd)
 
uint16_t getRegisteredEvents () const
 
bool registerInternalHandler (uint16_t events)
 
bool isPending () const
 

Protected Member Functions

virtual ssize_t sendmsg (NetworkSocket socket, const struct msghdr *message, int flags)
 
size_t handleErrMessages () noexcept
 
void failErrMessageRead (const AsyncSocketException &ex)
 

Protected Attributes

ReadCallbackreadCallback_
 

Private Member Functions

 AsyncUDPSocket (const AsyncUDPSocket &)=delete
 
AsyncUDPSocketoperator= (const AsyncUDPSocket &)=delete
 
void handlerReady (uint16_t events) noexceptoverride
 
void handleRead () noexcept
 
bool updateRegistration () noexcept
 

Private Attributes

EventBaseeventBase_
 
folly::SocketAddress localAddress_
 
NetworkSocket fd_
 
FDOwnership ownership_
 
folly::SocketAddress clientAddress_
 
bool reuseAddr_ {true}
 
bool reusePort_ {false}
 
int rcvBuf_ {0}
 
int sndBuf_ {0}
 
int busyPollUs_ {0}
 
folly::Optional< int > gso_
 
ErrMessageCallbackerrMessageCallback_ {nullptr}
 

Detailed Description

UDP socket

Definition at line 36 of file AsyncUDPSocket.h.

Member Enumeration Documentation

Enumerator
OWNS 
SHARED 

Definition at line 38 of file AsyncUDPSocket.h.

Constructor & Destructor Documentation

folly::AsyncUDPSocket::AsyncUDPSocket ( EventBase evb)
explicit

Create a new UDP socket that will run in the given eventbase

Definition at line 37 of file AsyncUDPSocket.cpp.

References folly::EventBase::dcheckIsInEventBaseThread().

38  : EventHandler(CHECK_NOTNULL(evb)),
39  readCallback_(nullptr),
40  eventBase_(evb),
41  fd_() {
42  evb->dcheckIsInEventBaseThread();
43 }
ReadCallback * readCallback_
EventHandler(EventBase *eventBase, int fd)
Definition: EventHandler.h:65
folly::AsyncUDPSocket::~AsyncUDPSocket ( )
override

Definition at line 45 of file AsyncUDPSocket.cpp.

References close(), and fd_.

45  {
46  if (fd_ != NetworkSocket()) {
47  close();
48  }
49 }
folly::AsyncUDPSocket::AsyncUDPSocket ( const AsyncUDPSocket )
privatedelete

Member Function Documentation

virtual const folly::SocketAddress& folly::AsyncUDPSocket::address ( ) const
inlinevirtual

Returns the address server is listening on

Definition at line 112 of file AsyncUDPSocket.h.

References bind(), fd_, and localAddress_.

Referenced by bind(), dontFragment(), setErrMessageCallback(), TEST(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

112  {
113  CHECK_NE(NetworkSocket(), fd_) << "Server not yet bound to an address";
114  return localAddress_;
115  }
folly::SocketAddress localAddress_
void folly::AsyncUDPSocket::attachEventBase ( folly::EventBase evb)
virtual

Definition at line 546 of file AsyncUDPSocket.cpp.

References folly::EventHandler::attachEventBase(), eventBase_, folly::EventBase::isInEventBaseThread(), and updateRegistration().

Referenced by isBound().

546  {
547  DCHECK(!eventBase_);
548  DCHECK(evb && evb->isInEventBaseThread());
549  eventBase_ = evb;
552 }
void attachEventBase(EventBase *eventBase)
bool isInEventBaseThread() const
Definition: EventBase.h:504
bool updateRegistration() noexcept
void folly::AsyncUDPSocket::bind ( const folly::SocketAddress address)
virtual

Bind the socket to the following address. If port is not set in the address an ephemeral port is chosen and you can use address() method above to get it after this method successfully returns.

Definition at line 51 of file AsyncUDPSocket.cpp.

References address(), folly::netops::bind(), busyPollUs_, folly::EventHandler::changeHandlerFD(), folly::netops::close(), folly::SocketAddress::describe(), fd_, flag, g(), folly::SocketAddress::getActualSize(), folly::SocketAddress::getAddress(), folly::SocketAddress::getFamily(), folly::SocketAddress::getPort(), localAddress_, folly::makeGuard(), folly::AsyncSocketException::NOT_OPEN, ownership_, OWNS, rcvBuf_, reuseAddr_, reusePort_, folly::netops::set_socket_non_blocking(), folly::SocketAddress::setFromLocalAddress(), folly::netops::setsockopt(), sndBuf_, SO_REUSEPORT, folly::netops::socket(), and folly::value().

Referenced by address(), TEST(), TEST_F(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

51  {
52  NetworkSocket socket =
53  netops::socket(address.getFamily(), SOCK_DGRAM, IPPROTO_UDP);
54  if (socket == NetworkSocket()) {
55  throw AsyncSocketException(
57  "error creating async udp socket",
58  errno);
59  }
60 
61  auto g = folly::makeGuard([&] { netops::close(socket); });
62 
63  // put the socket in non-blocking mode
64  int ret = netops::set_socket_non_blocking(socket);
65  if (ret != 0) {
66  throw AsyncSocketException(
68  "failed to put socket in non-blocking mode",
69  errno);
70  }
71 
72  if (reuseAddr_) {
73  // put the socket in reuse mode
74  int value = 1;
76  socket, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) != 0) {
77  throw AsyncSocketException(
79  "failed to put socket in reuse mode",
80  errno);
81  }
82  }
83 
84  if (reusePort_) {
85  // put the socket in port reuse mode
86  int value = 1;
88  socket, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)) != 0) {
89  throw AsyncSocketException(
91  "failed to put socket in reuse_port mode",
92  errno);
93  }
94  }
95 
96  if (busyPollUs_ > 0) {
97 #ifdef SO_BUSY_POLL
98  // Set busy_poll time in microseconds on the socket.
99  // It sets how long socket will be in busy_poll mode when no event occurs.
100  int value = busyPollUs_;
101  if (netops::setsockopt(
102  socket, SOL_SOCKET, SO_BUSY_POLL, &value, sizeof(value)) != 0) {
103  throw AsyncSocketException(
105  "failed to set SO_BUSY_POLL on the socket",
106  errno);
107  }
108 #else /* SO_BUSY_POLL is not supported*/
109  throw AsyncSocketException(
110  AsyncSocketException::NOT_OPEN, "SO_BUSY_POLL is not supported", errno);
111 #endif
112  }
113 
114  if (rcvBuf_ > 0) {
115  // Set the size of the buffer for the received messages in rx_queues.
116  int value = rcvBuf_;
117  if (netops::setsockopt(
118  socket, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) != 0) {
119  throw AsyncSocketException(
121  "failed to set SO_RCVBUF on the socket",
122  errno);
123  }
124  }
125 
126  if (sndBuf_ > 0) {
127  // Set the size of the buffer for the sent messages in tx_queues.
128  int value = rcvBuf_;
129  if (netops::setsockopt(
130  socket, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) != 0) {
131  throw AsyncSocketException(
133  "failed to set SO_SNDBUF on the socket",
134  errno);
135  }
136  }
137 
138  // If we're using IPv6, make sure we don't accept V4-mapped connections
139  if (address.getFamily() == AF_INET6) {
140  int flag = 1;
141  if (netops::setsockopt(
142  socket, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag))) {
143  throw AsyncSocketException(
144  AsyncSocketException::NOT_OPEN, "Failed to set IPV6_V6ONLY", errno);
145  }
146  }
147 
148  // bind to the address
149  sockaddr_storage addrStorage;
150  address.getAddress(&addrStorage);
151  auto& saddr = reinterpret_cast<sockaddr&>(addrStorage);
152  if (netops::bind(socket, &saddr, address.getActualSize()) != 0) {
153  throw AsyncSocketException(
155  "failed to bind the async udp socket for:" + address.describe(),
156  errno);
157  }
158 
159  // success
160  g.dismiss();
161  fd_ = socket;
163 
164  // attach to EventHandler
166 
167  if (address.getPort() != 0) {
169  } else {
171  }
172 }
virtual const folly::SocketAddress & address() const
int setsockopt(NetworkSocket s, int level, int optname, const void *optval, socklen_t optlen)
Definition: NetOps.cpp:384
socklen_t getActualSize() const
uint16_t getPort() const
std::string describe() const
static once_flag flag
Definition: Random.cpp:75
sa_family_t getFamily() const
#define SO_REUSEPORT
NetworkSocket socket(int af, int type, int protocol)
Definition: NetOps.cpp:412
socklen_t getAddress(sockaddr_storage *addr) const
void changeHandlerFD(int fd)
Definition: EventHandler.h:143
FOLLY_NODISCARD detail::ScopeGuardImplDecay< F, true > makeGuard(F &&f) noexcept(noexcept(detail::ScopeGuardImplDecay< F, true >(static_cast< F && >(f))))
Definition: ScopeGuard.h:184
int set_socket_non_blocking(NetworkSocket s)
Definition: NetOps.cpp:441
void setFromLocalAddress(int socket)
int bind(NetworkSocket s, const sockaddr *name, socklen_t namelen)
Definition: NetOps.cpp:76
g_t g(f_t)
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
folly::SocketAddress localAddress_
int close(NetworkSocket s)
Definition: NetOps.cpp:90
void folly::AsyncUDPSocket::close ( )
virtual

Stop listening on the socket.

Definition at line 329 of file AsyncUDPSocket.cpp.

References folly::netops::close(), folly::EventBase::dcheckIsInEventBaseThread(), eventBase_, fd_, folly::AsyncUDPSocket::ReadCallback::onReadClosed(), ownership_, OWNS, readCallback_, and folly::EventHandler::unregisterHandler().

Referenced by setFD(), ~AsyncUDPSocket(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

329  {
331 
332  if (readCallback_) {
333  auto cob = readCallback_;
334  readCallback_ = nullptr;
335 
336  cob->onReadClosed();
337  }
338 
339  // Unregister any events we are registered for
341 
342  if (fd_ != NetworkSocket() && ownership_ == FDOwnership::OWNS) {
344  }
345 
346  fd_ = NetworkSocket();
347 }
ReadCallback * readCallback_
virtual void onReadClosed() noexcept=0
void dcheckIsInEventBaseThread() const
Definition: EventBase.h:520
int close(NetworkSocket s)
Definition: NetOps.cpp:90
int folly::AsyncUDPSocket::connect ( const folly::SocketAddress address)
virtual

Connects the UDP socket to a remote destination address provided in address. This can speed up UDP writes on linux because it will cache flow state on connects. Using connect has many quirks, and you should be aware of them before using this API:

  1. This must only be called after binding the socket.
  2. Normally UDP can use the 2 tuple (src ip, src port) to steer packets sent by the peer to the socket, however after connecting the socket, only packets destined to the destination address specified in connect() will be forwarded and others will be dropped. If the server can send a packet from a different destination port / IP then you probably do not want to use this API.
  3. It can be called repeatedly on either the client or server however it's normally only useful on the client and not server.

Returns the result of calling the connect syscall.

Definition at line 421 of file AsyncUDPSocket.cpp.

References folly::netops::connect(), fd_, folly::SocketAddress::getActualSize(), and folly::SocketAddress::getAddress().

Referenced by getEventBase(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

421  {
422  CHECK_NE(NetworkSocket(), fd_) << "Socket not yet bound";
423  sockaddr_storage addrStorage;
424  address.getAddress(&addrStorage);
425  return netops::connect(
426  fd_, reinterpret_cast<sockaddr*>(&addrStorage), address.getActualSize());
427 }
int connect(NetworkSocket s, const sockaddr *name, socklen_t namelen)
Definition: NetOps.cpp:94
socklen_t getActualSize() const
socklen_t getAddress(sockaddr_storage *addr) const
void folly::AsyncUDPSocket::detachEventBase ( )
virtual
void folly::AsyncUDPSocket::dontFragment ( bool  df)
virtual

Enable or disable fragmentation on the socket.

On Linux, this sets IP(V6)_MTU_DISCOVER to IP(V6)_PMTUDISC_DO when enabled, and to IP(V6)_PMTUDISC_WANT when disabled. IP(V6)_PMTUDISC_WANT will use per-route setting to set DF bit. It may be more desirable to use IP(V6)_PMTUDISC_PROBE as opposed to IP(V6)_PMTUDISC_DO for apps that has its own PMTU Discovery mechanism. Note this doesn't work on Apple.

Definition at line 174 of file AsyncUDPSocket.cpp.

References address(), fd_, folly::SocketAddress::getFamily(), folly::AsyncSocketException::NOT_OPEN, and folly::netops::setsockopt().

Referenced by getEventBase(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

174  {
175  (void)df; // to avoid potential unused variable warning
176 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) && \
177  defined(IP_PMTUDISC_WANT)
178  if (address().getFamily() == AF_INET) {
179  int v4 = df ? IP_PMTUDISC_DO : IP_PMTUDISC_WANT;
180  if (netops::setsockopt(fd_, IPPROTO_IP, IP_MTU_DISCOVER, &v4, sizeof(v4))) {
181  throw AsyncSocketException(
183  "Failed to set DF with IP_MTU_DISCOVER",
184  errno);
185  }
186  }
187 #endif
188 #if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) && \
189  defined(IPV6_PMTUDISC_WANT)
190  if (address().getFamily() == AF_INET6) {
191  int v6 = df ? IPV6_PMTUDISC_DO : IPV6_PMTUDISC_WANT;
192  if (netops::setsockopt(
193  fd_, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &v6, sizeof(v6))) {
194  throw AsyncSocketException(
196  "Failed to set DF with IPV6_MTU_DISCOVER",
197  errno);
198  }
199  }
200 #endif
201 }
virtual const folly::SocketAddress & address() const
int setsockopt(NetworkSocket s, int level, int optname, const void *optval, socklen_t optlen)
Definition: NetOps.cpp:384
sa_family_t getFamily() const
void folly::AsyncUDPSocket::failErrMessageRead ( const AsyncSocketException ex)
protected

Definition at line 413 of file AsyncUDPSocket.cpp.

References errMessageCallback_, and folly::AsyncUDPSocket::ErrMessageCallback::errMessageError().

Referenced by handleErrMessages(), and sendmsg().

413  {
414  if (errMessageCallback_ != nullptr) {
415  ErrMessageCallback* callback = errMessageCallback_;
416  errMessageCallback_ = nullptr;
417  callback->errMessageError(ex);
418  }
419 }
virtual void errMessageError(const AsyncSocketException &ex) noexcept=0
ErrMessageCallback * errMessageCallback_
EventBase* folly::AsyncUDPSocket::getEventBase ( ) const
inline

Definition at line 231 of file AsyncUDPSocket.h.

References connect(), dontFragment(), eventBase_, and setErrMessageCallback().

231  {
232  return eventBase_;
233  }
virtual int folly::AsyncUDPSocket::getFD ( ) const
inlinevirtual

Get internal FD used by this socket

Definition at line 190 of file AsyncUDPSocket.h.

References fd_, and folly::NetworkSocket::toFd().

Referenced by folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

190  {
191  CHECK_NE(NetworkSocket(), fd_) << "Need to bind before getting FD out";
192  return fd_.toFd();
193  }
int folly::AsyncUDPSocket::getGSO ( )

Definition at line 520 of file AsyncUDPSocket.cpp.

References fd_, FOLLY_UNLIKELY, folly::netops::getsockopt(), gso_, folly::Optional< Value >::hasValue(), SOL_UDP, UDP_SEGMENT, and folly::Optional< Value >::value().

Referenced by isBound(), TEST(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

520  {
521  // check if we can return the cached value
522  if (FOLLY_UNLIKELY(!gso_.hasValue())) {
523 #ifdef FOLLY_HAVE_MSG_ERRQUEUE
524  int gso = -1;
525  socklen_t optlen = sizeof(gso);
526  if (!netops::getsockopt(fd_, SOL_UDP, UDP_SEGMENT, &gso, &optlen)) {
527  gso_ = gso;
528  } else {
529  gso_ = -1;
530  }
531 #else
532  gso_ = -1;
533 #endif
534  }
535 
536  return gso_.value();
537 }
#define FOLLY_UNLIKELY(x)
Definition: Likely.h:36
#define SOL_UDP
Definition: NetOps.h:59
#define UDP_SEGMENT
Definition: NetOps.h:67
FOLLY_CPP14_CONSTEXPR bool hasValue() const noexcept
Definition: Optional.h:300
int getsockopt(NetworkSocket s, int level, int optname, void *optval, socklen_t *optlen)
Definition: NetOps.cpp:112
folly::Optional< int > gso_
FOLLY_CPP14_CONSTEXPR const Value & value() const &
Definition: Optional.h:268
size_t folly::AsyncUDPSocket::handleErrMessages ( )
protectednoexcept

Definition at line 356 of file AsyncUDPSocket.cpp.

References folly::data(), folly::AsyncUDPSocket::ErrMessageCallback::errMessage(), errMessageCallback_, failErrMessageRead(), fd_, folly::AsyncSocketException::INTERNAL_ERROR, folly::netops::recvmsg(), and uint8_t.

Referenced by handleRead(), and sendmsg().

356  {
357 #ifdef FOLLY_HAVE_MSG_ERRQUEUE
358  if (errMessageCallback_ == nullptr) {
359  return 0;
360  }
361  uint8_t ctrl[1024];
362  unsigned char data;
363  struct msghdr msg;
364  iovec entry;
365 
366  entry.iov_base = &data;
367  entry.iov_len = sizeof(data);
368  msg.msg_iov = &entry;
369  msg.msg_iovlen = 1;
370  msg.msg_name = nullptr;
371  msg.msg_namelen = 0;
372  msg.msg_control = ctrl;
373  msg.msg_controllen = sizeof(ctrl);
374  msg.msg_flags = 0;
375 
376  int ret;
377  size_t num = 0;
378  while (fd_ != NetworkSocket()) {
379  ret = netops::recvmsg(fd_, &msg, MSG_ERRQUEUE);
380  VLOG(5) << "AsyncSocket::handleErrMessages(): recvmsg returned " << ret;
381 
382  if (ret < 0) {
383  if (errno != EAGAIN) {
384  auto errnoCopy = errno;
385  LOG(ERROR) << "::recvmsg exited with code " << ret
386  << ", errno: " << errnoCopy;
387  AsyncSocketException ex(
389  "recvmsg() failed",
390  errnoCopy);
391  failErrMessageRead(ex);
392  }
393  return num;
394  }
395 
396  for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
397  cmsg != nullptr && cmsg->cmsg_len != 0;
398  cmsg = CMSG_NXTHDR(&msg, cmsg)) {
399  ++num;
401  if (fd_ == NetworkSocket()) {
402  // once the socket is closed there is no use for more read errors.
403  return num;
404  }
405  }
406  }
407  return num;
408 #else
409  return 0;
410 #endif
411 }
void failErrMessageRead(const AsyncSocketException &ex)
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
virtual void errMessage(const cmsghdr &cmsg) noexcept=0
ssize_t recvmsg(NetworkSocket s, msghdr *message, int flags)
Definition: NetOps.cpp:268
ErrMessageCallback * errMessageCallback_
void folly::AsyncUDPSocket::handleRead ( )
privatenoexcept

Definition at line 429 of file AsyncUDPSocket.cpp.

References folly::AsyncSocketException::BAD_ARGS, clientAddress_, fd_, folly::SocketAddress::getFamily(), folly::AsyncUDPSocket::ReadCallback::getReadBuffer(), handleErrMessages(), folly::AsyncSocketException::INTERNAL_ERROR, localAddress_, folly::AsyncUDPSocket::ReadCallback::onDataAvailable(), folly::AsyncUDPSocket::ReadCallback::onReadError(), readCallback_, folly::netops::recvfrom(), folly::SocketAddress::setFromSockaddr(), and updateRegistration().

Referenced by handlerReady().

429  {
430  void* buf{nullptr};
431  size_t len{0};
432 
433  if (handleErrMessages()) {
434  return;
435  }
436 
437  if (fd_ == NetworkSocket()) {
438  // The socket may have been closed by the error callbacks.
439  return;
440  }
441 
442  readCallback_->getReadBuffer(&buf, &len);
443  if (buf == nullptr || len == 0) {
444  AsyncSocketException ex(
446  "AsyncUDPSocket::getReadBuffer() returned empty buffer");
447 
448  auto cob = readCallback_;
449  readCallback_ = nullptr;
450 
451  cob->onReadError(ex);
453  return;
454  }
455 
456  struct sockaddr_storage addrStorage;
457  socklen_t addrLen = sizeof(addrStorage);
458  memset(&addrStorage, 0, size_t(addrLen));
459  struct sockaddr* rawAddr = reinterpret_cast<sockaddr*>(&addrStorage);
460  rawAddr->sa_family = localAddress_.getFamily();
461 
462  ssize_t bytesRead =
463  netops::recvfrom(fd_, buf, len, MSG_TRUNC, rawAddr, &addrLen);
464  if (bytesRead >= 0) {
465  clientAddress_.setFromSockaddr(rawAddr, addrLen);
466 
467  if (bytesRead > 0) {
468  bool truncated = false;
469  if ((size_t)bytesRead > len) {
470  truncated = true;
471  bytesRead = ssize_t(len);
472  }
473 
475  clientAddress_, size_t(bytesRead), truncated);
476  }
477  } else {
478  if (errno == EAGAIN || errno == EWOULDBLOCK) {
479  // No data could be read without blocking the socket
480  return;
481  }
482 
483  AsyncSocketException ex(
484  AsyncSocketException::INTERNAL_ERROR, "::recvfrom() failed", errno);
485 
486  // In case of UDP we can continue reading from the socket
487  // even if the current request fails. We notify the user
488  // so that he can do some logging/stats collection if he wants.
489  auto cob = readCallback_;
490  readCallback_ = nullptr;
491 
492  cob->onReadError(ex);
494  }
495 }
ReadCallback * readCallback_
ssize_t recvfrom(NetworkSocket s, void *buf, size_t len, int flags, sockaddr *from, socklen_t *fromlen)
Definition: NetOps.cpp:207
virtual void onReadError(const AsyncSocketException &ex) noexcept=0
void setFromSockaddr(const struct sockaddr *address)
sa_family_t getFamily() const
bool updateRegistration() noexcept
virtual void getReadBuffer(void **buf, size_t *len) noexcept=0
size_t handleErrMessages() noexcept
virtual void onDataAvailable(const folly::SocketAddress &client, size_t len, bool truncated) noexcept=0
folly::SocketAddress clientAddress_
folly::SocketAddress localAddress_
void folly::AsyncUDPSocket::handlerReady ( uint16_t  events)
overrideprivatevirtualnoexcept

handlerReady() is invoked when the handler is ready.

Parameters
eventsA bitset indicating the events that are ready.

Implements folly::EventHandler.

Definition at line 349 of file AsyncUDPSocket.cpp.

References handleRead(), folly::EventHandler::READ, and readCallback_.

349  {
350  if (events & EventHandler::READ) {
351  DCHECK(readCallback_);
352  handleRead();
353  }
354 }
ReadCallback * readCallback_
void handleRead() noexcept
virtual bool folly::AsyncUDPSocket::isBound ( ) const
inlinevirtual

Definition at line 272 of file AsyncUDPSocket.h.

References attachEventBase(), detachEventBase(), fd_, getGSO(), setGSO(), and val.

Referenced by TEST_F(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

272  {
273  return fd_ != NetworkSocket();
274  }
AsyncUDPSocket& folly::AsyncUDPSocket::operator= ( const AsyncUDPSocket )
privatedelete
void folly::AsyncUDPSocket::pauseRead ( )
virtual

Pause reading datagrams

Definition at line 323 of file AsyncUDPSocket.cpp.

References readCallback_, and updateRegistration().

Referenced by setFD(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

323  {
324  // It is ok to pause an already paused socket
325  readCallback_ = nullptr;
327 }
ReadCallback * readCallback_
bool updateRegistration() noexcept
void folly::AsyncUDPSocket::resumeRead ( ReadCallback cob)
virtual

Start reading datagrams

Definition at line 307 of file AsyncUDPSocket.cpp.

References fd_, folly::AsyncSocketException::NOT_OPEN, folly::AsyncUDPSocket::ReadCallback::onReadError(), readCallback_, and updateRegistration().

Referenced by setFD(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

307  {
308  CHECK(!readCallback_) << "Another read callback already installed";
309  CHECK_NE(NetworkSocket(), fd_)
310  << "UDP server socket not yet bind to an address";
311 
312  readCallback_ = CHECK_NOTNULL(cob);
313  if (!updateRegistration()) {
314  AsyncSocketException ex(
315  AsyncSocketException::NOT_OPEN, "failed to register for accept events");
316 
317  readCallback_ = nullptr;
318  cob->onReadError(ex);
319  return;
320  }
321 }
ReadCallback * readCallback_
bool updateRegistration() noexcept
virtual ssize_t folly::AsyncUDPSocket::sendmsg ( NetworkSocket  socket,
const struct msghdr *  message,
int  flags 
)
inlineprotectedvirtual

Definition at line 288 of file AsyncUDPSocket.h.

References failErrMessageRead(), handleErrMessages(), folly::pushmi::__adl::noexcept(), and folly::netops::sendmsg().

Referenced by writev().

288  {
290  }
Definition: test.c:42
flags
Definition: http_parser.h:127
ssize_t sendmsg(NetworkSocket socket, const msghdr *message, int flags)
Definition: NetOps.cpp:328
NetworkSocket socket(int af, int type, int protocol)
Definition: NetOps.cpp:412
virtual void folly::AsyncUDPSocket::setBusyPoll ( int  busyPollUs)
inlinevirtual

Set SO_BUSY_POLL option on the socket, if not zero. Default is zero. Caution! The feature is not available on Apple's systems.

Definition at line 227 of file AsyncUDPSocket.h.

References busyPollUs_.

227  {
228  busyPollUs_ = busyPollUs;
229  }
void folly::AsyncUDPSocket::setErrMessageCallback ( ErrMessageCallback errMessageCallback)
virtual

Callback for receiving errors on the UDP sockets

Definition at line 203 of file AsyncUDPSocket.cpp.

References address(), errMessageCallback_, fd_, folly::SocketAddress::getFamily(), folly::AsyncSocketException::NOT_OPEN, and folly::netops::setsockopt().

Referenced by getEventBase(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

204  {
205  errMessageCallback_ = errMessageCallback;
206  int err = (errMessageCallback_ != nullptr);
207 #if defined(IP_RECVERR)
208  if (address().getFamily() == AF_INET &&
209  netops::setsockopt(fd_, IPPROTO_IP, IP_RECVERR, &err, sizeof(err))) {
210  throw AsyncSocketException(
211  AsyncSocketException::NOT_OPEN, "Failed to set IP_RECVERR", errno);
212  }
213 #endif
214 #if defined(IPV6_RECVERR)
215  if (address().getFamily() == AF_INET6 &&
216  netops::setsockopt(fd_, IPPROTO_IPV6, IPV6_RECVERR, &err, sizeof(err))) {
217  throw AsyncSocketException(
218  AsyncSocketException::NOT_OPEN, "Failed to set IPV6_RECVERR", errno);
219  }
220 #endif
221  (void)err;
222 }
virtual const folly::SocketAddress & address() const
int setsockopt(NetworkSocket s, int level, int optname, const void *optval, socklen_t optlen)
Definition: NetOps.cpp:384
sa_family_t getFamily() const
ErrMessageCallback * errMessageCallback_
void folly::AsyncUDPSocket::setFD ( int  fd,
FDOwnership  ownership 
)
inline

Use an already bound file descriptor. You can either transfer ownership of this FD by using ownership = FDOwnership::OWNS or share it using FDOwnership::SHARED. In case FD is shared, it will not be closed in destructor.

Definition at line 131 of file AsyncUDPSocket.h.

References close(), folly::NetworkSocket::fromFd(), pauseRead(), resumeRead(), write(), writeGSO(), and writev().

Referenced by folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

131  {
132  setFD(NetworkSocket::fromFd(fd), ownership);
133  }
void setFD(int fd, FDOwnership ownership)
static NetworkSocket fromFd(int fd)
Definition: NetworkSocket.h:44
void folly::AsyncUDPSocket::setFD ( NetworkSocket  fd,
FDOwnership  ownership 
)
virtual

Definition at line 224 of file AsyncUDPSocket.cpp.

References folly::EventHandler::changeHandlerFD(), fd_, localAddress_, ownership_, and folly::SocketAddress::setFromLocalAddress().

224  {
225  CHECK_EQ(NetworkSocket(), fd_) << "Already bound to another FD";
226 
227  fd_ = fd;
228  ownership_ = ownership;
229 
232 }
void changeHandlerFD(int fd)
Definition: EventHandler.h:143
void setFromLocalAddress(int socket)
folly::SocketAddress localAddress_
bool folly::AsyncUDPSocket::setGSO ( int  val)

Definition at line 507 of file AsyncUDPSocket.cpp.

References fd_, gso_, folly::netops::setsockopt(), SOL_UDP, UDP_SEGMENT, and val.

Referenced by isBound(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

507  {
508 #ifdef FOLLY_HAVE_MSG_ERRQUEUE
509  int ret = netops::setsockopt(fd_, SOL_UDP, UDP_SEGMENT, &val, sizeof(val));
510 
511  gso_ = ret ? -1 : val;
512 
513  return !ret;
514 #else
515  (void)val;
516  return false;
517 #endif
518 }
int setsockopt(NetworkSocket s, int level, int optname, const void *optval, socklen_t optlen)
Definition: NetOps.cpp:384
double val
Definition: String.cpp:273
#define SOL_UDP
Definition: NetOps.h:59
#define UDP_SEGMENT
Definition: NetOps.h:67
folly::Optional< int > gso_
virtual void folly::AsyncUDPSocket::setRcvBuf ( int  rcvBuf)
inlinevirtual

Set SO_RCVBUF option on the socket, if not zero. Default is zero.

Definition at line 212 of file AsyncUDPSocket.h.

References rcvBuf_.

212  {
213  rcvBuf_ = rcvBuf;
214  }
virtual void folly::AsyncUDPSocket::setReuseAddr ( bool  reuseAddr)
inlinevirtual

Set SO_REUSEADDR flag on the socket. Default is ON.

Definition at line 205 of file AsyncUDPSocket.h.

References reuseAddr_.

Referenced by folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

205  {
206  reuseAddr_ = reuseAddr;
207  }
virtual void folly::AsyncUDPSocket::setReusePort ( bool  reusePort)
inlinevirtual

Set reuse port mode to call bind() on the same address multiple times

Definition at line 198 of file AsyncUDPSocket.h.

References reusePort_.

Referenced by folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

198  {
199  reusePort_ = reusePort;
200  }
virtual void folly::AsyncUDPSocket::setSndBuf ( int  sndBuf)
inlinevirtual

Set SO_SNDBUG option on the socket, if not zero. Default is zero.

Definition at line 219 of file AsyncUDPSocket.h.

References sndBuf_.

219  {
220  sndBuf_ = sndBuf;
221  }
bool folly::AsyncUDPSocket::updateRegistration ( )
privatenoexcept
ssize_t folly::AsyncUDPSocket::write ( const folly::SocketAddress address,
const std::unique_ptr< folly::IOBuf > &  buf 
)
virtual

Send the data in buffer to destination. Returns the return code from ::sendmsg.

Definition at line 254 of file AsyncUDPSocket.cpp.

References writeGSO().

Referenced by setFD(), TEST(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

256  {
257  return writeGSO(address, buf, 0);
258 }
virtual ssize_t writeGSO(const folly::SocketAddress &address, const std::unique_ptr< folly::IOBuf > &buf, int gso)
ssize_t folly::AsyncUDPSocket::writeGSO ( const folly::SocketAddress address,
const std::unique_ptr< folly::IOBuf > &  buf,
int  gso 
)
virtual

Send the data in buffer to destination. Returns the return code from ::sendmsg. gso is the generic segmentation offload value writeGSO will return -1 if buf->computeChainDataLength() <= gso Before calling writeGSO with a positive value verify GSO is supported on this platform by calling getGSO

Definition at line 234 of file AsyncUDPSocket.cpp.

References folly::IOBuf::coalesce(), folly::IOBuf::data(), folly::IOBuf::fillIov(), folly::IOBuf::length(), uint8_t, UNLIKELY, and writev().

Referenced by GSOSendTest::GSOSendTest(), setFD(), write(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

237  {
238  // UDP's typical MTU size is 1500, so high number of buffers
239  // really do not make sense. Optimize for buffer chains with
240  // buffers less than 16, which is the highest I can think of
241  // for a real use case.
242  iovec vec[16];
243  size_t iovec_len = buf->fillIov(vec, sizeof(vec) / sizeof(vec[0]));
244  if (UNLIKELY(iovec_len == 0)) {
245  buf->coalesce();
246  vec[0].iov_base = const_cast<uint8_t*>(buf->data());
247  vec[0].iov_len = buf->length();
248  iovec_len = 1;
249  }
250 
251  return writev(address, vec, iovec_len, gso);
252 }
ByteRange coalesce()
Definition: IOBuf.h:1095
virtual ssize_t writev(const folly::SocketAddress &address, const struct iovec *vec, size_t veclen, int gso)
const uint8_t * data() const
Definition: IOBuf.h:499
size_t fillIov(struct iovec *iov, size_t len) const
Definition: IOBuf.cpp:1072
std::size_t length() const
Definition: IOBuf.h:533
Definition: Traits.h:588
#define UNLIKELY(x)
Definition: Likely.h:48
ssize_t folly::AsyncUDPSocket::writev ( const folly::SocketAddress address,
const struct iovec *  vec,
size_t  veclen,
int  gso 
)
virtual

Send data in iovec to destination. Returns the return code from sendmsg.

Definition at line 260 of file AsyncUDPSocket.cpp.

References fd_, folly::SocketAddress::getActualSize(), folly::SocketAddress::getAddress(), sendmsg(), SOL_UDP, UDP_SEGMENT, and uint16_t.

Referenced by setFD(), writeGSO(), writev(), and folly::test::MockAsyncUDPSocket::~MockAsyncUDPSocket().

264  {
265  CHECK_NE(NetworkSocket(), fd_) << "Socket not yet bound";
266 
267  sockaddr_storage addrStorage;
268  address.getAddress(&addrStorage);
269 
270  struct msghdr msg;
271  msg.msg_name = reinterpret_cast<void*>(&addrStorage);
272  msg.msg_namelen = address.getActualSize();
273  msg.msg_iov = const_cast<struct iovec*>(vec);
274  msg.msg_iovlen = iovec_len;
275  msg.msg_control = nullptr;
276  msg.msg_controllen = 0;
277  msg.msg_flags = 0;
278 
279 #ifdef FOLLY_HAVE_MSG_ERRQUEUE
280  if (gso > 0) {
281  char control[CMSG_SPACE(sizeof(uint16_t))];
282  msg.msg_control = control;
283  msg.msg_controllen = sizeof(control);
284 
285  struct cmsghdr* cm = CMSG_FIRSTHDR(&msg);
286  cm->cmsg_level = SOL_UDP;
287  cm->cmsg_type = UDP_SEGMENT;
288  cm->cmsg_len = CMSG_LEN(sizeof(uint16_t));
289  uint16_t gso_len = static_cast<uint16_t>(gso);
290  memcpy(CMSG_DATA(cm), &gso_len, sizeof(gso_len));
291 
292  return sendmsg(fd_, &msg, 0);
293  }
294 #else
295  CHECK_LT(gso, 1) << "GSO not supported";
296 #endif
297 
298  return sendmsg(fd_, &msg, 0);
299 }
socklen_t getActualSize() const
#define SOL_UDP
Definition: NetOps.h:59
virtual ssize_t sendmsg(NetworkSocket socket, const struct msghdr *message, int flags)
#define UDP_SEGMENT
Definition: NetOps.h:67
socklen_t getAddress(sockaddr_storage *addr) const
vector< string > vec
Definition: StringTest.cpp:35
ssize_t folly::AsyncUDPSocket::writev ( const folly::SocketAddress address,
const struct iovec *  vec,
size_t  veclen 
)
virtual

Definition at line 301 of file AsyncUDPSocket.cpp.

References writev().

304  {
305  return writev(address, vec, iovec_len, 0);
306 }
virtual ssize_t writev(const folly::SocketAddress &address, const struct iovec *vec, size_t veclen, int gso)
Definition: Traits.h:588

Member Data Documentation

int folly::AsyncUDPSocket::busyPollUs_ {0}
private

Definition at line 322 of file AsyncUDPSocket.h.

Referenced by bind(), and setBusyPoll().

folly::SocketAddress folly::AsyncUDPSocket::clientAddress_
private

Definition at line 316 of file AsyncUDPSocket.h.

Referenced by handleRead().

ErrMessageCallback* folly::AsyncUDPSocket::errMessageCallback_ {nullptr}
private

Definition at line 328 of file AsyncUDPSocket.h.

Referenced by failErrMessageRead(), handleErrMessages(), and setErrMessageCallback().

EventBase* folly::AsyncUDPSocket::eventBase_
private

Definition at line 309 of file AsyncUDPSocket.h.

Referenced by attachEventBase(), close(), detachEventBase(), and getEventBase().

folly::Optional<int> folly::AsyncUDPSocket::gso_
private

Definition at line 326 of file AsyncUDPSocket.h.

Referenced by getGSO(), and setGSO().

folly::SocketAddress folly::AsyncUDPSocket::localAddress_
private

Definition at line 310 of file AsyncUDPSocket.h.

Referenced by address(), bind(), handleRead(), and setFD().

FDOwnership folly::AsyncUDPSocket::ownership_
private

Definition at line 313 of file AsyncUDPSocket.h.

Referenced by bind(), close(), and setFD().

int folly::AsyncUDPSocket::rcvBuf_ {0}
private

Definition at line 320 of file AsyncUDPSocket.h.

Referenced by bind(), and setRcvBuf().

ReadCallback* folly::AsyncUDPSocket::readCallback_
protected
bool folly::AsyncUDPSocket::reuseAddr_ {true}
private

Definition at line 318 of file AsyncUDPSocket.h.

Referenced by bind(), and setReuseAddr().

bool folly::AsyncUDPSocket::reusePort_ {false}
private

Definition at line 319 of file AsyncUDPSocket.h.

Referenced by bind(), and setReusePort().

int folly::AsyncUDPSocket::sndBuf_ {0}
private

Definition at line 321 of file AsyncUDPSocket.h.

Referenced by bind(), and setSndBuf().


The documentation for this class was generated from the following files: