verdnatura-chat/ios/Pods/Flipper-Folly/folly/io/async/AsyncServerSocket.h

902 lines
29 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <folly/SocketAddress.h>
#include <folly/String.h>
#include <folly/io/ShutdownSocketSet.h>
#include <folly/io/async/AsyncSocketBase.h>
#include <folly/io/async/AsyncTimeout.h>
#include <folly/io/async/DelayedDestruction.h>
#include <folly/io/async/EventBase.h>
#include <folly/io/async/EventHandler.h>
#include <folly/io/async/NotificationQueue.h>
#include <folly/net/NetOps.h>
#include <folly/net/NetworkSocket.h>
#include <folly/portability/Sockets.h>
#include <limits.h>
#include <stddef.h>
#include <exception>
#include <memory>
#include <vector>
// Due to the way kernel headers are included, this may or may not be defined.
// Number pulled from 3.10 kernel headers.
#ifndef SO_REUSEPORT
#define SO_REUSEPORT 15
#endif
#if defined __linux__ && !defined SO_NO_TRANSPARENT_TLS
#define SO_NO_TRANSPARENT_TLS 200
#endif
namespace folly {
/**
* A listening socket that asynchronously informs a callback whenever a new
* connection has been accepted.
*
* Unlike most async interfaces that always invoke their callback in the same
* EventBase thread, AsyncServerSocket is unusual in that it can distribute
* the callbacks across multiple EventBase threads.
*
* This supports a common use case for network servers to distribute incoming
* connections across a number of EventBase threads. (Servers typically run
* with one EventBase thread per CPU.)
*
* Despite being able to invoke callbacks in multiple EventBase threads,
* AsyncServerSocket still has one "primary" EventBase. Operations that
* modify the AsyncServerSocket state may only be performed from the primary
* EventBase thread.
*/
class AsyncServerSocket : public DelayedDestruction, public AsyncSocketBase {
public:
typedef std::unique_ptr<AsyncServerSocket, Destructor> UniquePtr;
// Disallow copy, move, and default construction.
AsyncServerSocket(AsyncServerSocket&&) = delete;
/**
* A callback interface to get notified of client socket events.
*
* The ConnectionEventCallback implementations need to be thread-safe as the
* callbacks may be called from different threads.
*/
class ConnectionEventCallback {
public:
virtual ~ConnectionEventCallback() = default;
/**
* onConnectionAccepted() is called right after a client connection
* is accepted using the system accept()/accept4() APIs.
*/
virtual void onConnectionAccepted(
const NetworkSocket socket,
const SocketAddress& addr) noexcept = 0;
/**
* onConnectionAcceptError() is called when an error occurred accepting
* a connection.
*/
virtual void onConnectionAcceptError(const int err) noexcept = 0;
/**
* onConnectionDropped() is called when a connection is dropped,
* probably because of some error encountered.
*/
virtual void onConnectionDropped(
const NetworkSocket socket,
const SocketAddress& addr) noexcept = 0;
/**
* onConnectionEnqueuedForAcceptorCallback() is called when the
* connection is successfully enqueued for an AcceptCallback to pick up.
*/
virtual void onConnectionEnqueuedForAcceptorCallback(
const NetworkSocket socket,
const SocketAddress& addr) noexcept = 0;
/**
* onConnectionDequeuedByAcceptorCallback() is called when the
* connection is successfully dequeued by an AcceptCallback.
*/
virtual void onConnectionDequeuedByAcceptorCallback(
const NetworkSocket socket,
const SocketAddress& addr) noexcept = 0;
/**
* onBackoffStarted is called when the socket has successfully started
* backing off accepting new client sockets.
*/
virtual void onBackoffStarted() noexcept = 0;
/**
* onBackoffEnded is called when the backoff period has ended and the socket
* has successfully resumed accepting new connections if there is any
* AcceptCallback registered.
*/
virtual void onBackoffEnded() noexcept = 0;
/**
* onBackoffError is called when there is an error entering backoff
*/
virtual void onBackoffError() noexcept = 0;
};
class AcceptCallback {
public:
virtual ~AcceptCallback() = default;
/**
* connectionAccepted() is called whenever a new client connection is
* received.
*
* The AcceptCallback will remain installed after connectionAccepted()
* returns.
*
* @param fd The newly accepted client socket. The AcceptCallback
* assumes ownership of this socket, and is responsible
* for closing it when done. The newly accepted file
* descriptor will have already been put into
* non-blocking mode.
* @param clientAddr A reference to a SocketAddress struct containing the
* client's address. This struct is only guaranteed to
* remain valid until connectionAccepted() returns.
*/
virtual void connectionAccepted(
NetworkSocket fd,
const SocketAddress& clientAddr) noexcept = 0;
/**
* acceptError() is called if an error occurs while accepting.
*
* The AcceptCallback will remain installed even after an accept error,
* as the errors are typically somewhat transient, such as being out of
* file descriptors. The server socket must be explicitly stopped if you
* wish to stop accepting after an error.
*
* @param ex An exception representing the error.
*/
virtual void acceptError(const std::exception& ex) noexcept = 0;
/**
* acceptStarted() will be called in the callback's EventBase thread
* after this callback has been added to the AsyncServerSocket.
*
* acceptStarted() will be called before any calls to connectionAccepted()
* or acceptError() are made on this callback.
*
* acceptStarted() makes it easier for callbacks to perform initialization
* inside the callback thread. (The call to addAcceptCallback() must
* always be made from the AsyncServerSocket's primary EventBase thread.
* acceptStarted() provides a hook that will always be invoked in the
* callback's thread.)
*
* Note that the call to acceptStarted() is made once the callback is
* added, regardless of whether or not the AsyncServerSocket is actually
* accepting at the moment. acceptStarted() will be called even if the
* AsyncServerSocket is paused when the callback is added (including if
* the initial call to startAccepting() on the AsyncServerSocket has not
* been made yet).
*/
virtual void acceptStarted() noexcept {}
/**
* acceptStopped() will be called when this AcceptCallback is removed from
* the AsyncServerSocket, or when the AsyncServerSocket is destroyed,
* whichever occurs first.
*
* No more calls to connectionAccepted() or acceptError() will be made
* after acceptStopped() is invoked.
*/
virtual void acceptStopped() noexcept {}
};
static const uint32_t kDefaultMaxAcceptAtOnce = 30;
static const uint32_t kDefaultCallbackAcceptAtOnce = 5;
static const uint32_t kDefaultMaxMessagesInQueue = 1024;
/**
* Create a new AsyncServerSocket with the specified EventBase.
*
* @param eventBase The EventBase to use for driving the asynchronous I/O.
* If this parameter is nullptr, attachEventBase() must be
* called before this socket can begin accepting
* connections.
*/
explicit AsyncServerSocket(EventBase* eventBase = nullptr);
/**
* Helper function to create a shared_ptr<AsyncServerSocket>.
*
* This passes in the correct destructor object, since AsyncServerSocket's
* destructor is protected and cannot be invoked directly.
*/
static std::shared_ptr<AsyncServerSocket> newSocket(
EventBase* evb = nullptr) {
return std::shared_ptr<AsyncServerSocket>(
new AsyncServerSocket(evb), Destructor());
}
void setShutdownSocketSet(const std::weak_ptr<ShutdownSocketSet>& wNewSS);
/**
* Destroy the socket.
*
* AsyncServerSocket::destroy() must be called to destroy the socket.
* The normal destructor is private, and should not be invoked directly.
* This prevents callers from deleting a AsyncServerSocket while it is
* invoking a callback.
*
* destroy() must be invoked from the socket's primary EventBase thread.
*
* If there are AcceptCallbacks still installed when destroy() is called,
* acceptStopped() will be called on these callbacks to notify them that
* accepting has stopped. Accept callbacks being driven by other EventBase
* threads may continue to receive new accept callbacks for a brief period of
* time after destroy() returns. They will not receive any more callback
* invocations once acceptStopped() is invoked.
*/
void destroy() override;
/**
* Attach this AsyncServerSocket to its primary EventBase.
*
* This may only be called if the AsyncServerSocket is not already attached
* to a EventBase. The AsyncServerSocket must be attached to a EventBase
* before it can begin accepting connections.
*/
void attachEventBase(EventBase* eventBase);
/**
* Detach the AsyncServerSocket from its primary EventBase.
*
* detachEventBase() may only be called if the AsyncServerSocket is not
* currently accepting connections.
*/
void detachEventBase();
/**
* Get the EventBase used by this socket.
*/
EventBase* getEventBase() const override {
return eventBase_;
}
/**
* Create a AsyncServerSocket from an existing socket file descriptor.
*
* useExistingSocket() will cause the AsyncServerSocket to take ownership of
* the specified file descriptor, and use it to listen for new connections.
* The AsyncServerSocket will close the file descriptor when it is
* destroyed.
*
* useExistingSocket() must be called before bind() or listen().
*
* The supplied file descriptor will automatically be put into non-blocking
* mode. The caller may have already directly called bind() and possibly
* listen on the file descriptor. If so the caller should skip calling the
* corresponding AsyncServerSocket::bind() and listen() methods.
*
* On error a AsyncSocketException will be thrown and the caller will retain
* ownership of the file descriptor.
*/
void useExistingSocket(NetworkSocket fd);
void useExistingSockets(const std::vector<NetworkSocket>& fds);
/**
* Return the underlying file descriptor
*/
std::vector<NetworkSocket> getNetworkSockets() const {
std::vector<NetworkSocket> sockets;
for (auto& handler : sockets_) {
sockets.push_back(handler.socket_);
}
return sockets;
}
/**
* Backwards compatible getSocket, warns if > 1 socket
*/
NetworkSocket getNetworkSocket() const {
if (sockets_.size() > 1) {
VLOG(2) << "Warning: getSocket can return multiple fds, "
<< "but getSockets was not called, so only returning the first";
}
if (sockets_.size() == 0) {
return NetworkSocket();
} else {
return sockets_[0].socket_;
}
}
/* enable zerocopy support for the server sockets - the s = accept sockets
* inherit it
*/
bool setZeroCopy(bool enable);
/**
* Bind to the specified address.
*
* This must be called from the primary EventBase thread.
*
* Throws AsyncSocketException on error.
*/
virtual void bind(const SocketAddress& address);
/**
* Bind to the specified port for the specified addresses.
*
* This must be called from the primary EventBase thread.
*
* Throws AsyncSocketException on error.
*/
virtual void bind(const std::vector<IPAddress>& ipAddresses, uint16_t port);
/**
* Bind to the specified port.
*
* This must be called from the primary EventBase thread.
*
* Throws AsyncSocketException on error.
*/
virtual void bind(uint16_t port);
/**
* Get the local address to which the socket is bound.
*
* Throws AsyncSocketException on error.
*/
void getAddress(SocketAddress* addressReturn) const override;
/**
* Get the local address to which the socket is bound.
*
* Throws AsyncSocketException on error.
*/
SocketAddress getAddress() const {
SocketAddress ret;
getAddress(&ret);
return ret;
}
/**
* Get all the local addresses to which the socket is bound.
*
* Throws AsyncSocketException on error.
*/
std::vector<SocketAddress> getAddresses() const;
/**
* Begin listening for connections.
*
* This calls ::listen() with the specified backlog.
*
* Once listen() is invoked the socket will actually be open so that remote
* clients may establish connections. (Clients that attempt to connect
* before listen() is called will receive a connection refused error.)
*
* At least one callback must be set and startAccepting() must be called to
* actually begin notifying the accept callbacks of newly accepted
* connections. The backlog parameter controls how many connections the
* kernel will accept and buffer internally while the accept callbacks are
* paused (or if accepting is enabled but the callbacks cannot keep up).
*
* bind() must be called before calling listen().
* listen() must be called from the primary EventBase thread.
*
* Throws AsyncSocketException on error.
*/
virtual void listen(int backlog);
/**
* Add an AcceptCallback.
*
* When a new socket is accepted, one of the AcceptCallbacks will be invoked
* with the new socket. The AcceptCallbacks are invoked in a round-robin
* fashion. This allows the accepted sockets to be distributed among a pool
* of threads, each running its own EventBase object. This is a common model,
* since most asynchronous-style servers typically run one EventBase thread
* per CPU.
*
* The EventBase object associated with each AcceptCallback must be running
* its loop. If the EventBase loop is not running, sockets will still be
* scheduled for the callback, but the callback cannot actually get invoked
* until the loop runs.
*
* This method must be invoked from the AsyncServerSocket's primary
* EventBase thread.
*
* Note that startAccepting() must be called on the AsyncServerSocket to
* cause it to actually start accepting sockets once callbacks have been
* installed.
*
* @param callback The callback to invoke.
* @param eventBase The EventBase to use to invoke the callback. This
* parameter may be nullptr, in which case the callback will be invoked in
* the AsyncServerSocket's primary EventBase.
* @param maxAtOnce The maximum number of connections to accept in this
* callback on a single iteration of the event base loop.
* This only takes effect when eventBase is non-nullptr.
* When using a nullptr eventBase for the callback, the
* setMaxAcceptAtOnce() method controls how many
* connections the main event base will accept at once.
*/
virtual void addAcceptCallback(
AcceptCallback* callback,
EventBase* eventBase,
uint32_t maxAtOnce = kDefaultCallbackAcceptAtOnce);
/**
* Remove an AcceptCallback.
*
* This allows a single AcceptCallback to be removed from the round-robin
* pool.
*
* This method must be invoked from the AsyncServerSocket's primary
* EventBase thread. Use EventBase::runInEventBaseThread() to schedule the
* operation in the correct EventBase if your code is not in the server
* socket's primary EventBase.
*
* Given that the accept callback is being driven by a different EventBase,
* the AcceptCallback may continue to be invoked for a short period of time
* after removeAcceptCallback() returns in this thread. Once the other
* EventBase thread receives the notification to stop, it will call
* acceptStopped() on the callback to inform it that it is fully stopped and
* will not receive any new sockets.
*
* If the last accept callback is removed while the socket is accepting,
* the socket will implicitly pause accepting. If a callback is later added,
* it will resume accepting immediately, without requiring startAccepting()
* to be invoked.
*
* @param callback The callback to uninstall.
* @param eventBase The EventBase associated with this callback. This must
* be the same EventBase that was used when the callback was installed
* with addAcceptCallback().
*/
void removeAcceptCallback(AcceptCallback* callback, EventBase* eventBase);
/**
* Begin accepting connctions on this socket.
*
* bind() and listen() must be called before calling startAccepting().
*
* When a AsyncServerSocket is initially created, it will not begin
* accepting connections until at least one callback has been added and
* startAccepting() has been called. startAccepting() can also be used to
* resume accepting connections after a call to pauseAccepting().
*
* If startAccepting() is called when there are no accept callbacks
* installed, the socket will not actually begin accepting until an accept
* callback is added.
*
* This method may only be called from the primary EventBase thread.
*/
virtual void startAccepting();
/**
* Pause accepting connections.
*
* startAccepting() may be called to resume accepting.
*
* This method may only be called from the primary EventBase thread.
* If there are AcceptCallbacks being driven by other EventBase threads they
* may continue to receive callbacks for a short period of time after
* pauseAccepting() returns.
*
* Unlike removeAcceptCallback() or destroy(), acceptStopped() will not be
* called on the AcceptCallback objects simply due to a temporary pause. If
* the server socket is later destroyed while paused, acceptStopped() will be
* called all of the installed AcceptCallbacks.
*/
void pauseAccepting();
/**
* Shutdown the listen socket and notify all callbacks that accept has
* stopped, but don't close the socket. This invokes shutdown(2) with the
* supplied argument. Passing -1 will close the socket now. Otherwise, the
* close will be delayed until this object is destroyed.
*
* Only use this if you have reason to pass special flags to shutdown.
* Otherwise just destroy the socket.
*
* This method has no effect when a ShutdownSocketSet option is used.
*
* Returns the result of shutdown on sockets_[n-1]
*/
int stopAccepting(int shutdownFlags = -1);
/**
* Get the maximum number of connections that will be accepted each time
* around the event loop.
*/
uint32_t getMaxAcceptAtOnce() const {
return maxAcceptAtOnce_;
}
/**
* Set the maximum number of connections that will be accepted each time
* around the event loop.
*
* This provides a very coarse-grained way of controlling how fast the
* AsyncServerSocket will accept connections. If you find that when your
* server is overloaded AsyncServerSocket accepts connections more quickly
* than your code can process them, you can try lowering this number so that
* fewer connections will be accepted each event loop iteration.
*
* For more explicit control over the accept rate, you can also use
* pauseAccepting() to temporarily pause accepting when your server is
* overloaded, and then use startAccepting() later to resume accepting.
*/
void setMaxAcceptAtOnce(uint32_t numConns) {
maxAcceptAtOnce_ = numConns;
}
/**
* Get the maximum number of unprocessed messages which a NotificationQueue
* can hold.
*/
uint32_t getMaxNumMessagesInQueue() const {
return maxNumMsgsInQueue_;
}
/**
* Set the maximum number of unprocessed messages in NotificationQueue.
* No new message will be sent to that NotificationQueue if there are more
* than such number of unprocessed messages in that queue.
*
* Only works if called before addAcceptCallback.
*/
void setMaxNumMessagesInQueue(uint32_t num) {
maxNumMsgsInQueue_ = num;
}
/**
* Get the speed of adjusting connection accept rate.
*/
double getAcceptRateAdjustSpeed() const {
return acceptRateAdjustSpeed_;
}
/**
* Set the speed of adjusting connection accept rate.
*/
void setAcceptRateAdjustSpeed(double speed) {
acceptRateAdjustSpeed_ = speed;
}
/**
* Enable/Disable TOS reflection for the server socket
*/
void setTosReflect(bool enable);
bool getTosReflect() {
return tosReflect_;
}
/**
* Get the number of connections dropped by the AsyncServerSocket
*/
std::size_t getNumDroppedConnections() const {
return numDroppedConnections_;
}
/**
* Get the current number of unprocessed messages in NotificationQueue.
*
* This method must be invoked from the AsyncServerSocket's primary
* EventBase thread. Use EventBase::runInEventBaseThread() to schedule the
* operation in the correct EventBase if your code is not in the server
* socket's primary EventBase.
*/
int64_t getNumPendingMessagesInQueue() const {
if (eventBase_) {
eventBase_->dcheckIsInEventBaseThread();
}
int64_t numMsgs = 0;
for (const auto& callback : callbacks_) {
if (callback.consumer) {
numMsgs += callback.consumer->getQueue()->size();
}
}
return numMsgs;
}
/**
* Set whether or not SO_KEEPALIVE should be enabled on the server socket
* (and thus on all subsequently-accepted connections). By default, keepalive
* is enabled.
*
* Note that TCP keepalive usually only kicks in after the connection has
* been idle for several hours. Applications should almost always have their
* own, shorter idle timeout.
*/
void setKeepAliveEnabled(bool enabled) {
keepAliveEnabled_ = enabled;
for (auto& handler : sockets_) {
if (handler.socket_ == NetworkSocket()) {
continue;
}
int val = (enabled) ? 1 : 0;
if (netops::setsockopt(
handler.socket_, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) !=
0) {
LOG(ERROR) << "failed to set SO_KEEPALIVE on async server socket: %s"
<< errnoStr(errno);
}
}
}
/**
* Get whether or not SO_KEEPALIVE is enabled on the server socket.
*/
bool getKeepAliveEnabled() const {
return keepAliveEnabled_;
}
/**
* Set whether or not SO_REUSEPORT should be enabled on the server socket,
* allowing multiple binds to the same port
*/
void setReusePortEnabled(bool enabled) {
reusePortEnabled_ = enabled;
for (auto& handler : sockets_) {
if (handler.socket_ == NetworkSocket()) {
continue;
}
int val = (enabled) ? 1 : 0;
if (netops::setsockopt(
handler.socket_, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)) !=
0) {
auto errnoCopy = errno;
LOG(ERROR) << "failed to set SO_REUSEPORT on async server socket "
<< errnoCopy;
folly::throwSystemErrorExplicit(
errnoCopy, "failed to set SO_REUSEPORT on async server socket");
}
}
}
/**
* Get whether or not SO_REUSEPORT is enabled on the server socket.
*/
bool getReusePortEnabled_() const {
return reusePortEnabled_;
}
/**
* Set whether or not the socket should close during exec() (FD_CLOEXEC). By
* default, this is enabled
*/
void setCloseOnExec(bool closeOnExec) {
closeOnExec_ = closeOnExec;
}
/**
* Get whether or not FD_CLOEXEC is enabled on the server socket.
*/
bool getCloseOnExec() const {
return closeOnExec_;
}
/**
* Tries to enable TFO if the machine supports it.
*/
void setTFOEnabled(bool enabled, uint32_t maxTFOQueueSize) {
tfo_ = enabled;
tfoMaxQueueSize_ = maxTFOQueueSize;
}
/**
* Do not attempt the transparent TLS handshake
*/
void disableTransparentTls() {
noTransparentTls_ = true;
}
/**
* Get whether or not the socket is accepting new connections
*/
bool getAccepting() const {
return accepting_;
}
/**
* Set the ConnectionEventCallback
*/
void setConnectionEventCallback(
ConnectionEventCallback* const connectionEventCallback) {
connectionEventCallback_ = connectionEventCallback;
}
/**
* Get the ConnectionEventCallback
*/
ConnectionEventCallback* getConnectionEventCallback() const {
return connectionEventCallback_;
}
protected:
/**
* Protected destructor.
*
* Invoke destroy() instead to destroy the AsyncServerSocket.
*/
~AsyncServerSocket() override;
private:
enum class MessageType { MSG_NEW_CONN = 0, MSG_ERROR = 1 };
struct QueueMessage {
MessageType type;
NetworkSocket fd;
int err;
SocketAddress address;
std::string msg;
};
/**
* A class to receive notifications to invoke AcceptCallback objects
* in other EventBase threads.
*
* A RemoteAcceptor object is created for each AcceptCallback that
* is installed in a separate EventBase thread. The RemoteAcceptor
* receives notification of new sockets via a NotificationQueue,
* and then invokes the AcceptCallback.
*/
class RemoteAcceptor : private NotificationQueue<QueueMessage>::Consumer {
public:
explicit RemoteAcceptor(
AcceptCallback* callback,
ConnectionEventCallback* connectionEventCallback)
: callback_(callback),
connectionEventCallback_(connectionEventCallback) {}
~RemoteAcceptor() override = default;
void start(EventBase* eventBase, uint32_t maxAtOnce, uint32_t maxInQueue);
void stop(EventBase* eventBase, AcceptCallback* callback);
void messageAvailable(QueueMessage&& msg) noexcept override;
NotificationQueue<QueueMessage>* getQueue() {
return &queue_;
}
private:
AcceptCallback* callback_;
ConnectionEventCallback* connectionEventCallback_;
NotificationQueue<QueueMessage> queue_;
};
/**
* A struct to keep track of the callbacks associated with this server
* socket.
*/
struct CallbackInfo {
CallbackInfo(AcceptCallback* cb, EventBase* evb)
: callback(cb), eventBase(evb), consumer(nullptr) {}
AcceptCallback* callback;
EventBase* eventBase;
RemoteAcceptor* consumer;
};
class BackoffTimeout;
virtual void
handlerReady(uint16_t events, NetworkSocket fd, sa_family_t family) noexcept;
NetworkSocket createSocket(int family);
void setupSocket(NetworkSocket fd, int family);
void bindSocket(
NetworkSocket fd,
const SocketAddress& address,
bool isExistingSocket);
void dispatchSocket(NetworkSocket socket, SocketAddress&& address);
void dispatchError(const char* msg, int errnoValue);
void enterBackoff();
void backoffTimeoutExpired();
CallbackInfo* nextCallback() {
CallbackInfo* info = &callbacks_[callbackIndex_];
++callbackIndex_;
if (callbackIndex_ >= callbacks_.size()) {
callbackIndex_ = 0;
}
return info;
}
struct ServerEventHandler : public EventHandler {
ServerEventHandler(
EventBase* eventBase,
NetworkSocket socket,
AsyncServerSocket* parent,
sa_family_t addressFamily)
: EventHandler(eventBase, socket),
eventBase_(eventBase),
socket_(socket),
parent_(parent),
addressFamily_(addressFamily) {}
ServerEventHandler(const ServerEventHandler& other)
: EventHandler(other.eventBase_, other.socket_),
eventBase_(other.eventBase_),
socket_(other.socket_),
parent_(other.parent_),
addressFamily_(other.addressFamily_) {}
ServerEventHandler& operator=(const ServerEventHandler& other) {
if (this != &other) {
eventBase_ = other.eventBase_;
socket_ = other.socket_;
parent_ = other.parent_;
addressFamily_ = other.addressFamily_;
detachEventBase();
attachEventBase(other.eventBase_);
changeHandlerFD(other.socket_);
}
return *this;
}
// Inherited from EventHandler
void handlerReady(uint16_t events) noexcept override {
parent_->handlerReady(events, socket_, addressFamily_);
}
EventBase* eventBase_;
NetworkSocket socket_;
AsyncServerSocket* parent_;
sa_family_t addressFamily_;
};
EventBase* eventBase_;
std::vector<ServerEventHandler> sockets_;
std::vector<NetworkSocket> pendingCloseSockets_;
bool accepting_;
uint32_t maxAcceptAtOnce_;
uint32_t maxNumMsgsInQueue_;
double acceptRateAdjustSpeed_; // 0 to disable auto adjust
double acceptRate_;
std::chrono::time_point<std::chrono::steady_clock> lastAccepTimestamp_;
std::size_t numDroppedConnections_;
uint32_t callbackIndex_;
BackoffTimeout* backoffTimeout_;
std::vector<CallbackInfo> callbacks_;
bool keepAliveEnabled_;
bool reusePortEnabled_{false};
bool closeOnExec_;
bool tfo_{false};
bool noTransparentTls_{false};
uint32_t tfoMaxQueueSize_{0};
std::weak_ptr<ShutdownSocketSet> wShutdownSocketSet_;
ConnectionEventCallback* connectionEventCallback_{nullptr};
bool tosReflect_{false};
bool zeroCopyVal_{false};
};
} // namespace folly