Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net::Defaults: Revert and re-apply revised code #10366

Merged
merged 2 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions common/Unit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

#pragma once

#include <atomic>
#include <cassert>
#include <chrono>
#include <map>
Expand All @@ -17,7 +16,6 @@

#include <common/StateEnum.hpp>
#include "Util.hpp"
#include "NetUtil.hpp"
#include "net/Socket.hpp"
#include <Poco/Exception.h>

Expand Down Expand Up @@ -421,9 +419,6 @@ class UnitWSD : public UnitBase
/// Manipulate and modify the configuration before any usage.
virtual void configure(Poco::Util::LayeredConfiguration& /* config */) {}

/// Manipulate and modify the net::Defaults for before any usage.
virtual void configNet(net::Defaults& /* defaults */) {}

/// Main-loop reached, time for testing.
/// Invoked from coolwsd's main thread.
void invokeTest()
Expand Down
3 changes: 1 addition & 2 deletions kit/Kit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
#include <common/JsonUtil.hpp>
#include "KitHelper.hpp"
#include "Kit.hpp"
#include <NetUtil.hpp>
#include <Protocol.hpp>
#include <Log.hpp>
#include <Png.hpp>
Expand Down Expand Up @@ -2928,7 +2927,7 @@ void documentViewCallback(const int type, const char* payload, void* data)
int pollCallback(void* pData, int timeoutUs)
{
if (timeoutUs < 0)
timeoutUs = net::Defaults::get().SocketPollTimeout.count();
timeoutUs = SocketPoll::DefaultPollTimeoutMicroS.count();
#ifndef IOS
if (!pData)
return 0;
Expand Down
4 changes: 2 additions & 2 deletions net/HttpRequest.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1201,9 +1201,9 @@ class Session final : public ProtocolHandlerInterface
}

/// Returns the default timeout.
static std::chrono::milliseconds getDefaultTimeout()
static constexpr std::chrono::milliseconds getDefaultTimeout()
{
return std::chrono::duration_cast<std::chrono::milliseconds>( net::Defaults::get().HTTPTimeout );
return std::chrono::seconds(30);
}

/// Returns the current protocol scheme.
Expand Down
44 changes: 11 additions & 33 deletions net/NetUtil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,42 +29,20 @@ struct sockaddr;
namespace net
{

class Defaults
class DefaultValues
{
public:
/// WebSocketHandler ping timeout in us (2s default). Zero disables metric.
std::chrono::microseconds WSPingTimeout;
/// WebSocketHandler ping period in us (3s default), i.e. duration until next ping. Zero disables metric.
std::chrono::microseconds WSPingPeriod;
/// http::Session timeout in us (30s default). Zero disables metric.
std::chrono::microseconds HTTPTimeout;

/// Maximum total connections (9999 or MAX_CONNECTIONS). Zero disables metric.
size_t MaxConnections;

/// Socket poll timeout in us (64s), useful to increase for debugging.
std::chrono::microseconds SocketPollTimeout;

private:
Defaults()
: WSPingTimeout(std::chrono::microseconds(2000000))
, WSPingPeriod(std::chrono::microseconds(3000000))
, HTTPTimeout(std::chrono::microseconds(30000000))
, MaxConnections(9999)
, SocketPollTimeout(std::chrono::microseconds(64000000))
{
}

public:
Defaults(const Defaults&) = delete;
Defaults(Defaults&&) = delete;

static Defaults& get()
{
static Defaults def;
return def;
}
/// StreamSocket inactivity timeout in us (3600s default). Zero disables instrument.
std::chrono::microseconds inactivityTimeout;
/// WebSocketHandler average ping timeout in us (12s default). Zero disables instrument.
std::chrono::microseconds wsPingAvgTimeout;
/// WebSocketHandler ping interval in us (18s default), i.e. duration until next ping. Zero disables instrument.
std::chrono::microseconds wsPingInterval;

/// Maximum number of concurrent TCP connections. Zero disables instrument.
size_t maxTCPConnections;
};
extern DefaultValues Defaults;

class HostEntry
{
Expand Down
29 changes: 18 additions & 11 deletions net/Socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@
#include <Watchdog.hpp>
#include <wasm/base64.hpp>

// Bug in pre C++17 where static constexpr must be defined. Fixed in C++17.
constexpr std::chrono::microseconds SocketPoll::DefaultPollTimeoutMicroS;
constexpr std::chrono::microseconds WebSocketHandler::InitialPingDelayMicroS;

std::atomic<bool> SocketPoll::InhibitThreadChecks(false);
std::atomic<bool> Socket::InhibitThreadChecks(false);

Expand All @@ -65,6 +69,11 @@ std::unique_ptr<Watchdog> SocketPoll::PollWatchdog;
std::mutex SocketPoll::StatsMutex;
std::atomic<size_t> SocketPoll::StatsConnectionCount(0);

net::DefaultValues net::Defaults = { .inactivityTimeout = std::chrono::seconds(3600),
.wsPingAvgTimeout = std::chrono::seconds(12),
.wsPingInterval = std::chrono::seconds(18),
.maxTCPConnections = 200000 /* arbitrary value to be resolved */ };

size_t SocketPoll::StatsConnectionMod(size_t added, size_t removed) {
if( added == 0 && removed == 0 ) {
return GetStatsConnectionCount();
Expand Down Expand Up @@ -190,7 +199,6 @@ bool StreamSocket::socketpair(const std::chrono::steady_clock::time_point &creat
int rc = ::socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, pair);
if (rc != 0)
return false;

child = std::make_shared<StreamSocket>("save-child", pair[0], Socket::Type::Unix, true, HostType::Other, ReadType::NormalRead, creationTime);
child->setNoShutdown();
child->setClientAddress("save-child");
Expand Down Expand Up @@ -312,7 +320,6 @@ namespace {

SocketPoll::SocketPoll(std::string threadName)
: _name(std::move(threadName)),
_pollTimeout( net::Defaults::get().SocketPollTimeout ),
_limitedConnections( false ),
_connectionLimit( 0 ),
_pollStartIndex(0),
Expand Down Expand Up @@ -1089,7 +1096,7 @@ void WebSocketHandler::dumpState(std::ostream& os, const std::string& /*indent*/

void StreamSocket::dumpState(std::ostream& os)
{
int64_t timeoutMaxMicroS = _pollTimeout.count();
int64_t timeoutMaxMicroS = SocketPoll::DefaultPollTimeoutMicroS.count();
const int events = getPollEvents(std::chrono::steady_clock::now(), timeoutMaxMicroS);
os << '\t' << std::setw(6) << getFD() << "\t0x" << std::hex << events << std::dec << '\t'
<< (ignoringInput() ? "ignore\t" : "process\t") << std::setw(6) << _inBuffer.size() << '\t'
Expand Down Expand Up @@ -1487,14 +1494,14 @@ bool StreamSocket::checkRemoval(std::chrono::steady_clock::time_point now)
// Forced removal on outside-facing IPv[46] network connections only
const auto durLast =
std::chrono::duration_cast<std::chrono::milliseconds>(now - getLastSeenTime());
/// TO Criteria: Violate maximum idle (_pollTimeout default 64s)
const bool isIdle = _pollTimeout > std::chrono::microseconds::zero() &&
durLast > _pollTimeout;
/// TO Criteria: Shall terminate?
/// Timeout criteria: Violate maximum inactivity (default 3600s)
const bool isInactive = net::Defaults.inactivityTimeout > std::chrono::microseconds::zero() &&
durLast > net::Defaults.inactivityTimeout;
/// Timeout criteria: Shall terminate?
const bool isTermination = SigUtil::getTerminationFlag();
if (isIdle || isTermination )
if (isInactive || isTermination )
{
LOG_WRN("CheckRemoval: Timeout: {Idle " << isIdle
LOG_WRN("CheckRemoval: Timeout: {Inactive " << isInactive
<< ", Termination " << isTermination << "}, "
<< getStatsString(now) << ", "
<< *this);
Expand Down Expand Up @@ -1529,8 +1536,8 @@ bool StreamSocket::parseHeader(const char *clientName,
{
assert(map._headerSize == 0 && map._messageSize == 0);

const std::chrono::duration<float, std::milli> delayMax =
std::chrono::duration_cast<std::chrono::milliseconds>(_httpTimeout);
constexpr std::chrono::duration<float, std::milli> delayMax =
std::chrono::duration_cast<std::chrono::milliseconds>(SocketPoll::DefaultPollTimeoutMicroS);

std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
std::chrono::duration<float, std::milli> delayMs = now - lastHTTPHeader;
Expand Down
13 changes: 3 additions & 10 deletions net/Socket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
#include "Util.hpp"
#include "Buffer.hpp"
#include "SigUtil.hpp"
#include "NetUtil.hpp"

#include "FakeSocket.hpp"

Expand Down Expand Up @@ -714,6 +713,8 @@ class SocketPoll

static std::unique_ptr<Watchdog> PollWatchdog;

/// Default poll time - useful to increase for debugging.
static constexpr std::chrono::microseconds DefaultPollTimeoutMicroS = std::chrono::seconds(64);
static std::atomic<bool> InhibitThreadChecks;

/// Stop the polling thread.
Expand Down Expand Up @@ -947,7 +948,7 @@ class SocketPoll
{
while (continuePolling())
{
poll(_pollTimeout);
poll(DefaultPollTimeoutMicroS);
}
}

Expand Down Expand Up @@ -999,7 +1000,6 @@ class SocketPoll

/// Debug name used for logging.
const std::string _name;
const std::chrono::microseconds _pollTimeout;
bool _limitedConnections;
size_t _connectionLimit;

Expand Down Expand Up @@ -1067,8 +1067,6 @@ class StreamSocket : public Socket,
HostType hostType, ReadType readType = ReadType::NormalRead,
std::chrono::steady_clock::time_point creationTime = std::chrono::steady_clock::now() ) :
Socket(fd, type, creationTime),
_pollTimeout( net::Defaults::get().SocketPollTimeout ),
_httpTimeout( net::Defaults::get().HTTPTimeout ),
_hostname(std::move(host)),
_wsState(WSState::HTTP),
_isLocalHost(hostType == LocalHost),
Expand Down Expand Up @@ -1749,11 +1747,6 @@ class StreamSocket : public Socket,
#endif

private:
/// default to 64s, see net::Defaults::SocketPollTimeout
const std::chrono::microseconds _pollTimeout;
/// defaults to 30s, see net::Defaults::HTTPTimeout
const std::chrono::microseconds _httpTimeout;

/// The hostname (or IP) of the peer we are connecting to.
const std::string _hostname;

Expand Down
19 changes: 7 additions & 12 deletions net/WebSocketHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

#include "NetUtil.hpp"
#include "Socket.hpp"
#include "common/Common.hpp"
#include "common/Log.hpp"
#include "common/Protocol.hpp"
#include "common/Unit.hpp"
Expand All @@ -35,8 +34,6 @@ class WebSocketHandler : public ProtocolHandlerInterface
std::weak_ptr<StreamSocket> _socket;

#if !MOBILEAPP
std::chrono::microseconds _pingPeriod;
std::chrono::duration<double, std::micro> _pingTimeout;
std::chrono::steady_clock::time_point _lastPingSentTime;
Util::TimeAverage _pingMicroS;
bool _isMasking;
Expand Down Expand Up @@ -74,10 +71,8 @@ class WebSocketHandler : public ProtocolHandlerInterface
WebSocketHandler(bool isClient, [[maybe_unused]] bool isMasking)
:
#if !MOBILEAPP
_pingPeriod(net::Defaults::get().WSPingPeriod),
_pingTimeout(net::Defaults::get().WSPingTimeout),
_lastPingSentTime(std::chrono::steady_clock::now() -
_pingPeriod +
net::Defaults.wsPingInterval +
std::chrono::microseconds(InitialPingDelayMicroS))
, _isMasking(isClient && isMasking)
, _inFragmentBlock(false)
Expand Down Expand Up @@ -605,7 +600,7 @@ class WebSocketHandler : public ProtocolHandlerInterface
const auto timeSincePingMicroS
= std::chrono::duration_cast<std::chrono::microseconds>(now - _lastPingSentTime);
timeoutMaxMicroS
= std::min(timeoutMaxMicroS, (int64_t)(_pingPeriod - timeSincePingMicroS).count());
= std::min(timeoutMaxMicroS, (int64_t)(net::Defaults.wsPingInterval - timeSincePingMicroS).count());
}
#endif
int events = POLLIN;
Expand Down Expand Up @@ -672,21 +667,21 @@ class WebSocketHandler : public ProtocolHandlerInterface
if (_isClient)
return false;

if (_pingTimeout.count() > std::numeric_limits<double>::epsilon() &&
_pingMicroS.average() >= _pingTimeout.count())
if (net::Defaults.wsPingAvgTimeout > std::chrono::microseconds::zero() &&
_pingMicroS.average() >= net::Defaults.wsPingAvgTimeout.count())
{
std::shared_ptr<StreamSocket> socket = _socket.lock();
if (socket && socket->isIPType()) // Exclude non-IP local sockets
{
LOG_WRN("CheckTimeout: Timeout websocket: Ping: last " << _pingMicroS.last() << "us, avg "
<< _pingMicroS.average() << "us >= " << _pingTimeout.count() << "us over "
<< _pingMicroS.average() << "us >= " << net::Defaults.wsPingAvgTimeout.count() << "us over "
<< (int)_pingMicroS.duration() << "s, " << *socket);
shutdownSilent(socket);
return true;
}
}
if (!_pingMicroS.initialized() || (_pingPeriod > std::chrono::microseconds::zero() &&
now - _pingMicroS.lastTime() >= _pingPeriod))
if (!_pingMicroS.initialized() || (net::Defaults.wsPingInterval > std::chrono::microseconds::zero() &&
now - _pingMicroS.lastTime() >= net::Defaults.wsPingInterval))
{
const std::shared_ptr<StreamSocket> socket = _socket.lock();
if (socket)
Expand Down
4 changes: 1 addition & 3 deletions test/UnitPerf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ void UnitPerf::testPerf(std::string testType, std::string fileType, std::string
stats = std::make_shared<Stats>();
stats->setTypeOfTest(std::move(testType));

const std::chrono::microseconds PollTimeoutMicroS = net::Defaults::get().SocketPollTimeout;

TerminatingPoll poll("performance test");

std::string docName = "empty." + fileType;
Expand All @@ -74,7 +72,7 @@ void UnitPerf::testPerf(std::string testType, std::string fileType, std::string
stats);

do {
poll.poll(PollTimeoutMicroS);
poll.poll(TerminatingPoll::DefaultPollTimeoutMicroS);
} while (poll.continuePolling() && poll.getSocketCount() > 0);

stats->dump();
Expand Down
9 changes: 2 additions & 7 deletions test/UnitTimeoutConnections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,9 @@ static constexpr size_t ConnectionCount = 9;
/// Base test suite class for connection limit (limited) using HTTP and WS sessions.
class UnitTimeoutConnections : public UnitTimeoutBase1
{
void configNet(net::Defaults& defaults) override
void configure(Poco::Util::LayeredConfiguration& /* config */) override
{
// defaults.WSPingTimeout = std::chrono::microseconds(2000000);
// defaults.WSPingPeriod = std::chrono::microseconds(3000000);
// defaults.HTTPTimeout = std::chrono::microseconds(30000000);
// defaults.MaxConnections = 9999;
defaults.MaxConnections = ConnectionLimit;
// defaults.SocketPollTimeout = std::chrono::microseconds(64000000);
net::Defaults.maxTCPConnections = ConnectionLimit;
}

public:
Expand Down
8 changes: 1 addition & 7 deletions test/UnitTimeoutNone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,9 @@ static constexpr size_t ConnectionCount = 9;
/// Base test suite class for connection limit (no limits) using HTTP and WS sessions.
class UnitTimeoutNone : public UnitTimeoutBase1
{
void configNet(net::Defaults& /* defaults */) override
void configure(Poco::Util::LayeredConfiguration& /* config */) override
{
// Keep original values -> No timeout
// defaults.WSPingTimeout = std::chrono::microseconds(2000000);
// defaults.WSPingPeriod = std::chrono::microseconds(3000000);
// defaults.HTTPTimeout = std::chrono::microseconds(30000000);
// defaults.MaxConnections = 9999;
// defaults.MaxConnections = ConnectionLimit;
// defaults.SocketPollTimeout = std::chrono::microseconds(64000000);
}

public:
Expand Down
13 changes: 4 additions & 9 deletions test/UnitTimeoutWSPing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,10 @@ class UnitTimeoutWSPing : public UnitTimeoutBase0
{
TestResult testWSPing();

void configNet(net::Defaults& defaults) override
void configure(Poco::Util::LayeredConfiguration& /* config */) override
{
// defaults.WSPingTimeout = std::chrono::microseconds(2000000);
// defaults.WSPingPeriod = std::chrono::microseconds(3000000);
defaults.WSPingTimeout = std::chrono::microseconds(20);
defaults.WSPingPeriod = std::chrono::microseconds(10000);
// defaults.HTTPTimeout = std::chrono::microseconds(30000000);
// defaults.MaxConnections = 9999;
// defaults.SocketPollTimeout = std::chrono::microseconds(64000000);
net::Defaults.wsPingAvgTimeout = std::chrono::microseconds(20);
net::Defaults.wsPingInterval = std::chrono::milliseconds(10);
}

public:
Expand Down Expand Up @@ -90,7 +85,7 @@ void UnitTimeoutWSPing::invokeWSDTest()

result = testWSPing();
if (result != TestResult::Ok)
exitTest(result);
exitTest(result);

exitTest(TestResult::Ok);
}
Expand Down
Loading
Loading