mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-12 10:13:51 +01:00
Devel (#3586)
* 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>
This commit is contained in:
parent
6de1e18eb9
commit
7852153db5
14
.github/workflows/ci.yml
vendored
14
.github/workflows/ci.yml
vendored
@ -3,13 +3,23 @@ on: [push]
|
||||
jobs:
|
||||
linux-gcc-make:
|
||||
runs-on: ubuntu-20.04
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:latest
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
MYSQL_USER: pocotest
|
||||
MYSQL_PASSWORD: pocotest
|
||||
MYSQL_DATABASE: pocotest
|
||||
ports:
|
||||
- 3306:3306
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: sudo apt update && sudo apt install libssl-dev unixodbc-dev libmysqlclient-dev redis-server
|
||||
- run: sudo apt update && sudo apt install libssl-dev unixodbc-dev redis-server libmysqlclient-dev
|
||||
- run: ./configure --everything --omit=PDF && make all -s -j4 && sudo make install
|
||||
- run: >-
|
||||
sudo -s
|
||||
EXCLUDE_TESTS="Data/MySQL Data/ODBC Data/PostgreSQL MongoDB"
|
||||
EXCLUDE_TESTS="Data/ODBC Data/PostgreSQL MongoDB"
|
||||
./ci/runtests.sh
|
||||
|
||||
linux-gcc-make-asan:
|
||||
|
@ -14,7 +14,7 @@ set_target_properties(mod_poco
|
||||
target_include_directories(mod_poco
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE
|
||||
${APACHE2_INCLUDE_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
|
@ -50,6 +50,9 @@ if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
# Enable standard installation directories
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Include some common macros to simpilfy the Poco CMake files
|
||||
include(PocoMacros)
|
||||
|
||||
@ -436,7 +439,9 @@ add_custom_target(uninstall
|
||||
#############################################################
|
||||
# Enable packaging
|
||||
|
||||
include(InstallRequiredSystemLibraries)
|
||||
if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||
include(InstallRequiredSystemLibraries)
|
||||
endif()
|
||||
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Poco Libraries")
|
||||
set(CPACK_PACKAGE_VENDOR "Applied Informatics Software Engineering GmbH")
|
||||
@ -462,7 +467,7 @@ write_basic_package_version_file(
|
||||
if(WIN32)
|
||||
set(PocoConfigPackageLocation "cmake")
|
||||
else()
|
||||
set(PocoConfigPackageLocation "lib${LIB_SUFFIX}/cmake/${PROJECT_NAME}")
|
||||
set(PocoConfigPackageLocation "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
||||
endif()
|
||||
|
||||
configure_file(cmake/${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/${PROJECT_NAME}Config.cmake" @ONLY)
|
||||
|
@ -25,7 +25,7 @@ target_link_libraries(CppParser PUBLIC Poco::Foundation)
|
||||
target_include_directories(CppParser
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
|
@ -18,10 +18,15 @@ target_link_libraries(CppUnit PUBLIC Poco::Foundation)
|
||||
target_include_directories(CppUnit
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
if(WIN32)
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
target_compile_definitions(CppUnit PUBLIC POCO_NO_AUTOMATIC_LIBS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(CppUnit
|
||||
|
@ -55,7 +55,6 @@
|
||||
<ProjectGuid>{138BB448-808A-4FE5-A66D-78D1F8770F59}</ProjectGuid>
|
||||
<RootNamespace>CppUnit</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">
|
||||
|
@ -55,7 +55,6 @@
|
||||
<ProjectGuid>{138BB448-808A-4FE5-A66D-78D1F8770F59}</ProjectGuid>
|
||||
<RootNamespace>CppUnit</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">
|
||||
|
@ -55,7 +55,6 @@
|
||||
<ProjectGuid>{138BB448-808A-4FE5-A66D-78D1F8770F59}</ProjectGuid>
|
||||
<RootNamespace>CppUnit</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">
|
||||
|
@ -25,7 +25,7 @@ target_link_libraries(Crypto PUBLIC Poco::Foundation OpenSSL::SSL OpenSSL::Crypt
|
||||
target_include_directories(Crypto
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
@ -30,7 +30,7 @@ target_link_libraries(Data PUBLIC Poco::Foundation)
|
||||
target_include_directories(Data
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
|
@ -25,7 +25,7 @@ target_link_libraries(DataMySQL PUBLIC Poco::Data MySQL::client)
|
||||
target_include_directories(DataMySQL
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions(DataMySQL PUBLIC THREADSAFE NO_TCL)
|
||||
|
@ -323,6 +323,10 @@ public:
|
||||
private:
|
||||
bool realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, bool isUnsigned = false);
|
||||
|
||||
bool extractLongLOB(std::size_t pos);
|
||||
|
||||
bool extractJSON(std::size_t pos);
|
||||
|
||||
// Prevent VC8 warning "operator= could not be generated"
|
||||
Extractor& operator=(const Extractor&);
|
||||
|
||||
|
@ -40,6 +40,9 @@ class ResultMetadata
|
||||
/// MySQL result metadata
|
||||
{
|
||||
public:
|
||||
~ResultMetadata();
|
||||
/// Destroys the ResultMetadata.
|
||||
|
||||
void reset();
|
||||
/// Resets the metadata.
|
||||
|
||||
@ -64,10 +67,13 @@ public:
|
||||
bool isNull(std::size_t pos) const;
|
||||
/// Returns true if value at pos is null.
|
||||
|
||||
void adjustColumnSizeToFit(std::size_t pos);
|
||||
/// Expands the size allocated for column to fit the length of the data.
|
||||
|
||||
private:
|
||||
std::vector<MetaColumn> _columns;
|
||||
std::vector<MYSQL_BIND> _row;
|
||||
std::vector<char> _buffer;
|
||||
std::vector<char*> _buffer;
|
||||
std::vector<unsigned long> _lengths;
|
||||
std::vector<my_boolv> _isNull; // using char instead of bool to avoid std::vector<bool> disaster
|
||||
};
|
||||
|
@ -213,8 +213,7 @@ void Binder::bind(std::size_t pos, const Time& val, Direction dir)
|
||||
|
||||
void Binder::bind(std::size_t pos, const UUID& val, Direction dir)
|
||||
{
|
||||
std::string str = val.toString();
|
||||
bind(pos, str, dir);
|
||||
bind(pos, toString(val), dir);
|
||||
}
|
||||
|
||||
|
||||
|
@ -128,9 +128,12 @@ bool Extractor::extract(std::size_t pos, std::string& val)
|
||||
|
||||
//mysql reports TEXT types as FDT_BLOB when being extracted
|
||||
MetaColumn::ColumnDataType columnType = _metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type();
|
||||
if (columnType != Poco::Data::MetaColumn::FDT_STRING && columnType != Poco::Data::MetaColumn::FDT_BLOB)
|
||||
if (columnType != Poco::Data::MetaColumn::FDT_STRING && columnType != Poco::Data::MetaColumn::FDT_BLOB && columnType != Poco::Data::MetaColumn::FDT_JSON)
|
||||
throw MySQLException("Extractor: not a string");
|
||||
|
||||
if (columnType == Poco::Data::MetaColumn::FDT_JSON && !extractJSON(pos))
|
||||
return false;
|
||||
|
||||
val.assign(reinterpret_cast<const char*>(_metadata.rawData(pos)), _metadata.length(pos));
|
||||
return true;
|
||||
}
|
||||
@ -147,6 +150,9 @@ bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
|
||||
if (_metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type() != Poco::Data::MetaColumn::FDT_BLOB)
|
||||
throw MySQLException("Extractor: not a blob");
|
||||
|
||||
if (_metadata.metaColumn(static_cast<Poco::UInt32>(pos)).length() == 0 && !extractLongLOB(pos))
|
||||
return false;
|
||||
|
||||
val.assignRaw(_metadata.rawData(pos), _metadata.length(pos));
|
||||
return true;
|
||||
}
|
||||
@ -163,6 +169,9 @@ bool Extractor::extract(std::size_t pos, Poco::Data::CLOB& val)
|
||||
if (_metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type() != Poco::Data::MetaColumn::FDT_BLOB)
|
||||
throw MySQLException("Extractor: not a blob");
|
||||
|
||||
if (_metadata.metaColumn(static_cast<Poco::UInt32>(pos)).length() == 0 && !extractLongLOB(pos))
|
||||
return false;
|
||||
|
||||
val.assignRaw(reinterpret_cast<const char*>(_metadata.rawData(pos)), _metadata.length(pos));
|
||||
return true;
|
||||
}
|
||||
@ -263,6 +272,37 @@ bool Extractor::realExtractFixed(std::size_t pos, enum_field_types type, void* b
|
||||
return isNull == 0;
|
||||
}
|
||||
|
||||
bool Extractor::extractLongLOB(std::size_t pos)
|
||||
{
|
||||
// Large LOBs (LONGBLOB and LONGTEXT) are fetched
|
||||
// with a zero-length buffer to avoid allocating
|
||||
// huge amounts of memory. Therefore, when extracting
|
||||
// the buffers need to be adjusted.
|
||||
|
||||
_metadata.adjustColumnSizeToFit(pos);
|
||||
|
||||
MYSQL_BIND* row = _metadata.row();
|
||||
if (!_stmt.fetchColumn(pos, &row[pos]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Extractor::extractJSON(std::size_t pos)
|
||||
{
|
||||
// JSON columns are fetched with a zero-length
|
||||
// buffer to avoid allocating huge amounts of memory.
|
||||
// Therefore, when extracting the buffers need to be adjusted.
|
||||
|
||||
_metadata.adjustColumnSizeToFit(pos);
|
||||
|
||||
MYSQL_BIND* row = _metadata.row();
|
||||
row->buffer_type = MYSQL_TYPE_JSON;
|
||||
if (!_stmt.fetchColumn(pos, &row[pos]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////
|
||||
// Not implemented
|
||||
|
@ -71,6 +71,7 @@ namespace
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_JSON:
|
||||
return field.length;
|
||||
|
||||
default:
|
||||
@ -128,6 +129,8 @@ namespace
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_BLOB:
|
||||
return Poco::Data::MetaColumn::FDT_BLOB;
|
||||
case MYSQL_TYPE_JSON:
|
||||
return Poco::Data::MetaColumn::FDT_JSON;
|
||||
default:
|
||||
return Poco::Data::MetaColumn::FDT_UNKNOWN;
|
||||
}
|
||||
@ -140,6 +143,13 @@ namespace Data {
|
||||
namespace MySQL {
|
||||
|
||||
|
||||
ResultMetadata::~ResultMetadata()
|
||||
{
|
||||
for (std::vector<char*>::iterator it = _buffer.begin(); it != _buffer.end(); ++it)
|
||||
std::free(*it);
|
||||
}
|
||||
|
||||
|
||||
void ResultMetadata::reset()
|
||||
{
|
||||
_columns.resize(0);
|
||||
@ -165,7 +175,6 @@ void ResultMetadata::init(MYSQL_STMT* stmt)
|
||||
std::size_t count = mysql_num_fields(h);
|
||||
MYSQL_FIELD* fields = mysql_fetch_fields(h);
|
||||
|
||||
std::size_t commonSize = 0;
|
||||
_columns.reserve(count);
|
||||
|
||||
for (std::size_t i = 0; i < count; i++)
|
||||
@ -181,29 +190,24 @@ void ResultMetadata::init(MYSQL_STMT* stmt)
|
||||
0, // TODO: precision
|
||||
!IS_NOT_NULL(fields[i].flags) // nullable
|
||||
));
|
||||
|
||||
commonSize += _columns[i].length();
|
||||
}
|
||||
|
||||
_buffer.resize(commonSize);
|
||||
_buffer.resize(count);
|
||||
_row.resize(count);
|
||||
_lengths.resize(count);
|
||||
_isNull.resize(count);
|
||||
|
||||
std::size_t offset = 0;
|
||||
|
||||
for (std::size_t i = 0; i < count; i++)
|
||||
{
|
||||
std::memset(&_row[i], 0, sizeof(MYSQL_BIND));
|
||||
unsigned int len = static_cast<unsigned int>(_columns[i].length());
|
||||
_buffer[i] = (char*) std::calloc(len, sizeof(char));
|
||||
_row[i].buffer_type = fields[i].type;
|
||||
_row[i].buffer_length = len;
|
||||
_row[i].buffer = (len > 0) ? (&_buffer[0] + offset) : 0;
|
||||
_row[i].buffer = _buffer[i];
|
||||
_row[i].length = &_lengths[i];
|
||||
_row[i].is_null = reinterpret_cast<my_bool*>(&_isNull[i]); // workaround to make it work with both MySQL 8 and earlier
|
||||
_row[i].is_unsigned = (fields[i].flags & UNSIGNED_FLAG) > 0;
|
||||
|
||||
offset += _row[i].buffer_length;
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,4 +248,13 @@ bool ResultMetadata::isNull(std::size_t pos) const
|
||||
}
|
||||
|
||||
|
||||
void ResultMetadata::adjustColumnSizeToFit(std::size_t pos)
|
||||
{
|
||||
std::free(_buffer[pos]);
|
||||
_buffer[pos] = (char*) std::calloc(_lengths[pos], sizeof(char));
|
||||
_row[pos].buffer = _buffer[pos];
|
||||
_row[pos].buffer_length = _lengths[pos];
|
||||
}
|
||||
|
||||
|
||||
} } } // namespace Poco::Data::MySQL
|
||||
|
15
Data/MySQL/testsuite/run-db-setup.sh
Executable file
15
Data/MySQL/testsuite/run-db-setup.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
#apt-get install mariadb-server
|
||||
USER=pocotest
|
||||
PASS=pocotest
|
||||
|
||||
mysql -uroot <<MYSQL_SCRIPT
|
||||
CREATE DATABASE pocotest;
|
||||
CREATE USER '$USER'@'localhost' IDENTIFIED BY '$PASS';
|
||||
GRANT ALL PRIVILEGES ON pocotest.* TO '$USER'@'localhost';
|
||||
FLUSH PRIVILEGES;
|
||||
MYSQL_SCRIPT
|
||||
|
||||
echo "MySQL user created."
|
||||
echo "Username: $USER"
|
||||
echo "Password: $PASS"
|
@ -469,6 +469,23 @@ void MySQLTest::testBLOBStmt()
|
||||
}
|
||||
|
||||
|
||||
void MySQLTest::testLongBLOB()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
|
||||
recreatePersonLongBLOBTable();
|
||||
_pExecutor->longBlob();
|
||||
}
|
||||
|
||||
void MySQLTest::testJSON()
|
||||
{
|
||||
if (!_pSession) fail("Test not available.");
|
||||
|
||||
recreatePersonJSONTable();
|
||||
_pExecutor->json();
|
||||
}
|
||||
|
||||
|
||||
void MySQLTest::testUnsignedInts()
|
||||
{
|
||||
if (!_pSession) fail ("Test not available.");
|
||||
@ -752,6 +769,24 @@ void MySQLTest::recreatePersonTimeTable()
|
||||
}
|
||||
|
||||
|
||||
void MySQLTest::recreatePersonLongBLOBTable()
|
||||
{
|
||||
dropTable("Person");
|
||||
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Biography LONGTEXT)", now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail ("recreatePersonLongBLOBTable()"); }
|
||||
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail ("recreatePersonLongBLOBTable()"); }
|
||||
}
|
||||
|
||||
|
||||
void MySQLTest::recreatePersonJSONTable()
|
||||
{
|
||||
dropTable("Person");
|
||||
try { *_pSession << "CREATE TABLE Person (LastName VARCHAR(30), FirstName VARCHAR(30), Address VARCHAR(30), Biography JSON)", now; }
|
||||
catch (ConnectionException& ce) { std::cout << ce.displayText() << std::endl; fail("recreatePersonLongBLOBTable()"); }
|
||||
catch (StatementException& se) { std::cout << se.displayText() << std::endl; fail("recreatePersonLongBLOBTable()"); }
|
||||
}
|
||||
|
||||
|
||||
void MySQLTest::recreateIntsTable()
|
||||
{
|
||||
dropTable("Strings");
|
||||
@ -919,6 +954,8 @@ CppUnit::Test* MySQLTest::suite()
|
||||
CppUnit_addTest(pSuite, MySQLTest, testDateTime);
|
||||
//CppUnit_addTest(pSuite, MySQLTest, testBLOB);
|
||||
CppUnit_addTest(pSuite, MySQLTest, testBLOBStmt);
|
||||
CppUnit_addTest(pSuite, MySQLTest, testLongBLOB);
|
||||
CppUnit_addTest(pSuite, MySQLTest, testJSON);
|
||||
CppUnit_addTest(pSuite, MySQLTest, testUnsignedInts);
|
||||
CppUnit_addTest(pSuite, MySQLTest, testFloat);
|
||||
CppUnit_addTest(pSuite, MySQLTest, testDouble);
|
||||
|
@ -79,6 +79,8 @@ public:
|
||||
void testDateTime();
|
||||
void testBLOB();
|
||||
void testBLOBStmt();
|
||||
void testLongBLOB();
|
||||
void testJSON();
|
||||
|
||||
void testUnsignedInts();
|
||||
void testFloat();
|
||||
@ -117,6 +119,8 @@ private:
|
||||
void recreatePersonDateTimeTable();
|
||||
void recreatePersonDateTable();
|
||||
void recreatePersonTimeTable();
|
||||
void recreatePersonLongBLOBTable();
|
||||
void recreatePersonJSONTable();
|
||||
void recreateStringsTable();
|
||||
void recreateIntsTable();
|
||||
void recreateUnsignedIntsTable();
|
||||
|
@ -1435,6 +1435,57 @@ void SQLExecutor::blobStmt()
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::longBlob()
|
||||
{
|
||||
std::string funct = "longBlob()";
|
||||
std::string lastName("lastname");
|
||||
std::string firstName("firstname");
|
||||
std::string address("Address");
|
||||
Poco::Data::CLOB biography("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", 123);
|
||||
|
||||
int count = 0;
|
||||
Statement ins = (*_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(biography));
|
||||
ins.execute();
|
||||
try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
|
||||
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||
assertTrue (count == 1);
|
||||
|
||||
Poco::Data::CLOB res;
|
||||
poco_assert (res.size() == 0);
|
||||
Statement stmt = (*_pSession << "SELECT Biography FROM Person", into(res));
|
||||
try { stmt.execute(); }
|
||||
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
|
||||
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
|
||||
poco_assert (res == biography);
|
||||
}
|
||||
|
||||
void SQLExecutor::json()
|
||||
{
|
||||
std::string funct = "json()";
|
||||
std::string lastName("lastname");
|
||||
std::string firstName("firstname");
|
||||
std::string address("Address");
|
||||
std::string biography(R"({"biography": {"count": 42, "title": "Lorem Ipsum", "released": true}})");
|
||||
|
||||
int count = 0;
|
||||
Statement ins = (*_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(biography));
|
||||
ins.execute();
|
||||
try { *_pSession << "SELECT COUNT(*) FROM Person", into(count), now; }
|
||||
catch (ConnectionException& ce) { std::cout << ce.displayText() << std::endl; fail(funct); }
|
||||
catch (StatementException& se) { std::cout << se.displayText() << std::endl; fail(funct); }
|
||||
assertTrue(count == 1);
|
||||
|
||||
Poco::Data::JSON res;
|
||||
poco_assert(res.size() == 0);
|
||||
Statement stmt = (*_pSession << "SELECT Biography FROM Person", into(res));
|
||||
try { stmt.execute(); }
|
||||
catch (ConnectionException& ce) { std::cout << ce.displayText() << std::endl; fail(funct); }
|
||||
catch (StatementException& se) { std::cout << se.displayText() << std::endl; fail(funct); }
|
||||
poco_assert(res == biography);
|
||||
}
|
||||
|
||||
|
||||
void SQLExecutor::tuples()
|
||||
{
|
||||
typedef Tuple<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int> TupleType;
|
||||
|
@ -83,6 +83,8 @@ public:
|
||||
void dateTime();
|
||||
void date();
|
||||
void time();
|
||||
void longBlob();
|
||||
void json();
|
||||
void unsignedInts();
|
||||
void floats();
|
||||
void doubles();
|
||||
|
@ -25,7 +25,7 @@ target_link_libraries(DataODBC PUBLIC Poco::Data ODBC::ODBC)
|
||||
target_include_directories(DataODBC
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
target_compile_definitions(DataODBC PUBLIC THREADSAFE)
|
||||
|
@ -25,7 +25,7 @@ target_link_libraries(DataPostgreSQL PUBLIC Poco::Data PostgreSQL::client)
|
||||
target_include_directories(DataPostgreSQL
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
@ -38,7 +38,7 @@ target_link_libraries(DataSQLite PUBLIC Poco::Data)
|
||||
target_include_directories(DataSQLite
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
|
43
Data/SQLite/testsuite/src/SQLiteTest.cpp
Normal file → Executable file
43
Data/SQLite/testsuite/src/SQLiteTest.cpp
Normal file → Executable file
@ -55,6 +55,7 @@ using Poco::Data::SQLChannel;
|
||||
using Poco::Data::LimitException;
|
||||
using Poco::Data::ConnectionFailedException;
|
||||
using Poco::Data::CLOB;
|
||||
using Poco::Data::BLOB;
|
||||
using Poco::Data::Date;
|
||||
using Poco::Data::Time;
|
||||
using Poco::Data::Transaction;
|
||||
@ -1419,6 +1420,47 @@ void SQLiteTest::testCLOB()
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testBLOB()
|
||||
{
|
||||
std::string lastName("lastname");
|
||||
std::string firstName("firstname");
|
||||
std::string address("Address");
|
||||
Session tmp(Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
tmp << "DROP TABLE IF EXISTS Person", now;
|
||||
tmp << "CREATE TABLE IF NOT EXISTS Person (LastName VARCHAR(30), FirstName VARCHAR, Address VARCHAR, Image BLOB)", now;
|
||||
typedef struct
|
||||
{
|
||||
int i = 0;
|
||||
Poco::Int64 i64 = 1;
|
||||
float f = 2.5;
|
||||
double d = 3.5;
|
||||
char c[16] = {0};
|
||||
} DataStruct;
|
||||
DataStruct ds;
|
||||
strcpy(ds.c, "123456789ABCDEF");
|
||||
BLOB img(reinterpret_cast<unsigned char*>(&ds), sizeof(ds));
|
||||
assertTrue(img.size() == sizeof(ds));
|
||||
int count = 0;
|
||||
tmp << "INSERT INTO PERSON VALUES(:ln, :fn, :ad, :img)", use(lastName), use(firstName), use(address), use(img), now;
|
||||
tmp << "SELECT COUNT(*) FROM PERSON", into(count), now;
|
||||
assertTrue(count == 1);
|
||||
BLOB res;
|
||||
assertTrue(res.size() == 0);
|
||||
|
||||
tmp << "SELECT Image FROM Person WHERE LastName == :ln", bind("lastname"), into(res), now;
|
||||
assertTrue(res.size() == img.size());
|
||||
assertTrue(0 == std::memcmp(res.rawContent(), img.rawContent(), sizeof(img)));
|
||||
assertTrue(0 == std::memcmp(res.rawContent(), &ds, sizeof(ds)));
|
||||
DataStruct dsCopy;
|
||||
std::memcpy(&dsCopy, res.rawContent(), sizeof(dsCopy));
|
||||
assertTrue(ds.i == dsCopy.i);
|
||||
assertTrue(ds.i64 == dsCopy.i64);
|
||||
assertTrue(ds.f == dsCopy.f);
|
||||
assertTrue(ds.d == dsCopy.d);
|
||||
assertTrue(std::string(ds.c) == std::string(dsCopy.c));
|
||||
}
|
||||
|
||||
|
||||
void SQLiteTest::testTuple10()
|
||||
{
|
||||
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db");
|
||||
@ -3448,6 +3490,7 @@ CppUnit::Test* SQLiteTest::suite()
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testSingleSelect);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testEmptyDB);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testCLOB);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testBLOB);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testTuple10);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testTupleVector10);
|
||||
CppUnit_addTest(pSuite, SQLiteTest, testTuple9);
|
||||
|
1
Data/SQLite/testsuite/src/SQLiteTest.h
Normal file → Executable file
1
Data/SQLite/testsuite/src/SQLiteTest.h
Normal file → Executable file
@ -76,6 +76,7 @@ public:
|
||||
void testEmptyDB();
|
||||
|
||||
void testCLOB();
|
||||
void testBLOB();
|
||||
|
||||
void testTuple1();
|
||||
void testTupleVector1();
|
||||
|
@ -363,9 +363,12 @@ protected:
|
||||
bool transcodeRequired() const;
|
||||
void transcode(const std::string& from, std::string& to);
|
||||
void reverseTranscode(const std::string& from, std::string& to);
|
||||
const std::string& toString(const UUID& uuid);
|
||||
|
||||
private:
|
||||
using StringList = std::vector<std::string*>;
|
||||
std::unique_ptr<Transcoder> _pTranscoder;
|
||||
std::unique_ptr<StringList> _pStrings;
|
||||
};
|
||||
|
||||
|
||||
|
@ -221,7 +221,7 @@ private:
|
||||
|
||||
using BLOB = LOB<unsigned char>;
|
||||
using CLOB = LOB<char>;
|
||||
|
||||
using JSON = std::string;
|
||||
|
||||
//
|
||||
// inlines
|
||||
|
@ -51,6 +51,7 @@ public:
|
||||
FDT_TIME,
|
||||
FDT_TIMESTAMP,
|
||||
FDT_UUID,
|
||||
FDT_JSON,
|
||||
FDT_UNKNOWN
|
||||
};
|
||||
|
||||
|
@ -36,6 +36,11 @@ AbstractBinder::AbstractBinder(Poco::TextEncoding::Ptr pFromEncoding,
|
||||
|
||||
AbstractBinder::~AbstractBinder()
|
||||
{
|
||||
if (_pStrings)
|
||||
{
|
||||
for (auto& s : *_pStrings)
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -53,6 +58,14 @@ void AbstractBinder::reverseTranscode(const std::string& from, std::string& to)
|
||||
}
|
||||
|
||||
|
||||
const std::string& AbstractBinder::toString(const UUID& uuid)
|
||||
{
|
||||
if (!_pStrings) _pStrings.reset(new StringList);
|
||||
_pStrings->push_back(new std::string(uuid.toString()));
|
||||
return *_pStrings->back();
|
||||
}
|
||||
|
||||
|
||||
void AbstractBinder::bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir)
|
||||
{
|
||||
throw NotImplementedException("std::vector binder must be implemented.");
|
||||
|
@ -160,6 +160,7 @@ Poco::Dynamic::Var RecordSet::value(std::size_t col, std::size_t row, bool useFi
|
||||
case MetaColumn::FDT_TIME: return value<Time>(col, row, useFilter);
|
||||
case MetaColumn::FDT_TIMESTAMP: return value<DateTime>(col, row);
|
||||
case MetaColumn::FDT_UUID: return value<UUID>(col, row);
|
||||
case MetaColumn::FDT_JSON: return value<std::string>(col, row, useFilter);
|
||||
default:
|
||||
throw UnknownTypeException("Data type not supported.");
|
||||
}
|
||||
|
@ -353,6 +353,8 @@ void StatementImpl::makeExtractors(std::size_t count)
|
||||
addInternalExtract<DateTime>(mc); break;
|
||||
case MetaColumn::FDT_UUID:
|
||||
addInternalExtract<UUID>(mc); break;
|
||||
case MetaColumn::FDT_JSON:
|
||||
addInternalExtract<std::string>(mc); break;
|
||||
default:
|
||||
throw Poco::InvalidArgumentException("Data type not supported.");
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ target_link_libraries(Encodings PUBLIC Poco::Foundation)
|
||||
target_include_directories(Encodings
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
|
@ -108,7 +108,7 @@ endif(POCO_UNBUNDLED)
|
||||
target_include_directories(Foundation
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
@ -137,6 +137,9 @@ endif()
|
||||
|
||||
if(WIN32)
|
||||
target_compile_definitions(Foundation PUBLIC POCO_OS_FAMILY_WINDOWS UNICODE _UNICODE)
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
target_compile_definitions(Foundation PUBLIC POCO_NO_AUTOMATIC_LIBS)
|
||||
endif()
|
||||
target_link_libraries(Foundation PUBLIC iphlpapi)
|
||||
endif()
|
||||
|
||||
|
@ -55,7 +55,6 @@
|
||||
<ProjectGuid>{B01196CC-B693-4548-8464-2FF60499E73F}</ProjectGuid>
|
||||
<RootNamespace>Foundation</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">
|
||||
|
@ -55,7 +55,6 @@
|
||||
<ProjectGuid>{B01196CC-B693-4548-8464-2FF60499E73F}</ProjectGuid>
|
||||
<RootNamespace>Foundation</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">
|
||||
|
0
Foundation/include/Poco/AbstractObserver.h
Normal file → Executable file
0
Foundation/include/Poco/AbstractObserver.h
Normal file → Executable file
@ -142,6 +142,21 @@
|
||||
// #define POCO_NET_NO_IPv6
|
||||
|
||||
|
||||
// No UNIX socket support
|
||||
// Define to disable unix sockets
|
||||
// #define POCO_NET_NO_UNIX_SOCKET
|
||||
|
||||
|
||||
// Define to nonzero to enable move
|
||||
// semantics on classes where it
|
||||
// introduces a new state.
|
||||
// For explanation, see
|
||||
// https://github.com/pocoproject/poco/wiki/Move-Semantics-in-POCO
|
||||
#ifndef POCO_NEW_STATE_ON_MOVE
|
||||
#define POCO_NEW_STATE_ON_MOVE 1
|
||||
#endif
|
||||
|
||||
|
||||
// Windows CE has no locale support
|
||||
#if defined(_WIN32_WCE)
|
||||
#define POCO_NO_LOCALE
|
||||
|
@ -10,6 +10,9 @@
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// hashRange Copyright 2005-2014 Daniel James.
|
||||
// (Extracted from Boost 1.75.0 lib and adapted for poco on 2021-03-31)
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
@ -19,9 +22,17 @@
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include "Poco/Types.h"
|
||||
#include <cstddef>
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define POCO_HASH_ROTL32(x, r) _rotl(x,r)
|
||||
#else
|
||||
# define POCO_HASH_ROTL32(x, r) (x << r) | (x >> (32 - r))
|
||||
#endif
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
@ -99,6 +110,90 @@ inline std::size_t hash(UInt64 n)
|
||||
}
|
||||
|
||||
|
||||
namespace Impl {
|
||||
|
||||
|
||||
template <typename SizeT>
|
||||
inline void hashCombine(SizeT& seed, SizeT value)
|
||||
{
|
||||
seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
}
|
||||
|
||||
|
||||
inline void hashCombine(Poco::UInt32& h1, Poco::UInt32 k1)
|
||||
{
|
||||
const uint32_t c1 = 0xcc9e2d51;
|
||||
const uint32_t c2 = 0x1b873593;
|
||||
|
||||
k1 *= c1;
|
||||
k1 = POCO_HASH_ROTL32(k1,15);
|
||||
k1 *= c2;
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = POCO_HASH_ROTL32(h1,13);
|
||||
h1 = h1*5+0xe6546b64;
|
||||
}
|
||||
|
||||
|
||||
#if defined(POCO_PTR_IS_64_BIT) && !(defined(__GNUC__) && ULONG_MAX == 0xffffffff)
|
||||
|
||||
|
||||
inline void hashCombine(Poco::UInt64& h, Poco::UInt64 k)
|
||||
{
|
||||
const Poco::UInt64 m = UINT64_C(0xc6a4a7935bd1e995);
|
||||
const int r = 47;
|
||||
|
||||
k *= m;
|
||||
k ^= k >> r;
|
||||
k *= m;
|
||||
|
||||
h ^= k;
|
||||
h *= m;
|
||||
|
||||
// Completely arbitrary number, to
|
||||
// prevent zeros from hashing to 0.
|
||||
h += 0xe6546b64;
|
||||
}
|
||||
|
||||
|
||||
#endif // POCO_PTR_IS_64_BIT
|
||||
|
||||
|
||||
} // namespace Impl
|
||||
|
||||
|
||||
template <class T>
|
||||
inline void hashCombine(std::size_t& seed, T const& v)
|
||||
{
|
||||
Hash<T> hasher;
|
||||
Impl::hashCombine(seed, hasher(v));
|
||||
}
|
||||
|
||||
|
||||
template <class It>
|
||||
inline std::size_t hashRange(It first, It last)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
hashCombine<typename std::iterator_traits<It>::value_type>(seed, *first);
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
template <class It>
|
||||
inline void hashRange(std::size_t& seed, It first, It last)
|
||||
{
|
||||
for(; first != last; ++first)
|
||||
{
|
||||
hashCombine<typename std::iterator_traits<It>::value_type>(seed, *first);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
|
0
Foundation/include/Poco/NObserver.h
Normal file → Executable file
0
Foundation/include/Poco/NObserver.h
Normal file → Executable file
0
Foundation/include/Poco/Observer.h
Normal file → Executable file
0
Foundation/include/Poco/Observer.h
Normal file → Executable file
@ -35,7 +35,7 @@
|
||||
#error Inconsistent build settings (check for /MD[d])
|
||||
#endif
|
||||
|
||||
|
||||
// https://en.wikipedia.org/wiki/Microsoft_Visual_C++
|
||||
#if (_MSC_VER >= 1300) && (_MSC_VER < 1400) // Visual Studio 2003, MSVC++ 7.1
|
||||
#define POCO_MSVS_VERSION 2003
|
||||
#define POCO_MSVC_VERSION 71
|
||||
@ -57,9 +57,15 @@
|
||||
#elif (_MSC_VER >= 1900) && (_MSC_VER < 1910) // Visual Studio 2015, MSVC++ 14.0
|
||||
#define POCO_MSVS_VERSION 2015
|
||||
#define POCO_MSVC_VERSION 140
|
||||
#elif (_MSC_VER >= 1910) && (_MSC_VER < 2000) // Visual Studio 2017, MSVC++ 14.1
|
||||
#elif (_MSC_VER >= 1910) && (_MSC_VER < 1920) // Visual Studio 2017, MSVC++ 14.1
|
||||
#define POCO_MSVS_VERSION 2017
|
||||
#define POCO_MSVC_VERSION 141
|
||||
#elif (_MSC_VER >= 1920) && (_MSC_VER < 1930) // Visual Studio 2019, MSVC++ 14.2
|
||||
#define POCO_MSVS_VERSION 2019
|
||||
#define POCO_MSVC_VERSION 142
|
||||
#elif (_MSC_VER >= 1930) // Visual Studio 2022, MSVC++ 14.3
|
||||
#define POCO_MSVS_VERSION 2022
|
||||
#define POCO_MSVC_VERSION 143
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -55,7 +55,6 @@
|
||||
<ProjectGuid>{6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}</ProjectGuid>
|
||||
<RootNamespace>TestApp</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'" Label="Configuration">
|
||||
|
@ -55,7 +55,6 @@
|
||||
<ProjectGuid>{6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}</ProjectGuid>
|
||||
<RootNamespace>TestApp</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'" Label="Configuration">
|
||||
|
@ -22,7 +22,6 @@
|
||||
<ProjectName>TestLibrary</ProjectName>
|
||||
<ProjectGuid>{0955EB03-544B-4BD4-9C10-89CF38078F5F}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'" Label="Configuration">
|
||||
|
@ -22,7 +22,6 @@
|
||||
<ProjectName>TestLibrary</ProjectName>
|
||||
<ProjectGuid>{0955EB03-544B-4BD4-9C10-89CF38078F5F}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'" Label="Configuration">
|
||||
|
@ -55,7 +55,6 @@
|
||||
<ProjectGuid>{F1EE93DF-347F-4CB3-B191-C4E63F38E972}</ProjectGuid>
|
||||
<RootNamespace>TestSuite</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">
|
||||
|
@ -55,7 +55,6 @@
|
||||
<ProjectGuid>{F1EE93DF-347F-4CB3-B191-C4E63F38E972}</ProjectGuid>
|
||||
<RootNamespace>TestSuite</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">
|
||||
|
@ -26,7 +26,7 @@ target_link_libraries(JSON PUBLIC Poco::Foundation)
|
||||
target_include_directories(JSON
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
|
@ -25,7 +25,7 @@ target_link_libraries(JWT PUBLIC Poco::JSON Poco::Crypto)
|
||||
target_include_directories(JWT
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
|
@ -25,7 +25,7 @@ target_link_libraries(MongoDB PUBLIC Poco::Net)
|
||||
target_include_directories(MongoDB
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
|
@ -35,7 +35,7 @@ endif(WIN32)
|
||||
target_include_directories(Net
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
|
@ -24,7 +24,7 @@ objects = \
|
||||
HTTPRequestHandlerFactory HTTPStreamFactory ServerSocketImpl TCPServerParams \
|
||||
QuotedPrintableEncoder QuotedPrintableDecoder StringPartSource \
|
||||
FTPClientSession FTPStreamFactory PartHandler PartSource PartStore NullPartHandler \
|
||||
SocketReactor SocketNotifier SocketNotification AbstractHTTPRequestHandler \
|
||||
SocketReactor SocketProactor SocketNotifier SocketNotification AbstractHTTPRequestHandler \
|
||||
MailRecipient MailMessage MailStream SMTPClientSession POP3ClientSession \
|
||||
RawSocket RawSocketImpl ICMPClient ICMPEventArgs ICMPPacket ICMPPacketImpl \
|
||||
ICMPSocket ICMPSocketImpl ICMPv4PacketImpl \
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="debug_shared|Win32">
|
||||
@ -56,7 +56,7 @@
|
||||
<RootNamespace>Net</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
@ -117,45 +117,45 @@
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
|
||||
<ImportGroup Label="ExtensionSettings"/>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|x64'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|x64'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros"/>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>15.0.28307.799</_ProjectFileVersion>
|
||||
<TargetName Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">PocoNetd</TargetName>
|
||||
@ -235,7 +235,7 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>Default</CompileAs>
|
||||
@ -268,9 +268,9 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat/>
|
||||
<DebugInformationFormat />
|
||||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -299,7 +299,7 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<ProgramDataBaseFileName>..\lib\PocoNetmtd.pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
@ -325,9 +325,9 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat/>
|
||||
<DebugInformationFormat />
|
||||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -347,7 +347,7 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<ProgramDataBaseFileName>..\lib\PocoNetmdd.pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
@ -373,10 +373,10 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<ProgramDataBaseFileName>..\lib\PocoNetmd.pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat/>
|
||||
<DebugInformationFormat />
|
||||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -397,7 +397,7 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>Default</CompileAs>
|
||||
@ -430,9 +430,9 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat/>
|
||||
<DebugInformationFormat />
|
||||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -461,7 +461,7 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<ProgramDataBaseFileName>..\lib64\PocoNetmtd.pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
@ -487,9 +487,9 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat/>
|
||||
<DebugInformationFormat />
|
||||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -509,7 +509,7 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<ProgramDataBaseFileName>..\lib64\PocoNetmdd.pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
@ -535,9 +535,9 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat/>
|
||||
<DebugInformationFormat />
|
||||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -546,122 +546,123 @@
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\Poco\Net\AbstractHTTPRequestHandler.h"/>
|
||||
<ClInclude Include="include\Poco\Net\DatagramSocket.h"/>
|
||||
<ClInclude Include="include\Poco\Net\DatagramSocketImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\DialogSocket.h"/>
|
||||
<ClInclude Include="include\Poco\Net\DNS.h"/>
|
||||
<ClInclude Include="include\Poco\Net\FilePartSource.h"/>
|
||||
<ClInclude Include="include\Poco\Net\FTPClientSession.h"/>
|
||||
<ClInclude Include="include\Poco\Net\FTPStreamFactory.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HostEntry.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTMLForm.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPAuthenticationParams.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPBasicCredentials.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPBasicStreamBuf.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPBufferAllocator.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPChunkedStream.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPClientSession.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPCookie.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPCredentials.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPDigestCredentials.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPFixedLengthStream.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPHeaderStream.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPIOStream.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPMessage.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPNTLMCredentials.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPRequest.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPRequestHandler.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPRequestHandlerFactory.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPResponse.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPServer.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerConnection.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerConnectionFactory.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerParams.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerRequest.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerRequestImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerResponse.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerResponseImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerSession.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPSession.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPSessionFactory.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPSessionInstantiator.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPStream.h"/>
|
||||
<ClInclude Include="include\Poco\Net\HTTPStreamFactory.h"/>
|
||||
<ClInclude Include="include\Poco\Net\ICMPClient.h"/>
|
||||
<ClInclude Include="include\Poco\Net\ICMPEventArgs.h"/>
|
||||
<ClInclude Include="include\Poco\Net\ICMPPacket.h"/>
|
||||
<ClInclude Include="include\Poco\Net\ICMPPacketImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\ICMPSocket.h"/>
|
||||
<ClInclude Include="include\Poco\Net\ICMPSocketImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\ICMPv4PacketImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\IPAddress.h"/>
|
||||
<ClInclude Include="include\Poco\Net\IPAddressImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\MailMessage.h"/>
|
||||
<ClInclude Include="include\Poco\Net\MailRecipient.h"/>
|
||||
<ClInclude Include="include\Poco\Net\MailStream.h"/>
|
||||
<ClInclude Include="include\Poco\Net\MediaType.h"/>
|
||||
<ClInclude Include="include\Poco\Net\MessageHeader.h"/>
|
||||
<ClInclude Include="include\Poco\Net\MulticastSocket.h"/>
|
||||
<ClInclude Include="include\Poco\Net\MultipartReader.h"/>
|
||||
<ClInclude Include="include\Poco\Net\MultipartWriter.h"/>
|
||||
<ClInclude Include="include\Poco\Net\MultiSocketPoller.h"/>
|
||||
<ClInclude Include="include\Poco\Net\NameValueCollection.h"/>
|
||||
<ClInclude Include="include\Poco\Net\Net.h"/>
|
||||
<ClInclude Include="include\Poco\Net\NetException.h"/>
|
||||
<ClInclude Include="include\Poco\Net\NetworkInterface.h"/>
|
||||
<ClInclude Include="include\Poco\Net\NTLMCredentials.h"/>
|
||||
<ClInclude Include="include\Poco\Net\NTPClient.h"/>
|
||||
<ClInclude Include="include\Poco\Net\NTPEventArgs.h"/>
|
||||
<ClInclude Include="include\Poco\Net\NTPPacket.h"/>
|
||||
<ClInclude Include="include\Poco\Net\NullPartHandler.h"/>
|
||||
<ClInclude Include="include\Poco\Net\OAuth10Credentials.h"/>
|
||||
<ClInclude Include="include\Poco\Net\OAuth20Credentials.h"/>
|
||||
<ClInclude Include="include\Poco\Net\ParallelSocketAcceptor.h"/>
|
||||
<ClInclude Include="include\Poco\Net\ParallelSocketReactor.h"/>
|
||||
<ClInclude Include="include\Poco\Net\PartHandler.h"/>
|
||||
<ClInclude Include="include\Poco\Net\PartSource.h"/>
|
||||
<ClInclude Include="include\Poco\Net\PartStore.h"/>
|
||||
<ClInclude Include="include\Poco\Net\PollSet.h"/>
|
||||
<ClInclude Include="include\Poco\Net\POP3ClientSession.h"/>
|
||||
<ClInclude Include="include\Poco\Net\QuotedPrintableDecoder.h"/>
|
||||
<ClInclude Include="include\Poco\Net\QuotedPrintableEncoder.h"/>
|
||||
<ClInclude Include="include\Poco\Net\RawSocket.h"/>
|
||||
<ClInclude Include="include\Poco\Net\RawSocketImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\RemoteSyslogChannel.h"/>
|
||||
<ClInclude Include="include\Poco\Net\RemoteSyslogListener.h"/>
|
||||
<ClInclude Include="include\Poco\Net\ServerSocket.h"/>
|
||||
<ClInclude Include="include\Poco\Net\ServerSocketImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SingleSocketPoller.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SMTPChannel.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SMTPClientSession.h"/>
|
||||
<ClInclude Include="include\Poco\Net\Socket.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SocketAcceptor.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SocketAddress.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SocketAddressImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SocketConnector.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SocketDefs.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SocketImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SocketNotification.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SocketNotifier.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SocketReactor.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SocketStream.h"/>
|
||||
<ClInclude Include="include\Poco\Net\SSPINTLMCredentials.h"/>
|
||||
<ClInclude Include="include\Poco\Net\StreamSocket.h"/>
|
||||
<ClInclude Include="include\Poco\Net\StreamSocketImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\StringPartSource.h"/>
|
||||
<ClInclude Include="include\Poco\Net\TCPServer.h"/>
|
||||
<ClInclude Include="include\Poco\Net\TCPServerConnection.h"/>
|
||||
<ClInclude Include="include\Poco\Net\TCPServerConnectionFactory.h"/>
|
||||
<ClInclude Include="include\Poco\Net\TCPServerDispatcher.h"/>
|
||||
<ClInclude Include="include\Poco\Net\TCPServerParams.h"/>
|
||||
<ClInclude Include="include\Poco\Net\UDPClient.h"/>
|
||||
<ClInclude Include="include\Poco\Net\UDPHandler.h"/>
|
||||
<ClInclude Include="include\Poco\Net\UDPServer.h"/>
|
||||
<ClInclude Include="include\Poco\Net\UDPServerParams.h"/>
|
||||
<ClInclude Include="include\Poco\Net\UDPSocketReader.h"/>
|
||||
<ClInclude Include="include\Poco\Net\WebSocket.h"/>
|
||||
<ClInclude Include="include\Poco\Net\WebSocketImpl.h"/>
|
||||
<ClInclude Include="include\Poco\Net\AbstractHTTPRequestHandler.h" />
|
||||
<ClInclude Include="include\Poco\Net\DatagramSocket.h" />
|
||||
<ClInclude Include="include\Poco\Net\DatagramSocketImpl.h" />
|
||||
<ClInclude Include="include\Poco\Net\DialogSocket.h" />
|
||||
<ClInclude Include="include\Poco\Net\DNS.h" />
|
||||
<ClInclude Include="include\Poco\Net\FilePartSource.h" />
|
||||
<ClInclude Include="include\Poco\Net\FTPClientSession.h" />
|
||||
<ClInclude Include="include\Poco\Net\FTPStreamFactory.h" />
|
||||
<ClInclude Include="include\Poco\Net\HostEntry.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTMLForm.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPAuthenticationParams.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPBasicCredentials.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPBasicStreamBuf.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPBufferAllocator.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPChunkedStream.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPClientSession.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPCookie.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPCredentials.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPDigestCredentials.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPFixedLengthStream.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPHeaderStream.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPIOStream.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPMessage.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPNTLMCredentials.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPRequest.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPRequestHandler.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPRequestHandlerFactory.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPResponse.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPServer.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerConnection.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerConnectionFactory.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerParams.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerRequest.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerRequestImpl.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerResponse.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerResponseImpl.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPServerSession.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPSession.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPSessionFactory.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPSessionInstantiator.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPStream.h" />
|
||||
<ClInclude Include="include\Poco\Net\HTTPStreamFactory.h" />
|
||||
<ClInclude Include="include\Poco\Net\ICMPClient.h" />
|
||||
<ClInclude Include="include\Poco\Net\ICMPEventArgs.h" />
|
||||
<ClInclude Include="include\Poco\Net\ICMPPacket.h" />
|
||||
<ClInclude Include="include\Poco\Net\ICMPPacketImpl.h" />
|
||||
<ClInclude Include="include\Poco\Net\ICMPSocket.h" />
|
||||
<ClInclude Include="include\Poco\Net\ICMPSocketImpl.h" />
|
||||
<ClInclude Include="include\Poco\Net\ICMPv4PacketImpl.h" />
|
||||
<ClInclude Include="include\Poco\Net\IPAddress.h" />
|
||||
<ClInclude Include="include\Poco\Net\IPAddressImpl.h" />
|
||||
<ClInclude Include="include\Poco\Net\MailMessage.h" />
|
||||
<ClInclude Include="include\Poco\Net\MailRecipient.h" />
|
||||
<ClInclude Include="include\Poco\Net\MailStream.h" />
|
||||
<ClInclude Include="include\Poco\Net\MediaType.h" />
|
||||
<ClInclude Include="include\Poco\Net\MessageHeader.h" />
|
||||
<ClInclude Include="include\Poco\Net\MulticastSocket.h" />
|
||||
<ClInclude Include="include\Poco\Net\MultipartReader.h" />
|
||||
<ClInclude Include="include\Poco\Net\MultipartWriter.h" />
|
||||
<ClInclude Include="include\Poco\Net\MultiSocketPoller.h" />
|
||||
<ClInclude Include="include\Poco\Net\NameValueCollection.h" />
|
||||
<ClInclude Include="include\Poco\Net\Net.h" />
|
||||
<ClInclude Include="include\Poco\Net\NetException.h" />
|
||||
<ClInclude Include="include\Poco\Net\NetworkInterface.h" />
|
||||
<ClInclude Include="include\Poco\Net\NTLMCredentials.h" />
|
||||
<ClInclude Include="include\Poco\Net\NTPClient.h" />
|
||||
<ClInclude Include="include\Poco\Net\NTPEventArgs.h" />
|
||||
<ClInclude Include="include\Poco\Net\NTPPacket.h" />
|
||||
<ClInclude Include="include\Poco\Net\NullPartHandler.h" />
|
||||
<ClInclude Include="include\Poco\Net\OAuth10Credentials.h" />
|
||||
<ClInclude Include="include\Poco\Net\OAuth20Credentials.h" />
|
||||
<ClInclude Include="include\Poco\Net\ParallelSocketAcceptor.h" />
|
||||
<ClInclude Include="include\Poco\Net\ParallelSocketReactor.h" />
|
||||
<ClInclude Include="include\Poco\Net\PartHandler.h" />
|
||||
<ClInclude Include="include\Poco\Net\PartSource.h" />
|
||||
<ClInclude Include="include\Poco\Net\PartStore.h" />
|
||||
<ClInclude Include="include\Poco\Net\PollSet.h" />
|
||||
<ClInclude Include="include\Poco\Net\POP3ClientSession.h" />
|
||||
<ClInclude Include="include\Poco\Net\QuotedPrintableDecoder.h" />
|
||||
<ClInclude Include="include\Poco\Net\QuotedPrintableEncoder.h" />
|
||||
<ClInclude Include="include\Poco\Net\RawSocket.h" />
|
||||
<ClInclude Include="include\Poco\Net\RawSocketImpl.h" />
|
||||
<ClInclude Include="include\Poco\Net\RemoteSyslogChannel.h" />
|
||||
<ClInclude Include="include\Poco\Net\RemoteSyslogListener.h" />
|
||||
<ClInclude Include="include\Poco\Net\ServerSocket.h" />
|
||||
<ClInclude Include="include\Poco\Net\ServerSocketImpl.h" />
|
||||
<ClInclude Include="include\Poco\Net\SingleSocketPoller.h" />
|
||||
<ClInclude Include="include\Poco\Net\SMTPChannel.h" />
|
||||
<ClInclude Include="include\Poco\Net\SMTPClientSession.h" />
|
||||
<ClInclude Include="include\Poco\Net\Socket.h" />
|
||||
<ClInclude Include="include\Poco\Net\SocketAcceptor.h" />
|
||||
<ClInclude Include="include\Poco\Net\SocketAddress.h" />
|
||||
<ClInclude Include="include\Poco\Net\SocketAddressImpl.h" />
|
||||
<ClInclude Include="include\Poco\Net\SocketConnector.h" />
|
||||
<ClInclude Include="include\Poco\Net\SocketDefs.h" />
|
||||
<ClInclude Include="include\Poco\Net\SocketImpl.h" />
|
||||
<ClInclude Include="include\Poco\Net\SocketNotification.h" />
|
||||
<ClInclude Include="include\Poco\Net\SocketNotifier.h" />
|
||||
<ClInclude Include="include\Poco\Net\SocketProactor.h" />
|
||||
<ClInclude Include="include\Poco\Net\SocketReactor.h" />
|
||||
<ClInclude Include="include\Poco\Net\SocketStream.h" />
|
||||
<ClInclude Include="include\Poco\Net\SSPINTLMCredentials.h" />
|
||||
<ClInclude Include="include\Poco\Net\StreamSocket.h" />
|
||||
<ClInclude Include="include\Poco\Net\StreamSocketImpl.h" />
|
||||
<ClInclude Include="include\Poco\Net\StringPartSource.h" />
|
||||
<ClInclude Include="include\Poco\Net\TCPServer.h" />
|
||||
<ClInclude Include="include\Poco\Net\TCPServerConnection.h" />
|
||||
<ClInclude Include="include\Poco\Net\TCPServerConnectionFactory.h" />
|
||||
<ClInclude Include="include\Poco\Net\TCPServerDispatcher.h" />
|
||||
<ClInclude Include="include\Poco\Net\TCPServerParams.h" />
|
||||
<ClInclude Include="include\Poco\Net\UDPClient.h" />
|
||||
<ClInclude Include="include\Poco\Net\UDPHandler.h" />
|
||||
<ClInclude Include="include\Poco\Net\UDPServer.h" />
|
||||
<ClInclude Include="include\Poco\Net\UDPServerParams.h" />
|
||||
<ClInclude Include="include\Poco\Net\UDPSocketReader.h" />
|
||||
<ClInclude Include="include\Poco\Net\WebSocket.h" />
|
||||
<ClInclude Include="include\Poco\Net\WebSocketImpl.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\AbstractHTTPRequestHandler.cpp">
|
||||
@ -934,6 +935,7 @@
|
||||
<ClCompile Include="src\SocketNotifier.cpp">
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SocketProactor.cpp" />
|
||||
<ClCompile Include="src\SocketReactor.cpp">
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -992,6 +994,6 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
||||
<ImportGroup Label="ExtensionTargets"/>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
@ -513,6 +513,9 @@
|
||||
<ClInclude Include="include\Poco\Net\SSPINTLMCredentials.h">
|
||||
<Filter>NTLM\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\Net\SocketProactor.h">
|
||||
<Filter>Sockets\Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\DNS.cpp">
|
||||
@ -830,6 +833,9 @@
|
||||
<ClCompile Include="src\SSPINTLMCredentials.cpp">
|
||||
<Filter>NTLM\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SocketProactor.cpp">
|
||||
<Filter>Sockets\Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\DLLVersion.rc" />
|
||||
|
@ -48,19 +48,14 @@ public:
|
||||
/// The socket will be created for the
|
||||
/// given address family.
|
||||
|
||||
DatagramSocket(const SocketAddress& address, bool reuseAddress = false);
|
||||
/// Creates a datagram socket and binds it
|
||||
/// to the given address.
|
||||
///
|
||||
/// Depending on the address family, the socket
|
||||
/// will be either an IPv4 or an IPv6 socket.
|
||||
|
||||
DatagramSocket(const SocketAddress& address, bool reuseAddress, bool reusePort);
|
||||
DatagramSocket(const SocketAddress& address, bool reuseAddress, bool reusePort = false, bool ipV6Only = false);
|
||||
/// Creates a datagram socket and binds it
|
||||
/// to the given address.
|
||||
///
|
||||
/// Depending on the address family, the socket
|
||||
/// will be either an IPv4 or an IPv6 socket.
|
||||
/// If ipV6Only is true, socket will be bound
|
||||
/// to the IPv6 address only.
|
||||
|
||||
DatagramSocket(const Socket& socket);
|
||||
/// Creates the DatagramSocket with the SocketImpl
|
||||
@ -68,6 +63,10 @@ public:
|
||||
/// a DatagramSocketImpl, otherwise an InvalidArgumentException
|
||||
/// will be thrown.
|
||||
|
||||
DatagramSocket(const DatagramSocket& socket);
|
||||
/// Creates the DatagramSocket with the SocketImpl
|
||||
/// from another socket.
|
||||
|
||||
~DatagramSocket();
|
||||
/// Destroys the DatagramSocket.
|
||||
|
||||
@ -78,6 +77,43 @@ public:
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// increments the reference count of the SocketImpl.
|
||||
|
||||
#if POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
DatagramSocket(Socket&& socket);
|
||||
/// Creates the DatagramSocket with the SocketImpl
|
||||
/// from another socket and zeroes the other socket's
|
||||
/// SocketImpl.The SocketImpl must be
|
||||
/// a DatagramSocketImpl, otherwise an InvalidArgumentException
|
||||
/// will be thrown.
|
||||
|
||||
DatagramSocket(DatagramSocket&& socket);
|
||||
/// Creates the DatagramSocket with the SocketImpl
|
||||
/// from another socket and zeroes the other socket's
|
||||
/// SocketImpl.
|
||||
|
||||
DatagramSocket& operator = (Socket&& socket);
|
||||
/// Assignment move operator.
|
||||
///
|
||||
/// Releases the socket's SocketImpl and
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// zeroes the other socket's SocketImpl.
|
||||
|
||||
DatagramSocket& operator = (DatagramSocket&& socket);
|
||||
/// Assignment move operator.
|
||||
///
|
||||
/// Releases the socket's SocketImpl and
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// zeroes the other socket's SocketImpl.
|
||||
|
||||
#endif // POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
DatagramSocket& operator = (const DatagramSocket& socket);
|
||||
/// Assignment operator.
|
||||
///
|
||||
/// Releases the socket's SocketImpl and
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// increments the reference count of the SocketImpl.
|
||||
|
||||
void connect(const SocketAddress& address);
|
||||
/// Restricts incoming and outgoing
|
||||
/// packets to the specified address.
|
||||
@ -109,6 +145,23 @@ public:
|
||||
///
|
||||
/// Calls to connect cannot() come before calls to bind().
|
||||
|
||||
void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only = false);
|
||||
/// Bind a local address to the socket.
|
||||
///
|
||||
/// This is usually only done when establishing a server
|
||||
/// socket.
|
||||
///
|
||||
/// If reuseAddress is true, sets the SO_REUSEADDR
|
||||
/// socket option.
|
||||
///
|
||||
/// If reusePort is true, sets the SO_REUSEPORT
|
||||
/// socket option.
|
||||
///
|
||||
/// Sets the IPV6_V6ONLY socket option in accordance with
|
||||
/// the supplied ipV6Only value.
|
||||
///
|
||||
/// Calls to connect cannot() come before calls to bind().
|
||||
|
||||
int sendBytes(const void* buffer, int length, int flags = 0);
|
||||
/// Sends the contents of the given buffer through
|
||||
/// the socket.
|
||||
@ -231,7 +284,7 @@ protected:
|
||||
/// Creates the Socket and attaches the given SocketImpl.
|
||||
/// The socket takes ownership of the SocketImpl.
|
||||
///
|
||||
/// The SocketImpl must be a StreamSocketImpl, otherwise
|
||||
/// The SocketImpl must be a DatagramSocketImpl, otherwise
|
||||
/// an InvalidArgumentException will be thrown.
|
||||
};
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <ostream>
|
||||
|
||||
|
||||
@ -56,6 +57,13 @@ class Net_API IPAddress
|
||||
public:
|
||||
using List = std::vector<IPAddress>;
|
||||
|
||||
using RawIP = std::vector<unsigned char>;
|
||||
|
||||
static const unsigned IPv4Size = sizeof(in_addr);
|
||||
static const unsigned IPv6Size = sizeof(in6_addr);
|
||||
using RawIPv4 = std::array<unsigned char, IPv4Size>;
|
||||
using RawIPv6 = std::array<unsigned char, IPv6Size>;
|
||||
|
||||
// The following declarations keep the Family type
|
||||
// backwards compatible with the previously used
|
||||
// enum declaration.
|
||||
@ -71,6 +79,9 @@ public:
|
||||
IPAddress(const IPAddress& addr);
|
||||
/// Creates an IPAddress by copying another one.
|
||||
|
||||
IPAddress(IPAddress&& addr);
|
||||
/// Creates an IPAddress by moving another one.
|
||||
|
||||
explicit IPAddress(Family family);
|
||||
/// Creates a wildcard (zero) IPAddress for the
|
||||
/// given address family.
|
||||
@ -122,6 +133,15 @@ public:
|
||||
IPAddress& operator = (const IPAddress& addr);
|
||||
/// Assigns an IPAddress.
|
||||
|
||||
IPAddress& operator = (IPAddress&& addr);
|
||||
/// Move-assigns an IPAddress.
|
||||
|
||||
bool isV4() const;
|
||||
bool isV6() const;
|
||||
RawIPv4 toV4Bytes() const;
|
||||
RawIPv6 toV6Bytes() const;
|
||||
RawIP toBytes() const;
|
||||
|
||||
Family family() const;
|
||||
/// Returns the address family (IPv4 or IPv6) of the address.
|
||||
|
||||
@ -376,6 +396,8 @@ private:
|
||||
void newIPv6(const void* hostAddr);
|
||||
void newIPv6(const void* hostAddr, Poco::UInt32 scope);
|
||||
void newIPv6(unsigned prefix);
|
||||
static std::string& compressV6(std::string& v6addr);
|
||||
static std::string trimIPv6(const std::string v6Addr);
|
||||
#endif
|
||||
Ptr _pImpl;
|
||||
};
|
||||
@ -384,6 +406,19 @@ private:
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
inline bool IPAddress::isV4() const
|
||||
{
|
||||
return family() == IPv4;
|
||||
}
|
||||
|
||||
|
||||
inline bool IPAddress::isV6() const
|
||||
{
|
||||
return family() == IPv6;
|
||||
}
|
||||
|
||||
|
||||
inline IPAddress::Ptr IPAddress::pImpl() const
|
||||
{
|
||||
if (_pImpl) return _pImpl;
|
||||
|
@ -30,7 +30,7 @@ namespace Net {
|
||||
template <std::size_t S = POCO_UDP_BUF_SIZE>
|
||||
class MultiSocketPoller
|
||||
/// MultiSocketPoller, as its name indicates, repeatedly polls a set of
|
||||
/// sockets for readability and/or eror. If socket is readable or in error
|
||||
/// sockets for readability and/or error. If socket is readable or in error
|
||||
/// state, the reading/error handling actions are delegated to the reader.
|
||||
{
|
||||
public:
|
||||
|
@ -67,6 +67,14 @@
|
||||
#endif // POCO_NET_NO_IPv6, POCO_HAVE_IPv6
|
||||
|
||||
|
||||
// Default to enabled local socket support if not explicitly disabled
|
||||
#if !defined(POCO_NET_NO_UNIX_SOCKET) && !defined (POCO_HAVE_UNIX_SOCKET)
|
||||
#define POCO_HAVE_UNIX_SOCKET
|
||||
#elif defined(POCO_NET_NO_UNIX_SOCKET) && defined (POCO_HAVE_UNIX_SOCKET)
|
||||
#undef POCO_HAVE_UNIX_SOCKET
|
||||
#endif // POCO_NET_NO_UNIX_SOCKET, POCO_HAVE_UNIX_SOCKET
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
@ -124,4 +132,24 @@ POCO_NET_FORCE_SYMBOL(pocoNetworkInitializer)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_BSD)
|
||||
#ifndef POCO_HAVE_FD_POLL
|
||||
#define POCO_HAVE_FD_POLL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#ifndef POCO_HAVE_FD_POLL
|
||||
// WSAPoll wants POLLOUT flag in order to return POLERR when there is no
|
||||
// server on the other side. Windows default is multi-fd_set select, WSAPoll
|
||||
// is disabled and not considered a production-grade code.
|
||||
// see https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsapoll
|
||||
// This is the version where the WSAPoll was (allegedly) fixed.
|
||||
#if defined(WDK_NTDDI_VERSION) && (WDK_NTDDI_VERSION >= NTDDI_WIN10_VB)
|
||||
//#define POCO_HAVE_FD_POLL 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // Net_Net_INCLUDED
|
||||
|
@ -78,6 +78,13 @@ public:
|
||||
/// Returns a PollMap containing the sockets that have had
|
||||
/// their state changed.
|
||||
|
||||
int count() const;
|
||||
/// Returns the numberof sockets monitored.
|
||||
|
||||
void wakeUp();
|
||||
/// Wakes up a waiting PollSet.
|
||||
/// On platforms/implementations where this functionality
|
||||
/// is not available, it does nothing.
|
||||
private:
|
||||
PollSetImpl* _pImpl;
|
||||
|
||||
|
@ -53,6 +53,10 @@ public:
|
||||
/// a RawSocketImpl, otherwise an InvalidArgumentException
|
||||
/// will be thrown.
|
||||
|
||||
RawSocket(const RawSocket& socket);
|
||||
/// Creates the RawSocket with the SocketImpl
|
||||
/// from another socket.
|
||||
|
||||
~RawSocket();
|
||||
/// Destroys the RawSocket.
|
||||
|
||||
@ -63,6 +67,43 @@ public:
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// increments the reference count of the SocketImpl.
|
||||
|
||||
RawSocket& operator = (const RawSocket& socket);
|
||||
/// Assignment operator.
|
||||
///
|
||||
/// Releases the socket's SocketImpl and
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// increments the reference count of the SocketImpl.
|
||||
|
||||
#if POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
RawSocket(Socket&& socket);
|
||||
/// Creates the RawSocket with the SocketImpl
|
||||
/// from another socket and zeroes the other socket's
|
||||
/// SocketImpl.The SocketImpl must be
|
||||
/// a RawSocketImpl, otherwise an InvalidArgumentException
|
||||
/// will be thrown.
|
||||
|
||||
RawSocket(RawSocket&& socket);
|
||||
/// Creates the RawSocket with the SocketImpl
|
||||
/// from another socket and zeroes the other socket's
|
||||
/// SocketImpl.
|
||||
|
||||
RawSocket& operator = (Socket&& socket);
|
||||
/// Assignment move operator.
|
||||
///
|
||||
/// Releases the socket's SocketImpl and
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// zeroes the other socket's SocketImpl.
|
||||
|
||||
RawSocket& operator = (RawSocket&& socket);
|
||||
/// Assignment move operator.
|
||||
///
|
||||
/// Releases the socket's SocketImpl and
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// zeroes the other socket's SocketImpl.
|
||||
|
||||
#endif //POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
void connect(const SocketAddress& address);
|
||||
/// Restricts incoming and outgoing
|
||||
/// packets to the specified address.
|
||||
@ -135,7 +176,7 @@ protected:
|
||||
/// Creates the Socket and attaches the given SocketImpl.
|
||||
/// The socket takes ownership of the SocketImpl.
|
||||
///
|
||||
/// The SocketImpl must be a StreamSocketImpl, otherwise
|
||||
/// The SocketImpl must be a RawSocketImpl, otherwise
|
||||
/// an InvalidArgumentException will be thrown.
|
||||
};
|
||||
|
||||
|
@ -30,7 +30,7 @@ namespace Net {
|
||||
|
||||
template <std::size_t S = POCO_UDP_BUF_SIZE>
|
||||
class SingleSocketPoller
|
||||
/// SinlgeSocketPoller, as its name indicates, repeatedly polls a single
|
||||
/// SingleSocketPoller, as its name indicates, repeatedly polls a single
|
||||
/// socket for readability; if the socket is readable, the reading action
|
||||
/// is delegated to the reader.
|
||||
{
|
||||
|
@ -36,6 +36,8 @@ class Net_API Socket
|
||||
{
|
||||
public:
|
||||
using BufVec = SocketBufVec;
|
||||
using Type = SocketImpl::Type;
|
||||
using SocketList = std::vector<Socket>;
|
||||
|
||||
enum SelectMode
|
||||
/// The mode argument to poll() and select().
|
||||
@ -45,8 +47,6 @@ public:
|
||||
SELECT_ERROR = 4
|
||||
};
|
||||
|
||||
using SocketList = std::vector<Socket>;
|
||||
|
||||
Socket();
|
||||
/// Creates an uninitialized socket.
|
||||
|
||||
@ -63,6 +63,23 @@ public:
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// increments the reference count of the SocketImpl.
|
||||
|
||||
#if POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
Socket(Socket&& socket);
|
||||
/// Move constructor.
|
||||
///
|
||||
/// Attaches the SocketImpl from the other socket and
|
||||
/// zeroes the other socket's SocketImpl.
|
||||
|
||||
Socket& operator = (Socket&& socket);
|
||||
/// Assignment move operator.
|
||||
///
|
||||
/// Releases the socket's SocketImpl,
|
||||
/// attaches the SocketImpl from the other socket,
|
||||
/// and zeroes the other socket's SocketImpl.
|
||||
|
||||
#endif // POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
virtual ~Socket();
|
||||
/// Destroys the Socket and releases the
|
||||
/// SocketImpl.
|
||||
@ -87,6 +104,24 @@ public:
|
||||
bool operator >= (const Socket& socket) const;
|
||||
/// Compares the SocketImpl pointers.
|
||||
|
||||
bool isNull() const;
|
||||
/// Returns true if pointer to implementation is null.
|
||||
|
||||
Type type() const;
|
||||
/// Returns the socket type.
|
||||
|
||||
bool isStream() const;
|
||||
/// Returns true if socket is a stream socket,
|
||||
/// false otherwise.
|
||||
|
||||
bool isDatagram() const;
|
||||
/// Returns true if socket is a datagram socket,
|
||||
/// false otherwise.
|
||||
|
||||
bool isRaw() const;
|
||||
/// Returns true if socket is a raw socket,
|
||||
/// false otherwise.
|
||||
|
||||
void close();
|
||||
/// Closes the socket.
|
||||
|
||||
@ -134,6 +169,9 @@ public:
|
||||
/// Returns the number of bytes available that can be read
|
||||
/// without causing the socket to block.
|
||||
|
||||
int getError() const;
|
||||
/// Returns the socket error.
|
||||
|
||||
void setSendBufferSize(int size);
|
||||
/// Sets the size of the send buffer.
|
||||
|
||||
@ -334,6 +372,12 @@ public:
|
||||
/// of buffers used for writing (ie. reading from socket
|
||||
/// into buffers).
|
||||
|
||||
static int lastError();
|
||||
/// Returns the last error code.
|
||||
|
||||
static void error();
|
||||
/// Throws an appropriate exception for the last error.
|
||||
|
||||
protected:
|
||||
Socket(SocketImpl* pImpl);
|
||||
/// Creates the Socket and attaches the given SocketImpl.
|
||||
@ -403,212 +447,318 @@ inline bool Socket::operator >= (const Socket& socket) const
|
||||
}
|
||||
|
||||
|
||||
inline Socket::Type Socket::type() const
|
||||
{
|
||||
return _pImpl->type();
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket::isStream() const
|
||||
{
|
||||
return type() == Type::SOCKET_TYPE_STREAM;
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket::isDatagram() const
|
||||
{
|
||||
return type() == Type::SOCKET_TYPE_DATAGRAM;
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket::isRaw() const
|
||||
{
|
||||
return type() == Type::SOCKET_TYPE_RAW;
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket::isNull() const
|
||||
{
|
||||
return _pImpl == nullptr;
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::close()
|
||||
{
|
||||
_pImpl->close();
|
||||
if (_pImpl) _pImpl->close();
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket::poll(const Poco::Timespan& timeout, int mode) const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->poll(timeout, mode);
|
||||
}
|
||||
|
||||
|
||||
inline int Socket::available() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->available();
|
||||
}
|
||||
|
||||
|
||||
inline int Socket::getError() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->getError();
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setSendBufferSize(int size)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setSendBufferSize(size);
|
||||
}
|
||||
|
||||
|
||||
inline int Socket::getSendBufferSize() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->getSendBufferSize();
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setReceiveBufferSize(int size)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setReceiveBufferSize(size);
|
||||
}
|
||||
|
||||
|
||||
inline int Socket::getReceiveBufferSize() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->getReceiveBufferSize();
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setSendTimeout(const Poco::Timespan& timeout)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setSendTimeout(timeout);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::Timespan Socket::getSendTimeout() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->getSendTimeout();
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setReceiveTimeout(const Poco::Timespan& timeout)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setReceiveTimeout(timeout);
|
||||
}
|
||||
|
||||
|
||||
inline Poco::Timespan Socket::getReceiveTimeout() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->getReceiveTimeout();
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setOption(int level, int option, int value)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setOption(level, option, value);
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setOption(int level, int option, unsigned value)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setOption(level, option, value);
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setOption(int level, int option, unsigned char value)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setOption(level, option, value);
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setOption(int level, int option, const Poco::Timespan& value)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setOption(level, option, value);
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setOption(int level, int option, const IPAddress& value)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setOption(level, option, value);
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::getOption(int level, int option, int& value) const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->getOption(level, option, value);
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::getOption(int level, int option, unsigned& value) const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->getOption(level, option, value);
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::getOption(int level, int option, unsigned char& value) const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->getOption(level, option, value);
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::getOption(int level, int option, Poco::Timespan& value) const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->getOption(level, option, value);
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::getOption(int level, int option, IPAddress& value) const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->getOption(level, option, value);
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setLinger(bool on, int seconds)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setLinger(on, seconds);
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::getLinger(bool& on, int& seconds) const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->getLinger(on, seconds);
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setNoDelay(bool flag)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setNoDelay(flag);
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket::getNoDelay() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->getNoDelay();
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setKeepAlive(bool flag)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setKeepAlive(flag);
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket::getKeepAlive() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->getKeepAlive();
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setReuseAddress(bool flag)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setReuseAddress(flag);
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket::getReuseAddress() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->getReuseAddress();
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setReusePort(bool flag)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setReusePort(flag);
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket::getReusePort() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->getReusePort();
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setOOBInline(bool flag)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setOOBInline(flag);
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket::getOOBInline() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->getOOBInline();
|
||||
}
|
||||
|
||||
|
||||
inline void Socket::setBlocking(bool flag)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->setBlocking(flag);
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket::getBlocking() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->getBlocking();
|
||||
}
|
||||
|
||||
@ -621,24 +771,32 @@ inline SocketImpl* Socket::impl() const
|
||||
|
||||
inline poco_socket_t Socket::sockfd() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->sockfd();
|
||||
}
|
||||
|
||||
|
||||
inline SocketAddress Socket::address() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->address();
|
||||
}
|
||||
|
||||
|
||||
inline SocketAddress Socket::peerAddress() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->peerAddress();
|
||||
}
|
||||
|
||||
|
||||
inline bool Socket::secure() const
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
return _pImpl->secure();
|
||||
}
|
||||
|
||||
@ -661,6 +819,8 @@ inline bool Socket::supportsIPv6()
|
||||
|
||||
inline void Socket::init(int af)
|
||||
{
|
||||
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
|
||||
|
||||
_pImpl->init(af);
|
||||
}
|
||||
|
||||
|
@ -138,6 +138,9 @@ public:
|
||||
SocketAddress(const SocketAddress& addr);
|
||||
/// Creates a SocketAddress by copying another one.
|
||||
|
||||
SocketAddress(SocketAddress&& addr);
|
||||
/// Creates a SocketAddress by moving another one.
|
||||
|
||||
SocketAddress(const struct sockaddr* addr, poco_socklen_t length);
|
||||
/// Creates a SocketAddress from a native socket address.
|
||||
|
||||
@ -147,6 +150,9 @@ public:
|
||||
SocketAddress& operator = (const SocketAddress& socketAddress);
|
||||
/// Assigns another SocketAddress.
|
||||
|
||||
SocketAddress& operator = (SocketAddress&& socketAddress);
|
||||
/// Move-assigns another SocketAddress.
|
||||
|
||||
IPAddress host() const;
|
||||
/// Returns the host IP address.
|
||||
|
||||
|
@ -82,7 +82,7 @@ public:
|
||||
|
||||
SocketConnector(SocketAddress& address, SocketReactor& reactor, bool doRegister = true) :
|
||||
_pReactor(0)
|
||||
/// Creates an acceptor, using the given ServerSocket.
|
||||
/// Creates an connector, using the given ServerSocket.
|
||||
/// The SocketConnector registers itself with the given SocketReactor.
|
||||
{
|
||||
_socket.connectNB(address);
|
||||
@ -167,6 +167,7 @@ public:
|
||||
unregisterConnector();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual ServiceHandler* createServiceHandler()
|
||||
/// Create and initialize a new ServiceHandler instance.
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#include "Poco/UnWindows.h"
|
||||
#define FD_SETSIZE 1024 // increase as needed
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <ws2def.h>
|
||||
@ -371,16 +372,18 @@ struct AddressFamily
|
||||
enum Family
|
||||
/// Possible address families for socket addresses.
|
||||
{
|
||||
IPv4,
|
||||
UNKNOWN = AF_UNSPEC,
|
||||
/// Unspecified family
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
UNIX_LOCAL = AF_UNIX,
|
||||
/// UNIX domain socket address family. Available on UNIX/POSIX platforms only.
|
||||
#endif
|
||||
IPv4 = AF_INET,
|
||||
/// IPv4 address family.
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
IPv6,
|
||||
IPv6 = AF_INET6
|
||||
/// IPv6 address family.
|
||||
#endif
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
UNIX_LOCAL
|
||||
/// UNIX domain socket address family. Available on UNIX/POSIX platforms only.
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -39,6 +39,13 @@ class Net_API SocketImpl: public Poco::RefCountedObject
|
||||
/// You should not create any instances of this class.
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
SOCKET_TYPE_STREAM = SOCK_STREAM,
|
||||
SOCKET_TYPE_DATAGRAM = SOCK_DGRAM,
|
||||
SOCKET_TYPE_RAW = SOCK_RAW
|
||||
};
|
||||
|
||||
enum SelectMode
|
||||
{
|
||||
SELECT_READ = 1,
|
||||
@ -271,6 +278,12 @@ public:
|
||||
/// Returns true if the next operation corresponding to
|
||||
/// mode will not block, false otherwise.
|
||||
|
||||
Type type();
|
||||
/// Returns the socket type.
|
||||
|
||||
virtual int getError();
|
||||
/// Returns the socket error.
|
||||
|
||||
virtual void setSendBufferSize(int size);
|
||||
/// Sets the size of the send buffer.
|
||||
|
||||
@ -526,6 +539,17 @@ private:
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
inline SocketImpl::Type SocketImpl::type()
|
||||
{
|
||||
int type;
|
||||
getOption(SOL_SOCKET, SO_TYPE, type);
|
||||
poco_assert_dbg(type == SOCK_STREAM ||
|
||||
type == SOCK_DGRAM ||
|
||||
type == SOCK_RAW);
|
||||
return static_cast<Type>(type);
|
||||
}
|
||||
|
||||
|
||||
inline poco_socket_t SocketImpl::sockfd() const
|
||||
{
|
||||
return _sockfd;
|
||||
|
501
Net/include/Poco/Net/SocketProactor.h
Normal file
501
Net/include/Poco/Net/SocketProactor.h
Normal file
@ -0,0 +1,501 @@
|
||||
//
|
||||
// SocketProactor.h
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Sockets
|
||||
// Module: SocketProactor
|
||||
//
|
||||
// Definition of the SocketProactor class.
|
||||
//
|
||||
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef Net_SocketProactor_INCLUDED
|
||||
#define Net_SocketProactor_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Net/Net.h"
|
||||
#include "Poco/Net/Socket.h"
|
||||
#include "Poco/Net/PollSet.h"
|
||||
#include "Poco/Runnable.h"
|
||||
#include "Poco/Timespan.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/Mutex.h"
|
||||
#include "Poco/Activity.h"
|
||||
#include "Poco/NotificationQueue.h"
|
||||
#include "Poco/ErrorHandler.h"
|
||||
#include <unordered_map>
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <deque>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
class Thread;
|
||||
|
||||
|
||||
namespace Net {
|
||||
|
||||
|
||||
class Socket;
|
||||
class Worker;
|
||||
|
||||
|
||||
class Net_API SocketProactor final: public Poco::Runnable
|
||||
/// This class implements the proactor pattern.
|
||||
/// It may also contain a simple work executor (enabled by default),
|
||||
/// which executes submitted workload.
|
||||
{
|
||||
public:
|
||||
using Buffer = std::vector<std::uint8_t>;
|
||||
using Work = std::function<void()>;
|
||||
using Callback = std::function<void (const std::error_code& failure, int bytesReceived)>;
|
||||
|
||||
static const int POLL_READ = PollSet::POLL_READ;
|
||||
static const int POLL_WRITE = PollSet::POLL_WRITE;
|
||||
static const int POLL_ERROR = PollSet::POLL_ERROR;
|
||||
|
||||
static const Timestamp::TimeDiff PERMANENT_COMPLETION_HANDLER;
|
||||
|
||||
explicit SocketProactor(bool worker = true);
|
||||
/// Creates the SocketProactor.
|
||||
|
||||
explicit SocketProactor(const Poco::Timespan& timeout, bool worker = true);
|
||||
/// Creates the SocketProactor, using the given timeout.
|
||||
|
||||
SocketProactor(const SocketProactor&) = delete;
|
||||
SocketProactor(SocketProactor&&) = delete;
|
||||
SocketProactor& operator=(const SocketProactor&) = delete;
|
||||
SocketProactor& operator=(SocketProactor&&) = delete;
|
||||
|
||||
~SocketProactor();
|
||||
/// Destroys the SocketProactor.
|
||||
|
||||
void addWork(const Work& ch, Timestamp::TimeDiff ms = PERMANENT_COMPLETION_HANDLER);
|
||||
/// Adds work to be executed after the next poll() completion.
|
||||
/// Function will be called until the specified expiration,
|
||||
/// which defaults to immediately, ie. expiration after the
|
||||
/// first invocation.
|
||||
|
||||
void addWork(Work&& ch, Timestamp::TimeDiff ms = PERMANENT_COMPLETION_HANDLER, int pos = -1);
|
||||
/// Adds work to be executed after the next poll() completion.
|
||||
/// Function will be called until the specified expiration,
|
||||
/// which defaults to immediately, ie. expiration after the
|
||||
/// first invocation.
|
||||
|
||||
void removeWork();
|
||||
/// Removes all scheduled work.
|
||||
|
||||
int scheduledWork();
|
||||
/// Returns the number of scheduled functions.
|
||||
|
||||
int removeScheduledWork(int count = -1);
|
||||
/// Removes the count scheduled functions
|
||||
/// from the front of the schedule queue.
|
||||
/// Default is removal of all scheduled functions.
|
||||
|
||||
int permanentWork();
|
||||
/// Returns the number of permanent functions.
|
||||
|
||||
int removePermanentWork(int count = -1);
|
||||
/// Removes the count permanent functions
|
||||
/// from the front of the schedule queue.
|
||||
/// Default is removal of all functions.
|
||||
|
||||
int poll(int* pHandled = 0);
|
||||
/// Polls all registered sockets and calls their respective handlers.
|
||||
/// If pHandled is not null, after the call it contains the total number
|
||||
/// of read/write/error socket handlers called.
|
||||
/// Returns the number of completion handlers invoked.
|
||||
|
||||
int runOne();
|
||||
/// Runs one handler, scheduled or permanent.
|
||||
/// If there are no available handlers, it blocks
|
||||
/// until the first handler is encountered and executed.
|
||||
/// Returns 1 on successful handler invocation, 0 on
|
||||
/// exception.
|
||||
|
||||
void run();
|
||||
/// Runs the SocketProactor. The reactor will run
|
||||
/// until stop() is called (in a separate thread).
|
||||
|
||||
void stop();
|
||||
/// Stops the SocketProactor.
|
||||
///
|
||||
/// The proactor will be stopped when the next event
|
||||
/// (including a timeout event) occurs.
|
||||
|
||||
void wakeUp();
|
||||
/// Wakes up idle reactor.
|
||||
|
||||
void wait();
|
||||
/// Blocks and waits for the scheduled I/O completion
|
||||
/// handlers loop to end.
|
||||
|
||||
void setTimeout(const Poco::Timespan& timeout);
|
||||
/// Sets the timeout.
|
||||
///
|
||||
/// If no other event occurs for the given timeout
|
||||
/// interval, a timeout event is sent to all event listeners.
|
||||
///
|
||||
/// The default timeout is 250 milliseconds;
|
||||
///
|
||||
/// The timeout is passed to the Socket::select()
|
||||
/// method.
|
||||
|
||||
Poco::Timespan getTimeout() const;
|
||||
/// Returns the timeout.
|
||||
|
||||
void addSocket(Socket sock, int mode);
|
||||
/// Adds the socket to the poll set.
|
||||
|
||||
void updateSocket(Socket sock, int mode);
|
||||
/// Updates the socket mode in the poll set.
|
||||
|
||||
void removeSocket(Socket sock);
|
||||
/// Removes the socket from the poll set.
|
||||
|
||||
void addReceiveFrom(Socket sock, Buffer& buf, SocketAddress& addr, Callback&& onCompletion);
|
||||
/// Adds the datagram socket and the completion handler to the I/O receive queue.
|
||||
|
||||
void addSendTo(Socket sock, const Buffer& message, const SocketAddress& addr, Callback&& onCompletion);
|
||||
/// Adds the datagram socket and the completion handler to the I/O send queue.
|
||||
|
||||
void addSendTo(Socket sock, Buffer&& message, const SocketAddress&& addr, Callback&& onCompletion);
|
||||
/// Adds the datagram socket and the completion handler to the I/O send queue.
|
||||
|
||||
void addSend(Socket sock, Buffer* pMessage, SocketAddress* pAddr, Callback&& onCompletion, bool own = false);
|
||||
/// Adds the socket and the completion handler to the I/O send queue.
|
||||
/// For stream socket, pAddr can be nullptr.
|
||||
/// If `own` is true, message and address are deleted after the I/O completion.
|
||||
|
||||
void addReceive(Socket sock, Buffer& buf, Callback&& onCompletion);
|
||||
/// Adds the stream socket and the completion handler to the I/O receive queue.
|
||||
|
||||
void addSend(Socket sock, const Buffer& message, Callback&& onCompletion);
|
||||
/// Adds the stream socket and the completion handler to the I/O send queue.
|
||||
|
||||
void addSend(Socket sock, Buffer&& message, Callback&& onCompletion);
|
||||
/// Adds the stream socket and the completion handler to the I/O send queue.
|
||||
|
||||
bool hasSocketHandlers() const;
|
||||
/// Returns true if proactor had at least one I/O completion handler.
|
||||
|
||||
bool has(const Socket& sock) const;
|
||||
/// Returns true if socket is registered with this proactor.
|
||||
|
||||
bool isRunning() const;
|
||||
/// Returns true if this proactor is running
|
||||
|
||||
bool ioCompletionInProgress() const;
|
||||
/// Returns true if there are not executed handlers from last IO..
|
||||
|
||||
private:
|
||||
void onShutdown();
|
||||
/// Called when the SocketProactor is about to terminate.
|
||||
|
||||
int doWork(bool handleOne = false, bool expiredOnly = false);
|
||||
/// Runs the scheduled work.
|
||||
/// If handleOne is true, only the next scheduled function
|
||||
/// is called.
|
||||
/// If expiredOnly is true, only expired temporary functions
|
||||
/// are called.
|
||||
|
||||
typedef Poco::Mutex MutexType;
|
||||
typedef MutexType::ScopedLock ScopedLock;
|
||||
|
||||
static const long DEFAULT_MAX_TIMEOUT_MS = 250;
|
||||
|
||||
struct Handler
|
||||
/// Handler struct holds the scheduled I/O.
|
||||
/// At the actual I/O, Buffer and SocketAddress
|
||||
/// are used appropriately, and deleted if owned.
|
||||
/// Callback is passed to the IOCompletion queue.
|
||||
{
|
||||
Buffer* _pBuf = nullptr;
|
||||
SocketAddress* _pAddr = nullptr;
|
||||
Callback _onCompletion = nullptr;
|
||||
bool _owner = false;
|
||||
};
|
||||
|
||||
class IONotification: public Notification
|
||||
/// IONotification object is used to transfer
|
||||
/// the I/O completion handlers into the
|
||||
/// completion handlers queue.
|
||||
{
|
||||
public:
|
||||
IONotification() = delete;
|
||||
|
||||
IONotification(Callback&& onCompletion, int bytes, const std::error_code& errorCode):
|
||||
_onCompletion(std::move(onCompletion)),
|
||||
_bytes(bytes),
|
||||
_errorCode(errorCode)
|
||||
/// Creates the IONotification.
|
||||
{
|
||||
}
|
||||
|
||||
~IONotification() = default;
|
||||
|
||||
void call()
|
||||
/// Calls the completion handler.
|
||||
{
|
||||
_onCompletion(_errorCode, _bytes);
|
||||
};
|
||||
|
||||
private:
|
||||
Callback _onCompletion;
|
||||
int _bytes;
|
||||
std::error_code _errorCode;
|
||||
};
|
||||
|
||||
class IOCompletion
|
||||
/// IOCompletion utility class accompanies the
|
||||
/// SocketProactor and serves to execute I/O
|
||||
/// completion handlers in its own thread.
|
||||
{
|
||||
public:
|
||||
IOCompletion() = delete;
|
||||
|
||||
explicit IOCompletion(int maxTimeout):
|
||||
_activity(this, &IOCompletion::run)
|
||||
/// Creates IOCompletion.
|
||||
{
|
||||
start();
|
||||
}
|
||||
|
||||
~IOCompletion()
|
||||
{
|
||||
wakeUp();
|
||||
}
|
||||
|
||||
void start()
|
||||
/// Starts the I/O completion execution.
|
||||
{
|
||||
_activity.start();
|
||||
}
|
||||
|
||||
void stop()
|
||||
/// Stops the I/O completion execution.
|
||||
{
|
||||
_activity.stop();
|
||||
_nq.wakeUpAll();
|
||||
}
|
||||
|
||||
void wait()
|
||||
/// Blocks until I/O execution completely stops.
|
||||
{
|
||||
_activity.wait();
|
||||
}
|
||||
|
||||
void enqueue(Notification::Ptr pNotification)
|
||||
/// Enqueues I/O completion.
|
||||
{
|
||||
_nq.enqueueNotification(std::move(pNotification));
|
||||
}
|
||||
|
||||
void wakeUp()
|
||||
/// Wakes up the I/O completion execution loop.
|
||||
{
|
||||
_nq.wakeUpAll();
|
||||
}
|
||||
|
||||
int queueSize() const
|
||||
{
|
||||
return _nq.size();
|
||||
}
|
||||
|
||||
private:
|
||||
bool runOne()
|
||||
/// Runs the next I/O completion handler in the queue.
|
||||
{
|
||||
IONotification* pNf = dynamic_cast<IONotification*>(_nq.waitDequeueNotification());
|
||||
if (pNf)
|
||||
{
|
||||
try
|
||||
{
|
||||
pNf->call();
|
||||
pNf->release();
|
||||
return true;
|
||||
}
|
||||
catch (Exception& exc)
|
||||
{
|
||||
ErrorHandler::handle(exc);
|
||||
}
|
||||
catch (std::exception& exc)
|
||||
{
|
||||
ErrorHandler::handle(exc);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ErrorHandler::handle();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void run()
|
||||
/// Continuously runs enqueued completion handlers.
|
||||
{
|
||||
while(!_activity.isStopped()) runOne();
|
||||
}
|
||||
|
||||
Activity<IOCompletion> _activity;
|
||||
NotificationQueue _nq;
|
||||
};
|
||||
|
||||
using IOHandlerList = std::deque<std::unique_ptr<Handler>>;
|
||||
using IOHandlerIt = IOHandlerList::iterator;
|
||||
using SubscriberMap = std::unordered_map<poco_socket_t, std::deque<std::unique_ptr<Handler>>>;
|
||||
|
||||
void sleep(bool isAtWork);
|
||||
/// Sleep policy implementation.
|
||||
/// If there is currently any work being done,
|
||||
/// timeout is kept at zero (ie. no timeout),
|
||||
/// otherwise, the timeout is incremented and
|
||||
/// - trySleep() is called if proactor runs
|
||||
/// in a Poco::Thread, which is necessary
|
||||
/// for trySleep call to be interruptable
|
||||
/// or
|
||||
/// - sleep() is called (not interruptable)
|
||||
///
|
||||
/// The value of _timeout can grow up to
|
||||
/// _maxTimeout value.
|
||||
|
||||
int error(Socket& sock);
|
||||
/// Enqueues the completion handlers and removes
|
||||
/// them from the handlers list after the operation
|
||||
/// successfully completes.
|
||||
|
||||
bool hasHandlers(SubscriberMap& handlers, int sockfd);
|
||||
void deleteHandler(IOHandlerList& handlers, IOHandlerList::iterator& it);
|
||||
|
||||
template <typename T>
|
||||
int errorImpl(Socket& sock, T& handlerMap, Poco::Mutex& mutex)
|
||||
{
|
||||
Poco::Mutex::ScopedLock l(mutex);
|
||||
auto hIt = handlerMap.find(sock.impl()->sockfd());
|
||||
if (hIt == handlerMap.end()) return 0;
|
||||
unsigned err = 0;
|
||||
sock.getOption(SOL_SOCKET, SO_ERROR, err);
|
||||
IOHandlerList& handlers = hIt->second;
|
||||
int handled = static_cast<int>(handlers.size());
|
||||
auto it = handlers.begin();
|
||||
auto end = handlers.end();
|
||||
while (it != end)
|
||||
{
|
||||
enqueueIONotification(std::move((*it)->_onCompletion), 0, err);
|
||||
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;
|
||||
}
|
||||
|
||||
int send(Socket& sock);
|
||||
/// Calls the appropriate output function; enqueues
|
||||
/// the accompanying completion handler and removes
|
||||
/// it from the handlers list after the operation
|
||||
/// successfully completes.
|
||||
|
||||
int receive(Socket& sock);
|
||||
/// Calls the appropriate input function; enqueues
|
||||
/// the accompanying completion handler and removes
|
||||
/// it from the handlers list after the operation
|
||||
/// successfully completes.
|
||||
|
||||
void sendTo(SocketImpl& sock, IOHandlerIt& it);
|
||||
/// Sends data to the datagram socket and enqueues the
|
||||
/// accompanying completion handler.
|
||||
|
||||
void send(SocketImpl& sock, IOHandlerIt& it);
|
||||
/// Sends data to the stream socket and enqueues the
|
||||
/// accompanying completion handler.
|
||||
|
||||
void receiveFrom(SocketImpl& sock, IOHandlerIt& it, int available);
|
||||
/// Reads data from the datagram socket and enqueues the
|
||||
/// accompanying completion handler.
|
||||
|
||||
void receive(SocketImpl& sock, IOHandlerIt& it, int available);
|
||||
/// Reads data from the stream socket and enqueues the
|
||||
/// accompanying completion handler.
|
||||
|
||||
void enqueueIONotification(Callback&& onCompletion, int n, int err);
|
||||
/// Enqueues the completion handler into the I/O
|
||||
/// completion handler.
|
||||
|
||||
Worker& worker();
|
||||
|
||||
std::atomic<bool> _isRunning;
|
||||
std::atomic<bool> _isStopped;
|
||||
std::atomic<bool> _stop;
|
||||
long _timeout;
|
||||
long _maxTimeout;
|
||||
PollSet _pollSet;
|
||||
Poco::Thread* _pThread;
|
||||
|
||||
SubscriberMap _readHandlers;
|
||||
SubscriberMap _writeHandlers;
|
||||
IOCompletion _ioCompletion;
|
||||
Poco::Mutex _writeMutex;
|
||||
Poco::Mutex _readMutex;
|
||||
|
||||
std::unique_ptr<Worker> _pWorker;
|
||||
friend class Worker;
|
||||
};
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
inline void SocketProactor::addSocket(Socket sock, int mode)
|
||||
{
|
||||
_pollSet.add(sock, mode | PollSet::POLL_ERROR);
|
||||
}
|
||||
|
||||
|
||||
inline void SocketProactor::updateSocket(Socket sock, int mode)
|
||||
{
|
||||
_pollSet.update(sock, mode);
|
||||
}
|
||||
|
||||
|
||||
inline void SocketProactor::removeSocket(Socket sock)
|
||||
{
|
||||
_pollSet.remove(sock);
|
||||
}
|
||||
|
||||
|
||||
inline void SocketProactor::enqueueIONotification(Callback&& onCompletion, int n, int err)
|
||||
{
|
||||
if (onCompletion)
|
||||
{
|
||||
_ioCompletion.enqueue(new IONotification(
|
||||
std::move(onCompletion), n,
|
||||
std::error_code(err, std::generic_category())));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline bool SocketProactor::isRunning() const
|
||||
{
|
||||
return _isRunning;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
||||
|
||||
#endif // Net_SocketProactor_INCLUDED
|
@ -209,7 +209,7 @@ protected:
|
||||
private:
|
||||
typedef Poco::AutoPtr<SocketNotifier> NotifierPtr;
|
||||
typedef Poco::AutoPtr<SocketNotification> NotificationPtr;
|
||||
typedef std::map<Socket, NotifierPtr> EventHandlerMap;
|
||||
typedef std::map<poco_socket_t, NotifierPtr> EventHandlerMap;
|
||||
typedef Poco::FastMutex MutexType;
|
||||
typedef MutexType::ScopedLock ScopedLock;
|
||||
|
||||
|
@ -60,6 +60,10 @@ public:
|
||||
/// a StreamSocketImpl, otherwise an InvalidArgumentException
|
||||
/// will be thrown.
|
||||
|
||||
StreamSocket(const StreamSocket& socket);
|
||||
/// Creates the StreamSocket with the SocketImpl
|
||||
/// from another socket.
|
||||
|
||||
virtual ~StreamSocket();
|
||||
/// Destroys the StreamSocket.
|
||||
|
||||
@ -70,6 +74,43 @@ public:
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// increments the reference count of the SocketImpl.
|
||||
|
||||
StreamSocket& operator = (const StreamSocket& socket);
|
||||
/// Assignment operator.
|
||||
///
|
||||
/// Releases the socket's SocketImpl and
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// increments the reference count of the SocketImpl.
|
||||
|
||||
#if POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
StreamSocket(Socket&& socket);
|
||||
/// Creates the StreamSocket with the SocketImpl
|
||||
/// from another socket and zeroes the other socket's
|
||||
/// SocketImpl.The SocketImpl must be
|
||||
/// a StreamSocketImpl, otherwise an InvalidArgumentException
|
||||
/// will be thrown.
|
||||
|
||||
StreamSocket(StreamSocket&& socket);
|
||||
/// Creates the StreamSocket with the SocketImpl
|
||||
/// from another socket and zeroes the other socket's
|
||||
/// SocketImpl.
|
||||
|
||||
StreamSocket& operator = (Socket&& socket);
|
||||
/// Assignment move operator.
|
||||
///
|
||||
/// Releases the socket's SocketImpl and
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// zeroes the other socket's SocketImpl.
|
||||
|
||||
StreamSocket& operator = (StreamSocket&& socket);
|
||||
/// Assignment move operator.
|
||||
///
|
||||
/// Releases the socket's SocketImpl and
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// zeroes the other socket's SocketImpl.
|
||||
|
||||
#endif //POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
void connect(const SocketAddress& address);
|
||||
/// Initializes the socket and establishes a connection to
|
||||
/// the TCP server at the given address.
|
||||
|
@ -42,7 +42,7 @@ typedef int UDPMsgSizeT;
|
||||
|
||||
template <std::size_t S = POCO_UDP_BUF_SIZE>
|
||||
class UDPHandlerImpl: public Runnable, public RefCountedObject
|
||||
/// UDP handler handles the data that arives to the UDP server.
|
||||
/// UDP handler handles the data that arrives to the UDP server.
|
||||
/// The class is thread-safe and runs in its own thread, so many handlers
|
||||
/// can be used in parallel.Handler manages and provides the storage
|
||||
/// (fixed-size memory blocks of S size) to the reader, which signals back
|
||||
|
@ -176,8 +176,11 @@ public:
|
||||
/// Creates a WebSocket from another Socket, which must be a WebSocket,
|
||||
/// otherwise a Poco::InvalidArgumentException will be thrown.
|
||||
|
||||
WebSocket(const WebSocket& socket);
|
||||
/// Creates a WebSocket from another WebSocket.
|
||||
|
||||
virtual ~WebSocket();
|
||||
/// Destroys the StreamSocket.
|
||||
/// Destroys the WebSocket.
|
||||
|
||||
WebSocket& operator = (const Socket& socket);
|
||||
/// Assignment operator.
|
||||
@ -185,6 +188,39 @@ public:
|
||||
/// The other socket must be a WebSocket, otherwise a Poco::InvalidArgumentException
|
||||
/// will be thrown.
|
||||
|
||||
WebSocket& operator = (const WebSocket& socket);
|
||||
/// Assignment operator.
|
||||
|
||||
#if POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
WebSocket(Socket&& socket);
|
||||
/// Creates the WebSocket with the SocketImpl
|
||||
/// from another socket and zeroes the other socket's
|
||||
/// SocketImpl.The SocketImpl must be
|
||||
/// a WebSocketImpl, otherwise an InvalidArgumentException
|
||||
/// will be thrown.
|
||||
|
||||
WebSocket(WebSocket&& socket);
|
||||
/// Creates the WebSocket with the SocketImpl
|
||||
/// from another socket and zeroes the other socket's
|
||||
/// SocketImpl.
|
||||
|
||||
WebSocket& operator = (Socket&& socket);
|
||||
/// Assignment move operator.
|
||||
///
|
||||
/// Releases the socket's SocketImpl and
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// zeroes the other socket's SocketImpl.
|
||||
|
||||
WebSocket& operator = (WebSocket&& socket);
|
||||
/// Assignment move operator.
|
||||
///
|
||||
/// Releases the socket's SocketImpl and
|
||||
/// attaches the SocketImpl from the other socket and
|
||||
/// zeroes the other socket's SocketImpl.
|
||||
|
||||
#endif //POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
void shutdown();
|
||||
/// Sends a Close control frame to the server end of
|
||||
/// the connection to initiate an orderly shutdown
|
||||
|
@ -34,15 +34,12 @@ DatagramSocket::DatagramSocket(SocketAddress::Family family): Socket(new Datagra
|
||||
}
|
||||
|
||||
|
||||
DatagramSocket::DatagramSocket(const SocketAddress& address, bool reuseAddress): Socket(new DatagramSocketImpl(address.family()))
|
||||
DatagramSocket::DatagramSocket(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only):
|
||||
Socket(new DatagramSocketImpl(address.family()))
|
||||
{
|
||||
bind(address, reuseAddress);
|
||||
}
|
||||
|
||||
|
||||
DatagramSocket::DatagramSocket(const SocketAddress& address, bool reuseAddress, bool reusePort): Socket(new DatagramSocketImpl(address.family()))
|
||||
{
|
||||
bind(address, reuseAddress, reusePort);
|
||||
if (address.family() == SocketAddress::IPv6)
|
||||
bind6(address, reuseAddress, reusePort, ipV6Only);
|
||||
else bind(address, reuseAddress, reusePort);
|
||||
}
|
||||
|
||||
|
||||
@ -53,6 +50,11 @@ DatagramSocket::DatagramSocket(const Socket& socket): Socket(socket)
|
||||
}
|
||||
|
||||
|
||||
DatagramSocket::DatagramSocket(const DatagramSocket& socket): Socket(socket)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DatagramSocket::DatagramSocket(SocketImpl* pImpl): Socket(pImpl)
|
||||
{
|
||||
if (!dynamic_cast<DatagramSocketImpl*>(impl()))
|
||||
@ -74,6 +76,44 @@ DatagramSocket& DatagramSocket::operator = (const Socket& socket)
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
DatagramSocket::DatagramSocket(DatagramSocket&& socket): Socket(std::move(socket))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DatagramSocket::DatagramSocket(Socket&& socket): Socket(std::move(socket))
|
||||
{
|
||||
if (!dynamic_cast<DatagramSocketImpl*>(impl()))
|
||||
throw InvalidArgumentException("Cannot assign incompatible socket");
|
||||
}
|
||||
|
||||
|
||||
DatagramSocket& DatagramSocket::operator = (Socket&& socket)
|
||||
{
|
||||
if (dynamic_cast<DatagramSocketImpl*>(socket.impl()))
|
||||
Socket::operator = (std::move(socket));
|
||||
else
|
||||
throw InvalidArgumentException("Cannot assign incompatible socket");
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DatagramSocket& DatagramSocket::operator = (DatagramSocket&& socket)
|
||||
{
|
||||
Socket::operator = (std::move(socket));
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
DatagramSocket& DatagramSocket::operator = (const DatagramSocket& socket)
|
||||
{
|
||||
Socket::operator = (socket);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void DatagramSocket::connect(const SocketAddress& address)
|
||||
{
|
||||
@ -93,6 +133,12 @@ void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress, bool
|
||||
}
|
||||
|
||||
|
||||
void DatagramSocket::bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only)
|
||||
{
|
||||
impl()->bind6(address, reuseAddress, reusePort, ipV6Only);
|
||||
}
|
||||
|
||||
|
||||
int DatagramSocket::sendBytes(const void* buffer, int length, int flags)
|
||||
{
|
||||
return impl()->sendBytes(buffer, length, flags);
|
||||
|
@ -66,7 +66,7 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
|
||||
{
|
||||
int maxPacketSize = _icmpPacket.maxPacketSize();
|
||||
Poco::Buffer<unsigned char> buffer(maxPacketSize);
|
||||
int expected = _icmpPacket.packetSize();
|
||||
int leftover = _icmpPacket.packetSize();
|
||||
int type = 0, code = 0;
|
||||
|
||||
try
|
||||
@ -83,8 +83,8 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
|
||||
if (rc == 0) break;
|
||||
if (respAddr == address)
|
||||
{
|
||||
expected -= rc;
|
||||
if (expected <= 0)
|
||||
leftover -= rc;
|
||||
if (leftover <= 0)
|
||||
{
|
||||
if (_icmpPacket.validReplyID(buffer.begin(), maxPacketSize)) break;
|
||||
std::string err = _icmpPacket.errorDescription(buffer.begin(), maxPacketSize, type, code);
|
||||
@ -95,7 +95,7 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
while (expected > 0 && !_icmpPacket.validReplyID(buffer.begin(), maxPacketSize));
|
||||
while (leftover > 0 && !_icmpPacket.validReplyID(buffer.begin(), maxPacketSize));
|
||||
}
|
||||
catch (ICMPException&)
|
||||
{
|
||||
@ -113,10 +113,11 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
|
||||
else throw;
|
||||
}
|
||||
|
||||
if (expected > 0)
|
||||
if (leftover > 0)
|
||||
{
|
||||
throw ICMPException(Poco::format("No response: expected %d, received: %d", _icmpPacket.packetSize(),
|
||||
_icmpPacket.packetSize() - expected));
|
||||
std::string err = leftover < _icmpPacket.packetSize() ? "Incomplete" : "No";
|
||||
throw ICMPException(Poco::format("%s response: expected %d, received: %d", err, _icmpPacket.packetSize(),
|
||||
_icmpPacket.packetSize() - leftover));
|
||||
}
|
||||
|
||||
struct timeval then = _icmpPacket.time(buffer.begin(), maxPacketSize);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "Poco/BinaryReader.h"
|
||||
#include "Poco/BinaryWriter.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/Types.h"
|
||||
|
||||
|
||||
@ -69,6 +70,11 @@ IPAddress::IPAddress(const IPAddress& addr)
|
||||
}
|
||||
|
||||
|
||||
IPAddress::IPAddress(IPAddress&& addr): _pImpl(std::move(addr._pImpl))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
IPAddress::IPAddress(Family family)
|
||||
{
|
||||
if (family == IPv4)
|
||||
@ -99,7 +105,7 @@ IPAddress::IPAddress(const std::string& addr)
|
||||
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
IPv6AddressImpl empty6 = IPv6AddressImpl();
|
||||
if (addr.empty() || trim(addr) == "::")
|
||||
if (addr.empty() || trimIPv6(addr) == "::")
|
||||
{
|
||||
newIPv6(empty6.addr());
|
||||
return;
|
||||
@ -237,6 +243,13 @@ IPAddress& IPAddress::operator = (const IPAddress& addr)
|
||||
}
|
||||
|
||||
|
||||
IPAddress& IPAddress::operator = (IPAddress&& addr)
|
||||
{
|
||||
_pImpl = std::move(addr._pImpl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
IPAddress::Family IPAddress::family() const
|
||||
{
|
||||
return pImpl()->family();
|
||||
@ -519,6 +532,47 @@ unsigned IPAddress::prefixLength() const
|
||||
}
|
||||
|
||||
|
||||
std::string& IPAddress::compressV6(std::string& v6addr)
|
||||
{
|
||||
// get rid of leading zeros at the beginning
|
||||
while (v6addr.size() && v6addr[0] == '0') v6addr.erase(v6addr.begin());
|
||||
|
||||
// get rid of leading zeros in the middle
|
||||
while (v6addr.find(":0") != std::string::npos)
|
||||
Poco::replaceInPlace(v6addr, ":0", ":");
|
||||
|
||||
// get rid of extraneous colons
|
||||
while (v6addr.find(":::") != std::string::npos)
|
||||
Poco::replaceInPlace(v6addr, ":::", "::");
|
||||
|
||||
return v6addr;
|
||||
}
|
||||
|
||||
|
||||
std::string IPAddress::trimIPv6(const std::string v6Addr)
|
||||
{
|
||||
std::string v6addr(v6Addr);
|
||||
std::string::size_type len = v6addr.length();
|
||||
int dblColOcc = 0;
|
||||
auto pos = v6addr.find("::");
|
||||
while ((pos <= len-2) && (pos != std::string::npos))
|
||||
{
|
||||
++dblColOcc;
|
||||
pos = v6addr.find("::", pos + 2);
|
||||
}
|
||||
|
||||
if ((dblColOcc > 1) ||
|
||||
(std::count(v6addr.begin(), v6addr.end(), ':') > 8) ||
|
||||
(v6addr.find(":::") != std::string::npos) ||
|
||||
((len >= 2) && ((v6addr[len-1] == ':') && v6addr[len-2] != ':')))
|
||||
{
|
||||
return v6addr;
|
||||
}
|
||||
|
||||
return compressV6(v6addr);
|
||||
}
|
||||
|
||||
|
||||
IPAddress IPAddress::parse(const std::string& addr)
|
||||
{
|
||||
return IPAddress(addr);
|
||||
@ -535,7 +589,7 @@ bool IPAddress::tryParse(const std::string& addr, IPAddress& result)
|
||||
}
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr));
|
||||
if (impl6 != IPv6AddressImpl())
|
||||
if (impl6 != IPv6AddressImpl() || trimIPv6(addr) == "::")
|
||||
{
|
||||
result.newIPv6(impl6.addr(), impl6.scope());
|
||||
return true;
|
||||
@ -572,6 +626,54 @@ IPAddress IPAddress::broadcast()
|
||||
}
|
||||
|
||||
|
||||
IPAddress::RawIPv4 IPAddress::toV4Bytes() const
|
||||
{
|
||||
if (family() != IPv4)
|
||||
throw Poco::InvalidAccessException(Poco::format("IPAddress::toV4Bytes(%d)", (int)family()));
|
||||
|
||||
RawIPv4 bytes;
|
||||
std::memcpy(&bytes[0], addr(), IPv4Size);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
IPAddress::RawIPv6 IPAddress::toV6Bytes() const
|
||||
{
|
||||
if (family() != IPv6)
|
||||
throw Poco::InvalidAccessException(Poco::format("IPAddress::toV6Bytes(%d)", (int)family()));
|
||||
|
||||
RawIPv6 bytes;
|
||||
std::memcpy(&bytes[0], addr(), IPv6Size);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
std::vector<unsigned char> IPAddress::toBytes() const
|
||||
{
|
||||
std::size_t sz = 0;
|
||||
std::vector<unsigned char> bytes;
|
||||
const void* ptr = 0;
|
||||
switch (family())
|
||||
{
|
||||
case IPv4:
|
||||
sz = sizeof(in_addr);
|
||||
ptr = addr();
|
||||
break;
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
case IPv6:
|
||||
sz = sizeof(in6_addr);
|
||||
ptr = addr();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
throw Poco::IllegalStateException(Poco::format("IPAddress::toBytes(%d)", (int)family()));
|
||||
}
|
||||
bytes.resize(sz);
|
||||
std::memcpy(&bytes[0], ptr, sz);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
||||
|
||||
|
@ -18,23 +18,13 @@
|
||||
#include <set>
|
||||
|
||||
|
||||
#if defined(_WIN32) && _WIN32_WINNT >= 0x0600
|
||||
#ifndef POCO_HAVE_FD_POLL
|
||||
#define POCO_HAVE_FD_POLL 1
|
||||
#endif
|
||||
#elif defined(POCO_OS_FAMILY_BSD)
|
||||
#ifndef POCO_HAVE_FD_POLL
|
||||
#define POCO_HAVE_FD_POLL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(POCO_HAVE_FD_EPOLL)
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/eventfd.h>
|
||||
#elif defined(POCO_HAVE_FD_POLL)
|
||||
#ifndef _WIN32
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -51,12 +41,12 @@ namespace Net {
|
||||
class PollSetImpl
|
||||
{
|
||||
public:
|
||||
PollSetImpl():
|
||||
_epollfd(-1),
|
||||
_events(1024)
|
||||
PollSetImpl(): _epollfd(epoll_create(1)),
|
||||
_events(1024),
|
||||
_eventfd(eventfd(0, 0))
|
||||
{
|
||||
_epollfd = epoll_create(1);
|
||||
if (_epollfd < 0)
|
||||
int err = addImpl(_eventfd, PollSet::POLL_READ, 0);
|
||||
if ((err) || (_epollfd < 0))
|
||||
{
|
||||
SocketImpl::error();
|
||||
}
|
||||
@ -64,8 +54,8 @@ public:
|
||||
|
||||
~PollSetImpl()
|
||||
{
|
||||
if (_epollfd >= 0)
|
||||
::close(_epollfd);
|
||||
if (_epollfd >= 0) ::close(_epollfd);
|
||||
if (_eventfd >= 0) ::close(_eventfd);
|
||||
}
|
||||
|
||||
void add(const Socket& socket, int mode)
|
||||
@ -73,17 +63,8 @@ public:
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
SocketImpl* sockImpl = socket.impl();
|
||||
poco_socket_t fd = sockImpl->sockfd();
|
||||
struct epoll_event ev;
|
||||
ev.events = 0;
|
||||
if (mode & PollSet::POLL_READ)
|
||||
ev.events |= EPOLLIN;
|
||||
if (mode & PollSet::POLL_WRITE)
|
||||
ev.events |= EPOLLOUT;
|
||||
if (mode & PollSet::POLL_ERROR)
|
||||
ev.events |= EPOLLERR;
|
||||
ev.data.ptr = socket.impl();
|
||||
int err = epoll_ctl(_epollfd, EPOLL_CTL_ADD, fd, &ev);
|
||||
|
||||
int err = addImpl(sockImpl->sockfd(), mode, sockImpl);
|
||||
|
||||
if (err)
|
||||
{
|
||||
@ -158,18 +139,13 @@ public:
|
||||
PollSet::SocketModeMap poll(const Poco::Timespan& timeout)
|
||||
{
|
||||
PollSet::SocketModeMap result;
|
||||
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
if(_socketMap.empty()) return result;
|
||||
}
|
||||
|
||||
Poco::Timespan remainingTime(timeout);
|
||||
int rc;
|
||||
do
|
||||
{
|
||||
Poco::Timestamp start;
|
||||
rc = epoll_wait(_epollfd, &_events[0], _events.size(), remainingTime.totalMilliseconds());
|
||||
if (rc == 0) return result;
|
||||
if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
|
||||
{
|
||||
Poco::Timestamp end;
|
||||
@ -187,7 +163,9 @@ public:
|
||||
|
||||
for (int i = 0; i < rc; i++)
|
||||
{
|
||||
std::map<void*, Socket>::iterator it = _socketMap.find(_events[i].data.ptr);
|
||||
if (_events[i].data.ptr) // skip eventfd
|
||||
{
|
||||
std::map<void *, Socket>::iterator it = _socketMap.find(_events[i].data.ptr);
|
||||
if (it != _socketMap.end())
|
||||
{
|
||||
if (_events[i].events & EPOLLIN)
|
||||
@ -198,15 +176,44 @@ public:
|
||||
result[it->second] |= PollSet::POLL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void wakeUp()
|
||||
{
|
||||
uint64_t val = 1;
|
||||
int n = ::write(_eventfd, &val, sizeof(val));
|
||||
if (n < 0) Socket::error();
|
||||
}
|
||||
|
||||
int count() const
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
return static_cast<int>(_socketMap.size());
|
||||
}
|
||||
|
||||
private:
|
||||
int addImpl(int fd, int mode, void* ptr)
|
||||
{
|
||||
struct epoll_event ev;
|
||||
ev.events = 0;
|
||||
if (mode & PollSet::POLL_READ)
|
||||
ev.events |= EPOLLIN;
|
||||
if (mode & PollSet::POLL_WRITE)
|
||||
ev.events |= EPOLLOUT;
|
||||
if (mode & PollSet::POLL_ERROR)
|
||||
ev.events |= EPOLLERR;
|
||||
ev.data.ptr = ptr;
|
||||
return epoll_ctl(_epollfd, EPOLL_CTL_ADD, fd, &ev);
|
||||
}
|
||||
|
||||
mutable Poco::FastMutex _mutex;
|
||||
int _epollfd;
|
||||
std::map<void*, Socket> _socketMap;
|
||||
std::vector<struct epoll_event> _events;
|
||||
int _eventfd;
|
||||
};
|
||||
|
||||
|
||||
@ -222,7 +229,6 @@ public:
|
||||
void add(const Socket& socket, int mode)
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
poco_socket_t fd = socket.impl()->sockfd();
|
||||
_addMap[fd] = mode;
|
||||
_removeSet.erase(fd);
|
||||
@ -232,7 +238,6 @@ public:
|
||||
void remove(const Socket& socket)
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
poco_socket_t fd = socket.impl()->sockfd();
|
||||
_removeSet.insert(fd);
|
||||
_addMap.erase(fd);
|
||||
@ -256,7 +261,6 @@ public:
|
||||
void update(const Socket& socket, int mode)
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
poco_socket_t fd = socket.impl()->sockfd();
|
||||
for (auto it = _pollfds.begin(); it != _pollfds.end(); ++it)
|
||||
{
|
||||
@ -264,7 +268,7 @@ public:
|
||||
{
|
||||
it->events = 0;
|
||||
it->revents = 0;
|
||||
setMode(it->fd, it->events, mode);
|
||||
setMode(it->events, mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -305,7 +309,7 @@ public:
|
||||
pfd.fd = it->first;
|
||||
pfd.events = 0;
|
||||
pfd.revents = 0;
|
||||
setMode(pfd.fd, pfd.events, it->second);
|
||||
setMode(pfd.events, it->second);
|
||||
_pollfds.push_back(pfd);
|
||||
}
|
||||
_addMap.clear();
|
||||
@ -320,12 +324,6 @@ public:
|
||||
Poco::Timestamp start;
|
||||
#ifdef _WIN32
|
||||
rc = WSAPoll(&_pollfds[0], static_cast<ULONG>(_pollfds.size()), static_cast<INT>(remainingTime.totalMilliseconds()));
|
||||
// see https://github.com/pocoproject/poco/issues/3248
|
||||
if ((remainingTime > 0) && (rc > 0) && !hasSignaledFDs())
|
||||
{
|
||||
rc = -1;
|
||||
WSASetLastError(WSAEINTR);
|
||||
}
|
||||
#else
|
||||
rc = ::poll(&_pollfds[0], _pollfds.size(), remainingTime.totalMilliseconds());
|
||||
#endif
|
||||
@ -358,13 +356,9 @@ public:
|
||||
#endif
|
||||
)
|
||||
result[its->second] |= PollSet::POLL_READ;
|
||||
if ((it->revents & POLLOUT)
|
||||
#ifdef _WIN32
|
||||
&& (_wantPOLLOUT.find(it->fd) != _wantPOLLOUT.end())
|
||||
#endif
|
||||
)
|
||||
if (it->revents & POLLOUT)
|
||||
result[its->second] |= PollSet::POLL_WRITE;
|
||||
if (it->revents & POLLERR)
|
||||
if (it->revents & POLLERR || (it->revents & POLLHUP))
|
||||
result[its->second] |= PollSet::POLL_ERROR;
|
||||
}
|
||||
it->revents = 0;
|
||||
@ -375,38 +369,20 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
void wakeUp()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
int count() const
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
return static_cast<int>(_socketMap.size());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
void setMode(poco_socket_t fd, short& target, int mode)
|
||||
{
|
||||
if (mode & PollSet::POLL_READ)
|
||||
target |= POLLIN;
|
||||
|
||||
if (mode & PollSet::POLL_WRITE)
|
||||
_wantPOLLOUT.insert(fd);
|
||||
else
|
||||
_wantPOLLOUT.erase(fd);
|
||||
target |= POLLOUT;
|
||||
}
|
||||
|
||||
bool hasSignaledFDs()
|
||||
{
|
||||
for (const auto& pollfd : _pollfds)
|
||||
{
|
||||
if ((pollfd.revents | POLLOUT) &&
|
||||
(_wantPOLLOUT.find(pollfd.fd) != _wantPOLLOUT.end()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void setMode(poco_socket_t fd, short& target, int mode)
|
||||
void setMode(short& target, int mode)
|
||||
{
|
||||
if (mode & PollSet::POLL_READ)
|
||||
target |= POLLIN;
|
||||
@ -415,13 +391,8 @@ private:
|
||||
target |= POLLOUT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
mutable Poco::FastMutex _mutex;
|
||||
std::map<poco_socket_t, Socket> _socketMap;
|
||||
#ifdef _WIN32
|
||||
std::set<poco_socket_t> _wantPOLLOUT;
|
||||
#endif
|
||||
std::map<poco_socket_t, int> _addMap;
|
||||
std::set<poco_socket_t> _removeSet;
|
||||
std::vector<pollfd> _pollfds;
|
||||
@ -431,6 +402,300 @@ private:
|
||||
#else
|
||||
|
||||
|
||||
#ifdef POCO_OS_FAMILY_WINDOWS
|
||||
|
||||
|
||||
//
|
||||
// Windows-specific implementation using select()
|
||||
// The size of select set is determined at compile
|
||||
// time (see FD_SETSIZE in SocketDefs.h).
|
||||
//
|
||||
// This implementation works around that limit by
|
||||
// having multiple socket descriptor sets and,
|
||||
// when needed, calling select() multiple times.
|
||||
// To avoid multiple sets situtation, the FD_SETSIZE
|
||||
// can be increased, however then Poco::Net library
|
||||
// must be recompiled in order for the new setting
|
||||
// to be in effect.
|
||||
//
|
||||
|
||||
|
||||
class PollSetImpl
|
||||
{
|
||||
public:
|
||||
PollSetImpl() : _fdRead(1, {0, {0}}),
|
||||
_fdWrite(1, {0, {0}}),
|
||||
_fdExcept(1, {0, {0}}),
|
||||
_pFDRead(std::make_unique<fd_set>()),
|
||||
_pFDWrite(std::make_unique<fd_set>()),
|
||||
_pFDExcept(std::make_unique<fd_set>()),
|
||||
_nfd(0)
|
||||
{
|
||||
}
|
||||
|
||||
void add(const Socket& socket, int mode)
|
||||
{
|
||||
Poco::Net::SocketImpl* pImpl = socket.impl();
|
||||
poco_check_ptr(pImpl);
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
_map[socket] = mode;
|
||||
setMode(pImpl->sockfd(), mode);
|
||||
}
|
||||
|
||||
void remove(const Socket& socket)
|
||||
{
|
||||
Poco::Net::SocketImpl* pImpl = socket.impl();
|
||||
poco_check_ptr(pImpl);
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
remove(pImpl->sockfd());
|
||||
_map.erase(socket);
|
||||
}
|
||||
|
||||
bool has(const Socket& socket) const
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
return _map.find(socket) != _map.end();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
return _map.empty();
|
||||
}
|
||||
|
||||
void update(const Socket& socket, int mode)
|
||||
{
|
||||
Poco::Net::SocketImpl* pImpl = socket.impl();
|
||||
poco_check_ptr(pImpl);
|
||||
SOCKET fd = pImpl->sockfd();
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
_map[socket] = mode;
|
||||
setMode(fd, mode);
|
||||
if (!(mode & PollSet::POLL_READ)) remove(fd, _fdRead);
|
||||
if (!(mode & PollSet::POLL_WRITE)) remove(fd, _fdWrite);
|
||||
if (!(mode & PollSet::POLL_ERROR)) remove(fd, _fdExcept);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
_map.clear();
|
||||
for (auto& fd : _fdRead) std::memset(&fd, 0, sizeof(fd));
|
||||
for (auto& fd : _fdWrite) std::memset(&fd, 0, sizeof(fd));
|
||||
for (auto& fd : _fdExcept) std::memset(&fd, 0, sizeof(fd));
|
||||
_nfd = 0;
|
||||
}
|
||||
|
||||
PollSet::SocketModeMap poll(const Poco::Timespan& timeout)
|
||||
{
|
||||
Poco::Timestamp start;
|
||||
poco_assert_dbg(_fdRead.size() == _fdWrite.size());
|
||||
poco_assert_dbg(_fdWrite.size() == _fdExcept.size());
|
||||
|
||||
PollSet::SocketModeMap result;
|
||||
if (_nfd == 0) return result;
|
||||
|
||||
Poco::Timespan remainingTime(timeout);
|
||||
struct timeval tv {0, 1000};
|
||||
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
auto readIt = _fdRead.begin();
|
||||
auto writeIt = _fdWrite.begin();
|
||||
auto exceptIt = _fdExcept.begin();
|
||||
do
|
||||
{
|
||||
std::memcpy(_pFDRead.get(), &*readIt, sizeof(fd_set));
|
||||
std::memcpy(_pFDWrite.get(), &*writeIt, sizeof(fd_set));
|
||||
std::memcpy(_pFDExcept.get(), &*exceptIt, sizeof(fd_set));
|
||||
|
||||
int rc;
|
||||
do
|
||||
{
|
||||
rc = ::select((int)_nfd + 1, _pFDRead.get(), _pFDWrite.get(), _pFDExcept.get(), &tv);
|
||||
} while (rc < 0 && SocketImpl::lastError() == POCO_EINTR);
|
||||
if (rc < 0) SocketImpl::error();
|
||||
else if (rc > 0)
|
||||
{
|
||||
for (auto it = _map.begin(); it != _map.end(); ++it)
|
||||
{
|
||||
poco_socket_t fd = it->first.impl()->sockfd();
|
||||
if (fd != POCO_INVALID_SOCKET)
|
||||
{
|
||||
if (FD_ISSET(fd, _pFDRead.get()))
|
||||
{
|
||||
result[it->first] |= PollSet::POLL_READ;
|
||||
}
|
||||
if (FD_ISSET(fd, _pFDWrite.get()))
|
||||
{
|
||||
result[it->first] |= PollSet::POLL_WRITE;
|
||||
}
|
||||
if (FD_ISSET(fd, _pFDExcept.get()))
|
||||
{
|
||||
result[it->first] |= PollSet::POLL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timespan elapsed = Timestamp() - start;
|
||||
if (++readIt == _fdRead.end())
|
||||
{
|
||||
if ((rc > 0) || (elapsed.totalMilliseconds() > timeout.totalMilliseconds()))
|
||||
break;
|
||||
readIt = _fdRead.begin();
|
||||
writeIt = _fdWrite.begin();
|
||||
exceptIt = _fdExcept.begin();
|
||||
}
|
||||
else
|
||||
{
|
||||
++writeIt;
|
||||
++exceptIt;
|
||||
}
|
||||
|
||||
Poco::UInt64 tOut = (((Poco::UInt64)tv.tv_sec * 1000000) + tv.tv_usec) * 2;
|
||||
Poco::Timespan left = timeout - elapsed;
|
||||
if (tOut > left.totalMicroseconds())
|
||||
tOut = left.totalMicroseconds();
|
||||
|
||||
tv.tv_sec = static_cast<long>(tOut / 1000000);
|
||||
tv.tv_usec = tOut % 1000000;
|
||||
} while (true);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int count() const
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
return static_cast<int>(_map.size());
|
||||
}
|
||||
|
||||
void wakeUp()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void setMode(std::vector<fd_set>& fdSet, SOCKET fd)
|
||||
{
|
||||
SOCKET* pFD = 0;
|
||||
for (auto& fdr : fdSet)
|
||||
{
|
||||
SOCKET* begin = fdr.fd_array;
|
||||
SOCKET* end = fdr.fd_array + fdr.fd_count;
|
||||
pFD = std::find(begin, end, fd);
|
||||
if (end != pFD)
|
||||
{
|
||||
FD_SET(fd, &fdr);
|
||||
if (fd > _nfd) _nfd = fd;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// not found, insert at first free location
|
||||
for (auto& fdr : fdSet)
|
||||
{
|
||||
if (fdr.fd_count < FD_SETSIZE)
|
||||
{
|
||||
fdr.fd_count++;
|
||||
fdr.fd_array[fdr.fd_count-1] = fd;
|
||||
if (fd > _nfd) _nfd = fd;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// all fd sets are full; insert another one
|
||||
fdSet.push_back({0, {0}});
|
||||
fd_set& fds = fdSet.back();
|
||||
fds.fd_count = 1;
|
||||
fds.fd_array[0] = fd;
|
||||
if (fd > _nfd) _nfd = fd;
|
||||
}
|
||||
|
||||
void setMode(SOCKET fd, int mode)
|
||||
{
|
||||
if (mode & PollSet::POLL_READ) setMode(_fdRead, fd);
|
||||
if (mode & PollSet::POLL_WRITE) setMode(_fdWrite, fd);
|
||||
if (mode & PollSet::POLL_ERROR) setMode(_fdExcept, fd);
|
||||
}
|
||||
|
||||
void remove(SOCKET fd, std::vector<fd_set>& fdSets)
|
||||
{
|
||||
bool newNFD = false;
|
||||
for (auto& fdSet : fdSets)
|
||||
{
|
||||
if (fdSet.fd_count)
|
||||
{
|
||||
newNFD = (fd == _nfd);
|
||||
int i = 0;
|
||||
for (; i < fdSet.fd_count; ++i)
|
||||
{
|
||||
if (fdSet.fd_array[i] == fd)
|
||||
{
|
||||
if (i == (fdSet.fd_count-1))
|
||||
{
|
||||
fdSet.fd_array[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; i < fdSet.fd_count-1; ++i)
|
||||
{
|
||||
fdSet.fd_array[i] = fdSet.fd_array[i+1];
|
||||
if (newNFD && fdSet.fd_array[i] > _nfd)
|
||||
_nfd = fdSet.fd_array[i];
|
||||
}
|
||||
}
|
||||
fdSet.fd_array[fdSet.fd_count-1] = 0;
|
||||
fdSet.fd_count--;
|
||||
break;
|
||||
}
|
||||
if (newNFD && fdSet.fd_array[i] > _nfd)
|
||||
_nfd = fdSet.fd_array[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newNFD)
|
||||
{
|
||||
findNFD(_fdRead);
|
||||
findNFD(_fdWrite);
|
||||
findNFD(_fdExcept);
|
||||
}
|
||||
}
|
||||
|
||||
void findNFD(std::vector<fd_set>& fdSets)
|
||||
{
|
||||
for (auto& fdSet : fdSets)
|
||||
{
|
||||
for (int i = 0; i < fdSet.fd_count; ++i)
|
||||
{
|
||||
if (fdSet.fd_array[i] > _nfd)
|
||||
_nfd = fdSet.fd_array[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void remove(SOCKET fd)
|
||||
{
|
||||
remove(fd, _fdRead);
|
||||
remove(fd, _fdWrite);
|
||||
remove(fd, _fdExcept);
|
||||
}
|
||||
|
||||
mutable Poco::FastMutex _mutex;
|
||||
PollSet::SocketModeMap _map;
|
||||
SOCKET _nfd;
|
||||
std::vector<fd_set> _fdRead;
|
||||
std::vector<fd_set> _fdWrite;
|
||||
std::vector<fd_set> _fdExcept;
|
||||
std::unique_ptr<fd_set> _pFDRead;
|
||||
std::unique_ptr<fd_set> _pFDWrite;
|
||||
std::unique_ptr<fd_set> _pFDExcept;
|
||||
};
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
//
|
||||
// Fallback implementation using select()
|
||||
//
|
||||
@ -562,12 +827,26 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
void wakeUp()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
int count() const
|
||||
{
|
||||
Poco::FastMutex::ScopedLock lock(_mutex);
|
||||
return static_cast<int>(_map.size());
|
||||
}
|
||||
|
||||
private:
|
||||
mutable Poco::FastMutex _mutex;
|
||||
PollSet::SocketModeMap _map;
|
||||
};
|
||||
|
||||
|
||||
#endif // POCO_OS_FAMILY_WINDOWS
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -625,4 +904,16 @@ PollSet::SocketModeMap PollSet::poll(const Poco::Timespan& timeout)
|
||||
}
|
||||
|
||||
|
||||
int PollSet::count() const
|
||||
{
|
||||
return _pImpl->count();
|
||||
}
|
||||
|
||||
|
||||
void PollSet::wakeUp()
|
||||
{
|
||||
_pImpl->wakeUp();
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
@ -50,6 +50,16 @@ RawSocket::RawSocket(const Socket& socket): Socket(socket)
|
||||
}
|
||||
|
||||
|
||||
RawSocket::RawSocket(const RawSocket& socket): Socket(socket)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RawSocket::RawSocket(RawSocket&& socket): Socket(std::move(socket))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RawSocket::RawSocket(SocketImpl* pImpl): Socket(pImpl)
|
||||
{
|
||||
if (!dynamic_cast<RawSocketImpl*>(impl()))
|
||||
@ -72,6 +82,30 @@ RawSocket& RawSocket::operator = (const Socket& socket)
|
||||
}
|
||||
|
||||
|
||||
RawSocket& RawSocket::operator = (Socket&& socket)
|
||||
{
|
||||
if (dynamic_cast<RawSocketImpl*>(socket.impl()))
|
||||
Socket::operator = (std::move(socket));
|
||||
else
|
||||
throw InvalidArgumentException("Cannot assign incompatible socket");
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
RawSocket& RawSocket::operator = (const RawSocket& socket)
|
||||
{
|
||||
Socket::operator = (socket);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
RawSocket& RawSocket::operator = (RawSocket&& socket)
|
||||
{
|
||||
Socket::operator = (std::move(socket));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void RawSocket::connect(const SocketAddress& address)
|
||||
{
|
||||
impl()->connect(address);
|
||||
|
@ -18,10 +18,12 @@
|
||||
#include <algorithm>
|
||||
#include <string.h> // FD_SET needs memset on some platforms, so we can't use <cstring>
|
||||
#if defined(POCO_HAVE_FD_EPOLL)
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/epoll.h>
|
||||
#elif defined(POCO_HAVE_FD_POLL)
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include <poll.h>
|
||||
#include "Poco/SharedPtr.h"
|
||||
#ifndef _WIN32
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -50,6 +52,30 @@ Socket::Socket(const Socket& socket):
|
||||
_pImpl->duplicate();
|
||||
}
|
||||
|
||||
#if POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
Socket::Socket(Socket&& socket):
|
||||
_pImpl(socket._pImpl)
|
||||
{
|
||||
poco_check_ptr (_pImpl);
|
||||
|
||||
socket._pImpl = nullptr;
|
||||
}
|
||||
|
||||
|
||||
Socket& Socket::operator = (Socket&& socket)
|
||||
{
|
||||
if (&socket != this)
|
||||
{
|
||||
if (_pImpl) _pImpl->release();
|
||||
_pImpl = socket._pImpl;
|
||||
socket._pImpl = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
|
||||
Socket& Socket::operator = (const Socket& socket)
|
||||
{
|
||||
@ -62,10 +88,9 @@ Socket& Socket::operator = (const Socket& socket)
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Socket::~Socket()
|
||||
{
|
||||
_pImpl->release();
|
||||
if (_pImpl) _pImpl->release();
|
||||
}
|
||||
|
||||
|
||||
@ -207,8 +232,11 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce
|
||||
|
||||
#elif defined(POCO_HAVE_FD_POLL)
|
||||
typedef Poco::SharedPtr<pollfd, Poco::ReferenceCounter, Poco::ReleaseArrayPolicy<pollfd>> SharedPollArray;
|
||||
#ifdef _WIN32
|
||||
typedef ULONG nfds_t;
|
||||
#endif
|
||||
nfds_t nfd = static_cast<nfds_t>(readList.size() + writeList.size() + exceptList.size());
|
||||
|
||||
nfds_t nfd = readList.size() + writeList.size() + exceptList.size();
|
||||
if (0 == nfd) return 0;
|
||||
|
||||
SharedPollArray pPollArr = new pollfd[nfd]();
|
||||
@ -256,7 +284,11 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce
|
||||
do
|
||||
{
|
||||
Poco::Timestamp start;
|
||||
#ifdef _WIN32
|
||||
rc = WSAPoll(pPollArr, nfd, static_cast<INT>(remainingTime.totalMilliseconds()));
|
||||
#else
|
||||
rc = ::poll(pPollArr, nfd, remainingTime.totalMilliseconds());
|
||||
#endif
|
||||
if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
|
||||
{
|
||||
Poco::Timestamp end;
|
||||
@ -276,17 +308,17 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce
|
||||
SocketList::iterator endE = exceptList.end();
|
||||
for (int idx = 0; idx < nfd; ++idx)
|
||||
{
|
||||
SocketList::iterator slIt = std::find_if(begR, endR, Socket::FDCompare(pPollArr[idx].fd));
|
||||
SocketList::iterator slIt = std::find_if(begR, endR, Socket::FDCompare(static_cast<int>(pPollArr[idx].fd)));
|
||||
if (POLLIN & pPollArr[idx].revents && slIt != endR) readyReadList.push_back(*slIt);
|
||||
slIt = std::find_if(begW, endW, Socket::FDCompare(pPollArr[idx].fd));
|
||||
slIt = std::find_if(begW, endW, Socket::FDCompare(static_cast<int>(pPollArr[idx].fd)));
|
||||
if (POLLOUT & pPollArr[idx].revents && slIt != endW) readyWriteList.push_back(*slIt);
|
||||
slIt = std::find_if(begE, endE, Socket::FDCompare(pPollArr[idx].fd));
|
||||
slIt = std::find_if(begE, endE, Socket::FDCompare(static_cast<int>(pPollArr[idx].fd)));
|
||||
if (POLLERR & pPollArr[idx].revents && slIt != endE) readyExceptList.push_back(*slIt);
|
||||
}
|
||||
std::swap(readList, readyReadList);
|
||||
std::swap(writeList, readyWriteList);
|
||||
std::swap(exceptList, readyExceptList);
|
||||
return readList.size() + writeList.size() + exceptList.size();
|
||||
return static_cast<int>(readList.size() + writeList.size() + exceptList.size());
|
||||
|
||||
#else
|
||||
|
||||
@ -464,4 +496,16 @@ SocketBufVec Socket::makeBufVec(const std::vector<std::string>& vec)
|
||||
}
|
||||
|
||||
|
||||
int Socket::lastError()
|
||||
{
|
||||
return SocketImpl::lastError();
|
||||
}
|
||||
|
||||
|
||||
void Socket::error()
|
||||
{
|
||||
SocketImpl::error();
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
@ -150,6 +150,12 @@ SocketAddress::SocketAddress(const SocketAddress& socketAddress)
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(SocketAddress&& socketAddress):
|
||||
_pImpl(std::move(socketAddress._pImpl))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SocketAddress::SocketAddress(const struct sockaddr* sockAddr, poco_socklen_t length)
|
||||
{
|
||||
if (length == sizeof(struct sockaddr_in) && sockAddr->sa_family == AF_INET)
|
||||
@ -203,6 +209,13 @@ SocketAddress& SocketAddress::operator = (const SocketAddress& socketAddress)
|
||||
}
|
||||
|
||||
|
||||
SocketAddress& SocketAddress::operator = (SocketAddress&& socketAddress)
|
||||
{
|
||||
_pImpl = std::move(socketAddress._pImpl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
IPAddress SocketAddress::host() const
|
||||
{
|
||||
return pImpl()->host();
|
||||
|
@ -20,23 +20,12 @@
|
||||
#include <string.h> // FD_SET needs memset on some platforms, so we can't use <cstring>
|
||||
|
||||
|
||||
#if defined(_WIN32) && _WIN32_WINNT >= 0x0600
|
||||
#ifndef POCO_HAVE_FD_POLL
|
||||
#define POCO_HAVE_FD_POLL 1
|
||||
#endif
|
||||
#elif defined(POCO_OS_FAMILY_BSD)
|
||||
#ifndef POCO_HAVE_FD_POLL
|
||||
#define POCO_HAVE_FD_POLL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(POCO_HAVE_FD_EPOLL)
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/epoll.h>
|
||||
#elif defined(POCO_HAVE_FD_POLL)
|
||||
#ifndef _WIN32
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -219,10 +208,8 @@ void SocketImpl::bind(const SocketAddress& address, bool reuseAddress, bool reus
|
||||
{
|
||||
init(address.af());
|
||||
}
|
||||
if (reuseAddress)
|
||||
setReuseAddress(true);
|
||||
if (reusePort)
|
||||
setReusePort(true);
|
||||
setReuseAddress(reuseAddress);
|
||||
setReusePort(reusePort);
|
||||
#if defined(POCO_VXWORKS)
|
||||
int rc = ::bind(_sockfd, (sockaddr*) address.addr(), address.length());
|
||||
#else
|
||||
@ -253,10 +240,8 @@ void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool reu
|
||||
#else
|
||||
if (ipV6Only) throw Poco::NotImplementedException("IPV6_V6ONLY not defined.");
|
||||
#endif
|
||||
if (reuseAddress)
|
||||
setReuseAddress(true);
|
||||
if (reusePort)
|
||||
setReusePort(true);
|
||||
setReuseAddress(reuseAddress);
|
||||
setReusePort(reusePort);
|
||||
int rc = ::bind(_sockfd, address.addr(), address.length());
|
||||
if (rc != 0) error(address.toString());
|
||||
#else
|
||||
@ -614,6 +599,13 @@ int SocketImpl::available()
|
||||
{
|
||||
int result = 0;
|
||||
ioctl(FIONREAD, result);
|
||||
#if (POCO_OS != POCO_OS_LINUX)
|
||||
if (type() == SOCKET_TYPE_DATAGRAM)
|
||||
{
|
||||
std::vector<char> buf(result);
|
||||
result = recvfrom(sockfd(), &buf[0], result, MSG_PEEK, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -759,6 +751,14 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode)
|
||||
}
|
||||
|
||||
|
||||
int SocketImpl::getError()
|
||||
{
|
||||
int result;
|
||||
getOption(SOL_SOCKET, SO_ERROR, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void SocketImpl::setSendBufferSize(int size)
|
||||
{
|
||||
setOption(SOL_SOCKET, SO_SNDBUF, size);
|
||||
@ -1027,14 +1027,25 @@ void SocketImpl::setReuseAddress(bool flag)
|
||||
{
|
||||
int value = flag ? 1 : 0;
|
||||
setOption(SOL_SOCKET, SO_REUSEADDR, value);
|
||||
#ifdef POCO_OS_FAMILY_WINDOWS
|
||||
value = flag ? 0 : 1;
|
||||
setOption(SOL_SOCKET, SO_EXCLUSIVEADDRUSE, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool SocketImpl::getReuseAddress()
|
||||
{
|
||||
bool ret = false;
|
||||
int value(0);
|
||||
getOption(SOL_SOCKET, SO_REUSEADDR, value);
|
||||
return value != 0;
|
||||
ret = (value != 0);
|
||||
#ifdef POCO_OS_FAMILY_WINDOWS
|
||||
value = 0;
|
||||
getOption(SOL_SOCKET, SO_EXCLUSIVEADDRUSE, value);
|
||||
ret = ret && (value == 0);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
808
Net/src/SocketProactor.cpp
Normal file
808
Net/src/SocketProactor.cpp
Normal file
@ -0,0 +1,808 @@
|
||||
//
|
||||
// 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
|
@ -179,11 +179,14 @@ bool SocketReactor::hasEventHandler(const Socket& socket, const Poco::AbstractOb
|
||||
|
||||
SocketReactor::NotifierPtr SocketReactor::getNotifier(const Socket& socket, bool makeNew)
|
||||
{
|
||||
const SocketImpl* pImpl = socket.impl();
|
||||
if (pImpl == nullptr) return 0;
|
||||
poco_socket_t sockfd = pImpl->sockfd();
|
||||
ScopedLock lock(_mutex);
|
||||
|
||||
EventHandlerMap::iterator it = _handlers.find(socket);
|
||||
EventHandlerMap::iterator it = _handlers.find(sockfd);
|
||||
if (it != _handlers.end()) return it->second;
|
||||
else if (makeNew) return (_handlers[socket] = new SocketNotifier(socket));
|
||||
else if (makeNew) return (_handlers[sockfd] = new SocketNotifier(socket));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -191,6 +194,8 @@ SocketReactor::NotifierPtr SocketReactor::getNotifier(const Socket& socket, bool
|
||||
|
||||
void SocketReactor::removeEventHandler(const Socket& socket, const Poco::AbstractObserver& observer)
|
||||
{
|
||||
const SocketImpl* pImpl = socket.impl();
|
||||
if (pImpl == nullptr) return;
|
||||
NotifierPtr pNotifier = getNotifier(socket);
|
||||
if (pNotifier && pNotifier->hasObserver(observer))
|
||||
{
|
||||
@ -198,7 +203,7 @@ void SocketReactor::removeEventHandler(const Socket& socket, const Poco::Abstrac
|
||||
{
|
||||
{
|
||||
ScopedLock lock(_mutex);
|
||||
_handlers.erase(socket);
|
||||
_handlers.erase(pImpl->sockfd());
|
||||
}
|
||||
_pollSet.remove(socket);
|
||||
}
|
||||
|
@ -51,6 +51,11 @@ StreamSocket::StreamSocket(const Socket& socket): Socket(socket)
|
||||
}
|
||||
|
||||
|
||||
StreamSocket::StreamSocket(const StreamSocket& socket): Socket(socket)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
StreamSocket::StreamSocket(SocketImpl* pImpl): Socket(pImpl)
|
||||
{
|
||||
if (!dynamic_cast<StreamSocketImpl*>(impl()))
|
||||
@ -73,6 +78,40 @@ StreamSocket& StreamSocket::operator = (const Socket& socket)
|
||||
}
|
||||
|
||||
|
||||
StreamSocket& StreamSocket::operator = (const StreamSocket& socket)
|
||||
{
|
||||
Socket::operator = (socket);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
StreamSocket::StreamSocket(Socket&& socket): Socket(std::move(socket))
|
||||
{
|
||||
if (!dynamic_cast<StreamSocketImpl*>(impl()))
|
||||
throw InvalidArgumentException("Cannot assign incompatible socket");
|
||||
}
|
||||
|
||||
|
||||
StreamSocket::StreamSocket(StreamSocket&& socket): Socket(std::move(socket))
|
||||
{
|
||||
}
|
||||
|
||||
StreamSocket& StreamSocket::operator = (Socket&& socket)
|
||||
{
|
||||
Socket::operator = (std::move(socket));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
StreamSocket& StreamSocket::operator = (StreamSocket&& socket)
|
||||
{
|
||||
Socket::operator = (std::move(socket));
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // POCO_NEW_STATE_ON_MOVE
|
||||
|
||||
void StreamSocket::connect(const SocketAddress& address)
|
||||
{
|
||||
impl()->connect(address);
|
||||
|
@ -65,6 +65,26 @@ WebSocket::WebSocket(const Socket& socket):
|
||||
}
|
||||
|
||||
|
||||
WebSocket::WebSocket(Socket&& socket):
|
||||
StreamSocket(std::move(socket))
|
||||
{
|
||||
if (!dynamic_cast<WebSocketImpl*>(impl()))
|
||||
throw InvalidArgumentException("Cannot assign incompatible socket");
|
||||
}
|
||||
|
||||
|
||||
WebSocket::WebSocket(const WebSocket& socket):
|
||||
StreamSocket(socket)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
WebSocket::WebSocket(WebSocket&& socket):
|
||||
StreamSocket(std::move(socket))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
WebSocket::~WebSocket()
|
||||
{
|
||||
}
|
||||
@ -80,6 +100,30 @@ WebSocket& WebSocket::operator = (const Socket& socket)
|
||||
}
|
||||
|
||||
|
||||
WebSocket& WebSocket::operator = (Socket&& socket)
|
||||
{
|
||||
if (dynamic_cast<WebSocketImpl*>(socket.impl()))
|
||||
Socket::operator = (std::move(socket));
|
||||
else
|
||||
throw InvalidArgumentException("Cannot assign incompatible socket");
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
WebSocket& WebSocket::operator = (const WebSocket& socket)
|
||||
{
|
||||
Socket::operator = (socket);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
WebSocket& WebSocket::operator = (WebSocket&& socket)
|
||||
{
|
||||
Socket::operator = (std::move(socket));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void WebSocket::shutdown()
|
||||
{
|
||||
shutdown(WS_NORMAL_CLOSE);
|
||||
|
@ -19,7 +19,7 @@ objects = \
|
||||
MediaTypeTest QuotedPrintableTest DialogSocketTest \
|
||||
HTTPClientTestSuite FTPClientTestSuite FTPClientSessionTest \
|
||||
FTPStreamFactoryTest DialogServer \
|
||||
SocketReactorTest ReactorTestSuite \
|
||||
SocketReactorTest ReactorTestSuite SocketProactorTest \
|
||||
MailTestSuite MailMessageTest MailStreamTest \
|
||||
SMTPClientSessionTest POP3ClientSessionTest \
|
||||
RawSocketTest ICMPClientTest ICMPSocketTest ICMPClientTestSuite \
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="debug_shared|Win32">
|
||||
@ -56,7 +56,7 @@
|
||||
<RootNamespace>TestSuite</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
@ -117,45 +117,45 @@
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
|
||||
<ImportGroup Label="ExtensionSettings"/>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|x64'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|x64'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'" Label="PropertySheets">
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
||||
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros"/>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>15.0.28307.799</_ProjectFileVersion>
|
||||
<TargetName Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">TestSuited</TargetName>
|
||||
@ -243,7 +243,7 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>Default</CompileAs>
|
||||
@ -275,9 +275,9 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat/>
|
||||
<DebugInformationFormat />
|
||||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -304,7 +304,7 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>Default</CompileAs>
|
||||
@ -336,9 +336,9 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat/>
|
||||
<DebugInformationFormat />
|
||||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -365,7 +365,7 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>Default</CompileAs>
|
||||
@ -397,9 +397,9 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat/>
|
||||
<DebugInformationFormat />
|
||||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -426,7 +426,7 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>Default</CompileAs>
|
||||
@ -458,9 +458,9 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat/>
|
||||
<DebugInformationFormat />
|
||||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -487,7 +487,7 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>Default</CompileAs>
|
||||
@ -519,9 +519,9 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat/>
|
||||
<DebugInformationFormat />
|
||||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -548,7 +548,7 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>Default</CompileAs>
|
||||
@ -580,9 +580,9 @@
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat/>
|
||||
<DebugInformationFormat />
|
||||
<CompileAs>Default</CompileAs>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -598,70 +598,71 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\DatagramSocketTest.h"/>
|
||||
<ClInclude Include="src\DialogServer.h"/>
|
||||
<ClInclude Include="src\DialogSocketTest.h"/>
|
||||
<ClInclude Include="src\DNSTest.h"/>
|
||||
<ClInclude Include="src\EchoServer.h"/>
|
||||
<ClInclude Include="src\FTPClientSessionTest.h"/>
|
||||
<ClInclude Include="src\FTPClientTestSuite.h"/>
|
||||
<ClInclude Include="src\FTPStreamFactoryTest.h"/>
|
||||
<ClInclude Include="src\HTMLFormTest.h"/>
|
||||
<ClInclude Include="src\HTMLTestSuite.h"/>
|
||||
<ClInclude Include="src\HTTPClientSessionTest.h"/>
|
||||
<ClInclude Include="src\HTTPClientTestSuite.h"/>
|
||||
<ClInclude Include="src\HTTPCookieTest.h"/>
|
||||
<ClInclude Include="src\HTTPCredentialsTest.h"/>
|
||||
<ClInclude Include="src\HTTPRequestTest.h"/>
|
||||
<ClInclude Include="src\HTTPResponseTest.h"/>
|
||||
<ClInclude Include="src\HTTPServerTest.h"/>
|
||||
<ClInclude Include="src\HTTPServerTestSuite.h"/>
|
||||
<ClInclude Include="src\HTTPStreamFactoryTest.h"/>
|
||||
<ClInclude Include="src\HTTPTestServer.h"/>
|
||||
<ClInclude Include="src\HTTPTestSuite.h"/>
|
||||
<ClInclude Include="src\ICMPClientTest.h"/>
|
||||
<ClInclude Include="src\ICMPClientTestSuite.h"/>
|
||||
<ClInclude Include="src\ICMPSocketTest.h"/>
|
||||
<ClInclude Include="src\IPAddressTest.h"/>
|
||||
<ClInclude Include="src\MailMessageTest.h"/>
|
||||
<ClInclude Include="src\MailStreamTest.h"/>
|
||||
<ClInclude Include="src\MailTestSuite.h"/>
|
||||
<ClInclude Include="src\MediaTypeTest.h"/>
|
||||
<ClInclude Include="src\MessageHeaderTest.h"/>
|
||||
<ClInclude Include="src\MessagesTestSuite.h"/>
|
||||
<ClInclude Include="src\MulticastEchoServer.h"/>
|
||||
<ClInclude Include="src\MulticastSocketTest.h"/>
|
||||
<ClInclude Include="src\MultipartReaderTest.h"/>
|
||||
<ClInclude Include="src\MultipartWriterTest.h"/>
|
||||
<ClInclude Include="src\NameValueCollectionTest.h"/>
|
||||
<ClInclude Include="src\NetCoreTestSuite.h"/>
|
||||
<ClInclude Include="src\NetTestSuite.h"/>
|
||||
<ClInclude Include="src\NetworkInterfaceTest.h"/>
|
||||
<ClInclude Include="src\NTLMCredentialsTest.h"/>
|
||||
<ClInclude Include="src\NTPClientTest.h"/>
|
||||
<ClInclude Include="src\NTPClientTestSuite.h"/>
|
||||
<ClInclude Include="src\OAuth10CredentialsTest.h"/>
|
||||
<ClInclude Include="src\OAuth20CredentialsTest.h"/>
|
||||
<ClInclude Include="src\OAuthTestSuite.h"/>
|
||||
<ClInclude Include="src\PollSetTest.h"/>
|
||||
<ClInclude Include="src\POP3ClientSessionTest.h"/>
|
||||
<ClInclude Include="src\QuotedPrintableTest.h"/>
|
||||
<ClInclude Include="src\RawSocketTest.h"/>
|
||||
<ClInclude Include="src\ReactorTestSuite.h"/>
|
||||
<ClInclude Include="src\SMTPClientSessionTest.h"/>
|
||||
<ClInclude Include="src\SocketAddressTest.h"/>
|
||||
<ClInclude Include="src\SocketReactorTest.h"/>
|
||||
<ClInclude Include="src\SocketsTestSuite.h"/>
|
||||
<ClInclude Include="src\SocketStreamTest.h"/>
|
||||
<ClInclude Include="src\SocketTest.h"/>
|
||||
<ClInclude Include="src\SyslogTest.h"/>
|
||||
<ClInclude Include="src\TCPServerTest.h"/>
|
||||
<ClInclude Include="src\TCPServerTestSuite.h"/>
|
||||
<ClInclude Include="src\UDPEchoServer.h"/>
|
||||
<ClInclude Include="src\UDPServerTest.h"/>
|
||||
<ClInclude Include="src\UDPServerTestSuite.h"/>
|
||||
<ClInclude Include="src\WebSocketTest.h"/>
|
||||
<ClInclude Include="src\WebSocketTestSuite.h"/>
|
||||
<ClInclude Include="src\DatagramSocketTest.h" />
|
||||
<ClInclude Include="src\DialogServer.h" />
|
||||
<ClInclude Include="src\DialogSocketTest.h" />
|
||||
<ClInclude Include="src\DNSTest.h" />
|
||||
<ClInclude Include="src\EchoServer.h" />
|
||||
<ClInclude Include="src\FTPClientSessionTest.h" />
|
||||
<ClInclude Include="src\FTPClientTestSuite.h" />
|
||||
<ClInclude Include="src\FTPStreamFactoryTest.h" />
|
||||
<ClInclude Include="src\HTMLFormTest.h" />
|
||||
<ClInclude Include="src\HTMLTestSuite.h" />
|
||||
<ClInclude Include="src\HTTPClientSessionTest.h" />
|
||||
<ClInclude Include="src\HTTPClientTestSuite.h" />
|
||||
<ClInclude Include="src\HTTPCookieTest.h" />
|
||||
<ClInclude Include="src\HTTPCredentialsTest.h" />
|
||||
<ClInclude Include="src\HTTPRequestTest.h" />
|
||||
<ClInclude Include="src\HTTPResponseTest.h" />
|
||||
<ClInclude Include="src\HTTPServerTest.h" />
|
||||
<ClInclude Include="src\HTTPServerTestSuite.h" />
|
||||
<ClInclude Include="src\HTTPStreamFactoryTest.h" />
|
||||
<ClInclude Include="src\HTTPTestServer.h" />
|
||||
<ClInclude Include="src\HTTPTestSuite.h" />
|
||||
<ClInclude Include="src\ICMPClientTest.h" />
|
||||
<ClInclude Include="src\ICMPClientTestSuite.h" />
|
||||
<ClInclude Include="src\ICMPSocketTest.h" />
|
||||
<ClInclude Include="src\IPAddressTest.h" />
|
||||
<ClInclude Include="src\MailMessageTest.h" />
|
||||
<ClInclude Include="src\MailStreamTest.h" />
|
||||
<ClInclude Include="src\MailTestSuite.h" />
|
||||
<ClInclude Include="src\MediaTypeTest.h" />
|
||||
<ClInclude Include="src\MessageHeaderTest.h" />
|
||||
<ClInclude Include="src\MessagesTestSuite.h" />
|
||||
<ClInclude Include="src\MulticastEchoServer.h" />
|
||||
<ClInclude Include="src\MulticastSocketTest.h" />
|
||||
<ClInclude Include="src\MultipartReaderTest.h" />
|
||||
<ClInclude Include="src\MultipartWriterTest.h" />
|
||||
<ClInclude Include="src\NameValueCollectionTest.h" />
|
||||
<ClInclude Include="src\NetCoreTestSuite.h" />
|
||||
<ClInclude Include="src\NetTestSuite.h" />
|
||||
<ClInclude Include="src\NetworkInterfaceTest.h" />
|
||||
<ClInclude Include="src\NTLMCredentialsTest.h" />
|
||||
<ClInclude Include="src\NTPClientTest.h" />
|
||||
<ClInclude Include="src\NTPClientTestSuite.h" />
|
||||
<ClInclude Include="src\OAuth10CredentialsTest.h" />
|
||||
<ClInclude Include="src\OAuth20CredentialsTest.h" />
|
||||
<ClInclude Include="src\OAuthTestSuite.h" />
|
||||
<ClInclude Include="src\PollSetTest.h" />
|
||||
<ClInclude Include="src\POP3ClientSessionTest.h" />
|
||||
<ClInclude Include="src\QuotedPrintableTest.h" />
|
||||
<ClInclude Include="src\RawSocketTest.h" />
|
||||
<ClInclude Include="src\ReactorTestSuite.h" />
|
||||
<ClInclude Include="src\SMTPClientSessionTest.h" />
|
||||
<ClInclude Include="src\SocketAddressTest.h" />
|
||||
<ClInclude Include="src\SocketProactorTest.h" />
|
||||
<ClInclude Include="src\SocketReactorTest.h" />
|
||||
<ClInclude Include="src\SocketsTestSuite.h" />
|
||||
<ClInclude Include="src\SocketStreamTest.h" />
|
||||
<ClInclude Include="src\SocketTest.h" />
|
||||
<ClInclude Include="src\SyslogTest.h" />
|
||||
<ClInclude Include="src\TCPServerTest.h" />
|
||||
<ClInclude Include="src\TCPServerTestSuite.h" />
|
||||
<ClInclude Include="src\UDPEchoServer.h" />
|
||||
<ClInclude Include="src\UDPServerTest.h" />
|
||||
<ClInclude Include="src\UDPServerTestSuite.h" />
|
||||
<ClInclude Include="src\WebSocketTest.h" />
|
||||
<ClInclude Include="src\WebSocketTestSuite.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\DatagramSocketTest.cpp">
|
||||
@ -823,6 +824,7 @@
|
||||
<ClCompile Include="src\SocketAddressTest.cpp">
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SocketProactorTest.cpp" />
|
||||
<ClCompile Include="src\SocketReactorTest.cpp">
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
@ -860,6 +862,6 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
||||
<ImportGroup Label="ExtensionTargets"/>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
@ -363,6 +363,9 @@
|
||||
<ClInclude Include="src\UDPServerTestSuite.h">
|
||||
<Filter>UDP\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\SocketProactorTest.h">
|
||||
<Filter>Sockets\Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\DNSTest.cpp">
|
||||
@ -560,5 +563,8 @@
|
||||
<ClCompile Include="src\UDPServerTestSuite.cpp">
|
||||
<Filter>UDP\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SocketProactorTest.cpp">
|
||||
<Filter>Sockets\Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -13,12 +13,12 @@
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "UDPEchoServer.h"
|
||||
#include "Poco/Net/DatagramSocket.h"
|
||||
#include "Poco/Net/SocketAddress.h"
|
||||
#include "Poco/Net/NetworkInterface.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Timespan.h"
|
||||
#include "Poco/Buffer.h"
|
||||
#include "Poco/Stopwatch.h"
|
||||
#include "Poco/Thread.h"
|
||||
#include <cstring>
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ using Poco::Stopwatch;
|
||||
using Poco::TimeoutException;
|
||||
using Poco::InvalidArgumentException;
|
||||
using Poco::IOException;
|
||||
using Poco::Thread;
|
||||
|
||||
|
||||
DatagramSocketTest::DatagramSocketTest(const std::string& name): CppUnit::TestCase(name)
|
||||
@ -62,6 +63,46 @@ void DatagramSocketTest::testEcho()
|
||||
}
|
||||
|
||||
|
||||
void DatagramSocketTest::testMoveDatagramSocket()
|
||||
{
|
||||
UDPEchoServer echoServer;
|
||||
DatagramSocket ss0 = DatagramSocket();
|
||||
char buffer[256];
|
||||
ss0.connect(SocketAddress("127.0.0.1", echoServer.port()));
|
||||
DatagramSocket ss(std::move(ss0));
|
||||
#if POCO_NEW_STATE_ON_MOVE
|
||||
assertTrue (ss0.isNull());
|
||||
#else
|
||||
assertFalse (ss0.isNull());
|
||||
#endif
|
||||
int n = ss.sendBytes("hello", 5);
|
||||
assertTrue (n == 5);
|
||||
n = ss.receiveBytes(buffer, sizeof(buffer));
|
||||
assertTrue (n == 5);
|
||||
assertTrue (std::string(buffer, n) == "hello");
|
||||
|
||||
std::memset(buffer, 0, sizeof(buffer));
|
||||
ss0 = ss;
|
||||
assertTrue (ss0.impl());
|
||||
assertTrue (ss.impl());
|
||||
assertTrue (ss0.impl() == ss.impl());
|
||||
ss = std::move(ss0);
|
||||
#if POCO_NEW_STATE_ON_MOVE
|
||||
assertTrue (ss0.isNull());
|
||||
#else
|
||||
assertFalse (ss0.isNull());
|
||||
#endif
|
||||
assertTrue (ss.impl());
|
||||
n = ss.sendBytes("hello", 5);
|
||||
assertTrue (n == 5);
|
||||
n = ss.receiveBytes(buffer, sizeof(buffer));
|
||||
assertTrue (n == 5);
|
||||
assertTrue (std::string(buffer, n) == "hello");
|
||||
ss.close();
|
||||
ss0.close();
|
||||
}
|
||||
|
||||
|
||||
void DatagramSocketTest::testEchoBuffer()
|
||||
{
|
||||
UDPEchoServer echoServer;
|
||||
@ -81,6 +122,25 @@ void DatagramSocketTest::testEchoBuffer()
|
||||
}
|
||||
|
||||
|
||||
void DatagramSocketTest::testReceiveFromAvailable()
|
||||
{
|
||||
UDPEchoServer echoServer(SocketAddress("127.0.0.1", 0));
|
||||
DatagramSocket ss(SocketAddress::IPv4);
|
||||
int n = ss.sendTo("hello", 5, SocketAddress("127.0.0.1", echoServer.port()));
|
||||
assertTrue (n == 5);
|
||||
Thread::sleep(100);
|
||||
char buffer[256];
|
||||
SocketAddress sa;
|
||||
assertTrue (ss.available() == 5);
|
||||
n = ss.receiveFrom(buffer, sizeof(buffer), sa);
|
||||
assertTrue (sa.host() == echoServer.address().host());
|
||||
assertTrue (sa.port() == echoServer.port());
|
||||
assertTrue (n == 5);
|
||||
assertTrue (std::string(buffer, n) == "hello");
|
||||
ss.close();
|
||||
}
|
||||
|
||||
|
||||
void DatagramSocketTest::testSendToReceiveFrom()
|
||||
{
|
||||
UDPEchoServer echoServer(SocketAddress("127.0.0.1", 0));
|
||||
@ -113,6 +173,158 @@ void DatagramSocketTest::testUnbound()
|
||||
}
|
||||
|
||||
|
||||
Poco::UInt16 DatagramSocketTest::getFreePort(SocketAddress::Family family, Poco::UInt16 port)
|
||||
{
|
||||
bool failed = false;
|
||||
poco_assert_dbg(port > 0);
|
||||
--port;
|
||||
DatagramSocket sock(family);
|
||||
do
|
||||
{
|
||||
failed = false;
|
||||
SocketAddress sa(family, ++port);
|
||||
try
|
||||
{
|
||||
sock.bind(sa, false);
|
||||
}
|
||||
catch (Poco::Net::NetException&)
|
||||
{
|
||||
failed = true;
|
||||
}
|
||||
} while (failed && sock.getError() == POCO_EADDRINUSE);
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
void DatagramSocketTest::testReuseAddressPortWildcard()
|
||||
{
|
||||
Poco::UInt16 port = getFreePort(SocketAddress::IPv4, 1234);
|
||||
Poco::UInt16 port6 = getFreePort(SocketAddress::IPv6, 1234);
|
||||
assertTrue(port >= 1234);
|
||||
assertTrue(port6 >= 1234);
|
||||
|
||||
// reuse
|
||||
{
|
||||
DatagramSocket ds1(SocketAddress::IPv4);
|
||||
ds1.bind(SocketAddress(port), true);
|
||||
assertTrue(ds1.getReuseAddress());
|
||||
DatagramSocket ds2;
|
||||
ds2.bind(SocketAddress(port), true);
|
||||
assertTrue(ds2.getReuseAddress());
|
||||
#ifdef POCO_HAVE_IPv6
|
||||
DatagramSocket ds3(SocketAddress::IPv6);
|
||||
ds3.bind6(SocketAddress(SocketAddress::IPv6, port6), true, true, false);
|
||||
assertTrue(ds3.getReuseAddress());
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef POCO_HAVE_IPv6
|
||||
{
|
||||
DatagramSocket ds1(SocketAddress::IPv6);
|
||||
ds1.bind6(SocketAddress(SocketAddress::IPv6, port6), true, true, false);
|
||||
assertTrue(ds1.getReuseAddress());
|
||||
DatagramSocket ds2;
|
||||
ds2.bind6(SocketAddress(SocketAddress::IPv6, port6), true, true, false);
|
||||
assertTrue(ds2.getReuseAddress());
|
||||
DatagramSocket ds3;
|
||||
ds3.bind(SocketAddress(port), true, true);
|
||||
assertTrue(ds3.getReuseAddress());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef POCO_HAVE_IPv6
|
||||
{
|
||||
DatagramSocket ds1(SocketAddress::IPv6);
|
||||
ds1.bind6(SocketAddress(SocketAddress::IPv6, port), true, true, true);
|
||||
assertTrue(ds1.getReuseAddress());
|
||||
DatagramSocket ds2;
|
||||
ds2.bind6(SocketAddress(SocketAddress::IPv6, port), true, true, true);
|
||||
assertTrue(ds2.getReuseAddress());
|
||||
}
|
||||
#endif
|
||||
|
||||
// not reuse
|
||||
{
|
||||
DatagramSocket ds1(SocketAddress::IPv4);
|
||||
ds1.bind(SocketAddress(port), false);
|
||||
assertTrue(!ds1.getReuseAddress());
|
||||
DatagramSocket ds2;
|
||||
try
|
||||
{
|
||||
ds2.bind(SocketAddress(port), false);
|
||||
fail("binding to non-reuse address must throw");
|
||||
}
|
||||
catch (Poco::IOException&) {}
|
||||
|
||||
#ifdef POCO_HAVE_IPv6
|
||||
{
|
||||
DatagramSocket ds1(SocketAddress::IPv6);
|
||||
ds1.bind6(SocketAddress(SocketAddress::IPv6, port), false, false, true);
|
||||
assertTrue(!ds1.getReuseAddress());
|
||||
DatagramSocket ds2(SocketAddress::IPv6);
|
||||
try
|
||||
{
|
||||
ds2.bind6(SocketAddress(SocketAddress::IPv6, port), false, false, true);
|
||||
fail("binding to non-reuse address must throw");
|
||||
}
|
||||
catch (Poco::IOException&) {}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DatagramSocketTest::testReuseAddressPortSpecific()
|
||||
{
|
||||
Poco::UInt16 port = getFreePort(SocketAddress::IPv4, 1234);
|
||||
assertTrue(port >= 1234);
|
||||
|
||||
// reuse
|
||||
{
|
||||
DatagramSocket ds1(SocketAddress::IPv4);
|
||||
ds1.bind(SocketAddress(port), true);
|
||||
assertTrue(ds1.getReuseAddress());
|
||||
DatagramSocket ds2;
|
||||
ds2.bind(SocketAddress("127.0.0.1", port), true);
|
||||
assertTrue(ds2.getReuseAddress());
|
||||
#ifdef POCO_HAVE_IPv6
|
||||
DatagramSocket ds3(SocketAddress::IPv6);
|
||||
ds3.bind6(SocketAddress("::1", port), true, true, false);
|
||||
assertTrue(ds3.getReuseAddress());
|
||||
#endif
|
||||
}
|
||||
|
||||
// not reuse
|
||||
{
|
||||
DatagramSocket ds1(SocketAddress::IPv4);
|
||||
ds1.bind(SocketAddress("0.0.0.0", port), false);
|
||||
assertTrue(!ds1.getReuseAddress());
|
||||
DatagramSocket ds2;
|
||||
try
|
||||
{
|
||||
ds2.bind(SocketAddress("127.0.0.1", port), false);
|
||||
fail("binding to non-reuse IPv4 address must throw");
|
||||
}
|
||||
catch (Poco::IOException&) {}
|
||||
|
||||
#ifdef POCO_HAVE_IPv6
|
||||
{
|
||||
DatagramSocket ds1(SocketAddress::IPv6);
|
||||
ds1.bind6(SocketAddress("::", port), false, false, true);
|
||||
assertTrue(!ds1.getReuseAddress());
|
||||
DatagramSocket ds2(SocketAddress::IPv6);
|
||||
try
|
||||
{
|
||||
ds2.bind6(SocketAddress("::1", port), false, false, true);
|
||||
fail("binding to non-reuse IPv6 address must throw");
|
||||
}
|
||||
catch (Poco::IOException&) {}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DatagramSocketTest::testBroadcast()
|
||||
{
|
||||
UDPEchoServer echoServer;
|
||||
@ -607,9 +819,13 @@ CppUnit::Test* DatagramSocketTest::suite()
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DatagramSocketTest");
|
||||
|
||||
CppUnit_addTest(pSuite, DatagramSocketTest, testEcho);
|
||||
CppUnit_addTest(pSuite, DatagramSocketTest, testMoveDatagramSocket);
|
||||
CppUnit_addTest(pSuite, DatagramSocketTest, testEchoBuffer);
|
||||
CppUnit_addTest(pSuite, DatagramSocketTest, testReceiveFromAvailable);
|
||||
CppUnit_addTest(pSuite, DatagramSocketTest, testSendToReceiveFrom);
|
||||
CppUnit_addTest(pSuite, DatagramSocketTest, testUnbound);
|
||||
CppUnit_addTest(pSuite, DatagramSocketTest, testReuseAddressPortWildcard);
|
||||
CppUnit_addTest(pSuite, DatagramSocketTest, testReuseAddressPortSpecific);
|
||||
#if (POCO_OS != POCO_OS_FREE_BSD) // works only with local net bcast and very randomly
|
||||
CppUnit_addTest(pSuite, DatagramSocketTest, testBroadcast);
|
||||
#endif
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
|
||||
#include "Poco/Net/Net.h"
|
||||
#include "Poco/Net/SocketAddress.h"
|
||||
#include "CppUnit/TestCase.h"
|
||||
|
||||
|
||||
@ -25,9 +26,13 @@ public:
|
||||
~DatagramSocketTest();
|
||||
|
||||
void testEcho();
|
||||
void testMoveDatagramSocket();
|
||||
void testEchoBuffer();
|
||||
void testReceiveFromAvailable();
|
||||
void testSendToReceiveFrom();
|
||||
void testUnbound();
|
||||
void testReuseAddressPortWildcard();
|
||||
void testReuseAddressPortSpecific();
|
||||
void testBroadcast();
|
||||
void testGatherScatterFixed();
|
||||
void testGatherScatterVariable();
|
||||
@ -38,6 +43,8 @@ public:
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
static Poco::UInt16 getFreePort(Poco::Net::SocketAddress::Family family, std::uint16_t port);
|
||||
|
||||
// "STRF" are sendto/recvfrom versions of the same functionality
|
||||
void testGatherScatterFixedWin();
|
||||
void testGatherScatterSTRFFixedWin();
|
||||
|
@ -59,7 +59,7 @@ void ICMPClientTest::testPing()
|
||||
assertTrue (icmpClient.ping("10.0.2.15", 4) > 0);
|
||||
assertTrue (icmpClient.ping("10.0.2.2", 4) > 0);
|
||||
#else
|
||||
assertTrue (icmpClient.ping("www.appinf.com", 4) > 0);
|
||||
assertTrue (icmpClient.ping("github.com", 4) > 0);
|
||||
|
||||
// warning: may fail depending on the existence of the addresses at test site
|
||||
// if so, adjust accordingly (i.e. specify non-existent or unreachable IP addresses)
|
||||
@ -86,7 +86,7 @@ void ICMPClientTest::testBigPing()
|
||||
assertTrue (icmpClient.ping("10.0.2.15", 4) > 0);
|
||||
assertTrue (icmpClient.ping("10.0.2.2", 4) > 0);
|
||||
#else
|
||||
assertTrue (icmpClient.ping("www.appinf.com", 4) > 0);
|
||||
assertTrue (icmpClient.ping("github.com", 4) > 0);
|
||||
|
||||
// warning: may fail depending on the existence of the addresses at test site
|
||||
// if so, adjust accordingly (i.e. specify non-existent or unreachable IP addresses)
|
||||
|
@ -56,7 +56,7 @@ void ICMPSocketTest::testSendToReceiveFrom()
|
||||
{
|
||||
ICMPSocket ss(IPAddress::IPv4);
|
||||
|
||||
SocketAddress sa("www.appinf.com", 0);
|
||||
SocketAddress sa("github.com", 0);
|
||||
SocketAddress sr(sa);
|
||||
|
||||
try
|
||||
@ -90,7 +90,7 @@ void ICMPSocketTest::testMTU()
|
||||
std::cout << addr.toString() << " : MTU=" << mtu << std::endl;
|
||||
assertTrue (mtu != 0);
|
||||
sz = 1500;
|
||||
addr = SocketAddress("www.appinf.com:0");
|
||||
addr = SocketAddress("github.com:0");
|
||||
mtu = ICMPSocket::mtu(addr, sz);
|
||||
std::cout << addr.toString() << " : MTU=" << mtu << std::endl;
|
||||
assertTrue (mtu != 0 && mtu <= sz);
|
||||
|
@ -31,11 +31,13 @@ IPAddressTest::~IPAddressTest()
|
||||
|
||||
void IPAddressTest::testStringConv()
|
||||
{
|
||||
IPAddress ia1("127.0.0.1");
|
||||
IPAddress ia01 = IPAddress("127.0.0.1");
|
||||
IPAddress ia1(std::move(ia01));
|
||||
assertTrue (ia1.family() == IPAddress::IPv4);
|
||||
assertTrue (ia1.toString() == "127.0.0.1");
|
||||
|
||||
IPAddress ia2("192.168.1.120");
|
||||
IPAddress ia02 = IPAddress("192.168.1.120");
|
||||
IPAddress ia2(std::move(ia02));
|
||||
assertTrue (ia2.family() == IPAddress::IPv4);
|
||||
assertTrue (ia2.toString() == "192.168.1.120");
|
||||
|
||||
@ -56,15 +58,18 @@ void IPAddressTest::testStringConv()
|
||||
void IPAddressTest::testStringConv6()
|
||||
{
|
||||
#ifdef POCO_HAVE_IPv6
|
||||
IPAddress ia0("::1");
|
||||
IPAddress ia00 = IPAddress("::1");
|
||||
IPAddress ia0(std::move(ia00));
|
||||
assertTrue (ia0.family() == IPAddress::IPv6);
|
||||
assertTrue (ia0.toString() == "::1");
|
||||
|
||||
IPAddress ia1("1080:0:0:0:8:600:200a:425c");
|
||||
IPAddress ia01 = IPAddress("1080:0:0:0:8:600:200a:425c");
|
||||
IPAddress ia1(std::move(ia01));
|
||||
assertTrue (ia1.family() == IPAddress::IPv6);
|
||||
assertTrue (ia1.toString() == "1080::8:600:200a:425c");
|
||||
|
||||
IPAddress ia2("1080::8:600:200A:425C");
|
||||
IPAddress ia02 = IPAddress("1080::8:600:200A:425C");
|
||||
IPAddress ia2(std::move(ia02));
|
||||
assertTrue (ia2.family() == IPAddress::IPv6);
|
||||
assertTrue (ia2.toString() == "1080::8:600:200a:425c");
|
||||
|
||||
@ -94,8 +99,9 @@ void IPAddressTest::testStringConv6()
|
||||
void IPAddressTest::testParse()
|
||||
{
|
||||
IPAddress ip;
|
||||
assertTrue (IPAddress::tryParse("0.0.0.0", ip));
|
||||
assertTrue (IPAddress::tryParse("255.255.255.255", ip));
|
||||
assertTrue (IPAddress::tryParse("192.168.1.120", ip));
|
||||
|
||||
assertTrue (!IPAddress::tryParse("192.168.1.280", ip));
|
||||
|
||||
ip = IPAddress::parse("192.168.1.120");
|
||||
@ -107,6 +113,33 @@ void IPAddressTest::testParse()
|
||||
catch (InvalidAddressException&)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef POCO_HAVE_IPv6
|
||||
assertTrue (IPAddress::tryParse("::", ip));
|
||||
assertFalse (IPAddress::tryParse(":::", ip));
|
||||
assertTrue (IPAddress::tryParse("0::", ip));
|
||||
assertTrue (IPAddress::tryParse("0:0::", ip));
|
||||
assertTrue (IPAddress::tryParse("0:0:0::", ip));
|
||||
assertTrue (IPAddress::tryParse("0:0:0:0::", ip));
|
||||
assertTrue (IPAddress::tryParse("0:0:0:0:0::", ip));
|
||||
assertTrue (IPAddress::tryParse("0:0:0:0:0:0::", ip));
|
||||
assertTrue (IPAddress::tryParse("0:0:0:0:0:0:0::", ip));
|
||||
assertTrue (IPAddress::tryParse("0:0:0:0:0:0:0:0", ip));
|
||||
assertFalse (IPAddress::tryParse("0:0:0:0:0:0:0:0:", ip));
|
||||
assertFalse (IPAddress::tryParse("::0:0::", ip));
|
||||
assertFalse (IPAddress::tryParse("::0::0::", ip));
|
||||
|
||||
assertTrue (IPAddress::tryParse("::1", ip));
|
||||
assertTrue (IPAddress::tryParse("1080:0:0:0:8:600:200a:425c", ip));
|
||||
assertTrue (IPAddress::tryParse("1080::8:600:200a:425c", ip));
|
||||
assertTrue (IPAddress::tryParse("1080::8:600:200A:425C", ip));
|
||||
assertTrue (IPAddress::tryParse("1080::8:600:200a:425c", ip));
|
||||
assertTrue (IPAddress::tryParse("::192.168.1.120", ip));
|
||||
assertTrue (IPAddress::tryParse("::ffff:192.168.1.120", ip));
|
||||
assertTrue (IPAddress::tryParse("::ffff:192.168.1.120", ip));
|
||||
assertTrue (IPAddress::tryParse("ffff:ffff:ffff:ffff::", ip));
|
||||
assertTrue (IPAddress::tryParse("ffff:ffff::", ip));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/PollSet.h"
|
||||
#include "Poco/Stopwatch.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
using Poco::Net::Socket;
|
||||
@ -31,6 +32,38 @@ using Poco::Stopwatch;
|
||||
using Poco::Thread;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class Poller : public Poco::Runnable
|
||||
{
|
||||
public:
|
||||
Poller(PollSet& pollSet, const Timespan& timeout): _pollSet(pollSet),
|
||||
_timeout(timeout)
|
||||
{
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
_running = true;
|
||||
_pollSet.poll(_timeout);
|
||||
_running = false;
|
||||
}
|
||||
|
||||
bool isRunning()
|
||||
{
|
||||
return _running;
|
||||
}
|
||||
|
||||
private:
|
||||
PollSet& _pollSet;
|
||||
Timespan _timeout;
|
||||
bool _running = false;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
PollSetTest::PollSetTest(const std::string& name): CppUnit::TestCase(name)
|
||||
{
|
||||
}
|
||||
@ -41,6 +74,69 @@ PollSetTest::~PollSetTest()
|
||||
}
|
||||
|
||||
|
||||
void PollSetTest::testTimeout()
|
||||
{
|
||||
EchoServer echoServer;
|
||||
StreamSocket ss;
|
||||
ss.connect(SocketAddress("127.0.0.1", echoServer.port()));
|
||||
PollSet ps;
|
||||
ps.add(ss, PollSet::POLL_READ);
|
||||
Timespan timeout(1000000);
|
||||
Stopwatch sw; sw.start();
|
||||
PollSet::SocketModeMap sm = ps.poll(timeout);
|
||||
sw.stop();
|
||||
assertTrue(sm.empty());
|
||||
assertTrue(sw.elapsed() >= 900000);
|
||||
|
||||
ss.sendBytes("hello", 5);
|
||||
sw.restart();
|
||||
sm = ps.poll(timeout);
|
||||
sw.stop();
|
||||
assertTrue(ps.poll(timeout).size() == 1);
|
||||
|
||||
// just here to prevent server exception on connection reset
|
||||
char buffer[5];
|
||||
ss.receiveBytes(buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
|
||||
void PollSetTest::testPollNB()
|
||||
{
|
||||
EchoServer echoServer1;
|
||||
StreamSocket ss1;
|
||||
|
||||
ss1.connectNB(SocketAddress("127.0.0.1", echoServer1.port()));
|
||||
|
||||
PollSet ps;
|
||||
assertTrue(ps.empty());
|
||||
ps.add(ss1, PollSet::POLL_READ);
|
||||
ps.add(ss1, PollSet::POLL_WRITE);
|
||||
assertTrue(!ps.empty());
|
||||
assertTrue(ps.has(ss1));
|
||||
|
||||
while (!ss1.poll(Timespan(0, 10000), Socket::SELECT_WRITE))
|
||||
Poco::Thread::sleep(10);
|
||||
|
||||
Timespan timeout(1000000);
|
||||
PollSet::SocketModeMap sm;
|
||||
while (sm.empty()) sm = ps.poll(timeout);
|
||||
assertTrue(sm.find(ss1) != sm.end());
|
||||
assertTrue(sm.find(ss1)->second | PollSet::POLL_WRITE);
|
||||
|
||||
ss1.setBlocking(true);
|
||||
ss1.sendBytes("hello", 5);
|
||||
char buffer[256];
|
||||
|
||||
sm = ps.poll(timeout);
|
||||
assertTrue(sm.find(ss1) != sm.end());
|
||||
assertTrue(sm.find(ss1)->second | PollSet::POLL_READ);
|
||||
|
||||
int n = ss1.receiveBytes(buffer, sizeof(buffer));
|
||||
assertTrue(n == 5);
|
||||
assertTrue(std::string(buffer, n) == "hello");
|
||||
}
|
||||
|
||||
|
||||
void PollSetTest::testPoll()
|
||||
{
|
||||
EchoServer echoServer1;
|
||||
@ -76,31 +172,32 @@ void PollSetTest::testPoll()
|
||||
PollSet::SocketModeMap sm = ps.poll(timeout);
|
||||
assertTrue (sm.find(ss1) != sm.end());
|
||||
assertTrue (sm.find(ss2) == sm.end());
|
||||
assertTrue (sm.find(ss1)->second == PollSet::POLL_WRITE);
|
||||
assertTrue (sm.find(ss1)->second | PollSet::POLL_WRITE);
|
||||
assertTrue (sw.elapsed() < 1100000);
|
||||
|
||||
ps.update(ss1, PollSet::POLL_READ);
|
||||
|
||||
ss1.setBlocking(true);
|
||||
ss1.sendBytes("hello", 5);
|
||||
char buffer[256];
|
||||
sw.restart();
|
||||
sm = ps.poll(timeout);
|
||||
assertTrue (sm.find(ss1) != sm.end());
|
||||
assertTrue (sm.find(ss2) == sm.end());
|
||||
assertTrue (sm.find(ss1)->second == PollSet::POLL_READ);
|
||||
assertTrue (sm.find(ss1)->second | PollSet::POLL_READ);
|
||||
assertTrue (sw.elapsed() < 1100000);
|
||||
|
||||
int n = ss1.receiveBytes(buffer, sizeof(buffer));
|
||||
assertTrue (n == 5);
|
||||
assertTrue (std::string(buffer, n) == "hello");
|
||||
|
||||
|
||||
ss2.setBlocking(true);
|
||||
ss2.sendBytes("HELLO", 5);
|
||||
sw.restart();
|
||||
sm = ps.poll(timeout);
|
||||
assertTrue (sm.find(ss1) == sm.end());
|
||||
assertTrue (sm.find(ss2) != sm.end());
|
||||
assertTrue (sm.find(ss2)->second == PollSet::POLL_READ);
|
||||
assertTrue (sm.find(ss2)->second | PollSet::POLL_READ);
|
||||
assertTrue (sw.elapsed() < 1100000);
|
||||
|
||||
n = ss2.receiveBytes(buffer, sizeof(buffer));
|
||||
@ -128,16 +225,14 @@ void PollSetTest::testPoll()
|
||||
|
||||
void PollSetTest::testPollNoServer()
|
||||
{
|
||||
#ifndef POCO_OS_FAMILY_WINDOWS
|
||||
StreamSocket ss1;
|
||||
StreamSocket ss2;
|
||||
|
||||
ss1.connectNB(SocketAddress("127.0.0.1", 0xFEFE));
|
||||
ss2.connectNB(SocketAddress("127.0.0.1", 0xFEFF));
|
||||
PollSet ps;
|
||||
assertTrue(ps.empty());
|
||||
ps.add(ss1, PollSet::POLL_READ);
|
||||
ps.add(ss2, PollSet::POLL_READ);
|
||||
ps.add(ss1, PollSet::POLL_READ | PollSet::POLL_WRITE | PollSet::POLL_ERROR);
|
||||
ps.add(ss2, PollSet::POLL_READ | PollSet::POLL_WRITE | PollSet::POLL_ERROR);
|
||||
assertTrue(!ps.empty());
|
||||
assertTrue(ps.has(ss1));
|
||||
assertTrue(ps.has(ss2));
|
||||
@ -151,13 +246,11 @@ void PollSetTest::testPollNoServer()
|
||||
assertTrue(sm.size() == 2);
|
||||
for (auto s : sm)
|
||||
assertTrue(0 != (s.second | PollSet::POLL_ERROR));
|
||||
#endif // POCO_OS_FAMILY_WINDOWS
|
||||
}
|
||||
|
||||
|
||||
void PollSetTest::testPollClosedServer()
|
||||
{
|
||||
#ifndef POCO_OS_FAMILY_WINDOWS
|
||||
EchoServer echoServer1;
|
||||
EchoServer echoServer2;
|
||||
StreamSocket ss1;
|
||||
@ -165,7 +258,6 @@ void PollSetTest::testPollClosedServer()
|
||||
|
||||
ss1.connect(SocketAddress("127.0.0.1", echoServer1.port()));
|
||||
ss2.connect(SocketAddress("127.0.0.1", echoServer2.port()));
|
||||
|
||||
PollSet ps;
|
||||
assertTrue(ps.empty());
|
||||
ps.add(ss1, PollSet::POLL_READ);
|
||||
@ -190,7 +282,28 @@ void PollSetTest::testPollClosedServer()
|
||||
assertTrue(sm.size() == 2);
|
||||
assertTrue(0 == ss1.receiveBytes(0, 0));
|
||||
assertTrue(0 == ss2.receiveBytes(0, 0));
|
||||
#endif // POCO_OS_FAMILY_WINDOWS
|
||||
}
|
||||
|
||||
|
||||
void PollSetTest::testPollSetWakeUp()
|
||||
{
|
||||
#if defined(POCO_HAVE_FD_EPOLL)
|
||||
PollSet ps;
|
||||
Timespan timeout(100000000); // 100 seconds
|
||||
Poller poller(ps, timeout);
|
||||
Thread t;
|
||||
Stopwatch sw;
|
||||
sw.start();
|
||||
t.start(poller);
|
||||
while (!poller.isRunning()) Thread::sleep(100);
|
||||
ps.wakeUp();
|
||||
t.join();
|
||||
sw.stop();
|
||||
assertFalse (poller.isRunning());
|
||||
assertTrue(sw.elapsedSeconds() < 1);
|
||||
#else // TODO: other implementations
|
||||
std::cout << "not implemented";
|
||||
#endif // POCO_HAVE_FD_EPOLL
|
||||
}
|
||||
|
||||
|
||||
@ -208,9 +321,12 @@ CppUnit::Test* PollSetTest::suite()
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("PollSetTest");
|
||||
|
||||
CppUnit_addTest(pSuite, PollSetTest, testTimeout);
|
||||
CppUnit_addTest(pSuite, PollSetTest, testPollNB);
|
||||
CppUnit_addTest(pSuite, PollSetTest, testPoll);
|
||||
CppUnit_addTest(pSuite, PollSetTest, testPollNoServer);
|
||||
CppUnit_addTest(pSuite, PollSetTest, testPollClosedServer);
|
||||
CppUnit_addTest(pSuite, PollSetTest, testPollSetWakeUp);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -24,9 +24,12 @@ public:
|
||||
PollSetTest(const std::string& name);
|
||||
~PollSetTest();
|
||||
|
||||
void testTimeout();
|
||||
void testPollNB();
|
||||
void testPoll();
|
||||
void testPollNoServer();
|
||||
void testPollClosedServer();
|
||||
void testPollSetWakeUp();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
@ -84,6 +84,31 @@ void RawSocketTest::testSendToReceiveFromIPv4()
|
||||
}
|
||||
|
||||
|
||||
void RawSocketTest::testEchoIPv4Move()
|
||||
{
|
||||
SocketAddress sa("127.0.0.1", 0);
|
||||
RawSocket rs0 = RawSocket(IPAddress::IPv4);
|
||||
rs0.connect(sa);
|
||||
|
||||
RawSocket rs(std::move(rs0));
|
||||
assertTrue (rs0.impl() == nullptr);
|
||||
int n = rs.sendBytes("hello", 5);
|
||||
assertTrue (5 == n);
|
||||
|
||||
char buffer[256] = "";
|
||||
unsigned char* ptr = (unsigned char*) buffer;
|
||||
|
||||
n = rs.receiveBytes(buffer, sizeof(buffer));
|
||||
int shift = ((buffer[0] & 0x0F) * 4);
|
||||
ptr += shift;
|
||||
|
||||
assertTrue (5 == (n - shift));
|
||||
assertTrue ("hello" == std::string((char*)ptr, 5));
|
||||
|
||||
rs.close();
|
||||
}
|
||||
|
||||
|
||||
void RawSocketTest::setUp()
|
||||
{
|
||||
}
|
||||
@ -100,6 +125,7 @@ CppUnit::Test* RawSocketTest::suite()
|
||||
|
||||
CppUnit_addTest(pSuite, RawSocketTest, testEchoIPv4);
|
||||
CppUnit_addTest(pSuite, RawSocketTest, testSendToReceiveFromIPv4);
|
||||
CppUnit_addTest(pSuite, RawSocketTest, testEchoIPv4Move);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ public:
|
||||
|
||||
void testEchoIPv4();
|
||||
void testSendToReceiveFromIPv4();
|
||||
void testEchoIPv4Move();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/Net/SocketAddress.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
using Poco::Net::SocketAddress;
|
||||
@ -41,19 +42,22 @@ void SocketAddressTest::testSocketAddress()
|
||||
assertTrue (wild.host().isWildcard());
|
||||
assertTrue (wild.port() == 0);
|
||||
|
||||
SocketAddress sa1("192.168.1.100", 100);
|
||||
SocketAddress sa01 = SocketAddress("192.168.1.100", 100);
|
||||
SocketAddress sa1(std::move(sa01));
|
||||
assertTrue (sa1.af() == AF_INET);
|
||||
assertTrue (sa1.family() == SocketAddress::IPv4);
|
||||
assertTrue (sa1.host().toString() == "192.168.1.100");
|
||||
assertTrue (sa1.port() == 100);
|
||||
assertTrue (sa1.toString() == "192.168.1.100:100");
|
||||
|
||||
SocketAddress sa2("192.168.1.100", "100");
|
||||
SocketAddress sa02 = SocketAddress("192.168.1.100", "100");
|
||||
SocketAddress sa2(std::move(sa02));
|
||||
assertTrue (sa2.host().toString() == "192.168.1.100");
|
||||
assertTrue (sa2.port() == 100);
|
||||
|
||||
#if !defined(_WIN32_WCE)
|
||||
SocketAddress sa3("192.168.1.100", "ftp");
|
||||
SocketAddress sa03 = SocketAddress("192.168.1.100", "ftp");
|
||||
SocketAddress sa3(std::move(sa03));
|
||||
assertTrue (sa3.host().toString() == "192.168.1.100");
|
||||
assertTrue (sa3.port() == 21);
|
||||
#endif
|
||||
@ -67,7 +71,8 @@ void SocketAddressTest::testSocketAddress()
|
||||
{
|
||||
}
|
||||
|
||||
SocketAddress sa4("pocoproject.org", 80);
|
||||
SocketAddress sa04 = SocketAddress("pocoproject.org", 80);
|
||||
SocketAddress sa4(std::move(sa04));
|
||||
assertTrue (sa4.host().toString() == "54.93.62.90");
|
||||
assertTrue (sa4.port() == 80);
|
||||
|
||||
@ -92,11 +97,13 @@ void SocketAddressTest::testSocketAddress()
|
||||
{
|
||||
}
|
||||
|
||||
SocketAddress sa7("192.168.2.120:88");
|
||||
SocketAddress sa07 = SocketAddress("192.168.2.120:88");
|
||||
SocketAddress sa7(std::move(sa07));
|
||||
assertTrue (sa7.host().toString() == "192.168.2.120");
|
||||
assertTrue (sa7.port() == 88);
|
||||
|
||||
SocketAddress sa8("[192.168.2.120]:88");
|
||||
SocketAddress sa08 = SocketAddress("[192.168.2.120]:88");
|
||||
SocketAddress sa8(std::move(sa08));
|
||||
assertTrue (sa8.host().toString() == "192.168.2.120");
|
||||
assertTrue (sa8.port() == 88);
|
||||
|
||||
@ -121,7 +128,8 @@ void SocketAddressTest::testSocketAddress()
|
||||
SocketAddress sa10("www6.pocoproject.org", 80);
|
||||
assertTrue (sa10.host().toString() == "54.93.62.90" || sa10.host().toString() == "2001:4801:7828:101:be76:4eff:fe10:1455");
|
||||
|
||||
SocketAddress sa11(SocketAddress::IPv4, "www6.pocoproject.org", 80);
|
||||
SocketAddress sa011 = SocketAddress(SocketAddress::IPv4, "www6.pocoproject.org", 80);
|
||||
SocketAddress sa11(std::move(sa011));
|
||||
assertTrue (sa11.host().toString() == "54.93.62.90");
|
||||
|
||||
#ifdef POCO_HAVE_IPv6
|
||||
@ -168,6 +176,8 @@ void SocketAddressTest::testSocketAddress6()
|
||||
assertTrue (sa2.host().toString() == "fe80::e6ce:8fff:fe4a:edd0");
|
||||
assertTrue (sa2.port() == 100);
|
||||
assertTrue (sa2.toString() == "[fe80::e6ce:8fff:fe4a:edd0]:100");
|
||||
#else
|
||||
std::cout << "[IPv6 DISABLED]" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -191,6 +201,8 @@ void SocketAddressTest::testSocketAddressUnixLocal()
|
||||
SocketAddress sa4("/tmp/sock1");
|
||||
assertTrue (sa1 == sa4);
|
||||
assertTrue (sa4.toString() == "/tmp/sock1");
|
||||
#else
|
||||
std::cout << "[UNIX LOCAL DISABLED]" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
314
Net/testsuite/src/SocketProactorTest.cpp
Normal file
314
Net/testsuite/src/SocketProactorTest.cpp
Normal file
@ -0,0 +1,314 @@
|
||||
//
|
||||
// SocketProactorTest.cpp
|
||||
//
|
||||
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "SocketProactorTest.h"
|
||||
#include "UDPEchoServer.h"
|
||||
#include "CppUnit/TestCaller.h"
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/Net/StreamSocket.h"
|
||||
#include "Poco/Net/DatagramSocket.h"
|
||||
#include "Poco/Net/ServerSocket.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include <iostream>
|
||||
|
||||
using Poco::Net::SocketProactor;
|
||||
using Poco::Net::StreamSocket;
|
||||
using Poco::Net::DatagramSocket;
|
||||
using Poco::Net::ServerSocket;
|
||||
using Poco::Net::SocketAddress;
|
||||
using Poco::Thread;
|
||||
using Poco::Timestamp;
|
||||
|
||||
|
||||
SocketProactorTest::SocketProactorTest(const std::string& name): CppUnit::TestCase(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SocketProactorTest::~SocketProactorTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void SocketProactorTest::testTCPSocketProactor()
|
||||
{
|
||||
EchoServer echoServer;
|
||||
SocketProactor proactor(false);
|
||||
StreamSocket s;
|
||||
s.connect(SocketAddress("127.0.0.1", echoServer.port()));
|
||||
int mode = SocketProactor::POLL_READ | SocketProactor::POLL_WRITE | SocketProactor::POLL_ERROR;
|
||||
proactor.addSocket(s, mode);
|
||||
std::string hello = "hello proactor world";
|
||||
bool sent = false, sendPassed = false;
|
||||
auto onSendCompletion = [&](std::error_code err, int bytes)
|
||||
{
|
||||
sendPassed = (err.value() == 0) && (bytes == hello.length());
|
||||
sent = true;
|
||||
};
|
||||
proactor.addSend(s, SocketProactor::Buffer(hello.begin(), hello.end()), onSendCompletion);
|
||||
SocketProactor::Buffer buf(hello.size(), 0);
|
||||
bool received = false, receivePassed = false;
|
||||
auto onRecvCompletion = [&](std::error_code err, int bytes)
|
||||
{
|
||||
receivePassed = (err.value() == 0) &&
|
||||
(bytes == hello.length()) &&
|
||||
(std::string(buf.begin(), buf.end()) == hello);
|
||||
received = true;
|
||||
};
|
||||
proactor.addReceive(s, buf, onRecvCompletion);
|
||||
while (!received) proactor.poll();
|
||||
|
||||
assertTrue (sent);
|
||||
assertTrue (sendPassed);
|
||||
assertTrue (received);
|
||||
assertTrue (receivePassed);
|
||||
|
||||
buf.clear();
|
||||
buf.resize(hello.size());
|
||||
assertFalse(std::string(buf.begin(), buf.end()) == hello);
|
||||
|
||||
sent = false;
|
||||
sendPassed = false;
|
||||
received = false;
|
||||
receivePassed = false;
|
||||
|
||||
proactor.addSend(s, SocketProactor::Buffer(hello.begin(), hello.end()), nullptr);
|
||||
proactor.addReceive(s, buf, nullptr);
|
||||
int handled = 0, handledTot = 0;
|
||||
do
|
||||
{
|
||||
proactor.poll(&handled);
|
||||
handledTot += handled;
|
||||
}
|
||||
while (handledTot < 2);
|
||||
|
||||
assertTrue(std::string(buf.begin(), buf.end()) == hello);
|
||||
assertFalse (sent);
|
||||
assertFalse (sendPassed);
|
||||
assertFalse (received);
|
||||
assertFalse (receivePassed);
|
||||
|
||||
bool error = false;
|
||||
bool errorPassed = false;
|
||||
auto onError = [&](std::error_code err, int bytes)
|
||||
{
|
||||
errorPassed = (err.value() != 0) && (bytes == 0);
|
||||
error = true;
|
||||
};
|
||||
|
||||
StreamSocket errSock(SocketAddress::IPv4);
|
||||
errSock.connectNB(SocketAddress("127.0.0.1", 0xFFEE));
|
||||
proactor.addSend(errSock, SocketProactor::Buffer(hello.begin(), hello.end()), onError);
|
||||
Thread::sleep(100);
|
||||
while (!error) proactor.poll();
|
||||
assertTrue (error);
|
||||
assertTrue(errorPassed);
|
||||
}
|
||||
|
||||
|
||||
void SocketProactorTest::testUDPSocketProactor()
|
||||
{
|
||||
UDPEchoServer echoServer;
|
||||
DatagramSocket s(SocketAddress::IPv4);
|
||||
SocketProactor proactor(false);
|
||||
int mode = SocketProactor::POLL_READ | SocketProactor::POLL_WRITE;
|
||||
proactor.addSocket(s, mode);
|
||||
std::string hello = "hello proactor world";
|
||||
bool sent = false, sendPassed = false;
|
||||
auto onSendCompletion = [&](std::error_code err, int bytes)
|
||||
{
|
||||
sendPassed = (err.value() == 0) &&
|
||||
(bytes == hello.length());
|
||||
sent = true;
|
||||
};
|
||||
proactor.addSendTo(s,
|
||||
SocketProactor::Buffer(hello.begin(), hello.end()),
|
||||
SocketAddress("127.0.0.1", echoServer.port()),
|
||||
onSendCompletion);
|
||||
Poco::Net::SocketProactor::Buffer buf(hello.size(), 0);
|
||||
bool received = false, receivePassed = false;
|
||||
SocketAddress sa;
|
||||
auto onRecvCompletion = [&](std::error_code err, int bytes)
|
||||
{
|
||||
receivePassed = (err.value() == 0) &&
|
||||
(bytes == hello.length()) &&
|
||||
(sa.host().toString() == "127.0.0.1") &&
|
||||
(sa.port() == echoServer.port()) &&
|
||||
(std::string(buf.begin(), buf.end()) == hello);
|
||||
received = true;
|
||||
};
|
||||
proactor.addReceiveFrom(s, buf, sa, onRecvCompletion);
|
||||
while (!received) proactor.poll();
|
||||
|
||||
assertTrue (sent);
|
||||
assertTrue (sendPassed);
|
||||
assertTrue (received);
|
||||
assertTrue (receivePassed);
|
||||
|
||||
buf.clear();
|
||||
buf.resize(hello.size());
|
||||
assertFalse(std::string(buf.begin(), buf.end()) == hello);
|
||||
|
||||
sent = false;
|
||||
sendPassed = false;
|
||||
received = false;
|
||||
receivePassed = false;
|
||||
|
||||
proactor.addSendTo(s,
|
||||
SocketProactor::Buffer(hello.begin(), hello.end()),
|
||||
SocketAddress("127.0.0.1", echoServer.port()),
|
||||
nullptr);
|
||||
proactor.addReceiveFrom(s, buf, sa, nullptr);
|
||||
int handled = 0, handledTot = 0;
|
||||
do
|
||||
{
|
||||
proactor.poll(&handled);
|
||||
handledTot += handled;
|
||||
} while (handledTot < 2);
|
||||
|
||||
assertTrue(std::string(buf.begin(), buf.end()) == hello);
|
||||
assertFalse (sent);
|
||||
assertFalse (sendPassed);
|
||||
assertFalse (received);
|
||||
assertFalse (receivePassed);
|
||||
}
|
||||
|
||||
|
||||
void SocketProactorTest::testSocketProactorStartStop()
|
||||
{
|
||||
UDPEchoServer echoServer;
|
||||
DatagramSocket s(SocketAddress::IPv4);
|
||||
SocketProactor proactor(false);
|
||||
int mode = SocketProactor::POLL_READ | SocketProactor::POLL_WRITE;
|
||||
proactor.addSocket(s, mode);
|
||||
std::string hello = "hello proactor world";
|
||||
bool sent = false, sendPassed = false;
|
||||
auto onSendCompletion = [&](std::error_code err, int bytes)
|
||||
{
|
||||
sendPassed = (err.value() == 0) &&
|
||||
(bytes == hello.length());
|
||||
sent = true;
|
||||
};
|
||||
proactor.addSendTo(s,
|
||||
SocketProactor::Buffer(hello.begin(), hello.end()),
|
||||
SocketAddress("127.0.0.1", echoServer.port()),
|
||||
onSendCompletion);
|
||||
Poco::Net::SocketProactor::Buffer buf(hello.size(), 0);
|
||||
bool received = false, receivePassed = false;
|
||||
SocketAddress sa;
|
||||
auto onRecvCompletion = [&](std::error_code err, int bytes)
|
||||
{
|
||||
receivePassed = (err.value() == 0) &&
|
||||
(bytes == hello.length()) &&
|
||||
(sa.host().toString() == "127.0.0.1") &&
|
||||
(sa.port() == echoServer.port()) &&
|
||||
(std::string(buf.begin(), buf.end()) == hello);
|
||||
received = true;
|
||||
proactor.stop();
|
||||
};
|
||||
proactor.addReceiveFrom(s, buf, sa, onRecvCompletion);
|
||||
|
||||
while (!received) proactor.poll();
|
||||
|
||||
assertTrue (sent);
|
||||
assertTrue (sendPassed);
|
||||
assertTrue (received);
|
||||
assertTrue (receivePassed);
|
||||
|
||||
buf.clear();
|
||||
buf.resize(hello.size());
|
||||
assertFalse(std::string(buf.begin(), buf.end()) == hello);
|
||||
|
||||
sent = false;
|
||||
sendPassed = false;
|
||||
received = false;
|
||||
receivePassed = false;
|
||||
|
||||
assertFalse (sent);
|
||||
assertFalse (sendPassed);
|
||||
assertFalse (received);
|
||||
assertFalse (receivePassed);
|
||||
|
||||
proactor.addSendTo(s,
|
||||
SocketProactor::Buffer(hello.begin(), hello.end()),
|
||||
SocketAddress("127.0.0.1", echoServer.port()),
|
||||
onSendCompletion);
|
||||
proactor.addReceiveFrom(s, buf, sa, onRecvCompletion);
|
||||
while (!received) proactor.poll();
|
||||
|
||||
assertTrue(std::string(buf.begin(), buf.end()) == hello);
|
||||
assertTrue (sent);
|
||||
assertTrue (sendPassed);
|
||||
assertTrue (received);
|
||||
assertTrue (receivePassed);
|
||||
}
|
||||
|
||||
|
||||
void SocketProactorTest::testWork()
|
||||
{
|
||||
SocketProactor proactor;
|
||||
int executed = 0;
|
||||
SocketProactor::Work work = [&]() { ++executed; };
|
||||
proactor.addWork(work);
|
||||
assertTrue (proactor.runOne() == 1);
|
||||
assertEquals (executed, 1);
|
||||
assertTrue (proactor.poll() == 0);
|
||||
assertEquals (executed, 1);
|
||||
|
||||
UDPEchoServer echoServer;
|
||||
DatagramSocket s(SocketAddress::IPv4);
|
||||
int mode = SocketProactor::POLL_READ | SocketProactor::POLL_WRITE;
|
||||
proactor.addSocket(s, mode);
|
||||
proactor.addSendTo(s,
|
||||
SocketProactor::Buffer(1, 0),
|
||||
SocketAddress("127.0.0.1", echoServer.port()),
|
||||
nullptr);
|
||||
assertTrue (proactor.poll() == 1);
|
||||
assertEquals (executed, 2);
|
||||
}
|
||||
|
||||
|
||||
void SocketProactorTest::testTimedWork()
|
||||
{
|
||||
SocketProactor proactor;
|
||||
int executed = 0;
|
||||
SocketProactor::Work work = [&]() { ++executed; };
|
||||
proactor.addWork(work, 0);
|
||||
proactor.addWork(work, 1000);
|
||||
assertTrue (proactor.poll() == 1);
|
||||
assertEquals (executed, 1);
|
||||
Thread::sleep(1000);
|
||||
assertTrue (proactor.poll() == 1);
|
||||
assertEquals (executed, 2);
|
||||
}
|
||||
|
||||
|
||||
void SocketProactorTest::setUp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void SocketProactorTest::tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* SocketProactorTest::suite()
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SocketProactorTest");
|
||||
|
||||
CppUnit_addTest(pSuite, SocketProactorTest, testTCPSocketProactor);
|
||||
CppUnit_addTest(pSuite, SocketProactorTest, testUDPSocketProactor);
|
||||
CppUnit_addTest(pSuite, SocketProactorTest, testSocketProactorStartStop);
|
||||
CppUnit_addTest(pSuite, SocketProactorTest, testWork);
|
||||
CppUnit_addTest(pSuite, SocketProactorTest, testTimedWork);
|
||||
|
||||
return pSuite;
|
||||
}
|
49
Net/testsuite/src/SocketProactorTest.h
Normal file
49
Net/testsuite/src/SocketProactorTest.h
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// SocketProactorTest.h
|
||||
//
|
||||
// Definition of the SocketProactorTest class.
|
||||
//
|
||||
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#ifndef SocketProactorTest_INCLUDED
|
||||
#define SocketProactorTest_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Net/Net.h"
|
||||
#include "Poco/Thread.h"
|
||||
#include "Poco/Observer.h"
|
||||
#include "Poco/Net/SocketAddress.h"
|
||||
#include "Poco/Net/SocketProactor.h"
|
||||
#include "Poco/Net/SocketNotification.h"
|
||||
#include "CppUnit/TestCase.h"
|
||||
#include "EchoServer.h"
|
||||
|
||||
|
||||
class SocketProactorTest: public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
SocketProactorTest(const std::string& name);
|
||||
~SocketProactorTest();
|
||||
|
||||
void testTCPSocketProactor();
|
||||
void testUDPSocketProactor();
|
||||
void testSocketProactorStartStop();
|
||||
|
||||
void testWork();
|
||||
void testTimedWork();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
#endif // SocketProactorTest_INCLUDED
|
@ -44,6 +44,10 @@ using Poco::Thread;
|
||||
|
||||
namespace
|
||||
{
|
||||
int DATA_SIZE = 1024;
|
||||
int REACTORS_COUNT = 8;
|
||||
int MAX_DATA_SIZE = DATA_SIZE * REACTORS_COUNT;
|
||||
|
||||
class EchoServiceHandler
|
||||
{
|
||||
public:
|
||||
@ -130,7 +134,7 @@ namespace
|
||||
checkReadableObserverCount(1);
|
||||
_reactor.removeEventHandler(_socket, Observer<ClientServiceHandler, ReadableNotification>(*this, &ClientServiceHandler::onReadable));
|
||||
checkReadableObserverCount(0);
|
||||
if (_once || _data.size() == 8192)
|
||||
if (_once || _data.size() == MAX_DATA_SIZE)
|
||||
{
|
||||
_reactor.stop();
|
||||
delete this;
|
||||
@ -144,7 +148,7 @@ namespace
|
||||
checkWritableObserverCount(1);
|
||||
_reactor.removeEventHandler(_socket, Observer<ClientServiceHandler, WritableNotification>(*this, &ClientServiceHandler::onWritable));
|
||||
checkWritableObserverCount(0);
|
||||
std::string data(1024, 'x');
|
||||
std::string data(DATA_SIZE, 'x');
|
||||
_socket.sendBytes(data.data(), (int) data.length());
|
||||
_socket.shutdownSend();
|
||||
}
|
||||
@ -405,7 +409,7 @@ void SocketReactorTest::testSocketReactor()
|
||||
ClientServiceHandler::resetData();
|
||||
reactor.run();
|
||||
std::string data(ClientServiceHandler::data());
|
||||
assertTrue (data.size() == 1024);
|
||||
assertTrue (data.size() == DATA_SIZE);
|
||||
assertTrue (!ClientServiceHandler::readableError());
|
||||
assertTrue (!ClientServiceHandler::writableError());
|
||||
assertTrue (!ClientServiceHandler::timeoutError());
|
||||
@ -425,7 +429,7 @@ void SocketReactorTest::testSetSocketReactor()
|
||||
ClientServiceHandler::resetData();
|
||||
reactor.run();
|
||||
std::string data(ClientServiceHandler::data());
|
||||
assertTrue (data.size() == 1024);
|
||||
assertTrue (data.size() == DATA_SIZE);
|
||||
assertTrue (!ClientServiceHandler::readableError());
|
||||
assertTrue (!ClientServiceHandler::writableError());
|
||||
assertTrue (!ClientServiceHandler::timeoutError());
|
||||
@ -434,27 +438,26 @@ void SocketReactorTest::testSetSocketReactor()
|
||||
|
||||
void SocketReactorTest::testParallelSocketReactor()
|
||||
{
|
||||
SocketAddress ssa;
|
||||
SocketAddress ssa("127.0.0.1:22087");
|
||||
ServerSocket ss(ssa);
|
||||
SocketReactor reactor;
|
||||
ParallelSocketAcceptor<EchoServiceHandler, SocketReactor> acceptor(ss, reactor);
|
||||
ParallelSocketAcceptor<EchoServiceHandler, SocketReactor> acceptor(ss, reactor, REACTORS_COUNT);
|
||||
|
||||
SocketAddress sa("127.0.0.1", ss.address().port());
|
||||
SocketConnector<ClientServiceHandler> connector1(sa, reactor);
|
||||
SocketConnector<ClientServiceHandler> connector2(sa, reactor);
|
||||
SocketConnector<ClientServiceHandler> connector3(sa, reactor);
|
||||
SocketConnector<ClientServiceHandler> connector4(sa, reactor);
|
||||
SocketConnector<ClientServiceHandler> connector5(sa, reactor);
|
||||
SocketConnector<ClientServiceHandler> connector6(sa, reactor);
|
||||
SocketConnector<ClientServiceHandler> connector7(sa, reactor);
|
||||
SocketConnector<ClientServiceHandler> connector8(sa, reactor);
|
||||
std::vector<SocketConnector<ClientServiceHandler>*> connectors;
|
||||
for (int i = 0; i < REACTORS_COUNT; ++i)
|
||||
connectors.push_back(new SocketConnector<ClientServiceHandler>(sa, reactor));
|
||||
|
||||
ClientServiceHandler::setOnce(false);
|
||||
ClientServiceHandler::resetData();
|
||||
reactor.run();
|
||||
|
||||
std::string data(ClientServiceHandler::data());
|
||||
assertTrue (data.size() == 8192);
|
||||
assertTrue (data.size() == MAX_DATA_SIZE);
|
||||
assertTrue (!ClientServiceHandler::readableError());
|
||||
assertTrue (!ClientServiceHandler::writableError());
|
||||
assertTrue (!ClientServiceHandler::timeoutError());
|
||||
for (auto& c : connectors) delete c;
|
||||
}
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user