diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2015-11-28 14:01:24 +0900 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2015-11-28 14:12:23 +0900 |
| commit | e8a9a366db7bf834a3e93c6ec05336e5aca882c4 (patch) | |
| tree | 01a422d15502dac3a117a80df17781b482773015 | |
| parent | 699f04d0b8a93dd92a85f68cd8c307b5f3fb4741 (diff) | |
Add --socket-recv-buffer-size option
Set the maximum socket receive buffer in bytes. Specifing 0 will
disable this option. This value will be set to socket file descriptor
using SO_RCVBUF socket option with setsockopt() call.
See GH-487 about the usecase of this option
| -rw-r--r-- | doc/manual-src/en/aria2c.rst | 8 | ||||
| -rw-r--r-- | src/Context.cc | 2 | ||||
| -rw-r--r-- | src/OptionHandlerFactory.cc | 10 | ||||
| -rw-r--r-- | src/SocketCore.cc | 41 | ||||
| -rw-r--r-- | src/SocketCore.h | 5 | ||||
| -rw-r--r-- | src/prefs.cc | 2 | ||||
| -rw-r--r-- | src/prefs.h | 2 | ||||
| -rw-r--r-- | src/usage_text.h | 6 |
8 files changed, 76 insertions, 0 deletions
diff --git a/doc/manual-src/en/aria2c.rst b/doc/manual-src/en/aria2c.rst index 8a2657a3..d42ecdac 100644 --- a/doc/manual-src/en/aria2c.rst +++ b/doc/manual-src/en/aria2c.rst @@ -1562,6 +1562,14 @@ Advanced Options :option:`--save-session` option every SEC seconds. If ``0`` is given, file will be saved only when aria2 exits. Default: ``0`` + +.. option:: --socket-recv-buffer-size=<SIZE> + + Set the maximum socket receive buffer in bytes. Specifing ``0`` + will disable this option. This value will be set to socket file + descriptor using ``SO_RCVBUF`` socket option with ``setsockopt()`` + call. Default: ``0`` + .. option:: --stop=<SEC> Stop application after SEC seconds has passed. diff --git a/src/Context.cc b/src/Context.cc index 70bbb4e5..1f6d8d10 100644 --- a/src/Context.cc +++ b/src/Context.cc @@ -223,6 +223,8 @@ Context::Context(bool standalone, setDefaultAIFlags(0); } SocketCore::setIpDscp(op->getAsInt(PREF_DSCP)); + SocketCore::setSocketRecvBufferSize(op->getAsInt + (PREF_SOCKET_RECV_BUFFER_SIZE)); net::checkAddrconfig(); // Bind interface if(!op->get(PREF_INTERFACE).empty()) { diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 85642c4b..3967d3c7 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -812,6 +812,16 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers() handlers.push_back(op); } { + OptionHandler* op(new UnitNumberOptionHandler + (PREF_SOCKET_RECV_BUFFER_SIZE, + TEXT_SOCKET_RECV_BUFFER_SIZE, + "0", + 0, + 16_m)); + op->addTag(TAG_ADVANCED); + handlers.push_back(op); + } + { OptionHandler* op(new NumberOptionHandler (PREF_STOP, TEXT_STOP, diff --git a/src/SocketCore.cc b/src/SocketCore.cc index 3b8cb4a5..96727837 100644 --- a/src/SocketCore.cc +++ b/src/SocketCore.cc @@ -143,6 +143,8 @@ SocketCore::bindAddrsList_; std::vector<std::vector<std::pair<sockaddr_union, socklen_t> > >::iterator SocketCore::bindAddrsListIt_; +int SocketCore::socketRecvBufferSize_ = 0; + #ifdef ENABLE_SSL std::shared_ptr<TLSContext> SocketCore::clTlsContext_; std::shared_ptr<TLSContext> SocketCore::svTlsContext_; @@ -187,6 +189,23 @@ SocketCore::~SocketCore() { closeConnection(); } +namespace { +void applySocketBufferSize(sock_t fd) +{ + auto recvBufSize = SocketCore::getSocketRecvBufferSize(); + if (recvBufSize == 0) { + return; + } + + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (a2_sockopt_t)&recvBufSize, + sizeof(recvBufSize)) < 0) { + auto errNum = SOCKET_ERRNO; + A2_LOG_WARN(fmt("Failed to set socket buffer size. Cause: %s", + errorMsg(errNum).c_str())); + } +} +} // namespace + void SocketCore::create(int family, int protocol) { int errNum; @@ -205,6 +224,9 @@ void SocketCore::create(int family, int protocol) throw DL_ABORT_EX (fmt("Failed to create socket. Cause:%s", errorMsg(errNum).c_str())); } + + applySocketBufferSize(fd); + sockfd_ = fd; } @@ -240,6 +262,9 @@ static sock_t bindInternal } } #endif // IPV6_V6ONLY + + applySocketBufferSize(fd); + if(::bind(fd, addr, addrlen) == -1) { errNum = SOCKET_ERRNO; error = errorMsg(errNum); @@ -364,6 +389,9 @@ std::shared_ptr<SocketCore> SocketCore::acceptConnection() const if(fd == (sock_t) -1) { throw DL_ABORT_EX(fmt(EX_SOCKET_ACCEPT, errorMsg(errNum).c_str())); } + + applySocketBufferSize(fd); + auto sock = std::make_shared<SocketCore>(fd, sockType_); sock->setNonBlockingMode(); return sock; @@ -437,6 +465,9 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port, CLOSE(fd); continue; } + + applySocketBufferSize(fd); + if(!bindAddrs_.empty()) { bool bindSuccess = false; for(std::vector<std::pair<sockaddr_union, socklen_t> >:: @@ -1284,6 +1315,16 @@ void SocketCore::bindAllAddress(const std::string& ifaces) bindAddrs_ = *bindAddrsListIt_; } +void SocketCore::setSocketRecvBufferSize(int size) +{ + socketRecvBufferSize_ = size; +} + +int SocketCore::getSocketRecvBufferSize() +{ + return socketRecvBufferSize_; +} + void getInterfaceAddress (std::vector<std::pair<sockaddr_union, socklen_t> >& ifAddrs, const std::string& iface, int family, int aiFlags) diff --git a/src/SocketCore.h b/src/SocketCore.h index de8e6cd2..9b346666 100644 --- a/src/SocketCore.h +++ b/src/SocketCore.h @@ -76,6 +76,8 @@ private: static std::vector<std::vector<std::pair<sockaddr_union, socklen_t> > > bindAddrsList_; static std::vector<std::vector<std::pair<sockaddr_union, socklen_t> > >::iterator bindAddrsListIt_; + static int socketRecvBufferSize_; + bool blocking_; int secure_; @@ -359,6 +361,9 @@ public: protocolFamily_ = protocolFamily; } + static void setSocketRecvBufferSize(int size); + static int getSocketRecvBufferSize(); + // Bind socket to interface. interface may be specified as a // hostname, IP address or interface name like eth0. If the given // interface is not found or binding socket is failed, exception diff --git a/src/prefs.cc b/src/prefs.cc index a3046b54..7da29859 100644 --- a/src/prefs.cc +++ b/src/prefs.cc @@ -375,6 +375,8 @@ PrefPtr PREF_PAUSE_METADATA = makePref("pause-metadata"); PrefPtr PREF_RLIMIT_NOFILE = makePref("rlimit-nofile"); // values: SSLv3 | TLSv1 | TLSv1.1 | TLSv1.2 PrefPtr PREF_MIN_TLS_VERSION = makePref("min-tls-version"); +// value: 1*digit +PrefPtr PREF_SOCKET_RECV_BUFFER_SIZE = makePref("socket-recv-buffer-size"); /** * FTP related preferences diff --git a/src/prefs.h b/src/prefs.h index 66eda2fb..615f8449 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -312,6 +312,8 @@ extern PrefPtr PREF_PAUSE_METADATA; extern PrefPtr PREF_RLIMIT_NOFILE; // values: SSLv3 | TLSv1 | TLSv1.1 | TLSv1.2 extern PrefPtr PREF_MIN_TLS_VERSION; +// value: 1*digit +extern PrefPtr PREF_SOCKET_RECV_BUFFER_SIZE; /** * FTP related preferences diff --git a/src/usage_text.h b/src/usage_text.h index d595c233..9a4b93c3 100644 --- a/src/usage_text.h +++ b/src/usage_text.h @@ -1040,3 +1040,9 @@ " public key when SFTP is used. If this option is\n" \ " not set, which is default, no validation takes\n" \ " place.") +#define TEXT_SOCKET_RECV_BUFFER_SIZE \ + _(" --socket-recv-buffer-size=SIZE\n" \ + " Set the maximum socket receive buffer in bytes.\n" \ + " Specifing 0 will disable this option. This value\n" \ + " will be set to socket file descriptor using\n" \ + " SO_RCVBUF socket option with setsockopt() call.") |
