Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add support for TcpNice on OSX, remove on Windows
I'm not convinced that it does anything on Windows without an RTT estimate,
which we can't get without administrator access:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb485738(v=vs.85).aspx

(cherry picked from commit b646d22)
  • Loading branch information
qris committed Nov 10, 2017
1 parent bf12447 commit fb3fa2a
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 10 deletions.
6 changes: 4 additions & 2 deletions infrastructure/cmake/CMakeLists.txt
Expand Up @@ -509,13 +509,15 @@ foreach(m4_filename boxbackup_tests.m4 ax_check_mount_point.m4 ax_func_syscall.m
foreach(function_name ${function_names})
list(APPEND detect_functions ${function_name})
endforeach()
elseif(m4_function MATCHES "^ *AC_CHECK_DECLS\\(\\[([A-Za-z._/ ]+)\\](,,, ..#include <([^>]+)>..)?\\)$")
elseif(m4_function MATCHES "^ *AC_CHECK_DECLS\\(\\[([A-Za-z._/ ,]+)\\](,,, ..#include <([^>]+)>..)?\\)$")
if(DEBUG)
message(STATUS "Processing ac_check_decls: ${CMAKE_MATCH_1} in ${CMAKE_MATCH_3}")
endif()

# Multiple declarations to check are comma-separated, which is unusual.
# http://stackoverflow.com/questions/5272781/what-is-common-way-to-split-string-into-list-with-cmake
string(REPLACE " " ";" decl_names "${CMAKE_MATCH_1}")
string(REPLACE "," ";" decl_names "${CMAKE_MATCH_1}")
string(REPLACE " " "" decl_names "${decl_names}")
string(REPLACE " " ";" header_files "${CMAKE_MATCH_3}")

foreach(decl_name ${decl_names})
Expand Down
4 changes: 2 additions & 2 deletions infrastructure/m4/boxbackup_tests.m4
Expand Up @@ -248,8 +248,8 @@ AC_CHECK_DECLS([O_BINARY],,, [[#include <fcntl.h>]])
AC_CHECK_DECLS([ENOTSUP],,, [[#include <sys/errno.h>]])
AC_CHECK_DECLS([INFTIM],,, [[#include <poll.h>]])
AC_CHECK_DECLS([SO_PEERCRED],,, [[#include <sys/socket.h>]])
AC_CHECK_DECLS([SOL_TCP],,, [[#include <netinet/tcp.h>]])
AC_CHECK_DECLS([TCP_INFO],,, [[#include <netinet/tcp.h>]])
AC_CHECK_DECLS([IPPROTO_TCP],,, [[#include <netinet/in.h>]])
AC_CHECK_DECLS([SOL_TCP,TCP_INFO,TCP_CONNECTION_INFO],,, [[#include <netinet/tcp.h>]])

if test -n "$have_sys_socket_h"; then
AC_CHECK_DECLS([SO_SNDBUF],,, [[#include <sys/socket.h>]])
Expand Down
10 changes: 8 additions & 2 deletions lib/bbackupd/BackupClientContext.cpp
Expand Up @@ -73,8 +73,10 @@ BackupClientContext::BackupClientContext
mKeepAliveTimer(0, "KeepAliveTime"),
mbIsManaged(false),
mrProgressNotifier(rProgressNotifier),
mTcpNiceMode(TcpNiceMode),
mpNice(NULL)
mTcpNiceMode(TcpNiceMode)
#ifdef ENABLE_TCP_NICE
, mpNice(NULL)
#endif
{
}

Expand Down Expand Up @@ -135,13 +137,17 @@ BackupProtocolCallable &BackupClientContext::GetConnection()

if(mTcpNiceMode)
{
#ifdef ENABLE_TCP_NICE
// Pass control of apSocket to NiceSocketStream,
// which will take care of destroying it for us.
// But we need to hang onto a pointer to the nice
// socket, so we can enable and disable nice mode.
// This is scary, it could be deallocated under us.
mpNice = new NiceSocketStream(apSocket);
apSocket.reset(mpNice);
#else
BOX_WARNING("TcpNice option is enabled but not supported on this system");
#endif
}

// We need to call some methods that aren't defined in
Expand Down
4 changes: 4 additions & 0 deletions lib/bbackupd/BackupClientContext.h
Expand Up @@ -216,7 +216,9 @@ class BackupClientContext : public DiffTimer
{
if(mTcpNiceMode)
{
#ifdef ENABLE_TCP_NICE
mpNice->SetEnabled(enabled);
#endif
}
}

Expand Down Expand Up @@ -246,7 +248,9 @@ class BackupClientContext : public DiffTimer
int mMaximumDiffingTime;
ProgressNotifier &mrProgressNotifier;
bool mTcpNiceMode;
#ifdef ENABLE_TCP_NICE
NiceSocketStream *mpNice;
#endif
};

#endif // BACKUPCLIENTCONTEXT__H
29 changes: 25 additions & 4 deletions lib/server/TcpNice.cpp
Expand Up @@ -30,6 +30,7 @@

#include "MemLeakFindOn.h"

#ifdef ENABLE_TCP_NICE
// --------------------------------------------------------------------------
//
// Function
Expand Down Expand Up @@ -139,7 +140,6 @@ NiceSocketStream::NiceSocketStream(std::auto_ptr<SocketStream> apSocket)
// --------------------------------------------------------------------------
void NiceSocketStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
#if HAVE_DECL_SO_SNDBUF && HAVE_DECL_TCP_INFO
if(mEnabled && mapTimer.get() && mapTimer->HasExpired())
{
box_time_t newPeriodStart = GetCurrentBoxTime();
Expand All @@ -148,6 +148,7 @@ void NiceSocketStream::Write(const void *pBuffer, int NBytes, int Timeout)
int rtt = 50; // WAG

# if HAVE_DECL_SOL_TCP && defined HAVE_STRUCT_TCP_INFO_TCPI_RTT
// The Linux way
struct tcp_info info;
socklen_t optlen = sizeof(info);
if(getsockopt(socket, SOL_TCP, TCP_INFO, &info, &optlen) == -1)
Expand All @@ -165,6 +166,27 @@ void NiceSocketStream::Write(const void *pBuffer, int NBytes, int Timeout)
{
rtt = info.tcpi_rtt;
}
# elif HAVE_DECL_IPPROTO_TCP && defined HAVE_DECL_TCP_CONNECTION_INFO
// The OSX way: https://stackoverflow.com/a/40478874/648162
struct tcp_connection_info info;
socklen_t optlen = sizeof(info);
if(getsockopt(socket, IPPROTO_TCP, TCP_CONNECTION_INFO, &info, &optlen) == -1)
{
BOX_LOG_SYS_WARNING("getsockopt(" << socket << ", IPPROTO_TCP, "
"TCP_CONNECTION_INFO) failed");
}
else if(optlen < sizeof(info))
{
BOX_WARNING("getsockopt(" << socket << ", IPPROTO_TCP, "
"TCP_CONNECTION_INFO) return structure size " << optlen << ", "
"expected " << sizeof(info));
}
else
{
rtt = info.tcpi_rttcur;
}
# else
# error "Don't know how to get current TCP RTT"
# endif // HAVE_DECL_SOL_TCP && defined HAVE_STRUCT_TCP_INFO_TCPI_RTT

int newWindow = mTcpNice.GetNextWindowSize(mBytesWrittenThisPeriod,
Expand Down Expand Up @@ -192,7 +214,6 @@ void NiceSocketStream::Write(const void *pBuffer, int NBytes, int Timeout)
}

mBytesWrittenThisPeriod += NBytes;
#endif // HAVE_DECL_SO_SNDBUF

mapSocket->Write(pBuffer, NBytes, Timeout);
}
Expand All @@ -214,7 +235,6 @@ void NiceSocketStream::SetEnabled(bool enabled)
if(!enabled)
{
StopTimer();
#if HAVE_DECL_SO_SNDBUF
int socket = mapSocket->GetSocketHandle();
int newWindow = 1<<17;
if(setsockopt(socket, SOL_SOCKET, SO_SNDBUF,
Expand All @@ -231,6 +251,7 @@ void NiceSocketStream::SetEnabled(bool enabled)
BOX_LOG_SYS_WARNING("getsockopt(" << socket << ", SOL_SOCKET, "
"SO_SNDBUF, " << newWindow << ") failed");
}
#endif
}
}

#endif // ENABLE_TCP_NICE
11 changes: 11 additions & 0 deletions lib/server/TcpNice.h
Expand Up @@ -18,6 +18,16 @@
#include "SocketStream.h"
#include "Timer.h"

#if HAVE_DECL_SO_SNDBUF
# if HAVE_DECL_SOL_TCP && defined HAVE_STRUCT_TCP_INFO_TCPI_RTT
# define ENABLE_TCP_NICE
# elif HAVE_DECL_IPPROTO_TCP && HAVE_DECL_TCP_CONNECTION_INFO
// https://stackoverflow.com/a/40478874/648162
# define ENABLE_TCP_NICE
# endif
#endif

#ifdef ENABLE_TCP_NICE
// --------------------------------------------------------------------------
//
// Class
Expand Down Expand Up @@ -176,5 +186,6 @@ class NiceSocketStream : public SocketStream
NiceSocketStream(const NiceSocketStream &rToCopy)
{ /* do not call */ }
};
#endif // ENABLE_TCP_NICE

#endif // TCPNICE__H

0 comments on commit fb3fa2a

Please sign in to comment.