Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add setsockopt to HttpServer #2086

Merged
merged 1 commit into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions examples/helloworld/main.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <netinet/tcp.h>
#include <sys/socket.h>
#endif

#include <drogon/drogon.h>
using namespace drogon;

Expand Down Expand Up @@ -61,6 +68,23 @@ int main()
},
{Get});

app()
.setBeforeListenSockOptCallback([](int fd) {
LOG_INFO << "setBeforeListenSockOptCallback:" << fd;
#ifdef _WIN32
#elif __linux__
int enable = 1;
if (setsockopt(
fd, IPPROTO_TCP, TCP_FASTOPEN, &enable, sizeof(enable)) ==
-1)
{
LOG_INFO << "setsockopt TCP_FASTOPEN failed";
}
#else
#endif
})
.setAfterAcceptSockOptCallback([](int) {});

// Ask Drogon to listen on 127.0.0.1 port 8848. Drogon supports listening
// on multiple IP addresses by adding multiple listeners. For example, if
// you want the server also listen on 127.0.0.1 port 5555. Just add another
Expand Down
16 changes: 16 additions & 0 deletions lib/inc/drogon/HttpAppFramework.h
Original file line number Diff line number Diff line change
Expand Up @@ -1590,6 +1590,22 @@ class DROGON_EXPORT HttpAppFramework : public trantor::NonCopyable
*/
virtual int64_t getConnectionCount() const = 0;

/**
* @brief Set the before listen setsockopt callback.
*
* @param cb This callback will be called before the listen
*/
virtual HttpAppFramework &setBeforeListenSockOptCallback(
std::function<void(int)> cb) = 0;

/**
* @brief Set the after accept setsockopt callback.
*
* @param cb This callback will be called after accept
*/
virtual HttpAppFramework &setAfterAcceptSockOptCallback(
std::function<void(int)> cb) = 0;

private:
virtual void registerHttpController(
const std::string &pathPattern,
Expand Down
14 changes: 14 additions & 0 deletions lib/src/HttpAppFrameworkImpl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1336,3 +1336,17 @@ HttpAppFramework &HttpAppFrameworkImpl::registerPreSendingAdvice(
AopAdvice::instance().registerPreSendingAdvice(advice);
return *this;
}

HttpAppFramework &HttpAppFrameworkImpl::setBeforeListenSockOptCallback(
std::function<void(int)> cb)
{
listenerManagerPtr_->setBeforeListenSockOptCallback(std::move(cb));
return *this;
}

HttpAppFramework &HttpAppFrameworkImpl::setAfterAcceptSockOptCallback(
std::function<void(int)> cb)
{
listenerManagerPtr_->setAfterAcceptSockOptCallback(std::move(cb));
return *this;
}
5 changes: 5 additions & 0 deletions lib/src/HttpAppFrameworkImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,11 @@ class HttpAppFrameworkImpl final : public HttpAppFramework
HttpResponsePtr handleSessionForResponse(const HttpRequestImplPtr &req,
const HttpResponsePtr &resp);

HttpAppFramework &setBeforeListenSockOptCallback(
std::function<void(int)> cb) override;
HttpAppFramework &setAfterAcceptSockOptCallback(
std::function<void(int)> cb) override;

private:
void registerHttpController(const std::string &pathPattern,
const internal::HttpBinderBasePtr &binder,
Expand Down
8 changes: 8 additions & 0 deletions lib/src/HttpServer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ HttpServer::~HttpServer() = default;

void HttpServer::start()
{
if (beforeListenSetSockOptCallback_)
{
server_.setBeforeListenSockOptCallback(beforeListenSetSockOptCallback_);
}
if (afterAcceptSetSockOptCallback_)
{
server_.setAfterAcceptSockOptCallback(afterAcceptSetSockOptCallback_);
}
LOG_TRACE << "HttpServer[" << server_.name() << "] starts listening on "
<< server_.ipPort();
server_.start();
Expand Down
13 changes: 13 additions & 0 deletions lib/src/HttpServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ class HttpServer : trantor::NonCopyable
return server_.address();
}

void setBeforeListenSockOptCallback(std::function<void(int)> cb)
{
beforeListenSetSockOptCallback_ = std::move(cb);
}

void setAfterAcceptSockOptCallback(std::function<void(int)> cb)
{
afterAcceptSetSockOptCallback_ = std::move(cb);
}

private:
friend class HttpInternalForwardHelper;

Expand Down Expand Up @@ -126,6 +136,9 @@ class HttpServer : trantor::NonCopyable
trantor::MsgBuffer &buffer);

trantor::TcpServer server_;

std::function<void(int)> beforeListenSetSockOptCallback_;
std::function<void(int)> afterAcceptSetSockOptCallback_;
};

class HttpInternalForwardHelper
Expand Down
10 changes: 10 additions & 0 deletions lib/src/ListenerManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ void ListenerManager::createListeners(
std::make_shared<HttpServer>(ioLoops[i],
listenAddress,
"drogon");
if (beforeListenSetSockOptCallback_)
{
serverPtr->setBeforeListenSockOptCallback(
beforeListenSetSockOptCallback_);
}
if (afterAcceptSetSockOptCallback_)
{
serverPtr->setAfterAcceptSockOptCallback(
afterAcceptSetSockOptCallback_);
}

if (listener.useSSL_ && utils::supportsTls())
{
Expand Down
12 changes: 12 additions & 0 deletions lib/src/ListenerManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ class ListenerManager : public trantor::NonCopyable
void startListening();
void stopListening();

void setBeforeListenSockOptCallback(std::function<void(int)> cb)
{
beforeListenSetSockOptCallback_ = std::move(cb);
}

void setAfterAcceptSockOptCallback(std::function<void(int)> cb)
{
afterAcceptSetSockOptCallback_ = std::move(cb);
}

private:
struct ListenerInfo
{
Expand Down Expand Up @@ -87,6 +97,8 @@ class ListenerManager : public trantor::NonCopyable
// should have value when and only when on OS that one port can only be
// listened by one thread
std::unique_ptr<trantor::EventLoopThread> listeningThread_;
std::function<void(int)> beforeListenSetSockOptCallback_;
std::function<void(int)> afterAcceptSetSockOptCallback_;
};

} // namespace drogon
Loading