diff --git a/.gitmodules b/.gitmodules index c438e0030b..b6b2064fc1 100755 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/lib/inc/drogon/HttpAppFramework.h b/lib/inc/drogon/HttpAppFramework.h index 4ddd32301f..af5d340c19 100644 --- a/lib/inc/drogon/HttpAppFramework.h +++ b/lib/inc/drogon/HttpAppFramework.h @@ -871,6 +871,34 @@ class DROGON_EXPORT HttpAppFramework : public trantor::NonCopyable const std::vector> &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 diff --git a/lib/src/ConfigLoader.cc b/lib/src/ConfigLoader.cc index 3940811b6b..4fdc10eadf 100644 --- a/lib/src/ConfigLoader.cc +++ b/lib/src/ConfigLoader.cc @@ -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(); diff --git a/lib/src/HttpAppFrameworkImpl.cc b/lib/src/HttpAppFrameworkImpl.cc index 988e037f57..7d3374470f 100644 --- a/lib/src/HttpAppFrameworkImpl.cc +++ b/lib/src/HttpAppFrameworkImpl.cc @@ -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) { diff --git a/lib/src/HttpAppFrameworkImpl.h b/lib/src/HttpAppFrameworkImpl.h index 498482a5ff..7929d10d2e 100644 --- a/lib/src/HttpAppFrameworkImpl.h +++ b/lib/src/HttpAppFrameworkImpl.h @@ -72,6 +72,9 @@ class HttpAppFrameworkImpl final : public HttpAppFramework bool useOldTLS, const std::vector> &sslConfCmds) override; +#ifndef _WIN32 + HttpAppFramework &addListener(const std::string &unixSocketPath) override; +#endif HttpAppFramework &setThreadNum(size_t threadNum) override; size_t getThreadNum() const override diff --git a/lib/src/ListenerManager.cc b/lib/src/ListenerManager.cc index 5b7483280b..7566a9c4ca 100644 --- a/lib/src/ListenerManager.cc +++ b/lib/src/ListenerManager.cc @@ -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 ListenerManager::getListeners() const { std::vector listeners; @@ -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("DrogonListeningLoop"); + listeningThread_->run(); + } + loop = listeningThread_->getLoop(); +#endif + auto serverPtr = + std::make_shared(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() @@ -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(); diff --git a/lib/src/ListenerManager.h b/lib/src/ListenerManager.h index 6cbabe145b..37b12e868d 100644 --- a/lib/src/ListenerManager.h +++ b/lib/src/ListenerManager.h @@ -42,6 +42,9 @@ class ListenerManager : public trantor::NonCopyable bool useOldTLS = false, const std::vector> &sslConfCmds = {}); +#ifndef _WIN32 + void addUnixListener(const std::string &socketPath); +#endif std::vector getListeners() const; void createListeners( const std::string &globalCertFile, @@ -102,6 +105,20 @@ class ListenerManager : public trantor::NonCopyable std::vector listeners_; std::vector> servers_; +#ifndef _WIN32 + struct UnixListenerInfo + { + explicit UnixListenerInfo(std::string socketPath) + : socketPath_(std::move(socketPath)) + { + } + + std::string socketPath_; + }; + + std::vector unixListeners_; +#endif + // should have value when and only when on OS that one port can only be // listened by one thread std::unique_ptr listeningThread_; diff --git a/trantor b/trantor index 5000e2a726..8f50700976 160000 --- a/trantor +++ b/trantor @@ -1 +1 @@ -Subproject commit 5000e2a72687232c8675b28ce86a29ed7d44309e +Subproject commit 8f50700976f6661f84aeabae75f917087d698d6e