Commit 50c13594 authored by Subodh Iyengar's avatar Subodh Iyengar Committed by Facebook Github Bot

add connect method to AsyncUDPSocket

Summary:
Calling connect on the UDP socket can avoid route lookups
on the write path. This would be an optimization that would be
useful for clients.

There are several caveats of using connect() which we discovered
during testing. These are documented and unit tests have been written
for each of them.

Reviewed By: yfeldblum

Differential Revision: D7802389

fbshipit-source-id: 09b71373a3a95c5dab73ee9345db0dbbf66d4ec5
parent 7a500026
...@@ -380,6 +380,14 @@ void AsyncUDPSocket::failErrMessageRead(const AsyncSocketException& ex) { ...@@ -380,6 +380,14 @@ void AsyncUDPSocket::failErrMessageRead(const AsyncSocketException& ex) {
} }
} }
int AsyncUDPSocket::connect(const folly::SocketAddress& address) {
CHECK_NE(-1, fd_) << "Socket not yet bound";
sockaddr_storage addrStorage;
address.getAddress(&addrStorage);
return fsp::connect(
fd_, reinterpret_cast<sockaddr*>(&addrStorage), address.getActualSize());
}
void AsyncUDPSocket::handleRead() noexcept { void AsyncUDPSocket::handleRead() noexcept {
void* buf{nullptr}; void* buf{nullptr};
size_t len{0}; size_t len{0};
......
...@@ -224,6 +224,26 @@ class AsyncUDPSocket : public EventHandler { ...@@ -224,6 +224,26 @@ class AsyncUDPSocket : public EventHandler {
*/ */
virtual void setErrMessageCallback(ErrMessageCallback* errMessageCallback); virtual void setErrMessageCallback(ErrMessageCallback* errMessageCallback);
/**
* 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.
*/
virtual int connect(const folly::SocketAddress& address);
protected: protected:
virtual ssize_t sendmsg(int socket, const struct msghdr* message, int flags) { virtual ssize_t sendmsg(int socket, const struct msghdr* message, int flags) {
return ::sendmsg(socket, message, flags); return ::sendmsg(socket, message, flags);
......
This diff is collapsed.
...@@ -42,6 +42,7 @@ struct MockAsyncUDPSocket : public AsyncUDPSocket { ...@@ -42,6 +42,7 @@ struct MockAsyncUDPSocket : public AsyncUDPSocket {
MOCK_METHOD1(setReuseAddr, void(bool)); MOCK_METHOD1(setReuseAddr, void(bool));
MOCK_METHOD1(dontFragment, void(bool)); MOCK_METHOD1(dontFragment, void(bool));
MOCK_METHOD1(setErrMessageCallback, void(ErrMessageCallback*)); MOCK_METHOD1(setErrMessageCallback, void(ErrMessageCallback*));
MOCK_METHOD1(connect, int(const SocketAddress&));
}; };
} // namespace test } // namespace test
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment