Skip to content
Open
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
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "trantor"]
path = trantor
url = https://github.com/an-tao/trantor.git
url = https://github.com/SBALAVIGNESH123/trantor.git
branch = master
28 changes: 28 additions & 0 deletions lib/inc/drogon/HttpAppFramework.h
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,34 @@ class DROGON_EXPORT HttpAppFramework : public trantor::NonCopyable
const std::vector<std::pair<std::string, std::string>> &sslConfCmds =
{}) = 0;

#ifndef _WIN32
/// Add a Unix domain socket listener.
/**
* @param unixSocketPath The filesystem path for the Unix domain socket.
*
* @note Unix domain sockets provide lower latency than TCP for same-host
* communication, making them ideal for reverse proxy setups (e.g.,
* Nginx -> Drogon). The socket file is automatically cleaned up when the
* server stops.
*
* This is only supported on POSIX systems (Linux, macOS, FreeBSD).
*
* Example usage:
* @code
* app().addListener("/var/run/drogon.sock");
* // Then use: curl --unix-socket /var/run/drogon.sock http://localhost/
* @endcode
*
* @note
* This operation can also be performed via the configuration file:
* @code
* "listeners": [{"unix_socket": "/var/run/drogon.sock"}]
* @endcode
*/
virtual HttpAppFramework &addListener(
const std::string &unixSocketPath) = 0;
#endif

/// Enable sessions supporting.
/**
* @param timeout The number of seconds which is the timeout of a session
Expand Down
10 changes: 10 additions & 0 deletions lib/src/ConfigLoader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,16 @@ static void loadListeners(const Json::Value &listeners)
LOG_TRACE << "Has " << listeners.size() << " listeners";
for (auto const &listener : listeners)
{
#ifndef _WIN32
// Check for Unix domain socket listener
auto unixSocketPath = listener.get("unix_socket", "").asString();
if (!unixSocketPath.empty())
{
LOG_TRACE << "Add Unix domain socket listener: " << unixSocketPath;
drogon::app().addListener(unixSocketPath);
continue;
}
#endif
auto addr = listener.get("address", "0.0.0.0").asString();
auto port = (uint16_t)listener.get("port", 0).asUInt();
auto useSSL = listener.get("https", false).asBool();
Expand Down
10 changes: 10 additions & 0 deletions lib/src/HttpAppFrameworkImpl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,16 @@ HttpAppFramework &HttpAppFrameworkImpl::addListener(
return *this;
}

#ifndef _WIN32
HttpAppFramework &HttpAppFrameworkImpl::addListener(
const std::string &unixSocketPath)
{
assert(!running_);
listenerManagerPtr_->addUnixListener(unixSocketPath);
return *this;
}
#endif

HttpAppFramework &HttpAppFrameworkImpl::setMaxConnectionNum(
size_t maxConnections)
{
Expand Down
3 changes: 3 additions & 0 deletions lib/src/HttpAppFrameworkImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class HttpAppFrameworkImpl final : public HttpAppFramework
bool useOldTLS,
const std::vector<std::pair<std::string, std::string>> &sslConfCmds)
override;
#ifndef _WIN32
HttpAppFramework &addListener(const std::string &unixSocketPath) override;
#endif
HttpAppFramework &setThreadNum(size_t threadNum) override;

size_t getThreadNum() const override
Expand Down
59 changes: 59 additions & 0 deletions lib/src/ListenerManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ void ListenerManager::addListener(
ip, port, useSSL, certFile, keyFile, useOldTLS, sslConfCmds);
}

#ifndef _WIN32
void ListenerManager::addUnixListener(const std::string &socketPath)
{
LOG_TRACE << "Add Unix domain socket listener: " << socketPath;
unixListeners_.emplace_back(socketPath);
}
#endif

std::vector<trantor::InetAddress> ListenerManager::getListeners() const
{
std::vector<trantor::InetAddress> listeners;
Expand Down Expand Up @@ -194,6 +202,48 @@ void ListenerManager::createListeners(
}
}
#endif

#ifndef _WIN32
// Create Unix domain socket listeners
for (auto const &udsListener : unixListeners_)
{
InetAddress listenAddress(udsListener.socketPath_,
trantor::UnixDomainTag{});
trantor::EventLoop *loop;
#ifdef __linux__
// On Linux with SO_REUSEPORT, use the main loop for UDS
loop = HttpAppFrameworkImpl::instance().getLoop();
#else
if (!listeningThread_)
{
listeningThread_ =
std::make_unique<EventLoopThread>("DrogonListeningLoop");
listeningThread_->run();
}
loop = listeningThread_->getLoop();
#endif
auto serverPtr =
std::make_shared<HttpServer>(loop, listenAddress, "drogon-unix");
if (beforeListenSetSockOptCallback_)
{
serverPtr->setBeforeListenSockOptCallback(
beforeListenSetSockOptCallback_);
}
if (afterAcceptSetSockOptCallback_)
{
serverPtr->setAfterAcceptSockOptCallback(
afterAcceptSetSockOptCallback_);
}
if (connectionCallback_)
{
serverPtr->setConnectionCallback(connectionCallback_);
}
serverPtr->setIoLoops(ioLoops);
servers_.push_back(serverPtr);
LOG_INFO << "Unix domain socket listener created: "
<< udsListener.socketPath_;
}
#endif
}

void ListenerManager::startListening()
Expand All @@ -210,6 +260,15 @@ void ListenerManager::stopListening()
{
serverPtr->stop();
}
#ifndef _WIN32
// Clean up Unix domain socket files
for (auto const &udsListener : unixListeners_)
{
::unlink(udsListener.socketPath_.c_str());
LOG_TRACE << "Removed Unix domain socket file: "
<< udsListener.socketPath_;
}
#endif
if (listeningThread_)
{
auto loop = listeningThread_->getLoop();
Expand Down
17 changes: 17 additions & 0 deletions lib/src/ListenerManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class ListenerManager : public trantor::NonCopyable
bool useOldTLS = false,
const std::vector<std::pair<std::string, std::string>>
&sslConfCmds = {});
#ifndef _WIN32
void addUnixListener(const std::string &socketPath);
#endif
std::vector<trantor::InetAddress> getListeners() const;
void createListeners(
const std::string &globalCertFile,
Expand Down Expand Up @@ -102,6 +105,20 @@ class ListenerManager : public trantor::NonCopyable
std::vector<ListenerInfo> listeners_;
std::vector<std::shared_ptr<HttpServer>> servers_;

#ifndef _WIN32
struct UnixListenerInfo
{
explicit UnixListenerInfo(std::string socketPath)
: socketPath_(std::move(socketPath))
{
}

std::string socketPath_;
};

std::vector<UnixListenerInfo> unixListeners_;
#endif

// 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_;
Expand Down
Loading