Bläddra i källkod

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
Tatsuhiro Tsujikawa 10 år sedan
förälder
incheckning
e8a9a366db
8 ändrade filer med 76 tillägg och 0 borttagningar
  1. 8 0
      doc/manual-src/en/aria2c.rst
  2. 2 0
      src/Context.cc
  3. 10 0
      src/OptionHandlerFactory.cc
  4. 41 0
      src/SocketCore.cc
  5. 5 0
      src/SocketCore.h
  6. 2 0
      src/prefs.cc
  7. 2 0
      src/prefs.h
  8. 6 0
      src/usage_text.h

+ 8 - 0
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.

+ 2 - 0
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()) {

+ 10 - 0
src/OptionHandlerFactory.cc

@@ -811,6 +811,16 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_ADVANCED);
     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,

+ 41 - 0
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)

+ 5 - 0
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

+ 2 - 0
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

+ 2 - 0
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

+ 6 - 0
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.")