/* * Copyright (C) 1996-2023 The Squid Software Foundation and contributors * * Squid software is distributed under GPLv2+ license and includes * contributions from numerous individuals and organizations. * Please see the COPYING and CONTRIBUTORS files for details. */ #include "squid.h" #include "acl/Acl.h" #include "acl/Gadgets.h" #include "ClientDelayConfig.h" #include "ConfigParser.h" #include "Parsing.h" #include "Store.h" ClientDelayPool::~ClientDelayPool() { if (access) aclDestroyAccessList(&access); } void ClientDelayPool::dump(StoreEntry * entry, unsigned int poolNumberMinusOne) const { LOCAL_ARRAY(char, nom, 32); snprintf(nom, 32, "client_delay_access %d", poolNumberMinusOne + 1); dump_acl_access(entry, nom, access); storeAppendPrintf(entry, "client_delay_parameters %d %d %" PRId64 "\n", poolNumberMinusOne + 1, rate,highwatermark); storeAppendPrintf(entry, "\n"); } ClientDelayPools * ClientDelayPools::Instance() { static ClientDelayPools pools; return &pools; } ClientDelayPools::~ClientDelayPools() { pools.clear(); } void ClientDelayConfig::finalize() { for (unsigned int i = 0; i < pools().size(); ++i) { /* pools require explicit 'allow' to assign a client into them */ if (!pool(i).access) { debugs(77, DBG_IMPORTANT, "WARNING: client_delay_pool #" << (i+1) << " has no client_delay_access configured. " << "No client will ever use it."); } } } void ClientDelayConfig::dumpPoolCount(StoreEntry * entry, const char *name) const { const auto &pools_ = ClientDelayPools::Instance()->pools; if (pools_.size()) { storeAppendPrintf(entry, "%s %d\n", name, static_cast(pools_.size())); for (unsigned int i = 0; i < pools_.size(); ++i) pools_[i]->dump(entry, i); } } void ClientDelayConfig::freePools() { pools().clear(); } void ClientDelayConfig::parsePoolCount() { if (pools().size()) { debugs(3, DBG_CRITICAL, "parse_client_delay_pool_count: multiple client_delay_pools lines, " << "aborting all previous client_delay_pools config"); freePools(); } unsigned short pools_; ConfigParser::ParseUShort(&pools_); for (int i = 0; i < pools_; ++i) pools().push_back(new ClientDelayPool()); } void ClientDelayConfig::parsePoolRates() { if (unsigned short poolId = parsePoolId()) { --poolId; pool(poolId).rate = GetInteger(); pool(poolId).highwatermark = GetInteger64(); } } void ClientDelayConfig::parsePoolAccess(ConfigParser &parser) { if (const unsigned short poolId = parsePoolId()) aclParseAccessLine("client_delay_access", parser, &(pool(poolId-1).access)); } unsigned short ClientDelayConfig::parsePoolId() { unsigned short poolId = 0; ConfigParser::ParseUShort(&poolId); if (poolId < 1 || poolId > pools().size()) { debugs(3, DBG_CRITICAL, "parse_client_delay_pool_rates: Ignoring pool " << poolId << " not in 1 .. " << pools().size()); return 0; } return poolId; }