mirror of https://github.com/aria2/aria2
Add feature: Inherit RPC socket from systemd.
Allow using systemd socket activation for aria2c RPC socket. Require libsystemd to be available at build time.pull/1910/head
parent
21f476588c
commit
a548ea930c
18
configure.ac
18
configure.ac
|
@ -67,6 +67,7 @@ ARIA2_ARG_WITHOUT([libz])
|
||||||
ARIA2_ARG_WITH([tcmalloc])
|
ARIA2_ARG_WITH([tcmalloc])
|
||||||
ARIA2_ARG_WITH([jemalloc])
|
ARIA2_ARG_WITH([jemalloc])
|
||||||
ARIA2_ARG_WITHOUT([libssh2])
|
ARIA2_ARG_WITHOUT([libssh2])
|
||||||
|
ARIA2_ARG_WITHOUT([systemd])
|
||||||
|
|
||||||
ARIA2_ARG_DISABLE([ssl])
|
ARIA2_ARG_DISABLE([ssl])
|
||||||
ARIA2_ARG_DISABLE([bittorrent])
|
ARIA2_ARG_DISABLE([bittorrent])
|
||||||
|
@ -494,6 +495,19 @@ if test "x$with_libssh2" = "xyes"; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
have_systemd=no
|
||||||
|
if test "x$with_systemd" = "xyes"; then
|
||||||
|
PKG_CHECK_MODULES([SYSTEMD], [libsystemd], [have_systemd=yes], [have_systemd=no])
|
||||||
|
if test "x$have_systemd" = "xyes"; then
|
||||||
|
AC_DEFINE([HAVE_SYSTEMD], [1], [Define to 1 if you have systemd.])
|
||||||
|
else
|
||||||
|
AC_MSG_WARN([$SYSTEMD_PKG_ERRORS])
|
||||||
|
if test "x$with_systemd_requested" = "xyes"; then
|
||||||
|
ARIA2_DEP_NOT_MET([systemd])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
have_libcares=no
|
have_libcares=no
|
||||||
if test "x$with_libcares" = "xyes"; then
|
if test "x$with_libcares" = "xyes"; then
|
||||||
PKG_CHECK_MODULES([LIBCARES], [libcares >= 1.7.0], [have_libcares=yes],
|
PKG_CHECK_MODULES([LIBCARES], [libcares >= 1.7.0], [have_libcares=yes],
|
||||||
|
@ -645,6 +659,9 @@ AM_CONDITIONAL([HAVE_SQLITE3], [test "x$have_sqlite3" = "xyes"])
|
||||||
# Set conditional for libssh2
|
# Set conditional for libssh2
|
||||||
AM_CONDITIONAL([HAVE_LIBSSH2], [test "x$have_libssh2" = "xyes"])
|
AM_CONDITIONAL([HAVE_LIBSSH2], [test "x$have_libssh2" = "xyes"])
|
||||||
|
|
||||||
|
# Set conditional for systemd
|
||||||
|
AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$have_systemd" = "xyes"])
|
||||||
|
|
||||||
case "$host" in
|
case "$host" in
|
||||||
*solaris*)
|
*solaris*)
|
||||||
save_LIBS=$LIBS
|
save_LIBS=$LIBS
|
||||||
|
@ -1112,6 +1129,7 @@ LibExpat: $have_libexpat (CFLAGS='$EXPAT_CFLAGS' LIBS='$EXPAT_LIBS')
|
||||||
LibCares: $have_libcares (CFLAGS='$LIBCARES_CFLAGS' LIBS='$LIBCARES_LIBS')
|
LibCares: $have_libcares (CFLAGS='$LIBCARES_CFLAGS' LIBS='$LIBCARES_LIBS')
|
||||||
Zlib: $have_zlib (CFLAGS='$ZLIB_CFLAGS' LIBS='$ZLIB_LIBS')
|
Zlib: $have_zlib (CFLAGS='$ZLIB_CFLAGS' LIBS='$ZLIB_LIBS')
|
||||||
Libssh2: $have_libssh2 (CFLAGS='$LIBSSH2_CFLAGS' LIBS='$LIBSSH2_LIBS')
|
Libssh2: $have_libssh2 (CFLAGS='$LIBSSH2_CFLAGS' LIBS='$LIBSSH2_LIBS')
|
||||||
|
Systemd: $have_systemd (CFLAGS='$SYSTEMD_CFLAGS' LIBS='$SYSTEMD_LIBS')
|
||||||
Tcmalloc: $have_tcmalloc (CFLAGS='$TCMALLOC_CFLAGS' LIBS='$TCMALLOC_LIBS')
|
Tcmalloc: $have_tcmalloc (CFLAGS='$TCMALLOC_CFLAGS' LIBS='$TCMALLOC_LIBS')
|
||||||
Jemalloc: $have_jemalloc (CFLAGS='$JEMALLOC_CFLAGS' LIBS='$JEMALLOC_LIBS')
|
Jemalloc: $have_jemalloc (CFLAGS='$JEMALLOC_CFLAGS' LIBS='$JEMALLOC_LIBS')
|
||||||
Epoll: $have_epoll
|
Epoll: $have_epoll
|
||||||
|
|
|
@ -35,6 +35,9 @@
|
||||||
#include "DownloadEngineFactory.h"
|
#include "DownloadEngineFactory.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#ifdef HAVE_SYSTEMD
|
||||||
|
#include <systemd/sd-daemon.h>
|
||||||
|
#endif // HAVE_SYSTEMD
|
||||||
|
|
||||||
#include "Option.h"
|
#include "Option.h"
|
||||||
#include "RequestGroup.h"
|
#include "RequestGroup.h"
|
||||||
|
@ -205,16 +208,33 @@ std::unique_ptr<DownloadEngine> DownloadEngineFactory::newDownloadEngine(
|
||||||
if (secure) {
|
if (secure) {
|
||||||
A2_LOG_NOTICE("RPC transport will be encrypted.");
|
A2_LOG_NOTICE("RPC transport will be encrypted.");
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_SYSTEMD
|
||||||
|
int fds = sd_listen_fds(1);
|
||||||
|
if (0 < fds) {
|
||||||
|
for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + fds; fd++) {
|
||||||
|
auto httpListenCommand = make_unique<HttpListenCommand>(
|
||||||
|
e->newCUID(), e.get(), fd, secure);
|
||||||
|
if (httpListenCommand->listen()) {
|
||||||
|
e->addCommand(std::move(httpListenCommand));
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#endif // HAVE_SYSTEMD
|
||||||
|
{
|
||||||
static int families[] = {AF_INET, AF_INET6};
|
static int families[] = {AF_INET, AF_INET6};
|
||||||
size_t familiesLength = op->getAsBool(PREF_DISABLE_IPV6) ? 1 : 2;
|
size_t familiesLength = op->getAsBool(PREF_DISABLE_IPV6) ? 1 : 2;
|
||||||
for (size_t i = 0; i < familiesLength; ++i) {
|
for (size_t i = 0; i < familiesLength; ++i) {
|
||||||
auto httpListenCommand = make_unique<HttpListenCommand>(
|
auto httpListenCommand = make_unique<HttpListenCommand>(
|
||||||
e->newCUID(), e.get(), families[i], secure);
|
e->newCUID(), e.get(), families[i],
|
||||||
if (httpListenCommand->bindPort(op->getAsInt(PREF_RPC_LISTEN_PORT))) {
|
op->getAsInt(PREF_RPC_LISTEN_PORT),
|
||||||
|
secure);
|
||||||
|
if (httpListenCommand->listen()) {
|
||||||
e->addCommand(std::move(httpListenCommand));
|
e->addCommand(std::move(httpListenCommand));
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
throw DL_ABORT_EX("Failed to setup RPC server.");
|
throw DL_ABORT_EX("Failed to setup RPC server.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,14 @@
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
HttpListenCommand::HttpListenCommand(cuid_t cuid, DownloadEngine* e, int family,
|
HttpListenCommand::HttpListenCommand(cuid_t cuid, DownloadEngine* e, int family,
|
||||||
|
uint16_t port, bool secure)
|
||||||
|
: Command(cuid), e_(e), fd_(-1), family_(family), port_(port), secure_(secure)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpListenCommand::HttpListenCommand(cuid_t cuid, DownloadEngine* e, int fd,
|
||||||
bool secure)
|
bool secure)
|
||||||
: Command(cuid), e_(e), family_(family), secure_(secure)
|
: Command(cuid), e_(e), fd_(fd), family_(AF_INET), port_(0), secure_(secure)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,27 +95,34 @@ bool HttpListenCommand::execute()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HttpListenCommand::bindPort(uint16_t port)
|
bool HttpListenCommand::listen()
|
||||||
{
|
{
|
||||||
if (serverSocket_) {
|
if (serverSocket_) {
|
||||||
e_->deleteSocketForReadCheck(serverSocket_, this);
|
e_->deleteSocketForReadCheck(serverSocket_, this);
|
||||||
}
|
}
|
||||||
serverSocket_ = std::make_shared<SocketCore>();
|
serverSocket_ = std::make_shared<SocketCore>();
|
||||||
const int ipv = (family_ == AF_INET) ? 4 : 6;
|
std::string sListen;
|
||||||
try {
|
try {
|
||||||
|
if (fd_ < 0) {
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
const int ipv = (family_ == AF_INET) ? 4 : 6;
|
||||||
|
sListen = fmt("TCP/IPv%d port %u", ipv, port_);
|
||||||
if (e_->getOption()->getAsBool(PREF_RPC_LISTEN_ALL)) {
|
if (e_->getOption()->getAsBool(PREF_RPC_LISTEN_ALL)) {
|
||||||
flags = AI_PASSIVE;
|
flags = AI_PASSIVE;
|
||||||
}
|
}
|
||||||
serverSocket_->bind(nullptr, port, family_, flags);
|
serverSocket_->bind(nullptr, port_, family_, flags);
|
||||||
|
} else {
|
||||||
|
sListen = fmt("file descriptor fd=%d", fd_);
|
||||||
|
serverSocket_->bindExistingFd(fd_);
|
||||||
|
}
|
||||||
serverSocket_->beginListen();
|
serverSocket_->beginListen();
|
||||||
A2_LOG_INFO(fmt(MSG_LISTENING_PORT, getCuid(), port));
|
A2_LOG_INFO(fmt(MSG_LISTENING_RPC, getCuid(), sListen.c_str()));
|
||||||
e_->addSocketForReadCheck(serverSocket_, this);
|
e_->addSocketForReadCheck(serverSocket_, this);
|
||||||
A2_LOG_NOTICE(fmt(_("IPv%d RPC: listening on TCP port %u"), ipv, port));
|
A2_LOG_NOTICE(fmt(_("RPC: listening on %s"), sListen.c_str()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (RecoverableException& e) {
|
catch (RecoverableException& e) {
|
||||||
A2_LOG_ERROR_EX(fmt("IPv%d RPC: failed to bind TCP port %u", ipv, port), e);
|
A2_LOG_ERROR_EX(fmt("RPC: failed to listen on %s", sListen.c_str()), e);
|
||||||
serverSocket_->closeConnection();
|
serverSocket_->closeConnection();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -47,18 +47,22 @@ class SocketCore;
|
||||||
class HttpListenCommand : public Command {
|
class HttpListenCommand : public Command {
|
||||||
private:
|
private:
|
||||||
DownloadEngine* e_;
|
DownloadEngine* e_;
|
||||||
|
int fd_;
|
||||||
int family_;
|
int family_;
|
||||||
|
uint16_t port_;
|
||||||
std::shared_ptr<SocketCore> serverSocket_;
|
std::shared_ptr<SocketCore> serverSocket_;
|
||||||
bool secure_;
|
bool secure_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HttpListenCommand(cuid_t cuid, DownloadEngine* e, int family, bool secure);
|
HttpListenCommand(cuid_t cuid, DownloadEngine* e, int family, uint16_t port, bool secure);
|
||||||
|
|
||||||
|
HttpListenCommand(cuid_t cuid, DownloadEngine* e, int fd, bool secure);
|
||||||
|
|
||||||
virtual ~HttpListenCommand();
|
virtual ~HttpListenCommand();
|
||||||
|
|
||||||
virtual bool execute() CXX11_OVERRIDE;
|
virtual bool execute() CXX11_OVERRIDE;
|
||||||
|
|
||||||
bool bindPort(uint16_t port);
|
bool listen();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -712,6 +712,7 @@ AM_CPPFLAGS = \
|
||||||
@LIBGMP_CFLAGS@ \
|
@LIBGMP_CFLAGS@ \
|
||||||
@LIBGCRYPT_CFLAGS@ \
|
@LIBGCRYPT_CFLAGS@ \
|
||||||
@LIBSSH2_CFLAGS@ \
|
@LIBSSH2_CFLAGS@ \
|
||||||
|
@SYSTEMD_CFLAGS@ \
|
||||||
@LIBCARES_CFLAGS@ \
|
@LIBCARES_CFLAGS@ \
|
||||||
@WSLAY_CFLAGS@ \
|
@WSLAY_CFLAGS@ \
|
||||||
@TCMALLOC_CFLAGS@ \
|
@TCMALLOC_CFLAGS@ \
|
||||||
|
@ -735,6 +736,7 @@ EXTLDADD = @ALLOCA@ \
|
||||||
@LIBGMP_LIBS@ \
|
@LIBGMP_LIBS@ \
|
||||||
@LIBGCRYPT_LIBS@ \
|
@LIBGCRYPT_LIBS@ \
|
||||||
@LIBSSH2_LIBS@ \
|
@LIBSSH2_LIBS@ \
|
||||||
|
@SYSTEMD_LIBS@ \
|
||||||
@LIBCARES_LIBS@ \
|
@LIBCARES_LIBS@ \
|
||||||
@WSLAY_LIBS@ \
|
@WSLAY_LIBS@ \
|
||||||
@TCMALLOC_LIBS@ \
|
@TCMALLOC_LIBS@ \
|
||||||
|
|
|
@ -360,6 +360,18 @@ void SocketCore::bind(const struct sockaddr* addr, socklen_t addrlen)
|
||||||
sockfd_ = fd;
|
sockfd_ = fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SocketCore::bindExistingFd(int fd)
|
||||||
|
{
|
||||||
|
std::string error;
|
||||||
|
if (fd < 0) {
|
||||||
|
error = fmt("Invalid file descriptor fd=%d", fd);
|
||||||
|
throw DL_ABORT_EX(fmt(EX_SOCKET_BIND, error.c_str()));
|
||||||
|
}
|
||||||
|
util::make_fd_cloexec(fd);
|
||||||
|
applySocketBufferSize(fd);
|
||||||
|
sockfd_ = fd;
|
||||||
|
}
|
||||||
|
|
||||||
void SocketCore::beginListen()
|
void SocketCore::beginListen()
|
||||||
{
|
{
|
||||||
if (listen(sockfd_, 1024) == -1) {
|
if (listen(sockfd_, 1024) == -1) {
|
||||||
|
|
|
@ -162,6 +162,11 @@ public:
|
||||||
void bind(const char* addrp, uint16_t port, int family,
|
void bind(const char* addrp, uint16_t port, int family,
|
||||||
int flags = AI_PASSIVE);
|
int flags = AI_PASSIVE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind to an existing file descriptor.
|
||||||
|
*/
|
||||||
|
void bindExistingFd(int fd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listens form connection on it.
|
* Listens form connection on it.
|
||||||
* Call bind(uint16_t) before calling this function.
|
* Call bind(uint16_t) before calling this function.
|
||||||
|
|
|
@ -93,8 +93,8 @@
|
||||||
#define MSG_CONTENT_DISPOSITION_DETECTED \
|
#define MSG_CONTENT_DISPOSITION_DETECTED \
|
||||||
"CUID#%" PRId64 " - Content-Disposition detected. Use %s as filename"
|
"CUID#%" PRId64 " - Content-Disposition detected. Use %s as filename"
|
||||||
#define MSG_PEER_BANNED "CUID#%" PRId64 " - Peer %s:%d banned."
|
#define MSG_PEER_BANNED "CUID#%" PRId64 " - Peer %s:%d banned."
|
||||||
#define MSG_LISTENING_PORT \
|
#define MSG_LISTENING_RPC \
|
||||||
"CUID#%" PRId64 " - Using port %d for accepting new connections"
|
"CUID#%" PRId64 " - Using %s for accepting new connections"
|
||||||
#define MSG_BIND_FAILURE "CUID#%" PRId64 " - An error occurred while binding port=%d"
|
#define MSG_BIND_FAILURE "CUID#%" PRId64 " - An error occurred while binding port=%d"
|
||||||
#define MSG_INCOMING_PEER_CONNECTION \
|
#define MSG_INCOMING_PEER_CONNECTION \
|
||||||
"CUID#%" PRId64 " - Incoming connection, adding new command CUID#%" PRId64 ""
|
"CUID#%" PRId64 " - Incoming connection, adding new command CUID#%" PRId64 ""
|
||||||
|
|
Loading…
Reference in New Issue