mirror of https://github.com/aria2/aria2
				
				
				
			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 optionpull/498/head
							parent
							
								
									699f04d0b8
								
							
						
					
					
						commit
						e8a9a366db
					
				|  | @ -1562,6 +1562,14 @@ Advanced Options | ||||||
|   :option:`--save-session` option every SEC seconds. If ``0`` is |   :option:`--save-session` option every SEC seconds. If ``0`` is | ||||||
|   given, file will be saved only when aria2 exits. Default: ``0`` |   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> | .. option:: --stop=<SEC> | ||||||
| 
 | 
 | ||||||
|   Stop application after SEC seconds has passed. |   Stop application after SEC seconds has passed. | ||||||
|  |  | ||||||
|  | @ -223,6 +223,8 @@ Context::Context(bool standalone, | ||||||
|     setDefaultAIFlags(0); |     setDefaultAIFlags(0); | ||||||
|   } |   } | ||||||
|   SocketCore::setIpDscp(op->getAsInt(PREF_DSCP)); |   SocketCore::setIpDscp(op->getAsInt(PREF_DSCP)); | ||||||
|  |   SocketCore::setSocketRecvBufferSize(op->getAsInt | ||||||
|  |                                       (PREF_SOCKET_RECV_BUFFER_SIZE)); | ||||||
|   net::checkAddrconfig(); |   net::checkAddrconfig(); | ||||||
|   // Bind interface
 |   // Bind interface
 | ||||||
|   if(!op->get(PREF_INTERFACE).empty()) { |   if(!op->get(PREF_INTERFACE).empty()) { | ||||||
|  |  | ||||||
|  | @ -811,6 +811,16 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers() | ||||||
|     op->addTag(TAG_ADVANCED); |     op->addTag(TAG_ADVANCED); | ||||||
|     handlers.push_back(op); |     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 |     OptionHandler* op(new NumberOptionHandler | ||||||
|                       (PREF_STOP, |                       (PREF_STOP, | ||||||
|  |  | ||||||
|  | @ -143,6 +143,8 @@ SocketCore::bindAddrsList_; | ||||||
| std::vector<std::vector<std::pair<sockaddr_union, socklen_t> > >::iterator | std::vector<std::vector<std::pair<sockaddr_union, socklen_t> > >::iterator | ||||||
| SocketCore::bindAddrsListIt_; | SocketCore::bindAddrsListIt_; | ||||||
| 
 | 
 | ||||||
|  | int SocketCore::socketRecvBufferSize_ = 0; | ||||||
|  | 
 | ||||||
| #ifdef ENABLE_SSL | #ifdef ENABLE_SSL | ||||||
| std::shared_ptr<TLSContext> SocketCore::clTlsContext_; | std::shared_ptr<TLSContext> SocketCore::clTlsContext_; | ||||||
| std::shared_ptr<TLSContext> SocketCore::svTlsContext_; | std::shared_ptr<TLSContext> SocketCore::svTlsContext_; | ||||||
|  | @ -187,6 +189,23 @@ SocketCore::~SocketCore() { | ||||||
|   closeConnection(); |   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) | void SocketCore::create(int family, int protocol) | ||||||
| { | { | ||||||
|   int errNum; |   int errNum; | ||||||
|  | @ -205,6 +224,9 @@ void SocketCore::create(int family, int protocol) | ||||||
|     throw DL_ABORT_EX |     throw DL_ABORT_EX | ||||||
|       (fmt("Failed to create socket. Cause:%s", errorMsg(errNum).c_str())); |       (fmt("Failed to create socket. Cause:%s", errorMsg(errNum).c_str())); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   applySocketBufferSize(fd); | ||||||
|  | 
 | ||||||
|   sockfd_ = fd; |   sockfd_ = fd; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -240,6 +262,9 @@ static sock_t bindInternal | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| #endif // IPV6_V6ONLY
 | #endif // IPV6_V6ONLY
 | ||||||
|  | 
 | ||||||
|  |   applySocketBufferSize(fd); | ||||||
|  | 
 | ||||||
|   if(::bind(fd, addr, addrlen) == -1) { |   if(::bind(fd, addr, addrlen) == -1) { | ||||||
|     errNum = SOCKET_ERRNO; |     errNum = SOCKET_ERRNO; | ||||||
|     error = errorMsg(errNum); |     error = errorMsg(errNum); | ||||||
|  | @ -364,6 +389,9 @@ std::shared_ptr<SocketCore> SocketCore::acceptConnection() const | ||||||
|   if(fd == (sock_t) -1) { |   if(fd == (sock_t) -1) { | ||||||
|     throw DL_ABORT_EX(fmt(EX_SOCKET_ACCEPT, errorMsg(errNum).c_str())); |     throw DL_ABORT_EX(fmt(EX_SOCKET_ACCEPT, errorMsg(errNum).c_str())); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   applySocketBufferSize(fd); | ||||||
|  | 
 | ||||||
|   auto sock = std::make_shared<SocketCore>(fd, sockType_); |   auto sock = std::make_shared<SocketCore>(fd, sockType_); | ||||||
|   sock->setNonBlockingMode(); |   sock->setNonBlockingMode(); | ||||||
|   return sock; |   return sock; | ||||||
|  | @ -437,6 +465,9 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port, | ||||||
|       CLOSE(fd); |       CLOSE(fd); | ||||||
|       continue; |       continue; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     applySocketBufferSize(fd); | ||||||
|  | 
 | ||||||
|     if(!bindAddrs_.empty()) { |     if(!bindAddrs_.empty()) { | ||||||
|       bool bindSuccess = false; |       bool bindSuccess = false; | ||||||
|       for(std::vector<std::pair<sockaddr_union, socklen_t> >:: |       for(std::vector<std::pair<sockaddr_union, socklen_t> >:: | ||||||
|  | @ -1284,6 +1315,16 @@ void SocketCore::bindAllAddress(const std::string& ifaces) | ||||||
|   bindAddrs_ = *bindAddrsListIt_; |   bindAddrs_ = *bindAddrsListIt_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void SocketCore::setSocketRecvBufferSize(int size) | ||||||
|  | { | ||||||
|  |   socketRecvBufferSize_ = size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int SocketCore::getSocketRecvBufferSize() | ||||||
|  | { | ||||||
|  |   return socketRecvBufferSize_; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void getInterfaceAddress | void getInterfaceAddress | ||||||
| (std::vector<std::pair<sockaddr_union, socklen_t> >& ifAddrs, | (std::vector<std::pair<sockaddr_union, socklen_t> >& ifAddrs, | ||||||
|  const std::string& iface, int family, int aiFlags) |  const std::string& iface, int family, int aiFlags) | ||||||
|  |  | ||||||
|  | @ -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> > > bindAddrsList_; | ||||||
|   static std::vector<std::vector<std::pair<sockaddr_union, socklen_t> > >::iterator bindAddrsListIt_; |   static std::vector<std::vector<std::pair<sockaddr_union, socklen_t> > >::iterator bindAddrsListIt_; | ||||||
| 
 | 
 | ||||||
|  |   static int socketRecvBufferSize_; | ||||||
|  | 
 | ||||||
|   bool blocking_; |   bool blocking_; | ||||||
|   int secure_; |   int secure_; | ||||||
| 
 | 
 | ||||||
|  | @ -359,6 +361,9 @@ public: | ||||||
|     protocolFamily_ = protocolFamily; |     protocolFamily_ = protocolFamily; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   static void setSocketRecvBufferSize(int size); | ||||||
|  |   static int getSocketRecvBufferSize(); | ||||||
|  | 
 | ||||||
|   // Bind socket to interface. interface may be specified as a
 |   // Bind socket to interface. interface may be specified as a
 | ||||||
|   // hostname, IP address or interface name like eth0.  If the given
 |   // hostname, IP address or interface name like eth0.  If the given
 | ||||||
|   // interface is not found or binding socket is failed, exception
 |   // interface is not found or binding socket is failed, exception
 | ||||||
|  |  | ||||||
|  | @ -375,6 +375,8 @@ PrefPtr PREF_PAUSE_METADATA = makePref("pause-metadata"); | ||||||
| PrefPtr PREF_RLIMIT_NOFILE = makePref("rlimit-nofile"); | PrefPtr PREF_RLIMIT_NOFILE = makePref("rlimit-nofile"); | ||||||
| // values: SSLv3 | TLSv1 | TLSv1.1 | TLSv1.2
 | // values: SSLv3 | TLSv1 | TLSv1.1 | TLSv1.2
 | ||||||
| PrefPtr PREF_MIN_TLS_VERSION = makePref("min-tls-version"); | 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 |  * FTP related preferences | ||||||
|  |  | ||||||
|  | @ -312,6 +312,8 @@ extern PrefPtr PREF_PAUSE_METADATA; | ||||||
| extern PrefPtr PREF_RLIMIT_NOFILE; | extern PrefPtr PREF_RLIMIT_NOFILE; | ||||||
| // values: SSLv3 | TLSv1 | TLSv1.1 | TLSv1.2
 | // values: SSLv3 | TLSv1 | TLSv1.1 | TLSv1.2
 | ||||||
| extern PrefPtr PREF_MIN_TLS_VERSION; | extern PrefPtr PREF_MIN_TLS_VERSION; | ||||||
|  | // value: 1*digit
 | ||||||
|  | extern PrefPtr PREF_SOCKET_RECV_BUFFER_SIZE; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * FTP related preferences |  * FTP related preferences | ||||||
|  |  | ||||||
|  | @ -1040,3 +1040,9 @@ | ||||||
|     "                              public key when SFTP is used. If this option is\n" \ |     "                              public key when SFTP is used. If this option is\n" \ | ||||||
|     "                              not set, which is default, no validation takes\n" \ |     "                              not set, which is default, no validation takes\n" \ | ||||||
|     "                              place.") |     "                              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.") | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Tatsuhiro Tsujikawa
						Tatsuhiro Tsujikawa