summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2015-11-28 14:01:24 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2015-11-28 14:12:23 +0900
commite8a9a366db7bf834a3e93c6ec05336e5aca882c4 (patch)
tree01a422d15502dac3a117a80df17781b482773015 /src
parent699f04d0b8a93dd92a85f68cd8c307b5f3fb4741 (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
Diffstat (limited to 'src')
-rw-r--r--src/Context.cc2
-rw-r--r--src/OptionHandlerFactory.cc10
-rw-r--r--src/SocketCore.cc41
-rw-r--r--src/SocketCore.h5
-rw-r--r--src/prefs.cc2
-rw-r--r--src/prefs.h2
-rw-r--r--src/usage_text.h6
7 files changed, 68 insertions, 0 deletions
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.")