mirror of
https://github.com/pocoproject/poco.git
synced 2025-01-08 11:02:17 +01:00
7852153db5
* Enable unit test in cmake build * add BLOB SQLite test * accept notifications by name (if they have one) * catch std::exception on parsing * fix a leak, add some table features * few PostgreSQL fixes * GH #2351: WebSocket docs * Rename pcre internal symbols used by Poco to avoid symbol collision https://github.com/pocoproject/poco/issues/2916 This patch was backported from https://github.com/pld-linux/poco/blob/master/pcre.patch * Fix warning in clang * Fix MSVC clang build fail * Zip and SevenZip do not depend on Util, XML, JSON * Added Test and new Pattern 'O' to only log the Filename not the full Path. * Updated Comment * Configuration to receive OCSP stapling response for client connections and callback implementation to verify the response if the server returns any response * removed SDK version from project files * run Application::initialize() in try-catch block * fix Invalid condition [ICMPv4PacketImpl.cpp:234] #2783 * style fixes for #2935; check OpenSSL version * Fixed issue 2945 (#2946) * Fixed #2945 * Added unit tests for #2945 * Dissalow iterator on empty Var (#2945) * Updated unit tests for #2945 * More concise unit tests for #2945 * Removed some more clutter (#2945) * NetSSL_Win: fix potential endless loop due to wrong error handling * fixed GH #2970: Poco::Data::TypeHandler<Poco::Nullable<T>>::prepare() must prepare with underlying type, not Poco::Data::Keywords::null * Fixed linking with Data ODBC error on some platforms * Fix set padding call for new versions of OpenSSL * PatternFormatter priorityNames fix * PKCS12Container: fix memory leaks on exceptions * Fix constness of URI::getPathSegments * Fix typo in the ThreadPool's docs * cmake: use GNUInstallDirs * Changed EventHandlerMap key (#3116) * Changed EventHandlerMap key Changed EventHandlerMap key from Socket to poco_socket_t to avoid errors in removing/access EventHandlerMap when for example we make an SSL handshake * Changed EventHandlerMap key Changed EventHandlerMap key from Socket to poco_socket_t to avoid errors in removing/access EventHandlerMap when for example we make an SSL handshake * avoid too much call to sockfd() and impl() * Fix configuration error while cross compiling (#3127) During the configuration phase in a cross compilation scenario, `include(InstallRequiredSystemLibraries)` fails even if `MSVC_REDIST_DIR` is provided. This should not be an hard error, in case someone wants to compile/use the library, and not package it. As explained on https://reviews.llvm.org/D41220, the most sensible fix is to include `InstallRequiredSystemLibraries` only on a Windows host. * crash when remove key from JSON::Object(JSON_PRESERVE_KEY_ORDER). (#3151) * #3153: Poco::Data::ODBC [N]VARCHAR(MAX) wrong maxDataSize() result * [SharedPtr] Poco::makeSharedArray #3200 * #3202: JWT: ESxxx signature must include padding for ECDSA R and S values * feat(HashRange): port HashRange from boost * chore(cmake): spelling typo fix * fix(hashRange): change function names casing * merge changes from 1.10.2 * formatting * merge JSON formatting changes from 1.10.2 * added Application::windowSize() * RemoteSyslogChannel/RemoteSyslogListener: make UDP buffer size configurable * merge fix from 1.10.2 * merge Postgres fixes from 1.10.2 * #2993: The Sec-WebSocket-Key of WebSocket is always the same one * formatting * #2927 * remove HowToGetHelp page due to outdated information * formatting * #3044: Upgrade PCRE to 8.44 * #3086: Use POCO_IOS_INIT_HACK for Linux in combination with libc++ * #3095: Digest proxy authentication does not work in 1.10.1 * #3136: Fixed null character issue when parsing a JSON * #3114: Added JSON Array::empty() method * #3230: ECDSADigestEngine: include missing header * fix include order * include order * fix(PollSet): #3248 #3249 * chore(UDPServer): fix spelling * feat(SocketReactor): extract and expose poll() as a member function * feat(Endpoint): add Endpoint (socket address directly wrapping native structures) * fix(Endpoint): osx build, align family enum with patform, some other adjustments * fix(EndpointTest): add missing include * feat(Endpoint): add some low-level accessors * feat(IPAddress): add functions returning addres as raw bytes * feat(DatagramSocket): DatagramSocket does not allow IPV6_V6ONLY #3283 * feat(SocketReactor): Add completion handling to SocketReactor #3290 * feat(SocketReactor): Add completion handling to SocketReactor #3290 (add scheduled handlers and runOne()) * chore(Net-testsuite): fix some tests warnings * feat: move semantics for sockets and addresses * fix(NetworkInterface): Unterminated string possible in NetworkInterfaceImpl::setPhyParams() #3301 * feat(Net): Add move semantics to Net (sockets and addresses) #3296 * fix(HostEntry): DNS HostEntry returns multiple entries #3303 * fix(SocketReactor): completion handling fixes and tests, separation of i/o and completion mutexes * feat(SocketReactor): execute permanent completion handlers on when there are I/O handlers and the expired ones whenever they expire * feat(Socket): expose lastError() * fix(SocketReactor): windows compile * windows fixes, remove Endnpoint * feat(Socket): expose error() * feat(PollSet): Use select() on windows for PollSet #3339 * add ci.yml * fix compile errors * revert(SocketReactor): back to devel branch * feat(SocketProactor): initial version w/ completion handler and executor * chore(SocketProactor): Sockets package * chore(ci): add dir and run script * feat(SocketProactor): add socket error handling #3357 * modify(SocketProactor): wait for completion handlers availability #3357 * feat(PollSet): Make PollSet::poll() interruptible #3359 * modify(SocketProactor): make addSend() public #3357 * modify(SocketProactor): platform non-interrupt sleep without Poco thread #3357 * modify(SocketProactor): allow restart #3357 * fix(SocketProactor): windows fixes and VS build * fix(SocketProactor): race when stop() is called before run() * fix(Socket): Windows SO_REUSEADDR is neither reliable nor safe #3380 * fix(SocketProactor): rvalue refs should not be const * fix(DNS): DNS::hostByAddress not thread-safe #3381 * chore(SocketProactor): remove unnecessary this capture * fix(IPAddress): IPAddress::tryParse does not work for :: #3385 * fix(SoccketProactor): add some try/catch safety nets; broaden the work list mutex coverage to protect all function access * fix(SocketProactor): use Poco::Mutex only * fix(SocketProactor): scheduled work skipped in the absence of socket events * fix(SocketProactor): test * chore (SocketProactor): add some state members * Fix clang linker problem by defining POCO_NO_AUTOMATIC_LIBS (#3177) * Dev/devel 1.12.0 (#3585) * fix(PollSet): #3248 #3249 * bump version to 1.11.0 * updated changelog| * #3299: NetSSL: Allow per-Context InvalidCertificateHandler * #3022: Process::isRunning(PID pid) causes handle leak on Windows * #3022: fix for WinCE * upgrade bundled pdjson to latest master * update build configs - add support for Apple Silicon * #2906, #2904: Support environments without hardware floating point * #3130: fix error handling: report original error before close() * #3107: remove unused variable * #3219: SMTPClientSession: invalid SMTP command if empty recipients list in MailMessage * Poco::trim*() code cleanup - use ptrdiff_t instead of int; additional test cases * #3182 Poco::Process:launch on MacOS BigSur: limit maximum number of file descriptors to close before exec() to 100000 * #3278: Fixing no hardware floating point support - Part II * #3090: Do not initialize value with undefined behavior * #3163: Correct Var::parse null value * #3196: std::forward for Poco::Optional ctor with rvalue * #3068: Documented ENABLE_JWT option * #3041: PostgreSQL and TEXT column type * #3099: Fixed Postgres extraction into Dynamic::Var * #3138: Add support of arch riscv32 * #2825: riscv: Enable double operations when using double float abi * #3166: Fix PostgresSQL BLOB extractor * #3237: An error in the documentation for Poco/JSON/Parser.h * #3193: ServerApplication::registerService() unquoted path security vulnerability * #3266: Order of Util::Application::uninitialize() is not in reverse as documented * #3215: XML parser returns item from different element in a array * #3282: Update constant in setContentType documentation * #3089: HTTPSessionFactory does not support HTTPClientSession::ProxyConfig * #2418: SecureServerSocket doesn't work with IpV6 * fix warnings * #3019: ObjectPool wait on borrow condition fix * #3224: Remove SSL23 support from Poco/Crypto * #3191: Fixing a bug in the NetSSL_Win module (Host name verification failed error) * disallow SSLv3 * #3269: Poco::Net::Context initialization with empty certificateFile * #3307: Poco::Crypto::X509Certificate: obtain certificate fingerprint * #3260: Memory leak in EVPPKey::loadKey used with files & wrong password * #3157: fix(openssl): add missing dependency to OpenSSL components * #3066: CMake warning about MYSQL casing * #3135: Poco::Data::SQLite::Utility::fileToMemory unsuccessful if journal exists * #3217: CMake: warning message with -DPOCO_STATIC confusing * #3274: Fix localtime_r for VxWorks 6.9 and later * #2746, #3169: Fix race condition on TCPServerDispatcher stop * #3092: add more detailed error description when LoadLibrary fails| * #3074: Fix sessions may not return back to the pool * #3309: optimize parsing from stream (no copying of entire JSON to memory); limit maximum depth to avoid stack overflow with malicious documents (fuzzing - #3285); code cleanup * JSON Parser performance improvements * #3310: Upgrade bundled SQLite to 3.35.5 * fix UB/bad cast in TCPServerTest.cpp * add comment regarding potential UB in AnyTest::testCastToReference() * support sanitizers in build configs * bump version * fix 'catching polymorphic type by value' warnings * fix 'catching polymorphic type by value' warnings * fix 'catching polymorphic type by value' warnings * remove failing Android build; add sanitizer builds * update postgres version * fix warning * fix warning * add GitHub workflow * fix ci.yml * fix ci.yml * additional ci builds * fix ci.yml for macos and windows * fix(double-conversion): Upgrade bundled double-conversion #3313 * ci fixes * #3314: NetSSL_OpenSSL: any.pem certificate error: ca md too weak * testReuseSession: remove bad checks for session reuse * investigate failing test * investigate failing test * investigate failing test * investigate failing test * ci * remove travis and appveyor * ci, readme * ci fixes * fix ci * fix ci * fix ci * fix memory leak when ignoring test error/failure * fix ci * don't define UNREACHABLE as poco_bugcheck as it triggers 'control reaches end of non-void function' warning * add Linux cross build, build Data libs on macos * fix ci * add MySQL include/lib search paths for Homebrew * ci fixes * ci fixes * ci fixes * ci fixes * fix indluce paths for brew mysql * #3317: Data::MySQL MySQL headers and library search paths * fix ARM-Linux build config * fix MySQL.make * update FindMySQL.cmake * fix(SocketReactor): fix dataCollection test * chore: remove troubleshooting help leftovers * #3302: MSVC: Poco hides warnings (C4996) for the C++14 attribute [[deprecated]] * fix potential crash in testAsyncNotify: don't delete event object while async notification is still in progress * fix(PollSetTest): change connect to blocking * added ActiveRecord library and compiler * added dependencies file * update copyright dates * ActiveRecord: project files and fixes for MSVC * ci: enable ActiveRecord on Windows * fix(PollSetTest): remove poll timing check (fails on msvc ci) * fix ActiveRecord CMake build and configuration * feat(build): add gen directory (for generated sources) and macchina lib link dirs (if needed) * #3318: Data: Support Poco::UUID for data binding * ODBC tests for UUID, updated ActiveRecord projects * ActiveRecord user guide * update ActiveRecord documentation * documentation fixes * #3321: manually merge ODBC text encoding support * CppParser: merge changes from internal repository * updated Makefile * AbstractObserver::accepts() - add optional name parameter * fix SharedPtr::makeSharedArray() [merge from devel] * remove blank line * #2895, #2935: support OCSP stapling * style * clang support (merge from devel) * #3322: remove useless struct * link libmariadb instead of libmysql if headers indicate MariaDB * fix nullptr passed to memcmp/memcpy reported by ubsan * fix nullptr passed to memcmp/memcpy reported by ubsan * fix PageCompiler cross-compile; fix Content-Security-Policy header * remove Data release notes page * style, remove unused var * update docs * improve BLOB handling, clean-up code * fix(ICMPv4Packet): [asan] Undefined behavior in ICMPv4PacketImpl.cpp #3326 * fix(NumericString): Bug in NumericString with decSep != '.' #3159 * fix(HostEntry): DNS HostEntry returns multiple entries #3303 * fix(PollSet): #3248 #3249 * fix(NetworkInterface): Unterminated string possible in NetworkInterfaceImpl::setPhyParams() #3301 * style/whitespace * fix warnings * add version resources to executables * style * whitespace * update changelog * cpproj: also copy testsuite/include if it's there * branch off 1.11.1 * #3335: XML error when build 1.11.0 * #3353: add POCO_NO_FORK_EXEC CMake option * #3381: DNS::hostByAddress not thread-safe * #3400: fix std::localtime not thread safe * #3221: Crash reported on Windows in X509Certificate verification * #3344: [bug] MacOS bundle destination path is not set * #3360: Add POCO_PGSQL_{INCLUDE,LIB} variables * #3363: Fixed compilation error with MongoDB::Connection and Util::Application * #3377: Correct Poco::Path::configHome() and dataHome() documentation for Windows * #2823: error: implicit conversion from 'int' to 'float' changes value from 2147483647 to 2147483648 * #3425: Fixed suspend/resumeEvents pair in DirectoryWatcher * #2966: SocketReactor loads one core of CPU up to 100% * #3330: Poco::Data::ODBC::ODBCStatementImpl causes crash * use OpenSSL 1.1.1 on macOS * add missing include search path * upgrade bundled PCRE to 8.45 * upgrade bundled SQLite to 3.36.0 * updated changelog * fix brew OpenSSL version * branch off poco-1.11.2 * #3506: Upgrade bundled expat to 2.4.4 * manually merge #3448, part 1 (Crypto) * manually merge #3448, part 1 (NetSSL) * #3515: NetSSL_OpenSSL Testsuite: testInterop() and testProxy() fail due to changed certificate * #3448: fix version check * #3465: NetSSL_Win: bad error handling when decodeMessage() fails * #3458: encryptString() crash on redhat/centos 8 with FIPS enabled using md5 default digest * #3505: JSON::PrintHandler.value(bool) prints incorrect value * #3527: Upgrade bundled expat to 2.4.5 * #3470: bug in JSON ParseHandler.cpp (RFC 7159 should be valid) * #3507: Reference counting for bound configuration in Util::Option is broken * #3518: Expat version check in #defines incorrect * #3338: NamedMutex does not work on Linux distributions where fs.protected_regular=1 * CI: don't build PageCompiler in ARM cross build * detect ARM64 on Windows * updated README.md * ProGen: support generation of VS 2022 project files * ci: add windows 2022 * fix library name * remove unused CppUnit headers * added VS2022 project files * #3530: Upgrade bundled expat to 2.4.6 * #3538: Upgrade bundled expat to 2.4.7 * Add back NIOS2 double conversion detection to fix compile errors The commit558324f672
removed the nios2 support, which was originally added ine7b91e8125
This commit add it back. Signed-off-by: Julien Olivain <ju.o@free.fr> * #3466: DefinePlatformSpecific.cmake: handle RelWithDebInfo and MinSizeRel configurations * #3524: remove XML and Util dependencies in Zip/SevenZip * #3483: Adds Windows 11 and Server 2022 to Environment::osDisplayName() * #3495: Array::operator[] should not throw * #3268: Poco redis command set have a bug when you want to set nx ex or expireTime * #3509: fix dst and utcOffset handling for Dublin time zone * #2882: another attempt at fixing it that should also work on other platforms * remove unused method in Timezone_WIN32.cpp * use tm_gmtoff on Linux * Basic support for OpenSSL 3.0.0 (#3448) * updated README.md * Create close-inactive-issues.yml * check return codes of EVP_CIPHER_CTX_new and EVP_CipherInit Especially with OpenSSL 3, it is possible that EVP_CipherInit may fail even when passed a non-null cipher[1]. Without the checking, it will finally get to a segfault. [1] https://github.com/openssl/openssl/issues/16864 * Automatically load default and legacy providers with OpenSSL 3 Without the legacy provider [1], some ciphers are not available. For example, the 'des-ecb' one used by test sutie is missed and the test will fail. [1] OSSL_PROVIDER-LEGACY(7ossl) * Make p12 ca order the same as pem OpenSSL < 3 returns p12 ca order in reversed order. This is fixed in OpenSSL 3. We work around it with old OpenSSL. See: https://github.com/openssl/openssl/issues/16421 https://github.com/openssl/openssl/pull/12641f5eb85eb0f
* Implement SSL abort handling on OpenSSL 3 On an unexpected EOF, versions before OpenSSL 3.0 returned SSL_ERROR_SYSCALL, nothing was added to the error stack, and errno was 0. Since OpenSSL 3.0 the returned error is SSL_ERROR_SSL with a meaningful error on the error stack.[1] [1] SSL_GET_ERROR(3ossl) Co-authored-by: Günter Obiltschnig <guenter.obiltschnig@appinf.com> Co-authored-by: Robin Lee <cheeselee@fedoraproject.org> Co-authored-by: Aleksandar Fabijanic <aleks-f@users.noreply.github.com> * fix(Socket): shutdown fixes from pull #3448 * #3500: Sandbox all iFrames in PocoDoc * #3549; replace assert with assertTrue * #3553: Upgrade bundled zlib to 1.2.12 * #3525: Bad management of file in case of OpenSSLException in X509Certificate::readPEM and X509Certificate::writePEM * disable OpenSSL deprecation warnings * chore: cleanup * fix(X509Certificate): add missing string format * #3559: Poco::Data::PostgreSQL - DateTime extraction truncates fractional seconds * feat(EVP): 3.0 support - add EVPCipher - additional EVPPKey constructors - tests - fix and improve openssl-related exceptions Transition towards 3.0 support; deprecating direct EC and RSA interface portions. * fix(openssl): pre 3.0 compile * feat(Envelope): Add envelope to crypto #3561 * fix(Envelope): mac/clang compile * fix(Any): #3297 #3514 * #3562: fixed OpenSSL setup/shutdown * fix exception text * #3563: Remove support for OpenSSL < 1.0 * ci jobs for OpenSSL 1.1 and 3 * updated CHANGELOG * updated .vscode * Refactor/any soo (#3564) * refactor(Any): SOO - encapsulate data holders - add missing gets and ops - eliminate g++ warnings with enable_if's - default enable SOO * refactor(Placeholder): encapsulate SOO memory management and fix leaks; cf. #3297 #3514 * fix(Placeholder): asan errors and add tests cf. #3297 #3514 * fix(SSLManager): Race condition in SSLManager #3558 * remove unused include * updated copyright date * PocoDoc: fix iframe sandboxing * fix(SHA2Engine): cannot use HMACEngine with SHA2Engine #3421 * refactor(Placeholder): ifdef POCO_NO_SOO only in Placeholder and remove it anywhere else (#3566) * refactor(Placeholder): more SOO consolidation and optimization * fix(FPEnvironment): Visual Studio Warning C4244 #3543 * fix(Extractor): move extraction decoding to AbstractExtractor #3396 * Netssl/openssl3 (#3575) * feat(Context): DH init openssl3 port (1/2 hardcoded params) * create poco-1.11.3 branch, bump version * update copyright date * #3567: check legacy provider existence for legacy exception #3567 * fix(Placeholder): comparison for zero value * feat(Context): DH init openssl3 port (2/2 params from file) * test(HTTPSClientSession): try/catch to understand CI failure * chore(cmake): copy the DH parameters file * fix(OpenSSLInitializer): unload provider on uninitialize * chore(HTTPSClientSessionTest): remove try/catch * fix(OpenSSLInitializer): fix provider unloading * feat(CppUnit): make tests exceptions more descriptive * chore(CppUnit): a more descriptive name for callback Co-authored-by: Günter Obiltschnig <guenter.obiltschnig@appinf.com> * fix(Foundation): update VS 2019 platform version * chore(Data): update VS project files (add Transcoder #3396) * fix(Data): Poco::Data::ODBC-dbEncoding property not used for insert/update #3396 * fix(Data): add transcoder to Makefile #3396 * fix(JWT): remove duplicate test functions after merge Co-authored-by: Günter Obiltschnig <guenter.obiltschnig@appinf.com> Co-authored-by: Julien Olivain <ju.o@free.fr> Co-authored-by: Robin Lee <robinlee.sysu@gmail.com> Co-authored-by: Robin Lee <cheeselee@fedoraproject.org> * #2755: Fix MySQL's LONGBLOB/LONGTEXT not allocating enough space (#3474) * Unit test for bug #2755. * Removed condition to set buffer length to 0. * Fixes to unit tests for LONGBLOB/TEXT data type. * Adjusted buffer sizes to accommodate LONGBLOBs. Co-authored-by: Hector Toledo Soto <hsoto@transperfect.com> * fix(Data): MySQL UUID binding temporary string #3587 * feat(CI): add MySQL tests to CI #3588 * fix(CI): remove mysql client dev (using mariadb) #3588 * fix(CI): another shot at mysql * fix(Net/testsuite): add missing include * fix(DatagramSocket): Socket::available does not always return correct value for UDP #3589 * fix(SocketProactor): few improvements (#3357) * fix(ICMPsocketTest): change appinf (doesn't respond to ping) to github * fix(PollSet): windows fixes * fix(PollSet): windows implementation fixes (multi-fd_set select); minor reactor fixes * Extract JSON type as string (#3491) * Declared JSON as string data # Conflicts: # Data/include/Poco/Data/MetaColumn.h # Data/src/RecordSet.cpp # Data/src/StatementImpl.cpp * Added JSON extractor as string * Added unit test * Update comment Co-authored-by: Joerg-Christian Boehme <joerg@chaosdorf.de> Co-authored-by: Günter Obiltschnig <guenter.obiltschnig@appinf.com> Co-authored-by: tbarbier <thomas.barbier@amadeus.com> Co-authored-by: Linquize <linquize@yahoo.com.hk> Co-authored-by: Jan Kevin Dick <fixed-term.jan.dick@de.bosch.com> Co-authored-by: Neelima Patil <neelima.patil@honeywell.com> Co-authored-by: akete <akete@users.noreply.github.com> Co-authored-by: YuriAzathoth <iamkiller@mail.com> Co-authored-by: Jonathan Horvath <byteme@bytedreamer.com> Co-authored-by: Maksim Kita <kitaetoya@gmail.com> Co-authored-by: Alexander Galanin <al@galanin.nnov.ru> Co-authored-by: Thomas Sablik <thomas.sablik@wombytes.de> Co-authored-by: Nikita Migunov <nmigunov@iponweb.net> Co-authored-by: Ben Wolsieffer <benwolsieffer@gmail.com> Co-authored-by: micheleselea <michele.pradella@selea.com> Co-authored-by: Federico Kircheis <federico.kircheis@gmail.com> Co-authored-by: fenghao119 <fenghao119@gmail.com> Co-authored-by: Alex Fabijanic <alex@pocoprojecct.org> Co-authored-by: linquize <linquize2@yahoo.com> Co-authored-by: Julien Olivain <ju.o@free.fr> Co-authored-by: Robin Lee <robinlee.sysu@gmail.com> Co-authored-by: Robin Lee <cheeselee@fedoraproject.org> Co-authored-by: hectots <monkey.instinct@gmail.com> Co-authored-by: Hector Toledo Soto <hsoto@transperfect.com> Co-authored-by: Hernan Martinez <hernan.c.martinez@gmail.com>
809 lines
17 KiB
C++
809 lines
17 KiB
C++
//
|
|
// SocketProactor.cpp
|
|
//
|
|
// Library: Net
|
|
// Package: Sockets
|
|
// Module: SocketProactor
|
|
//
|
|
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
|
// and Contributors.
|
|
//
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
//
|
|
|
|
|
|
#include "Poco/Net/SocketProactor.h"
|
|
#include "Poco/Net/DatagramSocket.h"
|
|
#include "Poco/Net/DatagramSocketImpl.h"
|
|
#include "Poco/Thread.h"
|
|
#include "Poco/Exception.h"
|
|
#ifdef POCO_OS_FAMILY_WINDOWS
|
|
#ifdef max
|
|
#undef max
|
|
#endif // max
|
|
#endif // POCO_OS_FAMILY_WINDOWS
|
|
#include <limits>
|
|
|
|
|
|
using Poco::Exception;
|
|
using Poco::ErrorHandler;
|
|
|
|
|
|
namespace Poco {
|
|
namespace Net {
|
|
|
|
|
|
//
|
|
// Worker
|
|
//
|
|
|
|
class Worker
|
|
/// Worker is a utility class that executes work (functions).
|
|
/// Workload can be permanent (executed on every doWork() call),
|
|
/// or "one-shot" (scheduled for a single execution at a point
|
|
/// in the future).
|
|
{
|
|
public:
|
|
using MutexType = SocketProactor::MutexType;
|
|
using ScopedLock = SocketProactor::ScopedLock;
|
|
using Work = SocketProactor::Work;
|
|
using WorkEntry = std::pair<Work, Poco::Timestamp>;
|
|
using WorkList = std::deque<WorkEntry>;
|
|
|
|
void addWork(const Work& ch, Timestamp::TimeDiff ms = SocketProactor::PERMANENT_COMPLETION_HANDLER)
|
|
{
|
|
addWork(Work(ch), ms);
|
|
}
|
|
|
|
void addWork(Work&& ch, Timestamp::TimeDiff ms, int pos = -1)
|
|
{
|
|
auto pch = SocketProactor::PERMANENT_COMPLETION_HANDLER;
|
|
Poco::Timestamp expires = (ms != pch) ? Timestamp() + (ms * 1000) : Timestamp(pch);
|
|
if (pos == -1 || (pos + 1) > _funcList.size())
|
|
{
|
|
ScopedLock lock(_mutex);
|
|
_funcList.push_back({std::move(ch), expires});
|
|
}
|
|
else
|
|
{
|
|
if (pos < 0)
|
|
throw Poco::InvalidArgumentException("SocketProactor::addWork()");
|
|
ScopedLock lock(_mutex);
|
|
_funcList.insert(_funcList.begin() + pos, {std::move(ch), expires});
|
|
}
|
|
|
|
}
|
|
|
|
void removeWork()
|
|
{
|
|
ScopedLock lock(_mutex);
|
|
_funcList.clear();
|
|
}
|
|
|
|
int scheduledWork()
|
|
{
|
|
int cnt = 0;
|
|
ScopedLock lock(_mutex);
|
|
WorkList::iterator it = _funcList.begin();
|
|
for (; it != _funcList.end(); ++it)
|
|
{
|
|
if (!isPermanent(it->second)) ++cnt;
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
int removeScheduledWork(int count)
|
|
{
|
|
auto isScheduled = [](const Timestamp &ts)
|
|
{ return !isPermanent(ts); };
|
|
return removeWork(isScheduled, count);
|
|
}
|
|
|
|
int permanentWork()
|
|
{
|
|
int cnt = 0;
|
|
ScopedLock lock(_mutex);
|
|
WorkList::iterator it = _funcList.begin();
|
|
for (; it != _funcList.end(); ++it)
|
|
{
|
|
if (isPermanent(it->second))
|
|
++cnt;
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
|
|
int removePermanentWork(int count)
|
|
{
|
|
auto perm = [](const Timestamp &ts)
|
|
{ return isPermanent(ts); };
|
|
return removeWork(perm, count);
|
|
}
|
|
|
|
static bool isPermanent(const Timestamp &entry)
|
|
{
|
|
return entry == Timestamp(SocketProactor::PERMANENT_COMPLETION_HANDLER);
|
|
}
|
|
|
|
int doWork(bool handleOne, bool expiredOnly)
|
|
{
|
|
std::unique_ptr<Work> pCH;
|
|
int handled = 0;
|
|
{
|
|
ScopedLock lock(_mutex);
|
|
WorkList::iterator it = _funcList.begin();
|
|
try
|
|
{
|
|
while (it != _funcList.end())
|
|
{
|
|
std::size_t prevSize = 0;
|
|
bool alwaysRun = isPermanent(it->second) && !expiredOnly;
|
|
bool isExpired = !alwaysRun && (Timestamp() >= it->second);
|
|
if (isExpired)
|
|
{
|
|
pCH.reset(new Work(std::move(it->first)));
|
|
it = _funcList.erase(it);
|
|
}
|
|
else if (alwaysRun)
|
|
{
|
|
pCH.reset(new Work(it->first));
|
|
++it;
|
|
}
|
|
else ++it;
|
|
prevSize = _funcList.size();
|
|
|
|
if (pCH)
|
|
{
|
|
(*pCH)();
|
|
pCH.reset();
|
|
++handled;
|
|
if (handleOne) break;
|
|
}
|
|
// handler call may add or remove handlers;
|
|
// if so, we must start from the beginning
|
|
if (prevSize != _funcList.size())
|
|
it = _funcList.begin();
|
|
}
|
|
}
|
|
catch (Exception& exc)
|
|
{
|
|
ErrorHandler::handle(exc);
|
|
}
|
|
catch (std::exception& exc)
|
|
{
|
|
ErrorHandler::handle(exc);
|
|
}
|
|
catch (...)
|
|
{
|
|
ErrorHandler::handle();
|
|
}
|
|
}
|
|
return handled;
|
|
}
|
|
|
|
int runOne()
|
|
{
|
|
try
|
|
{
|
|
while (0 == doWork(true, false));
|
|
return 1;
|
|
}
|
|
catch(...) {}
|
|
return 0;
|
|
}
|
|
|
|
private:
|
|
template <typename F>
|
|
int removeWork(F isType, int count)
|
|
/// Removes `count` functions of the specified type;
|
|
/// if count is -1, removes all the functions of the
|
|
/// specified type.
|
|
{
|
|
int removed = 0;
|
|
ScopedLock lock(_mutex);
|
|
int left = count > -1 ? count : static_cast<int>(_funcList.size());
|
|
WorkList::iterator it = _funcList.begin();
|
|
while (left && it != _funcList.end())
|
|
{
|
|
if (isType(it->second))
|
|
{
|
|
++removed;
|
|
it = _funcList.erase((it));
|
|
--left;
|
|
}
|
|
else ++it;
|
|
}
|
|
return removed;
|
|
}
|
|
|
|
WorkList _funcList;
|
|
MutexType _mutex;
|
|
};
|
|
|
|
|
|
//
|
|
// SocketProactor
|
|
//
|
|
|
|
const Timestamp::TimeDiff SocketProactor::PERMANENT_COMPLETION_HANDLER =
|
|
std::numeric_limits<Timestamp::TimeDiff>::max();
|
|
|
|
|
|
SocketProactor::SocketProactor(bool worker):
|
|
_isRunning(false),
|
|
_isStopped(false),
|
|
_stop(false),
|
|
_timeout(0),
|
|
_maxTimeout(DEFAULT_MAX_TIMEOUT_MS),
|
|
_pThread(nullptr),
|
|
_ioCompletion(_maxTimeout),
|
|
_pWorker(worker ? new Worker : nullptr)
|
|
{
|
|
}
|
|
|
|
|
|
SocketProactor::SocketProactor(const Poco::Timespan& timeout, bool worker):
|
|
_isRunning(false),
|
|
_isStopped(false),
|
|
_stop(false),
|
|
_timeout(0),
|
|
_maxTimeout(static_cast<long>(timeout.totalMilliseconds())),
|
|
_pThread(nullptr),
|
|
_ioCompletion(_maxTimeout),
|
|
_pWorker(worker ? new Worker : nullptr)
|
|
{
|
|
}
|
|
|
|
|
|
SocketProactor::~SocketProactor()
|
|
{
|
|
_ioCompletion.stop();
|
|
wait();
|
|
for (auto& pS : _writeHandlers)
|
|
{
|
|
for (auto& pH : pS.second)
|
|
{
|
|
if (pH->_pBuf && pH->_owner)
|
|
delete pH->_pBuf;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SocketProactor::wait()
|
|
{
|
|
_ioCompletion.wakeUp();
|
|
_ioCompletion.wait();
|
|
}
|
|
|
|
|
|
bool SocketProactor::hasHandlers(SubscriberMap& handlers, int sockfd)
|
|
{
|
|
Poco::Mutex::ScopedLock l(_writeMutex);
|
|
if (handlers.end() == handlers.find(sockfd))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
|
|
int SocketProactor::poll(int* pHandled)
|
|
{
|
|
int handled = 0;
|
|
int worked = 0;
|
|
PollSet::SocketModeMap sm = _pollSet.poll(_timeout);
|
|
if (sm.size() > 0)
|
|
{
|
|
auto it = sm.begin();
|
|
auto end = sm.end();
|
|
for (; it != end; ++it)
|
|
{
|
|
if (it->second & PollSet::POLL_READ)
|
|
{
|
|
Socket sock = it->first;
|
|
if (hasHandlers(_readHandlers, static_cast<int>(sock.impl()->sockfd())))
|
|
handled += receive(sock);
|
|
}
|
|
if (it->second & PollSet::POLL_WRITE)
|
|
{
|
|
Socket sock = it->first;
|
|
if (hasHandlers(_writeHandlers, static_cast<int>(sock.impl()->sockfd())))
|
|
handled += send(sock);
|
|
}
|
|
if (it->second & PollSet::POLL_ERROR)
|
|
{
|
|
Socket sock = it->first;
|
|
handled += error(sock);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_pWorker)
|
|
{
|
|
if (hasSocketHandlers() && handled) worked = doWork();
|
|
else worked = doWork(false, true);
|
|
}
|
|
|
|
if (pHandled) *pHandled = handled;
|
|
return worked;
|
|
}
|
|
|
|
|
|
void SocketProactor::addReceiveFrom(Socket sock, Buffer& buf, Poco::Net::SocketAddress& addr, Callback&& onCompletion)
|
|
{
|
|
if (!sock.isDatagram())
|
|
throw Poco::InvalidArgumentException("SocketProactor::addSend(): UDP socket required");
|
|
std::unique_ptr<Handler> pHandler(new Handler);
|
|
pHandler->_pAddr = std::addressof(addr);
|
|
pHandler->_pBuf = std::addressof(buf);
|
|
pHandler->_onCompletion = std::move(onCompletion);
|
|
|
|
Poco::Mutex::ScopedLock l(_readMutex);
|
|
_readHandlers[sock.impl()->sockfd()].push_back(std::move(pHandler));
|
|
}
|
|
|
|
|
|
void SocketProactor::addSendTo(Socket sock, const Buffer& message, const SocketAddress& addr, Callback&& onCompletion)
|
|
{
|
|
if (!sock.isDatagram())
|
|
throw Poco::InvalidArgumentException("SocketProactor::addSend(): UDP socket required");
|
|
Buffer* pMessage = nullptr;
|
|
SocketAddress* pAddr = nullptr;
|
|
try
|
|
{
|
|
pMessage = new Buffer(message);
|
|
pAddr = new SocketAddress(addr);
|
|
}
|
|
catch(...)
|
|
{
|
|
delete pMessage;
|
|
delete pAddr;
|
|
throw;
|
|
}
|
|
addSend(sock, pMessage, pAddr, std::move(onCompletion), true);
|
|
}
|
|
|
|
|
|
void SocketProactor::addSendTo(Socket sock, Buffer&& message, const SocketAddress&& addr, Callback&& onCompletion)
|
|
{
|
|
if (!sock.isDatagram())
|
|
throw Poco::InvalidArgumentException("SocketProactor::addSend(): UDP socket required");
|
|
Buffer* pMessage = nullptr;
|
|
SocketAddress* pAddr = nullptr;
|
|
try
|
|
{
|
|
pMessage = new Buffer(std::move(message));
|
|
pAddr = new SocketAddress(std::move(addr));
|
|
}
|
|
catch(...)
|
|
{
|
|
delete pMessage;
|
|
delete pAddr;
|
|
throw;
|
|
}
|
|
addSend(sock, pMessage, pAddr, std::move(onCompletion), true);
|
|
}
|
|
|
|
|
|
void SocketProactor::addReceive(Socket sock, Buffer& buf, Callback&& onCompletion)
|
|
{
|
|
if (!sock.isStream())
|
|
throw Poco::InvalidArgumentException("SocketProactor::addSend(): TCP socket required");
|
|
std::unique_ptr<Handler> pHandler(new Handler);
|
|
pHandler->_pAddr = nullptr;
|
|
pHandler->_pBuf = std::addressof(buf);
|
|
pHandler->_onCompletion = std::move(onCompletion);
|
|
|
|
Poco::Mutex::ScopedLock l(_readMutex);
|
|
_readHandlers[sock.impl()->sockfd()].push_back(std::move(pHandler));
|
|
if (!has(sock)) addSocket(sock, PollSet::POLL_READ);
|
|
}
|
|
|
|
|
|
void SocketProactor::addSend(Socket sock, const Buffer& message, Callback&& onCompletion)
|
|
{
|
|
if (!sock.isStream())
|
|
throw Poco::InvalidArgumentException("SocketProactor::addSend(): TCP socket required");
|
|
Buffer* pMessage = nullptr;
|
|
try
|
|
{
|
|
pMessage = new Buffer(message);
|
|
}
|
|
catch(...)
|
|
{
|
|
delete pMessage;
|
|
throw;
|
|
}
|
|
addSend(sock, pMessage, nullptr, std::move(onCompletion), true);
|
|
}
|
|
|
|
|
|
void SocketProactor::addSend(Socket sock, Buffer&& message, Callback&& onCompletion)
|
|
{
|
|
if (!sock.isStream())
|
|
throw Poco::InvalidArgumentException("SocketProactor::addSend(): TCP socket required");
|
|
Buffer* pMessage = nullptr;
|
|
try
|
|
{
|
|
pMessage = new Buffer(std::move(message));
|
|
}
|
|
catch(...)
|
|
{
|
|
delete pMessage;
|
|
throw;
|
|
}
|
|
addSend(sock, pMessage, nullptr, std::move(onCompletion), true);
|
|
}
|
|
|
|
|
|
void SocketProactor::addSend(Socket sock, Buffer* pMessage, SocketAddress* pAddr, Callback&& onCompletion, bool own)
|
|
{
|
|
std::unique_ptr<Handler> pHandler(new Handler);
|
|
pHandler->_pAddr = pAddr;
|
|
pHandler->_pBuf = pMessage;
|
|
pHandler->_onCompletion = std::move(onCompletion);
|
|
pHandler->_owner = own;
|
|
|
|
Poco::Mutex::ScopedLock l(_writeMutex);
|
|
_writeHandlers[sock.impl()->sockfd()].push_back(std::move(pHandler));
|
|
if (!has(sock)) addSocket(sock, PollSet::POLL_WRITE);
|
|
}
|
|
|
|
|
|
int SocketProactor::error(Socket& sock)
|
|
{
|
|
int cnt = errorImpl(sock, _readHandlers, _readMutex);
|
|
cnt += errorImpl(sock, _writeHandlers, _writeMutex);
|
|
return cnt;
|
|
}
|
|
|
|
|
|
int SocketProactor::send(Socket& sock)
|
|
{
|
|
Poco::Mutex::ScopedLock l(_writeMutex);
|
|
auto hIt = _writeHandlers.find(sock.impl()->sockfd());
|
|
if (hIt == _writeHandlers.end()) return 0;
|
|
IOHandlerList& handlers = hIt->second;
|
|
int handled = static_cast<int>(handlers.size());
|
|
auto it = handlers.begin();
|
|
auto end = handlers.end();
|
|
while (it != end)
|
|
{
|
|
if (sock.isDatagram())
|
|
sendTo(*sock.impl(), it);
|
|
else if (sock.isStream())
|
|
send(*sock.impl(), it);
|
|
else
|
|
{
|
|
deleteHandler(handlers, it);
|
|
throw Poco::InvalidArgumentException("Unknown socket type.");
|
|
}
|
|
deleteHandler(handlers, it);
|
|
|
|
// end iterator is invalidated when the last member
|
|
// is removed, so make sure we don't check for it
|
|
if (handlers.empty()) break;
|
|
}
|
|
handled -= static_cast<int>(handlers.size());
|
|
if (handled) _ioCompletion.wakeUp();
|
|
return handled;
|
|
}
|
|
|
|
|
|
void SocketProactor::sendTo(SocketImpl& sock, IOHandlerIt& it)
|
|
{
|
|
Buffer* pBuf = (*it)->_pBuf;
|
|
if (pBuf && pBuf->size())
|
|
{
|
|
SocketAddress *pAddr = (*it)->_pAddr;
|
|
int n = 0, err = 0;
|
|
try
|
|
{
|
|
n = sock.sendTo(&(*pBuf)[0], static_cast<int>(pBuf->size()), *pAddr);
|
|
}
|
|
catch(std::exception&)
|
|
{
|
|
err = Socket::lastError();
|
|
}
|
|
enqueueIONotification(std::move((*it)->_onCompletion), n, err);
|
|
}
|
|
else
|
|
{
|
|
if (!pBuf)
|
|
throw Poco::NullPointerException("SocketProactor::sendTo(): null buffer");
|
|
else if (pBuf->empty())
|
|
throw Poco::InvalidArgumentException("SocketProactor::sendTo(): empty buffer");
|
|
else // we shouldn't be here
|
|
throw Poco::InvalidAccessException("SocketProactor::sendTo(): unexpected error");
|
|
}
|
|
}
|
|
|
|
|
|
void SocketProactor::send(SocketImpl& sock, IOHandlerIt& it)
|
|
{
|
|
Buffer* pBuf = (*it)->_pBuf;
|
|
if (pBuf && pBuf->size())
|
|
{
|
|
int n = 0, err = 0;
|
|
try
|
|
{
|
|
n = sock.sendBytes(&(*pBuf)[0], static_cast<int>(pBuf->size()));
|
|
}
|
|
catch(std::exception&)
|
|
{
|
|
err = Socket::lastError();
|
|
}
|
|
enqueueIONotification(std::move((*it)->_onCompletion), n, err);
|
|
}
|
|
else
|
|
{
|
|
if (!pBuf)
|
|
throw Poco::NullPointerException("SocketProactor::sendTo(): null buffer");
|
|
else if (pBuf->empty())
|
|
throw Poco::InvalidArgumentException("SocketProactor::sendTo(): empty buffer");
|
|
else // we shouldn't be here
|
|
throw Poco::InvalidAccessException("SocketProactor::sendTo(): unexpected error");
|
|
}
|
|
}
|
|
|
|
|
|
int SocketProactor::receive(Socket& sock)
|
|
{
|
|
Poco::Mutex::ScopedLock l(_readMutex);
|
|
auto hIt = _readHandlers.find(sock.impl()->sockfd());
|
|
if (hIt == _readHandlers.end()) return 0;
|
|
IOHandlerList& handlers = hIt->second;
|
|
int handled = static_cast<int>(handlers.size());
|
|
int avail = 0;
|
|
auto it = handlers.begin();
|
|
auto end = handlers.end();
|
|
for (; it != end;)
|
|
{
|
|
if ((avail = sock.available()))
|
|
{
|
|
if (sock.isDatagram())
|
|
receiveFrom(*sock.impl(), it, avail);
|
|
else if (sock.isStream())
|
|
receive(*sock.impl(), it, avail);
|
|
else
|
|
throw Poco::InvalidArgumentException("Unknown socket type.");
|
|
|
|
++it;
|
|
handlers.pop_front();
|
|
// end iterator is invalidated when the last member
|
|
// is removed, so make sure we don't check for it
|
|
if (handlers.size() == 0) break;
|
|
}
|
|
else break;
|
|
}
|
|
handled -= static_cast<int>(handlers.size());
|
|
if (handled) _ioCompletion.wakeUp();
|
|
return handled;
|
|
}
|
|
|
|
|
|
void SocketProactor::receiveFrom(SocketImpl& sock, IOHandlerIt& it, int available)
|
|
{
|
|
Buffer *pBuf = (*it)->_pBuf;
|
|
SocketAddress *pAddr = (*it)->_pAddr;
|
|
SocketAddress addr = *pAddr;
|
|
poco_check_ptr(pBuf);
|
|
if (pBuf->size() < available) pBuf->resize(available);
|
|
int n = 0, err = 0;
|
|
try
|
|
{
|
|
n = sock.receiveFrom(&(*pBuf)[0], available, *pAddr);
|
|
}
|
|
catch(std::exception&)
|
|
{
|
|
err = Socket::lastError();
|
|
}
|
|
enqueueIONotification(std::move((*it)->_onCompletion), n, err);
|
|
}
|
|
|
|
|
|
void SocketProactor::receive(SocketImpl& sock, IOHandlerIt& it, int available)
|
|
{
|
|
Buffer *pBuf = (*it)->_pBuf;
|
|
poco_check_ptr(pBuf);
|
|
if (pBuf->size() < available) pBuf->resize(available);
|
|
int n = 0, err = 0;
|
|
try
|
|
{
|
|
n = sock.receiveBytes(&(*pBuf)[0], available);
|
|
}
|
|
catch(std::exception&)
|
|
{
|
|
err = Socket::lastError();
|
|
}
|
|
enqueueIONotification(std::move((*it)->_onCompletion), n, err);
|
|
}
|
|
|
|
|
|
int SocketProactor::doWork(bool handleOne, bool expiredOnly)
|
|
{
|
|
return worker().doWork(handleOne, expiredOnly);
|
|
}
|
|
|
|
|
|
int SocketProactor::runOne()
|
|
{
|
|
return worker().runOne();
|
|
}
|
|
|
|
|
|
void SocketProactor::sleep(bool isAtWork)
|
|
{
|
|
try
|
|
{
|
|
if (isAtWork)
|
|
{
|
|
_timeout = 0;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (_timeout < _maxTimeout) ++_timeout;
|
|
}
|
|
if (_pThread) _pThread->trySleep(_timeout);
|
|
else Thread::sleep(_timeout);
|
|
}
|
|
catch (Exception& exc)
|
|
{
|
|
ErrorHandler::handle(exc);
|
|
}
|
|
catch (std::exception& exc)
|
|
{
|
|
ErrorHandler::handle(exc);
|
|
}
|
|
catch (...)
|
|
{
|
|
ErrorHandler::handle();
|
|
}
|
|
}
|
|
|
|
|
|
void SocketProactor::run()
|
|
{
|
|
_pThread = Thread::current();
|
|
_ioCompletion.start();
|
|
int handled = 0;
|
|
if (!_isStopped) _stop = false;
|
|
_isStopped = false;
|
|
while (!_stop)
|
|
{
|
|
this->sleep(poll(&handled) || handled);
|
|
_isRunning = true;
|
|
}
|
|
_isRunning = false;
|
|
onShutdown();
|
|
}
|
|
|
|
|
|
bool SocketProactor::hasSocketHandlers() const
|
|
{
|
|
if (_readHandlers.size() || _writeHandlers.size())
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
void SocketProactor::stop()
|
|
{
|
|
// the reason for two flags is to prevent a race
|
|
// when stop() is called before run() (which sets
|
|
// stop to false before entering the polling loop
|
|
// in order to allow multiple run()/stop() cycles)
|
|
_stop = true;
|
|
_isStopped = true;
|
|
}
|
|
|
|
|
|
void SocketProactor::wakeUp()
|
|
{
|
|
if (_pThread) _pThread->wakeUp();
|
|
}
|
|
|
|
|
|
void SocketProactor::setTimeout(const Poco::Timespan& timeout)
|
|
{
|
|
_timeout = static_cast<long>(timeout.totalMilliseconds());
|
|
}
|
|
|
|
|
|
Poco::Timespan SocketProactor::getTimeout() const
|
|
{
|
|
return _maxTimeout;
|
|
}
|
|
|
|
|
|
Worker& SocketProactor::worker()
|
|
{
|
|
poco_check_ptr(_pWorker);
|
|
return *_pWorker;
|
|
}
|
|
|
|
|
|
void SocketProactor::addWork(const Work& ch, Timestamp::TimeDiff ms)
|
|
{
|
|
worker().addWork(Work(ch), ms);
|
|
}
|
|
|
|
|
|
void SocketProactor::addWork(Work&& ch, Timestamp::TimeDiff ms, int pos)
|
|
{
|
|
worker().addWork(std::move(ch), ms, pos);
|
|
}
|
|
|
|
|
|
void SocketProactor::removeWork()
|
|
{
|
|
worker().removeWork();
|
|
}
|
|
|
|
|
|
int SocketProactor::scheduledWork()
|
|
{
|
|
return worker().scheduledWork();
|
|
}
|
|
|
|
|
|
int SocketProactor::removeScheduledWork(int count)
|
|
{
|
|
return worker().removeScheduledWork(count);
|
|
}
|
|
|
|
|
|
int SocketProactor::permanentWork()
|
|
{
|
|
return worker().permanentWork();
|
|
}
|
|
|
|
|
|
int SocketProactor::removePermanentWork(int count)
|
|
{
|
|
return worker().removePermanentWork(count);
|
|
}
|
|
|
|
|
|
bool SocketProactor::has(const Socket& sock) const
|
|
{
|
|
return _pollSet.has(sock);
|
|
}
|
|
|
|
|
|
bool SocketProactor::ioCompletionInProgress() const
|
|
{
|
|
return _ioCompletion.queueSize();
|
|
}
|
|
|
|
|
|
void SocketProactor::onShutdown()
|
|
{
|
|
_pollSet.wakeUp();
|
|
_ioCompletion.stop();
|
|
_ioCompletion.wait();
|
|
}
|
|
|
|
|
|
void SocketProactor::deleteHandler(IOHandlerList& handlers, IOHandlerList::iterator& it)
|
|
{
|
|
if ((*it)->_owner)
|
|
{
|
|
if ((*it)->_pBuf)
|
|
{
|
|
delete (*it)->_pBuf;
|
|
(*it)->_pBuf = nullptr;
|
|
}
|
|
if ((*it)->_pAddr)
|
|
{
|
|
delete (*it)->_pAddr;
|
|
(*it)->_pAddr = nullptr;
|
|
}
|
|
}
|
|
++it;
|
|
handlers.pop_front();
|
|
}
|
|
|
|
|
|
} } // namespace Poco::Net
|