diff --git a/service/connection_handler.h b/service/connection_handler.h index 409af51e..01dff5fc 100644 --- a/service/connection_handler.h +++ b/service/connection_handler.h @@ -177,6 +177,9 @@ struct ConnectionHandler { return *transport_; } + virtual double getEstimatedRTT() + { return transport().getEstimatedRTT(); } + const TransportBase & transport() const { if (!transport_) diff --git a/service/transport.cc b/service/transport.cc index 0f26cfc3..1b9d5546 100644 --- a/service/transport.cc +++ b/service/transport.cc @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include using namespace std; @@ -1026,5 +1028,31 @@ closePeer() return peer().close(); } +double +SocketTransport::getEstimatedRTT() +{ + tcp_info tcpinfo; + int len = sizeof(tcpinfo); + + int success = peer().get_option(IPPROTO_TCP, TCP_INFO, &tcpinfo, &len); + if (success != -1) { + + std::chrono::milliseconds rtt = std::chrono::duration_cast(std::chrono::microseconds(tcpinfo.tcpi_rtt)); + std::chrono::milliseconds rtt_var = std::chrono::duration_cast(std::chrono::microseconds(tcpinfo.tcpi_rttvar)); + + /* + * As discussed on the ML: + * We could also add some 'safety' levels to account for user-level + * overhead and weird values that could be returned from this i.e. + * rtt = tcp_rtt+3 * var_rtt + 2ms clamp to range (2ms, 50ms) + */ + return rtt.count() + 3 * rtt_var.count() + 2; + + } else { + return double(-1); + } +} + + } // namespace Datacratic diff --git a/service/transport.h b/service/transport.h index f56bc93b..8fcec054 100644 --- a/service/transport.h +++ b/service/transport.h @@ -58,6 +58,8 @@ struct TransportBase : public std::enable_shared_from_this { virtual int handleAsync(const boost::function & callback, const char * name, Date dateSet); + virtual double getEstimatedRTT() { return double(-1);} + virtual ssize_t send(const char * buf, size_t len, int flags) = 0; virtual ssize_t recv(char * buf, size_t buf_size, int flags) = 0; @@ -604,6 +606,7 @@ struct SocketTransport virtual ssize_t send(const char * buf, size_t len, int flags); virtual ssize_t recv(char * buf, size_t buf_size, int flags); virtual int closePeer(); + virtual double getEstimatedRTT(); ACE_SOCK_Stream & peer() { return peer_; } const ACE_SOCK_Stream & peer() const { return peer_; }