* 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 commit
558324f672

removed the nios2 support, which was originally added in
e7b91e8125

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/12641
f5eb85eb0f

* 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:
Aleksandar Fabijanic 2022-05-15 11:05:56 -05:00 committed by GitHub
parent 6de1e18eb9
commit 7852153db5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
116 changed files with 4136 additions and 557 deletions

View File

@ -3,13 +3,23 @@ on: [push]
jobs: jobs:
linux-gcc-make: linux-gcc-make:
runs-on: ubuntu-20.04 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: steps:
- uses: actions/checkout@v2 - 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: ./configure --everything --omit=PDF && make all -s -j4 && sudo make install
- run: >- - run: >-
sudo -s sudo -s
EXCLUDE_TESTS="Data/MySQL Data/ODBC Data/PostgreSQL MongoDB" EXCLUDE_TESTS="Data/ODBC Data/PostgreSQL MongoDB"
./ci/runtests.sh ./ci/runtests.sh
linux-gcc-make-asan: linux-gcc-make-asan:

View File

@ -14,7 +14,7 @@ set_target_properties(mod_poco
target_include_directories(mod_poco target_include_directories(mod_poco
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE PRIVATE
${APACHE2_INCLUDE_DIRS} ${APACHE2_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src

View File

@ -50,6 +50,9 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "RelWithDebInfo") set(CMAKE_BUILD_TYPE "RelWithDebInfo")
endif() endif()
# Enable standard installation directories
include(GNUInstallDirs)
# Include some common macros to simpilfy the Poco CMake files # Include some common macros to simpilfy the Poco CMake files
include(PocoMacros) include(PocoMacros)
@ -436,7 +439,9 @@ add_custom_target(uninstall
############################################################# #############################################################
# Enable packaging # Enable packaging
include(InstallRequiredSystemLibraries) if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
include(InstallRequiredSystemLibraries)
endif()
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Poco Libraries") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Poco Libraries")
set(CPACK_PACKAGE_VENDOR "Applied Informatics Software Engineering GmbH") set(CPACK_PACKAGE_VENDOR "Applied Informatics Software Engineering GmbH")
@ -462,7 +467,7 @@ write_basic_package_version_file(
if(WIN32) if(WIN32)
set(PocoConfigPackageLocation "cmake") set(PocoConfigPackageLocation "cmake")
else() else()
set(PocoConfigPackageLocation "lib${LIB_SUFFIX}/cmake/${PROJECT_NAME}") set(PocoConfigPackageLocation "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
endif() endif()
configure_file(cmake/${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/${PROJECT_NAME}Config.cmake" @ONLY) configure_file(cmake/${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/${PROJECT_NAME}Config.cmake" @ONLY)

View File

@ -25,7 +25,7 @@ target_link_libraries(CppParser PUBLIC Poco::Foundation)
target_include_directories(CppParser target_include_directories(CppParser
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
) )

View File

@ -18,10 +18,15 @@ target_link_libraries(CppUnit PUBLIC Poco::Foundation)
target_include_directories(CppUnit target_include_directories(CppUnit
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src ${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) if(NOT BUILD_SHARED_LIBS)
target_compile_definitions(CppUnit target_compile_definitions(CppUnit

View File

@ -55,7 +55,6 @@
<ProjectGuid>{138BB448-808A-4FE5-A66D-78D1F8770F59}</ProjectGuid> <ProjectGuid>{138BB448-808A-4FE5-A66D-78D1F8770F59}</ProjectGuid>
<RootNamespace>CppUnit</RootNamespace> <RootNamespace>CppUnit</RootNamespace>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </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"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">

View File

@ -55,7 +55,6 @@
<ProjectGuid>{138BB448-808A-4FE5-A66D-78D1F8770F59}</ProjectGuid> <ProjectGuid>{138BB448-808A-4FE5-A66D-78D1F8770F59}</ProjectGuid>
<RootNamespace>CppUnit</RootNamespace> <RootNamespace>CppUnit</RootNamespace>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </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"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">

View File

@ -55,7 +55,6 @@
<ProjectGuid>{138BB448-808A-4FE5-A66D-78D1F8770F59}</ProjectGuid> <ProjectGuid>{138BB448-808A-4FE5-A66D-78D1F8770F59}</ProjectGuid>
<RootNamespace>CppUnit</RootNamespace> <RootNamespace>CppUnit</RootNamespace>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup> </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"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">

View File

@ -25,7 +25,7 @@ target_link_libraries(Crypto PUBLIC Poco::Foundation OpenSSL::SSL OpenSSL::Crypt
target_include_directories(Crypto target_include_directories(Crypto
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src
) )

View File

@ -30,7 +30,7 @@ target_link_libraries(Data PUBLIC Poco::Foundation)
target_include_directories(Data target_include_directories(Data
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
) )

View File

@ -25,7 +25,7 @@ target_link_libraries(DataMySQL PUBLIC Poco::Data MySQL::client)
target_include_directories(DataMySQL target_include_directories(DataMySQL
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
) )
target_compile_definitions(DataMySQL PUBLIC THREADSAFE NO_TCL) target_compile_definitions(DataMySQL PUBLIC THREADSAFE NO_TCL)

View File

@ -323,6 +323,10 @@ public:
private: private:
bool realExtractFixed(std::size_t pos, enum_field_types type, void* buffer, bool isUnsigned = false); 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" // Prevent VC8 warning "operator= could not be generated"
Extractor& operator=(const Extractor&); Extractor& operator=(const Extractor&);

View File

@ -40,6 +40,9 @@ class ResultMetadata
/// MySQL result metadata /// MySQL result metadata
{ {
public: public:
~ResultMetadata();
/// Destroys the ResultMetadata.
void reset(); void reset();
/// Resets the metadata. /// Resets the metadata.
@ -64,10 +67,13 @@ public:
bool isNull(std::size_t pos) const; bool isNull(std::size_t pos) const;
/// Returns true if value at pos is null. /// 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: private:
std::vector<MetaColumn> _columns; std::vector<MetaColumn> _columns;
std::vector<MYSQL_BIND> _row; std::vector<MYSQL_BIND> _row;
std::vector<char> _buffer; std::vector<char*> _buffer;
std::vector<unsigned long> _lengths; std::vector<unsigned long> _lengths;
std::vector<my_boolv> _isNull; // using char instead of bool to avoid std::vector<bool> disaster std::vector<my_boolv> _isNull; // using char instead of bool to avoid std::vector<bool> disaster
}; };

View File

@ -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) void Binder::bind(std::size_t pos, const UUID& val, Direction dir)
{ {
std::string str = val.toString(); bind(pos, toString(val), dir);
bind(pos, str, dir);
} }

View File

@ -128,9 +128,12 @@ bool Extractor::extract(std::size_t pos, std::string& val)
//mysql reports TEXT types as FDT_BLOB when being extracted //mysql reports TEXT types as FDT_BLOB when being extracted
MetaColumn::ColumnDataType columnType = _metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type(); 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"); 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)); val.assign(reinterpret_cast<const char*>(_metadata.rawData(pos)), _metadata.length(pos));
return true; return true;
} }
@ -142,11 +145,14 @@ bool Extractor::extract(std::size_t pos, Poco::Data::BLOB& val)
throw MySQLException("Extractor: attempt to extract more parameters, than query result contain"); throw MySQLException("Extractor: attempt to extract more parameters, than query result contain");
if (_metadata.isNull(static_cast<Poco::UInt32>(pos))) if (_metadata.isNull(static_cast<Poco::UInt32>(pos)))
return false; return false;
if (_metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type() != Poco::Data::MetaColumn::FDT_BLOB) if (_metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type() != Poco::Data::MetaColumn::FDT_BLOB)
throw MySQLException("Extractor: not a 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)); val.assignRaw(_metadata.rawData(pos), _metadata.length(pos));
return true; 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) if (_metadata.metaColumn(static_cast<Poco::UInt32>(pos)).type() != Poco::Data::MetaColumn::FDT_BLOB)
throw MySQLException("Extractor: not a 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)); val.assignRaw(reinterpret_cast<const char*>(_metadata.rawData(pos)), _metadata.length(pos));
return true; return true;
} }
@ -263,6 +272,37 @@ bool Extractor::realExtractFixed(std::size_t pos, enum_field_types type, void* b
return isNull == 0; 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 // Not implemented

View File

@ -71,6 +71,7 @@ namespace
case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB: case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_JSON:
return field.length; return field.length;
default: default:
@ -128,6 +129,8 @@ namespace
case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB: case MYSQL_TYPE_BLOB:
return Poco::Data::MetaColumn::FDT_BLOB; return Poco::Data::MetaColumn::FDT_BLOB;
case MYSQL_TYPE_JSON:
return Poco::Data::MetaColumn::FDT_JSON;
default: default:
return Poco::Data::MetaColumn::FDT_UNKNOWN; return Poco::Data::MetaColumn::FDT_UNKNOWN;
} }
@ -140,6 +143,13 @@ namespace Data {
namespace MySQL { namespace MySQL {
ResultMetadata::~ResultMetadata()
{
for (std::vector<char*>::iterator it = _buffer.begin(); it != _buffer.end(); ++it)
std::free(*it);
}
void ResultMetadata::reset() void ResultMetadata::reset()
{ {
_columns.resize(0); _columns.resize(0);
@ -165,7 +175,6 @@ void ResultMetadata::init(MYSQL_STMT* stmt)
std::size_t count = mysql_num_fields(h); std::size_t count = mysql_num_fields(h);
MYSQL_FIELD* fields = mysql_fetch_fields(h); MYSQL_FIELD* fields = mysql_fetch_fields(h);
std::size_t commonSize = 0;
_columns.reserve(count); _columns.reserve(count);
for (std::size_t i = 0; i < count; i++) for (std::size_t i = 0; i < count; i++)
@ -181,29 +190,24 @@ void ResultMetadata::init(MYSQL_STMT* stmt)
0, // TODO: precision 0, // TODO: precision
!IS_NOT_NULL(fields[i].flags) // nullable !IS_NOT_NULL(fields[i].flags) // nullable
)); ));
commonSize += _columns[i].length();
} }
_buffer.resize(commonSize); _buffer.resize(count);
_row.resize(count); _row.resize(count);
_lengths.resize(count); _lengths.resize(count);
_isNull.resize(count); _isNull.resize(count);
std::size_t offset = 0;
for (std::size_t i = 0; i < count; i++) for (std::size_t i = 0; i < count; i++)
{ {
std::memset(&_row[i], 0, sizeof(MYSQL_BIND)); std::memset(&_row[i], 0, sizeof(MYSQL_BIND));
unsigned int len = static_cast<unsigned int>(_columns[i].length()); 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_type = fields[i].type;
_row[i].buffer_length = len; _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].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_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; _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 } } } // namespace Poco::Data::MySQL

View 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"

View File

@ -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() void MySQLTest::testUnsignedInts()
{ {
if (!_pSession) fail ("Test not available."); 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() void MySQLTest::recreateIntsTable()
{ {
dropTable("Strings"); dropTable("Strings");
@ -919,6 +954,8 @@ CppUnit::Test* MySQLTest::suite()
CppUnit_addTest(pSuite, MySQLTest, testDateTime); CppUnit_addTest(pSuite, MySQLTest, testDateTime);
//CppUnit_addTest(pSuite, MySQLTest, testBLOB); //CppUnit_addTest(pSuite, MySQLTest, testBLOB);
CppUnit_addTest(pSuite, MySQLTest, testBLOBStmt); CppUnit_addTest(pSuite, MySQLTest, testBLOBStmt);
CppUnit_addTest(pSuite, MySQLTest, testLongBLOB);
CppUnit_addTest(pSuite, MySQLTest, testJSON);
CppUnit_addTest(pSuite, MySQLTest, testUnsignedInts); CppUnit_addTest(pSuite, MySQLTest, testUnsignedInts);
CppUnit_addTest(pSuite, MySQLTest, testFloat); CppUnit_addTest(pSuite, MySQLTest, testFloat);
CppUnit_addTest(pSuite, MySQLTest, testDouble); CppUnit_addTest(pSuite, MySQLTest, testDouble);

View File

@ -79,6 +79,8 @@ public:
void testDateTime(); void testDateTime();
void testBLOB(); void testBLOB();
void testBLOBStmt(); void testBLOBStmt();
void testLongBLOB();
void testJSON();
void testUnsignedInts(); void testUnsignedInts();
void testFloat(); void testFloat();
@ -117,6 +119,8 @@ private:
void recreatePersonDateTimeTable(); void recreatePersonDateTimeTable();
void recreatePersonDateTable(); void recreatePersonDateTable();
void recreatePersonTimeTable(); void recreatePersonTimeTable();
void recreatePersonLongBLOBTable();
void recreatePersonJSONTable();
void recreateStringsTable(); void recreateStringsTable();
void recreateIntsTable(); void recreateIntsTable();
void recreateUnsignedIntsTable(); void recreateUnsignedIntsTable();

View File

@ -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() 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; typedef Tuple<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int> TupleType;

View File

@ -83,6 +83,8 @@ public:
void dateTime(); void dateTime();
void date(); void date();
void time(); void time();
void longBlob();
void json();
void unsignedInts(); void unsignedInts();
void floats(); void floats();
void doubles(); void doubles();

View File

@ -25,7 +25,7 @@ target_link_libraries(DataODBC PUBLIC Poco::Data ODBC::ODBC)
target_include_directories(DataODBC target_include_directories(DataODBC
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
) )
target_compile_definitions(DataODBC PUBLIC THREADSAFE) target_compile_definitions(DataODBC PUBLIC THREADSAFE)

View File

@ -25,7 +25,7 @@ target_link_libraries(DataPostgreSQL PUBLIC Poco::Data PostgreSQL::client)
target_include_directories(DataPostgreSQL target_include_directories(DataPostgreSQL
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src
) )

View File

@ -38,7 +38,7 @@ target_link_libraries(DataSQLite PUBLIC Poco::Data)
target_include_directories(DataSQLite target_include_directories(DataSQLite
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
) )

43
Data/SQLite/testsuite/src/SQLiteTest.cpp Normal file → Executable file
View File

@ -55,6 +55,7 @@ using Poco::Data::SQLChannel;
using Poco::Data::LimitException; using Poco::Data::LimitException;
using Poco::Data::ConnectionFailedException; using Poco::Data::ConnectionFailedException;
using Poco::Data::CLOB; using Poco::Data::CLOB;
using Poco::Data::BLOB;
using Poco::Data::Date; using Poco::Data::Date;
using Poco::Data::Time; using Poco::Data::Time;
using Poco::Data::Transaction; 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() void SQLiteTest::testTuple10()
{ {
Session tmp (Poco::Data::SQLite::Connector::KEY, "dummy.db"); 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, testSingleSelect);
CppUnit_addTest(pSuite, SQLiteTest, testEmptyDB); CppUnit_addTest(pSuite, SQLiteTest, testEmptyDB);
CppUnit_addTest(pSuite, SQLiteTest, testCLOB); CppUnit_addTest(pSuite, SQLiteTest, testCLOB);
CppUnit_addTest(pSuite, SQLiteTest, testBLOB);
CppUnit_addTest(pSuite, SQLiteTest, testTuple10); CppUnit_addTest(pSuite, SQLiteTest, testTuple10);
CppUnit_addTest(pSuite, SQLiteTest, testTupleVector10); CppUnit_addTest(pSuite, SQLiteTest, testTupleVector10);
CppUnit_addTest(pSuite, SQLiteTest, testTuple9); CppUnit_addTest(pSuite, SQLiteTest, testTuple9);

1
Data/SQLite/testsuite/src/SQLiteTest.h Normal file → Executable file
View File

@ -76,6 +76,7 @@ public:
void testEmptyDB(); void testEmptyDB();
void testCLOB(); void testCLOB();
void testBLOB();
void testTuple1(); void testTuple1();
void testTupleVector1(); void testTupleVector1();

View File

@ -363,9 +363,12 @@ protected:
bool transcodeRequired() const; bool transcodeRequired() const;
void transcode(const std::string& from, std::string& to); void transcode(const std::string& from, std::string& to);
void reverseTranscode(const std::string& from, std::string& to); void reverseTranscode(const std::string& from, std::string& to);
const std::string& toString(const UUID& uuid);
private: private:
using StringList = std::vector<std::string*>;
std::unique_ptr<Transcoder> _pTranscoder; std::unique_ptr<Transcoder> _pTranscoder;
std::unique_ptr<StringList> _pStrings;
}; };

View File

@ -221,7 +221,7 @@ private:
using BLOB = LOB<unsigned char>; using BLOB = LOB<unsigned char>;
using CLOB = LOB<char>; using CLOB = LOB<char>;
using JSON = std::string;
// //
// inlines // inlines

View File

@ -51,6 +51,7 @@ public:
FDT_TIME, FDT_TIME,
FDT_TIMESTAMP, FDT_TIMESTAMP,
FDT_UUID, FDT_UUID,
FDT_JSON,
FDT_UNKNOWN FDT_UNKNOWN
}; };

View File

@ -36,6 +36,11 @@ AbstractBinder::AbstractBinder(Poco::TextEncoding::Ptr pFromEncoding,
AbstractBinder::~AbstractBinder() 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) void AbstractBinder::bind(std::size_t pos, const std::vector<Poco::Int8>& val, Direction dir)
{ {
throw NotImplementedException("std::vector binder must be implemented."); throw NotImplementedException("std::vector binder must be implemented.");

View File

@ -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_TIME: return value<Time>(col, row, useFilter);
case MetaColumn::FDT_TIMESTAMP: return value<DateTime>(col, row); case MetaColumn::FDT_TIMESTAMP: return value<DateTime>(col, row);
case MetaColumn::FDT_UUID: return value<UUID>(col, row); case MetaColumn::FDT_UUID: return value<UUID>(col, row);
case MetaColumn::FDT_JSON: return value<std::string>(col, row, useFilter);
default: default:
throw UnknownTypeException("Data type not supported."); throw UnknownTypeException("Data type not supported.");
} }

View File

@ -353,6 +353,8 @@ void StatementImpl::makeExtractors(std::size_t count)
addInternalExtract<DateTime>(mc); break; addInternalExtract<DateTime>(mc); break;
case MetaColumn::FDT_UUID: case MetaColumn::FDT_UUID:
addInternalExtract<UUID>(mc); break; addInternalExtract<UUID>(mc); break;
case MetaColumn::FDT_JSON:
addInternalExtract<std::string>(mc); break;
default: default:
throw Poco::InvalidArgumentException("Data type not supported."); throw Poco::InvalidArgumentException("Data type not supported.");
} }

View File

@ -25,7 +25,7 @@ target_link_libraries(Encodings PUBLIC Poco::Foundation)
target_include_directories(Encodings target_include_directories(Encodings
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
) )

View File

@ -108,7 +108,7 @@ endif(POCO_UNBUNDLED)
target_include_directories(Foundation target_include_directories(Foundation
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
) )
@ -137,6 +137,9 @@ endif()
if(WIN32) if(WIN32)
target_compile_definitions(Foundation PUBLIC POCO_OS_FAMILY_WINDOWS UNICODE _UNICODE) 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) target_link_libraries(Foundation PUBLIC iphlpapi)
endif() endif()

View File

@ -55,7 +55,6 @@
<ProjectGuid>{B01196CC-B693-4548-8464-2FF60499E73F}</ProjectGuid> <ProjectGuid>{B01196CC-B693-4548-8464-2FF60499E73F}</ProjectGuid>
<RootNamespace>Foundation</RootNamespace> <RootNamespace>Foundation</RootNamespace>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </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"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">

View File

@ -55,7 +55,6 @@
<ProjectGuid>{B01196CC-B693-4548-8464-2FF60499E73F}</ProjectGuid> <ProjectGuid>{B01196CC-B693-4548-8464-2FF60499E73F}</ProjectGuid>
<RootNamespace>Foundation</RootNamespace> <RootNamespace>Foundation</RootNamespace>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </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"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">

0
Foundation/include/Poco/AbstractObserver.h Normal file → Executable file
View File

View File

@ -142,6 +142,21 @@
// #define POCO_NET_NO_IPv6 // #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 // Windows CE has no locale support
#if defined(_WIN32_WCE) #if defined(_WIN32_WCE)
#define POCO_NO_LOCALE #define POCO_NO_LOCALE

View File

@ -10,6 +10,9 @@
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. // Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // 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 // SPDX-License-Identifier: BSL-1.0
// //
@ -19,9 +22,17 @@
#include "Poco/Foundation.h" #include "Poco/Foundation.h"
#include "Poco/Types.h"
#include <cstddef> #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 { 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 } // namespace Poco

0
Foundation/include/Poco/NObserver.h Normal file → Executable file
View File

View File

@ -113,10 +113,10 @@ public:
void wakeUpAll(); void wakeUpAll();
/// Wakes up all threads that wait for a notification. /// Wakes up all threads that wait for a notification.
bool empty() const; bool empty() const;
/// Returns true iff the queue is empty. /// Returns true iff the queue is empty.
int size() const; int size() const;
/// Returns the number of notifications in the queue. /// Returns the number of notifications in the queue.
@ -127,17 +127,17 @@ public:
/// Removes a notification from the queue. /// Removes a notification from the queue.
/// Returns true if remove succeeded, false otherwise /// Returns true if remove succeeded, false otherwise
bool hasIdleThreads() const; bool hasIdleThreads() const;
/// Returns true if the queue has at least one thread waiting /// Returns true if the queue has at least one thread waiting
/// for a notification. /// for a notification.
static NotificationQueue& defaultQueue(); static NotificationQueue& defaultQueue();
/// Returns a reference to the default /// Returns a reference to the default
/// NotificationQueue. /// NotificationQueue.
protected: protected:
Notification::Ptr dequeueOne(); Notification::Ptr dequeueOne();
private: private:
typedef std::deque<Notification::Ptr> NfQueue; typedef std::deque<Notification::Ptr> NfQueue;
struct WaitInfo struct WaitInfo

0
Foundation/include/Poco/Observer.h Normal file → Executable file
View File

View File

@ -35,7 +35,7 @@
#error Inconsistent build settings (check for /MD[d]) #error Inconsistent build settings (check for /MD[d])
#endif #endif
// https://en.wikipedia.org/wiki/Microsoft_Visual_C++
#if (_MSC_VER >= 1300) && (_MSC_VER < 1400) // Visual Studio 2003, MSVC++ 7.1 #if (_MSC_VER >= 1300) && (_MSC_VER < 1400) // Visual Studio 2003, MSVC++ 7.1
#define POCO_MSVS_VERSION 2003 #define POCO_MSVS_VERSION 2003
#define POCO_MSVC_VERSION 71 #define POCO_MSVC_VERSION 71
@ -57,9 +57,15 @@
#elif (_MSC_VER >= 1900) && (_MSC_VER < 1910) // Visual Studio 2015, MSVC++ 14.0 #elif (_MSC_VER >= 1900) && (_MSC_VER < 1910) // Visual Studio 2015, MSVC++ 14.0
#define POCO_MSVS_VERSION 2015 #define POCO_MSVS_VERSION 2015
#define POCO_MSVC_VERSION 140 #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_MSVS_VERSION 2017
#define POCO_MSVC_VERSION 141 #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 #endif

View File

@ -55,7 +55,6 @@
<ProjectGuid>{6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}</ProjectGuid> <ProjectGuid>{6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}</ProjectGuid>
<RootNamespace>TestApp</RootNamespace> <RootNamespace>TestApp</RootNamespace>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'" Label="Configuration">

View File

@ -55,7 +55,6 @@
<ProjectGuid>{6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}</ProjectGuid> <ProjectGuid>{6C41E55D-C0FC-4E01-AA8D-B7DA40E31D3A}</ProjectGuid>
<RootNamespace>TestApp</RootNamespace> <RootNamespace>TestApp</RootNamespace>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'" Label="Configuration">

View File

@ -22,7 +22,6 @@
<ProjectName>TestLibrary</ProjectName> <ProjectName>TestLibrary</ProjectName>
<ProjectGuid>{0955EB03-544B-4BD4-9C10-89CF38078F5F}</ProjectGuid> <ProjectGuid>{0955EB03-544B-4BD4-9C10-89CF38078F5F}</ProjectGuid>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'" Label="Configuration">

View File

@ -22,7 +22,6 @@
<ProjectName>TestLibrary</ProjectName> <ProjectName>TestLibrary</ProjectName>
<ProjectGuid>{0955EB03-544B-4BD4-9C10-89CF38078F5F}</ProjectGuid> <ProjectGuid>{0955EB03-544B-4BD4-9C10-89CF38078F5F}</ProjectGuid>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'" Label="Configuration">

View File

@ -55,7 +55,6 @@
<ProjectGuid>{F1EE93DF-347F-4CB3-B191-C4E63F38E972}</ProjectGuid> <ProjectGuid>{F1EE93DF-347F-4CB3-B191-C4E63F38E972}</ProjectGuid>
<RootNamespace>TestSuite</RootNamespace> <RootNamespace>TestSuite</RootNamespace>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </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"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">

View File

@ -55,7 +55,6 @@
<ProjectGuid>{F1EE93DF-347F-4CB3-B191-C4E63F38E972}</ProjectGuid> <ProjectGuid>{F1EE93DF-347F-4CB3-B191-C4E63F38E972}</ProjectGuid>
<RootNamespace>TestSuite</RootNamespace> <RootNamespace>TestSuite</RootNamespace>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup> </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"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">

View File

@ -26,7 +26,7 @@ target_link_libraries(JSON PUBLIC Poco::Foundation)
target_include_directories(JSON target_include_directories(JSON
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
) )

View File

@ -25,7 +25,7 @@ target_link_libraries(JWT PUBLIC Poco::JSON Poco::Crypto)
target_include_directories(JWT target_include_directories(JWT
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
) )

View File

@ -25,7 +25,7 @@ target_link_libraries(MongoDB PUBLIC Poco::Net)
target_include_directories(MongoDB target_include_directories(MongoDB
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
) )

View File

@ -35,7 +35,7 @@ endif(WIN32)
target_include_directories(Net target_include_directories(Net
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
) )

View File

@ -24,7 +24,7 @@ objects = \
HTTPRequestHandlerFactory HTTPStreamFactory ServerSocketImpl TCPServerParams \ HTTPRequestHandlerFactory HTTPStreamFactory ServerSocketImpl TCPServerParams \
QuotedPrintableEncoder QuotedPrintableDecoder StringPartSource \ QuotedPrintableEncoder QuotedPrintableDecoder StringPartSource \
FTPClientSession FTPStreamFactory PartHandler PartSource PartStore NullPartHandler \ FTPClientSession FTPStreamFactory PartHandler PartSource PartStore NullPartHandler \
SocketReactor SocketNotifier SocketNotification AbstractHTTPRequestHandler \ SocketReactor SocketProactor SocketNotifier SocketNotification AbstractHTTPRequestHandler \
MailRecipient MailMessage MailStream SMTPClientSession POP3ClientSession \ MailRecipient MailMessage MailStream SMTPClientSession POP3ClientSession \
RawSocket RawSocketImpl ICMPClient ICMPEventArgs ICMPPacket ICMPPacketImpl \ RawSocket RawSocketImpl ICMPClient ICMPEventArgs ICMPPacket ICMPPacketImpl \
ICMPSocket ICMPSocketImpl ICMPv4PacketImpl \ ICMPSocket ICMPSocketImpl ICMPv4PacketImpl \

View File

@ -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"> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="debug_shared|Win32"> <ProjectConfiguration Include="debug_shared|Win32">
@ -56,7 +56,7 @@
<RootNamespace>Net</RootNamespace> <RootNamespace>Net</RootNamespace>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
</PropertyGroup> </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"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
@ -117,45 +117,45 @@
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v142</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"/> <ImportGroup Label="ExtensionSettings" />
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|x64'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|x64'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'" Label="PropertySheets"> <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> </ImportGroup>
<PropertyGroup Label="UserMacros"/> <PropertyGroup Label="UserMacros" />
<PropertyGroup> <PropertyGroup>
<_ProjectFileVersion>15.0.28307.799</_ProjectFileVersion> <_ProjectFileVersion>15.0.28307.799</_ProjectFileVersion>
<TargetName Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">PocoNetd</TargetName> <TargetName Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">PocoNetd</TargetName>
@ -235,7 +235,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
@ -268,9 +268,9 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -299,7 +299,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<ProgramDataBaseFileName>..\lib\PocoNetmtd.pdb</ProgramDataBaseFileName> <ProgramDataBaseFileName>..\lib\PocoNetmtd.pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
@ -325,9 +325,9 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -347,7 +347,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<ProgramDataBaseFileName>..\lib\PocoNetmdd.pdb</ProgramDataBaseFileName> <ProgramDataBaseFileName>..\lib\PocoNetmdd.pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
@ -373,10 +373,10 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<ProgramDataBaseFileName>..\lib\PocoNetmd.pdb</ProgramDataBaseFileName> <ProgramDataBaseFileName>..\lib\PocoNetmd.pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -397,7 +397,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
@ -430,9 +430,9 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -461,7 +461,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<ProgramDataBaseFileName>..\lib64\PocoNetmtd.pdb</ProgramDataBaseFileName> <ProgramDataBaseFileName>..\lib64\PocoNetmtd.pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
@ -487,9 +487,9 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -509,7 +509,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<ProgramDataBaseFileName>..\lib64\PocoNetmdd.pdb</ProgramDataBaseFileName> <ProgramDataBaseFileName>..\lib64\PocoNetmdd.pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
@ -535,9 +535,9 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -546,122 +546,123 @@
</Lib> </Lib>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="include\Poco\Net\AbstractHTTPRequestHandler.h"/> <ClInclude Include="include\Poco\Net\AbstractHTTPRequestHandler.h" />
<ClInclude Include="include\Poco\Net\DatagramSocket.h"/> <ClInclude Include="include\Poco\Net\DatagramSocket.h" />
<ClInclude Include="include\Poco\Net\DatagramSocketImpl.h"/> <ClInclude Include="include\Poco\Net\DatagramSocketImpl.h" />
<ClInclude Include="include\Poco\Net\DialogSocket.h"/> <ClInclude Include="include\Poco\Net\DialogSocket.h" />
<ClInclude Include="include\Poco\Net\DNS.h"/> <ClInclude Include="include\Poco\Net\DNS.h" />
<ClInclude Include="include\Poco\Net\FilePartSource.h"/> <ClInclude Include="include\Poco\Net\FilePartSource.h" />
<ClInclude Include="include\Poco\Net\FTPClientSession.h"/> <ClInclude Include="include\Poco\Net\FTPClientSession.h" />
<ClInclude Include="include\Poco\Net\FTPStreamFactory.h"/> <ClInclude Include="include\Poco\Net\FTPStreamFactory.h" />
<ClInclude Include="include\Poco\Net\HostEntry.h"/> <ClInclude Include="include\Poco\Net\HostEntry.h" />
<ClInclude Include="include\Poco\Net\HTMLForm.h"/> <ClInclude Include="include\Poco\Net\HTMLForm.h" />
<ClInclude Include="include\Poco\Net\HTTPAuthenticationParams.h"/> <ClInclude Include="include\Poco\Net\HTTPAuthenticationParams.h" />
<ClInclude Include="include\Poco\Net\HTTPBasicCredentials.h"/> <ClInclude Include="include\Poco\Net\HTTPBasicCredentials.h" />
<ClInclude Include="include\Poco\Net\HTTPBasicStreamBuf.h"/> <ClInclude Include="include\Poco\Net\HTTPBasicStreamBuf.h" />
<ClInclude Include="include\Poco\Net\HTTPBufferAllocator.h"/> <ClInclude Include="include\Poco\Net\HTTPBufferAllocator.h" />
<ClInclude Include="include\Poco\Net\HTTPChunkedStream.h"/> <ClInclude Include="include\Poco\Net\HTTPChunkedStream.h" />
<ClInclude Include="include\Poco\Net\HTTPClientSession.h"/> <ClInclude Include="include\Poco\Net\HTTPClientSession.h" />
<ClInclude Include="include\Poco\Net\HTTPCookie.h"/> <ClInclude Include="include\Poco\Net\HTTPCookie.h" />
<ClInclude Include="include\Poco\Net\HTTPCredentials.h"/> <ClInclude Include="include\Poco\Net\HTTPCredentials.h" />
<ClInclude Include="include\Poco\Net\HTTPDigestCredentials.h"/> <ClInclude Include="include\Poco\Net\HTTPDigestCredentials.h" />
<ClInclude Include="include\Poco\Net\HTTPFixedLengthStream.h"/> <ClInclude Include="include\Poco\Net\HTTPFixedLengthStream.h" />
<ClInclude Include="include\Poco\Net\HTTPHeaderStream.h"/> <ClInclude Include="include\Poco\Net\HTTPHeaderStream.h" />
<ClInclude Include="include\Poco\Net\HTTPIOStream.h"/> <ClInclude Include="include\Poco\Net\HTTPIOStream.h" />
<ClInclude Include="include\Poco\Net\HTTPMessage.h"/> <ClInclude Include="include\Poco\Net\HTTPMessage.h" />
<ClInclude Include="include\Poco\Net\HTTPNTLMCredentials.h"/> <ClInclude Include="include\Poco\Net\HTTPNTLMCredentials.h" />
<ClInclude Include="include\Poco\Net\HTTPRequest.h"/> <ClInclude Include="include\Poco\Net\HTTPRequest.h" />
<ClInclude Include="include\Poco\Net\HTTPRequestHandler.h"/> <ClInclude Include="include\Poco\Net\HTTPRequestHandler.h" />
<ClInclude Include="include\Poco\Net\HTTPRequestHandlerFactory.h"/> <ClInclude Include="include\Poco\Net\HTTPRequestHandlerFactory.h" />
<ClInclude Include="include\Poco\Net\HTTPResponse.h"/> <ClInclude Include="include\Poco\Net\HTTPResponse.h" />
<ClInclude Include="include\Poco\Net\HTTPServer.h"/> <ClInclude Include="include\Poco\Net\HTTPServer.h" />
<ClInclude Include="include\Poco\Net\HTTPServerConnection.h"/> <ClInclude Include="include\Poco\Net\HTTPServerConnection.h" />
<ClInclude Include="include\Poco\Net\HTTPServerConnectionFactory.h"/> <ClInclude Include="include\Poco\Net\HTTPServerConnectionFactory.h" />
<ClInclude Include="include\Poco\Net\HTTPServerParams.h"/> <ClInclude Include="include\Poco\Net\HTTPServerParams.h" />
<ClInclude Include="include\Poco\Net\HTTPServerRequest.h"/> <ClInclude Include="include\Poco\Net\HTTPServerRequest.h" />
<ClInclude Include="include\Poco\Net\HTTPServerRequestImpl.h"/> <ClInclude Include="include\Poco\Net\HTTPServerRequestImpl.h" />
<ClInclude Include="include\Poco\Net\HTTPServerResponse.h"/> <ClInclude Include="include\Poco\Net\HTTPServerResponse.h" />
<ClInclude Include="include\Poco\Net\HTTPServerResponseImpl.h"/> <ClInclude Include="include\Poco\Net\HTTPServerResponseImpl.h" />
<ClInclude Include="include\Poco\Net\HTTPServerSession.h"/> <ClInclude Include="include\Poco\Net\HTTPServerSession.h" />
<ClInclude Include="include\Poco\Net\HTTPSession.h"/> <ClInclude Include="include\Poco\Net\HTTPSession.h" />
<ClInclude Include="include\Poco\Net\HTTPSessionFactory.h"/> <ClInclude Include="include\Poco\Net\HTTPSessionFactory.h" />
<ClInclude Include="include\Poco\Net\HTTPSessionInstantiator.h"/> <ClInclude Include="include\Poco\Net\HTTPSessionInstantiator.h" />
<ClInclude Include="include\Poco\Net\HTTPStream.h"/> <ClInclude Include="include\Poco\Net\HTTPStream.h" />
<ClInclude Include="include\Poco\Net\HTTPStreamFactory.h"/> <ClInclude Include="include\Poco\Net\HTTPStreamFactory.h" />
<ClInclude Include="include\Poco\Net\ICMPClient.h"/> <ClInclude Include="include\Poco\Net\ICMPClient.h" />
<ClInclude Include="include\Poco\Net\ICMPEventArgs.h"/> <ClInclude Include="include\Poco\Net\ICMPEventArgs.h" />
<ClInclude Include="include\Poco\Net\ICMPPacket.h"/> <ClInclude Include="include\Poco\Net\ICMPPacket.h" />
<ClInclude Include="include\Poco\Net\ICMPPacketImpl.h"/> <ClInclude Include="include\Poco\Net\ICMPPacketImpl.h" />
<ClInclude Include="include\Poco\Net\ICMPSocket.h"/> <ClInclude Include="include\Poco\Net\ICMPSocket.h" />
<ClInclude Include="include\Poco\Net\ICMPSocketImpl.h"/> <ClInclude Include="include\Poco\Net\ICMPSocketImpl.h" />
<ClInclude Include="include\Poco\Net\ICMPv4PacketImpl.h"/> <ClInclude Include="include\Poco\Net\ICMPv4PacketImpl.h" />
<ClInclude Include="include\Poco\Net\IPAddress.h"/> <ClInclude Include="include\Poco\Net\IPAddress.h" />
<ClInclude Include="include\Poco\Net\IPAddressImpl.h"/> <ClInclude Include="include\Poco\Net\IPAddressImpl.h" />
<ClInclude Include="include\Poco\Net\MailMessage.h"/> <ClInclude Include="include\Poco\Net\MailMessage.h" />
<ClInclude Include="include\Poco\Net\MailRecipient.h"/> <ClInclude Include="include\Poco\Net\MailRecipient.h" />
<ClInclude Include="include\Poco\Net\MailStream.h"/> <ClInclude Include="include\Poco\Net\MailStream.h" />
<ClInclude Include="include\Poco\Net\MediaType.h"/> <ClInclude Include="include\Poco\Net\MediaType.h" />
<ClInclude Include="include\Poco\Net\MessageHeader.h"/> <ClInclude Include="include\Poco\Net\MessageHeader.h" />
<ClInclude Include="include\Poco\Net\MulticastSocket.h"/> <ClInclude Include="include\Poco\Net\MulticastSocket.h" />
<ClInclude Include="include\Poco\Net\MultipartReader.h"/> <ClInclude Include="include\Poco\Net\MultipartReader.h" />
<ClInclude Include="include\Poco\Net\MultipartWriter.h"/> <ClInclude Include="include\Poco\Net\MultipartWriter.h" />
<ClInclude Include="include\Poco\Net\MultiSocketPoller.h"/> <ClInclude Include="include\Poco\Net\MultiSocketPoller.h" />
<ClInclude Include="include\Poco\Net\NameValueCollection.h"/> <ClInclude Include="include\Poco\Net\NameValueCollection.h" />
<ClInclude Include="include\Poco\Net\Net.h"/> <ClInclude Include="include\Poco\Net\Net.h" />
<ClInclude Include="include\Poco\Net\NetException.h"/> <ClInclude Include="include\Poco\Net\NetException.h" />
<ClInclude Include="include\Poco\Net\NetworkInterface.h"/> <ClInclude Include="include\Poco\Net\NetworkInterface.h" />
<ClInclude Include="include\Poco\Net\NTLMCredentials.h"/> <ClInclude Include="include\Poco\Net\NTLMCredentials.h" />
<ClInclude Include="include\Poco\Net\NTPClient.h"/> <ClInclude Include="include\Poco\Net\NTPClient.h" />
<ClInclude Include="include\Poco\Net\NTPEventArgs.h"/> <ClInclude Include="include\Poco\Net\NTPEventArgs.h" />
<ClInclude Include="include\Poco\Net\NTPPacket.h"/> <ClInclude Include="include\Poco\Net\NTPPacket.h" />
<ClInclude Include="include\Poco\Net\NullPartHandler.h"/> <ClInclude Include="include\Poco\Net\NullPartHandler.h" />
<ClInclude Include="include\Poco\Net\OAuth10Credentials.h"/> <ClInclude Include="include\Poco\Net\OAuth10Credentials.h" />
<ClInclude Include="include\Poco\Net\OAuth20Credentials.h"/> <ClInclude Include="include\Poco\Net\OAuth20Credentials.h" />
<ClInclude Include="include\Poco\Net\ParallelSocketAcceptor.h"/> <ClInclude Include="include\Poco\Net\ParallelSocketAcceptor.h" />
<ClInclude Include="include\Poco\Net\ParallelSocketReactor.h"/> <ClInclude Include="include\Poco\Net\ParallelSocketReactor.h" />
<ClInclude Include="include\Poco\Net\PartHandler.h"/> <ClInclude Include="include\Poco\Net\PartHandler.h" />
<ClInclude Include="include\Poco\Net\PartSource.h"/> <ClInclude Include="include\Poco\Net\PartSource.h" />
<ClInclude Include="include\Poco\Net\PartStore.h"/> <ClInclude Include="include\Poco\Net\PartStore.h" />
<ClInclude Include="include\Poco\Net\PollSet.h"/> <ClInclude Include="include\Poco\Net\PollSet.h" />
<ClInclude Include="include\Poco\Net\POP3ClientSession.h"/> <ClInclude Include="include\Poco\Net\POP3ClientSession.h" />
<ClInclude Include="include\Poco\Net\QuotedPrintableDecoder.h"/> <ClInclude Include="include\Poco\Net\QuotedPrintableDecoder.h" />
<ClInclude Include="include\Poco\Net\QuotedPrintableEncoder.h"/> <ClInclude Include="include\Poco\Net\QuotedPrintableEncoder.h" />
<ClInclude Include="include\Poco\Net\RawSocket.h"/> <ClInclude Include="include\Poco\Net\RawSocket.h" />
<ClInclude Include="include\Poco\Net\RawSocketImpl.h"/> <ClInclude Include="include\Poco\Net\RawSocketImpl.h" />
<ClInclude Include="include\Poco\Net\RemoteSyslogChannel.h"/> <ClInclude Include="include\Poco\Net\RemoteSyslogChannel.h" />
<ClInclude Include="include\Poco\Net\RemoteSyslogListener.h"/> <ClInclude Include="include\Poco\Net\RemoteSyslogListener.h" />
<ClInclude Include="include\Poco\Net\ServerSocket.h"/> <ClInclude Include="include\Poco\Net\ServerSocket.h" />
<ClInclude Include="include\Poco\Net\ServerSocketImpl.h"/> <ClInclude Include="include\Poco\Net\ServerSocketImpl.h" />
<ClInclude Include="include\Poco\Net\SingleSocketPoller.h"/> <ClInclude Include="include\Poco\Net\SingleSocketPoller.h" />
<ClInclude Include="include\Poco\Net\SMTPChannel.h"/> <ClInclude Include="include\Poco\Net\SMTPChannel.h" />
<ClInclude Include="include\Poco\Net\SMTPClientSession.h"/> <ClInclude Include="include\Poco\Net\SMTPClientSession.h" />
<ClInclude Include="include\Poco\Net\Socket.h"/> <ClInclude Include="include\Poco\Net\Socket.h" />
<ClInclude Include="include\Poco\Net\SocketAcceptor.h"/> <ClInclude Include="include\Poco\Net\SocketAcceptor.h" />
<ClInclude Include="include\Poco\Net\SocketAddress.h"/> <ClInclude Include="include\Poco\Net\SocketAddress.h" />
<ClInclude Include="include\Poco\Net\SocketAddressImpl.h"/> <ClInclude Include="include\Poco\Net\SocketAddressImpl.h" />
<ClInclude Include="include\Poco\Net\SocketConnector.h"/> <ClInclude Include="include\Poco\Net\SocketConnector.h" />
<ClInclude Include="include\Poco\Net\SocketDefs.h"/> <ClInclude Include="include\Poco\Net\SocketDefs.h" />
<ClInclude Include="include\Poco\Net\SocketImpl.h"/> <ClInclude Include="include\Poco\Net\SocketImpl.h" />
<ClInclude Include="include\Poco\Net\SocketNotification.h"/> <ClInclude Include="include\Poco\Net\SocketNotification.h" />
<ClInclude Include="include\Poco\Net\SocketNotifier.h"/> <ClInclude Include="include\Poco\Net\SocketNotifier.h" />
<ClInclude Include="include\Poco\Net\SocketReactor.h"/> <ClInclude Include="include\Poco\Net\SocketProactor.h" />
<ClInclude Include="include\Poco\Net\SocketStream.h"/> <ClInclude Include="include\Poco\Net\SocketReactor.h" />
<ClInclude Include="include\Poco\Net\SSPINTLMCredentials.h"/> <ClInclude Include="include\Poco\Net\SocketStream.h" />
<ClInclude Include="include\Poco\Net\StreamSocket.h"/> <ClInclude Include="include\Poco\Net\SSPINTLMCredentials.h" />
<ClInclude Include="include\Poco\Net\StreamSocketImpl.h"/> <ClInclude Include="include\Poco\Net\StreamSocket.h" />
<ClInclude Include="include\Poco\Net\StringPartSource.h"/> <ClInclude Include="include\Poco\Net\StreamSocketImpl.h" />
<ClInclude Include="include\Poco\Net\TCPServer.h"/> <ClInclude Include="include\Poco\Net\StringPartSource.h" />
<ClInclude Include="include\Poco\Net\TCPServerConnection.h"/> <ClInclude Include="include\Poco\Net\TCPServer.h" />
<ClInclude Include="include\Poco\Net\TCPServerConnectionFactory.h"/> <ClInclude Include="include\Poco\Net\TCPServerConnection.h" />
<ClInclude Include="include\Poco\Net\TCPServerDispatcher.h"/> <ClInclude Include="include\Poco\Net\TCPServerConnectionFactory.h" />
<ClInclude Include="include\Poco\Net\TCPServerParams.h"/> <ClInclude Include="include\Poco\Net\TCPServerDispatcher.h" />
<ClInclude Include="include\Poco\Net\UDPClient.h"/> <ClInclude Include="include\Poco\Net\TCPServerParams.h" />
<ClInclude Include="include\Poco\Net\UDPHandler.h"/> <ClInclude Include="include\Poco\Net\UDPClient.h" />
<ClInclude Include="include\Poco\Net\UDPServer.h"/> <ClInclude Include="include\Poco\Net\UDPHandler.h" />
<ClInclude Include="include\Poco\Net\UDPServerParams.h"/> <ClInclude Include="include\Poco\Net\UDPServer.h" />
<ClInclude Include="include\Poco\Net\UDPSocketReader.h"/> <ClInclude Include="include\Poco\Net\UDPServerParams.h" />
<ClInclude Include="include\Poco\Net\WebSocket.h"/> <ClInclude Include="include\Poco\Net\UDPSocketReader.h" />
<ClInclude Include="include\Poco\Net\WebSocketImpl.h"/> <ClInclude Include="include\Poco\Net\WebSocket.h" />
<ClInclude Include="include\Poco\Net\WebSocketImpl.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\AbstractHTTPRequestHandler.cpp"> <ClCompile Include="src\AbstractHTTPRequestHandler.cpp">
@ -934,6 +935,7 @@
<ClCompile Include="src\SocketNotifier.cpp"> <ClCompile Include="src\SocketNotifier.cpp">
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<ClCompile Include="src\SocketProactor.cpp" />
<ClCompile Include="src\SocketReactor.cpp"> <ClCompile Include="src\SocketReactor.cpp">
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -992,6 +994,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
</ResourceCompile> </ResourceCompile>
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"/> <ImportGroup Label="ExtensionTargets" />
</Project> </Project>

View File

@ -513,6 +513,9 @@
<ClInclude Include="include\Poco\Net\SSPINTLMCredentials.h"> <ClInclude Include="include\Poco\Net\SSPINTLMCredentials.h">
<Filter>NTLM\Header Files</Filter> <Filter>NTLM\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="include\Poco\Net\SocketProactor.h">
<Filter>Sockets\Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\DNS.cpp"> <ClCompile Include="src\DNS.cpp">
@ -830,6 +833,9 @@
<ClCompile Include="src\SSPINTLMCredentials.cpp"> <ClCompile Include="src\SSPINTLMCredentials.cpp">
<Filter>NTLM\Source Files</Filter> <Filter>NTLM\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\SocketProactor.cpp">
<Filter>Sockets\Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="..\DLLVersion.rc" /> <ResourceCompile Include="..\DLLVersion.rc" />

View File

@ -48,19 +48,14 @@ public:
/// The socket will be created for the /// The socket will be created for the
/// given address family. /// given address family.
DatagramSocket(const SocketAddress& address, bool reuseAddress = false); 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.
DatagramSocket(const SocketAddress& address, bool reuseAddress, bool reusePort);
/// Creates a datagram socket and binds it /// Creates a datagram socket and binds it
/// to the given address. /// to the given address.
/// ///
/// Depending on the address family, the socket /// Depending on the address family, the socket
/// will be either an IPv4 or an IPv6 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); DatagramSocket(const Socket& socket);
/// Creates the DatagramSocket with the SocketImpl /// Creates the DatagramSocket with the SocketImpl
@ -68,6 +63,10 @@ public:
/// a DatagramSocketImpl, otherwise an InvalidArgumentException /// a DatagramSocketImpl, otherwise an InvalidArgumentException
/// will be thrown. /// will be thrown.
DatagramSocket(const DatagramSocket& socket);
/// Creates the DatagramSocket with the SocketImpl
/// from another socket.
~DatagramSocket(); ~DatagramSocket();
/// Destroys the DatagramSocket. /// Destroys the DatagramSocket.
@ -78,6 +77,43 @@ public:
/// attaches the SocketImpl from the other socket and /// attaches the SocketImpl from the other socket and
/// increments the reference count of the SocketImpl. /// 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); void connect(const SocketAddress& address);
/// Restricts incoming and outgoing /// Restricts incoming and outgoing
/// packets to the specified address. /// packets to the specified address.
@ -109,6 +145,23 @@ public:
/// ///
/// Calls to connect cannot() come before calls to bind(). /// 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); int sendBytes(const void* buffer, int length, int flags = 0);
/// Sends the contents of the given buffer through /// Sends the contents of the given buffer through
/// the socket. /// the socket.
@ -231,7 +284,7 @@ protected:
/// Creates the Socket and attaches the given SocketImpl. /// Creates the Socket and attaches the given SocketImpl.
/// The socket takes ownership of the 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. /// an InvalidArgumentException will be thrown.
}; };

View File

@ -24,6 +24,7 @@
#include "Poco/AutoPtr.h" #include "Poco/AutoPtr.h"
#include "Poco/Exception.h" #include "Poco/Exception.h"
#include <vector> #include <vector>
#include <array>
#include <ostream> #include <ostream>
@ -56,6 +57,13 @@ class Net_API IPAddress
public: public:
using List = std::vector<IPAddress>; 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 // The following declarations keep the Family type
// backwards compatible with the previously used // backwards compatible with the previously used
// enum declaration. // enum declaration.
@ -71,6 +79,9 @@ public:
IPAddress(const IPAddress& addr); IPAddress(const IPAddress& addr);
/// Creates an IPAddress by copying another one. /// Creates an IPAddress by copying another one.
IPAddress(IPAddress&& addr);
/// Creates an IPAddress by moving another one.
explicit IPAddress(Family family); explicit IPAddress(Family family);
/// Creates a wildcard (zero) IPAddress for the /// Creates a wildcard (zero) IPAddress for the
/// given address family. /// given address family.
@ -121,7 +132,16 @@ public:
IPAddress& operator = (const IPAddress& addr); IPAddress& operator = (const IPAddress& addr);
/// Assigns an IPAddress. /// 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; Family family() const;
/// Returns the address family (IPv4 or IPv6) of the address. /// 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);
void newIPv6(const void* hostAddr, Poco::UInt32 scope); void newIPv6(const void* hostAddr, Poco::UInt32 scope);
void newIPv6(unsigned prefix); void newIPv6(unsigned prefix);
static std::string& compressV6(std::string& v6addr);
static std::string trimIPv6(const std::string v6Addr);
#endif #endif
Ptr _pImpl; Ptr _pImpl;
}; };
@ -384,6 +406,19 @@ private:
// //
// inlines // inlines
// //
inline bool IPAddress::isV4() const
{
return family() == IPv4;
}
inline bool IPAddress::isV6() const
{
return family() == IPv6;
}
inline IPAddress::Ptr IPAddress::pImpl() const inline IPAddress::Ptr IPAddress::pImpl() const
{ {
if (_pImpl) return _pImpl; if (_pImpl) return _pImpl;

View File

@ -30,7 +30,7 @@ namespace Net {
template <std::size_t S = POCO_UDP_BUF_SIZE> template <std::size_t S = POCO_UDP_BUF_SIZE>
class MultiSocketPoller class MultiSocketPoller
/// MultiSocketPoller, as its name indicates, repeatedly polls a set of /// 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. /// state, the reading/error handling actions are delegated to the reader.
{ {
public: public:

View File

@ -67,6 +67,14 @@
#endif // POCO_NET_NO_IPv6, POCO_HAVE_IPv6 #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 Poco {
namespace Net { namespace Net {
@ -124,4 +132,24 @@ POCO_NET_FORCE_SYMBOL(pocoNetworkInitializer)
#endif #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 #endif // Net_Net_INCLUDED

View File

@ -78,6 +78,13 @@ public:
/// Returns a PollMap containing the sockets that have had /// Returns a PollMap containing the sockets that have had
/// their state changed. /// 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: private:
PollSetImpl* _pImpl; PollSetImpl* _pImpl;

View File

@ -53,6 +53,10 @@ public:
/// a RawSocketImpl, otherwise an InvalidArgumentException /// a RawSocketImpl, otherwise an InvalidArgumentException
/// will be thrown. /// will be thrown.
RawSocket(const RawSocket& socket);
/// Creates the RawSocket with the SocketImpl
/// from another socket.
~RawSocket(); ~RawSocket();
/// Destroys the RawSocket. /// Destroys the RawSocket.
@ -61,7 +65,44 @@ public:
/// ///
/// Releases the socket's SocketImpl and /// Releases the socket's SocketImpl and
/// attaches the SocketImpl from the other socket and /// attaches the SocketImpl from the other socket and
/// increments the reference count of the SocketImpl. /// 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); void connect(const SocketAddress& address);
/// Restricts incoming and outgoing /// Restricts incoming and outgoing
@ -135,7 +176,7 @@ protected:
/// Creates the Socket and attaches the given SocketImpl. /// Creates the Socket and attaches the given SocketImpl.
/// The socket takes ownership of the 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. /// an InvalidArgumentException will be thrown.
}; };

View File

@ -30,7 +30,7 @@ namespace Net {
template <std::size_t S = POCO_UDP_BUF_SIZE> template <std::size_t S = POCO_UDP_BUF_SIZE>
class SingleSocketPoller 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 /// socket for readability; if the socket is readable, the reading action
/// is delegated to the reader. /// is delegated to the reader.
{ {

View File

@ -36,6 +36,8 @@ class Net_API Socket
{ {
public: public:
using BufVec = SocketBufVec; using BufVec = SocketBufVec;
using Type = SocketImpl::Type;
using SocketList = std::vector<Socket>;
enum SelectMode enum SelectMode
/// The mode argument to poll() and select(). /// The mode argument to poll() and select().
@ -44,8 +46,6 @@ public:
SELECT_WRITE = 2, SELECT_WRITE = 2,
SELECT_ERROR = 4 SELECT_ERROR = 4
}; };
using SocketList = std::vector<Socket>;
Socket(); Socket();
/// Creates an uninitialized socket. /// Creates an uninitialized socket.
@ -55,14 +55,31 @@ public:
/// ///
/// Attaches the SocketImpl from the other socket and /// Attaches the SocketImpl from the other socket and
/// increments the reference count of the SocketImpl. /// increments the reference count of the SocketImpl.
Socket& operator = (const Socket& socket); Socket& operator = (const Socket& socket);
/// Assignment operator. /// Assignment operator.
/// ///
/// Releases the socket's SocketImpl and /// Releases the socket's SocketImpl and
/// attaches the SocketImpl from the other socket and /// attaches the SocketImpl from the other socket and
/// increments the reference count of the SocketImpl. /// 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(); virtual ~Socket();
/// Destroys the Socket and releases the /// Destroys the Socket and releases the
/// SocketImpl. /// SocketImpl.
@ -86,7 +103,25 @@ public:
bool operator >= (const Socket& socket) const; bool operator >= (const Socket& socket) const;
/// Compares the SocketImpl pointers. /// 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(); void close();
/// Closes the socket. /// Closes the socket.
@ -134,6 +169,9 @@ public:
/// Returns the number of bytes available that can be read /// Returns the number of bytes available that can be read
/// without causing the socket to block. /// without causing the socket to block.
int getError() const;
/// Returns the socket error.
void setSendBufferSize(int size); void setSendBufferSize(int size);
/// Sets the size of the send buffer. /// Sets the size of the send buffer.
@ -334,6 +372,12 @@ public:
/// of buffers used for writing (ie. reading from socket /// of buffers used for writing (ie. reading from socket
/// into buffers). /// into buffers).
static int lastError();
/// Returns the last error code.
static void error();
/// Throws an appropriate exception for the last error.
protected: protected:
Socket(SocketImpl* pImpl); Socket(SocketImpl* pImpl);
/// Creates the Socket and attaches the given SocketImpl. /// 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() inline void Socket::close()
{ {
_pImpl->close(); if (_pImpl) _pImpl->close();
} }
inline bool Socket::poll(const Poco::Timespan& timeout, int mode) const 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); return _pImpl->poll(timeout, mode);
} }
inline int Socket::available() const inline int Socket::available() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->available(); 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) inline void Socket::setSendBufferSize(int size)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->setSendBufferSize(size); _pImpl->setSendBufferSize(size);
} }
inline int Socket::getSendBufferSize() const inline int Socket::getSendBufferSize() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->getSendBufferSize(); return _pImpl->getSendBufferSize();
} }
inline void Socket::setReceiveBufferSize(int size) inline void Socket::setReceiveBufferSize(int size)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->setReceiveBufferSize(size); _pImpl->setReceiveBufferSize(size);
} }
inline int Socket::getReceiveBufferSize() const inline int Socket::getReceiveBufferSize() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->getReceiveBufferSize(); return _pImpl->getReceiveBufferSize();
} }
inline void Socket::setSendTimeout(const Poco::Timespan& timeout) inline void Socket::setSendTimeout(const Poco::Timespan& timeout)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->setSendTimeout(timeout); _pImpl->setSendTimeout(timeout);
} }
inline Poco::Timespan Socket::getSendTimeout() const inline Poco::Timespan Socket::getSendTimeout() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->getSendTimeout(); return _pImpl->getSendTimeout();
} }
inline void Socket::setReceiveTimeout(const Poco::Timespan& timeout) inline void Socket::setReceiveTimeout(const Poco::Timespan& timeout)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->setReceiveTimeout(timeout); _pImpl->setReceiveTimeout(timeout);
} }
inline Poco::Timespan Socket::getReceiveTimeout() const inline Poco::Timespan Socket::getReceiveTimeout() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->getReceiveTimeout(); return _pImpl->getReceiveTimeout();
} }
inline void Socket::setOption(int level, int option, int value) inline void Socket::setOption(int level, int option, int value)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->setOption(level, option, value); _pImpl->setOption(level, option, value);
} }
inline void Socket::setOption(int level, int option, unsigned 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); _pImpl->setOption(level, option, value);
} }
inline void Socket::setOption(int level, int option, unsigned char 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); _pImpl->setOption(level, option, value);
} }
inline void Socket::setOption(int level, int option, const Poco::Timespan& 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); _pImpl->setOption(level, option, value);
} }
inline void Socket::setOption(int level, int option, const IPAddress& 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); _pImpl->setOption(level, option, value);
} }
inline void Socket::getOption(int level, int option, int& value) const 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); _pImpl->getOption(level, option, value);
} }
inline void Socket::getOption(int level, int option, unsigned& value) const 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); _pImpl->getOption(level, option, value);
} }
inline void Socket::getOption(int level, int option, unsigned char& value) const 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); _pImpl->getOption(level, option, value);
} }
inline void Socket::getOption(int level, int option, Poco::Timespan& value) const 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); _pImpl->getOption(level, option, value);
} }
inline void Socket::getOption(int level, int option, IPAddress& value) const 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); _pImpl->getOption(level, option, value);
} }
inline void Socket::setLinger(bool on, int seconds) inline void Socket::setLinger(bool on, int seconds)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->setLinger(on, seconds); _pImpl->setLinger(on, seconds);
} }
inline void Socket::getLinger(bool& on, int& seconds) const inline void Socket::getLinger(bool& on, int& seconds) const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->getLinger(on, seconds); _pImpl->getLinger(on, seconds);
} }
inline void Socket::setNoDelay(bool flag) inline void Socket::setNoDelay(bool flag)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->setNoDelay(flag); _pImpl->setNoDelay(flag);
} }
inline bool Socket::getNoDelay() const inline bool Socket::getNoDelay() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->getNoDelay(); return _pImpl->getNoDelay();
} }
inline void Socket::setKeepAlive(bool flag) inline void Socket::setKeepAlive(bool flag)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->setKeepAlive(flag); _pImpl->setKeepAlive(flag);
} }
inline bool Socket::getKeepAlive() const inline bool Socket::getKeepAlive() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->getKeepAlive(); return _pImpl->getKeepAlive();
} }
inline void Socket::setReuseAddress(bool flag) inline void Socket::setReuseAddress(bool flag)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->setReuseAddress(flag); _pImpl->setReuseAddress(flag);
} }
inline bool Socket::getReuseAddress() const inline bool Socket::getReuseAddress() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->getReuseAddress(); return _pImpl->getReuseAddress();
} }
inline void Socket::setReusePort(bool flag) inline void Socket::setReusePort(bool flag)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->setReusePort(flag); _pImpl->setReusePort(flag);
} }
inline bool Socket::getReusePort() const inline bool Socket::getReusePort() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->getReusePort(); return _pImpl->getReusePort();
} }
inline void Socket::setOOBInline(bool flag) inline void Socket::setOOBInline(bool flag)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->setOOBInline(flag); _pImpl->setOOBInline(flag);
} }
inline bool Socket::getOOBInline() const inline bool Socket::getOOBInline() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->getOOBInline(); return _pImpl->getOOBInline();
} }
inline void Socket::setBlocking(bool flag) inline void Socket::setBlocking(bool flag)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->setBlocking(flag); _pImpl->setBlocking(flag);
} }
inline bool Socket::getBlocking() const inline bool Socket::getBlocking() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->getBlocking(); return _pImpl->getBlocking();
} }
@ -621,24 +771,32 @@ inline SocketImpl* Socket::impl() const
inline poco_socket_t Socket::sockfd() const inline poco_socket_t Socket::sockfd() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->sockfd(); return _pImpl->sockfd();
} }
inline SocketAddress Socket::address() const inline SocketAddress Socket::address() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->address(); return _pImpl->address();
} }
inline SocketAddress Socket::peerAddress() const inline SocketAddress Socket::peerAddress() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->peerAddress(); return _pImpl->peerAddress();
} }
inline bool Socket::secure() const inline bool Socket::secure() const
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
return _pImpl->secure(); return _pImpl->secure();
} }
@ -661,6 +819,8 @@ inline bool Socket::supportsIPv6()
inline void Socket::init(int af) inline void Socket::init(int af)
{ {
poco_assert_dbg(POCO_NEW_STATE_ON_MOVE && _pImpl);
_pImpl->init(af); _pImpl->init(af);
} }

View File

@ -138,6 +138,9 @@ public:
SocketAddress(const SocketAddress& addr); SocketAddress(const SocketAddress& addr);
/// Creates a SocketAddress by copying another one. /// 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); SocketAddress(const struct sockaddr* addr, poco_socklen_t length);
/// Creates a SocketAddress from a native socket address. /// Creates a SocketAddress from a native socket address.
@ -147,6 +150,9 @@ public:
SocketAddress& operator = (const SocketAddress& socketAddress); SocketAddress& operator = (const SocketAddress& socketAddress);
/// Assigns another SocketAddress. /// Assigns another SocketAddress.
SocketAddress& operator = (SocketAddress&& socketAddress);
/// Move-assigns another SocketAddress.
IPAddress host() const; IPAddress host() const;
/// Returns the host IP address. /// Returns the host IP address.

View File

@ -82,7 +82,7 @@ public:
SocketConnector(SocketAddress& address, SocketReactor& reactor, bool doRegister = true) : SocketConnector(SocketAddress& address, SocketReactor& reactor, bool doRegister = true) :
_pReactor(0) _pReactor(0)
/// Creates an acceptor, using the given ServerSocket. /// Creates an connector, using the given ServerSocket.
/// The SocketConnector registers itself with the given SocketReactor. /// The SocketConnector registers itself with the given SocketReactor.
{ {
_socket.connectNB(address); _socket.connectNB(address);
@ -152,21 +152,22 @@ public:
pNotification->release(); pNotification->release();
onConnect(); onConnect();
} }
void onConnect() void onConnect()
{ {
_socket.setBlocking(true); _socket.setBlocking(true);
createServiceHandler(); createServiceHandler();
unregisterConnector(); unregisterConnector();
} }
void onError(ErrorNotification* pNotification) void onError(ErrorNotification* pNotification)
{ {
pNotification->release(); pNotification->release();
onError(_socket.impl()->socketError()); onError(_socket.impl()->socketError());
unregisterConnector(); unregisterConnector();
} }
protected: protected:
virtual ServiceHandler* createServiceHandler() virtual ServiceHandler* createServiceHandler()
/// Create and initialize a new ServiceHandler instance. /// Create and initialize a new ServiceHandler instance.
@ -191,7 +192,7 @@ protected:
{ {
return _pReactor; return _pReactor;
} }
StreamSocket& socket() StreamSocket& socket()
/// Returns a reference to the SocketConnector's socket. /// Returns a reference to the SocketConnector's socket.
{ {

View File

@ -26,6 +26,7 @@
#if defined(POCO_OS_FAMILY_WINDOWS) #if defined(POCO_OS_FAMILY_WINDOWS)
#include "Poco/UnWindows.h" #include "Poco/UnWindows.h"
#define FD_SETSIZE 1024 // increase as needed
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <ws2def.h> #include <ws2def.h>
@ -371,16 +372,18 @@ struct AddressFamily
enum Family enum Family
/// Possible address families for socket addresses. /// 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. /// IPv4 address family.
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6)
IPv6, IPv6 = AF_INET6
/// IPv6 address family. /// IPv6 address family.
#endif #endif
#if defined(POCO_OS_FAMILY_UNIX)
UNIX_LOCAL
/// UNIX domain socket address family. Available on UNIX/POSIX platforms only.
#endif
}; };
}; };

View File

@ -39,6 +39,13 @@ class Net_API SocketImpl: public Poco::RefCountedObject
/// You should not create any instances of this class. /// You should not create any instances of this class.
{ {
public: public:
enum Type
{
SOCKET_TYPE_STREAM = SOCK_STREAM,
SOCKET_TYPE_DATAGRAM = SOCK_DGRAM,
SOCKET_TYPE_RAW = SOCK_RAW
};
enum SelectMode enum SelectMode
{ {
SELECT_READ = 1, SELECT_READ = 1,
@ -271,6 +278,12 @@ public:
/// Returns true if the next operation corresponding to /// Returns true if the next operation corresponding to
/// mode will not block, false otherwise. /// mode will not block, false otherwise.
Type type();
/// Returns the socket type.
virtual int getError();
/// Returns the socket error.
virtual void setSendBufferSize(int size); virtual void setSendBufferSize(int size);
/// Sets the size of the send buffer. /// Sets the size of the send buffer.
@ -526,6 +539,17 @@ private:
// //
// inlines // 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 inline poco_socket_t SocketImpl::sockfd() const
{ {
return _sockfd; return _sockfd;

View 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

View File

@ -209,7 +209,7 @@ protected:
private: private:
typedef Poco::AutoPtr<SocketNotifier> NotifierPtr; typedef Poco::AutoPtr<SocketNotifier> NotifierPtr;
typedef Poco::AutoPtr<SocketNotification> NotificationPtr; typedef Poco::AutoPtr<SocketNotification> NotificationPtr;
typedef std::map<Socket, NotifierPtr> EventHandlerMap; typedef std::map<poco_socket_t, NotifierPtr> EventHandlerMap;
typedef Poco::FastMutex MutexType; typedef Poco::FastMutex MutexType;
typedef MutexType::ScopedLock ScopedLock; typedef MutexType::ScopedLock ScopedLock;

View File

@ -60,6 +60,10 @@ public:
/// a StreamSocketImpl, otherwise an InvalidArgumentException /// a StreamSocketImpl, otherwise an InvalidArgumentException
/// will be thrown. /// will be thrown.
StreamSocket(const StreamSocket& socket);
/// Creates the StreamSocket with the SocketImpl
/// from another socket.
virtual ~StreamSocket(); virtual ~StreamSocket();
/// Destroys the StreamSocket. /// Destroys the StreamSocket.
@ -70,6 +74,43 @@ public:
/// attaches the SocketImpl from the other socket and /// attaches the SocketImpl from the other socket and
/// increments the reference count of the SocketImpl. /// 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); void connect(const SocketAddress& address);
/// Initializes the socket and establishes a connection to /// Initializes the socket and establishes a connection to
/// the TCP server at the given address. /// the TCP server at the given address.

View File

@ -42,7 +42,7 @@ typedef int UDPMsgSizeT;
template <std::size_t S = POCO_UDP_BUF_SIZE> template <std::size_t S = POCO_UDP_BUF_SIZE>
class UDPHandlerImpl: public Runnable, public RefCountedObject 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 /// 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 /// can be used in parallel.Handler manages and provides the storage
/// (fixed-size memory blocks of S size) to the reader, which signals back /// (fixed-size memory blocks of S size) to the reader, which signals back

View File

@ -176,8 +176,11 @@ public:
/// Creates a WebSocket from another Socket, which must be a WebSocket, /// Creates a WebSocket from another Socket, which must be a WebSocket,
/// otherwise a Poco::InvalidArgumentException will be thrown. /// otherwise a Poco::InvalidArgumentException will be thrown.
WebSocket(const WebSocket& socket);
/// Creates a WebSocket from another WebSocket.
virtual ~WebSocket(); virtual ~WebSocket();
/// Destroys the StreamSocket. /// Destroys the WebSocket.
WebSocket& operator = (const Socket& socket); WebSocket& operator = (const Socket& socket);
/// Assignment operator. /// Assignment operator.
@ -185,6 +188,39 @@ public:
/// The other socket must be a WebSocket, otherwise a Poco::InvalidArgumentException /// The other socket must be a WebSocket, otherwise a Poco::InvalidArgumentException
/// will be thrown. /// 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(); void shutdown();
/// Sends a Close control frame to the server end of /// Sends a Close control frame to the server end of
/// the connection to initiate an orderly shutdown /// the connection to initiate an orderly shutdown

View File

@ -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); if (address.family() == SocketAddress::IPv6)
} bind6(address, reuseAddress, reusePort, ipV6Only);
else bind(address, reuseAddress, reusePort);
DatagramSocket::DatagramSocket(const SocketAddress& address, bool reuseAddress, bool reusePort): Socket(new DatagramSocketImpl(address.family()))
{
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) DatagramSocket::DatagramSocket(SocketImpl* pImpl): Socket(pImpl)
{ {
if (!dynamic_cast<DatagramSocketImpl*>(impl())) if (!dynamic_cast<DatagramSocketImpl*>(impl()))
@ -74,6 +76,44 @@ DatagramSocket& DatagramSocket::operator = (const Socket& socket)
return *this; 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) 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) int DatagramSocket::sendBytes(const void* buffer, int length, int flags)
{ {
return impl()->sendBytes(buffer, length, flags); return impl()->sendBytes(buffer, length, flags);

View File

@ -66,7 +66,7 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
{ {
int maxPacketSize = _icmpPacket.maxPacketSize(); int maxPacketSize = _icmpPacket.maxPacketSize();
Poco::Buffer<unsigned char> buffer(maxPacketSize); Poco::Buffer<unsigned char> buffer(maxPacketSize);
int expected = _icmpPacket.packetSize(); int leftover = _icmpPacket.packetSize();
int type = 0, code = 0; int type = 0, code = 0;
try try
@ -83,8 +83,8 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
if (rc == 0) break; if (rc == 0) break;
if (respAddr == address) if (respAddr == address)
{ {
expected -= rc; leftover -= rc;
if (expected <= 0) if (leftover <= 0)
{ {
if (_icmpPacket.validReplyID(buffer.begin(), maxPacketSize)) break; if (_icmpPacket.validReplyID(buffer.begin(), maxPacketSize)) break;
std::string err = _icmpPacket.errorDescription(buffer.begin(), maxPacketSize, type, code); 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; else continue;
} }
while (expected > 0 && !_icmpPacket.validReplyID(buffer.begin(), maxPacketSize)); while (leftover > 0 && !_icmpPacket.validReplyID(buffer.begin(), maxPacketSize));
} }
catch (ICMPException&) catch (ICMPException&)
{ {
@ -113,10 +113,11 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
else throw; else throw;
} }
if (expected > 0) if (leftover > 0)
{ {
throw ICMPException(Poco::format("No response: expected %d, received: %d", _icmpPacket.packetSize(), std::string err = leftover < _icmpPacket.packetSize() ? "Incomplete" : "No";
_icmpPacket.packetSize() - expected)); throw ICMPException(Poco::format("%s response: expected %d, received: %d", err, _icmpPacket.packetSize(),
_icmpPacket.packetSize() - leftover));
} }
struct timeval then = _icmpPacket.time(buffer.begin(), maxPacketSize); struct timeval then = _icmpPacket.time(buffer.begin(), maxPacketSize);

View File

@ -19,6 +19,7 @@
#include "Poco/BinaryReader.h" #include "Poco/BinaryReader.h"
#include "Poco/BinaryWriter.h" #include "Poco/BinaryWriter.h"
#include "Poco/String.h" #include "Poco/String.h"
#include "Poco/Format.h"
#include "Poco/Types.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) IPAddress::IPAddress(Family family)
{ {
if (family == IPv4) if (family == IPv4)
@ -99,7 +105,7 @@ IPAddress::IPAddress(const std::string& addr)
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6)
IPv6AddressImpl empty6 = IPv6AddressImpl(); IPv6AddressImpl empty6 = IPv6AddressImpl();
if (addr.empty() || trim(addr) == "::") if (addr.empty() || trimIPv6(addr) == "::")
{ {
newIPv6(empty6.addr()); newIPv6(empty6.addr());
return; 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 IPAddress::Family IPAddress::family() const
{ {
return pImpl()->family(); 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) IPAddress IPAddress::parse(const std::string& addr)
{ {
return IPAddress(addr); return IPAddress(addr);
@ -535,7 +589,7 @@ bool IPAddress::tryParse(const std::string& addr, IPAddress& result)
} }
#if defined(POCO_HAVE_IPv6) #if defined(POCO_HAVE_IPv6)
IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr)); IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr));
if (impl6 != IPv6AddressImpl()) if (impl6 != IPv6AddressImpl() || trimIPv6(addr) == "::")
{ {
result.newIPv6(impl6.addr(), impl6.scope()); result.newIPv6(impl6.addr(), impl6.scope());
return true; 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 } } // namespace Poco::Net

View File

@ -18,23 +18,13 @@
#include <set> #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) #if defined(POCO_HAVE_FD_EPOLL)
#include <sys/epoll.h> #include <sys/epoll.h>
#include <sys/eventfd.h>
#elif defined(POCO_HAVE_FD_POLL) #elif defined(POCO_HAVE_FD_POLL)
#ifndef _WIN32 #ifndef _WIN32
#include <poll.h> #include <poll.h>
#endif #endif
#endif #endif
@ -51,12 +41,12 @@ namespace Net {
class PollSetImpl class PollSetImpl
{ {
public: public:
PollSetImpl(): PollSetImpl(): _epollfd(epoll_create(1)),
_epollfd(-1), _events(1024),
_events(1024) _eventfd(eventfd(0, 0))
{ {
_epollfd = epoll_create(1); int err = addImpl(_eventfd, PollSet::POLL_READ, 0);
if (_epollfd < 0) if ((err) || (_epollfd < 0))
{ {
SocketImpl::error(); SocketImpl::error();
} }
@ -64,8 +54,8 @@ public:
~PollSetImpl() ~PollSetImpl()
{ {
if (_epollfd >= 0) if (_epollfd >= 0) ::close(_epollfd);
::close(_epollfd); if (_eventfd >= 0) ::close(_eventfd);
} }
void add(const Socket& socket, int mode) void add(const Socket& socket, int mode)
@ -73,17 +63,8 @@ public:
Poco::FastMutex::ScopedLock lock(_mutex); Poco::FastMutex::ScopedLock lock(_mutex);
SocketImpl* sockImpl = socket.impl(); SocketImpl* sockImpl = socket.impl();
poco_socket_t fd = sockImpl->sockfd();
struct epoll_event ev; int err = addImpl(sockImpl->sockfd(), mode, sockImpl);
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);
if (err) if (err)
{ {
@ -158,18 +139,13 @@ public:
PollSet::SocketModeMap poll(const Poco::Timespan& timeout) PollSet::SocketModeMap poll(const Poco::Timespan& timeout)
{ {
PollSet::SocketModeMap result; PollSet::SocketModeMap result;
{
Poco::FastMutex::ScopedLock lock(_mutex);
if(_socketMap.empty()) return result;
}
Poco::Timespan remainingTime(timeout); Poco::Timespan remainingTime(timeout);
int rc; int rc;
do do
{ {
Poco::Timestamp start; Poco::Timestamp start;
rc = epoll_wait(_epollfd, &_events[0], _events.size(), remainingTime.totalMilliseconds()); rc = epoll_wait(_epollfd, &_events[0], _events.size(), remainingTime.totalMilliseconds());
if (rc == 0) return result;
if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
{ {
Poco::Timestamp end; Poco::Timestamp end;
@ -187,26 +163,57 @@ public:
for (int i = 0; i < rc; i++) 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
if (it != _socketMap.end())
{ {
if (_events[i].events & EPOLLIN) std::map<void *, Socket>::iterator it = _socketMap.find(_events[i].data.ptr);
result[it->second] |= PollSet::POLL_READ; if (it != _socketMap.end())
if (_events[i].events & EPOLLOUT) {
result[it->second] |= PollSet::POLL_WRITE; if (_events[i].events & EPOLLIN)
if (_events[i].events & EPOLLERR) result[it->second] |= PollSet::POLL_READ;
result[it->second] |= PollSet::POLL_ERROR; if (_events[i].events & EPOLLOUT)
result[it->second] |= PollSet::POLL_WRITE;
if (_events[i].events & EPOLLERR)
result[it->second] |= PollSet::POLL_ERROR;
}
} }
} }
return result; 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: 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; mutable Poco::FastMutex _mutex;
int _epollfd; int _epollfd;
std::map<void*, Socket> _socketMap; std::map<void*, Socket> _socketMap;
std::vector<struct epoll_event> _events; std::vector<struct epoll_event> _events;
int _eventfd;
}; };
@ -222,7 +229,6 @@ public:
void add(const Socket& socket, int mode) void add(const Socket& socket, int mode)
{ {
Poco::FastMutex::ScopedLock lock(_mutex); Poco::FastMutex::ScopedLock lock(_mutex);
poco_socket_t fd = socket.impl()->sockfd(); poco_socket_t fd = socket.impl()->sockfd();
_addMap[fd] = mode; _addMap[fd] = mode;
_removeSet.erase(fd); _removeSet.erase(fd);
@ -232,7 +238,6 @@ public:
void remove(const Socket& socket) void remove(const Socket& socket)
{ {
Poco::FastMutex::ScopedLock lock(_mutex); Poco::FastMutex::ScopedLock lock(_mutex);
poco_socket_t fd = socket.impl()->sockfd(); poco_socket_t fd = socket.impl()->sockfd();
_removeSet.insert(fd); _removeSet.insert(fd);
_addMap.erase(fd); _addMap.erase(fd);
@ -256,7 +261,6 @@ public:
void update(const Socket& socket, int mode) void update(const Socket& socket, int mode)
{ {
Poco::FastMutex::ScopedLock lock(_mutex); Poco::FastMutex::ScopedLock lock(_mutex);
poco_socket_t fd = socket.impl()->sockfd(); poco_socket_t fd = socket.impl()->sockfd();
for (auto it = _pollfds.begin(); it != _pollfds.end(); ++it) for (auto it = _pollfds.begin(); it != _pollfds.end(); ++it)
{ {
@ -264,7 +268,7 @@ public:
{ {
it->events = 0; it->events = 0;
it->revents = 0; it->revents = 0;
setMode(it->fd, it->events, mode); setMode(it->events, mode);
} }
} }
} }
@ -305,7 +309,7 @@ public:
pfd.fd = it->first; pfd.fd = it->first;
pfd.events = 0; pfd.events = 0;
pfd.revents = 0; pfd.revents = 0;
setMode(pfd.fd, pfd.events, it->second); setMode(pfd.events, it->second);
_pollfds.push_back(pfd); _pollfds.push_back(pfd);
} }
_addMap.clear(); _addMap.clear();
@ -320,12 +324,6 @@ public:
Poco::Timestamp start; Poco::Timestamp start;
#ifdef _WIN32 #ifdef _WIN32
rc = WSAPoll(&_pollfds[0], static_cast<ULONG>(_pollfds.size()), static_cast<INT>(remainingTime.totalMilliseconds())); 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 #else
rc = ::poll(&_pollfds[0], _pollfds.size(), remainingTime.totalMilliseconds()); rc = ::poll(&_pollfds[0], _pollfds.size(), remainingTime.totalMilliseconds());
#endif #endif
@ -354,17 +352,13 @@ public:
{ {
if ((it->revents & POLLIN) if ((it->revents & POLLIN)
#ifdef _WIN32 #ifdef _WIN32
|| (it->revents & POLLHUP) || (it->revents & POLLHUP)
#endif #endif
) )
result[its->second] |= PollSet::POLL_READ; result[its->second] |= PollSet::POLL_READ;
if ((it->revents & POLLOUT) if (it->revents & POLLOUT)
#ifdef _WIN32
&& (_wantPOLLOUT.find(it->fd) != _wantPOLLOUT.end())
#endif
)
result[its->second] |= PollSet::POLL_WRITE; result[its->second] |= PollSet::POLL_WRITE;
if (it->revents & POLLERR) if (it->revents & POLLERR || (it->revents & POLLHUP))
result[its->second] |= PollSet::POLL_ERROR; result[its->second] |= PollSet::POLL_ERROR;
} }
it->revents = 0; it->revents = 0;
@ -375,38 +369,20 @@ public:
return result; return result;
} }
void wakeUp()
{
// TODO
}
int count() const
{
Poco::FastMutex::ScopedLock lock(_mutex);
return static_cast<int>(_socketMap.size());
}
private: private:
#ifdef _WIN32 void setMode(short& target, int mode)
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)
{ {
if (mode & PollSet::POLL_READ) if (mode & PollSet::POLL_READ)
target |= POLLIN; target |= POLLIN;
@ -415,13 +391,8 @@ private:
target |= POLLOUT; target |= POLLOUT;
} }
#endif
mutable Poco::FastMutex _mutex; mutable Poco::FastMutex _mutex;
std::map<poco_socket_t, Socket> _socketMap; std::map<poco_socket_t, Socket> _socketMap;
#ifdef _WIN32
std::set<poco_socket_t> _wantPOLLOUT;
#endif
std::map<poco_socket_t, int> _addMap; std::map<poco_socket_t, int> _addMap;
std::set<poco_socket_t> _removeSet; std::set<poco_socket_t> _removeSet;
std::vector<pollfd> _pollfds; std::vector<pollfd> _pollfds;
@ -431,6 +402,300 @@ private:
#else #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() // Fallback implementation using select()
// //
@ -562,12 +827,26 @@ public:
return result; return result;
} }
void wakeUp()
{
// TODO
}
int count() const
{
Poco::FastMutex::ScopedLock lock(_mutex);
return static_cast<int>(_map.size());
}
private: private:
mutable Poco::FastMutex _mutex; mutable Poco::FastMutex _mutex;
PollSet::SocketModeMap _map; PollSet::SocketModeMap _map;
}; };
#endif // POCO_OS_FAMILY_WINDOWS
#endif #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 } } // namespace Poco::Net

View File

@ -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) RawSocket::RawSocket(SocketImpl* pImpl): Socket(pImpl)
{ {
if (!dynamic_cast<RawSocketImpl*>(impl())) 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) void RawSocket::connect(const SocketAddress& address)
{ {
impl()->connect(address); impl()->connect(address);

View File

@ -18,10 +18,12 @@
#include <algorithm> #include <algorithm>
#include <string.h> // FD_SET needs memset on some platforms, so we can't use <cstring> #include <string.h> // FD_SET needs memset on some platforms, so we can't use <cstring>
#if defined(POCO_HAVE_FD_EPOLL) #if defined(POCO_HAVE_FD_EPOLL)
#include <sys/epoll.h> #include <sys/epoll.h>
#elif defined(POCO_HAVE_FD_POLL) #elif defined(POCO_HAVE_FD_POLL)
#include "Poco/SharedPtr.h" #include "Poco/SharedPtr.h"
#include <poll.h> #ifndef _WIN32
#include <poll.h>
#endif
#endif #endif
@ -50,6 +52,30 @@ Socket::Socket(const Socket& socket):
_pImpl->duplicate(); _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) Socket& Socket::operator = (const Socket& socket)
{ {
@ -62,10 +88,9 @@ Socket& Socket::operator = (const Socket& socket)
return *this; return *this;
} }
Socket::~Socket() 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) #elif defined(POCO_HAVE_FD_POLL)
typedef Poco::SharedPtr<pollfd, Poco::ReferenceCounter, Poco::ReleaseArrayPolicy<pollfd>> SharedPollArray; 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; if (0 == nfd) return 0;
SharedPollArray pPollArr = new pollfd[nfd](); SharedPollArray pPollArr = new pollfd[nfd]();
@ -256,7 +284,11 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce
do do
{ {
Poco::Timestamp start; Poco::Timestamp start;
#ifdef _WIN32
rc = WSAPoll(pPollArr, nfd, static_cast<INT>(remainingTime.totalMilliseconds()));
#else
rc = ::poll(pPollArr, nfd, remainingTime.totalMilliseconds()); rc = ::poll(pPollArr, nfd, remainingTime.totalMilliseconds());
#endif
if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
{ {
Poco::Timestamp end; Poco::Timestamp end;
@ -276,17 +308,17 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce
SocketList::iterator endE = exceptList.end(); SocketList::iterator endE = exceptList.end();
for (int idx = 0; idx < nfd; ++idx) 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); 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); 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); if (POLLERR & pPollArr[idx].revents && slIt != endE) readyExceptList.push_back(*slIt);
} }
std::swap(readList, readyReadList); std::swap(readList, readyReadList);
std::swap(writeList, readyWriteList); std::swap(writeList, readyWriteList);
std::swap(exceptList, readyExceptList); std::swap(exceptList, readyExceptList);
return readList.size() + writeList.size() + exceptList.size(); return static_cast<int>(readList.size() + writeList.size() + exceptList.size());
#else #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 } } // namespace Poco::Net

View File

@ -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) SocketAddress::SocketAddress(const struct sockaddr* sockAddr, poco_socklen_t length)
{ {
if (length == sizeof(struct sockaddr_in) && sockAddr->sa_family == AF_INET) 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 IPAddress SocketAddress::host() const
{ {
return pImpl()->host(); return pImpl()->host();

View File

@ -20,23 +20,12 @@
#include <string.h> // FD_SET needs memset on some platforms, so we can't use <cstring> #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) #if defined(POCO_HAVE_FD_EPOLL)
#include <sys/epoll.h> #include <sys/epoll.h>
#elif defined(POCO_HAVE_FD_POLL) #elif defined(POCO_HAVE_FD_POLL)
#ifndef _WIN32 #ifndef _WIN32
#include <poll.h> #include <poll.h>
#endif #endif
#endif #endif
@ -219,10 +208,8 @@ void SocketImpl::bind(const SocketAddress& address, bool reuseAddress, bool reus
{ {
init(address.af()); init(address.af());
} }
if (reuseAddress) setReuseAddress(reuseAddress);
setReuseAddress(true); setReusePort(reusePort);
if (reusePort)
setReusePort(true);
#if defined(POCO_VXWORKS) #if defined(POCO_VXWORKS)
int rc = ::bind(_sockfd, (sockaddr*) address.addr(), address.length()); int rc = ::bind(_sockfd, (sockaddr*) address.addr(), address.length());
#else #else
@ -253,10 +240,8 @@ void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool reu
#else #else
if (ipV6Only) throw Poco::NotImplementedException("IPV6_V6ONLY not defined."); if (ipV6Only) throw Poco::NotImplementedException("IPV6_V6ONLY not defined.");
#endif #endif
if (reuseAddress) setReuseAddress(reuseAddress);
setReuseAddress(true); setReusePort(reusePort);
if (reusePort)
setReusePort(true);
int rc = ::bind(_sockfd, address.addr(), address.length()); int rc = ::bind(_sockfd, address.addr(), address.length());
if (rc != 0) error(address.toString()); if (rc != 0) error(address.toString());
#else #else
@ -614,6 +599,13 @@ int SocketImpl::available()
{ {
int result = 0; int result = 0;
ioctl(FIONREAD, result); 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; 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) void SocketImpl::setSendBufferSize(int size)
{ {
setOption(SOL_SOCKET, SO_SNDBUF, size); setOption(SOL_SOCKET, SO_SNDBUF, size);
@ -1027,14 +1027,25 @@ void SocketImpl::setReuseAddress(bool flag)
{ {
int value = flag ? 1 : 0; int value = flag ? 1 : 0;
setOption(SOL_SOCKET, SO_REUSEADDR, value); 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 SocketImpl::getReuseAddress()
{ {
bool ret = false;
int value(0); int value(0);
getOption(SOL_SOCKET, SO_REUSEADDR, value); 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;
} }

View File

@ -29,7 +29,7 @@ SocketNotification::~SocketNotification()
{ {
} }
void SocketNotification::setSocket(const Socket& socket) void SocketNotification::setSocket(const Socket& socket)
{ {
_socket = socket; _socket = socket;

808
Net/src/SocketProactor.cpp Normal file
View 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

View File

@ -179,11 +179,14 @@ bool SocketReactor::hasEventHandler(const Socket& socket, const Poco::AbstractOb
SocketReactor::NotifierPtr SocketReactor::getNotifier(const Socket& socket, bool makeNew) 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); ScopedLock lock(_mutex);
EventHandlerMap::iterator it = _handlers.find(socket); EventHandlerMap::iterator it = _handlers.find(sockfd);
if (it != _handlers.end()) return it->second; 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; return 0;
} }
@ -191,6 +194,8 @@ SocketReactor::NotifierPtr SocketReactor::getNotifier(const Socket& socket, bool
void SocketReactor::removeEventHandler(const Socket& socket, const Poco::AbstractObserver& observer) void SocketReactor::removeEventHandler(const Socket& socket, const Poco::AbstractObserver& observer)
{ {
const SocketImpl* pImpl = socket.impl();
if (pImpl == nullptr) return;
NotifierPtr pNotifier = getNotifier(socket); NotifierPtr pNotifier = getNotifier(socket);
if (pNotifier && pNotifier->hasObserver(observer)) if (pNotifier && pNotifier->hasObserver(observer))
{ {
@ -198,7 +203,7 @@ void SocketReactor::removeEventHandler(const Socket& socket, const Poco::Abstrac
{ {
{ {
ScopedLock lock(_mutex); ScopedLock lock(_mutex);
_handlers.erase(socket); _handlers.erase(pImpl->sockfd());
} }
_pollSet.remove(socket); _pollSet.remove(socket);
} }

View File

@ -51,6 +51,11 @@ StreamSocket::StreamSocket(const Socket& socket): Socket(socket)
} }
StreamSocket::StreamSocket(const StreamSocket& socket): Socket(socket)
{
}
StreamSocket::StreamSocket(SocketImpl* pImpl): Socket(pImpl) StreamSocket::StreamSocket(SocketImpl* pImpl): Socket(pImpl)
{ {
if (!dynamic_cast<StreamSocketImpl*>(impl())) 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) void StreamSocket::connect(const SocketAddress& address)
{ {
impl()->connect(address); impl()->connect(address);

View File

@ -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() 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() void WebSocket::shutdown()
{ {
shutdown(WS_NORMAL_CLOSE); shutdown(WS_NORMAL_CLOSE);

View File

@ -19,7 +19,7 @@ objects = \
MediaTypeTest QuotedPrintableTest DialogSocketTest \ MediaTypeTest QuotedPrintableTest DialogSocketTest \
HTTPClientTestSuite FTPClientTestSuite FTPClientSessionTest \ HTTPClientTestSuite FTPClientTestSuite FTPClientSessionTest \
FTPStreamFactoryTest DialogServer \ FTPStreamFactoryTest DialogServer \
SocketReactorTest ReactorTestSuite \ SocketReactorTest ReactorTestSuite SocketProactorTest \
MailTestSuite MailMessageTest MailStreamTest \ MailTestSuite MailMessageTest MailStreamTest \
SMTPClientSessionTest POP3ClientSessionTest \ SMTPClientSessionTest POP3ClientSessionTest \
RawSocketTest ICMPClientTest ICMPSocketTest ICMPClientTestSuite \ RawSocketTest ICMPClientTest ICMPSocketTest ICMPClientTestSuite \

View File

@ -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"> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="debug_shared|Win32"> <ProjectConfiguration Include="debug_shared|Win32">
@ -56,7 +56,7 @@
<RootNamespace>TestSuite</RootNamespace> <RootNamespace>TestSuite</RootNamespace>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
</PropertyGroup> </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"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
@ -117,45 +117,45 @@
<CharacterSet>MultiByte</CharacterSet> <CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v142</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"/> <ImportGroup Label="ExtensionSettings" />
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|Win32'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|Win32'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_md|x64'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='release_shared|x64'" Label="PropertySheets"> <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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'" Label="PropertySheets"> <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> </ImportGroup>
<PropertyGroup Label="UserMacros"/> <PropertyGroup Label="UserMacros" />
<PropertyGroup> <PropertyGroup>
<_ProjectFileVersion>15.0.28307.799</_ProjectFileVersion> <_ProjectFileVersion>15.0.28307.799</_ProjectFileVersion>
<TargetName Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">TestSuited</TargetName> <TargetName Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">TestSuited</TargetName>
@ -243,7 +243,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
@ -275,9 +275,9 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -304,7 +304,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
@ -336,9 +336,9 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -365,7 +365,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
@ -397,9 +397,9 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -426,7 +426,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
@ -458,9 +458,9 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -487,7 +487,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
@ -519,9 +519,9 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -548,7 +548,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
@ -580,9 +580,9 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
<PrecompiledHeader/> <PrecompiledHeader />
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat/> <DebugInformationFormat />
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -598,70 +598,71 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="src\DatagramSocketTest.h"/> <ClInclude Include="src\DatagramSocketTest.h" />
<ClInclude Include="src\DialogServer.h"/> <ClInclude Include="src\DialogServer.h" />
<ClInclude Include="src\DialogSocketTest.h"/> <ClInclude Include="src\DialogSocketTest.h" />
<ClInclude Include="src\DNSTest.h"/> <ClInclude Include="src\DNSTest.h" />
<ClInclude Include="src\EchoServer.h"/> <ClInclude Include="src\EchoServer.h" />
<ClInclude Include="src\FTPClientSessionTest.h"/> <ClInclude Include="src\FTPClientSessionTest.h" />
<ClInclude Include="src\FTPClientTestSuite.h"/> <ClInclude Include="src\FTPClientTestSuite.h" />
<ClInclude Include="src\FTPStreamFactoryTest.h"/> <ClInclude Include="src\FTPStreamFactoryTest.h" />
<ClInclude Include="src\HTMLFormTest.h"/> <ClInclude Include="src\HTMLFormTest.h" />
<ClInclude Include="src\HTMLTestSuite.h"/> <ClInclude Include="src\HTMLTestSuite.h" />
<ClInclude Include="src\HTTPClientSessionTest.h"/> <ClInclude Include="src\HTTPClientSessionTest.h" />
<ClInclude Include="src\HTTPClientTestSuite.h"/> <ClInclude Include="src\HTTPClientTestSuite.h" />
<ClInclude Include="src\HTTPCookieTest.h"/> <ClInclude Include="src\HTTPCookieTest.h" />
<ClInclude Include="src\HTTPCredentialsTest.h"/> <ClInclude Include="src\HTTPCredentialsTest.h" />
<ClInclude Include="src\HTTPRequestTest.h"/> <ClInclude Include="src\HTTPRequestTest.h" />
<ClInclude Include="src\HTTPResponseTest.h"/> <ClInclude Include="src\HTTPResponseTest.h" />
<ClInclude Include="src\HTTPServerTest.h"/> <ClInclude Include="src\HTTPServerTest.h" />
<ClInclude Include="src\HTTPServerTestSuite.h"/> <ClInclude Include="src\HTTPServerTestSuite.h" />
<ClInclude Include="src\HTTPStreamFactoryTest.h"/> <ClInclude Include="src\HTTPStreamFactoryTest.h" />
<ClInclude Include="src\HTTPTestServer.h"/> <ClInclude Include="src\HTTPTestServer.h" />
<ClInclude Include="src\HTTPTestSuite.h"/> <ClInclude Include="src\HTTPTestSuite.h" />
<ClInclude Include="src\ICMPClientTest.h"/> <ClInclude Include="src\ICMPClientTest.h" />
<ClInclude Include="src\ICMPClientTestSuite.h"/> <ClInclude Include="src\ICMPClientTestSuite.h" />
<ClInclude Include="src\ICMPSocketTest.h"/> <ClInclude Include="src\ICMPSocketTest.h" />
<ClInclude Include="src\IPAddressTest.h"/> <ClInclude Include="src\IPAddressTest.h" />
<ClInclude Include="src\MailMessageTest.h"/> <ClInclude Include="src\MailMessageTest.h" />
<ClInclude Include="src\MailStreamTest.h"/> <ClInclude Include="src\MailStreamTest.h" />
<ClInclude Include="src\MailTestSuite.h"/> <ClInclude Include="src\MailTestSuite.h" />
<ClInclude Include="src\MediaTypeTest.h"/> <ClInclude Include="src\MediaTypeTest.h" />
<ClInclude Include="src\MessageHeaderTest.h"/> <ClInclude Include="src\MessageHeaderTest.h" />
<ClInclude Include="src\MessagesTestSuite.h"/> <ClInclude Include="src\MessagesTestSuite.h" />
<ClInclude Include="src\MulticastEchoServer.h"/> <ClInclude Include="src\MulticastEchoServer.h" />
<ClInclude Include="src\MulticastSocketTest.h"/> <ClInclude Include="src\MulticastSocketTest.h" />
<ClInclude Include="src\MultipartReaderTest.h"/> <ClInclude Include="src\MultipartReaderTest.h" />
<ClInclude Include="src\MultipartWriterTest.h"/> <ClInclude Include="src\MultipartWriterTest.h" />
<ClInclude Include="src\NameValueCollectionTest.h"/> <ClInclude Include="src\NameValueCollectionTest.h" />
<ClInclude Include="src\NetCoreTestSuite.h"/> <ClInclude Include="src\NetCoreTestSuite.h" />
<ClInclude Include="src\NetTestSuite.h"/> <ClInclude Include="src\NetTestSuite.h" />
<ClInclude Include="src\NetworkInterfaceTest.h"/> <ClInclude Include="src\NetworkInterfaceTest.h" />
<ClInclude Include="src\NTLMCredentialsTest.h"/> <ClInclude Include="src\NTLMCredentialsTest.h" />
<ClInclude Include="src\NTPClientTest.h"/> <ClInclude Include="src\NTPClientTest.h" />
<ClInclude Include="src\NTPClientTestSuite.h"/> <ClInclude Include="src\NTPClientTestSuite.h" />
<ClInclude Include="src\OAuth10CredentialsTest.h"/> <ClInclude Include="src\OAuth10CredentialsTest.h" />
<ClInclude Include="src\OAuth20CredentialsTest.h"/> <ClInclude Include="src\OAuth20CredentialsTest.h" />
<ClInclude Include="src\OAuthTestSuite.h"/> <ClInclude Include="src\OAuthTestSuite.h" />
<ClInclude Include="src\PollSetTest.h"/> <ClInclude Include="src\PollSetTest.h" />
<ClInclude Include="src\POP3ClientSessionTest.h"/> <ClInclude Include="src\POP3ClientSessionTest.h" />
<ClInclude Include="src\QuotedPrintableTest.h"/> <ClInclude Include="src\QuotedPrintableTest.h" />
<ClInclude Include="src\RawSocketTest.h"/> <ClInclude Include="src\RawSocketTest.h" />
<ClInclude Include="src\ReactorTestSuite.h"/> <ClInclude Include="src\ReactorTestSuite.h" />
<ClInclude Include="src\SMTPClientSessionTest.h"/> <ClInclude Include="src\SMTPClientSessionTest.h" />
<ClInclude Include="src\SocketAddressTest.h"/> <ClInclude Include="src\SocketAddressTest.h" />
<ClInclude Include="src\SocketReactorTest.h"/> <ClInclude Include="src\SocketProactorTest.h" />
<ClInclude Include="src\SocketsTestSuite.h"/> <ClInclude Include="src\SocketReactorTest.h" />
<ClInclude Include="src\SocketStreamTest.h"/> <ClInclude Include="src\SocketsTestSuite.h" />
<ClInclude Include="src\SocketTest.h"/> <ClInclude Include="src\SocketStreamTest.h" />
<ClInclude Include="src\SyslogTest.h"/> <ClInclude Include="src\SocketTest.h" />
<ClInclude Include="src\TCPServerTest.h"/> <ClInclude Include="src\SyslogTest.h" />
<ClInclude Include="src\TCPServerTestSuite.h"/> <ClInclude Include="src\TCPServerTest.h" />
<ClInclude Include="src\UDPEchoServer.h"/> <ClInclude Include="src\TCPServerTestSuite.h" />
<ClInclude Include="src\UDPServerTest.h"/> <ClInclude Include="src\UDPEchoServer.h" />
<ClInclude Include="src\UDPServerTestSuite.h"/> <ClInclude Include="src\UDPServerTest.h" />
<ClInclude Include="src\WebSocketTest.h"/> <ClInclude Include="src\UDPServerTestSuite.h" />
<ClInclude Include="src\WebSocketTestSuite.h"/> <ClInclude Include="src\WebSocketTest.h" />
<ClInclude Include="src\WebSocketTestSuite.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\DatagramSocketTest.cpp"> <ClCompile Include="src\DatagramSocketTest.cpp">
@ -823,6 +824,7 @@
<ClCompile Include="src\SocketAddressTest.cpp"> <ClCompile Include="src\SocketAddressTest.cpp">
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
<ClCompile Include="src\SocketProactorTest.cpp" />
<ClCompile Include="src\SocketReactorTest.cpp"> <ClCompile Include="src\SocketReactorTest.cpp">
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
@ -860,6 +862,6 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"/> <ImportGroup Label="ExtensionTargets" />
</Project> </Project>

View File

@ -363,6 +363,9 @@
<ClInclude Include="src\UDPServerTestSuite.h"> <ClInclude Include="src\UDPServerTestSuite.h">
<Filter>UDP\Header Files</Filter> <Filter>UDP\Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\SocketProactorTest.h">
<Filter>Sockets\Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\DNSTest.cpp"> <ClCompile Include="src\DNSTest.cpp">
@ -560,5 +563,8 @@
<ClCompile Include="src\UDPServerTestSuite.cpp"> <ClCompile Include="src\UDPServerTestSuite.cpp">
<Filter>UDP\Source Files</Filter> <Filter>UDP\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\SocketProactorTest.cpp">
<Filter>Sockets\Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -13,12 +13,12 @@
#include "CppUnit/TestSuite.h" #include "CppUnit/TestSuite.h"
#include "UDPEchoServer.h" #include "UDPEchoServer.h"
#include "Poco/Net/DatagramSocket.h" #include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/NetworkInterface.h" #include "Poco/Net/NetworkInterface.h"
#include "Poco/Net/NetException.h" #include "Poco/Net/NetException.h"
#include "Poco/Timespan.h" #include "Poco/Timespan.h"
#include "Poco/Buffer.h" #include "Poco/Buffer.h"
#include "Poco/Stopwatch.h" #include "Poco/Stopwatch.h"
#include "Poco/Thread.h"
#include <cstring> #include <cstring>
@ -35,6 +35,7 @@ using Poco::Stopwatch;
using Poco::TimeoutException; using Poco::TimeoutException;
using Poco::InvalidArgumentException; using Poco::InvalidArgumentException;
using Poco::IOException; using Poco::IOException;
using Poco::Thread;
DatagramSocketTest::DatagramSocketTest(const std::string& name): CppUnit::TestCase(name) 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() void DatagramSocketTest::testEchoBuffer()
{ {
UDPEchoServer echoServer; 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() void DatagramSocketTest::testSendToReceiveFrom()
{ {
UDPEchoServer echoServer(SocketAddress("127.0.0.1", 0)); 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() void DatagramSocketTest::testBroadcast()
{ {
UDPEchoServer echoServer; UDPEchoServer echoServer;
@ -607,9 +819,13 @@ CppUnit::Test* DatagramSocketTest::suite()
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DatagramSocketTest"); CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("DatagramSocketTest");
CppUnit_addTest(pSuite, DatagramSocketTest, testEcho); CppUnit_addTest(pSuite, DatagramSocketTest, testEcho);
CppUnit_addTest(pSuite, DatagramSocketTest, testMoveDatagramSocket);
CppUnit_addTest(pSuite, DatagramSocketTest, testEchoBuffer); CppUnit_addTest(pSuite, DatagramSocketTest, testEchoBuffer);
CppUnit_addTest(pSuite, DatagramSocketTest, testReceiveFromAvailable);
CppUnit_addTest(pSuite, DatagramSocketTest, testSendToReceiveFrom); CppUnit_addTest(pSuite, DatagramSocketTest, testSendToReceiveFrom);
CppUnit_addTest(pSuite, DatagramSocketTest, testUnbound); 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 #if (POCO_OS != POCO_OS_FREE_BSD) // works only with local net bcast and very randomly
CppUnit_addTest(pSuite, DatagramSocketTest, testBroadcast); CppUnit_addTest(pSuite, DatagramSocketTest, testBroadcast);
#endif #endif

View File

@ -15,6 +15,7 @@
#include "Poco/Net/Net.h" #include "Poco/Net/Net.h"
#include "Poco/Net/SocketAddress.h"
#include "CppUnit/TestCase.h" #include "CppUnit/TestCase.h"
@ -25,9 +26,13 @@ public:
~DatagramSocketTest(); ~DatagramSocketTest();
void testEcho(); void testEcho();
void testMoveDatagramSocket();
void testEchoBuffer(); void testEchoBuffer();
void testReceiveFromAvailable();
void testSendToReceiveFrom(); void testSendToReceiveFrom();
void testUnbound(); void testUnbound();
void testReuseAddressPortWildcard();
void testReuseAddressPortSpecific();
void testBroadcast(); void testBroadcast();
void testGatherScatterFixed(); void testGatherScatterFixed();
void testGatherScatterVariable(); void testGatherScatterVariable();
@ -38,6 +43,8 @@ public:
static CppUnit::Test* suite(); static CppUnit::Test* suite();
private: private:
static Poco::UInt16 getFreePort(Poco::Net::SocketAddress::Family family, std::uint16_t port);
// "STRF" are sendto/recvfrom versions of the same functionality // "STRF" are sendto/recvfrom versions of the same functionality
void testGatherScatterFixedWin(); void testGatherScatterFixedWin();
void testGatherScatterSTRFFixedWin(); void testGatherScatterSTRFFixedWin();

View File

@ -59,7 +59,7 @@ void ICMPClientTest::testPing()
assertTrue (icmpClient.ping("10.0.2.15", 4) > 0); assertTrue (icmpClient.ping("10.0.2.15", 4) > 0);
assertTrue (icmpClient.ping("10.0.2.2", 4) > 0); assertTrue (icmpClient.ping("10.0.2.2", 4) > 0);
#else #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 // 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) // 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.15", 4) > 0);
assertTrue (icmpClient.ping("10.0.2.2", 4) > 0); assertTrue (icmpClient.ping("10.0.2.2", 4) > 0);
#else #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 // 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) // if so, adjust accordingly (i.e. specify non-existent or unreachable IP addresses)

View File

@ -56,7 +56,7 @@ void ICMPSocketTest::testSendToReceiveFrom()
{ {
ICMPSocket ss(IPAddress::IPv4); ICMPSocket ss(IPAddress::IPv4);
SocketAddress sa("www.appinf.com", 0); SocketAddress sa("github.com", 0);
SocketAddress sr(sa); SocketAddress sr(sa);
try try
@ -90,7 +90,7 @@ void ICMPSocketTest::testMTU()
std::cout << addr.toString() << " : MTU=" << mtu << std::endl; std::cout << addr.toString() << " : MTU=" << mtu << std::endl;
assertTrue (mtu != 0); assertTrue (mtu != 0);
sz = 1500; sz = 1500;
addr = SocketAddress("www.appinf.com:0"); addr = SocketAddress("github.com:0");
mtu = ICMPSocket::mtu(addr, sz); mtu = ICMPSocket::mtu(addr, sz);
std::cout << addr.toString() << " : MTU=" << mtu << std::endl; std::cout << addr.toString() << " : MTU=" << mtu << std::endl;
assertTrue (mtu != 0 && mtu <= sz); assertTrue (mtu != 0 && mtu <= sz);

View File

@ -31,11 +31,13 @@ IPAddressTest::~IPAddressTest()
void IPAddressTest::testStringConv() 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.family() == IPAddress::IPv4);
assertTrue (ia1.toString() == "127.0.0.1"); 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.family() == IPAddress::IPv4);
assertTrue (ia2.toString() == "192.168.1.120"); assertTrue (ia2.toString() == "192.168.1.120");
@ -56,15 +58,18 @@ void IPAddressTest::testStringConv()
void IPAddressTest::testStringConv6() void IPAddressTest::testStringConv6()
{ {
#ifdef POCO_HAVE_IPv6 #ifdef POCO_HAVE_IPv6
IPAddress ia0("::1"); IPAddress ia00 = IPAddress("::1");
IPAddress ia0(std::move(ia00));
assertTrue (ia0.family() == IPAddress::IPv6); assertTrue (ia0.family() == IPAddress::IPv6);
assertTrue (ia0.toString() == "::1"); 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.family() == IPAddress::IPv6);
assertTrue (ia1.toString() == "1080::8:600:200a:425c"); 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.family() == IPAddress::IPv6);
assertTrue (ia2.toString() == "1080::8:600:200a:425c"); assertTrue (ia2.toString() == "1080::8:600:200a:425c");
@ -94,8 +99,9 @@ void IPAddressTest::testStringConv6()
void IPAddressTest::testParse() void IPAddressTest::testParse()
{ {
IPAddress ip; 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.120", ip));
assertTrue (!IPAddress::tryParse("192.168.1.280", ip)); assertTrue (!IPAddress::tryParse("192.168.1.280", ip));
ip = IPAddress::parse("192.168.1.120"); ip = IPAddress::parse("192.168.1.120");
@ -103,10 +109,37 @@ void IPAddressTest::testParse()
{ {
ip = IPAddress::parse("192.168.1.280"); ip = IPAddress::parse("192.168.1.280");
fail("bad address - must throw"); fail("bad address - must throw");
} }
catch (InvalidAddressException&) 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
} }

View File

@ -18,6 +18,7 @@
#include "Poco/Net/NetException.h" #include "Poco/Net/NetException.h"
#include "Poco/Net/PollSet.h" #include "Poco/Net/PollSet.h"
#include "Poco/Stopwatch.h" #include "Poco/Stopwatch.h"
#include <iostream>
using Poco::Net::Socket; using Poco::Net::Socket;
@ -31,6 +32,38 @@ using Poco::Stopwatch;
using Poco::Thread; 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) 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() void PollSetTest::testPoll()
{ {
EchoServer echoServer1; EchoServer echoServer1;
@ -76,31 +172,32 @@ void PollSetTest::testPoll()
PollSet::SocketModeMap sm = ps.poll(timeout); PollSet::SocketModeMap sm = ps.poll(timeout);
assertTrue (sm.find(ss1) != sm.end()); assertTrue (sm.find(ss1) != sm.end());
assertTrue (sm.find(ss2) == 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); assertTrue (sw.elapsed() < 1100000);
ps.update(ss1, PollSet::POLL_READ); ps.update(ss1, PollSet::POLL_READ);
ss1.setBlocking(true);
ss1.sendBytes("hello", 5); ss1.sendBytes("hello", 5);
char buffer[256]; char buffer[256];
sw.restart(); sw.restart();
sm = ps.poll(timeout); sm = ps.poll(timeout);
assertTrue (sm.find(ss1) != sm.end()); assertTrue (sm.find(ss1) != sm.end());
assertTrue (sm.find(ss2) == 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); assertTrue (sw.elapsed() < 1100000);
int n = ss1.receiveBytes(buffer, sizeof(buffer)); int n = ss1.receiveBytes(buffer, sizeof(buffer));
assertTrue (n == 5); assertTrue (n == 5);
assertTrue (std::string(buffer, n) == "hello"); assertTrue (std::string(buffer, n) == "hello");
ss2.setBlocking(true);
ss2.sendBytes("HELLO", 5); ss2.sendBytes("HELLO", 5);
sw.restart(); sw.restart();
sm = ps.poll(timeout); sm = ps.poll(timeout);
assertTrue (sm.find(ss1) == sm.end()); assertTrue (sm.find(ss1) == sm.end());
assertTrue (sm.find(ss2) != 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); assertTrue (sw.elapsed() < 1100000);
n = ss2.receiveBytes(buffer, sizeof(buffer)); n = ss2.receiveBytes(buffer, sizeof(buffer));
@ -128,16 +225,14 @@ void PollSetTest::testPoll()
void PollSetTest::testPollNoServer() void PollSetTest::testPollNoServer()
{ {
#ifndef POCO_OS_FAMILY_WINDOWS
StreamSocket ss1; StreamSocket ss1;
StreamSocket ss2; StreamSocket ss2;
ss1.connectNB(SocketAddress("127.0.0.1", 0xFEFE)); ss1.connectNB(SocketAddress("127.0.0.1", 0xFEFE));
ss2.connectNB(SocketAddress("127.0.0.1", 0xFEFF)); ss2.connectNB(SocketAddress("127.0.0.1", 0xFEFF));
PollSet ps; PollSet ps;
assertTrue(ps.empty()); assertTrue(ps.empty());
ps.add(ss1, PollSet::POLL_READ); ps.add(ss1, PollSet::POLL_READ | PollSet::POLL_WRITE | PollSet::POLL_ERROR);
ps.add(ss2, PollSet::POLL_READ); ps.add(ss2, PollSet::POLL_READ | PollSet::POLL_WRITE | PollSet::POLL_ERROR);
assertTrue(!ps.empty()); assertTrue(!ps.empty());
assertTrue(ps.has(ss1)); assertTrue(ps.has(ss1));
assertTrue(ps.has(ss2)); assertTrue(ps.has(ss2));
@ -151,13 +246,11 @@ void PollSetTest::testPollNoServer()
assertTrue(sm.size() == 2); assertTrue(sm.size() == 2);
for (auto s : sm) for (auto s : sm)
assertTrue(0 != (s.second | PollSet::POLL_ERROR)); assertTrue(0 != (s.second | PollSet::POLL_ERROR));
#endif // POCO_OS_FAMILY_WINDOWS
} }
void PollSetTest::testPollClosedServer() void PollSetTest::testPollClosedServer()
{ {
#ifndef POCO_OS_FAMILY_WINDOWS
EchoServer echoServer1; EchoServer echoServer1;
EchoServer echoServer2; EchoServer echoServer2;
StreamSocket ss1; StreamSocket ss1;
@ -165,7 +258,6 @@ void PollSetTest::testPollClosedServer()
ss1.connect(SocketAddress("127.0.0.1", echoServer1.port())); ss1.connect(SocketAddress("127.0.0.1", echoServer1.port()));
ss2.connect(SocketAddress("127.0.0.1", echoServer2.port())); ss2.connect(SocketAddress("127.0.0.1", echoServer2.port()));
PollSet ps; PollSet ps;
assertTrue(ps.empty()); assertTrue(ps.empty());
ps.add(ss1, PollSet::POLL_READ); ps.add(ss1, PollSet::POLL_READ);
@ -190,7 +282,28 @@ void PollSetTest::testPollClosedServer()
assertTrue(sm.size() == 2); assertTrue(sm.size() == 2);
assertTrue(0 == ss1.receiveBytes(0, 0)); assertTrue(0 == ss1.receiveBytes(0, 0));
assertTrue(0 == ss2.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::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, testPoll);
CppUnit_addTest(pSuite, PollSetTest, testPollNoServer); CppUnit_addTest(pSuite, PollSetTest, testPollNoServer);
CppUnit_addTest(pSuite, PollSetTest, testPollClosedServer); CppUnit_addTest(pSuite, PollSetTest, testPollClosedServer);
CppUnit_addTest(pSuite, PollSetTest, testPollSetWakeUp);
return pSuite; return pSuite;
} }

View File

@ -24,9 +24,12 @@ public:
PollSetTest(const std::string& name); PollSetTest(const std::string& name);
~PollSetTest(); ~PollSetTest();
void testTimeout();
void testPollNB();
void testPoll(); void testPoll();
void testPollNoServer(); void testPollNoServer();
void testPollClosedServer(); void testPollClosedServer();
void testPollSetWakeUp();
void setUp(); void setUp();
void tearDown(); void tearDown();

View File

@ -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() void RawSocketTest::setUp()
{ {
} }
@ -100,6 +125,7 @@ CppUnit::Test* RawSocketTest::suite()
CppUnit_addTest(pSuite, RawSocketTest, testEchoIPv4); CppUnit_addTest(pSuite, RawSocketTest, testEchoIPv4);
CppUnit_addTest(pSuite, RawSocketTest, testSendToReceiveFromIPv4); CppUnit_addTest(pSuite, RawSocketTest, testSendToReceiveFromIPv4);
CppUnit_addTest(pSuite, RawSocketTest, testEchoIPv4Move);
return pSuite; return pSuite;
} }

View File

@ -26,6 +26,7 @@ public:
void testEchoIPv4(); void testEchoIPv4();
void testSendToReceiveFromIPv4(); void testSendToReceiveFromIPv4();
void testEchoIPv4Move();
void setUp(); void setUp();
void tearDown(); void tearDown();

View File

@ -13,6 +13,7 @@
#include "CppUnit/TestSuite.h" #include "CppUnit/TestSuite.h"
#include "Poco/Net/SocketAddress.h" #include "Poco/Net/SocketAddress.h"
#include "Poco/Net/NetException.h" #include "Poco/Net/NetException.h"
#include <iostream>
using Poco::Net::SocketAddress; using Poco::Net::SocketAddress;
@ -41,19 +42,22 @@ void SocketAddressTest::testSocketAddress()
assertTrue (wild.host().isWildcard()); assertTrue (wild.host().isWildcard());
assertTrue (wild.port() == 0); 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.af() == AF_INET);
assertTrue (sa1.family() == SocketAddress::IPv4); assertTrue (sa1.family() == SocketAddress::IPv4);
assertTrue (sa1.host().toString() == "192.168.1.100"); assertTrue (sa1.host().toString() == "192.168.1.100");
assertTrue (sa1.port() == 100); assertTrue (sa1.port() == 100);
assertTrue (sa1.toString() == "192.168.1.100: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.host().toString() == "192.168.1.100");
assertTrue (sa2.port() == 100); assertTrue (sa2.port() == 100);
#if !defined(_WIN32_WCE) #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.host().toString() == "192.168.1.100");
assertTrue (sa3.port() == 21); assertTrue (sa3.port() == 21);
#endif #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.host().toString() == "54.93.62.90");
assertTrue (sa4.port() == 80); 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.host().toString() == "192.168.2.120");
assertTrue (sa7.port() == 88); 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.host().toString() == "192.168.2.120");
assertTrue (sa8.port() == 88); assertTrue (sa8.port() == 88);
@ -121,7 +128,8 @@ void SocketAddressTest::testSocketAddress()
SocketAddress sa10("www6.pocoproject.org", 80); 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"); 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"); assertTrue (sa11.host().toString() == "54.93.62.90");
#ifdef POCO_HAVE_IPv6 #ifdef POCO_HAVE_IPv6
@ -168,6 +176,8 @@ void SocketAddressTest::testSocketAddress6()
assertTrue (sa2.host().toString() == "fe80::e6ce:8fff:fe4a:edd0"); assertTrue (sa2.host().toString() == "fe80::e6ce:8fff:fe4a:edd0");
assertTrue (sa2.port() == 100); assertTrue (sa2.port() == 100);
assertTrue (sa2.toString() == "[fe80::e6ce:8fff:fe4a:edd0]:100"); assertTrue (sa2.toString() == "[fe80::e6ce:8fff:fe4a:edd0]:100");
#else
std::cout << "[IPv6 DISABLED]" << std::endl;
#endif #endif
} }
@ -191,6 +201,8 @@ void SocketAddressTest::testSocketAddressUnixLocal()
SocketAddress sa4("/tmp/sock1"); SocketAddress sa4("/tmp/sock1");
assertTrue (sa1 == sa4); assertTrue (sa1 == sa4);
assertTrue (sa4.toString() == "/tmp/sock1"); assertTrue (sa4.toString() == "/tmp/sock1");
#else
std::cout << "[UNIX LOCAL DISABLED]" << std::endl;
#endif #endif
} }

View 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;
}

Some files were not shown because too many files have changed in this diff Show More