diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/poco/Net/src | |
parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
download | ydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/poco/Net/src')
100 files changed, 23268 insertions, 23268 deletions
diff --git a/contrib/libs/poco/Net/src/AbstractHTTPRequestHandler.cpp b/contrib/libs/poco/Net/src/AbstractHTTPRequestHandler.cpp index ed39617e2b..33ebf8f9c9 100644 --- a/contrib/libs/poco/Net/src/AbstractHTTPRequestHandler.cpp +++ b/contrib/libs/poco/Net/src/AbstractHTTPRequestHandler.cpp @@ -1,109 +1,109 @@ -// -// AbstractHTTPRequestHandler.cpp -// -// Library: Net -// Package: HTTPServer -// Module: AbstractHTTPRequestHandler -// -// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/AbstractHTTPRequestHandler.h" -#include "Poco/Net/HTTPServerRequest.h" -#include "Poco/Net/HTTPServerResponse.h" -#include "Poco/Net/HTMLForm.h" -#include "Poco/NumberFormatter.h" -#include "Poco/Exception.h" - - -using Poco::NumberFormatter; - - -namespace Poco { -namespace Net { - - -AbstractHTTPRequestHandler::AbstractHTTPRequestHandler(): - _pRequest(0), - _pResponse(0), - _pForm(0) -{ -} - - -AbstractHTTPRequestHandler::~AbstractHTTPRequestHandler() -{ - delete _pForm; -} - - -void AbstractHTTPRequestHandler::handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) -{ - _pRequest = &request; - _pResponse = &response; - if (authenticate()) - { - try - { - run(); - } - catch (Poco::Exception& exc) - { - if (!response.sent()) - { - sendErrorResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, exc.displayText()); - } - } - catch (std::exception& exc) - { - if (!response.sent()) - { - sendErrorResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, exc.what()); - } - } - } - else - { - sendErrorResponse(HTTPResponse::HTTP_UNAUTHORIZED, ""); - } -} - - -bool AbstractHTTPRequestHandler::authenticate() -{ - return true; -} - - -HTMLForm& AbstractHTTPRequestHandler::form() -{ - if (!_pForm) - _pForm = new HTMLForm(request(), request().stream()); - - return *_pForm; -} - - -void AbstractHTTPRequestHandler::sendErrorResponse(HTTPResponse::HTTPStatus status, const std::string& message) -{ - response().setStatusAndReason(status); - std::string statusAndReason(NumberFormatter::format(static_cast<int>(response().getStatus()))); - statusAndReason += " - "; - statusAndReason += response().getReason(); - std::string page("<HTML><HEAD><TITLE>"); - page += statusAndReason; - page += "</TITLE></HEAD><BODY><H1>"; - page += statusAndReason; - page += "</H1>"; - page += "<P>"; - page += message; - page += "</P></BODY></HTML>"; - response().sendBuffer(page.data(), page.size()); -} - - -} } // namespace Poco::Net +// +// AbstractHTTPRequestHandler.cpp +// +// Library: Net +// Package: HTTPServer +// Module: AbstractHTTPRequestHandler +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/AbstractHTTPRequestHandler.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/HTMLForm.h" +#include "Poco/NumberFormatter.h" +#include "Poco/Exception.h" + + +using Poco::NumberFormatter; + + +namespace Poco { +namespace Net { + + +AbstractHTTPRequestHandler::AbstractHTTPRequestHandler(): + _pRequest(0), + _pResponse(0), + _pForm(0) +{ +} + + +AbstractHTTPRequestHandler::~AbstractHTTPRequestHandler() +{ + delete _pForm; +} + + +void AbstractHTTPRequestHandler::handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) +{ + _pRequest = &request; + _pResponse = &response; + if (authenticate()) + { + try + { + run(); + } + catch (Poco::Exception& exc) + { + if (!response.sent()) + { + sendErrorResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, exc.displayText()); + } + } + catch (std::exception& exc) + { + if (!response.sent()) + { + sendErrorResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, exc.what()); + } + } + } + else + { + sendErrorResponse(HTTPResponse::HTTP_UNAUTHORIZED, ""); + } +} + + +bool AbstractHTTPRequestHandler::authenticate() +{ + return true; +} + + +HTMLForm& AbstractHTTPRequestHandler::form() +{ + if (!_pForm) + _pForm = new HTMLForm(request(), request().stream()); + + return *_pForm; +} + + +void AbstractHTTPRequestHandler::sendErrorResponse(HTTPResponse::HTTPStatus status, const std::string& message) +{ + response().setStatusAndReason(status); + std::string statusAndReason(NumberFormatter::format(static_cast<int>(response().getStatus()))); + statusAndReason += " - "; + statusAndReason += response().getReason(); + std::string page("<HTML><HEAD><TITLE>"); + page += statusAndReason; + page += "</TITLE></HEAD><BODY><H1>"; + page += statusAndReason; + page += "</H1>"; + page += "<P>"; + page += message; + page += "</P></BODY></HTML>"; + response().sendBuffer(page.data(), page.size()); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/DNS.cpp b/contrib/libs/poco/Net/src/DNS.cpp index 6ef8810aa1..58e6225584 100644 --- a/contrib/libs/poco/Net/src/DNS.cpp +++ b/contrib/libs/poco/Net/src/DNS.cpp @@ -1,867 +1,867 @@ -// -// DNS.cpp -// -// Library: Net -// Package: NetCore -// Module: DNS -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/DNS.h" -#include "Poco/Net/NetException.h" -#include "Poco/Net/SocketAddress.h" -#include "Poco/Environment.h" -#include "Poco/NumberFormatter.h" -#include "Poco/RWLock.h" -#include "Poco/TextIterator.h" -#include "Poco/TextConverter.h" -#include "Poco/UTF8Encoding.h" -#include "Poco/UTF32Encoding.h" -#include "Poco/Unicode.h" -#include "Poco/Timespan.h" -#include "Poco/Mutex.h" -#include <cstring> -#include <list> -#include <atomic> - - -#if defined(POCO_HAVE_LIBRESOLV) -#include <resolv.h> -#endif - - -/// set default DNS timeout to 60 seconds -const Poco::Timespan Poco::Net::DNS::DEFAULT_DNS_TIMEOUT = Poco::Timespan(60, 0); - -#if defined(POCO_HAVE_GETADDRINFO_A) -/** getaddrinfo иногда работает бесконечно долго. - * Этот код использует getaddrinfo_a c некоторым таймаутом. - * - * При выполнении в один поток производительность ниже на 30% - * При выполнении запросов в 4 потока производительность отличается - * иногда в лучшую иногда в худшую сторону на ~10-20% - */ -class GetAddrinfo -{ -public: - static GetAddrinfo & instance() - { - static GetAddrinfo impl; - return impl; - } - - int getaddrinfo(const char * name, - const char * service, - const struct addrinfo * hints, - struct addrinfo ** pai, - const Poco::Timespan * timeout_); - - size_t requestsNum() - { - Poco::ScopedLock<Poco::FastMutex> lock(mutex); - return requests.size(); - } - -private: - GetAddrinfo() {} - - GetAddrinfo(const GetAddrinfo &) = delete; - const GetAddrinfo & operator=(const GetAddrinfo &) = delete; - - void releaseUnused() - { - for (auto it = requests.rbegin(); it != requests.rend();) - { - /// don't delete if structure is used by other thread or by internal cycle of getaddrinfo - if (it->unused && gai_error(&(*it)) != EAI_INPROGRESS) - { - free(const_cast<char *>(it->ar_name)); - it->ar_name = nullptr; - free(const_cast<char *>(it->ar_service)); - it->ar_service = nullptr; - free(const_cast<addrinfo *>(it->ar_request)); - it->ar_request = nullptr; - freeaddrinfo(it->ar_result); - it->ar_result = nullptr; - - auto it_to_delete = --(it.base()); - - it = decltype(it)(requests.erase(it_to_delete)); - } - else - break; - } - } - - void addOne(const char * name, - const char * service, - const struct addrinfo * hints) - { - requests.emplace_back(); - - auto & request = requests.back(); - - request.ar_name = name ? strdup(name) : nullptr; - request.ar_service = service ? strdup(service) : nullptr; - - addrinfo * my_hints = nullptr; - if (hints) - { - /// only ai_flags are used in Poco - my_hints = (addrinfo *)calloc(1, sizeof(addrinfo)); - my_hints->ai_flags = hints->ai_flags; - } - request.ar_request = my_hints; - - request.ar_result = nullptr; - } - -private: - struct gaicb_ext : public gaicb - { - gaicb_ext() - { - memset(this, 0, sizeof(gaicb_ext)); - } - - ~gaicb_ext() - { - if (gai_error(this) != EAI_INPROGRESS) - { - free(const_cast<char *>(ar_name)); - free(const_cast<char *>(ar_service)); - free(const_cast<addrinfo *>(ar_request)); - - freeaddrinfo(ar_result); - } - } - - std::atomic<bool> unused {false}; - }; - - std::list<gaicb_ext> requests; - - Poco::FastMutex mutex; -}; - -int GetAddrinfo::getaddrinfo(const char * name, - const char * service, - const struct addrinfo * hints, - struct addrinfo ** pai, - const Poco::Timespan * timeout_) -{ - if (timeout_) - { - timespec timeout; - timeout.tv_sec = timeout_->totalSeconds(); - timeout.tv_nsec = timeout_->microseconds() * 1000; - - gaicb_ext * request_ext_ptr = nullptr; - { - Poco::ScopedLock<Poco::FastMutex> lock(mutex); - addOne(name, service, hints); - request_ext_ptr = &requests.back(); - } - gaicb * request_ptr = request_ext_ptr; - - int code = getaddrinfo_a(GAI_NOWAIT, &request_ptr, 1, nullptr); - - if (!code) - { - gai_suspend(&request_ptr, 1, &timeout); - - *pai = request_ext_ptr->ar_result; - /// prevent deleting result in dctor - request_ext_ptr->ar_result = nullptr; - - code = gai_error(request_ext_ptr); - } - - request_ext_ptr->unused = true; - - { - Poco::ScopedLock<Poco::FastMutex> lock(mutex); - releaseUnused(); - } - - return code; - } - else - { - return ::getaddrinfo(name, service, hints, pai); - } -} -#endif - - -using Poco::Environment; -using Poco::NumberFormatter; -using Poco::IOException; - - -namespace Poco { -namespace Net { - - -typedef Poco::UInt32 punycode_uint; - - -enum -{ - punycode_success = 0, - punycode_overflow = -1, - punycode_big_output = -2, - punycode_bad_input = -3 -}; - - -static int punycode_encode(size_t input_length, const punycode_uint input[], size_t* output_length, char output[]); -static int punycode_decode(size_t input_length, const char input[], size_t* output_length, punycode_uint output[]); - - -#if defined(POCO_HAVE_LIBRESOLV) -static Poco::RWLock resolverLock; -#endif - - -HostEntry DNS::hostByName(const std::string& hostname, const Poco::Timespan * timeout_, unsigned -#ifdef POCO_HAVE_ADDRINFO - hintFlags -#endif - ) -{ -#if defined(POCO_HAVE_LIBRESOLV) - Poco::ScopedReadRWLock readLock(resolverLock); -#endif - -#if defined(POCO_HAVE_ADDRINFO) - struct addrinfo* pAI; - struct addrinfo hints; - std::memset(&hints, 0, sizeof(hints)); - hints.ai_flags = hintFlags; -#if defined(POCO_HAVE_GETADDRINFO_A) - int rc = GetAddrinfo::instance().getaddrinfo(hostname.c_str(), NULL, &hints, &pAI, timeout_); -#else - int rc = getaddrinfo(hostname.c_str(), NULL, &hints, &pAI); -#endif - if (rc == 0) - { - HostEntry result(pAI); - freeaddrinfo(pAI); - return result; - } - else - { - aierror(rc, hostname); - } -#elif defined(POCO_VXWORKS) - int addr = hostGetByName(const_cast<char*>(hostname.c_str())); - if (addr != ERROR) - { - return HostEntry(hostname, IPAddress(&addr, sizeof(addr))); - } -#else - struct hostent* he = gethostbyname(hostname.c_str()); - if (he) - { - return HostEntry(he); - } -#endif - error(lastError(), hostname); // will throw an appropriate exception - throw NetException(); // to silence compiler -} - - -HostEntry DNS::hostByAddress(const IPAddress& address, const Poco::Timespan * timeout_, unsigned -#ifdef POCO_HAVE_ADDRINFO - hintFlags -#endif - ) -{ -#if defined(POCO_HAVE_LIBRESOLV) - Poco::ScopedReadRWLock readLock(resolverLock); -#endif - -#if defined(POCO_HAVE_ADDRINFO) - SocketAddress sa(address, 0); - static char fqname[1024]; - int rc = getnameinfo(sa.addr(), sa.length(), fqname, sizeof(fqname), NULL, 0, NI_NAMEREQD); - if (rc == 0) - { - struct addrinfo* pAI; - struct addrinfo hints; - std::memset(&hints, 0, sizeof(hints)); - hints.ai_flags = hintFlags; -#if defined(POCO_HAVE_GETADDRINFO_A) - int rc = GetAddrinfo::instance().getaddrinfo(fqname, NULL, &hints, &pAI, timeout_); -#else - int rc = getaddrinfo(fqname, NULL, &hints, &pAI); -#endif - if (rc == 0) - { - HostEntry result(pAI); - freeaddrinfo(pAI); - return result; - } - else - { - aierror(rc, address.toString()); - } - } - else - { - aierror(rc, address.toString()); - } -#elif defined(POCO_VXWORKS) - char name[MAXHOSTNAMELEN + 1]; - if (hostGetByAddr(*reinterpret_cast<const int*>(address.addr()), name) == OK) - { - return HostEntry(std::string(name), address); - } -#else - struct hostent* he = gethostbyaddr(reinterpret_cast<const char*>(address.addr()), address.length(), address.af()); - if (he) - { - return HostEntry(he); - } -#endif - int err = lastError(); - error(err, address.toString()); // will throw an appropriate exception - throw NetException(); // to silence compiler -} - - -HostEntry DNS::resolve(const std::string& address) -{ - IPAddress ip; - if (IPAddress::tryParse(address, ip)) - { - return hostByAddress(ip); - } - else if (isIDN(address)) - { - std::string encoded = encodeIDN(address); - return hostByName(encoded); - } - else - { - return hostByName(address); - } -} - - -IPAddress DNS::resolveOne(const std::string& address) -{ - const HostEntry& entry = resolve(address); - if (!entry.addresses().empty()) - return entry.addresses()[0]; - else - throw NoAddressFoundException(address); -} - - -HostEntry DNS::thisHost() -{ - return hostByName(hostName()); -} - - -void DNS::reload() -{ -#if defined(POCO_HAVE_LIBRESOLV) - Poco::ScopedWriteRWLock writeLock(resolverLock); - res_init(); -#endif -} - - -std::string DNS::hostName() -{ - char buffer[256]; - int rc = gethostname(buffer, sizeof(buffer)); - if (rc == 0) - return std::string(buffer); - else - throw NetException("Cannot get host name"); -} - - -bool DNS::isIDN(const std::string& hostname) -{ - for (std::string::const_iterator it = hostname.begin(); it != hostname.end(); ++it) - { - if (static_cast<unsigned char>(*it) >= 0x80) return true; - } - return false; -} - - -bool DNS::isEncodedIDN(const std::string& hostname) -{ - return hostname.compare(0, 4, "xn--") == 0 || hostname.find(".xn--") != std::string::npos; -} - - -std::string DNS::encodeIDN(const std::string& idn) -{ - std::string encoded; - std::string::const_iterator it = idn.begin(); - std::string::const_iterator end = idn.end(); - while (it != end) - { - std::string label; - bool mustEncode = false; - while (it != end && *it != '.') - { - if (static_cast<unsigned char>(*it) >= 0x80) mustEncode = true; - label += *it++; - } - if (mustEncode) - encoded += encodeIDNLabel(label); - else - encoded += label; - if (it != end) encoded += *it++; - } - return encoded; -} - - -std::string DNS::decodeIDN(const std::string& encodedIDN) -{ - std::string decoded; - std::string::const_iterator it = encodedIDN.begin(); - std::string::const_iterator end = encodedIDN.end(); - while (it != end) - { - std::string label; - while (it != end && *it != '.') - { - label += *it++; - } - decoded += decodeIDNLabel(label); - if (it != end) decoded += *it++; - } - return decoded; -} - - -std::string DNS::encodeIDNLabel(const std::string& label) -{ - std::string encoded = "xn--"; - std::vector<Poco::UInt32> uniLabel; - Poco::UTF8Encoding utf8; - Poco::TextIterator it(label, utf8); - Poco::TextIterator end(label); - while (it != end) - { - int ch = *it; - if (ch < 0) throw DNSException("Invalid UTF-8 character in IDN label", label); - if (Poco::Unicode::isUpper(ch)) - { - ch = Poco::Unicode::toLower(ch); - } - uniLabel.push_back(static_cast<Poco::UInt32>(ch)); - ++it; - } - char buffer[64]; - std::size_t size = 64; - int rc = punycode_encode(uniLabel.size(), &uniLabel[0], &size, buffer); - if (rc == punycode_success) - encoded.append(buffer, size); - else - throw DNSException("Failed to encode IDN label", label); - return encoded; -} - - -std::string DNS::decodeIDNLabel(const std::string& encodedIDN) -{ - std::string decoded; - if (encodedIDN.compare(0, 4, "xn--") == 0) - { - std::size_t size = 64; - punycode_uint buffer[64]; - int rc = punycode_decode(encodedIDN.size() - 4, encodedIDN.data() + 4, &size, buffer); - if (rc == punycode_success) - { - Poco::UTF32Encoding utf32; - Poco::UTF8Encoding utf8; - Poco::TextConverter converter(utf32, utf8); - converter.convert(buffer, static_cast<int>(size*sizeof(punycode_uint)), decoded); - } - else throw DNSException("Failed to decode IDN label: ", encodedIDN); - } - else - { - decoded = encodedIDN; - } - return decoded; -} - - -int DNS::lastError() -{ -#if defined(_WIN32) - return GetLastError(); -#elif defined(POCO_VXWORKS) - return errno; -#else - return h_errno; -#endif -} - - -void DNS::error(int code, const std::string& arg) -{ - switch (code) - { - case POCO_ESYSNOTREADY: - throw NetException("Net subsystem not ready"); - case POCO_ENOTINIT: - throw NetException("Net subsystem not initialized"); - case POCO_HOST_NOT_FOUND: - throw HostNotFoundException(arg); - case POCO_TRY_AGAIN: - throw DNSException("Temporary DNS error while resolving", arg); - case POCO_NO_RECOVERY: - throw DNSException("Non recoverable DNS error while resolving", arg); - case POCO_NO_DATA: - throw NoAddressFoundException(arg); - default: - throw IOException(NumberFormatter::format(code)); - } -} - - -void DNS::aierror(int code, const std::string& arg) -{ -#if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO) - switch (code) - { - case EAI_AGAIN: - throw DNSException("Temporary DNS error while resolving", arg); - case EAI_FAIL: - throw DNSException("Non recoverable DNS error while resolving", arg); -#if !defined(_WIN32) // EAI_NODATA and EAI_NONAME have the same value -#if defined(EAI_NODATA) // deprecated in favor of EAI_NONAME on FreeBSD - case EAI_NODATA: - throw NoAddressFoundException(arg); -#endif -#endif - case EAI_NONAME: - throw HostNotFoundException(arg); -#if defined(EAI_SYSTEM) - case EAI_SYSTEM: - error(lastError(), arg); - break; -#endif -#if defined(_WIN32) - case WSANO_DATA: // may happen on XP - throw HostNotFoundException(arg); -#endif - default: -#if defined(POCO_HAVE_ADDRINFO) - throw DNSException(gai_strerror(code), NumberFormatter::format(code), code); -#else - throw DNSException("EAI", NumberFormatter::format(code), code); -#endif - } -#endif // POCO_HAVE_IPv6 || defined(POCO_HAVE_ADDRINFO) -} - - -/* - Code copied from http://www.nicemice.net/idn/punycode-spec.gz on - 2018-02-17 with SHA-1 a966a8017f6be579d74a50a226accc7607c40133 - labeled punycode-spec 1.0.3 (2006-Mar-23-Thu). - - Modified for POCO C++ Libraries by Guenter Obiltschnig. - - License on the original code: - - punycode-spec 1.0.3 (2006-Mar-23-Thu) - http://www.nicemice.net/idn/ - Adam M. Costello - http://www.nicemice.net/amc/ - - B. Disclaimer and license - - Regarding this entire document or any portion of it (including - the pseudocode and C code), the author makes no guarantees and - is not responsible for any damage resulting from its use. The - author grants irrevocable permission to anyone to use, modify, - and distribute it in any way that does not diminish the rights - of anyone else to use, modify, and distribute it, provided that - redistributed derivative works do not contain misleading author or - version information. Derivative works need not be licensed under - similar terms. - - C. Punycode sample implementation - - punycode-sample.c 2.0.0 (2004-Mar-21-Sun) - http://www.nicemice.net/idn/ - Adam M. Costello - http://www.nicemice.net/amc/ - - This is ANSI C code (C89) implementing Punycode 1.0.x. -*/ - - -/*** Bootstring parameters for Punycode ***/ - -enum -{ - base = 36, - tmin = 1, - tmax = 26, - skew = 38, - damp = 700, - initial_bias = 72, - initial_n = 0x80, - delimiter = 0x2D -}; - -/* basic(cp) tests whether cp is a basic code point: */ -#define basic(cp) ((punycode_uint)(cp) < 0x80) - -/* delim(cp) tests whether cp is a delimiter: */ -#define delim(cp) ((cp) == delimiter) - -/* encode_digit(d,flag) returns the basic code point whose value */ -/* (when used for representing integers) is d, which needs to be in */ -/* the range 0 to base-1. The lowercase form is used unless flag is */ -/* nonzero, in which case the uppercase form is used. The behavior */ -/* is undefined if flag is nonzero and digit d has no uppercase form. */ - -static char encode_digit(punycode_uint d, int flag) -{ - return static_cast<char>(d + 22 + 75 * (d < 26) - ((flag != 0) << 5)); - /* 0..25 map to ASCII a..z or A..Z */ - /* 26..35 map to ASCII 0..9 */ -} - -/* decode_digit(cp) returns the numeric value of a basic code */ -/* point (for use in representing integers) in the range 0 to */ -/* base-1, or base if cp does not represent a value. */ - -static unsigned decode_digit(int cp) -{ - return (unsigned) (cp - 48 < 10 ? cp - 22 : cp - 65 < 26 ? cp - 65 : - cp - 97 < 26 ? cp - 97 : base); -} - -/*** Platform-specific constants ***/ - -/* maxint is the maximum value of a punycode_uint variable: */ -static const punycode_uint maxint = punycode_uint (-1); -/* Because maxint is unsigned, -1 becomes the maximum value. */ - -/*** Bias adaptation function ***/ - -static punycode_uint adapt(punycode_uint delta, punycode_uint numpoints, int firsttime); - -static punycode_uint adapt(punycode_uint delta, punycode_uint numpoints, int firsttime) -{ - punycode_uint k; - - delta = firsttime ? delta / damp : delta >> 1; - /* delta >> 1 is a faster way of doing delta / 2 */ - delta += delta / numpoints; - - for (k = 0; delta > ((base - tmin) * tmax) / 2; k += base) - { - delta /= base - tmin; - } - - return k + (base - tmin + 1) * delta / (delta + skew); -} - -/*** Main encode function ***/ - -int punycode_encode(size_t input_length_orig, const punycode_uint input[], size_t *output_length, char output[]) -{ - punycode_uint input_length, n, delta, h, b, bias, j, m, q, k, t; - size_t out, max_out; - - /* The Punycode spec assumes that the input length is the same type */ - /* of integer as a code point, so we need to convert the size_t to */ - /* a punycode_uint, which could overflow. */ - - if (input_length_orig > maxint) return punycode_overflow; - input_length = (punycode_uint) input_length_orig; - - /* Initialize the state: */ - - n = initial_n; - delta = 0; - out = 0; - max_out = *output_length; - bias = initial_bias; - - /* Handle the basic code points: */ - - for (j = 0; j < input_length; ++j) - { - if (basic(input[j])) - { - if (max_out - out < 2) return punycode_big_output; - output[out++] = (char) input[j]; - } - /* else if (input[j] < n) return punycode_bad_input; */ - /* (not needed for Punycode with unsigned code points) */ - } - - h = b = (punycode_uint) out; - /* cannot overflow because out <= input_length <= maxint */ - - /* h is the number of code points that have been handled, b is the */ - /* number of basic code points, and out is the number of ASCII code */ - /* points that have been output. */ - - if (b > 0) output[out++] = delimiter; - - /* Main encoding loop: */ - - while (h < input_length) - { - /* All non-basic code points < n have been */ - /* handled already. Find the next larger one: */ - - for (m = maxint, j = 0; j < input_length; ++j) - { - /* if (basic(input[j])) continue; */ - /* (not needed for Punycode) */ - if (input[j] >= n && input[j] < m) m = input[j]; - } - - /* Increase delta enough to advance the decoder's */ - /* <n,i> state to <m,0>, but guard against overflow: */ - - if (m - n > (maxint - delta) / (h + 1)) return punycode_overflow; - delta += (m - n) * (h + 1); - n = m; - - for (j = 0; j < input_length; ++j) - { - /* Punycode does not need to check whether input[j] is basic: */ - if (input[j] < n /* || basic(input[j]) */ ) - { - if (++delta == 0) return punycode_overflow; - } - - if (input[j] == n) - { - /* Represent delta as a generalized variable-length integer: */ - - for (q = delta, k = base; ; k += base) - { - if (out >= max_out) return punycode_big_output; - t = k <= bias /* + tmin */ ? tmin : /* +tmin not needed */ - k >= bias + tmax ? tmax : k - bias; - if (q < t) break; - output[out++] = encode_digit(t + (q - t) % (base - t), 0); - q = (q - t) / (base - t); - } - - output[out++] = encode_digit(q, 0); - bias = adapt(delta, h + 1, h == b); - delta = 0; - ++h; - } - } - - ++delta, ++n; - } - - *output_length = out; - return punycode_success; -} - -/*** Main decode function ***/ - -int punycode_decode(size_t input_length, const char input[], size_t *output_length, punycode_uint output[]) -{ - punycode_uint n, out, i, max_out, bias, oldi, w, k, digit, t; - size_t b, j, in; - - /* Initialize the state: */ - - n = initial_n; - out = i = 0; - max_out = *output_length > maxint ? maxint : (punycode_uint) *output_length; - bias = initial_bias; - - /* Handle the basic code points: Let b be the number of input code */ - /* points before the last delimiter, or 0 if there is none, then */ - /* copy the first b code points to the output. */ - - for (b = j = 0; j < input_length; ++j) - { - if (delim(input[j])) b = j; - } - if (b > max_out) return punycode_big_output; - - for (j = 0; j < b; ++j) - { - if (!basic(input[j])) return punycode_bad_input; - output[out++] = input[j]; - } - - /* Main decoding loop: Start just after the last delimiter if any */ - /* basic code points were copied; start at the beginning otherwise. */ - - for (in = b > 0 ? b + 1 : 0; in < input_length; ++out) - { - /* in is the index of the next ASCII code point to be consumed, */ - /* and out is the number of code points in the output array. */ - - /* Decode a generalized variable-length integer into delta, */ - /* which gets added to i. The overflow checking is easier */ - /* if we increase i as we go, then subtract off its starting */ - /* value at the end to obtain delta. */ - - for (oldi = i, w = 1, k = base; ; k += base) - { - if (in >= input_length) return punycode_bad_input; - digit = decode_digit(input[in++]); - if (digit >= base) return punycode_bad_input; - if (digit > (maxint - i) / w) return punycode_overflow; - i += digit * w; - t = k <= bias /* + tmin */ ? tmin : /* +tmin not needed */ - k >= bias + tmax ? tmax : k - bias; - if (digit < t) break; - if (w > maxint / (base - t)) return punycode_overflow; - w *= (base - t); - } - - bias = adapt(i - oldi, out + 1, oldi == 0); - - /* i was supposed to wrap around from out+1 to 0, */ - /* incrementing n each time, so we'll fix that now: */ - - if (i / (out + 1) > maxint - n) return punycode_overflow; - n += i / (out + 1); - i %= (out + 1); - - /* Insert n at position i of the output: */ - - /* not needed for Punycode: */ - /* if (basic(n)) return punycode_bad_input; */ - if (out >= max_out) return punycode_big_output; - - std::memmove(output + i + 1, output + i, (out - i) * sizeof *output); - output[i++] = n; - } - - *output_length = (size_t) out; - /* cannot overflow because out <= old value of *output_length */ - return punycode_success; -} - - -} } // namespace Poco::Net +// +// DNS.cpp +// +// Library: Net +// Package: NetCore +// Module: DNS +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/DNS.h" +#include "Poco/Net/NetException.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/Environment.h" +#include "Poco/NumberFormatter.h" +#include "Poco/RWLock.h" +#include "Poco/TextIterator.h" +#include "Poco/TextConverter.h" +#include "Poco/UTF8Encoding.h" +#include "Poco/UTF32Encoding.h" +#include "Poco/Unicode.h" +#include "Poco/Timespan.h" +#include "Poco/Mutex.h" +#include <cstring> +#include <list> +#include <atomic> + + +#if defined(POCO_HAVE_LIBRESOLV) +#include <resolv.h> +#endif + + +/// set default DNS timeout to 60 seconds +const Poco::Timespan Poco::Net::DNS::DEFAULT_DNS_TIMEOUT = Poco::Timespan(60, 0); + +#if defined(POCO_HAVE_GETADDRINFO_A) +/** getaddrinfo иногда работает бесконечно долго. + * Этот код использует getaddrinfo_a c некоторым таймаутом. + * + * При выполнении в один поток производительность ниже на 30% + * При выполнении запросов в 4 потока производительность отличается + * иногда в лучшую иногда в худшую сторону на ~10-20% + */ +class GetAddrinfo +{ +public: + static GetAddrinfo & instance() + { + static GetAddrinfo impl; + return impl; + } + + int getaddrinfo(const char * name, + const char * service, + const struct addrinfo * hints, + struct addrinfo ** pai, + const Poco::Timespan * timeout_); + + size_t requestsNum() + { + Poco::ScopedLock<Poco::FastMutex> lock(mutex); + return requests.size(); + } + +private: + GetAddrinfo() {} + + GetAddrinfo(const GetAddrinfo &) = delete; + const GetAddrinfo & operator=(const GetAddrinfo &) = delete; + + void releaseUnused() + { + for (auto it = requests.rbegin(); it != requests.rend();) + { + /// don't delete if structure is used by other thread or by internal cycle of getaddrinfo + if (it->unused && gai_error(&(*it)) != EAI_INPROGRESS) + { + free(const_cast<char *>(it->ar_name)); + it->ar_name = nullptr; + free(const_cast<char *>(it->ar_service)); + it->ar_service = nullptr; + free(const_cast<addrinfo *>(it->ar_request)); + it->ar_request = nullptr; + freeaddrinfo(it->ar_result); + it->ar_result = nullptr; + + auto it_to_delete = --(it.base()); + + it = decltype(it)(requests.erase(it_to_delete)); + } + else + break; + } + } + + void addOne(const char * name, + const char * service, + const struct addrinfo * hints) + { + requests.emplace_back(); + + auto & request = requests.back(); + + request.ar_name = name ? strdup(name) : nullptr; + request.ar_service = service ? strdup(service) : nullptr; + + addrinfo * my_hints = nullptr; + if (hints) + { + /// only ai_flags are used in Poco + my_hints = (addrinfo *)calloc(1, sizeof(addrinfo)); + my_hints->ai_flags = hints->ai_flags; + } + request.ar_request = my_hints; + + request.ar_result = nullptr; + } + +private: + struct gaicb_ext : public gaicb + { + gaicb_ext() + { + memset(this, 0, sizeof(gaicb_ext)); + } + + ~gaicb_ext() + { + if (gai_error(this) != EAI_INPROGRESS) + { + free(const_cast<char *>(ar_name)); + free(const_cast<char *>(ar_service)); + free(const_cast<addrinfo *>(ar_request)); + + freeaddrinfo(ar_result); + } + } + + std::atomic<bool> unused {false}; + }; + + std::list<gaicb_ext> requests; + + Poco::FastMutex mutex; +}; + +int GetAddrinfo::getaddrinfo(const char * name, + const char * service, + const struct addrinfo * hints, + struct addrinfo ** pai, + const Poco::Timespan * timeout_) +{ + if (timeout_) + { + timespec timeout; + timeout.tv_sec = timeout_->totalSeconds(); + timeout.tv_nsec = timeout_->microseconds() * 1000; + + gaicb_ext * request_ext_ptr = nullptr; + { + Poco::ScopedLock<Poco::FastMutex> lock(mutex); + addOne(name, service, hints); + request_ext_ptr = &requests.back(); + } + gaicb * request_ptr = request_ext_ptr; + + int code = getaddrinfo_a(GAI_NOWAIT, &request_ptr, 1, nullptr); + + if (!code) + { + gai_suspend(&request_ptr, 1, &timeout); + + *pai = request_ext_ptr->ar_result; + /// prevent deleting result in dctor + request_ext_ptr->ar_result = nullptr; + + code = gai_error(request_ext_ptr); + } + + request_ext_ptr->unused = true; + + { + Poco::ScopedLock<Poco::FastMutex> lock(mutex); + releaseUnused(); + } + + return code; + } + else + { + return ::getaddrinfo(name, service, hints, pai); + } +} +#endif + + +using Poco::Environment; +using Poco::NumberFormatter; +using Poco::IOException; + + +namespace Poco { +namespace Net { + + +typedef Poco::UInt32 punycode_uint; + + +enum +{ + punycode_success = 0, + punycode_overflow = -1, + punycode_big_output = -2, + punycode_bad_input = -3 +}; + + +static int punycode_encode(size_t input_length, const punycode_uint input[], size_t* output_length, char output[]); +static int punycode_decode(size_t input_length, const char input[], size_t* output_length, punycode_uint output[]); + + +#if defined(POCO_HAVE_LIBRESOLV) +static Poco::RWLock resolverLock; +#endif + + +HostEntry DNS::hostByName(const std::string& hostname, const Poco::Timespan * timeout_, unsigned +#ifdef POCO_HAVE_ADDRINFO + hintFlags +#endif + ) +{ +#if defined(POCO_HAVE_LIBRESOLV) + Poco::ScopedReadRWLock readLock(resolverLock); +#endif + +#if defined(POCO_HAVE_ADDRINFO) + struct addrinfo* pAI; + struct addrinfo hints; + std::memset(&hints, 0, sizeof(hints)); + hints.ai_flags = hintFlags; +#if defined(POCO_HAVE_GETADDRINFO_A) + int rc = GetAddrinfo::instance().getaddrinfo(hostname.c_str(), NULL, &hints, &pAI, timeout_); +#else + int rc = getaddrinfo(hostname.c_str(), NULL, &hints, &pAI); +#endif + if (rc == 0) + { + HostEntry result(pAI); + freeaddrinfo(pAI); + return result; + } + else + { + aierror(rc, hostname); + } +#elif defined(POCO_VXWORKS) + int addr = hostGetByName(const_cast<char*>(hostname.c_str())); + if (addr != ERROR) + { + return HostEntry(hostname, IPAddress(&addr, sizeof(addr))); + } +#else + struct hostent* he = gethostbyname(hostname.c_str()); + if (he) + { + return HostEntry(he); + } +#endif + error(lastError(), hostname); // will throw an appropriate exception + throw NetException(); // to silence compiler +} + + +HostEntry DNS::hostByAddress(const IPAddress& address, const Poco::Timespan * timeout_, unsigned +#ifdef POCO_HAVE_ADDRINFO + hintFlags +#endif + ) +{ +#if defined(POCO_HAVE_LIBRESOLV) + Poco::ScopedReadRWLock readLock(resolverLock); +#endif + +#if defined(POCO_HAVE_ADDRINFO) + SocketAddress sa(address, 0); + static char fqname[1024]; + int rc = getnameinfo(sa.addr(), sa.length(), fqname, sizeof(fqname), NULL, 0, NI_NAMEREQD); + if (rc == 0) + { + struct addrinfo* pAI; + struct addrinfo hints; + std::memset(&hints, 0, sizeof(hints)); + hints.ai_flags = hintFlags; +#if defined(POCO_HAVE_GETADDRINFO_A) + int rc = GetAddrinfo::instance().getaddrinfo(fqname, NULL, &hints, &pAI, timeout_); +#else + int rc = getaddrinfo(fqname, NULL, &hints, &pAI); +#endif + if (rc == 0) + { + HostEntry result(pAI); + freeaddrinfo(pAI); + return result; + } + else + { + aierror(rc, address.toString()); + } + } + else + { + aierror(rc, address.toString()); + } +#elif defined(POCO_VXWORKS) + char name[MAXHOSTNAMELEN + 1]; + if (hostGetByAddr(*reinterpret_cast<const int*>(address.addr()), name) == OK) + { + return HostEntry(std::string(name), address); + } +#else + struct hostent* he = gethostbyaddr(reinterpret_cast<const char*>(address.addr()), address.length(), address.af()); + if (he) + { + return HostEntry(he); + } +#endif + int err = lastError(); + error(err, address.toString()); // will throw an appropriate exception + throw NetException(); // to silence compiler +} + + +HostEntry DNS::resolve(const std::string& address) +{ + IPAddress ip; + if (IPAddress::tryParse(address, ip)) + { + return hostByAddress(ip); + } + else if (isIDN(address)) + { + std::string encoded = encodeIDN(address); + return hostByName(encoded); + } + else + { + return hostByName(address); + } +} + + +IPAddress DNS::resolveOne(const std::string& address) +{ + const HostEntry& entry = resolve(address); + if (!entry.addresses().empty()) + return entry.addresses()[0]; + else + throw NoAddressFoundException(address); +} + + +HostEntry DNS::thisHost() +{ + return hostByName(hostName()); +} + + +void DNS::reload() +{ +#if defined(POCO_HAVE_LIBRESOLV) + Poco::ScopedWriteRWLock writeLock(resolverLock); + res_init(); +#endif +} + + +std::string DNS::hostName() +{ + char buffer[256]; + int rc = gethostname(buffer, sizeof(buffer)); + if (rc == 0) + return std::string(buffer); + else + throw NetException("Cannot get host name"); +} + + +bool DNS::isIDN(const std::string& hostname) +{ + for (std::string::const_iterator it = hostname.begin(); it != hostname.end(); ++it) + { + if (static_cast<unsigned char>(*it) >= 0x80) return true; + } + return false; +} + + +bool DNS::isEncodedIDN(const std::string& hostname) +{ + return hostname.compare(0, 4, "xn--") == 0 || hostname.find(".xn--") != std::string::npos; +} + + +std::string DNS::encodeIDN(const std::string& idn) +{ + std::string encoded; + std::string::const_iterator it = idn.begin(); + std::string::const_iterator end = idn.end(); + while (it != end) + { + std::string label; + bool mustEncode = false; + while (it != end && *it != '.') + { + if (static_cast<unsigned char>(*it) >= 0x80) mustEncode = true; + label += *it++; + } + if (mustEncode) + encoded += encodeIDNLabel(label); + else + encoded += label; + if (it != end) encoded += *it++; + } + return encoded; +} + + +std::string DNS::decodeIDN(const std::string& encodedIDN) +{ + std::string decoded; + std::string::const_iterator it = encodedIDN.begin(); + std::string::const_iterator end = encodedIDN.end(); + while (it != end) + { + std::string label; + while (it != end && *it != '.') + { + label += *it++; + } + decoded += decodeIDNLabel(label); + if (it != end) decoded += *it++; + } + return decoded; +} + + +std::string DNS::encodeIDNLabel(const std::string& label) +{ + std::string encoded = "xn--"; + std::vector<Poco::UInt32> uniLabel; + Poco::UTF8Encoding utf8; + Poco::TextIterator it(label, utf8); + Poco::TextIterator end(label); + while (it != end) + { + int ch = *it; + if (ch < 0) throw DNSException("Invalid UTF-8 character in IDN label", label); + if (Poco::Unicode::isUpper(ch)) + { + ch = Poco::Unicode::toLower(ch); + } + uniLabel.push_back(static_cast<Poco::UInt32>(ch)); + ++it; + } + char buffer[64]; + std::size_t size = 64; + int rc = punycode_encode(uniLabel.size(), &uniLabel[0], &size, buffer); + if (rc == punycode_success) + encoded.append(buffer, size); + else + throw DNSException("Failed to encode IDN label", label); + return encoded; +} + + +std::string DNS::decodeIDNLabel(const std::string& encodedIDN) +{ + std::string decoded; + if (encodedIDN.compare(0, 4, "xn--") == 0) + { + std::size_t size = 64; + punycode_uint buffer[64]; + int rc = punycode_decode(encodedIDN.size() - 4, encodedIDN.data() + 4, &size, buffer); + if (rc == punycode_success) + { + Poco::UTF32Encoding utf32; + Poco::UTF8Encoding utf8; + Poco::TextConverter converter(utf32, utf8); + converter.convert(buffer, static_cast<int>(size*sizeof(punycode_uint)), decoded); + } + else throw DNSException("Failed to decode IDN label: ", encodedIDN); + } + else + { + decoded = encodedIDN; + } + return decoded; +} + + +int DNS::lastError() +{ +#if defined(_WIN32) + return GetLastError(); +#elif defined(POCO_VXWORKS) + return errno; +#else + return h_errno; +#endif +} + + +void DNS::error(int code, const std::string& arg) +{ + switch (code) + { + case POCO_ESYSNOTREADY: + throw NetException("Net subsystem not ready"); + case POCO_ENOTINIT: + throw NetException("Net subsystem not initialized"); + case POCO_HOST_NOT_FOUND: + throw HostNotFoundException(arg); + case POCO_TRY_AGAIN: + throw DNSException("Temporary DNS error while resolving", arg); + case POCO_NO_RECOVERY: + throw DNSException("Non recoverable DNS error while resolving", arg); + case POCO_NO_DATA: + throw NoAddressFoundException(arg); + default: + throw IOException(NumberFormatter::format(code)); + } +} + + +void DNS::aierror(int code, const std::string& arg) +{ +#if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO) + switch (code) + { + case EAI_AGAIN: + throw DNSException("Temporary DNS error while resolving", arg); + case EAI_FAIL: + throw DNSException("Non recoverable DNS error while resolving", arg); +#if !defined(_WIN32) // EAI_NODATA and EAI_NONAME have the same value +#if defined(EAI_NODATA) // deprecated in favor of EAI_NONAME on FreeBSD + case EAI_NODATA: + throw NoAddressFoundException(arg); +#endif +#endif + case EAI_NONAME: + throw HostNotFoundException(arg); +#if defined(EAI_SYSTEM) + case EAI_SYSTEM: + error(lastError(), arg); + break; +#endif +#if defined(_WIN32) + case WSANO_DATA: // may happen on XP + throw HostNotFoundException(arg); +#endif + default: +#if defined(POCO_HAVE_ADDRINFO) + throw DNSException(gai_strerror(code), NumberFormatter::format(code), code); +#else + throw DNSException("EAI", NumberFormatter::format(code), code); +#endif + } +#endif // POCO_HAVE_IPv6 || defined(POCO_HAVE_ADDRINFO) +} + + +/* + Code copied from http://www.nicemice.net/idn/punycode-spec.gz on + 2018-02-17 with SHA-1 a966a8017f6be579d74a50a226accc7607c40133 + labeled punycode-spec 1.0.3 (2006-Mar-23-Thu). + + Modified for POCO C++ Libraries by Guenter Obiltschnig. + + License on the original code: + + punycode-spec 1.0.3 (2006-Mar-23-Thu) + http://www.nicemice.net/idn/ + Adam M. Costello + http://www.nicemice.net/amc/ + + B. Disclaimer and license + + Regarding this entire document or any portion of it (including + the pseudocode and C code), the author makes no guarantees and + is not responsible for any damage resulting from its use. The + author grants irrevocable permission to anyone to use, modify, + and distribute it in any way that does not diminish the rights + of anyone else to use, modify, and distribute it, provided that + redistributed derivative works do not contain misleading author or + version information. Derivative works need not be licensed under + similar terms. + + C. Punycode sample implementation + + punycode-sample.c 2.0.0 (2004-Mar-21-Sun) + http://www.nicemice.net/idn/ + Adam M. Costello + http://www.nicemice.net/amc/ + + This is ANSI C code (C89) implementing Punycode 1.0.x. +*/ + + +/*** Bootstring parameters for Punycode ***/ + +enum +{ + base = 36, + tmin = 1, + tmax = 26, + skew = 38, + damp = 700, + initial_bias = 72, + initial_n = 0x80, + delimiter = 0x2D +}; + +/* basic(cp) tests whether cp is a basic code point: */ +#define basic(cp) ((punycode_uint)(cp) < 0x80) + +/* delim(cp) tests whether cp is a delimiter: */ +#define delim(cp) ((cp) == delimiter) + +/* encode_digit(d,flag) returns the basic code point whose value */ +/* (when used for representing integers) is d, which needs to be in */ +/* the range 0 to base-1. The lowercase form is used unless flag is */ +/* nonzero, in which case the uppercase form is used. The behavior */ +/* is undefined if flag is nonzero and digit d has no uppercase form. */ + +static char encode_digit(punycode_uint d, int flag) +{ + return static_cast<char>(d + 22 + 75 * (d < 26) - ((flag != 0) << 5)); + /* 0..25 map to ASCII a..z or A..Z */ + /* 26..35 map to ASCII 0..9 */ +} + +/* decode_digit(cp) returns the numeric value of a basic code */ +/* point (for use in representing integers) in the range 0 to */ +/* base-1, or base if cp does not represent a value. */ + +static unsigned decode_digit(int cp) +{ + return (unsigned) (cp - 48 < 10 ? cp - 22 : cp - 65 < 26 ? cp - 65 : + cp - 97 < 26 ? cp - 97 : base); +} + +/*** Platform-specific constants ***/ + +/* maxint is the maximum value of a punycode_uint variable: */ +static const punycode_uint maxint = punycode_uint (-1); +/* Because maxint is unsigned, -1 becomes the maximum value. */ + +/*** Bias adaptation function ***/ + +static punycode_uint adapt(punycode_uint delta, punycode_uint numpoints, int firsttime); + +static punycode_uint adapt(punycode_uint delta, punycode_uint numpoints, int firsttime) +{ + punycode_uint k; + + delta = firsttime ? delta / damp : delta >> 1; + /* delta >> 1 is a faster way of doing delta / 2 */ + delta += delta / numpoints; + + for (k = 0; delta > ((base - tmin) * tmax) / 2; k += base) + { + delta /= base - tmin; + } + + return k + (base - tmin + 1) * delta / (delta + skew); +} + +/*** Main encode function ***/ + +int punycode_encode(size_t input_length_orig, const punycode_uint input[], size_t *output_length, char output[]) +{ + punycode_uint input_length, n, delta, h, b, bias, j, m, q, k, t; + size_t out, max_out; + + /* The Punycode spec assumes that the input length is the same type */ + /* of integer as a code point, so we need to convert the size_t to */ + /* a punycode_uint, which could overflow. */ + + if (input_length_orig > maxint) return punycode_overflow; + input_length = (punycode_uint) input_length_orig; + + /* Initialize the state: */ + + n = initial_n; + delta = 0; + out = 0; + max_out = *output_length; + bias = initial_bias; + + /* Handle the basic code points: */ + + for (j = 0; j < input_length; ++j) + { + if (basic(input[j])) + { + if (max_out - out < 2) return punycode_big_output; + output[out++] = (char) input[j]; + } + /* else if (input[j] < n) return punycode_bad_input; */ + /* (not needed for Punycode with unsigned code points) */ + } + + h = b = (punycode_uint) out; + /* cannot overflow because out <= input_length <= maxint */ + + /* h is the number of code points that have been handled, b is the */ + /* number of basic code points, and out is the number of ASCII code */ + /* points that have been output. */ + + if (b > 0) output[out++] = delimiter; + + /* Main encoding loop: */ + + while (h < input_length) + { + /* All non-basic code points < n have been */ + /* handled already. Find the next larger one: */ + + for (m = maxint, j = 0; j < input_length; ++j) + { + /* if (basic(input[j])) continue; */ + /* (not needed for Punycode) */ + if (input[j] >= n && input[j] < m) m = input[j]; + } + + /* Increase delta enough to advance the decoder's */ + /* <n,i> state to <m,0>, but guard against overflow: */ + + if (m - n > (maxint - delta) / (h + 1)) return punycode_overflow; + delta += (m - n) * (h + 1); + n = m; + + for (j = 0; j < input_length; ++j) + { + /* Punycode does not need to check whether input[j] is basic: */ + if (input[j] < n /* || basic(input[j]) */ ) + { + if (++delta == 0) return punycode_overflow; + } + + if (input[j] == n) + { + /* Represent delta as a generalized variable-length integer: */ + + for (q = delta, k = base; ; k += base) + { + if (out >= max_out) return punycode_big_output; + t = k <= bias /* + tmin */ ? tmin : /* +tmin not needed */ + k >= bias + tmax ? tmax : k - bias; + if (q < t) break; + output[out++] = encode_digit(t + (q - t) % (base - t), 0); + q = (q - t) / (base - t); + } + + output[out++] = encode_digit(q, 0); + bias = adapt(delta, h + 1, h == b); + delta = 0; + ++h; + } + } + + ++delta, ++n; + } + + *output_length = out; + return punycode_success; +} + +/*** Main decode function ***/ + +int punycode_decode(size_t input_length, const char input[], size_t *output_length, punycode_uint output[]) +{ + punycode_uint n, out, i, max_out, bias, oldi, w, k, digit, t; + size_t b, j, in; + + /* Initialize the state: */ + + n = initial_n; + out = i = 0; + max_out = *output_length > maxint ? maxint : (punycode_uint) *output_length; + bias = initial_bias; + + /* Handle the basic code points: Let b be the number of input code */ + /* points before the last delimiter, or 0 if there is none, then */ + /* copy the first b code points to the output. */ + + for (b = j = 0; j < input_length; ++j) + { + if (delim(input[j])) b = j; + } + if (b > max_out) return punycode_big_output; + + for (j = 0; j < b; ++j) + { + if (!basic(input[j])) return punycode_bad_input; + output[out++] = input[j]; + } + + /* Main decoding loop: Start just after the last delimiter if any */ + /* basic code points were copied; start at the beginning otherwise. */ + + for (in = b > 0 ? b + 1 : 0; in < input_length; ++out) + { + /* in is the index of the next ASCII code point to be consumed, */ + /* and out is the number of code points in the output array. */ + + /* Decode a generalized variable-length integer into delta, */ + /* which gets added to i. The overflow checking is easier */ + /* if we increase i as we go, then subtract off its starting */ + /* value at the end to obtain delta. */ + + for (oldi = i, w = 1, k = base; ; k += base) + { + if (in >= input_length) return punycode_bad_input; + digit = decode_digit(input[in++]); + if (digit >= base) return punycode_bad_input; + if (digit > (maxint - i) / w) return punycode_overflow; + i += digit * w; + t = k <= bias /* + tmin */ ? tmin : /* +tmin not needed */ + k >= bias + tmax ? tmax : k - bias; + if (digit < t) break; + if (w > maxint / (base - t)) return punycode_overflow; + w *= (base - t); + } + + bias = adapt(i - oldi, out + 1, oldi == 0); + + /* i was supposed to wrap around from out+1 to 0, */ + /* incrementing n each time, so we'll fix that now: */ + + if (i / (out + 1) > maxint - n) return punycode_overflow; + n += i / (out + 1); + i %= (out + 1); + + /* Insert n at position i of the output: */ + + /* not needed for Punycode: */ + /* if (basic(n)) return punycode_bad_input; */ + if (out >= max_out) return punycode_big_output; + + std::memmove(output + i + 1, output + i, (out - i) * sizeof *output); + output[i++] = n; + } + + *output_length = (size_t) out; + /* cannot overflow because out <= old value of *output_length */ + return punycode_success; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/DatagramSocket.cpp b/contrib/libs/poco/Net/src/DatagramSocket.cpp index 8d7cc92e3e..2e0a6d1e1d 100644 --- a/contrib/libs/poco/Net/src/DatagramSocket.cpp +++ b/contrib/libs/poco/Net/src/DatagramSocket.cpp @@ -1,114 +1,114 @@ -// -// DatagramSocket.cpp -// -// Library: Net -// Package: Sockets -// Module: DatagramSocket -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/DatagramSocket.h" -#include "Poco/Net/DatagramSocketImpl.h" -#include "Poco/Exception.h" - - -using Poco::InvalidArgumentException; - - -namespace Poco { -namespace Net { - - -DatagramSocket::DatagramSocket(): Socket(new DatagramSocketImpl) -{ -} - - -DatagramSocket::DatagramSocket(SocketAddress::Family family): Socket(new DatagramSocketImpl(family)) -{ -} - - -DatagramSocket::DatagramSocket(const SocketAddress& address, bool reuseAddress): Socket(new DatagramSocketImpl(address.family())) -{ - bind(address, reuseAddress); -} - - -DatagramSocket::DatagramSocket(const Socket& socket): Socket(socket) -{ - if (!dynamic_cast<DatagramSocketImpl*>(impl())) - throw InvalidArgumentException("Cannot assign incompatible socket"); -} - - -DatagramSocket::DatagramSocket(SocketImpl* pImpl): Socket(pImpl) -{ - if (!dynamic_cast<DatagramSocketImpl*>(impl())) - throw InvalidArgumentException("Cannot assign incompatible socket"); -} - - -DatagramSocket::~DatagramSocket() -{ -} - - -DatagramSocket& DatagramSocket::operator = (const Socket& socket) -{ - if (dynamic_cast<DatagramSocketImpl*>(socket.impl())) - Socket::operator = (socket); - else - throw InvalidArgumentException("Cannot assign incompatible socket"); - return *this; -} - - -void DatagramSocket::connect(const SocketAddress& address) -{ - impl()->connect(address); -} - - -void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress) -{ - impl()->bind(address, reuseAddress); -} - - -void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) -{ - impl()->bind(address, reuseAddress, reusePort); -} - - -int DatagramSocket::sendBytes(const void* buffer, int length, int flags) -{ - return impl()->sendBytes(buffer, length, flags); -} - - -int DatagramSocket::receiveBytes(void* buffer, int length, int flags) -{ - return impl()->receiveBytes(buffer, length, flags); -} - - -int DatagramSocket::sendTo(const void* buffer, int length, const SocketAddress& address, int flags) -{ - return impl()->sendTo(buffer, length, address, flags); -} - - -int DatagramSocket::receiveFrom(void* buffer, int length, SocketAddress& address, int flags) -{ - return impl()->receiveFrom(buffer, length, address, flags); -} - - -} } // namespace Poco::Net +// +// DatagramSocket.cpp +// +// Library: Net +// Package: Sockets +// Module: DatagramSocket +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/DatagramSocket.h" +#include "Poco/Net/DatagramSocketImpl.h" +#include "Poco/Exception.h" + + +using Poco::InvalidArgumentException; + + +namespace Poco { +namespace Net { + + +DatagramSocket::DatagramSocket(): Socket(new DatagramSocketImpl) +{ +} + + +DatagramSocket::DatagramSocket(SocketAddress::Family family): Socket(new DatagramSocketImpl(family)) +{ +} + + +DatagramSocket::DatagramSocket(const SocketAddress& address, bool reuseAddress): Socket(new DatagramSocketImpl(address.family())) +{ + bind(address, reuseAddress); +} + + +DatagramSocket::DatagramSocket(const Socket& socket): Socket(socket) +{ + if (!dynamic_cast<DatagramSocketImpl*>(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +DatagramSocket::DatagramSocket(SocketImpl* pImpl): Socket(pImpl) +{ + if (!dynamic_cast<DatagramSocketImpl*>(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +DatagramSocket::~DatagramSocket() +{ +} + + +DatagramSocket& DatagramSocket::operator = (const Socket& socket) +{ + if (dynamic_cast<DatagramSocketImpl*>(socket.impl())) + Socket::operator = (socket); + else + throw InvalidArgumentException("Cannot assign incompatible socket"); + return *this; +} + + +void DatagramSocket::connect(const SocketAddress& address) +{ + impl()->connect(address); +} + + +void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress) +{ + impl()->bind(address, reuseAddress); +} + + +void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) +{ + impl()->bind(address, reuseAddress, reusePort); +} + + +int DatagramSocket::sendBytes(const void* buffer, int length, int flags) +{ + return impl()->sendBytes(buffer, length, flags); +} + + +int DatagramSocket::receiveBytes(void* buffer, int length, int flags) +{ + return impl()->receiveBytes(buffer, length, flags); +} + + +int DatagramSocket::sendTo(const void* buffer, int length, const SocketAddress& address, int flags) +{ + return impl()->sendTo(buffer, length, address, flags); +} + + +int DatagramSocket::receiveFrom(void* buffer, int length, SocketAddress& address, int flags) +{ + return impl()->receiveFrom(buffer, length, address, flags); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/DatagramSocketImpl.cpp b/contrib/libs/poco/Net/src/DatagramSocketImpl.cpp index 9b86ebe611..7cfee05ede 100644 --- a/contrib/libs/poco/Net/src/DatagramSocketImpl.cpp +++ b/contrib/libs/poco/Net/src/DatagramSocketImpl.cpp @@ -1,63 +1,63 @@ -// -// DatagramSocketImpl.cpp -// -// Library: Net -// Package: Sockets -// Module: DatagramSocketImpl -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/DatagramSocketImpl.h" -#include "Poco/Net/NetException.h" - - -using Poco::InvalidArgumentException; - - -namespace Poco { -namespace Net { - - -DatagramSocketImpl::DatagramSocketImpl() -{ -} - - -DatagramSocketImpl::DatagramSocketImpl(SocketAddress::Family family) -{ - if (family == SocketAddress::IPv4) - init(AF_INET); -#if defined(POCO_HAVE_IPv6) - else if (family == SocketAddress::IPv6) - init(AF_INET6); -#endif -#if defined(POCO_OS_FAMILY_UNIX) - else if (family == SocketAddress::UNIX_LOCAL) - init(AF_UNIX); -#endif - else throw InvalidArgumentException("Invalid or unsupported address family passed to DatagramSocketImpl"); -} - - -DatagramSocketImpl::DatagramSocketImpl(poco_socket_t sockfd): SocketImpl(sockfd) -{ -} - - -DatagramSocketImpl::~DatagramSocketImpl() -{ -} - - -void DatagramSocketImpl::init(int af) -{ - initSocket(af, SOCK_DGRAM); -} - - -} } // namespace Poco::Net +// +// DatagramSocketImpl.cpp +// +// Library: Net +// Package: Sockets +// Module: DatagramSocketImpl +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/DatagramSocketImpl.h" +#include "Poco/Net/NetException.h" + + +using Poco::InvalidArgumentException; + + +namespace Poco { +namespace Net { + + +DatagramSocketImpl::DatagramSocketImpl() +{ +} + + +DatagramSocketImpl::DatagramSocketImpl(SocketAddress::Family family) +{ + if (family == SocketAddress::IPv4) + init(AF_INET); +#if defined(POCO_HAVE_IPv6) + else if (family == SocketAddress::IPv6) + init(AF_INET6); +#endif +#if defined(POCO_OS_FAMILY_UNIX) + else if (family == SocketAddress::UNIX_LOCAL) + init(AF_UNIX); +#endif + else throw InvalidArgumentException("Invalid or unsupported address family passed to DatagramSocketImpl"); +} + + +DatagramSocketImpl::DatagramSocketImpl(poco_socket_t sockfd): SocketImpl(sockfd) +{ +} + + +DatagramSocketImpl::~DatagramSocketImpl() +{ +} + + +void DatagramSocketImpl::init(int af) +{ + initSocket(af, SOCK_DGRAM); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/DialogSocket.cpp b/contrib/libs/poco/Net/src/DialogSocket.cpp index 030280c6c3..7b7e2adf01 100644 --- a/contrib/libs/poco/Net/src/DialogSocket.cpp +++ b/contrib/libs/poco/Net/src/DialogSocket.cpp @@ -1,295 +1,295 @@ -// -// DialogSocket.cpp -// -// Library: Net -// Package: Sockets -// Module: DialogSocket -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/DialogSocket.h" -#include "Poco/Exception.h" -#include "Poco/Ascii.h" -#include <cstring> - - -namespace Poco { -namespace Net { - - -DialogSocket::DialogSocket(): - _pBuffer(0), - _pNext(0), - _pEnd(0) -{ - allocBuffer(); -} - - -DialogSocket::DialogSocket(const SocketAddress& address): - StreamSocket(address), - _pBuffer(0), - _pNext(0), - _pEnd(0) -{ - allocBuffer(); -} - - -DialogSocket::DialogSocket(const Socket& socket): - StreamSocket(socket), - _pBuffer(0), - _pNext(0), - _pEnd(0) -{ - allocBuffer(); -} - - -DialogSocket::DialogSocket(const DialogSocket& socket): - StreamSocket(socket), - _pBuffer(0), - _pNext(0), - _pEnd(0) -{ - allocBuffer(); -} - - -DialogSocket::~DialogSocket() -{ - delete [] _pBuffer; -} - - -DialogSocket& DialogSocket::operator = (const Socket& socket) -{ - StreamSocket::operator = (socket); - _pNext = _pBuffer; - _pEnd = _pBuffer; - return *this; -} - - -DialogSocket& DialogSocket::operator = (const DialogSocket& socket) -{ - StreamSocket::operator = (socket); - _pNext = _pBuffer; - _pEnd = _pBuffer; - return *this; -} - - -void DialogSocket::sendByte(unsigned char ch) -{ - sendBytes(&ch, 1); -} - - -void DialogSocket::sendString(const char* str) -{ - sendBytes(str, (int) std::strlen(str)); -} - - -void DialogSocket::sendString(const std::string& str) -{ - sendBytes(str.data(), (int) str.length()); -} - - -void DialogSocket::sendMessage(const std::string& message) -{ - std::string line; - line.reserve(message.length() + 2); - line.append(message); - line.append("\r\n"); - sendString(line); -} - - -void DialogSocket::sendMessage(const std::string& message, const std::string& arg) -{ - std::string line; - line.reserve(message.length() + arg.length() + 3); - line.append(message); - if (!arg.empty()) - { - line.append(" "); - line.append(arg); - } - line.append("\r\n"); - sendString(line); -} - - -void DialogSocket::sendMessage(const std::string& message, const std::string& arg1, const std::string& arg2) -{ - std::string line; - line.reserve(message.length() + arg1.length() +arg2.length() + 4); - line.append(message); - line.append(" "); - line.append(arg1); - if (!arg2.empty()) - { - line.append(" "); - line.append(arg2); - } - line.append("\r\n"); - sendString(line); -} - - -bool DialogSocket::receiveMessage(std::string& message) -{ - message.clear(); - return receiveLine(message, MAX_LINE_LENGTH); -} - - -int DialogSocket::receiveStatusMessage(std::string& message) -{ - message.clear(); - int status = receiveStatusLine(message, MAX_LINE_LENGTH); - if (status < 0) - { - while (status <= 0) - { - message += '\n'; - status = receiveStatusLine(message, message.length() + MAX_LINE_LENGTH); - } - } - return status; -} - - -int DialogSocket::get() -{ - refill(); - if (_pNext != _pEnd) - return std::char_traits<char>::to_int_type(*_pNext++); - else - return EOF_CHAR; -} - - -int DialogSocket::peek() -{ - refill(); - if (_pNext != _pEnd) - return std::char_traits<char>::to_int_type(*_pNext); - else - return EOF_CHAR; -} - - -void DialogSocket::synch() -{ - sendUrgent(TELNET_DM); -} - - -void DialogSocket::sendTelnetCommand(unsigned char command) -{ - unsigned char buffer[2]; - buffer[0] = TELNET_IAC; - buffer[1] = command; - sendBytes(buffer, 2); -} - - -void DialogSocket::sendTelnetCommand(unsigned char command, unsigned char arg) -{ - unsigned char buffer[3]; - buffer[0] = TELNET_IAC; - buffer[1] = command; - buffer[2] = arg; - sendBytes(buffer, 3); -} - - -void DialogSocket::refill() -{ - if (_pNext == _pEnd) - { - int n = receiveBytes(_pBuffer, RECEIVE_BUFFER_SIZE); - if (n > 0) - { - _pNext = _pBuffer; - _pEnd = _pBuffer + n; - } - } -} - - -void DialogSocket::allocBuffer() -{ - _pBuffer = new char [RECEIVE_BUFFER_SIZE]; - _pNext = _pBuffer; - _pEnd = _pBuffer; -} - - -bool DialogSocket::receiveLine(std::string& line, std::size_t lineLengthLimit) -{ - // An old wisdom goes: be strict in what you emit - // and generous in what you accept. - int ch = get(); - while (ch != EOF_CHAR && ch != '\r' && ch != '\n') - { - if (lineLengthLimit == 0 || line.size() < lineLengthLimit) - line += (char) ch; - else - throw Poco::IOException("Line too long"); - ch = get(); - } - if (ch == '\r' && peek() == '\n') - get(); - else if (ch == EOF_CHAR) - return false; - return true; -} - - -int DialogSocket::receiveStatusLine(std::string& line, std::size_t lineLengthLimit) -{ - int status = 0; - int ch = get(); - if (ch != EOF_CHAR) line += (char) ch; - int n = 0; - while (Poco::Ascii::isDigit(ch) && n < 3) - { - status *= 10; - status += ch - '0'; - ++n; - ch = get(); - if (ch != EOF_CHAR) line += (char) ch; - } - if (n == 3) - { - if (ch == '-') - status = -status; - } - else status = 0; - if (ch != EOF_CHAR) receiveLine(line, lineLengthLimit); - return status; -} - - -int DialogSocket::receiveRawBytes(void* buffer, int length) -{ - refill(); - int n = static_cast<int>(_pEnd - _pNext); - if (n > length) n = length; - std::memcpy(buffer, _pNext, n); - _pNext += n; - return n; -} - - -} } // namespace Poco::Net +// +// DialogSocket.cpp +// +// Library: Net +// Package: Sockets +// Module: DialogSocket +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/DialogSocket.h" +#include "Poco/Exception.h" +#include "Poco/Ascii.h" +#include <cstring> + + +namespace Poco { +namespace Net { + + +DialogSocket::DialogSocket(): + _pBuffer(0), + _pNext(0), + _pEnd(0) +{ + allocBuffer(); +} + + +DialogSocket::DialogSocket(const SocketAddress& address): + StreamSocket(address), + _pBuffer(0), + _pNext(0), + _pEnd(0) +{ + allocBuffer(); +} + + +DialogSocket::DialogSocket(const Socket& socket): + StreamSocket(socket), + _pBuffer(0), + _pNext(0), + _pEnd(0) +{ + allocBuffer(); +} + + +DialogSocket::DialogSocket(const DialogSocket& socket): + StreamSocket(socket), + _pBuffer(0), + _pNext(0), + _pEnd(0) +{ + allocBuffer(); +} + + +DialogSocket::~DialogSocket() +{ + delete [] _pBuffer; +} + + +DialogSocket& DialogSocket::operator = (const Socket& socket) +{ + StreamSocket::operator = (socket); + _pNext = _pBuffer; + _pEnd = _pBuffer; + return *this; +} + + +DialogSocket& DialogSocket::operator = (const DialogSocket& socket) +{ + StreamSocket::operator = (socket); + _pNext = _pBuffer; + _pEnd = _pBuffer; + return *this; +} + + +void DialogSocket::sendByte(unsigned char ch) +{ + sendBytes(&ch, 1); +} + + +void DialogSocket::sendString(const char* str) +{ + sendBytes(str, (int) std::strlen(str)); +} + + +void DialogSocket::sendString(const std::string& str) +{ + sendBytes(str.data(), (int) str.length()); +} + + +void DialogSocket::sendMessage(const std::string& message) +{ + std::string line; + line.reserve(message.length() + 2); + line.append(message); + line.append("\r\n"); + sendString(line); +} + + +void DialogSocket::sendMessage(const std::string& message, const std::string& arg) +{ + std::string line; + line.reserve(message.length() + arg.length() + 3); + line.append(message); + if (!arg.empty()) + { + line.append(" "); + line.append(arg); + } + line.append("\r\n"); + sendString(line); +} + + +void DialogSocket::sendMessage(const std::string& message, const std::string& arg1, const std::string& arg2) +{ + std::string line; + line.reserve(message.length() + arg1.length() +arg2.length() + 4); + line.append(message); + line.append(" "); + line.append(arg1); + if (!arg2.empty()) + { + line.append(" "); + line.append(arg2); + } + line.append("\r\n"); + sendString(line); +} + + +bool DialogSocket::receiveMessage(std::string& message) +{ + message.clear(); + return receiveLine(message, MAX_LINE_LENGTH); +} + + +int DialogSocket::receiveStatusMessage(std::string& message) +{ + message.clear(); + int status = receiveStatusLine(message, MAX_LINE_LENGTH); + if (status < 0) + { + while (status <= 0) + { + message += '\n'; + status = receiveStatusLine(message, message.length() + MAX_LINE_LENGTH); + } + } + return status; +} + + +int DialogSocket::get() +{ + refill(); + if (_pNext != _pEnd) + return std::char_traits<char>::to_int_type(*_pNext++); + else + return EOF_CHAR; +} + + +int DialogSocket::peek() +{ + refill(); + if (_pNext != _pEnd) + return std::char_traits<char>::to_int_type(*_pNext); + else + return EOF_CHAR; +} + + +void DialogSocket::synch() +{ + sendUrgent(TELNET_DM); +} + + +void DialogSocket::sendTelnetCommand(unsigned char command) +{ + unsigned char buffer[2]; + buffer[0] = TELNET_IAC; + buffer[1] = command; + sendBytes(buffer, 2); +} + + +void DialogSocket::sendTelnetCommand(unsigned char command, unsigned char arg) +{ + unsigned char buffer[3]; + buffer[0] = TELNET_IAC; + buffer[1] = command; + buffer[2] = arg; + sendBytes(buffer, 3); +} + + +void DialogSocket::refill() +{ + if (_pNext == _pEnd) + { + int n = receiveBytes(_pBuffer, RECEIVE_BUFFER_SIZE); + if (n > 0) + { + _pNext = _pBuffer; + _pEnd = _pBuffer + n; + } + } +} + + +void DialogSocket::allocBuffer() +{ + _pBuffer = new char [RECEIVE_BUFFER_SIZE]; + _pNext = _pBuffer; + _pEnd = _pBuffer; +} + + +bool DialogSocket::receiveLine(std::string& line, std::size_t lineLengthLimit) +{ + // An old wisdom goes: be strict in what you emit + // and generous in what you accept. + int ch = get(); + while (ch != EOF_CHAR && ch != '\r' && ch != '\n') + { + if (lineLengthLimit == 0 || line.size() < lineLengthLimit) + line += (char) ch; + else + throw Poco::IOException("Line too long"); + ch = get(); + } + if (ch == '\r' && peek() == '\n') + get(); + else if (ch == EOF_CHAR) + return false; + return true; +} + + +int DialogSocket::receiveStatusLine(std::string& line, std::size_t lineLengthLimit) +{ + int status = 0; + int ch = get(); + if (ch != EOF_CHAR) line += (char) ch; + int n = 0; + while (Poco::Ascii::isDigit(ch) && n < 3) + { + status *= 10; + status += ch - '0'; + ++n; + ch = get(); + if (ch != EOF_CHAR) line += (char) ch; + } + if (n == 3) + { + if (ch == '-') + status = -status; + } + else status = 0; + if (ch != EOF_CHAR) receiveLine(line, lineLengthLimit); + return status; +} + + +int DialogSocket::receiveRawBytes(void* buffer, int length) +{ + refill(); + int n = static_cast<int>(_pEnd - _pNext); + if (n > length) n = length; + std::memcpy(buffer, _pNext, n); + _pNext += n; + return n; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/FTPClientSession.cpp b/contrib/libs/poco/Net/src/FTPClientSession.cpp index e0bf448983..ea6870ca49 100644 --- a/contrib/libs/poco/Net/src/FTPClientSession.cpp +++ b/contrib/libs/poco/Net/src/FTPClientSession.cpp @@ -1,599 +1,599 @@ -// -// FTPClientSession.cpp -// -// Library: Net -// Package: FTP -// Module: FTPClientSession -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/FTPClientSession.h" -#include "Poco/Net/SocketAddress.h" -#include "Poco/Net/SocketStream.h" -#include "Poco/Net/ServerSocket.h" -#include "Poco/Net/NetException.h" -#include "Poco/NumberFormatter.h" -#include "Poco/Ascii.h" - - -using Poco::NumberFormatter; - - -namespace Poco { -namespace Net { - - -FTPClientSession::FTPClientSession(): - _port(0), - _pControlSocket(0), - _pDataStream(0), - _passiveMode(true), - _fileType(TYPE_BINARY), - _supports1738(true), - _serverReady(false), - _isLoggedIn(false), - _timeout(DEFAULT_TIMEOUT) -{ -} - - -FTPClientSession::FTPClientSession(const StreamSocket& socket): - _host(socket.address().host().toString()), - _port(socket.address().port()), - _pControlSocket(new DialogSocket(socket)), - _pDataStream(0), - _passiveMode(true), - _fileType(TYPE_BINARY), - _supports1738(true), - _serverReady(false), - _isLoggedIn(false), - _timeout(DEFAULT_TIMEOUT) -{ - _pControlSocket->setReceiveTimeout(_timeout); -} - - -FTPClientSession::FTPClientSession(const std::string& host, - Poco::UInt16 port, - const std::string& username, - const std::string& password): - _host(host), - _port(port), - _pControlSocket(new DialogSocket(SocketAddress(host, port))), - _pDataStream(0), - _passiveMode(true), - _fileType(TYPE_BINARY), - _supports1738(true), - _serverReady(false), - _isLoggedIn(false), - _timeout(DEFAULT_TIMEOUT) -{ - if (!username.empty()) - login(username, password); - else - _pControlSocket->setReceiveTimeout(_timeout); -} - - -FTPClientSession::~FTPClientSession() -{ - try - { - close(); - } - catch (...) - { - } -} - - -void FTPClientSession::setTimeout(const Poco::Timespan& timeout) -{ - if (!isOpen()) - throw FTPException("Connection is closed."); - - _timeout = timeout; - _pControlSocket->setReceiveTimeout(timeout); -} - - -Poco::Timespan FTPClientSession::getTimeout() const -{ - return _timeout; -} - - -void FTPClientSession::setPassive(bool flag, bool useRFC1738) -{ - _passiveMode = flag; - _supports1738 = useRFC1738; -} - - -bool FTPClientSession::getPassive() const -{ - return _passiveMode; -} - - -void FTPClientSession::open(const std::string& host, - Poco::UInt16 port, - const std::string& username, - const std::string& password) -{ - _host = host; - _port = port; - if (!username.empty()) - { - login(username, password); - } - else - { - _pControlSocket = new DialogSocket(SocketAddress(_host, _port)); - _pControlSocket->setReceiveTimeout(_timeout); - } -} - - -void FTPClientSession::login(const std::string& username, const std::string& password) -{ - if (_isLoggedIn) logout(); - - int status = FTP_POSITIVE_COMPLETION * 100; - std::string response; - if (!_pControlSocket) - { - _pControlSocket = new DialogSocket(SocketAddress(_host, _port)); - _pControlSocket->setReceiveTimeout(_timeout); - } - - if (!_serverReady) - { - status = _pControlSocket->receiveStatusMessage(response); - if (!isPositiveCompletion(status)) - throw FTPException("Cannot login to server", response, status); - - _serverReady = true; - } - - status = sendCommand("USER", username, response); - if (isPositiveIntermediate(status)) - status = sendCommand("PASS", password, response); - if (!isPositiveCompletion(status)) - throw FTPException("Login denied", response, status); - - setFileType(_fileType); - _isLoggedIn = true; -} - - -void FTPClientSession::logout() -{ - if (!isOpen()) - throw FTPException("Connection is closed."); - - if (_isLoggedIn) - { - try { endTransfer(); } - catch (...) { } - _isLoggedIn = false; - std::string response; - sendCommand("QUIT", response); - } -} - - -void FTPClientSession::close() -{ - try { logout(); } - catch (...) {} - _serverReady = false; - if (_pControlSocket) - { - _pControlSocket->close(); - delete _pControlSocket; - _pControlSocket = 0; - } -} - - -void FTPClientSession::setFileType(FTPClientSession::FileType type) -{ - std::string response; - int status = sendCommand("TYPE", (type == TYPE_TEXT ? "A" : "I"), response); - if (!isPositiveCompletion(status)) throw FTPException("Cannot set file type", response, status); - _fileType = type; -} - - -FTPClientSession::FileType FTPClientSession::getFileType() const -{ - return _fileType; -} - - -std::string FTPClientSession::systemType() -{ - std::string response; - int status = sendCommand("SYST", response); - if (isPositiveCompletion(status)) - return response.substr(4); - else - throw FTPException("Cannot get remote system type", response, status); -} - - -void FTPClientSession::setWorkingDirectory(const std::string& path) -{ - std::string response; - int status = sendCommand("CWD", path, response); - if (!isPositiveCompletion(status)) - throw FTPException("Cannot change directory", response, status); -} - - -std::string FTPClientSession::getWorkingDirectory() -{ - std::string response; - int status = sendCommand("PWD", response); - if (isPositiveCompletion(status)) - return extractPath(response); - else - throw FTPException("Cannot get current working directory", response, status); -} - - -void FTPClientSession::cdup() -{ - std::string response; - int status = sendCommand("CDUP", response); - if (!isPositiveCompletion(status)) - throw FTPException("Cannot change directory", response, status); -} - - -void FTPClientSession::rename(const std::string& oldName, const std::string& newName) -{ - std::string response; - int status = sendCommand("RNFR", oldName, response); - if (!isPositiveIntermediate(status)) - throw FTPException(std::string("Cannot rename ") + oldName, response, status); - status = sendCommand("RNTO", newName, response); - if (!isPositiveCompletion(status)) - throw FTPException(std::string("Cannot rename to ") + newName, response, status); -} - - -void FTPClientSession::remove(const std::string& path) -{ - std::string response; - int status = sendCommand("DELE", path, response); - if (!isPositiveCompletion(status)) - throw FTPException(std::string("Cannot remove " + path), response, status); -} - - -void FTPClientSession::createDirectory(const std::string& path) -{ - std::string response; - int status = sendCommand("MKD", path, response); - if (!isPositiveCompletion(status)) - throw FTPException(std::string("Cannot create directory ") + path, response, status); -} - - -void FTPClientSession::removeDirectory(const std::string& path) -{ - std::string response; - int status = sendCommand("RMD", path, response); - if (!isPositiveCompletion(status)) - throw FTPException(std::string("Cannot remove directory ") + path, response, status); -} - - -std::istream& FTPClientSession::beginDownload(const std::string& path) -{ - if (!isOpen()) - throw FTPException("Connection is closed."); - - delete _pDataStream; - _pDataStream = 0; - _pDataStream = new SocketStream(establishDataConnection("RETR", path)); - return *_pDataStream; -} - - -void FTPClientSession::endDownload() -{ - endTransfer(); -} - - -std::ostream& FTPClientSession::beginUpload(const std::string& path) -{ - if (!isOpen()) - throw FTPException("Connection is closed."); - - delete _pDataStream; - _pDataStream = 0; - _pDataStream = new SocketStream(establishDataConnection("STOR", path)); - return *_pDataStream; -} - - -void FTPClientSession::endUpload() -{ - endTransfer(); -} - - -std::istream& FTPClientSession::beginList(const std::string& path, bool extended) -{ - if (!isOpen()) - throw FTPException("Connection is closed."); - - delete _pDataStream; - _pDataStream = 0; - _pDataStream = new SocketStream(establishDataConnection(extended ? "LIST" : "NLST", path)); - return *_pDataStream; -} - - -void FTPClientSession::endList() -{ - endTransfer(); -} - - -void FTPClientSession::abort() -{ - if (!isOpen()) - throw FTPException("Connection is closed."); - - _pControlSocket->sendByte(DialogSocket::TELNET_IP); - _pControlSocket->synch(); - std::string response; - int status = sendCommand("ABOR", response); - if (status == 426) - status = _pControlSocket->receiveStatusMessage(response); - if (status != 226) - throw FTPException("Cannot abort transfer", response, status); -} - - -int FTPClientSession::sendCommand(const std::string& command, std::string& response) -{ - if (!isOpen()) - throw FTPException("Connection is closed."); - - _pControlSocket->sendMessage(command); - return _pControlSocket->receiveStatusMessage(response); -} - - -int FTPClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response) -{ - if (!isOpen()) - throw FTPException("Connection is closed."); - - _pControlSocket->sendMessage(command, arg); - return _pControlSocket->receiveStatusMessage(response); -} - - -std::string FTPClientSession::extractPath(const std::string& response) -{ - std::string path; - std::string::const_iterator it = response.begin(); - std::string::const_iterator end = response.end(); - while (it != end && *it != '"') ++it; - if (it != end) - { - ++it; - while (it != end) - { - if (*it == '"') - { - ++it; - if (it == end || (it != end && *it != '"')) break; - } - path += *it++; - } - } - return path; -} - - -StreamSocket FTPClientSession::establishDataConnection(const std::string& command, const std::string& arg) -{ - if (_passiveMode) - return passiveDataConnection(command, arg); - else - return activeDataConnection(command, arg); -} - - -StreamSocket FTPClientSession::activeDataConnection(const std::string& command, const std::string& arg) -{ - if (!isOpen()) - throw FTPException("Connection is closed."); - - ServerSocket server(SocketAddress(_pControlSocket->address().host(), 0)); - sendPortCommand(server.address()); - std::string response; - int status = sendCommand(command, arg, response); - if (!isPositivePreliminary(status)) - throw FTPException(command + " command failed", response, status); - if (server.poll(_timeout, Socket::SELECT_READ)) - return server.acceptConnection(); - else - throw FTPException("The server has not initiated a data connection"); -} - - -StreamSocket FTPClientSession::passiveDataConnection(const std::string& command, const std::string& arg) -{ - SocketAddress sa(sendPassiveCommand()); - StreamSocket sock(sa); - std::string response; - int status = sendCommand(command, arg, response); - if (!isPositivePreliminary(status)) - throw FTPException(command + " command failed", response, status); - return sock; -} - - -void FTPClientSession::sendPortCommand(const SocketAddress& addr) -{ - if (_supports1738) - { - if (sendEPRT(addr)) - return; - else - _supports1738 = false; - } - sendPORT(addr); -} - - -SocketAddress FTPClientSession::sendPassiveCommand() -{ - SocketAddress addr; - if (_supports1738) - { - if (sendEPSV(addr)) - return addr; - else - _supports1738 = false; - } - sendPASV(addr); - return addr; -} - - -bool FTPClientSession::sendEPRT(const SocketAddress& addr) -{ - std::string arg("|"); - arg += addr.af() == AF_INET ? '1' : '2'; - arg += '|'; - arg += addr.host().toString(); - arg += '|'; - arg += NumberFormatter::format(addr.port()); - arg += '|'; - std::string response; - int status = sendCommand("EPRT", arg, response); - if (isPositiveCompletion(status)) - return true; - else if (isPermanentNegative(status)) - return false; - else - throw FTPException("EPRT command failed", response, status); -} - - -void FTPClientSession::sendPORT(const SocketAddress& addr) -{ - std::string arg(addr.host().toString()); - for (std::string::iterator it = arg.begin(); it != arg.end(); ++it) - { - if (*it == '.') *it = ','; - } - arg += ','; - Poco::UInt16 port = addr.port(); - arg += NumberFormatter::format(port/256); - arg += ','; - arg += NumberFormatter::format(port % 256); - std::string response; - int status = sendCommand("PORT", arg, response); +// +// FTPClientSession.cpp +// +// Library: Net +// Package: FTP +// Module: FTPClientSession +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/FTPClientSession.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/Net/SocketStream.h" +#include "Poco/Net/ServerSocket.h" +#include "Poco/Net/NetException.h" +#include "Poco/NumberFormatter.h" +#include "Poco/Ascii.h" + + +using Poco::NumberFormatter; + + +namespace Poco { +namespace Net { + + +FTPClientSession::FTPClientSession(): + _port(0), + _pControlSocket(0), + _pDataStream(0), + _passiveMode(true), + _fileType(TYPE_BINARY), + _supports1738(true), + _serverReady(false), + _isLoggedIn(false), + _timeout(DEFAULT_TIMEOUT) +{ +} + + +FTPClientSession::FTPClientSession(const StreamSocket& socket): + _host(socket.address().host().toString()), + _port(socket.address().port()), + _pControlSocket(new DialogSocket(socket)), + _pDataStream(0), + _passiveMode(true), + _fileType(TYPE_BINARY), + _supports1738(true), + _serverReady(false), + _isLoggedIn(false), + _timeout(DEFAULT_TIMEOUT) +{ + _pControlSocket->setReceiveTimeout(_timeout); +} + + +FTPClientSession::FTPClientSession(const std::string& host, + Poco::UInt16 port, + const std::string& username, + const std::string& password): + _host(host), + _port(port), + _pControlSocket(new DialogSocket(SocketAddress(host, port))), + _pDataStream(0), + _passiveMode(true), + _fileType(TYPE_BINARY), + _supports1738(true), + _serverReady(false), + _isLoggedIn(false), + _timeout(DEFAULT_TIMEOUT) +{ + if (!username.empty()) + login(username, password); + else + _pControlSocket->setReceiveTimeout(_timeout); +} + + +FTPClientSession::~FTPClientSession() +{ + try + { + close(); + } + catch (...) + { + } +} + + +void FTPClientSession::setTimeout(const Poco::Timespan& timeout) +{ + if (!isOpen()) + throw FTPException("Connection is closed."); + + _timeout = timeout; + _pControlSocket->setReceiveTimeout(timeout); +} + + +Poco::Timespan FTPClientSession::getTimeout() const +{ + return _timeout; +} + + +void FTPClientSession::setPassive(bool flag, bool useRFC1738) +{ + _passiveMode = flag; + _supports1738 = useRFC1738; +} + + +bool FTPClientSession::getPassive() const +{ + return _passiveMode; +} + + +void FTPClientSession::open(const std::string& host, + Poco::UInt16 port, + const std::string& username, + const std::string& password) +{ + _host = host; + _port = port; + if (!username.empty()) + { + login(username, password); + } + else + { + _pControlSocket = new DialogSocket(SocketAddress(_host, _port)); + _pControlSocket->setReceiveTimeout(_timeout); + } +} + + +void FTPClientSession::login(const std::string& username, const std::string& password) +{ + if (_isLoggedIn) logout(); + + int status = FTP_POSITIVE_COMPLETION * 100; + std::string response; + if (!_pControlSocket) + { + _pControlSocket = new DialogSocket(SocketAddress(_host, _port)); + _pControlSocket->setReceiveTimeout(_timeout); + } + + if (!_serverReady) + { + status = _pControlSocket->receiveStatusMessage(response); + if (!isPositiveCompletion(status)) + throw FTPException("Cannot login to server", response, status); + + _serverReady = true; + } + + status = sendCommand("USER", username, response); + if (isPositiveIntermediate(status)) + status = sendCommand("PASS", password, response); + if (!isPositiveCompletion(status)) + throw FTPException("Login denied", response, status); + + setFileType(_fileType); + _isLoggedIn = true; +} + + +void FTPClientSession::logout() +{ + if (!isOpen()) + throw FTPException("Connection is closed."); + + if (_isLoggedIn) + { + try { endTransfer(); } + catch (...) { } + _isLoggedIn = false; + std::string response; + sendCommand("QUIT", response); + } +} + + +void FTPClientSession::close() +{ + try { logout(); } + catch (...) {} + _serverReady = false; + if (_pControlSocket) + { + _pControlSocket->close(); + delete _pControlSocket; + _pControlSocket = 0; + } +} + + +void FTPClientSession::setFileType(FTPClientSession::FileType type) +{ + std::string response; + int status = sendCommand("TYPE", (type == TYPE_TEXT ? "A" : "I"), response); + if (!isPositiveCompletion(status)) throw FTPException("Cannot set file type", response, status); + _fileType = type; +} + + +FTPClientSession::FileType FTPClientSession::getFileType() const +{ + return _fileType; +} + + +std::string FTPClientSession::systemType() +{ + std::string response; + int status = sendCommand("SYST", response); + if (isPositiveCompletion(status)) + return response.substr(4); + else + throw FTPException("Cannot get remote system type", response, status); +} + + +void FTPClientSession::setWorkingDirectory(const std::string& path) +{ + std::string response; + int status = sendCommand("CWD", path, response); if (!isPositiveCompletion(status)) - throw FTPException("PORT command failed", response, status); -} - - -bool FTPClientSession::sendEPSV(SocketAddress& addr) -{ - std::string response; - int status = sendCommand("EPSV", response); - if (isPositiveCompletion(status)) - { - parseExtAddress(response, addr); - return true; - } - else if (isPermanentNegative(status)) - { - return false; - } - else throw FTPException("EPSV command failed", response, status); -} - - -void FTPClientSession::sendPASV(SocketAddress& addr) -{ - std::string response; - int status = sendCommand("PASV", response); + throw FTPException("Cannot change directory", response, status); +} + + +std::string FTPClientSession::getWorkingDirectory() +{ + std::string response; + int status = sendCommand("PWD", response); + if (isPositiveCompletion(status)) + return extractPath(response); + else + throw FTPException("Cannot get current working directory", response, status); +} + + +void FTPClientSession::cdup() +{ + std::string response; + int status = sendCommand("CDUP", response); if (!isPositiveCompletion(status)) - throw FTPException("PASV command failed", response, status); - parseAddress(response, addr); -} - - -void FTPClientSession::parseAddress(const std::string& str, SocketAddress& addr) -{ - std::string::const_iterator it = str.begin(); - std::string::const_iterator end = str.end(); - while (it != end && *it != '(') ++it; - if (it != end) ++it; - std::string host; - while (it != end && Poco::Ascii::isDigit(*it)) host += *it++; - if (it != end && *it == ',') { host += '.'; ++it; } - while (it != end && Poco::Ascii::isDigit(*it)) host += *it++; - if (it != end && *it == ',') { host += '.'; ++it; } - while (it != end && Poco::Ascii::isDigit(*it)) host += *it++; - if (it != end && *it == ',') { host += '.'; ++it; } - while (it != end && Poco::Ascii::isDigit(*it)) host += *it++; - if (it != end && *it == ',') ++it; - Poco::UInt16 portHi = 0; - while (it != end && Poco::Ascii::isDigit(*it)) { portHi *= 10; portHi += *it++ - '0'; } - if (it != end && *it == ',') ++it; - Poco::UInt16 portLo = 0; - while (it != end && Poco::Ascii::isDigit(*it)) { portLo *= 10; portLo += *it++ - '0'; } - addr = SocketAddress(host, portHi*256 + portLo); -} - - -void FTPClientSession::parseExtAddress(const std::string& str, SocketAddress& addr) -{ - std::string::const_iterator it = str.begin(); - std::string::const_iterator end = str.end(); - while (it != end && *it != '(') ++it; - if (it != end) ++it; - char delim = '|'; - if (it != end) delim = *it++; - if (it != end && *it == delim) ++it; - if (it != end && *it == delim) ++it; - Poco::UInt16 port = 0; - while (it != end && Poco::Ascii::isDigit(*it)) { port *= 10; port += *it++ - '0'; } - addr = SocketAddress(_pControlSocket->peerAddress().host(), port); -} - - -void FTPClientSession::endTransfer() -{ - if (_pDataStream) - { - delete _pDataStream; - _pDataStream = 0; - std::string response; - int status = _pControlSocket->receiveStatusMessage(response); - if (!isPositiveCompletion(status)) - throw FTPException("Data transfer failed", response, status); - } -} - - -} } // namespace Poco::Net + throw FTPException("Cannot change directory", response, status); +} + + +void FTPClientSession::rename(const std::string& oldName, const std::string& newName) +{ + std::string response; + int status = sendCommand("RNFR", oldName, response); + if (!isPositiveIntermediate(status)) + throw FTPException(std::string("Cannot rename ") + oldName, response, status); + status = sendCommand("RNTO", newName, response); + if (!isPositiveCompletion(status)) + throw FTPException(std::string("Cannot rename to ") + newName, response, status); +} + + +void FTPClientSession::remove(const std::string& path) +{ + std::string response; + int status = sendCommand("DELE", path, response); + if (!isPositiveCompletion(status)) + throw FTPException(std::string("Cannot remove " + path), response, status); +} + + +void FTPClientSession::createDirectory(const std::string& path) +{ + std::string response; + int status = sendCommand("MKD", path, response); + if (!isPositiveCompletion(status)) + throw FTPException(std::string("Cannot create directory ") + path, response, status); +} + + +void FTPClientSession::removeDirectory(const std::string& path) +{ + std::string response; + int status = sendCommand("RMD", path, response); + if (!isPositiveCompletion(status)) + throw FTPException(std::string("Cannot remove directory ") + path, response, status); +} + + +std::istream& FTPClientSession::beginDownload(const std::string& path) +{ + if (!isOpen()) + throw FTPException("Connection is closed."); + + delete _pDataStream; + _pDataStream = 0; + _pDataStream = new SocketStream(establishDataConnection("RETR", path)); + return *_pDataStream; +} + + +void FTPClientSession::endDownload() +{ + endTransfer(); +} + + +std::ostream& FTPClientSession::beginUpload(const std::string& path) +{ + if (!isOpen()) + throw FTPException("Connection is closed."); + + delete _pDataStream; + _pDataStream = 0; + _pDataStream = new SocketStream(establishDataConnection("STOR", path)); + return *_pDataStream; +} + + +void FTPClientSession::endUpload() +{ + endTransfer(); +} + + +std::istream& FTPClientSession::beginList(const std::string& path, bool extended) +{ + if (!isOpen()) + throw FTPException("Connection is closed."); + + delete _pDataStream; + _pDataStream = 0; + _pDataStream = new SocketStream(establishDataConnection(extended ? "LIST" : "NLST", path)); + return *_pDataStream; +} + + +void FTPClientSession::endList() +{ + endTransfer(); +} + + +void FTPClientSession::abort() +{ + if (!isOpen()) + throw FTPException("Connection is closed."); + + _pControlSocket->sendByte(DialogSocket::TELNET_IP); + _pControlSocket->synch(); + std::string response; + int status = sendCommand("ABOR", response); + if (status == 426) + status = _pControlSocket->receiveStatusMessage(response); + if (status != 226) + throw FTPException("Cannot abort transfer", response, status); +} + + +int FTPClientSession::sendCommand(const std::string& command, std::string& response) +{ + if (!isOpen()) + throw FTPException("Connection is closed."); + + _pControlSocket->sendMessage(command); + return _pControlSocket->receiveStatusMessage(response); +} + + +int FTPClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response) +{ + if (!isOpen()) + throw FTPException("Connection is closed."); + + _pControlSocket->sendMessage(command, arg); + return _pControlSocket->receiveStatusMessage(response); +} + + +std::string FTPClientSession::extractPath(const std::string& response) +{ + std::string path; + std::string::const_iterator it = response.begin(); + std::string::const_iterator end = response.end(); + while (it != end && *it != '"') ++it; + if (it != end) + { + ++it; + while (it != end) + { + if (*it == '"') + { + ++it; + if (it == end || (it != end && *it != '"')) break; + } + path += *it++; + } + } + return path; +} + + +StreamSocket FTPClientSession::establishDataConnection(const std::string& command, const std::string& arg) +{ + if (_passiveMode) + return passiveDataConnection(command, arg); + else + return activeDataConnection(command, arg); +} + + +StreamSocket FTPClientSession::activeDataConnection(const std::string& command, const std::string& arg) +{ + if (!isOpen()) + throw FTPException("Connection is closed."); + + ServerSocket server(SocketAddress(_pControlSocket->address().host(), 0)); + sendPortCommand(server.address()); + std::string response; + int status = sendCommand(command, arg, response); + if (!isPositivePreliminary(status)) + throw FTPException(command + " command failed", response, status); + if (server.poll(_timeout, Socket::SELECT_READ)) + return server.acceptConnection(); + else + throw FTPException("The server has not initiated a data connection"); +} + + +StreamSocket FTPClientSession::passiveDataConnection(const std::string& command, const std::string& arg) +{ + SocketAddress sa(sendPassiveCommand()); + StreamSocket sock(sa); + std::string response; + int status = sendCommand(command, arg, response); + if (!isPositivePreliminary(status)) + throw FTPException(command + " command failed", response, status); + return sock; +} + + +void FTPClientSession::sendPortCommand(const SocketAddress& addr) +{ + if (_supports1738) + { + if (sendEPRT(addr)) + return; + else + _supports1738 = false; + } + sendPORT(addr); +} + + +SocketAddress FTPClientSession::sendPassiveCommand() +{ + SocketAddress addr; + if (_supports1738) + { + if (sendEPSV(addr)) + return addr; + else + _supports1738 = false; + } + sendPASV(addr); + return addr; +} + + +bool FTPClientSession::sendEPRT(const SocketAddress& addr) +{ + std::string arg("|"); + arg += addr.af() == AF_INET ? '1' : '2'; + arg += '|'; + arg += addr.host().toString(); + arg += '|'; + arg += NumberFormatter::format(addr.port()); + arg += '|'; + std::string response; + int status = sendCommand("EPRT", arg, response); + if (isPositiveCompletion(status)) + return true; + else if (isPermanentNegative(status)) + return false; + else + throw FTPException("EPRT command failed", response, status); +} + + +void FTPClientSession::sendPORT(const SocketAddress& addr) +{ + std::string arg(addr.host().toString()); + for (std::string::iterator it = arg.begin(); it != arg.end(); ++it) + { + if (*it == '.') *it = ','; + } + arg += ','; + Poco::UInt16 port = addr.port(); + arg += NumberFormatter::format(port/256); + arg += ','; + arg += NumberFormatter::format(port % 256); + std::string response; + int status = sendCommand("PORT", arg, response); + if (!isPositiveCompletion(status)) + throw FTPException("PORT command failed", response, status); +} + + +bool FTPClientSession::sendEPSV(SocketAddress& addr) +{ + std::string response; + int status = sendCommand("EPSV", response); + if (isPositiveCompletion(status)) + { + parseExtAddress(response, addr); + return true; + } + else if (isPermanentNegative(status)) + { + return false; + } + else throw FTPException("EPSV command failed", response, status); +} + + +void FTPClientSession::sendPASV(SocketAddress& addr) +{ + std::string response; + int status = sendCommand("PASV", response); + if (!isPositiveCompletion(status)) + throw FTPException("PASV command failed", response, status); + parseAddress(response, addr); +} + + +void FTPClientSession::parseAddress(const std::string& str, SocketAddress& addr) +{ + std::string::const_iterator it = str.begin(); + std::string::const_iterator end = str.end(); + while (it != end && *it != '(') ++it; + if (it != end) ++it; + std::string host; + while (it != end && Poco::Ascii::isDigit(*it)) host += *it++; + if (it != end && *it == ',') { host += '.'; ++it; } + while (it != end && Poco::Ascii::isDigit(*it)) host += *it++; + if (it != end && *it == ',') { host += '.'; ++it; } + while (it != end && Poco::Ascii::isDigit(*it)) host += *it++; + if (it != end && *it == ',') { host += '.'; ++it; } + while (it != end && Poco::Ascii::isDigit(*it)) host += *it++; + if (it != end && *it == ',') ++it; + Poco::UInt16 portHi = 0; + while (it != end && Poco::Ascii::isDigit(*it)) { portHi *= 10; portHi += *it++ - '0'; } + if (it != end && *it == ',') ++it; + Poco::UInt16 portLo = 0; + while (it != end && Poco::Ascii::isDigit(*it)) { portLo *= 10; portLo += *it++ - '0'; } + addr = SocketAddress(host, portHi*256 + portLo); +} + + +void FTPClientSession::parseExtAddress(const std::string& str, SocketAddress& addr) +{ + std::string::const_iterator it = str.begin(); + std::string::const_iterator end = str.end(); + while (it != end && *it != '(') ++it; + if (it != end) ++it; + char delim = '|'; + if (it != end) delim = *it++; + if (it != end && *it == delim) ++it; + if (it != end && *it == delim) ++it; + Poco::UInt16 port = 0; + while (it != end && Poco::Ascii::isDigit(*it)) { port *= 10; port += *it++ - '0'; } + addr = SocketAddress(_pControlSocket->peerAddress().host(), port); +} + + +void FTPClientSession::endTransfer() +{ + if (_pDataStream) + { + delete _pDataStream; + _pDataStream = 0; + std::string response; + int status = _pControlSocket->receiveStatusMessage(response); + if (!isPositiveCompletion(status)) + throw FTPException("Data transfer failed", response, status); + } +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/FTPStreamFactory.cpp b/contrib/libs/poco/Net/src/FTPStreamFactory.cpp index b557e2f751..f93bb7cfbc 100644 --- a/contrib/libs/poco/Net/src/FTPStreamFactory.cpp +++ b/contrib/libs/poco/Net/src/FTPStreamFactory.cpp @@ -1,243 +1,243 @@ -// -// FTPStreamFactory.cpp -// -// Library: Net -// Package: FTP -// Module: FTPStreamFactory -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/FTPStreamFactory.h" -#include "Poco/Net/FTPClientSession.h" -#include "Poco/Net/NetException.h" -#include "Poco/URI.h" -#include "Poco/URIStreamOpener.h" -#include "Poco/UnbufferedStreamBuf.h" -#include "Poco/Path.h" - - -using Poco::URIStreamFactory; -using Poco::URI; -using Poco::URIStreamOpener; -using Poco::UnbufferedStreamBuf; -using Poco::Path; - - -namespace Poco { -namespace Net { - - -class FTPStreamBuf: public UnbufferedStreamBuf -{ -public: - FTPStreamBuf(std::istream& istr): - _istr(istr) - { - // make sure exceptions from underlying string propagate - _istr.exceptions(std::ios::badbit); - } - - ~FTPStreamBuf() - { - } - -private: - int readFromDevice() - { - return _istr.get(); - } - - std::istream& _istr; -}; - - -class FTPIOS: public virtual std::ios -{ -public: - FTPIOS(std::istream& istr): - _buf(istr) - { - poco_ios_init(&_buf); - } - - ~FTPIOS() - { - } - - FTPStreamBuf* rdbuf() - { - return &_buf; - } - -protected: - FTPStreamBuf _buf; -}; - - -class FTPStream: public FTPIOS, public std::istream -{ -public: - FTPStream(std::istream& istr, FTPClientSession* pSession): - FTPIOS(istr), - std::istream(&_buf), - _pSession(pSession) - { - } - - ~FTPStream() - { - delete _pSession; - } - -private: - FTPClientSession* _pSession; -}; - - -FTPPasswordProvider::FTPPasswordProvider() -{ -} - - -FTPPasswordProvider::~FTPPasswordProvider() -{ -} - - -std::string FTPStreamFactory::_anonymousPassword("poco@localhost"); -FTPPasswordProvider* FTPStreamFactory::_pPasswordProvider(0); - - -FTPStreamFactory::FTPStreamFactory() -{ -} - - -FTPStreamFactory::~FTPStreamFactory() -{ -} - - -std::istream* FTPStreamFactory::open(const URI& uri) -{ - poco_assert (uri.getScheme() == "ftp"); - - FTPClientSession* pSession = new FTPClientSession(uri.getHost(), uri.getPort()); - try - { - std::string username; - std::string password; - getUserInfo(uri, username, password); - - std::string path; - char type; - getPathAndType(uri, path, type); - - pSession->login(username, password); - if (type == 'a') - pSession->setFileType(FTPClientSession::TYPE_TEXT); - - Path p(path, Path::PATH_UNIX); - p.makeFile(); - for (int i = 0; i < p.depth(); ++i) - pSession->setWorkingDirectory(p[i]); - std::string file(p.getFileName()); - std::istream& istr = (type == 'd' ? pSession->beginList(file) : pSession->beginDownload(file)); - return new FTPStream(istr, pSession); - } - catch (...) - { - delete pSession; - throw; - } -} - - -void FTPStreamFactory::setAnonymousPassword(const std::string& password) -{ - _anonymousPassword = password; -} - - -const std::string& FTPStreamFactory::getAnonymousPassword() -{ - return _anonymousPassword; -} - - -void FTPStreamFactory::setPasswordProvider(FTPPasswordProvider* pProvider) -{ - _pPasswordProvider = pProvider; -} - - -FTPPasswordProvider* FTPStreamFactory::getPasswordProvider() -{ - return _pPasswordProvider; -} - - -void FTPStreamFactory::splitUserInfo(const std::string& userInfo, std::string& username, std::string& password) -{ - std::string::size_type pos = userInfo.find(':'); - if (pos != std::string::npos) - { - username.assign(userInfo, 0, pos++); - password.assign(userInfo, pos, userInfo.size() - pos); - } - else username = userInfo; -} - - -void FTPStreamFactory::getUserInfo(const URI& uri, std::string& username, std::string& password) -{ - splitUserInfo(uri.getUserInfo(), username, password); - if (username.empty()) - { - username = "anonymous"; - password = _anonymousPassword; - } - else if (password.empty()) - { - if (_pPasswordProvider) - password = _pPasswordProvider->password(username, uri.getHost()); - else - throw FTPException(std::string("Password required for ") + username + "@" + uri.getHost()); - } -} - - -void FTPStreamFactory::getPathAndType(const Poco::URI& uri, std::string& path, char& type) -{ - path = uri.getPath(); - type = 'i'; - std::string::size_type pos = path.rfind(';'); - if (pos != std::string::npos) - { - if (path.length() == pos + 7 && path.compare(pos + 1, 5, "type=") == 0) - { - type = path[pos + 6]; - path.resize(pos); - } - } -} - - -void FTPStreamFactory::registerFactory() -{ - URIStreamOpener::defaultOpener().registerStreamFactory("ftp", new FTPStreamFactory); -} - - -void FTPStreamFactory::unregisterFactory() -{ - URIStreamOpener::defaultOpener().unregisterStreamFactory("ftp"); -} - - -} } // namespace Poco::Net +// +// FTPStreamFactory.cpp +// +// Library: Net +// Package: FTP +// Module: FTPStreamFactory +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/FTPStreamFactory.h" +#include "Poco/Net/FTPClientSession.h" +#include "Poco/Net/NetException.h" +#include "Poco/URI.h" +#include "Poco/URIStreamOpener.h" +#include "Poco/UnbufferedStreamBuf.h" +#include "Poco/Path.h" + + +using Poco::URIStreamFactory; +using Poco::URI; +using Poco::URIStreamOpener; +using Poco::UnbufferedStreamBuf; +using Poco::Path; + + +namespace Poco { +namespace Net { + + +class FTPStreamBuf: public UnbufferedStreamBuf +{ +public: + FTPStreamBuf(std::istream& istr): + _istr(istr) + { + // make sure exceptions from underlying string propagate + _istr.exceptions(std::ios::badbit); + } + + ~FTPStreamBuf() + { + } + +private: + int readFromDevice() + { + return _istr.get(); + } + + std::istream& _istr; +}; + + +class FTPIOS: public virtual std::ios +{ +public: + FTPIOS(std::istream& istr): + _buf(istr) + { + poco_ios_init(&_buf); + } + + ~FTPIOS() + { + } + + FTPStreamBuf* rdbuf() + { + return &_buf; + } + +protected: + FTPStreamBuf _buf; +}; + + +class FTPStream: public FTPIOS, public std::istream +{ +public: + FTPStream(std::istream& istr, FTPClientSession* pSession): + FTPIOS(istr), + std::istream(&_buf), + _pSession(pSession) + { + } + + ~FTPStream() + { + delete _pSession; + } + +private: + FTPClientSession* _pSession; +}; + + +FTPPasswordProvider::FTPPasswordProvider() +{ +} + + +FTPPasswordProvider::~FTPPasswordProvider() +{ +} + + +std::string FTPStreamFactory::_anonymousPassword("poco@localhost"); +FTPPasswordProvider* FTPStreamFactory::_pPasswordProvider(0); + + +FTPStreamFactory::FTPStreamFactory() +{ +} + + +FTPStreamFactory::~FTPStreamFactory() +{ +} + + +std::istream* FTPStreamFactory::open(const URI& uri) +{ + poco_assert (uri.getScheme() == "ftp"); + + FTPClientSession* pSession = new FTPClientSession(uri.getHost(), uri.getPort()); + try + { + std::string username; + std::string password; + getUserInfo(uri, username, password); + + std::string path; + char type; + getPathAndType(uri, path, type); + + pSession->login(username, password); + if (type == 'a') + pSession->setFileType(FTPClientSession::TYPE_TEXT); + + Path p(path, Path::PATH_UNIX); + p.makeFile(); + for (int i = 0; i < p.depth(); ++i) + pSession->setWorkingDirectory(p[i]); + std::string file(p.getFileName()); + std::istream& istr = (type == 'd' ? pSession->beginList(file) : pSession->beginDownload(file)); + return new FTPStream(istr, pSession); + } + catch (...) + { + delete pSession; + throw; + } +} + + +void FTPStreamFactory::setAnonymousPassword(const std::string& password) +{ + _anonymousPassword = password; +} + + +const std::string& FTPStreamFactory::getAnonymousPassword() +{ + return _anonymousPassword; +} + + +void FTPStreamFactory::setPasswordProvider(FTPPasswordProvider* pProvider) +{ + _pPasswordProvider = pProvider; +} + + +FTPPasswordProvider* FTPStreamFactory::getPasswordProvider() +{ + return _pPasswordProvider; +} + + +void FTPStreamFactory::splitUserInfo(const std::string& userInfo, std::string& username, std::string& password) +{ + std::string::size_type pos = userInfo.find(':'); + if (pos != std::string::npos) + { + username.assign(userInfo, 0, pos++); + password.assign(userInfo, pos, userInfo.size() - pos); + } + else username = userInfo; +} + + +void FTPStreamFactory::getUserInfo(const URI& uri, std::string& username, std::string& password) +{ + splitUserInfo(uri.getUserInfo(), username, password); + if (username.empty()) + { + username = "anonymous"; + password = _anonymousPassword; + } + else if (password.empty()) + { + if (_pPasswordProvider) + password = _pPasswordProvider->password(username, uri.getHost()); + else + throw FTPException(std::string("Password required for ") + username + "@" + uri.getHost()); + } +} + + +void FTPStreamFactory::getPathAndType(const Poco::URI& uri, std::string& path, char& type) +{ + path = uri.getPath(); + type = 'i'; + std::string::size_type pos = path.rfind(';'); + if (pos != std::string::npos) + { + if (path.length() == pos + 7 && path.compare(pos + 1, 5, "type=") == 0) + { + type = path[pos + 6]; + path.resize(pos); + } + } +} + + +void FTPStreamFactory::registerFactory() +{ + URIStreamOpener::defaultOpener().registerStreamFactory("ftp", new FTPStreamFactory); +} + + +void FTPStreamFactory::unregisterFactory() +{ + URIStreamOpener::defaultOpener().unregisterStreamFactory("ftp"); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/FilePartSource.cpp b/contrib/libs/poco/Net/src/FilePartSource.cpp index afd3a01db7..4309136649 100644 --- a/contrib/libs/poco/Net/src/FilePartSource.cpp +++ b/contrib/libs/poco/Net/src/FilePartSource.cpp @@ -1,87 +1,87 @@ -// -// FilePartSource.cpp -// -// Library: Net -// Package: Messages -// Module: FilePartSource -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/FilePartSource.h" -#include "Poco/Path.h" -#include "Poco/File.h" -#include "Poco/Exception.h" - - -using Poco::Path; -using Poco::OpenFileException; - - -namespace Poco { -namespace Net { - - -FilePartSource::FilePartSource(const std::string& path): - _path(path), _istr(path) -{ - Path p(path); - _filename = p.getFileName(); - if (!_istr.good()) - throw OpenFileException(path); -} - - -FilePartSource::FilePartSource(const std::string& path, const std::string& mediaType): - PartSource(mediaType), - _path(path), - _istr(path) -{ - Path p(path); - _filename = p.getFileName(); - if (!_istr.good()) - throw OpenFileException(path); -} - - -FilePartSource::FilePartSource(const std::string& path, const std::string& filename, const std::string& mediaType): - PartSource(mediaType), - _path(path), - _filename(filename), - _istr(path) -{ - Path p(path); - if (!_istr.good()) - throw OpenFileException(path); -} - - -FilePartSource::~FilePartSource() -{ -} - - -std::istream& FilePartSource::stream() -{ - return _istr; -} - - -const std::string& FilePartSource::filename() const -{ - return _filename; -} - - -std::streamsize FilePartSource::getContentLength() const -{ - Poco::File p(_path); - return static_cast<std::streamsize>(p.getSize()); -} - - -} } // namespace Poco::Net +// +// FilePartSource.cpp +// +// Library: Net +// Package: Messages +// Module: FilePartSource +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/FilePartSource.h" +#include "Poco/Path.h" +#include "Poco/File.h" +#include "Poco/Exception.h" + + +using Poco::Path; +using Poco::OpenFileException; + + +namespace Poco { +namespace Net { + + +FilePartSource::FilePartSource(const std::string& path): + _path(path), _istr(path) +{ + Path p(path); + _filename = p.getFileName(); + if (!_istr.good()) + throw OpenFileException(path); +} + + +FilePartSource::FilePartSource(const std::string& path, const std::string& mediaType): + PartSource(mediaType), + _path(path), + _istr(path) +{ + Path p(path); + _filename = p.getFileName(); + if (!_istr.good()) + throw OpenFileException(path); +} + + +FilePartSource::FilePartSource(const std::string& path, const std::string& filename, const std::string& mediaType): + PartSource(mediaType), + _path(path), + _filename(filename), + _istr(path) +{ + Path p(path); + if (!_istr.good()) + throw OpenFileException(path); +} + + +FilePartSource::~FilePartSource() +{ +} + + +std::istream& FilePartSource::stream() +{ + return _istr; +} + + +const std::string& FilePartSource::filename() const +{ + return _filename; +} + + +std::streamsize FilePartSource::getContentLength() const +{ + Poco::File p(_path); + return static_cast<std::streamsize>(p.getSize()); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTMLForm.cpp b/contrib/libs/poco/Net/src/HTMLForm.cpp index 0518bdddd6..65defbe014 100644 --- a/contrib/libs/poco/Net/src/HTMLForm.cpp +++ b/contrib/libs/poco/Net/src/HTMLForm.cpp @@ -1,468 +1,468 @@ -// -// HTMLForm.cpp -// -// Library: Net -// Package: HTML -// Module: HTMLForm -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTMLForm.h" -#include "Poco/Net/HTTPRequest.h" -#include "Poco/Net/PartSource.h" -#include "Poco/Net/PartHandler.h" -#include "Poco/Net/MultipartWriter.h" -#include "Poco/Net/MultipartReader.h" -#include "Poco/Net/NullPartHandler.h" -#include "Poco/Net/NetException.h" -#include "Poco/NullStream.h" -#include "Poco/CountingStream.h" -#include "Poco/StreamCopier.h" -#include "Poco/URI.h" -#include "Poco/String.h" -#include "Poco/CountingStream.h" -#include "Poco/UTF8String.h" -#include <sstream> - - -using Poco::NullInputStream; -using Poco::StreamCopier; -using Poco::SyntaxException; -using Poco::URI; -using Poco::icompare; - - -namespace Poco { -namespace Net { - - -const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded"; -const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data"; -const int HTMLForm::UNKNOWN_CONTENT_LENGTH = -1; - - -class HTMLFormCountingOutputStream: public CountingOutputStream -{ -public: - HTMLFormCountingOutputStream(): - _valid(true) - { - } - - bool isValid() const - { - return _valid; - } - - void setValid(bool v) - { - _valid = v; - } - -private: - bool _valid; -}; - - -HTMLForm::HTMLForm(): - _fieldLimit(DFL_FIELD_LIMIT), - _valueLengthLimit(DFL_MAX_VALUE_LENGTH), - _encoding(ENCODING_URL) -{ -} - - -HTMLForm::HTMLForm(const std::string& encoding): - _fieldLimit(DFL_FIELD_LIMIT), - _valueLengthLimit(DFL_MAX_VALUE_LENGTH), - _encoding(encoding) -{ -} - - -HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler): - _fieldLimit(DFL_FIELD_LIMIT), - _valueLengthLimit(DFL_MAX_VALUE_LENGTH) -{ - load(request, requestBody, handler); -} - - -HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody): - _fieldLimit(DFL_FIELD_LIMIT), - _valueLengthLimit(DFL_MAX_VALUE_LENGTH) -{ - load(request, requestBody); -} - - -HTMLForm::HTMLForm(const HTTPRequest& request): - _fieldLimit(DFL_FIELD_LIMIT), - _valueLengthLimit(DFL_MAX_VALUE_LENGTH) -{ - load(request); -} - - -HTMLForm::~HTMLForm() -{ - for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it) - { - delete it->pSource; - } -} - - -void HTMLForm::setEncoding(const std::string& encoding) -{ - _encoding = encoding; -} - - -void HTMLForm::addPart(const std::string& name, PartSource* pSource) -{ - poco_check_ptr (pSource); - - Part part; - part.name = name; - part.pSource = pSource; - _parts.push_back(part); -} - - -void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler) -{ - clear(); - - URI uri(request.getURI()); - const std::string& query = uri.getRawQuery(); - if (!query.empty()) - { - std::istringstream istr(query); - readUrl(istr); - } - - if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT) - { - std::string mediaType; - NameValueCollection params; - MessageHeader::splitParameters(request.getContentType(), mediaType, params); - _encoding = mediaType; - if (_encoding == ENCODING_MULTIPART) - { - _boundary = params["boundary"]; - readMultipart(requestBody, handler); - } - else - { - readUrl(requestBody); - } - } -} - - -void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody) -{ - NullPartHandler nah; - load(request, requestBody, nah); -} - - -void HTMLForm::load(const HTTPRequest& request) -{ - NullPartHandler nah; - NullInputStream nis; - load(request, nis, nah); -} - - -void HTMLForm::read(std::istream& istr, PartHandler& handler) -{ - if (_encoding == ENCODING_URL) - readUrl(istr); - else - readMultipart(istr, handler); -} - - -void HTMLForm::read(std::istream& istr) -{ - readUrl(istr); -} - - -void HTMLForm::read(const std::string& queryString) -{ - std::istringstream istr(queryString); - readUrl(istr); -} - - -void HTMLForm::prepareSubmit(HTTPRequest& request, int options) -{ - if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT) - { - if (_encoding == ENCODING_URL) - { - request.setContentType(_encoding); - request.setChunkedTransferEncoding(false); - Poco::CountingOutputStream ostr; - writeUrl(ostr); - request.setContentLength(ostr.chars()); - } - else - { - _boundary = MultipartWriter::createBoundary(); - std::string ct(_encoding); - ct.append("; boundary=\""); - ct.append(_boundary); - ct.append("\""); - request.setContentType(ct); - } - if (request.getVersion() == HTTPMessage::HTTP_1_0) - { - request.setKeepAlive(false); - request.setChunkedTransferEncoding(false); - } - else if (_encoding != ENCODING_URL && (options & OPT_USE_CONTENT_LENGTH) == 0) - { - request.setChunkedTransferEncoding(true); - } - if (!request.getChunkedTransferEncoding() && !request.hasContentLength()) - { - request.setContentLength(calculateContentLength()); - } - } - else - { - std::string uri = request.getURI(); - std::ostringstream ostr; - writeUrl(ostr); - uri.append("?"); - uri.append(ostr.str()); - request.setURI(uri); - } -} - - -std::streamsize HTMLForm::calculateContentLength() -{ - if (_encoding == ENCODING_MULTIPART && _boundary.empty()) - throw HTMLFormException("Form must be prepared"); - - HTMLFormCountingOutputStream c; - write(c); - if (c.isValid()) - return c.chars(); - else - return UNKNOWN_CONTENT_LENGTH; -} - - -void HTMLForm::write(std::ostream& ostr, const std::string& boundary) -{ - if (_encoding == ENCODING_URL) - { - writeUrl(ostr); - } - else - { - _boundary = boundary; - writeMultipart(ostr); - } -} - - -void HTMLForm::write(std::ostream& ostr) -{ - if (_encoding == ENCODING_URL) - writeUrl(ostr); - else - writeMultipart(ostr); -} - - -void HTMLForm::readUrl(std::istream& istr) -{ - static const int eof = std::char_traits<char>::eof(); - - int fields = 0; - int ch = istr.get(); - bool isFirst = true; - while (ch != eof) - { - if (_fieldLimit > 0 && fields == _fieldLimit) - throw HTMLFormException("Too many form fields"); - std::string name; - std::string value; - while (ch != eof && ch != '=' && ch != '&') - { - if (ch == '+') ch = ' '; - if (name.size() < MAX_NAME_LENGTH) - name += (char) ch; - else - throw HTMLFormException("Field name too long"); - ch = istr.get(); - } - if (ch == '=') - { - ch = istr.get(); - while (ch != eof && ch != '&') - { - if (ch == '+') ch = ' '; - if (value.size() < _valueLengthLimit) - value += (char) ch; - else - throw HTMLFormException("Field value too long"); - ch = istr.get(); - } - } - // remove UTF-8 byte order mark from first name, if present - if (isFirst) - { - UTF8::removeBOM(name); - } - std::string decodedName; - std::string decodedValue; - URI::decode(name, decodedName); - URI::decode(value, decodedValue); - add(decodedName, decodedValue); - ++fields; - if (ch == '&') ch = istr.get(); - isFirst = false; - } -} - - -void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler) -{ - static const int eof = std::char_traits<char>::eof(); - - int fields = 0; - MultipartReader reader(istr, _boundary); - while (reader.hasNextPart()) - { - if (_fieldLimit > 0 && fields == _fieldLimit) - throw HTMLFormException("Too many form fields"); - MessageHeader header; - reader.nextPart(header); - std::string disp; - NameValueCollection params; - if (header.has("Content-Disposition")) - { - std::string cd = header.get("Content-Disposition"); - MessageHeader::splitParameters(cd, disp, params); - } - if (params.has("filename")) - { - handler.handlePart(header, reader.stream()); - // Ensure that the complete part has been read. - while (reader.stream().good()) reader.stream().get(); - } - else - { - std::string name = params["name"]; - std::string value; - std::istream& input = reader.stream(); - int ch = istr.get(); - while (ch != eof) - { - if (value.size() < _valueLengthLimit) - value += (char) ch; - else - throw HTMLFormException("Field value too long"); - ch = input.get(); - } - add(name, value); - } - ++fields; - } -} - - -void HTMLForm::writeUrl(std::ostream& ostr) -{ - for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it) - { - if (it != begin()) ostr << "&"; - std::string name; - URI::encode(it->first, "!?#/'\",;:$&()[]*+=@", name); - std::string value; - URI::encode(it->second, "!?#/'\",;:$&()[]*+=@", value); - ostr << name << "=" << value; - } -} - - -void HTMLForm::writeMultipart(std::ostream& ostr) -{ - HTMLFormCountingOutputStream* pCountingOutputStream(dynamic_cast<HTMLFormCountingOutputStream*>(&ostr)); - - MultipartWriter writer(ostr, _boundary); - for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it) - { - MessageHeader header; - std::string disp("form-data; name=\""); - disp.append(it->first); - disp.append("\""); - header.set("Content-Disposition", disp); - writer.nextPart(header); - ostr << it->second; - } - for (PartVec::iterator ita = _parts.begin(); ita != _parts.end(); ++ita) - { - MessageHeader header(ita->pSource->headers()); - std::string disp("form-data; name=\""); - disp.append(ita->name); - disp.append("\""); - std::string filename = ita->pSource->filename(); - if (!filename.empty()) - { - disp.append("; filename=\""); - disp.append(filename); - disp.append("\""); - } - header.set("Content-Disposition", disp); - header.set("Content-Type", ita->pSource->mediaType()); - writer.nextPart(header); - if (pCountingOutputStream) - { - // count only, don't move stream position - std::streamsize partlen = ita->pSource->getContentLength(); - if (partlen != PartSource::UNKNOWN_CONTENT_LENGTH) - pCountingOutputStream->addChars(static_cast<int>(partlen)); - else - pCountingOutputStream->setValid(false); - } - else - { - StreamCopier::copyStream(ita->pSource->stream(), ostr); - } - } - writer.close(); - _boundary = writer.boundary(); -} - - -void HTMLForm::setFieldLimit(int limit) -{ - poco_assert (limit >= 0); - - _fieldLimit = limit; -} - - -void HTMLForm::setValueLengthLimit(int limit) -{ - poco_assert (limit >= 0); - - _valueLengthLimit = limit; -} - - -} } // namespace Poco::Net +// +// HTMLForm.cpp +// +// Library: Net +// Package: HTML +// Module: HTMLForm +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTMLForm.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/PartSource.h" +#include "Poco/Net/PartHandler.h" +#include "Poco/Net/MultipartWriter.h" +#include "Poco/Net/MultipartReader.h" +#include "Poco/Net/NullPartHandler.h" +#include "Poco/Net/NetException.h" +#include "Poco/NullStream.h" +#include "Poco/CountingStream.h" +#include "Poco/StreamCopier.h" +#include "Poco/URI.h" +#include "Poco/String.h" +#include "Poco/CountingStream.h" +#include "Poco/UTF8String.h" +#include <sstream> + + +using Poco::NullInputStream; +using Poco::StreamCopier; +using Poco::SyntaxException; +using Poco::URI; +using Poco::icompare; + + +namespace Poco { +namespace Net { + + +const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded"; +const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data"; +const int HTMLForm::UNKNOWN_CONTENT_LENGTH = -1; + + +class HTMLFormCountingOutputStream: public CountingOutputStream +{ +public: + HTMLFormCountingOutputStream(): + _valid(true) + { + } + + bool isValid() const + { + return _valid; + } + + void setValid(bool v) + { + _valid = v; + } + +private: + bool _valid; +}; + + +HTMLForm::HTMLForm(): + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH), + _encoding(ENCODING_URL) +{ +} + + +HTMLForm::HTMLForm(const std::string& encoding): + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH), + _encoding(encoding) +{ +} + + +HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler): + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH) +{ + load(request, requestBody, handler); +} + + +HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody): + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH) +{ + load(request, requestBody); +} + + +HTMLForm::HTMLForm(const HTTPRequest& request): + _fieldLimit(DFL_FIELD_LIMIT), + _valueLengthLimit(DFL_MAX_VALUE_LENGTH) +{ + load(request); +} + + +HTMLForm::~HTMLForm() +{ + for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it) + { + delete it->pSource; + } +} + + +void HTMLForm::setEncoding(const std::string& encoding) +{ + _encoding = encoding; +} + + +void HTMLForm::addPart(const std::string& name, PartSource* pSource) +{ + poco_check_ptr (pSource); + + Part part; + part.name = name; + part.pSource = pSource; + _parts.push_back(part); +} + + +void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler) +{ + clear(); + + URI uri(request.getURI()); + const std::string& query = uri.getRawQuery(); + if (!query.empty()) + { + std::istringstream istr(query); + readUrl(istr); + } + + if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT) + { + std::string mediaType; + NameValueCollection params; + MessageHeader::splitParameters(request.getContentType(), mediaType, params); + _encoding = mediaType; + if (_encoding == ENCODING_MULTIPART) + { + _boundary = params["boundary"]; + readMultipart(requestBody, handler); + } + else + { + readUrl(requestBody); + } + } +} + + +void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody) +{ + NullPartHandler nah; + load(request, requestBody, nah); +} + + +void HTMLForm::load(const HTTPRequest& request) +{ + NullPartHandler nah; + NullInputStream nis; + load(request, nis, nah); +} + + +void HTMLForm::read(std::istream& istr, PartHandler& handler) +{ + if (_encoding == ENCODING_URL) + readUrl(istr); + else + readMultipart(istr, handler); +} + + +void HTMLForm::read(std::istream& istr) +{ + readUrl(istr); +} + + +void HTMLForm::read(const std::string& queryString) +{ + std::istringstream istr(queryString); + readUrl(istr); +} + + +void HTMLForm::prepareSubmit(HTTPRequest& request, int options) +{ + if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT) + { + if (_encoding == ENCODING_URL) + { + request.setContentType(_encoding); + request.setChunkedTransferEncoding(false); + Poco::CountingOutputStream ostr; + writeUrl(ostr); + request.setContentLength(ostr.chars()); + } + else + { + _boundary = MultipartWriter::createBoundary(); + std::string ct(_encoding); + ct.append("; boundary=\""); + ct.append(_boundary); + ct.append("\""); + request.setContentType(ct); + } + if (request.getVersion() == HTTPMessage::HTTP_1_0) + { + request.setKeepAlive(false); + request.setChunkedTransferEncoding(false); + } + else if (_encoding != ENCODING_URL && (options & OPT_USE_CONTENT_LENGTH) == 0) + { + request.setChunkedTransferEncoding(true); + } + if (!request.getChunkedTransferEncoding() && !request.hasContentLength()) + { + request.setContentLength(calculateContentLength()); + } + } + else + { + std::string uri = request.getURI(); + std::ostringstream ostr; + writeUrl(ostr); + uri.append("?"); + uri.append(ostr.str()); + request.setURI(uri); + } +} + + +std::streamsize HTMLForm::calculateContentLength() +{ + if (_encoding == ENCODING_MULTIPART && _boundary.empty()) + throw HTMLFormException("Form must be prepared"); + + HTMLFormCountingOutputStream c; + write(c); + if (c.isValid()) + return c.chars(); + else + return UNKNOWN_CONTENT_LENGTH; +} + + +void HTMLForm::write(std::ostream& ostr, const std::string& boundary) +{ + if (_encoding == ENCODING_URL) + { + writeUrl(ostr); + } + else + { + _boundary = boundary; + writeMultipart(ostr); + } +} + + +void HTMLForm::write(std::ostream& ostr) +{ + if (_encoding == ENCODING_URL) + writeUrl(ostr); + else + writeMultipart(ostr); +} + + +void HTMLForm::readUrl(std::istream& istr) +{ + static const int eof = std::char_traits<char>::eof(); + + int fields = 0; + int ch = istr.get(); + bool isFirst = true; + while (ch != eof) + { + if (_fieldLimit > 0 && fields == _fieldLimit) + throw HTMLFormException("Too many form fields"); + std::string name; + std::string value; + while (ch != eof && ch != '=' && ch != '&') + { + if (ch == '+') ch = ' '; + if (name.size() < MAX_NAME_LENGTH) + name += (char) ch; + else + throw HTMLFormException("Field name too long"); + ch = istr.get(); + } + if (ch == '=') + { + ch = istr.get(); + while (ch != eof && ch != '&') + { + if (ch == '+') ch = ' '; + if (value.size() < _valueLengthLimit) + value += (char) ch; + else + throw HTMLFormException("Field value too long"); + ch = istr.get(); + } + } + // remove UTF-8 byte order mark from first name, if present + if (isFirst) + { + UTF8::removeBOM(name); + } + std::string decodedName; + std::string decodedValue; + URI::decode(name, decodedName); + URI::decode(value, decodedValue); + add(decodedName, decodedValue); + ++fields; + if (ch == '&') ch = istr.get(); + isFirst = false; + } +} + + +void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler) +{ + static const int eof = std::char_traits<char>::eof(); + + int fields = 0; + MultipartReader reader(istr, _boundary); + while (reader.hasNextPart()) + { + if (_fieldLimit > 0 && fields == _fieldLimit) + throw HTMLFormException("Too many form fields"); + MessageHeader header; + reader.nextPart(header); + std::string disp; + NameValueCollection params; + if (header.has("Content-Disposition")) + { + std::string cd = header.get("Content-Disposition"); + MessageHeader::splitParameters(cd, disp, params); + } + if (params.has("filename")) + { + handler.handlePart(header, reader.stream()); + // Ensure that the complete part has been read. + while (reader.stream().good()) reader.stream().get(); + } + else + { + std::string name = params["name"]; + std::string value; + std::istream& input = reader.stream(); + int ch = istr.get(); + while (ch != eof) + { + if (value.size() < _valueLengthLimit) + value += (char) ch; + else + throw HTMLFormException("Field value too long"); + ch = input.get(); + } + add(name, value); + } + ++fields; + } +} + + +void HTMLForm::writeUrl(std::ostream& ostr) +{ + for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it) + { + if (it != begin()) ostr << "&"; + std::string name; + URI::encode(it->first, "!?#/'\",;:$&()[]*+=@", name); + std::string value; + URI::encode(it->second, "!?#/'\",;:$&()[]*+=@", value); + ostr << name << "=" << value; + } +} + + +void HTMLForm::writeMultipart(std::ostream& ostr) +{ + HTMLFormCountingOutputStream* pCountingOutputStream(dynamic_cast<HTMLFormCountingOutputStream*>(&ostr)); + + MultipartWriter writer(ostr, _boundary); + for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it) + { + MessageHeader header; + std::string disp("form-data; name=\""); + disp.append(it->first); + disp.append("\""); + header.set("Content-Disposition", disp); + writer.nextPart(header); + ostr << it->second; + } + for (PartVec::iterator ita = _parts.begin(); ita != _parts.end(); ++ita) + { + MessageHeader header(ita->pSource->headers()); + std::string disp("form-data; name=\""); + disp.append(ita->name); + disp.append("\""); + std::string filename = ita->pSource->filename(); + if (!filename.empty()) + { + disp.append("; filename=\""); + disp.append(filename); + disp.append("\""); + } + header.set("Content-Disposition", disp); + header.set("Content-Type", ita->pSource->mediaType()); + writer.nextPart(header); + if (pCountingOutputStream) + { + // count only, don't move stream position + std::streamsize partlen = ita->pSource->getContentLength(); + if (partlen != PartSource::UNKNOWN_CONTENT_LENGTH) + pCountingOutputStream->addChars(static_cast<int>(partlen)); + else + pCountingOutputStream->setValid(false); + } + else + { + StreamCopier::copyStream(ita->pSource->stream(), ostr); + } + } + writer.close(); + _boundary = writer.boundary(); +} + + +void HTMLForm::setFieldLimit(int limit) +{ + poco_assert (limit >= 0); + + _fieldLimit = limit; +} + + +void HTMLForm::setValueLengthLimit(int limit) +{ + poco_assert (limit >= 0); + + _valueLengthLimit = limit; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPAuthenticationParams.cpp b/contrib/libs/poco/Net/src/HTTPAuthenticationParams.cpp index 1c01ac268f..5d97adcf67 100644 --- a/contrib/libs/poco/Net/src/HTTPAuthenticationParams.cpp +++ b/contrib/libs/poco/Net/src/HTTPAuthenticationParams.cpp @@ -1,316 +1,316 @@ -// -// HTTPAuthenticationParams.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPAuthenticationParams -// -// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru). -// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Exception.h" -#include "Poco/Net/HTTPAuthenticationParams.h" -#include "Poco/Net/HTTPRequest.h" -#include "Poco/Net/HTTPResponse.h" -#include "Poco/Net/NetException.h" -#include "Poco/String.h" -#include "Poco/Ascii.h" - - -using Poco::icompare; -using Poco::Ascii; - - -namespace -{ - bool mustBeQuoted(const std::string& name) - { - return - icompare(name, "cnonce") == 0 || - icompare(name, "domain") == 0 || - icompare(name, "nonce") == 0 || - icompare(name, "opaque") == 0 || - icompare(name, "qop") == 0 || - icompare(name, "realm") == 0 || - icompare(name, "response") == 0 || - icompare(name, "uri") == 0 || - icompare(name, "username") == 0; - } - - - void formatParameter(std::string& result, const std::string& name, const std::string& value) - { - result += name; - result += '='; - if (mustBeQuoted(name)) - { - result += '"'; - result += value; - result += '"'; - } - else - { - result += value; - } - } -} - - -namespace Poco { -namespace Net { - - -const std::string HTTPAuthenticationParams::REALM("realm"); -const std::string HTTPAuthenticationParams::WWW_AUTHENTICATE("WWW-Authenticate"); -const std::string HTTPAuthenticationParams::PROXY_AUTHENTICATE("Proxy-Authenticate"); - - -HTTPAuthenticationParams::HTTPAuthenticationParams() -{ -} - - -HTTPAuthenticationParams::HTTPAuthenticationParams(const std::string& authInfo) -{ - fromAuthInfo(authInfo); -} - - -HTTPAuthenticationParams::HTTPAuthenticationParams(const HTTPRequest& request) -{ - fromRequest(request); -} - - -HTTPAuthenticationParams::HTTPAuthenticationParams(const HTTPResponse& response, const std::string& header) -{ - fromResponse(response, header); -} - - -HTTPAuthenticationParams::~HTTPAuthenticationParams() -{ -} - - -HTTPAuthenticationParams& HTTPAuthenticationParams::operator = (const HTTPAuthenticationParams& authParams) -{ - NameValueCollection::operator = (authParams); - - return *this; -} - - -void HTTPAuthenticationParams::fromAuthInfo(const std::string& authInfo) -{ - parse(authInfo.begin(), authInfo.end()); -} - - -void HTTPAuthenticationParams::fromRequest(const HTTPRequest& request) -{ - std::string scheme; - std::string authInfo; - - request.getCredentials(scheme, authInfo); - - if (icompare(scheme, "Digest") != 0) - throw InvalidArgumentException("Could not parse non-Digest authentication information", scheme); - +// +// HTTPAuthenticationParams.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPAuthenticationParams +// +// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru). +// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Exception.h" +#include "Poco/Net/HTTPAuthenticationParams.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/HTTPResponse.h" +#include "Poco/Net/NetException.h" +#include "Poco/String.h" +#include "Poco/Ascii.h" + + +using Poco::icompare; +using Poco::Ascii; + + +namespace +{ + bool mustBeQuoted(const std::string& name) + { + return + icompare(name, "cnonce") == 0 || + icompare(name, "domain") == 0 || + icompare(name, "nonce") == 0 || + icompare(name, "opaque") == 0 || + icompare(name, "qop") == 0 || + icompare(name, "realm") == 0 || + icompare(name, "response") == 0 || + icompare(name, "uri") == 0 || + icompare(name, "username") == 0; + } + + + void formatParameter(std::string& result, const std::string& name, const std::string& value) + { + result += name; + result += '='; + if (mustBeQuoted(name)) + { + result += '"'; + result += value; + result += '"'; + } + else + { + result += value; + } + } +} + + +namespace Poco { +namespace Net { + + +const std::string HTTPAuthenticationParams::REALM("realm"); +const std::string HTTPAuthenticationParams::WWW_AUTHENTICATE("WWW-Authenticate"); +const std::string HTTPAuthenticationParams::PROXY_AUTHENTICATE("Proxy-Authenticate"); + + +HTTPAuthenticationParams::HTTPAuthenticationParams() +{ +} + + +HTTPAuthenticationParams::HTTPAuthenticationParams(const std::string& authInfo) +{ fromAuthInfo(authInfo); -} - - -void HTTPAuthenticationParams::fromResponse(const HTTPResponse& response, const std::string& header) -{ - NameValueCollection::ConstIterator it = response.find(header); - if (it == response.end()) - throw NotAuthenticatedException("HTTP response has no authentication header"); - - bool found = false; - while (!found && it != response.end() && icompare(it->first, header) == 0) - { - const std::string& header2 = it->second; - if (icompare(header2, 0, 6, "Basic ") == 0) - { - parse(header2.begin() + 6, header2.end()); - found = true; - } - else if (icompare(header2, 0, 7, "Digest ") == 0) - { - parse(header2.begin() + 7, header2.end()); - found = true; - } - ++it; - } - if (!found) throw NotAuthenticatedException("No Basic or Digest authentication header found"); -} - - -const std::string& HTTPAuthenticationParams::getRealm() const -{ - return get(REALM); -} - - -void HTTPAuthenticationParams::setRealm(const std::string& realm) -{ - set(REALM, realm); -} - - -std::string HTTPAuthenticationParams::toString() const -{ - ConstIterator iter = begin(); - std::string result; - - if (iter != end()) - { - formatParameter(result, iter->first, iter->second); - ++iter; - } - - for (; iter != end(); ++iter) - { - result.append(", "); - formatParameter(result, iter->first, iter->second); - } - - return result; -} - - -void HTTPAuthenticationParams::parse(std::string::const_iterator first, std::string::const_iterator last) -{ - enum State - { - STATE_INITIAL = 0x0100, - STATE_FINAL = 0x0200, - - STATE_SPACE = STATE_INITIAL | 0, - STATE_TOKEN = 1, - STATE_EQUALS = 2, - STATE_VALUE = STATE_FINAL | 3, - STATE_VALUE_QUOTED = 4, - STATE_VALUE_ESCAPE = 5, - STATE_COMMA = STATE_FINAL | 6 - }; - - int state = STATE_SPACE; - std::string token; - std::string value; - - for (std::string::const_iterator it = first; it != last; ++it) - { - switch (state) - { - case STATE_SPACE: - if (Ascii::isAlphaNumeric(*it) || *it == '_' || *it == '-') - { - token += *it; - state = STATE_TOKEN; - } - else if (Ascii::isSpace(*it)) - { - // Skip - } - else throw SyntaxException("Invalid authentication information"); - break; - - case STATE_TOKEN: - if (*it == '=') - { - state = STATE_EQUALS; - } - else if (Ascii::isAlphaNumeric(*it) || *it == '_' || *it == '-') - { - token += *it; - } - else throw SyntaxException("Invalid authentication information"); - break; - - case STATE_EQUALS: - if (Ascii::isAlphaNumeric(*it) || *it == '_') - { - value += *it; - state = STATE_VALUE; - } - else if (*it == '"') - { - state = STATE_VALUE_QUOTED; - } - else throw SyntaxException("Invalid authentication information"); - break; - - case STATE_VALUE_QUOTED: - if (*it == '\\') - { - state = STATE_VALUE_ESCAPE; - } - else if (*it == '"') - { - add(token, value); - token.clear(); - value.clear(); - state = STATE_COMMA; - } - else - { - value += *it; - } - break; - - case STATE_VALUE_ESCAPE: - value += *it; - state = STATE_VALUE_QUOTED; - break; - - case STATE_VALUE: - if (Ascii::isSpace(*it)) - { - add(token, value); - token.clear(); - value.clear(); - state = STATE_COMMA; - } - else if (*it == ',') - { - add(token, value); - token.clear(); - value.clear(); - state = STATE_SPACE; - } - else - { - value += *it; - } - break; - - case STATE_COMMA: - if (*it == ',') - { - state = STATE_SPACE; - } - else if (Ascii::isSpace(*it)) - { - // Skip - } - else throw SyntaxException("Invalid authentication information"); - break; - } - } - - if (state == STATE_VALUE) - add(token, value); - - if (!(state & STATE_FINAL)) - throw SyntaxException("Invalid authentication information"); -} - - -} } // namespace Poco::Net +} + + +HTTPAuthenticationParams::HTTPAuthenticationParams(const HTTPRequest& request) +{ + fromRequest(request); +} + + +HTTPAuthenticationParams::HTTPAuthenticationParams(const HTTPResponse& response, const std::string& header) +{ + fromResponse(response, header); +} + + +HTTPAuthenticationParams::~HTTPAuthenticationParams() +{ +} + + +HTTPAuthenticationParams& HTTPAuthenticationParams::operator = (const HTTPAuthenticationParams& authParams) +{ + NameValueCollection::operator = (authParams); + + return *this; +} + + +void HTTPAuthenticationParams::fromAuthInfo(const std::string& authInfo) +{ + parse(authInfo.begin(), authInfo.end()); +} + + +void HTTPAuthenticationParams::fromRequest(const HTTPRequest& request) +{ + std::string scheme; + std::string authInfo; + + request.getCredentials(scheme, authInfo); + + if (icompare(scheme, "Digest") != 0) + throw InvalidArgumentException("Could not parse non-Digest authentication information", scheme); + + fromAuthInfo(authInfo); +} + + +void HTTPAuthenticationParams::fromResponse(const HTTPResponse& response, const std::string& header) +{ + NameValueCollection::ConstIterator it = response.find(header); + if (it == response.end()) + throw NotAuthenticatedException("HTTP response has no authentication header"); + + bool found = false; + while (!found && it != response.end() && icompare(it->first, header) == 0) + { + const std::string& header2 = it->second; + if (icompare(header2, 0, 6, "Basic ") == 0) + { + parse(header2.begin() + 6, header2.end()); + found = true; + } + else if (icompare(header2, 0, 7, "Digest ") == 0) + { + parse(header2.begin() + 7, header2.end()); + found = true; + } + ++it; + } + if (!found) throw NotAuthenticatedException("No Basic or Digest authentication header found"); +} + + +const std::string& HTTPAuthenticationParams::getRealm() const +{ + return get(REALM); +} + + +void HTTPAuthenticationParams::setRealm(const std::string& realm) +{ + set(REALM, realm); +} + + +std::string HTTPAuthenticationParams::toString() const +{ + ConstIterator iter = begin(); + std::string result; + + if (iter != end()) + { + formatParameter(result, iter->first, iter->second); + ++iter; + } + + for (; iter != end(); ++iter) + { + result.append(", "); + formatParameter(result, iter->first, iter->second); + } + + return result; +} + + +void HTTPAuthenticationParams::parse(std::string::const_iterator first, std::string::const_iterator last) +{ + enum State + { + STATE_INITIAL = 0x0100, + STATE_FINAL = 0x0200, + + STATE_SPACE = STATE_INITIAL | 0, + STATE_TOKEN = 1, + STATE_EQUALS = 2, + STATE_VALUE = STATE_FINAL | 3, + STATE_VALUE_QUOTED = 4, + STATE_VALUE_ESCAPE = 5, + STATE_COMMA = STATE_FINAL | 6 + }; + + int state = STATE_SPACE; + std::string token; + std::string value; + + for (std::string::const_iterator it = first; it != last; ++it) + { + switch (state) + { + case STATE_SPACE: + if (Ascii::isAlphaNumeric(*it) || *it == '_' || *it == '-') + { + token += *it; + state = STATE_TOKEN; + } + else if (Ascii::isSpace(*it)) + { + // Skip + } + else throw SyntaxException("Invalid authentication information"); + break; + + case STATE_TOKEN: + if (*it == '=') + { + state = STATE_EQUALS; + } + else if (Ascii::isAlphaNumeric(*it) || *it == '_' || *it == '-') + { + token += *it; + } + else throw SyntaxException("Invalid authentication information"); + break; + + case STATE_EQUALS: + if (Ascii::isAlphaNumeric(*it) || *it == '_') + { + value += *it; + state = STATE_VALUE; + } + else if (*it == '"') + { + state = STATE_VALUE_QUOTED; + } + else throw SyntaxException("Invalid authentication information"); + break; + + case STATE_VALUE_QUOTED: + if (*it == '\\') + { + state = STATE_VALUE_ESCAPE; + } + else if (*it == '"') + { + add(token, value); + token.clear(); + value.clear(); + state = STATE_COMMA; + } + else + { + value += *it; + } + break; + + case STATE_VALUE_ESCAPE: + value += *it; + state = STATE_VALUE_QUOTED; + break; + + case STATE_VALUE: + if (Ascii::isSpace(*it)) + { + add(token, value); + token.clear(); + value.clear(); + state = STATE_COMMA; + } + else if (*it == ',') + { + add(token, value); + token.clear(); + value.clear(); + state = STATE_SPACE; + } + else + { + value += *it; + } + break; + + case STATE_COMMA: + if (*it == ',') + { + state = STATE_SPACE; + } + else if (Ascii::isSpace(*it)) + { + // Skip + } + else throw SyntaxException("Invalid authentication information"); + break; + } + } + + if (state == STATE_VALUE) + add(token, value); + + if (!(state & STATE_FINAL)) + throw SyntaxException("Invalid authentication information"); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPBasicCredentials.cpp b/contrib/libs/poco/Net/src/HTTPBasicCredentials.cpp index 5b5e89897e..dace0afd5e 100644 --- a/contrib/libs/poco/Net/src/HTTPBasicCredentials.cpp +++ b/contrib/libs/poco/Net/src/HTTPBasicCredentials.cpp @@ -1,134 +1,134 @@ -// -// HTTPBasicCredentials.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPBasicCredentials -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPBasicCredentials.h" -#include "Poco/Net/HTTPRequest.h" -#include "Poco/Net/NetException.h" -#include "Poco/Base64Encoder.h" -#include "Poco/Base64Decoder.h" -#include "Poco/String.h" -#include <sstream> - - -using Poco::Base64Decoder; -using Poco::Base64Encoder; -using Poco::icompare; - - -namespace Poco { -namespace Net { - - -const std::string HTTPBasicCredentials::SCHEME = "Basic"; - - -HTTPBasicCredentials::HTTPBasicCredentials() -{ -} - - -HTTPBasicCredentials::HTTPBasicCredentials(const std::string& username, const std::string& password): - _username(username), - _password(password) -{ -} - - -HTTPBasicCredentials::HTTPBasicCredentials(const HTTPRequest& request) -{ - std::string scheme; - std::string authInfo; - request.getCredentials(scheme, authInfo); - if (icompare(scheme, SCHEME) == 0) - { - parseAuthInfo(authInfo); - } - else throw NotAuthenticatedException("Basic authentication expected"); -} - - -HTTPBasicCredentials::HTTPBasicCredentials(const std::string& authInfo) -{ - parseAuthInfo(authInfo); -} - - -HTTPBasicCredentials::~HTTPBasicCredentials() -{ -} - - -void HTTPBasicCredentials::clear() -{ - _username.clear(); - _password.clear(); -} - - -void HTTPBasicCredentials::setUsername(const std::string& username) -{ - _username = username; -} - - -void HTTPBasicCredentials::setPassword(const std::string& password) -{ - _password = password; -} - - -void HTTPBasicCredentials::authenticate(HTTPRequest& request) const -{ - std::ostringstream ostr; - Base64Encoder encoder(ostr); - encoder.rdbuf()->setLineLength(0); - encoder << _username << ":" << _password; - encoder.close(); - request.setCredentials(SCHEME, ostr.str()); -} - - -void HTTPBasicCredentials::proxyAuthenticate(HTTPRequest& request) const -{ - std::ostringstream ostr; - Base64Encoder encoder(ostr); - encoder.rdbuf()->setLineLength(0); - encoder << _username << ":" << _password; - encoder.close(); - request.setProxyCredentials(SCHEME, ostr.str()); -} - - -void HTTPBasicCredentials::parseAuthInfo(const std::string& authInfo) -{ - static const int eof = std::char_traits<char>::eof(); - - std::istringstream istr(authInfo); - Base64Decoder decoder(istr); - int ch = decoder.get(); - while (ch != eof && ch != ':') - { - _username += (char) ch; - ch = decoder.get(); - } - if (ch == ':') ch = decoder.get(); - while (ch != eof) - { - _password += (char) ch; - ch = decoder.get(); - } -} - - -} } // namespace Poco::Net +// +// HTTPBasicCredentials.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPBasicCredentials +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPBasicCredentials.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/NetException.h" +#include "Poco/Base64Encoder.h" +#include "Poco/Base64Decoder.h" +#include "Poco/String.h" +#include <sstream> + + +using Poco::Base64Decoder; +using Poco::Base64Encoder; +using Poco::icompare; + + +namespace Poco { +namespace Net { + + +const std::string HTTPBasicCredentials::SCHEME = "Basic"; + + +HTTPBasicCredentials::HTTPBasicCredentials() +{ +} + + +HTTPBasicCredentials::HTTPBasicCredentials(const std::string& username, const std::string& password): + _username(username), + _password(password) +{ +} + + +HTTPBasicCredentials::HTTPBasicCredentials(const HTTPRequest& request) +{ + std::string scheme; + std::string authInfo; + request.getCredentials(scheme, authInfo); + if (icompare(scheme, SCHEME) == 0) + { + parseAuthInfo(authInfo); + } + else throw NotAuthenticatedException("Basic authentication expected"); +} + + +HTTPBasicCredentials::HTTPBasicCredentials(const std::string& authInfo) +{ + parseAuthInfo(authInfo); +} + + +HTTPBasicCredentials::~HTTPBasicCredentials() +{ +} + + +void HTTPBasicCredentials::clear() +{ + _username.clear(); + _password.clear(); +} + + +void HTTPBasicCredentials::setUsername(const std::string& username) +{ + _username = username; +} + + +void HTTPBasicCredentials::setPassword(const std::string& password) +{ + _password = password; +} + + +void HTTPBasicCredentials::authenticate(HTTPRequest& request) const +{ + std::ostringstream ostr; + Base64Encoder encoder(ostr); + encoder.rdbuf()->setLineLength(0); + encoder << _username << ":" << _password; + encoder.close(); + request.setCredentials(SCHEME, ostr.str()); +} + + +void HTTPBasicCredentials::proxyAuthenticate(HTTPRequest& request) const +{ + std::ostringstream ostr; + Base64Encoder encoder(ostr); + encoder.rdbuf()->setLineLength(0); + encoder << _username << ":" << _password; + encoder.close(); + request.setProxyCredentials(SCHEME, ostr.str()); +} + + +void HTTPBasicCredentials::parseAuthInfo(const std::string& authInfo) +{ + static const int eof = std::char_traits<char>::eof(); + + std::istringstream istr(authInfo); + Base64Decoder decoder(istr); + int ch = decoder.get(); + while (ch != eof && ch != ':') + { + _username += (char) ch; + ch = decoder.get(); + } + if (ch == ':') ch = decoder.get(); + while (ch != eof) + { + _password += (char) ch; + ch = decoder.get(); + } +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPBufferAllocator.cpp b/contrib/libs/poco/Net/src/HTTPBufferAllocator.cpp index 2944e2a612..fdade27b68 100644 --- a/contrib/libs/poco/Net/src/HTTPBufferAllocator.cpp +++ b/contrib/libs/poco/Net/src/HTTPBufferAllocator.cpp @@ -1,44 +1,44 @@ -// -// HTTPBufferAllocator.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPBufferAllocator -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPBufferAllocator.h" - - -using Poco::MemoryPool; - - -namespace Poco { -namespace Net { - - -MemoryPool HTTPBufferAllocator::_pool(HTTPBufferAllocator::BUFFER_SIZE, 16); - - -char* HTTPBufferAllocator::allocate(std::streamsize size) -{ - poco_assert_dbg (size == BUFFER_SIZE); - - return reinterpret_cast<char*>(_pool.get()); -} - - -void HTTPBufferAllocator::deallocate(char* ptr, std::streamsize size) -{ - poco_assert_dbg (size == BUFFER_SIZE); - - _pool.release(ptr); -} - - -} } // namespace Poco::Net +// +// HTTPBufferAllocator.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPBufferAllocator +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPBufferAllocator.h" + + +using Poco::MemoryPool; + + +namespace Poco { +namespace Net { + + +MemoryPool HTTPBufferAllocator::_pool(HTTPBufferAllocator::BUFFER_SIZE, 16); + + +char* HTTPBufferAllocator::allocate(std::streamsize size) +{ + poco_assert_dbg (size == BUFFER_SIZE); + + return reinterpret_cast<char*>(_pool.get()); +} + + +void HTTPBufferAllocator::deallocate(char* ptr, std::streamsize size) +{ + poco_assert_dbg (size == BUFFER_SIZE); + + _pool.release(ptr); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPChunkedStream.cpp b/contrib/libs/poco/Net/src/HTTPChunkedStream.cpp index 5e8da38b9e..f035a978fd 100644 --- a/contrib/libs/poco/Net/src/HTTPChunkedStream.cpp +++ b/contrib/libs/poco/Net/src/HTTPChunkedStream.cpp @@ -1,213 +1,213 @@ -// -// HTTPChunkedStream.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPChunkedStream -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPChunkedStream.h" -#include "Poco/Net/HTTPSession.h" -#include "Poco/NumberFormatter.h" -#include "Poco/NumberParser.h" -#include "Poco/Ascii.h" - - -using Poco::NumberFormatter; -using Poco::NumberParser; - - -namespace Poco { -namespace Net { - - -// -// HTTPChunkedStreamBuf -// - - -HTTPChunkedStreamBuf::HTTPChunkedStreamBuf(HTTPSession& session, openmode mode): - HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode), - _session(session), - _mode(mode), - _chunk(0) -{ -} - - -HTTPChunkedStreamBuf::~HTTPChunkedStreamBuf() -{ -} - - -void HTTPChunkedStreamBuf::close() -{ - if (_mode & std::ios::out) - { - sync(); - _session.write("0\r\n\r\n", 5); - } -} - - -int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length) -{ - static const int eof = std::char_traits<char>::eof(); - - if (_chunk == 0) - { - int ch = _session.get(); - while (Poco::Ascii::isSpace(ch)) ch = _session.get(); - std::string chunkLen; - while (Poco::Ascii::isHexDigit(ch) && chunkLen.size() < 8) { chunkLen += (char) ch; ch = _session.get(); } - if (ch != eof && !(Poco::Ascii::isSpace(ch) || ch == ';')) return eof; - while (ch != eof && ch != '\n') ch = _session.get(); - unsigned chunk; - if (NumberParser::tryParseHex(chunkLen, chunk)) - _chunk = (std::streamsize) chunk; - else - return eof; - } - if (_chunk > 0) - { - if (length > _chunk) length = _chunk; - int n = _session.read(buffer, length); - if (n > 0) _chunk -= n; - return n; - } - else - { - int ch = _session.get(); - while (ch != eof && ch != '\n') ch = _session.get(); - return 0; - } -} - - -int HTTPChunkedStreamBuf::writeToDevice(const char* buffer, std::streamsize length) -{ - _chunkBuffer.clear(); - NumberFormatter::appendHex(_chunkBuffer, length); - _chunkBuffer.append("\r\n", 2); - _chunkBuffer.append(buffer, static_cast<std::string::size_type>(length)); - _chunkBuffer.append("\r\n", 2); - _session.write(_chunkBuffer.data(), static_cast<std::streamsize>(_chunkBuffer.size())); - return static_cast<int>(length); -} - - -// -// HTTPChunkedIOS -// - - -HTTPChunkedIOS::HTTPChunkedIOS(HTTPSession& session, HTTPChunkedStreamBuf::openmode mode): - _buf(session, mode) -{ - poco_ios_init(&_buf); -} - - -HTTPChunkedIOS::~HTTPChunkedIOS() -{ - try - { - _buf.close(); - } - catch (...) - { - } -} - - -HTTPChunkedStreamBuf* HTTPChunkedIOS::rdbuf() -{ - return &_buf; -} - - -// -// HTTPChunkedInputStream -// - - -Poco::MemoryPool HTTPChunkedInputStream::_pool(sizeof(HTTPChunkedInputStream)); - - -HTTPChunkedInputStream::HTTPChunkedInputStream(HTTPSession& session): - HTTPChunkedIOS(session, std::ios::in), - std::istream(&_buf) -{ -} - - -HTTPChunkedInputStream::~HTTPChunkedInputStream() -{ -} - - -void* HTTPChunkedInputStream::operator new(std::size_t /*size*/) -{ - return _pool.get(); -} - - -void HTTPChunkedInputStream::operator delete(void* ptr) -{ - try - { - _pool.release(ptr); - } - catch (...) - { - poco_unexpected(); - } -} - - -// -// HTTPChunkedOutputStream -// - - -Poco::MemoryPool HTTPChunkedOutputStream::_pool(sizeof(HTTPChunkedOutputStream)); - - -HTTPChunkedOutputStream::HTTPChunkedOutputStream(HTTPSession& session): - HTTPChunkedIOS(session, std::ios::out), - std::ostream(&_buf) -{ -} - - -HTTPChunkedOutputStream::~HTTPChunkedOutputStream() -{ -} - - -void* HTTPChunkedOutputStream::operator new(std::size_t /*size*/) -{ - return _pool.get(); -} - - -void HTTPChunkedOutputStream::operator delete(void* ptr) -{ - try - { - _pool.release(ptr); - } - catch (...) - { - poco_unexpected(); - } -} - - -} } // namespace Poco::Net +// +// HTTPChunkedStream.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPChunkedStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPChunkedStream.h" +#include "Poco/Net/HTTPSession.h" +#include "Poco/NumberFormatter.h" +#include "Poco/NumberParser.h" +#include "Poco/Ascii.h" + + +using Poco::NumberFormatter; +using Poco::NumberParser; + + +namespace Poco { +namespace Net { + + +// +// HTTPChunkedStreamBuf +// + + +HTTPChunkedStreamBuf::HTTPChunkedStreamBuf(HTTPSession& session, openmode mode): + HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode), + _session(session), + _mode(mode), + _chunk(0) +{ +} + + +HTTPChunkedStreamBuf::~HTTPChunkedStreamBuf() +{ +} + + +void HTTPChunkedStreamBuf::close() +{ + if (_mode & std::ios::out) + { + sync(); + _session.write("0\r\n\r\n", 5); + } +} + + +int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + static const int eof = std::char_traits<char>::eof(); + + if (_chunk == 0) + { + int ch = _session.get(); + while (Poco::Ascii::isSpace(ch)) ch = _session.get(); + std::string chunkLen; + while (Poco::Ascii::isHexDigit(ch) && chunkLen.size() < 8) { chunkLen += (char) ch; ch = _session.get(); } + if (ch != eof && !(Poco::Ascii::isSpace(ch) || ch == ';')) return eof; + while (ch != eof && ch != '\n') ch = _session.get(); + unsigned chunk; + if (NumberParser::tryParseHex(chunkLen, chunk)) + _chunk = (std::streamsize) chunk; + else + return eof; + } + if (_chunk > 0) + { + if (length > _chunk) length = _chunk; + int n = _session.read(buffer, length); + if (n > 0) _chunk -= n; + return n; + } + else + { + int ch = _session.get(); + while (ch != eof && ch != '\n') ch = _session.get(); + return 0; + } +} + + +int HTTPChunkedStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + _chunkBuffer.clear(); + NumberFormatter::appendHex(_chunkBuffer, length); + _chunkBuffer.append("\r\n", 2); + _chunkBuffer.append(buffer, static_cast<std::string::size_type>(length)); + _chunkBuffer.append("\r\n", 2); + _session.write(_chunkBuffer.data(), static_cast<std::streamsize>(_chunkBuffer.size())); + return static_cast<int>(length); +} + + +// +// HTTPChunkedIOS +// + + +HTTPChunkedIOS::HTTPChunkedIOS(HTTPSession& session, HTTPChunkedStreamBuf::openmode mode): + _buf(session, mode) +{ + poco_ios_init(&_buf); +} + + +HTTPChunkedIOS::~HTTPChunkedIOS() +{ + try + { + _buf.close(); + } + catch (...) + { + } +} + + +HTTPChunkedStreamBuf* HTTPChunkedIOS::rdbuf() +{ + return &_buf; +} + + +// +// HTTPChunkedInputStream +// + + +Poco::MemoryPool HTTPChunkedInputStream::_pool(sizeof(HTTPChunkedInputStream)); + + +HTTPChunkedInputStream::HTTPChunkedInputStream(HTTPSession& session): + HTTPChunkedIOS(session, std::ios::in), + std::istream(&_buf) +{ +} + + +HTTPChunkedInputStream::~HTTPChunkedInputStream() +{ +} + + +void* HTTPChunkedInputStream::operator new(std::size_t /*size*/) +{ + return _pool.get(); +} + + +void HTTPChunkedInputStream::operator delete(void* ptr) +{ + try + { + _pool.release(ptr); + } + catch (...) + { + poco_unexpected(); + } +} + + +// +// HTTPChunkedOutputStream +// + + +Poco::MemoryPool HTTPChunkedOutputStream::_pool(sizeof(HTTPChunkedOutputStream)); + + +HTTPChunkedOutputStream::HTTPChunkedOutputStream(HTTPSession& session): + HTTPChunkedIOS(session, std::ios::out), + std::ostream(&_buf) +{ +} + + +HTTPChunkedOutputStream::~HTTPChunkedOutputStream() +{ +} + + +void* HTTPChunkedOutputStream::operator new(std::size_t /*size*/) +{ + return _pool.get(); +} + + +void HTTPChunkedOutputStream::operator delete(void* ptr) +{ + try + { + _pool.release(ptr); + } + catch (...) + { + poco_unexpected(); + } +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPClientSession.cpp b/contrib/libs/poco/Net/src/HTTPClientSession.cpp index c2b8170343..cca2808b1b 100644 --- a/contrib/libs/poco/Net/src/HTTPClientSession.cpp +++ b/contrib/libs/poco/Net/src/HTTPClientSession.cpp @@ -1,470 +1,470 @@ -// -// HTTPClientSession.cpp -// -// Library: Net -// Package: HTTPClient -// Module: HTTPClientSession -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPClientSession.h" -#include "Poco/Net/HTTPRequest.h" -#include "Poco/Net/HTTPResponse.h" -#include "Poco/Net/HTTPHeaderStream.h" -#include "Poco/Net/HTTPStream.h" -#include "Poco/Net/HTTPFixedLengthStream.h" -#include "Poco/Net/HTTPChunkedStream.h" -#include "Poco/Net/HTTPBasicCredentials.h" -#include "Poco/Net/NetException.h" -#include "Poco/NumberFormatter.h" -#include "Poco/CountingStream.h" -#include "Poco/RegularExpression.h" -#include <sstream> - - -using Poco::NumberFormatter; -using Poco::IllegalStateException; - - -namespace Poco { -namespace Net { - - -HTTPClientSession::ProxyConfig HTTPClientSession::_globalProxyConfig; - - -HTTPClientSession::HTTPClientSession(): - _port(HTTPSession::HTTP_PORT), - _proxyConfig(_globalProxyConfig), - _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0), - _reconnect(false), - _mustReconnect(false), - _expectResponseBody(false), - _responseReceived(false) -{ -} - - -HTTPClientSession::HTTPClientSession(const StreamSocket& socket): - HTTPSession(socket), - _port(HTTPSession::HTTP_PORT), - _proxyConfig(_globalProxyConfig), - _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0), - _reconnect(false), - _mustReconnect(false), - _expectResponseBody(false), - _responseReceived(false) -{ -} - - -HTTPClientSession::HTTPClientSession(const SocketAddress& address): - _host(address.host().toString()), - _port(address.port()), - _proxyConfig(_globalProxyConfig), - _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0), - _reconnect(false), - _mustReconnect(false), - _expectResponseBody(false), - _responseReceived(false) -{ -} - - -HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port): - _host(host), - _port(port), - _proxyConfig(_globalProxyConfig), - _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0), - _reconnect(false), - _mustReconnect(false), - _expectResponseBody(false), - _responseReceived(false) -{ -} - - -HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port, const ProxyConfig& proxyConfig): - _host(host), - _port(port), - _proxyConfig(proxyConfig), - _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0), - _reconnect(false), - _mustReconnect(false), - _expectResponseBody(false), - _responseReceived(false) -{ -} - - -HTTPClientSession::~HTTPClientSession() -{ -} - - -void HTTPClientSession::setHost(const std::string& host) -{ - if (!connected()) - _host = host; - else - throw IllegalStateException("Cannot set the host for an already connected session"); -} - - -void HTTPClientSession::setPort(Poco::UInt16 port) -{ - if (!connected()) - _port = port; - else - throw IllegalStateException("Cannot set the port number for an already connected session"); -} - - -void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port) -{ - if (!connected()) - { - _proxyConfig.host = host; - _proxyConfig.port = port; - } - else throw IllegalStateException("Cannot set the proxy host and port for an already connected session"); -} - - -void HTTPClientSession::setProxyHost(const std::string& host) -{ - if (!connected()) - _proxyConfig.host = host; - else - throw IllegalStateException("Cannot set the proxy host for an already connected session"); -} - - -void HTTPClientSession::setProxyPort(Poco::UInt16 port) -{ - if (!connected()) - _proxyConfig.port = port; - else - throw IllegalStateException("Cannot set the proxy port number for an already connected session"); -} - - -void HTTPClientSession::setProxyCredentials(const std::string& username, const std::string& password) -{ - _proxyConfig.username = username; - _proxyConfig.password = password; -} - - -void HTTPClientSession::setProxyUsername(const std::string& username) -{ - _proxyConfig.username = username; -} - - -void HTTPClientSession::setProxyPassword(const std::string& password) -{ - _proxyConfig.password = password; -} - - -void HTTPClientSession::setProxyConfig(const ProxyConfig& config) -{ - _proxyConfig = config; -} - - -void HTTPClientSession::setGlobalProxyConfig(const ProxyConfig& config) -{ - _globalProxyConfig = config; -} - - -void HTTPClientSession::setKeepAliveTimeout(const Poco::Timespan& timeout) -{ - _keepAliveTimeout = timeout; -} - - -std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request) -{ - _pRequestStream = 0; - _pResponseStream = 0; - clearException(); - _responseReceived = false; - - bool keepAlive = getKeepAlive(); - if (((connected() && !keepAlive) || mustReconnect()) && !_host.empty()) - { - close(); - _mustReconnect = false; - } - try - { - if (!connected()) - reconnect(); - if (!keepAlive) - request.setKeepAlive(false); - if (!request.has(HTTPRequest::HOST) && !_host.empty()) - request.setHost(_host, _port); - if (!_proxyConfig.host.empty() && !bypassProxy()) - { - request.setURI(proxyRequestPrefix() + request.getURI()); - proxyAuthenticate(request); - } - _reconnect = keepAlive; - _expectResponseBody = request.getMethod() != HTTPRequest::HTTP_HEAD; - const std::string& method = request.getMethod(); - if (request.getChunkedTransferEncoding()) - { - HTTPHeaderOutputStream hos(*this); - request.write(hos); - _pRequestStream = new HTTPChunkedOutputStream(*this); - } - else if (request.hasContentLength()) - { - Poco::CountingOutputStream cs; - request.write(cs); -#if POCO_HAVE_INT64 - _pRequestStream = new HTTPFixedLengthOutputStream(*this, request.getContentLength64() + cs.chars()); -#else - _pRequestStream = new HTTPFixedLengthOutputStream(*this, request.getContentLength() + cs.chars()); -#endif - request.write(*_pRequestStream); - } - else if ((method != HTTPRequest::HTTP_PUT && method != HTTPRequest::HTTP_POST && method != HTTPRequest::HTTP_PATCH) || request.has(HTTPRequest::UPGRADE)) - { - Poco::CountingOutputStream cs; - request.write(cs); - _pRequestStream = new HTTPFixedLengthOutputStream(*this, cs.chars()); - request.write(*_pRequestStream); - } - else - { - _pRequestStream = new HTTPOutputStream(*this); - request.write(*_pRequestStream); - } - _lastRequest.update(); - return *_pRequestStream; - } - catch (Exception&) - { - close(); - throw; - } -} - - -void HTTPClientSession::flushRequest() -{ - _pRequestStream = 0; - if (networkException()) networkException()->rethrow(); -} - - -std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response) -{ - flushRequest(); - if (!_responseReceived) - { - do - { - response.clear(); - HTTPHeaderInputStream his(*this); - try - { - response.read(his); - } - catch (Exception&) - { - close(); - if (networkException()) - networkException()->rethrow(); - else - throw; - throw; - } - } - while (response.getStatus() == HTTPResponse::HTTP_CONTINUE); - } - - _mustReconnect = getKeepAlive() && !response.getKeepAlive(); - - if (!_expectResponseBody || response.getStatus() < 200 || response.getStatus() == HTTPResponse::HTTP_NO_CONTENT || response.getStatus() == HTTPResponse::HTTP_NOT_MODIFIED) - _pResponseStream = new HTTPFixedLengthInputStream(*this, 0); - else if (response.getChunkedTransferEncoding()) - _pResponseStream = new HTTPChunkedInputStream(*this); - else if (response.hasContentLength()) -#if defined(POCO_HAVE_INT64) - _pResponseStream = new HTTPFixedLengthInputStream(*this, response.getContentLength64()); -#else - _pResponseStream = new HTTPFixedLengthInputStream(*this, response.getContentLength()); -#endif - else - _pResponseStream = new HTTPInputStream(*this); - - return *_pResponseStream; -} - - -bool HTTPClientSession::peekResponse(HTTPResponse& response) -{ - poco_assert (!_responseReceived); - - _pRequestStream->flush(); - - if (networkException()) networkException()->rethrow(); - - response.clear(); - HTTPHeaderInputStream his(*this); - try - { - response.read(his); - } - catch (Exception&) - { - close(); - if (networkException()) - networkException()->rethrow(); - else - throw; - throw; - } - _responseReceived = response.getStatus() != HTTPResponse::HTTP_CONTINUE; - return !_responseReceived; -} - - -void HTTPClientSession::reset() -{ - close(); -} - - -bool HTTPClientSession::secure() const -{ - return false; -} - - -int HTTPClientSession::write(const char* buffer, std::streamsize length) -{ - try - { - int rc = HTTPSession::write(buffer, length); - _reconnect = false; - return rc; - } - catch (IOException&) - { - if (_reconnect) - { - close(); - reconnect(); - int rc = HTTPSession::write(buffer, length); - clearException(); - _reconnect = false; - return rc; - } - else throw; - } -} - - -void HTTPClientSession::reconnect() -{ - if (_proxyConfig.host.empty() || bypassProxy()) - { - SocketAddress addr(_host, _port); - connect(addr); - } - else - { - SocketAddress addr(_proxyConfig.host, _proxyConfig.port); - connect(addr); - } -} - - -std::string HTTPClientSession::proxyRequestPrefix() const -{ - std::string result("http://"); - result.append(_host); - result.append(":"); - NumberFormatter::append(result, _port); - return result; -} - - -bool HTTPClientSession::mustReconnect() const -{ - if (!_mustReconnect) - { - Poco::Timestamp now; - return _keepAliveTimeout <= now - _lastRequest; - } - else return true; -} - - -void HTTPClientSession::proxyAuthenticate(HTTPRequest& request) -{ - proxyAuthenticateImpl(request); -} - - -void HTTPClientSession::proxyAuthenticateImpl(HTTPRequest& request) -{ - if (!_proxyConfig.username.empty()) - { - HTTPBasicCredentials creds(_proxyConfig.username, _proxyConfig.password); - creds.proxyAuthenticate(request); - } -} - - -StreamSocket HTTPClientSession::proxyConnect() -{ - ProxyConfig emptyProxyConfig; - HTTPClientSession proxySession(getProxyHost(), getProxyPort(), emptyProxyConfig); - proxySession.setTimeout(getTimeout()); - std::string targetAddress(_host); - targetAddress.append(":"); - NumberFormatter::append(targetAddress, _port); - HTTPRequest proxyRequest(HTTPRequest::HTTP_CONNECT, targetAddress, HTTPMessage::HTTP_1_1); - HTTPResponse proxyResponse; - proxyRequest.set("Proxy-Connection", "keep-alive"); - proxyRequest.set("Host", getHost()); - proxyAuthenticateImpl(proxyRequest); - proxySession.setKeepAlive(true); - proxySession.sendRequest(proxyRequest); - proxySession.receiveResponse(proxyResponse); - if (proxyResponse.getStatus() != HTTPResponse::HTTP_OK) - throw HTTPException("Cannot establish proxy connection", proxyResponse.getReason()); - return proxySession.detachSocket(); -} - - -void HTTPClientSession::proxyTunnel() -{ - StreamSocket ss = proxyConnect(); - attachSocket(ss); -} - - -bool HTTPClientSession::bypassProxy() const -{ - if (!_proxyConfig.nonProxyHosts.empty()) - { - return RegularExpression::match(_host, _proxyConfig.nonProxyHosts, RegularExpression::RE_CASELESS | RegularExpression::RE_ANCHORED); - } - else return false; -} - - -} } // namespace Poco::Net +// +// HTTPClientSession.cpp +// +// Library: Net +// Package: HTTPClient +// Module: HTTPClientSession +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPClientSession.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/HTTPResponse.h" +#include "Poco/Net/HTTPHeaderStream.h" +#include "Poco/Net/HTTPStream.h" +#include "Poco/Net/HTTPFixedLengthStream.h" +#include "Poco/Net/HTTPChunkedStream.h" +#include "Poco/Net/HTTPBasicCredentials.h" +#include "Poco/Net/NetException.h" +#include "Poco/NumberFormatter.h" +#include "Poco/CountingStream.h" +#include "Poco/RegularExpression.h" +#include <sstream> + + +using Poco::NumberFormatter; +using Poco::IllegalStateException; + + +namespace Poco { +namespace Net { + + +HTTPClientSession::ProxyConfig HTTPClientSession::_globalProxyConfig; + + +HTTPClientSession::HTTPClientSession(): + _port(HTTPSession::HTTP_PORT), + _proxyConfig(_globalProxyConfig), + _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0), + _reconnect(false), + _mustReconnect(false), + _expectResponseBody(false), + _responseReceived(false) +{ +} + + +HTTPClientSession::HTTPClientSession(const StreamSocket& socket): + HTTPSession(socket), + _port(HTTPSession::HTTP_PORT), + _proxyConfig(_globalProxyConfig), + _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0), + _reconnect(false), + _mustReconnect(false), + _expectResponseBody(false), + _responseReceived(false) +{ +} + + +HTTPClientSession::HTTPClientSession(const SocketAddress& address): + _host(address.host().toString()), + _port(address.port()), + _proxyConfig(_globalProxyConfig), + _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0), + _reconnect(false), + _mustReconnect(false), + _expectResponseBody(false), + _responseReceived(false) +{ +} + + +HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port): + _host(host), + _port(port), + _proxyConfig(_globalProxyConfig), + _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0), + _reconnect(false), + _mustReconnect(false), + _expectResponseBody(false), + _responseReceived(false) +{ +} + + +HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port, const ProxyConfig& proxyConfig): + _host(host), + _port(port), + _proxyConfig(proxyConfig), + _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0), + _reconnect(false), + _mustReconnect(false), + _expectResponseBody(false), + _responseReceived(false) +{ +} + + +HTTPClientSession::~HTTPClientSession() +{ +} + + +void HTTPClientSession::setHost(const std::string& host) +{ + if (!connected()) + _host = host; + else + throw IllegalStateException("Cannot set the host for an already connected session"); +} + + +void HTTPClientSession::setPort(Poco::UInt16 port) +{ + if (!connected()) + _port = port; + else + throw IllegalStateException("Cannot set the port number for an already connected session"); +} + + +void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port) +{ + if (!connected()) + { + _proxyConfig.host = host; + _proxyConfig.port = port; + } + else throw IllegalStateException("Cannot set the proxy host and port for an already connected session"); +} + + +void HTTPClientSession::setProxyHost(const std::string& host) +{ + if (!connected()) + _proxyConfig.host = host; + else + throw IllegalStateException("Cannot set the proxy host for an already connected session"); +} + + +void HTTPClientSession::setProxyPort(Poco::UInt16 port) +{ + if (!connected()) + _proxyConfig.port = port; + else + throw IllegalStateException("Cannot set the proxy port number for an already connected session"); +} + + +void HTTPClientSession::setProxyCredentials(const std::string& username, const std::string& password) +{ + _proxyConfig.username = username; + _proxyConfig.password = password; +} + + +void HTTPClientSession::setProxyUsername(const std::string& username) +{ + _proxyConfig.username = username; +} + + +void HTTPClientSession::setProxyPassword(const std::string& password) +{ + _proxyConfig.password = password; +} + + +void HTTPClientSession::setProxyConfig(const ProxyConfig& config) +{ + _proxyConfig = config; +} + + +void HTTPClientSession::setGlobalProxyConfig(const ProxyConfig& config) +{ + _globalProxyConfig = config; +} + + +void HTTPClientSession::setKeepAliveTimeout(const Poco::Timespan& timeout) +{ + _keepAliveTimeout = timeout; +} + + +std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request) +{ + _pRequestStream = 0; + _pResponseStream = 0; + clearException(); + _responseReceived = false; + + bool keepAlive = getKeepAlive(); + if (((connected() && !keepAlive) || mustReconnect()) && !_host.empty()) + { + close(); + _mustReconnect = false; + } + try + { + if (!connected()) + reconnect(); + if (!keepAlive) + request.setKeepAlive(false); + if (!request.has(HTTPRequest::HOST) && !_host.empty()) + request.setHost(_host, _port); + if (!_proxyConfig.host.empty() && !bypassProxy()) + { + request.setURI(proxyRequestPrefix() + request.getURI()); + proxyAuthenticate(request); + } + _reconnect = keepAlive; + _expectResponseBody = request.getMethod() != HTTPRequest::HTTP_HEAD; + const std::string& method = request.getMethod(); + if (request.getChunkedTransferEncoding()) + { + HTTPHeaderOutputStream hos(*this); + request.write(hos); + _pRequestStream = new HTTPChunkedOutputStream(*this); + } + else if (request.hasContentLength()) + { + Poco::CountingOutputStream cs; + request.write(cs); +#if POCO_HAVE_INT64 + _pRequestStream = new HTTPFixedLengthOutputStream(*this, request.getContentLength64() + cs.chars()); +#else + _pRequestStream = new HTTPFixedLengthOutputStream(*this, request.getContentLength() + cs.chars()); +#endif + request.write(*_pRequestStream); + } + else if ((method != HTTPRequest::HTTP_PUT && method != HTTPRequest::HTTP_POST && method != HTTPRequest::HTTP_PATCH) || request.has(HTTPRequest::UPGRADE)) + { + Poco::CountingOutputStream cs; + request.write(cs); + _pRequestStream = new HTTPFixedLengthOutputStream(*this, cs.chars()); + request.write(*_pRequestStream); + } + else + { + _pRequestStream = new HTTPOutputStream(*this); + request.write(*_pRequestStream); + } + _lastRequest.update(); + return *_pRequestStream; + } + catch (Exception&) + { + close(); + throw; + } +} + + +void HTTPClientSession::flushRequest() +{ + _pRequestStream = 0; + if (networkException()) networkException()->rethrow(); +} + + +std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response) +{ + flushRequest(); + if (!_responseReceived) + { + do + { + response.clear(); + HTTPHeaderInputStream his(*this); + try + { + response.read(his); + } + catch (Exception&) + { + close(); + if (networkException()) + networkException()->rethrow(); + else + throw; + throw; + } + } + while (response.getStatus() == HTTPResponse::HTTP_CONTINUE); + } + + _mustReconnect = getKeepAlive() && !response.getKeepAlive(); + + if (!_expectResponseBody || response.getStatus() < 200 || response.getStatus() == HTTPResponse::HTTP_NO_CONTENT || response.getStatus() == HTTPResponse::HTTP_NOT_MODIFIED) + _pResponseStream = new HTTPFixedLengthInputStream(*this, 0); + else if (response.getChunkedTransferEncoding()) + _pResponseStream = new HTTPChunkedInputStream(*this); + else if (response.hasContentLength()) +#if defined(POCO_HAVE_INT64) + _pResponseStream = new HTTPFixedLengthInputStream(*this, response.getContentLength64()); +#else + _pResponseStream = new HTTPFixedLengthInputStream(*this, response.getContentLength()); +#endif + else + _pResponseStream = new HTTPInputStream(*this); + + return *_pResponseStream; +} + + +bool HTTPClientSession::peekResponse(HTTPResponse& response) +{ + poco_assert (!_responseReceived); + + _pRequestStream->flush(); + + if (networkException()) networkException()->rethrow(); + + response.clear(); + HTTPHeaderInputStream his(*this); + try + { + response.read(his); + } + catch (Exception&) + { + close(); + if (networkException()) + networkException()->rethrow(); + else + throw; + throw; + } + _responseReceived = response.getStatus() != HTTPResponse::HTTP_CONTINUE; + return !_responseReceived; +} + + +void HTTPClientSession::reset() +{ + close(); +} + + +bool HTTPClientSession::secure() const +{ + return false; +} + + +int HTTPClientSession::write(const char* buffer, std::streamsize length) +{ + try + { + int rc = HTTPSession::write(buffer, length); + _reconnect = false; + return rc; + } + catch (IOException&) + { + if (_reconnect) + { + close(); + reconnect(); + int rc = HTTPSession::write(buffer, length); + clearException(); + _reconnect = false; + return rc; + } + else throw; + } +} + + +void HTTPClientSession::reconnect() +{ + if (_proxyConfig.host.empty() || bypassProxy()) + { + SocketAddress addr(_host, _port); + connect(addr); + } + else + { + SocketAddress addr(_proxyConfig.host, _proxyConfig.port); + connect(addr); + } +} + + +std::string HTTPClientSession::proxyRequestPrefix() const +{ + std::string result("http://"); + result.append(_host); + result.append(":"); + NumberFormatter::append(result, _port); + return result; +} + + +bool HTTPClientSession::mustReconnect() const +{ + if (!_mustReconnect) + { + Poco::Timestamp now; + return _keepAliveTimeout <= now - _lastRequest; + } + else return true; +} + + +void HTTPClientSession::proxyAuthenticate(HTTPRequest& request) +{ + proxyAuthenticateImpl(request); +} + + +void HTTPClientSession::proxyAuthenticateImpl(HTTPRequest& request) +{ + if (!_proxyConfig.username.empty()) + { + HTTPBasicCredentials creds(_proxyConfig.username, _proxyConfig.password); + creds.proxyAuthenticate(request); + } +} + + +StreamSocket HTTPClientSession::proxyConnect() +{ + ProxyConfig emptyProxyConfig; + HTTPClientSession proxySession(getProxyHost(), getProxyPort(), emptyProxyConfig); + proxySession.setTimeout(getTimeout()); + std::string targetAddress(_host); + targetAddress.append(":"); + NumberFormatter::append(targetAddress, _port); + HTTPRequest proxyRequest(HTTPRequest::HTTP_CONNECT, targetAddress, HTTPMessage::HTTP_1_1); + HTTPResponse proxyResponse; + proxyRequest.set("Proxy-Connection", "keep-alive"); + proxyRequest.set("Host", getHost()); + proxyAuthenticateImpl(proxyRequest); + proxySession.setKeepAlive(true); + proxySession.sendRequest(proxyRequest); + proxySession.receiveResponse(proxyResponse); + if (proxyResponse.getStatus() != HTTPResponse::HTTP_OK) + throw HTTPException("Cannot establish proxy connection", proxyResponse.getReason()); + return proxySession.detachSocket(); +} + + +void HTTPClientSession::proxyTunnel() +{ + StreamSocket ss = proxyConnect(); + attachSocket(ss); +} + + +bool HTTPClientSession::bypassProxy() const +{ + if (!_proxyConfig.nonProxyHosts.empty()) + { + return RegularExpression::match(_host, _proxyConfig.nonProxyHosts, RegularExpression::RE_CASELESS | RegularExpression::RE_ANCHORED); + } + else return false; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPCookie.cpp b/contrib/libs/poco/Net/src/HTTPCookie.cpp index 9cbae4ad8a..240fb2e452 100644 --- a/contrib/libs/poco/Net/src/HTTPCookie.cpp +++ b/contrib/libs/poco/Net/src/HTTPCookie.cpp @@ -1,343 +1,343 @@ -// -// HTTPCookie.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPCookie -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPCookie.h" -#include "Poco/Net/NameValueCollection.h" -#include "Poco/Timestamp.h" -#include "Poco/DateTime.h" -#include "Poco/DateTimeFormatter.h" -#include "Poco/DateTimeFormat.h" -#include "Poco/DateTimeParser.h" -#include "Poco/NumberFormatter.h" -#include "Poco/NumberParser.h" -#include "Poco/String.h" -#include "Poco/URI.h" - - -using Poco::Timestamp; -using Poco::DateTime; -using Poco::DateTimeFormatter; -using Poco::DateTimeFormat; -using Poco::DateTimeParser; -using Poco::NumberFormatter; -using Poco::NumberParser; -using Poco::icompare; - - -namespace Poco { -namespace Net { - - -HTTPCookie::HTTPCookie(): - _version(0), - _secure(false), - _maxAge(-1), - _httpOnly(false) -{ -} - - -HTTPCookie::HTTPCookie(const std::string& name): - _version(0), - _name(name), - _secure(false), - _maxAge(-1), - _httpOnly(false) -{ -} - - -HTTPCookie::HTTPCookie(const NameValueCollection& nvc): - _version(0), - _secure(false), - _maxAge(-1), - _httpOnly(false) -{ - for (NameValueCollection::ConstIterator it = nvc.begin(); it != nvc.end(); ++it) - { - const std::string& name = it->first; - const std::string& value = it->second; - if (icompare(name, "comment") == 0) - { - setComment(value); - } - else if (icompare(name, "domain") == 0) - { - setDomain(value); - } - else if (icompare(name, "path") == 0) - { - setPath(value); - } - else if (icompare(name, "priority") == 0) - { - setPriority(value); - } - else if (icompare(name, "max-age") == 0) - { - setMaxAge(NumberParser::parse(value)); - } - else if (icompare(name, "secure") == 0) - { - setSecure(true); - } - else if (icompare(name, "expires") == 0) - { - int tzd; - DateTime exp = DateTimeParser::parse(value, tzd); - Timestamp now; - setMaxAge((int) ((exp.timestamp() - now) / Timestamp::resolution())); - } - else if (icompare(name, "version") == 0) - { - setVersion(NumberParser::parse(value)); - } - else if (icompare(name, "HttpOnly") == 0) - { - setHttpOnly(true); - } - else - { - setName(name); - setValue(value); - } - } -} - - -HTTPCookie::HTTPCookie(const std::string& name, const std::string& value): - _version(0), - _name(name), - _value(value), - _secure(false), - _maxAge(-1), - _httpOnly(false) -{ -} - - -HTTPCookie::HTTPCookie(const HTTPCookie& cookie): - _version(cookie._version), - _name(cookie._name), - _value(cookie._value), - _comment(cookie._comment), - _domain(cookie._domain), - _path(cookie._path), - _priority(cookie._priority), - _secure(cookie._secure), - _maxAge(cookie._maxAge), - _httpOnly(cookie._httpOnly) -{ -} - - -HTTPCookie::~HTTPCookie() -{ -} - - -HTTPCookie& HTTPCookie::operator = (const HTTPCookie& cookie) -{ - if (&cookie != this) - { - _version = cookie._version; - _name = cookie._name; - _value = cookie._value; - _comment = cookie._comment; - _domain = cookie._domain; - _path = cookie._path; - _priority = cookie._priority; - _secure = cookie._secure; - _maxAge = cookie._maxAge; - _httpOnly = cookie._httpOnly; - } - return *this; -} - - -void HTTPCookie::setVersion(int version) -{ - _version = version; -} - - -void HTTPCookie::setName(const std::string& name) -{ - _name = name; -} - - -void HTTPCookie::setValue(const std::string& value) -{ - _value = value; -} - - -void HTTPCookie::setComment(const std::string& comment) -{ - _comment = comment; -} - - -void HTTPCookie::setDomain(const std::string& domain) -{ - _domain = domain; -} - - -void HTTPCookie::setPath(const std::string& path) -{ - _path = path; -} - - -void HTTPCookie::setPriority(const std::string& priority) -{ - _priority = priority; -} - - -void HTTPCookie::setSecure(bool secure) -{ - _secure = secure; -} - - -void HTTPCookie::setMaxAge(int maxAge) -{ - _maxAge = maxAge; -} - - -void HTTPCookie::setHttpOnly(bool flag) -{ - _httpOnly = flag; -} - - -std::string HTTPCookie::toString() const -{ - std::string result; - result.reserve(256); - result.append(_name); - result.append("="); - if (_version == 0) - { - // Netscape cookie - result.append(_value); - if (!_domain.empty()) - { - result.append("; domain="); - result.append(_domain); - } - if (!_path.empty()) - { - result.append("; path="); - result.append(_path); - } - if (!_priority.empty()) - { - result.append("; Priority="); - result.append(_priority); - } - if (_maxAge != -1) - { - Timestamp ts; - ts += _maxAge * Timestamp::resolution(); - result.append("; expires="); - DateTimeFormatter::append(result, ts, DateTimeFormat::HTTP_FORMAT); - } - if (_secure) - { - result.append("; secure"); - } - if (_httpOnly) - { - result.append("; HttpOnly"); - } - } - else - { - // RFC 2109 cookie - result.append("\""); - result.append(_value); - result.append("\""); - if (!_comment.empty()) - { - result.append("; Comment=\""); - result.append(_comment); - result.append("\""); - } - if (!_domain.empty()) - { - result.append("; Domain=\""); - result.append(_domain); - result.append("\""); - } - if (!_path.empty()) - { - result.append("; Path=\""); - result.append(_path); - result.append("\""); - } - if (!_priority.empty()) - { - result.append("; Priority=\""); - result.append(_priority); - result.append("\""); - } - - if (_maxAge != -1) - { - result.append("; Max-Age=\""); - NumberFormatter::append(result, _maxAge); - result.append("\""); - } - if (_secure) - { - result.append("; secure"); - } - if (_httpOnly) - { - result.append("; HttpOnly"); - } - result.append("; Version=\"1\""); - } - return result; -} - - -namespace -{ - static const std::string ILLEGAL_CHARS("()[]/|\\',;"); -} - - -std::string HTTPCookie::escape(const std::string& str) -{ - std::string result; - Poco::URI::encode(str, ILLEGAL_CHARS, result); - return result; -} - - -std::string HTTPCookie::unescape(const std::string& str) -{ - std::string result; - Poco::URI::decode(str, result); - return result; -} - - -} } // namespace Poco::Net +// +// HTTPCookie.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPCookie +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPCookie.h" +#include "Poco/Net/NameValueCollection.h" +#include "Poco/Timestamp.h" +#include "Poco/DateTime.h" +#include "Poco/DateTimeFormatter.h" +#include "Poco/DateTimeFormat.h" +#include "Poco/DateTimeParser.h" +#include "Poco/NumberFormatter.h" +#include "Poco/NumberParser.h" +#include "Poco/String.h" +#include "Poco/URI.h" + + +using Poco::Timestamp; +using Poco::DateTime; +using Poco::DateTimeFormatter; +using Poco::DateTimeFormat; +using Poco::DateTimeParser; +using Poco::NumberFormatter; +using Poco::NumberParser; +using Poco::icompare; + + +namespace Poco { +namespace Net { + + +HTTPCookie::HTTPCookie(): + _version(0), + _secure(false), + _maxAge(-1), + _httpOnly(false) +{ +} + + +HTTPCookie::HTTPCookie(const std::string& name): + _version(0), + _name(name), + _secure(false), + _maxAge(-1), + _httpOnly(false) +{ +} + + +HTTPCookie::HTTPCookie(const NameValueCollection& nvc): + _version(0), + _secure(false), + _maxAge(-1), + _httpOnly(false) +{ + for (NameValueCollection::ConstIterator it = nvc.begin(); it != nvc.end(); ++it) + { + const std::string& name = it->first; + const std::string& value = it->second; + if (icompare(name, "comment") == 0) + { + setComment(value); + } + else if (icompare(name, "domain") == 0) + { + setDomain(value); + } + else if (icompare(name, "path") == 0) + { + setPath(value); + } + else if (icompare(name, "priority") == 0) + { + setPriority(value); + } + else if (icompare(name, "max-age") == 0) + { + setMaxAge(NumberParser::parse(value)); + } + else if (icompare(name, "secure") == 0) + { + setSecure(true); + } + else if (icompare(name, "expires") == 0) + { + int tzd; + DateTime exp = DateTimeParser::parse(value, tzd); + Timestamp now; + setMaxAge((int) ((exp.timestamp() - now) / Timestamp::resolution())); + } + else if (icompare(name, "version") == 0) + { + setVersion(NumberParser::parse(value)); + } + else if (icompare(name, "HttpOnly") == 0) + { + setHttpOnly(true); + } + else + { + setName(name); + setValue(value); + } + } +} + + +HTTPCookie::HTTPCookie(const std::string& name, const std::string& value): + _version(0), + _name(name), + _value(value), + _secure(false), + _maxAge(-1), + _httpOnly(false) +{ +} + + +HTTPCookie::HTTPCookie(const HTTPCookie& cookie): + _version(cookie._version), + _name(cookie._name), + _value(cookie._value), + _comment(cookie._comment), + _domain(cookie._domain), + _path(cookie._path), + _priority(cookie._priority), + _secure(cookie._secure), + _maxAge(cookie._maxAge), + _httpOnly(cookie._httpOnly) +{ +} + + +HTTPCookie::~HTTPCookie() +{ +} + + +HTTPCookie& HTTPCookie::operator = (const HTTPCookie& cookie) +{ + if (&cookie != this) + { + _version = cookie._version; + _name = cookie._name; + _value = cookie._value; + _comment = cookie._comment; + _domain = cookie._domain; + _path = cookie._path; + _priority = cookie._priority; + _secure = cookie._secure; + _maxAge = cookie._maxAge; + _httpOnly = cookie._httpOnly; + } + return *this; +} + + +void HTTPCookie::setVersion(int version) +{ + _version = version; +} + + +void HTTPCookie::setName(const std::string& name) +{ + _name = name; +} + + +void HTTPCookie::setValue(const std::string& value) +{ + _value = value; +} + + +void HTTPCookie::setComment(const std::string& comment) +{ + _comment = comment; +} + + +void HTTPCookie::setDomain(const std::string& domain) +{ + _domain = domain; +} + + +void HTTPCookie::setPath(const std::string& path) +{ + _path = path; +} + + +void HTTPCookie::setPriority(const std::string& priority) +{ + _priority = priority; +} + + +void HTTPCookie::setSecure(bool secure) +{ + _secure = secure; +} + + +void HTTPCookie::setMaxAge(int maxAge) +{ + _maxAge = maxAge; +} + + +void HTTPCookie::setHttpOnly(bool flag) +{ + _httpOnly = flag; +} + + +std::string HTTPCookie::toString() const +{ + std::string result; + result.reserve(256); + result.append(_name); + result.append("="); + if (_version == 0) + { + // Netscape cookie + result.append(_value); + if (!_domain.empty()) + { + result.append("; domain="); + result.append(_domain); + } + if (!_path.empty()) + { + result.append("; path="); + result.append(_path); + } + if (!_priority.empty()) + { + result.append("; Priority="); + result.append(_priority); + } + if (_maxAge != -1) + { + Timestamp ts; + ts += _maxAge * Timestamp::resolution(); + result.append("; expires="); + DateTimeFormatter::append(result, ts, DateTimeFormat::HTTP_FORMAT); + } + if (_secure) + { + result.append("; secure"); + } + if (_httpOnly) + { + result.append("; HttpOnly"); + } + } + else + { + // RFC 2109 cookie + result.append("\""); + result.append(_value); + result.append("\""); + if (!_comment.empty()) + { + result.append("; Comment=\""); + result.append(_comment); + result.append("\""); + } + if (!_domain.empty()) + { + result.append("; Domain=\""); + result.append(_domain); + result.append("\""); + } + if (!_path.empty()) + { + result.append("; Path=\""); + result.append(_path); + result.append("\""); + } + if (!_priority.empty()) + { + result.append("; Priority=\""); + result.append(_priority); + result.append("\""); + } + + if (_maxAge != -1) + { + result.append("; Max-Age=\""); + NumberFormatter::append(result, _maxAge); + result.append("\""); + } + if (_secure) + { + result.append("; secure"); + } + if (_httpOnly) + { + result.append("; HttpOnly"); + } + result.append("; Version=\"1\""); + } + return result; +} + + +namespace +{ + static const std::string ILLEGAL_CHARS("()[]/|\\',;"); +} + + +std::string HTTPCookie::escape(const std::string& str) +{ + std::string result; + Poco::URI::encode(str, ILLEGAL_CHARS, result); + return result; +} + + +std::string HTTPCookie::unescape(const std::string& str) +{ + std::string result; + Poco::URI::decode(str, result); + return result; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPCredentials.cpp b/contrib/libs/poco/Net/src/HTTPCredentials.cpp index ae1d6ea0b6..36a314f246 100644 --- a/contrib/libs/poco/Net/src/HTTPCredentials.cpp +++ b/contrib/libs/poco/Net/src/HTTPCredentials.cpp @@ -1,208 +1,208 @@ -// -// HTTPCredentials.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPCredentials -// -// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru). -// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPAuthenticationParams.h" -#include "Poco/Net/HTTPBasicCredentials.h" -#include "Poco/Net/HTTPCredentials.h" -#include "Poco/Net/HTTPRequest.h" -#include "Poco/Net/HTTPResponse.h" -#include "Poco/Net/NetException.h" -#include "Poco/String.h" -#include "Poco/Ascii.h" -#include "Poco/URI.h" - - -using Poco::icompare; - - -namespace Poco { -namespace Net { - - -HTTPCredentials::HTTPCredentials() -{ -} - - -HTTPCredentials::HTTPCredentials(const std::string& username, const std::string& password): - _digest(username, password) -{ -} - - -HTTPCredentials::~HTTPCredentials() -{ -} - - -void HTTPCredentials::fromUserInfo(const std::string& userInfo) -{ - std::string username; - std::string password; - - extractCredentials(userInfo, username, password); - setUsername(username); - setPassword(password); - _digest.reset(); -} - - -void HTTPCredentials::fromURI(const URI& uri) -{ - std::string username; - std::string password; - - extractCredentials(uri, username, password); - setUsername(username); - setPassword(password); - _digest.reset(); -} - - -void HTTPCredentials::authenticate(HTTPRequest& request, const HTTPResponse& response) -{ - for (HTTPResponse::ConstIterator iter = response.find(HTTPAuthenticationParams::WWW_AUTHENTICATE); iter != response.end(); ++iter) - { - if (isBasicCredentials(iter->second)) - { - HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).authenticate(request); - return; +// +// HTTPCredentials.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPCredentials +// +// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru). +// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPAuthenticationParams.h" +#include "Poco/Net/HTTPBasicCredentials.h" +#include "Poco/Net/HTTPCredentials.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/HTTPResponse.h" +#include "Poco/Net/NetException.h" +#include "Poco/String.h" +#include "Poco/Ascii.h" +#include "Poco/URI.h" + + +using Poco::icompare; + + +namespace Poco { +namespace Net { + + +HTTPCredentials::HTTPCredentials() +{ +} + + +HTTPCredentials::HTTPCredentials(const std::string& username, const std::string& password): + _digest(username, password) +{ +} + + +HTTPCredentials::~HTTPCredentials() +{ +} + + +void HTTPCredentials::fromUserInfo(const std::string& userInfo) +{ + std::string username; + std::string password; + + extractCredentials(userInfo, username, password); + setUsername(username); + setPassword(password); + _digest.reset(); +} + + +void HTTPCredentials::fromURI(const URI& uri) +{ + std::string username; + std::string password; + + extractCredentials(uri, username, password); + setUsername(username); + setPassword(password); + _digest.reset(); +} + + +void HTTPCredentials::authenticate(HTTPRequest& request, const HTTPResponse& response) +{ + for (HTTPResponse::ConstIterator iter = response.find(HTTPAuthenticationParams::WWW_AUTHENTICATE); iter != response.end(); ++iter) + { + if (isBasicCredentials(iter->second)) + { + HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).authenticate(request); + return; + } + else if (isDigestCredentials(iter->second)) + { + _digest.authenticate(request, HTTPAuthenticationParams(iter->second.substr(7))); + return; } - else if (isDigestCredentials(iter->second)) - { - _digest.authenticate(request, HTTPAuthenticationParams(iter->second.substr(7))); - return; - } - } -} - - -void HTTPCredentials::updateAuthInfo(HTTPRequest& request) -{ - if (request.has(HTTPRequest::AUTHORIZATION)) - { - const std::string& authorization = request.get(HTTPRequest::AUTHORIZATION); - - if (isBasicCredentials(authorization)) - { - HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).authenticate(request); + } +} + + +void HTTPCredentials::updateAuthInfo(HTTPRequest& request) +{ + if (request.has(HTTPRequest::AUTHORIZATION)) + { + const std::string& authorization = request.get(HTTPRequest::AUTHORIZATION); + + if (isBasicCredentials(authorization)) + { + HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).authenticate(request); + } + else if (isDigestCredentials(authorization)) + { + _digest.updateAuthInfo(request); } - else if (isDigestCredentials(authorization)) - { - _digest.updateAuthInfo(request); - } - } -} - - -void HTTPCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response) -{ - for (HTTPResponse::ConstIterator iter = response.find(HTTPAuthenticationParams::PROXY_AUTHENTICATE); iter != response.end(); ++iter) - { - if (isBasicCredentials(iter->second)) - { - HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).proxyAuthenticate(request); - return; + } +} + + +void HTTPCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response) +{ + for (HTTPResponse::ConstIterator iter = response.find(HTTPAuthenticationParams::PROXY_AUTHENTICATE); iter != response.end(); ++iter) + { + if (isBasicCredentials(iter->second)) + { + HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).proxyAuthenticate(request); + return; + } + else if (isDigestCredentials(iter->second)) + { + _digest.proxyAuthenticate(request, HTTPAuthenticationParams(iter->second.substr(7))); + return; } - else if (isDigestCredentials(iter->second)) - { - _digest.proxyAuthenticate(request, HTTPAuthenticationParams(iter->second.substr(7))); - return; - } - } -} - - -void HTTPCredentials::updateProxyAuthInfo(HTTPRequest& request) -{ - if (request.has(HTTPRequest::PROXY_AUTHORIZATION)) - { - const std::string& authorization = request.get(HTTPRequest::PROXY_AUTHORIZATION); - - if (isBasicCredentials(authorization)) - { - HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).proxyAuthenticate(request); + } +} + + +void HTTPCredentials::updateProxyAuthInfo(HTTPRequest& request) +{ + if (request.has(HTTPRequest::PROXY_AUTHORIZATION)) + { + const std::string& authorization = request.get(HTTPRequest::PROXY_AUTHORIZATION); + + if (isBasicCredentials(authorization)) + { + HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).proxyAuthenticate(request); + } + else if (isDigestCredentials(authorization)) + { + _digest.updateProxyAuthInfo(request); } - else if (isDigestCredentials(authorization)) - { - _digest.updateProxyAuthInfo(request); - } - } -} - - -bool HTTPCredentials::isBasicCredentials(const std::string& header) -{ - return icompare(header, 0, 5, "Basic") == 0 && (header.size() > 5 ? Poco::Ascii::isSpace(header[5]) : true); -} - - -bool HTTPCredentials::isDigestCredentials(const std::string& header) -{ - return icompare(header, 0, 6, "Digest") == 0 && (header.size() > 6 ? Poco::Ascii::isSpace(header[6]) : true); -} - - -bool HTTPCredentials::hasBasicCredentials(const HTTPRequest& request) -{ - return request.has(HTTPRequest::AUTHORIZATION) && isBasicCredentials(request.get(HTTPRequest::AUTHORIZATION)); -} - - -bool HTTPCredentials::hasDigestCredentials(const HTTPRequest& request) -{ - return request.has(HTTPRequest::AUTHORIZATION) && isDigestCredentials(request.get(HTTPRequest::AUTHORIZATION)); -} - - -bool HTTPCredentials::hasProxyBasicCredentials(const HTTPRequest& request) -{ - return request.has(HTTPRequest::PROXY_AUTHORIZATION) && isBasicCredentials(request.get(HTTPRequest::PROXY_AUTHORIZATION)); -} - - -bool HTTPCredentials::hasProxyDigestCredentials(const HTTPRequest& request) -{ - return request.has(HTTPRequest::PROXY_AUTHORIZATION) && isDigestCredentials(request.get(HTTPRequest::PROXY_AUTHORIZATION)); -} - - -void HTTPCredentials::extractCredentials(const std::string& userInfo, std::string& username, std::string& password) -{ - const std::string::size_type p = userInfo.find(':'); - - if (p != std::string::npos) - { - username.assign(userInfo, 0, p); - password.assign(userInfo, p + 1, std::string::npos); } - else - { - username.assign(userInfo); - password.clear(); - } -} - - -void HTTPCredentials::extractCredentials(const Poco::URI& uri, std::string& username, std::string& password) -{ - if (!uri.getUserInfo().empty()) - { - extractCredentials(uri.getUserInfo(), username, password); - } -} - - -} } // namespace Poco::Net +} + + +bool HTTPCredentials::isBasicCredentials(const std::string& header) +{ + return icompare(header, 0, 5, "Basic") == 0 && (header.size() > 5 ? Poco::Ascii::isSpace(header[5]) : true); +} + + +bool HTTPCredentials::isDigestCredentials(const std::string& header) +{ + return icompare(header, 0, 6, "Digest") == 0 && (header.size() > 6 ? Poco::Ascii::isSpace(header[6]) : true); +} + + +bool HTTPCredentials::hasBasicCredentials(const HTTPRequest& request) +{ + return request.has(HTTPRequest::AUTHORIZATION) && isBasicCredentials(request.get(HTTPRequest::AUTHORIZATION)); +} + + +bool HTTPCredentials::hasDigestCredentials(const HTTPRequest& request) +{ + return request.has(HTTPRequest::AUTHORIZATION) && isDigestCredentials(request.get(HTTPRequest::AUTHORIZATION)); +} + + +bool HTTPCredentials::hasProxyBasicCredentials(const HTTPRequest& request) +{ + return request.has(HTTPRequest::PROXY_AUTHORIZATION) && isBasicCredentials(request.get(HTTPRequest::PROXY_AUTHORIZATION)); +} + + +bool HTTPCredentials::hasProxyDigestCredentials(const HTTPRequest& request) +{ + return request.has(HTTPRequest::PROXY_AUTHORIZATION) && isDigestCredentials(request.get(HTTPRequest::PROXY_AUTHORIZATION)); +} + + +void HTTPCredentials::extractCredentials(const std::string& userInfo, std::string& username, std::string& password) +{ + const std::string::size_type p = userInfo.find(':'); + + if (p != std::string::npos) + { + username.assign(userInfo, 0, p); + password.assign(userInfo, p + 1, std::string::npos); + } + else + { + username.assign(userInfo); + password.clear(); + } +} + + +void HTTPCredentials::extractCredentials(const Poco::URI& uri, std::string& username, std::string& password) +{ + if (!uri.getUserInfo().empty()) + { + extractCredentials(uri.getUserInfo(), username, password); + } +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPDigestCredentials.cpp b/contrib/libs/poco/Net/src/HTTPDigestCredentials.cpp index 0d3deb5146..43456a683d 100644 --- a/contrib/libs/poco/Net/src/HTTPDigestCredentials.cpp +++ b/contrib/libs/poco/Net/src/HTTPDigestCredentials.cpp @@ -1,313 +1,313 @@ -// -// HTTPDigestCredentials.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPDigestCredentials -// -// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru). -// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/DateTime.h" -#include "Poco/DateTimeFormat.h" -#include "Poco/DateTimeFormatter.h" -#include "Poco/Exception.h" -#include "Poco/MD5Engine.h" -#include "Poco/Net/HTTPDigestCredentials.h" -#include "Poco/Net/HTTPRequest.h" -#include "Poco/Net/HTTPResponse.h" -#include "Poco/NumberFormatter.h" -#include "Poco/StringTokenizer.h" - - -namespace -{ - std::string digest(Poco::DigestEngine& engine, - const std::string& a, - const std::string& b, - const std::string& c = std::string(), - const std::string& d = std::string(), - const std::string& e = std::string(), - const std::string& f = std::string()) - { - engine.reset(); - engine.update(a); - engine.update(':'); - engine.update(b); - if (!c.empty()) - { - engine.update(':'); - engine.update(c); - if (!d.empty()) - { - engine.update(':'); - engine.update(d); - engine.update(':'); - engine.update(e); - engine.update(':'); - engine.update(f); - } - } - return Poco::DigestEngine::digestToHex(engine.digest()); - } - - std::string formatNonceCounter(int counter) - { - return Poco::NumberFormatter::formatHex(counter, 8); - } -} - - -namespace Poco { -namespace Net { - - -const std::string HTTPDigestCredentials::SCHEME = "Digest"; -const std::string HTTPDigestCredentials::DEFAULT_ALGORITHM("MD5"); -const std::string HTTPDigestCredentials::DEFAULT_QOP(""); -const std::string HTTPDigestCredentials::NONCE_PARAM("nonce"); -const std::string HTTPDigestCredentials::REALM_PARAM("realm"); -const std::string HTTPDigestCredentials::QOP_PARAM("qop"); -const std::string HTTPDigestCredentials::ALGORITHM_PARAM("algorithm"); -const std::string HTTPDigestCredentials::USERNAME_PARAM("username"); -const std::string HTTPDigestCredentials::OPAQUE_PARAM("opaque"); -const std::string HTTPDigestCredentials::URI_PARAM("uri"); -const std::string HTTPDigestCredentials::RESPONSE_PARAM("response"); -const std::string HTTPDigestCredentials::AUTH_PARAM("auth"); -const std::string HTTPDigestCredentials::CNONCE_PARAM("cnonce"); -const std::string HTTPDigestCredentials::NC_PARAM("nc"); -int HTTPDigestCredentials::_nonceCounter(0); -Poco::FastMutex HTTPDigestCredentials::_nonceMutex; - - -HTTPDigestCredentials::HTTPDigestCredentials() -{ -} - - -HTTPDigestCredentials::HTTPDigestCredentials(const std::string& username, const std::string& password): - _username(username), - _password(password) -{ -} - - -HTTPDigestCredentials::~HTTPDigestCredentials() -{ -} - - -void HTTPDigestCredentials::reset() -{ - _requestAuthParams.clear(); - _nc.clear(); -} - - -void HTTPDigestCredentials::setUsername(const std::string& username) -{ - _username = username; -} - - -void HTTPDigestCredentials::setPassword(const std::string& password) -{ - _password = password; -} - - -void HTTPDigestCredentials::clear() -{ - _username.clear(); - _password.clear(); -} - - -void HTTPDigestCredentials::authenticate(HTTPRequest& request, const HTTPResponse& response) -{ - authenticate(request, HTTPAuthenticationParams(response)); -} - - -void HTTPDigestCredentials::authenticate(HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams) -{ - createAuthParams(request, responseAuthParams); - request.setCredentials(SCHEME, _requestAuthParams.toString()); -} - - -void HTTPDigestCredentials::updateAuthInfo(HTTPRequest& request) -{ - updateAuthParams(request); - request.setCredentials(SCHEME, _requestAuthParams.toString()); -} - - -void HTTPDigestCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response) -{ - proxyAuthenticate(request, HTTPAuthenticationParams(response, HTTPAuthenticationParams::PROXY_AUTHENTICATE)); -} - - -void HTTPDigestCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams) -{ - createAuthParams(request, responseAuthParams); - request.setProxyCredentials(SCHEME, _requestAuthParams.toString()); -} - - -void HTTPDigestCredentials::updateProxyAuthInfo(HTTPRequest& request) -{ - updateAuthParams(request); - request.setProxyCredentials(SCHEME, _requestAuthParams.toString()); -} - - -std::string HTTPDigestCredentials::createNonce() -{ - Poco::FastMutex::ScopedLock lock(_nonceMutex); - - MD5Engine md5; - Timestamp::TimeVal now = Timestamp().epochMicroseconds(); - - md5.update(&_nonceCounter, sizeof(_nonceCounter)); - md5.update(&now, sizeof(now)); - - ++_nonceCounter; - - return DigestEngine::digestToHex(md5.digest()); -} - - -void HTTPDigestCredentials::createAuthParams(const HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams) -{ - // Not implemented: "domain" auth parameter and integrity protection. - - if (!responseAuthParams.has(NONCE_PARAM) || !responseAuthParams.has(REALM_PARAM)) - throw InvalidArgumentException("Invalid HTTP authentication parameters"); - - const std::string& algorithm = responseAuthParams.get(ALGORITHM_PARAM, DEFAULT_ALGORITHM); - - if (icompare(algorithm, DEFAULT_ALGORITHM) != 0) - throw NotImplementedException("Unsupported digest algorithm", algorithm); - - const std::string& nonce = responseAuthParams.get(NONCE_PARAM); - const std::string& qop = responseAuthParams.get(QOP_PARAM, DEFAULT_QOP); - const std::string& realm = responseAuthParams.getRealm(); - - _requestAuthParams.clear(); - _requestAuthParams.set(USERNAME_PARAM, _username); - _requestAuthParams.set(NONCE_PARAM, nonce); - _requestAuthParams.setRealm(realm); - if (responseAuthParams.has(OPAQUE_PARAM)) - { - _requestAuthParams.set(OPAQUE_PARAM, responseAuthParams.get(OPAQUE_PARAM)); - } - - if (qop.empty()) - { - updateAuthParams(request); - } - else - { - Poco::StringTokenizer tok(qop, ",", Poco::StringTokenizer::TOK_TRIM); - bool qopSupported = false; - for (Poco::StringTokenizer::Iterator it = tok.begin(); it != tok.end(); ++it) - { - if (icompare(*it, AUTH_PARAM) == 0) - { - qopSupported = true; - _requestAuthParams.set(CNONCE_PARAM, createNonce()); - _requestAuthParams.set(QOP_PARAM, *it); - updateAuthParams(request); - break; - } - } - if (!qopSupported) - throw NotImplementedException("Unsupported QoP requested", qop); - } -} - - -void HTTPDigestCredentials::updateAuthParams(const HTTPRequest& request) -{ - MD5Engine engine; - const std::string& qop = _requestAuthParams.get(QOP_PARAM, DEFAULT_QOP); - const std::string& realm = _requestAuthParams.getRealm(); - const std::string& nonce = _requestAuthParams.get(NONCE_PARAM); - - _requestAuthParams.set(URI_PARAM, request.getURI()); - - if (qop.empty()) - { - const std::string ha1 = digest(engine, _username, realm, _password); - const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); - - _requestAuthParams.set(RESPONSE_PARAM, digest(engine, ha1, nonce, ha2)); - } - else if (icompare(qop, AUTH_PARAM) == 0) - { - const std::string& cnonce = _requestAuthParams.get(CNONCE_PARAM); - - const std::string ha1 = digest(engine, _username, realm, _password); - const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); - const std::string nc = formatNonceCounter(updateNonceCounter(nonce)); - - _requestAuthParams.set(NC_PARAM, nc); - _requestAuthParams.set(RESPONSE_PARAM, digest(engine, ha1, nonce, nc, cnonce, qop, ha2)); - } -} - - -bool HTTPDigestCredentials::verifyAuthInfo(const HTTPRequest& request) const -{ - HTTPAuthenticationParams params(request); - return verifyAuthParams(request, params); -} - - -bool HTTPDigestCredentials::verifyAuthParams(const HTTPRequest& request, const HTTPAuthenticationParams& params) const -{ - const std::string& nonce = params.get(NONCE_PARAM); - const std::string& realm = params.getRealm(); - const std::string& qop = params.get(QOP_PARAM, DEFAULT_QOP); - std::string response; - MD5Engine engine; - if (qop.empty()) - { - const std::string ha1 = digest(engine, _username, realm, _password); - const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); - response = digest(engine, ha1, nonce, ha2); - } - else if (icompare(qop, AUTH_PARAM) == 0) - { - const std::string& cnonce = params.get(CNONCE_PARAM); - const std::string& nc = params.get(NC_PARAM); - const std::string ha1 = digest(engine, _username, realm, _password); - const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); - response = digest(engine, ha1, nonce, nc, cnonce, qop, ha2); - } - return response == params.get(RESPONSE_PARAM); -} - - -int HTTPDigestCredentials::updateNonceCounter(const std::string& nonce) -{ - NonceCounterMap::iterator iter = _nc.find(nonce); - - if (iter == _nc.end()) - { - iter = _nc.insert(NonceCounterMap::value_type(nonce, 0)).first; - } - iter->second++; - - return iter->second; -} - - -} } // namespace Poco::Net +// +// HTTPDigestCredentials.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPDigestCredentials +// +// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru). +// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/DateTime.h" +#include "Poco/DateTimeFormat.h" +#include "Poco/DateTimeFormatter.h" +#include "Poco/Exception.h" +#include "Poco/MD5Engine.h" +#include "Poco/Net/HTTPDigestCredentials.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/HTTPResponse.h" +#include "Poco/NumberFormatter.h" +#include "Poco/StringTokenizer.h" + + +namespace +{ + std::string digest(Poco::DigestEngine& engine, + const std::string& a, + const std::string& b, + const std::string& c = std::string(), + const std::string& d = std::string(), + const std::string& e = std::string(), + const std::string& f = std::string()) + { + engine.reset(); + engine.update(a); + engine.update(':'); + engine.update(b); + if (!c.empty()) + { + engine.update(':'); + engine.update(c); + if (!d.empty()) + { + engine.update(':'); + engine.update(d); + engine.update(':'); + engine.update(e); + engine.update(':'); + engine.update(f); + } + } + return Poco::DigestEngine::digestToHex(engine.digest()); + } + + std::string formatNonceCounter(int counter) + { + return Poco::NumberFormatter::formatHex(counter, 8); + } +} + + +namespace Poco { +namespace Net { + + +const std::string HTTPDigestCredentials::SCHEME = "Digest"; +const std::string HTTPDigestCredentials::DEFAULT_ALGORITHM("MD5"); +const std::string HTTPDigestCredentials::DEFAULT_QOP(""); +const std::string HTTPDigestCredentials::NONCE_PARAM("nonce"); +const std::string HTTPDigestCredentials::REALM_PARAM("realm"); +const std::string HTTPDigestCredentials::QOP_PARAM("qop"); +const std::string HTTPDigestCredentials::ALGORITHM_PARAM("algorithm"); +const std::string HTTPDigestCredentials::USERNAME_PARAM("username"); +const std::string HTTPDigestCredentials::OPAQUE_PARAM("opaque"); +const std::string HTTPDigestCredentials::URI_PARAM("uri"); +const std::string HTTPDigestCredentials::RESPONSE_PARAM("response"); +const std::string HTTPDigestCredentials::AUTH_PARAM("auth"); +const std::string HTTPDigestCredentials::CNONCE_PARAM("cnonce"); +const std::string HTTPDigestCredentials::NC_PARAM("nc"); +int HTTPDigestCredentials::_nonceCounter(0); +Poco::FastMutex HTTPDigestCredentials::_nonceMutex; + + +HTTPDigestCredentials::HTTPDigestCredentials() +{ +} + + +HTTPDigestCredentials::HTTPDigestCredentials(const std::string& username, const std::string& password): + _username(username), + _password(password) +{ +} + + +HTTPDigestCredentials::~HTTPDigestCredentials() +{ +} + + +void HTTPDigestCredentials::reset() +{ + _requestAuthParams.clear(); + _nc.clear(); +} + + +void HTTPDigestCredentials::setUsername(const std::string& username) +{ + _username = username; +} + + +void HTTPDigestCredentials::setPassword(const std::string& password) +{ + _password = password; +} + + +void HTTPDigestCredentials::clear() +{ + _username.clear(); + _password.clear(); +} + + +void HTTPDigestCredentials::authenticate(HTTPRequest& request, const HTTPResponse& response) +{ + authenticate(request, HTTPAuthenticationParams(response)); +} + + +void HTTPDigestCredentials::authenticate(HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams) +{ + createAuthParams(request, responseAuthParams); + request.setCredentials(SCHEME, _requestAuthParams.toString()); +} + + +void HTTPDigestCredentials::updateAuthInfo(HTTPRequest& request) +{ + updateAuthParams(request); + request.setCredentials(SCHEME, _requestAuthParams.toString()); +} + + +void HTTPDigestCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response) +{ + proxyAuthenticate(request, HTTPAuthenticationParams(response, HTTPAuthenticationParams::PROXY_AUTHENTICATE)); +} + + +void HTTPDigestCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams) +{ + createAuthParams(request, responseAuthParams); + request.setProxyCredentials(SCHEME, _requestAuthParams.toString()); +} + + +void HTTPDigestCredentials::updateProxyAuthInfo(HTTPRequest& request) +{ + updateAuthParams(request); + request.setProxyCredentials(SCHEME, _requestAuthParams.toString()); +} + + +std::string HTTPDigestCredentials::createNonce() +{ + Poco::FastMutex::ScopedLock lock(_nonceMutex); + + MD5Engine md5; + Timestamp::TimeVal now = Timestamp().epochMicroseconds(); + + md5.update(&_nonceCounter, sizeof(_nonceCounter)); + md5.update(&now, sizeof(now)); + + ++_nonceCounter; + + return DigestEngine::digestToHex(md5.digest()); +} + + +void HTTPDigestCredentials::createAuthParams(const HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams) +{ + // Not implemented: "domain" auth parameter and integrity protection. + + if (!responseAuthParams.has(NONCE_PARAM) || !responseAuthParams.has(REALM_PARAM)) + throw InvalidArgumentException("Invalid HTTP authentication parameters"); + + const std::string& algorithm = responseAuthParams.get(ALGORITHM_PARAM, DEFAULT_ALGORITHM); + + if (icompare(algorithm, DEFAULT_ALGORITHM) != 0) + throw NotImplementedException("Unsupported digest algorithm", algorithm); + + const std::string& nonce = responseAuthParams.get(NONCE_PARAM); + const std::string& qop = responseAuthParams.get(QOP_PARAM, DEFAULT_QOP); + const std::string& realm = responseAuthParams.getRealm(); + + _requestAuthParams.clear(); + _requestAuthParams.set(USERNAME_PARAM, _username); + _requestAuthParams.set(NONCE_PARAM, nonce); + _requestAuthParams.setRealm(realm); + if (responseAuthParams.has(OPAQUE_PARAM)) + { + _requestAuthParams.set(OPAQUE_PARAM, responseAuthParams.get(OPAQUE_PARAM)); + } + + if (qop.empty()) + { + updateAuthParams(request); + } + else + { + Poco::StringTokenizer tok(qop, ",", Poco::StringTokenizer::TOK_TRIM); + bool qopSupported = false; + for (Poco::StringTokenizer::Iterator it = tok.begin(); it != tok.end(); ++it) + { + if (icompare(*it, AUTH_PARAM) == 0) + { + qopSupported = true; + _requestAuthParams.set(CNONCE_PARAM, createNonce()); + _requestAuthParams.set(QOP_PARAM, *it); + updateAuthParams(request); + break; + } + } + if (!qopSupported) + throw NotImplementedException("Unsupported QoP requested", qop); + } +} + + +void HTTPDigestCredentials::updateAuthParams(const HTTPRequest& request) +{ + MD5Engine engine; + const std::string& qop = _requestAuthParams.get(QOP_PARAM, DEFAULT_QOP); + const std::string& realm = _requestAuthParams.getRealm(); + const std::string& nonce = _requestAuthParams.get(NONCE_PARAM); + + _requestAuthParams.set(URI_PARAM, request.getURI()); + + if (qop.empty()) + { + const std::string ha1 = digest(engine, _username, realm, _password); + const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); + + _requestAuthParams.set(RESPONSE_PARAM, digest(engine, ha1, nonce, ha2)); + } + else if (icompare(qop, AUTH_PARAM) == 0) + { + const std::string& cnonce = _requestAuthParams.get(CNONCE_PARAM); + + const std::string ha1 = digest(engine, _username, realm, _password); + const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); + const std::string nc = formatNonceCounter(updateNonceCounter(nonce)); + + _requestAuthParams.set(NC_PARAM, nc); + _requestAuthParams.set(RESPONSE_PARAM, digest(engine, ha1, nonce, nc, cnonce, qop, ha2)); + } +} + + +bool HTTPDigestCredentials::verifyAuthInfo(const HTTPRequest& request) const +{ + HTTPAuthenticationParams params(request); + return verifyAuthParams(request, params); +} + + +bool HTTPDigestCredentials::verifyAuthParams(const HTTPRequest& request, const HTTPAuthenticationParams& params) const +{ + const std::string& nonce = params.get(NONCE_PARAM); + const std::string& realm = params.getRealm(); + const std::string& qop = params.get(QOP_PARAM, DEFAULT_QOP); + std::string response; + MD5Engine engine; + if (qop.empty()) + { + const std::string ha1 = digest(engine, _username, realm, _password); + const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); + response = digest(engine, ha1, nonce, ha2); + } + else if (icompare(qop, AUTH_PARAM) == 0) + { + const std::string& cnonce = params.get(CNONCE_PARAM); + const std::string& nc = params.get(NC_PARAM); + const std::string ha1 = digest(engine, _username, realm, _password); + const std::string ha2 = digest(engine, request.getMethod(), request.getURI()); + response = digest(engine, ha1, nonce, nc, cnonce, qop, ha2); + } + return response == params.get(RESPONSE_PARAM); +} + + +int HTTPDigestCredentials::updateNonceCounter(const std::string& nonce) +{ + NonceCounterMap::iterator iter = _nc.find(nonce); + + if (iter == _nc.end()) + { + iter = _nc.insert(NonceCounterMap::value_type(nonce, 0)).first; + } + iter->second++; + + return iter->second; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPFixedLengthStream.cpp b/contrib/libs/poco/Net/src/HTTPFixedLengthStream.cpp index 3273fe6c00..e287de9f83 100644 --- a/contrib/libs/poco/Net/src/HTTPFixedLengthStream.cpp +++ b/contrib/libs/poco/Net/src/HTTPFixedLengthStream.cpp @@ -1,181 +1,181 @@ -// -// HTTPFixedLengthStream.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPFixedLengthStream -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPFixedLengthStream.h" -#include "Poco/Net/HTTPSession.h" - - -using Poco::BufferedStreamBuf; - - -namespace Poco { -namespace Net { - - -// -// HTTPFixedLengthStreamBuf -// - - -HTTPFixedLengthStreamBuf::HTTPFixedLengthStreamBuf(HTTPSession& session, ContentLength length, openmode mode): - HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode), - _session(session), - _length(length), - _count(0) -{ -} - - -HTTPFixedLengthStreamBuf::~HTTPFixedLengthStreamBuf() -{ -} - - -int HTTPFixedLengthStreamBuf::readFromDevice(char* buffer, std::streamsize length) -{ - int n = 0; - if (_count < _length) - { - if (_count + length > _length) - length = static_cast<std::streamsize>(_length - _count); - n = _session.read(buffer, length); - if (n > 0) _count += n; - } - return n; -} - - -int HTTPFixedLengthStreamBuf::writeToDevice(const char* buffer, std::streamsize length) -{ - int n = 0; - if (_count < _length) - { - if (_count + length > _length) - length = static_cast<std::streamsize>(_length - _count); - n = _session.write(buffer, length); - if (n > 0) _count += n; - } - return n; -} - - -// -// HTTPFixedLengthIOS -// - - -HTTPFixedLengthIOS::HTTPFixedLengthIOS(HTTPSession& session, HTTPFixedLengthStreamBuf::ContentLength length, HTTPFixedLengthStreamBuf::openmode mode): - _buf(session, length, mode) -{ - poco_ios_init(&_buf); -} - - -HTTPFixedLengthIOS::~HTTPFixedLengthIOS() -{ - try - { - _buf.sync(); - } - catch (...) - { - } -} - - -HTTPFixedLengthStreamBuf* HTTPFixedLengthIOS::rdbuf() -{ - return &_buf; -} - - -// -// HTTPFixedLengthInputStream -// - - -Poco::MemoryPool HTTPFixedLengthInputStream::_pool(sizeof(HTTPFixedLengthInputStream)); - - -HTTPFixedLengthInputStream::HTTPFixedLengthInputStream(HTTPSession& session, HTTPFixedLengthStreamBuf::ContentLength length): - HTTPFixedLengthIOS(session, length, std::ios::in), - std::istream(&_buf) -{ -} - - -HTTPFixedLengthInputStream::~HTTPFixedLengthInputStream() -{ -} - - -void* HTTPFixedLengthInputStream::operator new(std::size_t /*size*/) -{ - return _pool.get(); -} - - -void HTTPFixedLengthInputStream::operator delete(void* ptr) -{ - try - { - _pool.release(ptr); - } - catch (...) - { - poco_unexpected(); - } -} - - -// -// HTTPFixedLengthOutputStream -// - - -Poco::MemoryPool HTTPFixedLengthOutputStream::_pool(sizeof(HTTPFixedLengthOutputStream)); - - -HTTPFixedLengthOutputStream::HTTPFixedLengthOutputStream(HTTPSession& session, HTTPFixedLengthStreamBuf::ContentLength length): - HTTPFixedLengthIOS(session, length, std::ios::out), - std::ostream(&_buf) -{ -} - - -HTTPFixedLengthOutputStream::~HTTPFixedLengthOutputStream() -{ -} - - -void* HTTPFixedLengthOutputStream::operator new(std::size_t /*size*/) -{ - return _pool.get(); -} - - -void HTTPFixedLengthOutputStream::operator delete(void* ptr) -{ - try - { - _pool.release(ptr); - } - catch (...) - { - poco_unexpected(); - } -} - - -} } // namespace Poco::Net +// +// HTTPFixedLengthStream.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPFixedLengthStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPFixedLengthStream.h" +#include "Poco/Net/HTTPSession.h" + + +using Poco::BufferedStreamBuf; + + +namespace Poco { +namespace Net { + + +// +// HTTPFixedLengthStreamBuf +// + + +HTTPFixedLengthStreamBuf::HTTPFixedLengthStreamBuf(HTTPSession& session, ContentLength length, openmode mode): + HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode), + _session(session), + _length(length), + _count(0) +{ +} + + +HTTPFixedLengthStreamBuf::~HTTPFixedLengthStreamBuf() +{ +} + + +int HTTPFixedLengthStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + int n = 0; + if (_count < _length) + { + if (_count + length > _length) + length = static_cast<std::streamsize>(_length - _count); + n = _session.read(buffer, length); + if (n > 0) _count += n; + } + return n; +} + + +int HTTPFixedLengthStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + int n = 0; + if (_count < _length) + { + if (_count + length > _length) + length = static_cast<std::streamsize>(_length - _count); + n = _session.write(buffer, length); + if (n > 0) _count += n; + } + return n; +} + + +// +// HTTPFixedLengthIOS +// + + +HTTPFixedLengthIOS::HTTPFixedLengthIOS(HTTPSession& session, HTTPFixedLengthStreamBuf::ContentLength length, HTTPFixedLengthStreamBuf::openmode mode): + _buf(session, length, mode) +{ + poco_ios_init(&_buf); +} + + +HTTPFixedLengthIOS::~HTTPFixedLengthIOS() +{ + try + { + _buf.sync(); + } + catch (...) + { + } +} + + +HTTPFixedLengthStreamBuf* HTTPFixedLengthIOS::rdbuf() +{ + return &_buf; +} + + +// +// HTTPFixedLengthInputStream +// + + +Poco::MemoryPool HTTPFixedLengthInputStream::_pool(sizeof(HTTPFixedLengthInputStream)); + + +HTTPFixedLengthInputStream::HTTPFixedLengthInputStream(HTTPSession& session, HTTPFixedLengthStreamBuf::ContentLength length): + HTTPFixedLengthIOS(session, length, std::ios::in), + std::istream(&_buf) +{ +} + + +HTTPFixedLengthInputStream::~HTTPFixedLengthInputStream() +{ +} + + +void* HTTPFixedLengthInputStream::operator new(std::size_t /*size*/) +{ + return _pool.get(); +} + + +void HTTPFixedLengthInputStream::operator delete(void* ptr) +{ + try + { + _pool.release(ptr); + } + catch (...) + { + poco_unexpected(); + } +} + + +// +// HTTPFixedLengthOutputStream +// + + +Poco::MemoryPool HTTPFixedLengthOutputStream::_pool(sizeof(HTTPFixedLengthOutputStream)); + + +HTTPFixedLengthOutputStream::HTTPFixedLengthOutputStream(HTTPSession& session, HTTPFixedLengthStreamBuf::ContentLength length): + HTTPFixedLengthIOS(session, length, std::ios::out), + std::ostream(&_buf) +{ +} + + +HTTPFixedLengthOutputStream::~HTTPFixedLengthOutputStream() +{ +} + + +void* HTTPFixedLengthOutputStream::operator new(std::size_t /*size*/) +{ + return _pool.get(); +} + + +void HTTPFixedLengthOutputStream::operator delete(void* ptr) +{ + try + { + _pool.release(ptr); + } + catch (...) + { + poco_unexpected(); + } +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPHeaderStream.cpp b/contrib/libs/poco/Net/src/HTTPHeaderStream.cpp index 7d8279bc80..2b53e96815 100644 --- a/contrib/libs/poco/Net/src/HTTPHeaderStream.cpp +++ b/contrib/libs/poco/Net/src/HTTPHeaderStream.cpp @@ -1,180 +1,180 @@ -// -// HTTPHeaderStream.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPHeaderStream -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPHeaderStream.h" -#include "Poco/Net/HTTPSession.h" - - -namespace Poco { -namespace Net { - - -// -// HTTPHeaderStreamBuf -// - - -HTTPHeaderStreamBuf::HTTPHeaderStreamBuf(HTTPSession& session, openmode mode): - HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode), - _session(session), +// +// HTTPHeaderStream.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPHeaderStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPHeaderStream.h" +#include "Poco/Net/HTTPSession.h" + + +namespace Poco { +namespace Net { + + +// +// HTTPHeaderStreamBuf +// + + +HTTPHeaderStreamBuf::HTTPHeaderStreamBuf(HTTPSession& session, openmode mode): + HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode), + _session(session), _end(false), _line_ended(true) -{ -} - - -HTTPHeaderStreamBuf::~HTTPHeaderStreamBuf() -{ -} - - -int HTTPHeaderStreamBuf::readFromDevice(char* buffer, std::streamsize length) -{ - // read line-by-line; an empty line denotes the end of the headers. - static const int eof = std::char_traits<char>::eof(); - - if (_end) return 0; - - int n = 0; - int ch = _session.get(); - while (ch != eof && ch != '\n' && n < length - 1) - { - *buffer++ = (char) ch; ++n; - ch = _session.get(); - } - if (ch != eof) - { - *buffer++ = (char) ch; ++n; +{ +} + + +HTTPHeaderStreamBuf::~HTTPHeaderStreamBuf() +{ +} + + +int HTTPHeaderStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + // read line-by-line; an empty line denotes the end of the headers. + static const int eof = std::char_traits<char>::eof(); + + if (_end) return 0; + + int n = 0; + int ch = _session.get(); + while (ch != eof && ch != '\n' && n < length - 1) + { + *buffer++ = (char) ch; ++n; + ch = _session.get(); + } + if (ch != eof) + { + *buffer++ = (char) ch; ++n; if (n == 2) _end = _line_ended; - } + } _line_ended = (ch == '\n'); - return n; -} - - -int HTTPHeaderStreamBuf::writeToDevice(const char* buffer, std::streamsize length) -{ - return _session.write(buffer, length); -} - - -// -// HTTPHeaderIOS -// - - -HTTPHeaderIOS::HTTPHeaderIOS(HTTPSession& session, HTTPHeaderStreamBuf::openmode mode): - _buf(session, mode) -{ - poco_ios_init(&_buf); -} - - -HTTPHeaderIOS::~HTTPHeaderIOS() -{ - try - { - _buf.sync(); - } - catch (...) - { - } -} - - -HTTPHeaderStreamBuf* HTTPHeaderIOS::rdbuf() -{ - return &_buf; -} - - -// -// HTTPHeaderInputStream -// - - -Poco::MemoryPool HTTPHeaderInputStream::_pool(sizeof(HTTPHeaderInputStream)); - - -HTTPHeaderInputStream::HTTPHeaderInputStream(HTTPSession& session): - HTTPHeaderIOS(session, std::ios::in), - std::istream(&_buf) -{ -} - - -HTTPHeaderInputStream::~HTTPHeaderInputStream() -{ -} - - -void* HTTPHeaderInputStream::operator new(std::size_t /*size*/) -{ - return _pool.get(); -} - - -void HTTPHeaderInputStream::operator delete(void* ptr) -{ - try - { - _pool.release(ptr); - } - catch (...) - { - poco_unexpected(); - } -} - - -// -// HTTPHeaderOutputStream -// - - -Poco::MemoryPool HTTPHeaderOutputStream::_pool(sizeof(HTTPHeaderOutputStream)); - - -HTTPHeaderOutputStream::HTTPHeaderOutputStream(HTTPSession& session): - HTTPHeaderIOS(session, std::ios::out), - std::ostream(&_buf) -{ -} - - -HTTPHeaderOutputStream::~HTTPHeaderOutputStream() -{ -} - - -void* HTTPHeaderOutputStream::operator new(std::size_t /*size*/) -{ - return _pool.get(); -} - - -void HTTPHeaderOutputStream::operator delete(void* ptr) -{ - try - { - _pool.release(ptr); - } - catch (...) - { - poco_unexpected(); - } -} - - -} } // namespace Poco::Net + return n; +} + + +int HTTPHeaderStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + return _session.write(buffer, length); +} + + +// +// HTTPHeaderIOS +// + + +HTTPHeaderIOS::HTTPHeaderIOS(HTTPSession& session, HTTPHeaderStreamBuf::openmode mode): + _buf(session, mode) +{ + poco_ios_init(&_buf); +} + + +HTTPHeaderIOS::~HTTPHeaderIOS() +{ + try + { + _buf.sync(); + } + catch (...) + { + } +} + + +HTTPHeaderStreamBuf* HTTPHeaderIOS::rdbuf() +{ + return &_buf; +} + + +// +// HTTPHeaderInputStream +// + + +Poco::MemoryPool HTTPHeaderInputStream::_pool(sizeof(HTTPHeaderInputStream)); + + +HTTPHeaderInputStream::HTTPHeaderInputStream(HTTPSession& session): + HTTPHeaderIOS(session, std::ios::in), + std::istream(&_buf) +{ +} + + +HTTPHeaderInputStream::~HTTPHeaderInputStream() +{ +} + + +void* HTTPHeaderInputStream::operator new(std::size_t /*size*/) +{ + return _pool.get(); +} + + +void HTTPHeaderInputStream::operator delete(void* ptr) +{ + try + { + _pool.release(ptr); + } + catch (...) + { + poco_unexpected(); + } +} + + +// +// HTTPHeaderOutputStream +// + + +Poco::MemoryPool HTTPHeaderOutputStream::_pool(sizeof(HTTPHeaderOutputStream)); + + +HTTPHeaderOutputStream::HTTPHeaderOutputStream(HTTPSession& session): + HTTPHeaderIOS(session, std::ios::out), + std::ostream(&_buf) +{ +} + + +HTTPHeaderOutputStream::~HTTPHeaderOutputStream() +{ +} + + +void* HTTPHeaderOutputStream::operator new(std::size_t /*size*/) +{ + return _pool.get(); +} + + +void HTTPHeaderOutputStream::operator delete(void* ptr) +{ + try + { + _pool.release(ptr); + } + catch (...) + { + poco_unexpected(); + } +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPIOStream.cpp b/contrib/libs/poco/Net/src/HTTPIOStream.cpp index c6492aed8f..1342109741 100644 --- a/contrib/libs/poco/Net/src/HTTPIOStream.cpp +++ b/contrib/libs/poco/Net/src/HTTPIOStream.cpp @@ -1,65 +1,65 @@ -// -// HTTPIOStream.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPIOStream -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPIOStream.h" -#include "Poco/Net/HTTPClientSession.h" - - -using Poco::UnbufferedStreamBuf; - - -namespace Poco { -namespace Net { - - -HTTPResponseStreamBuf::HTTPResponseStreamBuf(std::istream& istr): - _istr(istr) -{ - // make sure exceptions from underlying string propagate - _istr.exceptions(std::ios::badbit); -} - - -HTTPResponseStreamBuf::~HTTPResponseStreamBuf() -{ -} - - -HTTPResponseIOS::HTTPResponseIOS(std::istream& istr): - _buf(istr) -{ - poco_ios_init(&_buf); -} - - -HTTPResponseIOS::~HTTPResponseIOS() -{ -} - - -HTTPResponseStream::HTTPResponseStream(std::istream& istr, HTTPClientSession* pSession): - HTTPResponseIOS(istr), - std::istream(&_buf), - _pSession(pSession) -{ -} - - -HTTPResponseStream::~HTTPResponseStream() -{ - delete _pSession; -} - - -} } // namespace Poco::Net +// +// HTTPIOStream.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPIOStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPIOStream.h" +#include "Poco/Net/HTTPClientSession.h" + + +using Poco::UnbufferedStreamBuf; + + +namespace Poco { +namespace Net { + + +HTTPResponseStreamBuf::HTTPResponseStreamBuf(std::istream& istr): + _istr(istr) +{ + // make sure exceptions from underlying string propagate + _istr.exceptions(std::ios::badbit); +} + + +HTTPResponseStreamBuf::~HTTPResponseStreamBuf() +{ +} + + +HTTPResponseIOS::HTTPResponseIOS(std::istream& istr): + _buf(istr) +{ + poco_ios_init(&_buf); +} + + +HTTPResponseIOS::~HTTPResponseIOS() +{ +} + + +HTTPResponseStream::HTTPResponseStream(std::istream& istr, HTTPClientSession* pSession): + HTTPResponseIOS(istr), + std::istream(&_buf), + _pSession(pSession) +{ +} + + +HTTPResponseStream::~HTTPResponseStream() +{ + delete _pSession; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPMessage.cpp b/contrib/libs/poco/Net/src/HTTPMessage.cpp index debda04c3b..6bddcc94f3 100644 --- a/contrib/libs/poco/Net/src/HTTPMessage.cpp +++ b/contrib/libs/poco/Net/src/HTTPMessage.cpp @@ -1,184 +1,184 @@ -// -// HTTPMessage.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPMessage -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPMessage.h" -#include "Poco/Net/MediaType.h" -#include "Poco/NumberFormatter.h" -#include "Poco/NumberParser.h" -#include "Poco/String.h" - - -using Poco::NumberFormatter; -using Poco::NumberParser; -using Poco::icompare; - - -namespace Poco { -namespace Net { - - -const std::string HTTPMessage::HTTP_1_0 = "HTTP/1.0"; -const std::string HTTPMessage::HTTP_1_1 = "HTTP/1.1"; -const std::string HTTPMessage::IDENTITY_TRANSFER_ENCODING = "identity"; -const std::string HTTPMessage::CHUNKED_TRANSFER_ENCODING = "chunked"; -const int HTTPMessage::UNKNOWN_CONTENT_LENGTH = -1; -const std::string HTTPMessage::UNKNOWN_CONTENT_TYPE; -const std::string HTTPMessage::CONTENT_LENGTH = "Content-Length"; -const std::string HTTPMessage::CONTENT_TYPE = "Content-Type"; -const std::string HTTPMessage::TRANSFER_ENCODING = "Transfer-Encoding"; -const std::string HTTPMessage::CONNECTION = "Connection"; -const std::string HTTPMessage::CONNECTION_KEEP_ALIVE = "Keep-Alive"; -const std::string HTTPMessage::CONNECTION_CLOSE = "Close"; -const std::string HTTPMessage::EMPTY; - - -HTTPMessage::HTTPMessage(): - _version(HTTP_1_0) -{ -} - - -HTTPMessage::HTTPMessage(const std::string& version): - _version(version) -{ -} - - -HTTPMessage::~HTTPMessage() -{ -} - - -void HTTPMessage::setVersion(const std::string& version) -{ - _version = version; -} - - -void HTTPMessage::setContentLength(std::streamsize length) -{ - if (length != UNKNOWN_CONTENT_LENGTH) - set(CONTENT_LENGTH, NumberFormatter::format(length)); - else - erase(CONTENT_LENGTH); -} - - -std::streamsize HTTPMessage::getContentLength() const -{ - const std::string& contentLength = get(CONTENT_LENGTH, EMPTY); - if (!contentLength.empty()) - { - if (sizeof(std::streamsize) == sizeof(Poco::Int64)) - return static_cast<std::streamsize>(NumberParser::parse64(contentLength)); - else - return static_cast<std::streamsize>(NumberParser::parse(contentLength)); - } - else return UNKNOWN_CONTENT_LENGTH; -} - - -#if defined(POCO_HAVE_INT64) -void HTTPMessage::setContentLength64(Poco::Int64 length) -{ - if (length != UNKNOWN_CONTENT_LENGTH) - set(CONTENT_LENGTH, NumberFormatter::format(length)); - else - erase(CONTENT_LENGTH); -} - - -Poco::Int64 HTTPMessage::getContentLength64() const -{ - const std::string& contentLength = get(CONTENT_LENGTH, EMPTY); - if (!contentLength.empty()) - { - return NumberParser::parse64(contentLength); - } - else return UNKNOWN_CONTENT_LENGTH; -} -#endif // defined(POCO_HAVE_INT64) - - -void HTTPMessage::setTransferEncoding(const std::string& transferEncoding) -{ - if (icompare(transferEncoding, IDENTITY_TRANSFER_ENCODING) == 0) - erase(TRANSFER_ENCODING); - else - set(TRANSFER_ENCODING, transferEncoding); -} - - -const std::string& HTTPMessage::getTransferEncoding() const -{ - return get(TRANSFER_ENCODING, IDENTITY_TRANSFER_ENCODING); -} - - -void HTTPMessage::setChunkedTransferEncoding(bool flag) -{ - if (flag) - setTransferEncoding(CHUNKED_TRANSFER_ENCODING); - else - setTransferEncoding(IDENTITY_TRANSFER_ENCODING); -} - - -bool HTTPMessage::getChunkedTransferEncoding() const -{ - return icompare(getTransferEncoding(), CHUNKED_TRANSFER_ENCODING) == 0; -} - - -void HTTPMessage::setContentType(const std::string& mediaType) -{ - if (mediaType.empty()) - erase(CONTENT_TYPE); - else - set(CONTENT_TYPE, mediaType); -} - - -void HTTPMessage::setContentType(const MediaType& mediaType) -{ - setContentType(mediaType.toString()); -} - - -const std::string& HTTPMessage::getContentType() const -{ - return get(CONTENT_TYPE, UNKNOWN_CONTENT_TYPE); -} - - -void HTTPMessage::setKeepAlive(bool keepAlive) -{ - if (keepAlive) - set(CONNECTION, CONNECTION_KEEP_ALIVE); - else - set(CONNECTION, CONNECTION_CLOSE); -} - - -bool HTTPMessage::getKeepAlive() const -{ - const std::string& connection = get(CONNECTION, EMPTY); - if (!connection.empty()) - return icompare(connection, CONNECTION_CLOSE) != 0; - else - return getVersion() == HTTP_1_1; -} - - -} } // namespace Poco::Net +// +// HTTPMessage.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPMessage +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPMessage.h" +#include "Poco/Net/MediaType.h" +#include "Poco/NumberFormatter.h" +#include "Poco/NumberParser.h" +#include "Poco/String.h" + + +using Poco::NumberFormatter; +using Poco::NumberParser; +using Poco::icompare; + + +namespace Poco { +namespace Net { + + +const std::string HTTPMessage::HTTP_1_0 = "HTTP/1.0"; +const std::string HTTPMessage::HTTP_1_1 = "HTTP/1.1"; +const std::string HTTPMessage::IDENTITY_TRANSFER_ENCODING = "identity"; +const std::string HTTPMessage::CHUNKED_TRANSFER_ENCODING = "chunked"; +const int HTTPMessage::UNKNOWN_CONTENT_LENGTH = -1; +const std::string HTTPMessage::UNKNOWN_CONTENT_TYPE; +const std::string HTTPMessage::CONTENT_LENGTH = "Content-Length"; +const std::string HTTPMessage::CONTENT_TYPE = "Content-Type"; +const std::string HTTPMessage::TRANSFER_ENCODING = "Transfer-Encoding"; +const std::string HTTPMessage::CONNECTION = "Connection"; +const std::string HTTPMessage::CONNECTION_KEEP_ALIVE = "Keep-Alive"; +const std::string HTTPMessage::CONNECTION_CLOSE = "Close"; +const std::string HTTPMessage::EMPTY; + + +HTTPMessage::HTTPMessage(): + _version(HTTP_1_0) +{ +} + + +HTTPMessage::HTTPMessage(const std::string& version): + _version(version) +{ +} + + +HTTPMessage::~HTTPMessage() +{ +} + + +void HTTPMessage::setVersion(const std::string& version) +{ + _version = version; +} + + +void HTTPMessage::setContentLength(std::streamsize length) +{ + if (length != UNKNOWN_CONTENT_LENGTH) + set(CONTENT_LENGTH, NumberFormatter::format(length)); + else + erase(CONTENT_LENGTH); +} + + +std::streamsize HTTPMessage::getContentLength() const +{ + const std::string& contentLength = get(CONTENT_LENGTH, EMPTY); + if (!contentLength.empty()) + { + if (sizeof(std::streamsize) == sizeof(Poco::Int64)) + return static_cast<std::streamsize>(NumberParser::parse64(contentLength)); + else + return static_cast<std::streamsize>(NumberParser::parse(contentLength)); + } + else return UNKNOWN_CONTENT_LENGTH; +} + + +#if defined(POCO_HAVE_INT64) +void HTTPMessage::setContentLength64(Poco::Int64 length) +{ + if (length != UNKNOWN_CONTENT_LENGTH) + set(CONTENT_LENGTH, NumberFormatter::format(length)); + else + erase(CONTENT_LENGTH); +} + + +Poco::Int64 HTTPMessage::getContentLength64() const +{ + const std::string& contentLength = get(CONTENT_LENGTH, EMPTY); + if (!contentLength.empty()) + { + return NumberParser::parse64(contentLength); + } + else return UNKNOWN_CONTENT_LENGTH; +} +#endif // defined(POCO_HAVE_INT64) + + +void HTTPMessage::setTransferEncoding(const std::string& transferEncoding) +{ + if (icompare(transferEncoding, IDENTITY_TRANSFER_ENCODING) == 0) + erase(TRANSFER_ENCODING); + else + set(TRANSFER_ENCODING, transferEncoding); +} + + +const std::string& HTTPMessage::getTransferEncoding() const +{ + return get(TRANSFER_ENCODING, IDENTITY_TRANSFER_ENCODING); +} + + +void HTTPMessage::setChunkedTransferEncoding(bool flag) +{ + if (flag) + setTransferEncoding(CHUNKED_TRANSFER_ENCODING); + else + setTransferEncoding(IDENTITY_TRANSFER_ENCODING); +} + + +bool HTTPMessage::getChunkedTransferEncoding() const +{ + return icompare(getTransferEncoding(), CHUNKED_TRANSFER_ENCODING) == 0; +} + + +void HTTPMessage::setContentType(const std::string& mediaType) +{ + if (mediaType.empty()) + erase(CONTENT_TYPE); + else + set(CONTENT_TYPE, mediaType); +} + + +void HTTPMessage::setContentType(const MediaType& mediaType) +{ + setContentType(mediaType.toString()); +} + + +const std::string& HTTPMessage::getContentType() const +{ + return get(CONTENT_TYPE, UNKNOWN_CONTENT_TYPE); +} + + +void HTTPMessage::setKeepAlive(bool keepAlive) +{ + if (keepAlive) + set(CONNECTION, CONNECTION_KEEP_ALIVE); + else + set(CONNECTION, CONNECTION_CLOSE); +} + + +bool HTTPMessage::getKeepAlive() const +{ + const std::string& connection = get(CONNECTION, EMPTY); + if (!connection.empty()) + return icompare(connection, CONNECTION_CLOSE) != 0; + else + return getVersion() == HTTP_1_1; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPRequest.cpp b/contrib/libs/poco/Net/src/HTTPRequest.cpp index 52b3cf2f71..d9b161e828 100644 --- a/contrib/libs/poco/Net/src/HTTPRequest.cpp +++ b/contrib/libs/poco/Net/src/HTTPRequest.cpp @@ -1,277 +1,277 @@ -// -// HTTPRequest.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPRequest -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPRequest.h" -#include "Poco/Net/NetException.h" -#include "Poco/Net/NameValueCollection.h" -#include "Poco/NumberFormatter.h" -#include "Poco/Ascii.h" -#include "Poco/String.h" - - -using Poco::NumberFormatter; - - -namespace Poco { -namespace Net { - - -const std::string HTTPRequest::HTTP_GET = "GET"; -const std::string HTTPRequest::HTTP_HEAD = "HEAD"; -const std::string HTTPRequest::HTTP_PUT = "PUT"; -const std::string HTTPRequest::HTTP_POST = "POST"; -const std::string HTTPRequest::HTTP_OPTIONS = "OPTIONS"; -const std::string HTTPRequest::HTTP_DELETE = "DELETE"; -const std::string HTTPRequest::HTTP_TRACE = "TRACE"; -const std::string HTTPRequest::HTTP_CONNECT = "CONNECT"; -const std::string HTTPRequest::HTTP_PATCH = "PATCH"; -const std::string HTTPRequest::HOST = "Host"; -const std::string HTTPRequest::COOKIE = "Cookie"; -const std::string HTTPRequest::AUTHORIZATION = "Authorization"; -const std::string HTTPRequest::PROXY_AUTHORIZATION = "Proxy-Authorization"; -const std::string HTTPRequest::UPGRADE = "Upgrade"; -const std::string HTTPRequest::EXPECT = "Expect"; - - -HTTPRequest::HTTPRequest(): - _method(HTTP_GET), - _uri("/") -{ -} - - -HTTPRequest::HTTPRequest(const std::string& version): - HTTPMessage(version), - _method(HTTP_GET), - _uri("/") -{ -} - - -HTTPRequest::HTTPRequest(const std::string& method, const std::string& uri): - _method(method), - _uri(uri) -{ -} - - -HTTPRequest::HTTPRequest(const std::string& method, const std::string& uri, const std::string& version): - HTTPMessage(version), - _method(method), - _uri(uri) -{ -} - - -HTTPRequest::~HTTPRequest() -{ -} - - -void HTTPRequest::setMethod(const std::string& method) -{ - _method = method; -} - - -void HTTPRequest::setURI(const std::string& uri) -{ - _uri = uri; -} - - -void HTTPRequest::setHost(const std::string& host) -{ - set(HOST, host); -} - - -void HTTPRequest::setHost(const std::string& host, Poco::UInt16 port) -{ - std::string value; - if (host.find(':') != std::string::npos) - { - // IPv6 address - value.append("["); - value.append(host); - value.append("]"); - } - else - { - value.append(host); - } - - if (port != 80 && port != 443) - { - value.append(":"); - NumberFormatter::append(value, port); - } - setHost(value); -} - - -const std::string& HTTPRequest::getHost() const -{ - return get(HOST); -} - - -void HTTPRequest::setCookies(const NameValueCollection& cookies) -{ - std::string cookie; - cookie.reserve(64); - for (NameValueCollection::ConstIterator it = cookies.begin(); it != cookies.end(); ++it) - { - if (it != cookies.begin()) - cookie.append("; "); - cookie.append(it->first); - cookie.append("="); - cookie.append(it->second); - } - add(COOKIE, cookie); -} - - -void HTTPRequest::getCookies(NameValueCollection& cookies) const -{ - NameValueCollection::ConstIterator it = find(COOKIE); - while (it != end() && Poco::icompare(it->first, COOKIE) == 0) - { - splitParameters(it->second.begin(), it->second.end(), cookies); - ++it; - } -} - - -bool HTTPRequest::hasCredentials() const -{ - return has(AUTHORIZATION); -} - - -void HTTPRequest::getCredentials(std::string& scheme, std::string& authInfo) const -{ - getCredentials(AUTHORIZATION, scheme, authInfo); -} - - -void HTTPRequest::setCredentials(const std::string& scheme, const std::string& authInfo) -{ - setCredentials(AUTHORIZATION, scheme, authInfo); -} - - -bool HTTPRequest::hasProxyCredentials() const -{ - return has(PROXY_AUTHORIZATION); -} - - -void HTTPRequest::getProxyCredentials(std::string& scheme, std::string& authInfo) const -{ - getCredentials(PROXY_AUTHORIZATION, scheme, authInfo); -} - - -void HTTPRequest::setProxyCredentials(const std::string& scheme, const std::string& authInfo) -{ - setCredentials(PROXY_AUTHORIZATION, scheme, authInfo); -} - - -void HTTPRequest::write(std::ostream& ostr) const -{ - ostr << _method << " " << _uri << " " << getVersion() << "\r\n"; - HTTPMessage::write(ostr); - ostr << "\r\n"; -} - - -void HTTPRequest::read(std::istream& istr) -{ - static const int eof = std::char_traits<char>::eof(); - - std::string method; - std::string uri; - std::string version; - method.reserve(16); - uri.reserve(64); - version.reserve(16); - int ch = istr.get(); - if (istr.bad()) throw NetException("Error reading HTTP request header"); - if (ch == eof) throw NoMessageException(); - while (Poco::Ascii::isSpace(ch)) ch = istr.get(); - if (ch == eof) throw MessageException("No HTTP request header"); - while (!Poco::Ascii::isSpace(ch) && ch != eof && method.length() < MAX_METHOD_LENGTH) { method += (char) ch; ch = istr.get(); } - if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP request method invalid or too long"); - while (Poco::Ascii::isSpace(ch)) ch = istr.get(); - while (!Poco::Ascii::isSpace(ch) && ch != eof && uri.length() < MAX_URI_LENGTH) { uri += (char) ch; ch = istr.get(); } - if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP request URI invalid or too long"); - while (Poco::Ascii::isSpace(ch)) ch = istr.get(); - while (!Poco::Ascii::isSpace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); } - if (!Poco::Ascii::isSpace(ch)) throw MessageException("Invalid HTTP version string"); - while (ch != '\n' && ch != eof) { ch = istr.get(); } - HTTPMessage::read(istr); - ch = istr.get(); - while (ch != '\n' && ch != eof) { ch = istr.get(); } - setMethod(method); - setURI(uri); - setVersion(version); -} - - -void HTTPRequest::getCredentials(const std::string& header, std::string& scheme, std::string& authInfo) const -{ - scheme.clear(); - authInfo.clear(); - if (has(header)) - { - const std::string& auth = get(header); - std::string::const_iterator it = auth.begin(); - std::string::const_iterator end = auth.end(); - while (it != end && Poco::Ascii::isSpace(*it)) ++it; - while (it != end && !Poco::Ascii::isSpace(*it)) scheme += *it++; - while (it != end && Poco::Ascii::isSpace(*it)) ++it; - while (it != end) authInfo += *it++; - } - else throw NotAuthenticatedException(); -} - - -void HTTPRequest::setCredentials(const std::string& header, const std::string& scheme, const std::string& authInfo) -{ - std::string auth(scheme); - auth.append(" "); - auth.append(authInfo); - set(header, auth); -} - - -bool HTTPRequest::getExpectContinue() const -{ - const std::string& expect = get(EXPECT, EMPTY); - return !expect.empty() && icompare(expect, "100-continue") == 0; -} - - -void HTTPRequest::setExpectContinue(bool expectContinue) -{ - if (expectContinue) - set(EXPECT, "100-continue"); - else - erase(EXPECT); -} - - -} } // namespace Poco::Net +// +// HTTPRequest.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPRequest +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/NetException.h" +#include "Poco/Net/NameValueCollection.h" +#include "Poco/NumberFormatter.h" +#include "Poco/Ascii.h" +#include "Poco/String.h" + + +using Poco::NumberFormatter; + + +namespace Poco { +namespace Net { + + +const std::string HTTPRequest::HTTP_GET = "GET"; +const std::string HTTPRequest::HTTP_HEAD = "HEAD"; +const std::string HTTPRequest::HTTP_PUT = "PUT"; +const std::string HTTPRequest::HTTP_POST = "POST"; +const std::string HTTPRequest::HTTP_OPTIONS = "OPTIONS"; +const std::string HTTPRequest::HTTP_DELETE = "DELETE"; +const std::string HTTPRequest::HTTP_TRACE = "TRACE"; +const std::string HTTPRequest::HTTP_CONNECT = "CONNECT"; +const std::string HTTPRequest::HTTP_PATCH = "PATCH"; +const std::string HTTPRequest::HOST = "Host"; +const std::string HTTPRequest::COOKIE = "Cookie"; +const std::string HTTPRequest::AUTHORIZATION = "Authorization"; +const std::string HTTPRequest::PROXY_AUTHORIZATION = "Proxy-Authorization"; +const std::string HTTPRequest::UPGRADE = "Upgrade"; +const std::string HTTPRequest::EXPECT = "Expect"; + + +HTTPRequest::HTTPRequest(): + _method(HTTP_GET), + _uri("/") +{ +} + + +HTTPRequest::HTTPRequest(const std::string& version): + HTTPMessage(version), + _method(HTTP_GET), + _uri("/") +{ +} + + +HTTPRequest::HTTPRequest(const std::string& method, const std::string& uri): + _method(method), + _uri(uri) +{ +} + + +HTTPRequest::HTTPRequest(const std::string& method, const std::string& uri, const std::string& version): + HTTPMessage(version), + _method(method), + _uri(uri) +{ +} + + +HTTPRequest::~HTTPRequest() +{ +} + + +void HTTPRequest::setMethod(const std::string& method) +{ + _method = method; +} + + +void HTTPRequest::setURI(const std::string& uri) +{ + _uri = uri; +} + + +void HTTPRequest::setHost(const std::string& host) +{ + set(HOST, host); +} + + +void HTTPRequest::setHost(const std::string& host, Poco::UInt16 port) +{ + std::string value; + if (host.find(':') != std::string::npos) + { + // IPv6 address + value.append("["); + value.append(host); + value.append("]"); + } + else + { + value.append(host); + } + + if (port != 80 && port != 443) + { + value.append(":"); + NumberFormatter::append(value, port); + } + setHost(value); +} + + +const std::string& HTTPRequest::getHost() const +{ + return get(HOST); +} + + +void HTTPRequest::setCookies(const NameValueCollection& cookies) +{ + std::string cookie; + cookie.reserve(64); + for (NameValueCollection::ConstIterator it = cookies.begin(); it != cookies.end(); ++it) + { + if (it != cookies.begin()) + cookie.append("; "); + cookie.append(it->first); + cookie.append("="); + cookie.append(it->second); + } + add(COOKIE, cookie); +} + + +void HTTPRequest::getCookies(NameValueCollection& cookies) const +{ + NameValueCollection::ConstIterator it = find(COOKIE); + while (it != end() && Poco::icompare(it->first, COOKIE) == 0) + { + splitParameters(it->second.begin(), it->second.end(), cookies); + ++it; + } +} + + +bool HTTPRequest::hasCredentials() const +{ + return has(AUTHORIZATION); +} + + +void HTTPRequest::getCredentials(std::string& scheme, std::string& authInfo) const +{ + getCredentials(AUTHORIZATION, scheme, authInfo); +} + + +void HTTPRequest::setCredentials(const std::string& scheme, const std::string& authInfo) +{ + setCredentials(AUTHORIZATION, scheme, authInfo); +} + + +bool HTTPRequest::hasProxyCredentials() const +{ + return has(PROXY_AUTHORIZATION); +} + + +void HTTPRequest::getProxyCredentials(std::string& scheme, std::string& authInfo) const +{ + getCredentials(PROXY_AUTHORIZATION, scheme, authInfo); +} + + +void HTTPRequest::setProxyCredentials(const std::string& scheme, const std::string& authInfo) +{ + setCredentials(PROXY_AUTHORIZATION, scheme, authInfo); +} + + +void HTTPRequest::write(std::ostream& ostr) const +{ + ostr << _method << " " << _uri << " " << getVersion() << "\r\n"; + HTTPMessage::write(ostr); + ostr << "\r\n"; +} + + +void HTTPRequest::read(std::istream& istr) +{ + static const int eof = std::char_traits<char>::eof(); + + std::string method; + std::string uri; + std::string version; + method.reserve(16); + uri.reserve(64); + version.reserve(16); + int ch = istr.get(); + if (istr.bad()) throw NetException("Error reading HTTP request header"); + if (ch == eof) throw NoMessageException(); + while (Poco::Ascii::isSpace(ch)) ch = istr.get(); + if (ch == eof) throw MessageException("No HTTP request header"); + while (!Poco::Ascii::isSpace(ch) && ch != eof && method.length() < MAX_METHOD_LENGTH) { method += (char) ch; ch = istr.get(); } + if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP request method invalid or too long"); + while (Poco::Ascii::isSpace(ch)) ch = istr.get(); + while (!Poco::Ascii::isSpace(ch) && ch != eof && uri.length() < MAX_URI_LENGTH) { uri += (char) ch; ch = istr.get(); } + if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP request URI invalid or too long"); + while (Poco::Ascii::isSpace(ch)) ch = istr.get(); + while (!Poco::Ascii::isSpace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); } + if (!Poco::Ascii::isSpace(ch)) throw MessageException("Invalid HTTP version string"); + while (ch != '\n' && ch != eof) { ch = istr.get(); } + HTTPMessage::read(istr); + ch = istr.get(); + while (ch != '\n' && ch != eof) { ch = istr.get(); } + setMethod(method); + setURI(uri); + setVersion(version); +} + + +void HTTPRequest::getCredentials(const std::string& header, std::string& scheme, std::string& authInfo) const +{ + scheme.clear(); + authInfo.clear(); + if (has(header)) + { + const std::string& auth = get(header); + std::string::const_iterator it = auth.begin(); + std::string::const_iterator end = auth.end(); + while (it != end && Poco::Ascii::isSpace(*it)) ++it; + while (it != end && !Poco::Ascii::isSpace(*it)) scheme += *it++; + while (it != end && Poco::Ascii::isSpace(*it)) ++it; + while (it != end) authInfo += *it++; + } + else throw NotAuthenticatedException(); +} + + +void HTTPRequest::setCredentials(const std::string& header, const std::string& scheme, const std::string& authInfo) +{ + std::string auth(scheme); + auth.append(" "); + auth.append(authInfo); + set(header, auth); +} + + +bool HTTPRequest::getExpectContinue() const +{ + const std::string& expect = get(EXPECT, EMPTY); + return !expect.empty() && icompare(expect, "100-continue") == 0; +} + + +void HTTPRequest::setExpectContinue(bool expectContinue) +{ + if (expectContinue) + set(EXPECT, "100-continue"); + else + erase(EXPECT); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPRequestHandler.cpp b/contrib/libs/poco/Net/src/HTTPRequestHandler.cpp index 1d73ff8227..19d6c4a4ac 100644 --- a/contrib/libs/poco/Net/src/HTTPRequestHandler.cpp +++ b/contrib/libs/poco/Net/src/HTTPRequestHandler.cpp @@ -1,32 +1,32 @@ -// -// HTTPRequestHandler.cpp -// -// Library: Net -// Package: HTTPServer -// Module: HTTPRequestHandler -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPRequestHandler.h" - - -namespace Poco { -namespace Net { - - -HTTPRequestHandler::HTTPRequestHandler() -{ -} - - -HTTPRequestHandler::~HTTPRequestHandler() -{ -} - - -} } // namespace Poco::Net +// +// HTTPRequestHandler.cpp +// +// Library: Net +// Package: HTTPServer +// Module: HTTPRequestHandler +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPRequestHandler.h" + + +namespace Poco { +namespace Net { + + +HTTPRequestHandler::HTTPRequestHandler() +{ +} + + +HTTPRequestHandler::~HTTPRequestHandler() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPRequestHandlerFactory.cpp b/contrib/libs/poco/Net/src/HTTPRequestHandlerFactory.cpp index d6f44f070b..7381029ab0 100644 --- a/contrib/libs/poco/Net/src/HTTPRequestHandlerFactory.cpp +++ b/contrib/libs/poco/Net/src/HTTPRequestHandlerFactory.cpp @@ -1,32 +1,32 @@ -// -// HTTPRequestHandlerFactory.cpp -// -// Library: Net -// Package: HTTPServer -// Module: HTTPRequestHandlerFactory -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPRequestHandlerFactory.h" - - -namespace Poco { -namespace Net { - - -HTTPRequestHandlerFactory::HTTPRequestHandlerFactory() -{ -} - - -HTTPRequestHandlerFactory::~HTTPRequestHandlerFactory() -{ -} - - -} } // namespace Poco::Net +// +// HTTPRequestHandlerFactory.cpp +// +// Library: Net +// Package: HTTPServer +// Module: HTTPRequestHandlerFactory +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPRequestHandlerFactory.h" + + +namespace Poco { +namespace Net { + + +HTTPRequestHandlerFactory::HTTPRequestHandlerFactory() +{ +} + + +HTTPRequestHandlerFactory::~HTTPRequestHandlerFactory() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPResponse.cpp b/contrib/libs/poco/Net/src/HTTPResponse.cpp index 70093ac07e..1670b01049 100644 --- a/contrib/libs/poco/Net/src/HTTPResponse.cpp +++ b/contrib/libs/poco/Net/src/HTTPResponse.cpp @@ -1,390 +1,390 @@ -// -// HTTPResponse.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPResponse -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPResponse.h" -#include "Poco/Net/NetException.h" -#include "Poco/NumberFormatter.h" -#include "Poco/NumberParser.h" -#include "Poco/DateTime.h" -#include "Poco/DateTimeFormatter.h" -#include "Poco/DateTimeFormat.h" -#include "Poco/DateTimeParser.h" -#include "Poco/Ascii.h" -#include "Poco/String.h" - - -using Poco::DateTime; -using Poco::NumberFormatter; -using Poco::NumberParser; -using Poco::DateTimeFormatter; -using Poco::DateTimeFormat; -using Poco::DateTimeParser; - - -namespace Poco { -namespace Net { - - -const std::string HTTPResponse::HTTP_REASON_CONTINUE = "Continue"; -const std::string HTTPResponse::HTTP_REASON_SWITCHING_PROTOCOLS = "Switching Protocols"; -const std::string HTTPResponse::HTTP_REASON_PROCESSING = "Processing"; -const std::string HTTPResponse::HTTP_REASON_OK = "OK"; -const std::string HTTPResponse::HTTP_REASON_CREATED = "Created"; -const std::string HTTPResponse::HTTP_REASON_ACCEPTED = "Accepted"; -const std::string HTTPResponse::HTTP_REASON_NONAUTHORITATIVE = "Non-Authoritative Information"; -const std::string HTTPResponse::HTTP_REASON_NO_CONTENT = "No Content"; -const std::string HTTPResponse::HTTP_REASON_RESET_CONTENT = "Reset Content"; -const std::string HTTPResponse::HTTP_REASON_PARTIAL_CONTENT = "Partial Content"; -const std::string HTTPResponse::HTTP_REASON_MULTI_STATUS = "Multi Status"; -const std::string HTTPResponse::HTTP_REASON_ALREADY_REPORTED = "Already Reported"; -const std::string HTTPResponse::HTTP_REASON_IM_USED = "IM Used"; -const std::string HTTPResponse::HTTP_REASON_MULTIPLE_CHOICES = "Multiple Choices"; -const std::string HTTPResponse::HTTP_REASON_MOVED_PERMANENTLY = "Moved Permanently"; -const std::string HTTPResponse::HTTP_REASON_FOUND = "Found"; -const std::string HTTPResponse::HTTP_REASON_SEE_OTHER = "See Other"; -const std::string HTTPResponse::HTTP_REASON_NOT_MODIFIED = "Not Modified"; -const std::string HTTPResponse::HTTP_REASON_USE_PROXY = "Use Proxy"; -const std::string HTTPResponse::HTTP_REASON_TEMPORARY_REDIRECT = "Temporary Redirect"; -const std::string HTTPResponse::HTTP_REASON_PERMANENT_REDIRECT = "Permanent Redirect"; -const std::string HTTPResponse::HTTP_REASON_BAD_REQUEST = "Bad Request"; -const std::string HTTPResponse::HTTP_REASON_UNAUTHORIZED = "Unauthorized"; -const std::string HTTPResponse::HTTP_REASON_PAYMENT_REQUIRED = "Payment Required"; -const std::string HTTPResponse::HTTP_REASON_FORBIDDEN = "Forbidden"; -const std::string HTTPResponse::HTTP_REASON_NOT_FOUND = "Not Found"; -const std::string HTTPResponse::HTTP_REASON_METHOD_NOT_ALLOWED = "Method Not Allowed"; -const std::string HTTPResponse::HTTP_REASON_NOT_ACCEPTABLE = "Not Acceptable"; -const std::string HTTPResponse::HTTP_REASON_PROXY_AUTHENTICATION_REQUIRED = "Proxy Authentication Required"; -const std::string HTTPResponse::HTTP_REASON_REQUEST_TIMEOUT = "Request Time-out"; -const std::string HTTPResponse::HTTP_REASON_CONFLICT = "Conflict"; -const std::string HTTPResponse::HTTP_REASON_GONE = "Gone"; -const std::string HTTPResponse::HTTP_REASON_LENGTH_REQUIRED = "Length Required"; -const std::string HTTPResponse::HTTP_REASON_PRECONDITION_FAILED = "Precondition Failed"; -const std::string HTTPResponse::HTTP_REASON_REQUEST_ENTITY_TOO_LARGE = "Request Entity Too Large"; -const std::string HTTPResponse::HTTP_REASON_REQUEST_URI_TOO_LONG = "Request-URI Too Large"; -const std::string HTTPResponse::HTTP_REASON_UNSUPPORTED_MEDIA_TYPE = "Unsupported Media Type"; -const std::string HTTPResponse::HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE = "Requested Range Not Satisfiable"; -const std::string HTTPResponse::HTTP_REASON_EXPECTATION_FAILED = "Expectation Failed"; -const std::string HTTPResponse::HTTP_REASON_IM_A_TEAPOT = "I'm a Teapot"; -const std::string HTTPResponse::HTTP_REASON_ENCHANCE_YOUR_CALM = "Enchance Your Calm"; -const std::string HTTPResponse::HTTP_REASON_MISDIRECTED_REQUEST = "Misdirected Request"; -const std::string HTTPResponse::HTTP_REASON_UNPROCESSABLE_ENTITY = "Unprocessable Entity"; -const std::string HTTPResponse::HTTP_REASON_LOCKED = "Locked"; -const std::string HTTPResponse::HTTP_REASON_FAILED_DEPENDENCY = "Failed Dependency"; -const std::string HTTPResponse::HTTP_REASON_UPGRADE_REQUIRED = "Upgrade Required"; -const std::string HTTPResponse::HTTP_REASON_PRECONDITION_REQUIRED = "Precondition Required"; -const std::string HTTPResponse::HTTP_REASON_TOO_MANY_REQUESTS = "Too Many Requests"; -const std::string HTTPResponse::HTTP_REASON_REQUEST_HEADER_FIELDS_TOO_LARGE = "Request Header Fields Too Large"; -const std::string HTTPResponse::HTTP_REASON_UNAVAILABLE_FOR_LEGAL_REASONS = "Unavailable For Legal Reasons"; -const std::string HTTPResponse::HTTP_REASON_INTERNAL_SERVER_ERROR = "Internal Server Error"; -const std::string HTTPResponse::HTTP_REASON_NOT_IMPLEMENTED = "Not Implemented"; -const std::string HTTPResponse::HTTP_REASON_BAD_GATEWAY = "Bad Gateway"; -const std::string HTTPResponse::HTTP_REASON_SERVICE_UNAVAILABLE = "Service Unavailable"; -const std::string HTTPResponse::HTTP_REASON_GATEWAY_TIMEOUT = "Gateway Time-Out"; -const std::string HTTPResponse::HTTP_REASON_VERSION_NOT_SUPPORTED = "HTTP Version Not Supported"; -const std::string HTTPResponse::HTTP_REASON_VARIANT_ALSO_NEGOTIATES = "Variant Also Negotiates"; -const std::string HTTPResponse::HTTP_REASON_INSUFFICIENT_STORAGE = "Insufficient Storage"; -const std::string HTTPResponse::HTTP_REASON_LOOP_DETECTED = "Loop Detected"; -const std::string HTTPResponse::HTTP_REASON_NOT_EXTENDED = "Not Extended"; -const std::string HTTPResponse::HTTP_REASON_NETWORK_AUTHENTICATION_REQUIRED = "Network Authentication Required"; -const std::string HTTPResponse::HTTP_REASON_UNKNOWN = "???"; -const std::string HTTPResponse::DATE = "Date"; -const std::string HTTPResponse::SET_COOKIE = "Set-Cookie"; - - -HTTPResponse::HTTPResponse(): - _status(HTTP_OK), - _reason(getReasonForStatus(HTTP_OK)) -{ -} - - -HTTPResponse::HTTPResponse(HTTPStatus status, const std::string& reason): - _status(status), - _reason(reason) -{ -} - - - -HTTPResponse::HTTPResponse(const std::string& version, HTTPStatus status, const std::string& reason): - HTTPMessage(version), - _status(status), - _reason(reason) -{ -} - - -HTTPResponse::HTTPResponse(HTTPStatus status): - _status(status), - _reason(getReasonForStatus(status)) -{ -} - - -HTTPResponse::HTTPResponse(const std::string& version, HTTPStatus status): - HTTPMessage(version), - _status(status), - _reason(getReasonForStatus(status)) -{ -} - - -HTTPResponse::~HTTPResponse() -{ -} - - -void HTTPResponse::setStatus(HTTPStatus status) -{ - _status = status; -} - - -void HTTPResponse::setStatus(const std::string& status) -{ - setStatus((HTTPStatus) NumberParser::parse(status)); -} - - -void HTTPResponse::setReason(const std::string& reason) -{ - _reason = reason; -} - - -void HTTPResponse::setStatusAndReason(HTTPStatus status, const std::string& reason) -{ - _status = status; - _reason = reason; -} - - -void HTTPResponse::setStatusAndReason(HTTPStatus status) -{ - setStatusAndReason(status, getReasonForStatus(status)); -} - - -void HTTPResponse::setDate(const Poco::Timestamp& dateTime) -{ - set(DATE, DateTimeFormatter::format(dateTime, DateTimeFormat::HTTP_FORMAT)); -} - - -Poco::Timestamp HTTPResponse::getDate() const -{ - const std::string& dateTime = get(DATE); - int tzd; - return DateTimeParser::parse(dateTime, tzd).timestamp(); -} - - -void HTTPResponse::addCookie(const HTTPCookie& cookie) -{ - add(SET_COOKIE, cookie.toString()); -} - - -void HTTPResponse::getCookies(std::vector<HTTPCookie>& cookies) const -{ - cookies.clear(); - NameValueCollection::ConstIterator it = find(SET_COOKIE); - while (it != end() && Poco::icompare(it->first, SET_COOKIE) == 0) - { - NameValueCollection nvc; - splitParameters(it->second.begin(), it->second.end(), nvc); - cookies.push_back(HTTPCookie(nvc)); - ++it; - } -} - - -void HTTPResponse::write(std::ostream& ostr) const -{ - beginWrite(ostr); - ostr << "\r\n"; -} - - -void HTTPResponse::beginWrite(std::ostream& ostr) const -{ - ostr << getVersion() << " " << static_cast<int>(_status) << " " << _reason << "\r\n"; - HTTPMessage::write(ostr); -} - - -void HTTPResponse::read(std::istream& istr) -{ - static const int eof = std::char_traits<char>::eof(); - - std::string version; - std::string status; - std::string reason; - - int ch = istr.get(); - if (istr.bad()) throw NetException("Error reading HTTP response header"); - if (ch == eof) throw NoMessageException(); - while (Poco::Ascii::isSpace(ch)) ch = istr.get(); - if (ch == eof) throw MessageException("No HTTP response header"); - while (!Poco::Ascii::isSpace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); } - if (!Poco::Ascii::isSpace(ch)) throw MessageException("Invalid HTTP version string"); - while (Poco::Ascii::isSpace(ch)) ch = istr.get(); - while (!Poco::Ascii::isSpace(ch) && ch != eof && status.length() < MAX_STATUS_LENGTH) { status += (char) ch; ch = istr.get(); } - if (!Poco::Ascii::isSpace(ch)) throw MessageException("Invalid HTTP status code"); - while (Poco::Ascii::isSpace(ch) && ch != '\r' && ch != '\n' && ch != eof) ch = istr.get(); - while (ch != '\r' && ch != '\n' && ch != eof && reason.length() < MAX_REASON_LENGTH) { reason += (char) ch; ch = istr.get(); } - if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP reason string too long"); - if (ch == '\r') ch = istr.get(); - if (ch != '\n') throw MessageException("Unterminated HTTP response line"); - - HTTPMessage::read(istr); - ch = istr.get(); - while (ch != '\n' && ch != eof) { ch = istr.get(); } - setVersion(version); - setStatus(status); - setReason(reason); -} - - -const std::string& HTTPResponse::getReasonForStatus(HTTPStatus status) -{ - switch (status) - { - case HTTP_CONTINUE: - return HTTP_REASON_CONTINUE; - case HTTP_SWITCHING_PROTOCOLS: - return HTTP_REASON_SWITCHING_PROTOCOLS; - case HTTP_PROCESSING: - return HTTP_REASON_PROCESSING; - case HTTP_OK: - return HTTP_REASON_OK; - case HTTP_CREATED: - return HTTP_REASON_CREATED; - case HTTP_ACCEPTED: - return HTTP_REASON_ACCEPTED; - case HTTP_NONAUTHORITATIVE: - return HTTP_REASON_NONAUTHORITATIVE; - case HTTP_NO_CONTENT: - return HTTP_REASON_NO_CONTENT; - case HTTP_RESET_CONTENT: - return HTTP_REASON_RESET_CONTENT; - case HTTP_PARTIAL_CONTENT: - return HTTP_REASON_PARTIAL_CONTENT; - case HTTP_MULTI_STATUS: - return HTTP_REASON_MULTI_STATUS; - case HTTP_ALREADY_REPORTED: - return HTTP_REASON_ALREADY_REPORTED; - case HTTP_IM_USED: - return HTTP_REASON_IM_USED; - case HTTP_MULTIPLE_CHOICES: - return HTTP_REASON_MULTIPLE_CHOICES; - case HTTP_MOVED_PERMANENTLY: - return HTTP_REASON_MOVED_PERMANENTLY; - case HTTP_FOUND: - return HTTP_REASON_FOUND; - case HTTP_SEE_OTHER: - return HTTP_REASON_SEE_OTHER; - case HTTP_NOT_MODIFIED: - return HTTP_REASON_NOT_MODIFIED; - case HTTP_USE_PROXY: - return HTTP_REASON_USE_PROXY; - case HTTP_TEMPORARY_REDIRECT: - return HTTP_REASON_TEMPORARY_REDIRECT; - case HTTP_BAD_REQUEST: - return HTTP_REASON_BAD_REQUEST; - case HTTP_UNAUTHORIZED: - return HTTP_REASON_UNAUTHORIZED; - case HTTP_PAYMENT_REQUIRED: - return HTTP_REASON_PAYMENT_REQUIRED; - case HTTP_FORBIDDEN: - return HTTP_REASON_FORBIDDEN; - case HTTP_NOT_FOUND: - return HTTP_REASON_NOT_FOUND; - case HTTP_METHOD_NOT_ALLOWED: - return HTTP_REASON_METHOD_NOT_ALLOWED; - case HTTP_NOT_ACCEPTABLE: - return HTTP_REASON_NOT_ACCEPTABLE; - case HTTP_PROXY_AUTHENTICATION_REQUIRED: - return HTTP_REASON_PROXY_AUTHENTICATION_REQUIRED; - case HTTP_REQUEST_TIMEOUT: - return HTTP_REASON_REQUEST_TIMEOUT; - case HTTP_CONFLICT: - return HTTP_REASON_CONFLICT; - case HTTP_GONE: - return HTTP_REASON_GONE; - case HTTP_LENGTH_REQUIRED: - return HTTP_REASON_LENGTH_REQUIRED; - case HTTP_PRECONDITION_FAILED: - return HTTP_REASON_PRECONDITION_FAILED; - case HTTP_REQUEST_ENTITY_TOO_LARGE: - return HTTP_REASON_REQUEST_ENTITY_TOO_LARGE; - case HTTP_REQUEST_URI_TOO_LONG: - return HTTP_REASON_REQUEST_URI_TOO_LONG; - case HTTP_UNSUPPORTED_MEDIA_TYPE: - return HTTP_REASON_UNSUPPORTED_MEDIA_TYPE; - case HTTP_REQUESTED_RANGE_NOT_SATISFIABLE: - return HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE; - case HTTP_EXPECTATION_FAILED: - return HTTP_REASON_EXPECTATION_FAILED; - case HTTP_IM_A_TEAPOT: - return HTTP_REASON_IM_A_TEAPOT; - case HTTP_ENCHANCE_YOUR_CALM: - return HTTP_REASON_ENCHANCE_YOUR_CALM; - case HTTP_MISDIRECTED_REQUEST: - return HTTP_REASON_MISDIRECTED_REQUEST; - case HTTP_UNPROCESSABLE_ENTITY: - return HTTP_REASON_UNPROCESSABLE_ENTITY; - case HTTP_LOCKED: - return HTTP_REASON_LOCKED; - case HTTP_FAILED_DEPENDENCY: - return HTTP_REASON_FAILED_DEPENDENCY; - case HTTP_UPGRADE_REQUIRED: - return HTTP_REASON_UPGRADE_REQUIRED; - case HTTP_PRECONDITION_REQUIRED: - return HTTP_REASON_PRECONDITION_REQUIRED; - case HTTP_TOO_MANY_REQUESTS: - return HTTP_REASON_TOO_MANY_REQUESTS; - case HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE: - return HTTP_REASON_REQUEST_HEADER_FIELDS_TOO_LARGE; - case HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: - return HTTP_REASON_UNAVAILABLE_FOR_LEGAL_REASONS; - case HTTP_INTERNAL_SERVER_ERROR: - return HTTP_REASON_INTERNAL_SERVER_ERROR; - case HTTP_NOT_IMPLEMENTED: - return HTTP_REASON_NOT_IMPLEMENTED; - case HTTP_BAD_GATEWAY: - return HTTP_REASON_BAD_GATEWAY; - case HTTP_SERVICE_UNAVAILABLE: - return HTTP_REASON_SERVICE_UNAVAILABLE; - case HTTP_GATEWAY_TIMEOUT: - return HTTP_REASON_GATEWAY_TIMEOUT; - case HTTP_VERSION_NOT_SUPPORTED: - return HTTP_REASON_VERSION_NOT_SUPPORTED; - case HTTP_VARIANT_ALSO_NEGOTIATES: - return HTTP_REASON_VARIANT_ALSO_NEGOTIATES; - case HTTP_INSUFFICIENT_STORAGE: - return HTTP_REASON_INSUFFICIENT_STORAGE; - case HTTP_LOOP_DETECTED: - return HTTP_REASON_LOOP_DETECTED; - case HTTP_NOT_EXTENDED: - return HTTP_REASON_NOT_EXTENDED; - case HTTP_NETWORK_AUTHENTICATION_REQUIRED: - return HTTP_REASON_NETWORK_AUTHENTICATION_REQUIRED; - default: - return HTTP_REASON_UNKNOWN; - } -} - - -} } // namespace Poco::Net +// +// HTTPResponse.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPResponse +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPResponse.h" +#include "Poco/Net/NetException.h" +#include "Poco/NumberFormatter.h" +#include "Poco/NumberParser.h" +#include "Poco/DateTime.h" +#include "Poco/DateTimeFormatter.h" +#include "Poco/DateTimeFormat.h" +#include "Poco/DateTimeParser.h" +#include "Poco/Ascii.h" +#include "Poco/String.h" + + +using Poco::DateTime; +using Poco::NumberFormatter; +using Poco::NumberParser; +using Poco::DateTimeFormatter; +using Poco::DateTimeFormat; +using Poco::DateTimeParser; + + +namespace Poco { +namespace Net { + + +const std::string HTTPResponse::HTTP_REASON_CONTINUE = "Continue"; +const std::string HTTPResponse::HTTP_REASON_SWITCHING_PROTOCOLS = "Switching Protocols"; +const std::string HTTPResponse::HTTP_REASON_PROCESSING = "Processing"; +const std::string HTTPResponse::HTTP_REASON_OK = "OK"; +const std::string HTTPResponse::HTTP_REASON_CREATED = "Created"; +const std::string HTTPResponse::HTTP_REASON_ACCEPTED = "Accepted"; +const std::string HTTPResponse::HTTP_REASON_NONAUTHORITATIVE = "Non-Authoritative Information"; +const std::string HTTPResponse::HTTP_REASON_NO_CONTENT = "No Content"; +const std::string HTTPResponse::HTTP_REASON_RESET_CONTENT = "Reset Content"; +const std::string HTTPResponse::HTTP_REASON_PARTIAL_CONTENT = "Partial Content"; +const std::string HTTPResponse::HTTP_REASON_MULTI_STATUS = "Multi Status"; +const std::string HTTPResponse::HTTP_REASON_ALREADY_REPORTED = "Already Reported"; +const std::string HTTPResponse::HTTP_REASON_IM_USED = "IM Used"; +const std::string HTTPResponse::HTTP_REASON_MULTIPLE_CHOICES = "Multiple Choices"; +const std::string HTTPResponse::HTTP_REASON_MOVED_PERMANENTLY = "Moved Permanently"; +const std::string HTTPResponse::HTTP_REASON_FOUND = "Found"; +const std::string HTTPResponse::HTTP_REASON_SEE_OTHER = "See Other"; +const std::string HTTPResponse::HTTP_REASON_NOT_MODIFIED = "Not Modified"; +const std::string HTTPResponse::HTTP_REASON_USE_PROXY = "Use Proxy"; +const std::string HTTPResponse::HTTP_REASON_TEMPORARY_REDIRECT = "Temporary Redirect"; +const std::string HTTPResponse::HTTP_REASON_PERMANENT_REDIRECT = "Permanent Redirect"; +const std::string HTTPResponse::HTTP_REASON_BAD_REQUEST = "Bad Request"; +const std::string HTTPResponse::HTTP_REASON_UNAUTHORIZED = "Unauthorized"; +const std::string HTTPResponse::HTTP_REASON_PAYMENT_REQUIRED = "Payment Required"; +const std::string HTTPResponse::HTTP_REASON_FORBIDDEN = "Forbidden"; +const std::string HTTPResponse::HTTP_REASON_NOT_FOUND = "Not Found"; +const std::string HTTPResponse::HTTP_REASON_METHOD_NOT_ALLOWED = "Method Not Allowed"; +const std::string HTTPResponse::HTTP_REASON_NOT_ACCEPTABLE = "Not Acceptable"; +const std::string HTTPResponse::HTTP_REASON_PROXY_AUTHENTICATION_REQUIRED = "Proxy Authentication Required"; +const std::string HTTPResponse::HTTP_REASON_REQUEST_TIMEOUT = "Request Time-out"; +const std::string HTTPResponse::HTTP_REASON_CONFLICT = "Conflict"; +const std::string HTTPResponse::HTTP_REASON_GONE = "Gone"; +const std::string HTTPResponse::HTTP_REASON_LENGTH_REQUIRED = "Length Required"; +const std::string HTTPResponse::HTTP_REASON_PRECONDITION_FAILED = "Precondition Failed"; +const std::string HTTPResponse::HTTP_REASON_REQUEST_ENTITY_TOO_LARGE = "Request Entity Too Large"; +const std::string HTTPResponse::HTTP_REASON_REQUEST_URI_TOO_LONG = "Request-URI Too Large"; +const std::string HTTPResponse::HTTP_REASON_UNSUPPORTED_MEDIA_TYPE = "Unsupported Media Type"; +const std::string HTTPResponse::HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE = "Requested Range Not Satisfiable"; +const std::string HTTPResponse::HTTP_REASON_EXPECTATION_FAILED = "Expectation Failed"; +const std::string HTTPResponse::HTTP_REASON_IM_A_TEAPOT = "I'm a Teapot"; +const std::string HTTPResponse::HTTP_REASON_ENCHANCE_YOUR_CALM = "Enchance Your Calm"; +const std::string HTTPResponse::HTTP_REASON_MISDIRECTED_REQUEST = "Misdirected Request"; +const std::string HTTPResponse::HTTP_REASON_UNPROCESSABLE_ENTITY = "Unprocessable Entity"; +const std::string HTTPResponse::HTTP_REASON_LOCKED = "Locked"; +const std::string HTTPResponse::HTTP_REASON_FAILED_DEPENDENCY = "Failed Dependency"; +const std::string HTTPResponse::HTTP_REASON_UPGRADE_REQUIRED = "Upgrade Required"; +const std::string HTTPResponse::HTTP_REASON_PRECONDITION_REQUIRED = "Precondition Required"; +const std::string HTTPResponse::HTTP_REASON_TOO_MANY_REQUESTS = "Too Many Requests"; +const std::string HTTPResponse::HTTP_REASON_REQUEST_HEADER_FIELDS_TOO_LARGE = "Request Header Fields Too Large"; +const std::string HTTPResponse::HTTP_REASON_UNAVAILABLE_FOR_LEGAL_REASONS = "Unavailable For Legal Reasons"; +const std::string HTTPResponse::HTTP_REASON_INTERNAL_SERVER_ERROR = "Internal Server Error"; +const std::string HTTPResponse::HTTP_REASON_NOT_IMPLEMENTED = "Not Implemented"; +const std::string HTTPResponse::HTTP_REASON_BAD_GATEWAY = "Bad Gateway"; +const std::string HTTPResponse::HTTP_REASON_SERVICE_UNAVAILABLE = "Service Unavailable"; +const std::string HTTPResponse::HTTP_REASON_GATEWAY_TIMEOUT = "Gateway Time-Out"; +const std::string HTTPResponse::HTTP_REASON_VERSION_NOT_SUPPORTED = "HTTP Version Not Supported"; +const std::string HTTPResponse::HTTP_REASON_VARIANT_ALSO_NEGOTIATES = "Variant Also Negotiates"; +const std::string HTTPResponse::HTTP_REASON_INSUFFICIENT_STORAGE = "Insufficient Storage"; +const std::string HTTPResponse::HTTP_REASON_LOOP_DETECTED = "Loop Detected"; +const std::string HTTPResponse::HTTP_REASON_NOT_EXTENDED = "Not Extended"; +const std::string HTTPResponse::HTTP_REASON_NETWORK_AUTHENTICATION_REQUIRED = "Network Authentication Required"; +const std::string HTTPResponse::HTTP_REASON_UNKNOWN = "???"; +const std::string HTTPResponse::DATE = "Date"; +const std::string HTTPResponse::SET_COOKIE = "Set-Cookie"; + + +HTTPResponse::HTTPResponse(): + _status(HTTP_OK), + _reason(getReasonForStatus(HTTP_OK)) +{ +} + + +HTTPResponse::HTTPResponse(HTTPStatus status, const std::string& reason): + _status(status), + _reason(reason) +{ +} + + + +HTTPResponse::HTTPResponse(const std::string& version, HTTPStatus status, const std::string& reason): + HTTPMessage(version), + _status(status), + _reason(reason) +{ +} + + +HTTPResponse::HTTPResponse(HTTPStatus status): + _status(status), + _reason(getReasonForStatus(status)) +{ +} + + +HTTPResponse::HTTPResponse(const std::string& version, HTTPStatus status): + HTTPMessage(version), + _status(status), + _reason(getReasonForStatus(status)) +{ +} + + +HTTPResponse::~HTTPResponse() +{ +} + + +void HTTPResponse::setStatus(HTTPStatus status) +{ + _status = status; +} + + +void HTTPResponse::setStatus(const std::string& status) +{ + setStatus((HTTPStatus) NumberParser::parse(status)); +} + + +void HTTPResponse::setReason(const std::string& reason) +{ + _reason = reason; +} + + +void HTTPResponse::setStatusAndReason(HTTPStatus status, const std::string& reason) +{ + _status = status; + _reason = reason; +} + + +void HTTPResponse::setStatusAndReason(HTTPStatus status) +{ + setStatusAndReason(status, getReasonForStatus(status)); +} + + +void HTTPResponse::setDate(const Poco::Timestamp& dateTime) +{ + set(DATE, DateTimeFormatter::format(dateTime, DateTimeFormat::HTTP_FORMAT)); +} + + +Poco::Timestamp HTTPResponse::getDate() const +{ + const std::string& dateTime = get(DATE); + int tzd; + return DateTimeParser::parse(dateTime, tzd).timestamp(); +} + + +void HTTPResponse::addCookie(const HTTPCookie& cookie) +{ + add(SET_COOKIE, cookie.toString()); +} + + +void HTTPResponse::getCookies(std::vector<HTTPCookie>& cookies) const +{ + cookies.clear(); + NameValueCollection::ConstIterator it = find(SET_COOKIE); + while (it != end() && Poco::icompare(it->first, SET_COOKIE) == 0) + { + NameValueCollection nvc; + splitParameters(it->second.begin(), it->second.end(), nvc); + cookies.push_back(HTTPCookie(nvc)); + ++it; + } +} + + +void HTTPResponse::write(std::ostream& ostr) const +{ + beginWrite(ostr); + ostr << "\r\n"; +} + + +void HTTPResponse::beginWrite(std::ostream& ostr) const +{ + ostr << getVersion() << " " << static_cast<int>(_status) << " " << _reason << "\r\n"; + HTTPMessage::write(ostr); +} + + +void HTTPResponse::read(std::istream& istr) +{ + static const int eof = std::char_traits<char>::eof(); + + std::string version; + std::string status; + std::string reason; + + int ch = istr.get(); + if (istr.bad()) throw NetException("Error reading HTTP response header"); + if (ch == eof) throw NoMessageException(); + while (Poco::Ascii::isSpace(ch)) ch = istr.get(); + if (ch == eof) throw MessageException("No HTTP response header"); + while (!Poco::Ascii::isSpace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); } + if (!Poco::Ascii::isSpace(ch)) throw MessageException("Invalid HTTP version string"); + while (Poco::Ascii::isSpace(ch)) ch = istr.get(); + while (!Poco::Ascii::isSpace(ch) && ch != eof && status.length() < MAX_STATUS_LENGTH) { status += (char) ch; ch = istr.get(); } + if (!Poco::Ascii::isSpace(ch)) throw MessageException("Invalid HTTP status code"); + while (Poco::Ascii::isSpace(ch) && ch != '\r' && ch != '\n' && ch != eof) ch = istr.get(); + while (ch != '\r' && ch != '\n' && ch != eof && reason.length() < MAX_REASON_LENGTH) { reason += (char) ch; ch = istr.get(); } + if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP reason string too long"); + if (ch == '\r') ch = istr.get(); + if (ch != '\n') throw MessageException("Unterminated HTTP response line"); + + HTTPMessage::read(istr); + ch = istr.get(); + while (ch != '\n' && ch != eof) { ch = istr.get(); } + setVersion(version); + setStatus(status); + setReason(reason); +} + + +const std::string& HTTPResponse::getReasonForStatus(HTTPStatus status) +{ + switch (status) + { + case HTTP_CONTINUE: + return HTTP_REASON_CONTINUE; + case HTTP_SWITCHING_PROTOCOLS: + return HTTP_REASON_SWITCHING_PROTOCOLS; + case HTTP_PROCESSING: + return HTTP_REASON_PROCESSING; + case HTTP_OK: + return HTTP_REASON_OK; + case HTTP_CREATED: + return HTTP_REASON_CREATED; + case HTTP_ACCEPTED: + return HTTP_REASON_ACCEPTED; + case HTTP_NONAUTHORITATIVE: + return HTTP_REASON_NONAUTHORITATIVE; + case HTTP_NO_CONTENT: + return HTTP_REASON_NO_CONTENT; + case HTTP_RESET_CONTENT: + return HTTP_REASON_RESET_CONTENT; + case HTTP_PARTIAL_CONTENT: + return HTTP_REASON_PARTIAL_CONTENT; + case HTTP_MULTI_STATUS: + return HTTP_REASON_MULTI_STATUS; + case HTTP_ALREADY_REPORTED: + return HTTP_REASON_ALREADY_REPORTED; + case HTTP_IM_USED: + return HTTP_REASON_IM_USED; + case HTTP_MULTIPLE_CHOICES: + return HTTP_REASON_MULTIPLE_CHOICES; + case HTTP_MOVED_PERMANENTLY: + return HTTP_REASON_MOVED_PERMANENTLY; + case HTTP_FOUND: + return HTTP_REASON_FOUND; + case HTTP_SEE_OTHER: + return HTTP_REASON_SEE_OTHER; + case HTTP_NOT_MODIFIED: + return HTTP_REASON_NOT_MODIFIED; + case HTTP_USE_PROXY: + return HTTP_REASON_USE_PROXY; + case HTTP_TEMPORARY_REDIRECT: + return HTTP_REASON_TEMPORARY_REDIRECT; + case HTTP_BAD_REQUEST: + return HTTP_REASON_BAD_REQUEST; + case HTTP_UNAUTHORIZED: + return HTTP_REASON_UNAUTHORIZED; + case HTTP_PAYMENT_REQUIRED: + return HTTP_REASON_PAYMENT_REQUIRED; + case HTTP_FORBIDDEN: + return HTTP_REASON_FORBIDDEN; + case HTTP_NOT_FOUND: + return HTTP_REASON_NOT_FOUND; + case HTTP_METHOD_NOT_ALLOWED: + return HTTP_REASON_METHOD_NOT_ALLOWED; + case HTTP_NOT_ACCEPTABLE: + return HTTP_REASON_NOT_ACCEPTABLE; + case HTTP_PROXY_AUTHENTICATION_REQUIRED: + return HTTP_REASON_PROXY_AUTHENTICATION_REQUIRED; + case HTTP_REQUEST_TIMEOUT: + return HTTP_REASON_REQUEST_TIMEOUT; + case HTTP_CONFLICT: + return HTTP_REASON_CONFLICT; + case HTTP_GONE: + return HTTP_REASON_GONE; + case HTTP_LENGTH_REQUIRED: + return HTTP_REASON_LENGTH_REQUIRED; + case HTTP_PRECONDITION_FAILED: + return HTTP_REASON_PRECONDITION_FAILED; + case HTTP_REQUEST_ENTITY_TOO_LARGE: + return HTTP_REASON_REQUEST_ENTITY_TOO_LARGE; + case HTTP_REQUEST_URI_TOO_LONG: + return HTTP_REASON_REQUEST_URI_TOO_LONG; + case HTTP_UNSUPPORTED_MEDIA_TYPE: + return HTTP_REASON_UNSUPPORTED_MEDIA_TYPE; + case HTTP_REQUESTED_RANGE_NOT_SATISFIABLE: + return HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE; + case HTTP_EXPECTATION_FAILED: + return HTTP_REASON_EXPECTATION_FAILED; + case HTTP_IM_A_TEAPOT: + return HTTP_REASON_IM_A_TEAPOT; + case HTTP_ENCHANCE_YOUR_CALM: + return HTTP_REASON_ENCHANCE_YOUR_CALM; + case HTTP_MISDIRECTED_REQUEST: + return HTTP_REASON_MISDIRECTED_REQUEST; + case HTTP_UNPROCESSABLE_ENTITY: + return HTTP_REASON_UNPROCESSABLE_ENTITY; + case HTTP_LOCKED: + return HTTP_REASON_LOCKED; + case HTTP_FAILED_DEPENDENCY: + return HTTP_REASON_FAILED_DEPENDENCY; + case HTTP_UPGRADE_REQUIRED: + return HTTP_REASON_UPGRADE_REQUIRED; + case HTTP_PRECONDITION_REQUIRED: + return HTTP_REASON_PRECONDITION_REQUIRED; + case HTTP_TOO_MANY_REQUESTS: + return HTTP_REASON_TOO_MANY_REQUESTS; + case HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE: + return HTTP_REASON_REQUEST_HEADER_FIELDS_TOO_LARGE; + case HTTP_UNAVAILABLE_FOR_LEGAL_REASONS: + return HTTP_REASON_UNAVAILABLE_FOR_LEGAL_REASONS; + case HTTP_INTERNAL_SERVER_ERROR: + return HTTP_REASON_INTERNAL_SERVER_ERROR; + case HTTP_NOT_IMPLEMENTED: + return HTTP_REASON_NOT_IMPLEMENTED; + case HTTP_BAD_GATEWAY: + return HTTP_REASON_BAD_GATEWAY; + case HTTP_SERVICE_UNAVAILABLE: + return HTTP_REASON_SERVICE_UNAVAILABLE; + case HTTP_GATEWAY_TIMEOUT: + return HTTP_REASON_GATEWAY_TIMEOUT; + case HTTP_VERSION_NOT_SUPPORTED: + return HTTP_REASON_VERSION_NOT_SUPPORTED; + case HTTP_VARIANT_ALSO_NEGOTIATES: + return HTTP_REASON_VARIANT_ALSO_NEGOTIATES; + case HTTP_INSUFFICIENT_STORAGE: + return HTTP_REASON_INSUFFICIENT_STORAGE; + case HTTP_LOOP_DETECTED: + return HTTP_REASON_LOOP_DETECTED; + case HTTP_NOT_EXTENDED: + return HTTP_REASON_NOT_EXTENDED; + case HTTP_NETWORK_AUTHENTICATION_REQUIRED: + return HTTP_REASON_NETWORK_AUTHENTICATION_REQUIRED; + default: + return HTTP_REASON_UNKNOWN; + } +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPServer.cpp b/contrib/libs/poco/Net/src/HTTPServer.cpp index 31aa83d1be..27c54bbe9f 100644 --- a/contrib/libs/poco/Net/src/HTTPServer.cpp +++ b/contrib/libs/poco/Net/src/HTTPServer.cpp @@ -1,56 +1,56 @@ -// -// HTTPServer.cpp -// -// Library: Net -// Package: HTTPServer -// Module: HTTPServer -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPServer.h" -#include "Poco/Net/HTTPServerConnectionFactory.h" - - -namespace Poco { -namespace Net { - - -HTTPServer::HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, Poco::UInt16 portNumber, HTTPServerParams::Ptr pParams): - TCPServer(new HTTPServerConnectionFactory(pParams, pFactory), portNumber, pParams), - _pFactory(pFactory) -{ -} - - -HTTPServer::HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, const ServerSocket& socket, HTTPServerParams::Ptr pParams): - TCPServer(new HTTPServerConnectionFactory(pParams, pFactory), socket, pParams), - _pFactory(pFactory) -{ -} - - -HTTPServer::HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, Poco::ThreadPool& threadPool, const ServerSocket& socket, HTTPServerParams::Ptr pParams): - TCPServer(new HTTPServerConnectionFactory(pParams, pFactory), threadPool, socket, pParams), - _pFactory(pFactory) -{ -} - - -HTTPServer::~HTTPServer() -{ -} - - -void HTTPServer::stopAll(bool abortCurrent) -{ - stop(); - _pFactory->serverStopped(this, abortCurrent); -} - - -} } // namespace Poco::Net +// +// HTTPServer.cpp +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServer +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPServer.h" +#include "Poco/Net/HTTPServerConnectionFactory.h" + + +namespace Poco { +namespace Net { + + +HTTPServer::HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, Poco::UInt16 portNumber, HTTPServerParams::Ptr pParams): + TCPServer(new HTTPServerConnectionFactory(pParams, pFactory), portNumber, pParams), + _pFactory(pFactory) +{ +} + + +HTTPServer::HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, const ServerSocket& socket, HTTPServerParams::Ptr pParams): + TCPServer(new HTTPServerConnectionFactory(pParams, pFactory), socket, pParams), + _pFactory(pFactory) +{ +} + + +HTTPServer::HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, Poco::ThreadPool& threadPool, const ServerSocket& socket, HTTPServerParams::Ptr pParams): + TCPServer(new HTTPServerConnectionFactory(pParams, pFactory), threadPool, socket, pParams), + _pFactory(pFactory) +{ +} + + +HTTPServer::~HTTPServer() +{ +} + + +void HTTPServer::stopAll(bool abortCurrent) +{ + stop(); + _pFactory->serverStopped(this, abortCurrent); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPServerConnection.cpp b/contrib/libs/poco/Net/src/HTTPServerConnection.cpp index a6c27ce8c9..6984b2f616 100644 --- a/contrib/libs/poco/Net/src/HTTPServerConnection.cpp +++ b/contrib/libs/poco/Net/src/HTTPServerConnection.cpp @@ -1,180 +1,180 @@ -// -// HTTPServerConnection.cpp -// -// Library: Net -// Package: HTTPServer -// Module: HTTPServerConnection -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPServerConnection.h" -#include "Poco/Net/HTTPServerSession.h" -#include "Poco/Net/HTTPServerRequestImpl.h" -#include "Poco/Net/HTTPServerResponseImpl.h" -#include "Poco/Net/HTTPRequestHandler.h" -#include "Poco/Net/HTTPRequestHandlerFactory.h" -#include "Poco/Net/NetException.h" -#include "Poco/NumberFormatter.h" -#include "Poco/Timestamp.h" -#include "Poco/Delegate.h" -#include <memory> - - -namespace Poco { -namespace Net { - - -HTTPServerConnection::HTTPServerConnection(const StreamSocket& socket, HTTPServerParams::Ptr pParams, HTTPRequestHandlerFactory::Ptr pFactory): - TCPServerConnection(socket), - _pParams(pParams), - _pFactory(pFactory), - _stopped(false) -{ - poco_check_ptr (pFactory); - - _pFactory->serverStopped += Poco::delegate(this, &HTTPServerConnection::onServerStopped); -} - - -HTTPServerConnection::~HTTPServerConnection() -{ - try - { - _pFactory->serverStopped -= Poco::delegate(this, &HTTPServerConnection::onServerStopped); - } - catch (...) - { - poco_unexpected(); - } -} - - -void HTTPServerConnection::run() -{ - std::string server = _pParams->getSoftwareVersion(); - HTTPServerSession session(socket(), _pParams); - while (!_stopped && session.hasMoreRequests()) - { - try - { - Poco::FastMutex::ScopedLock lock(_mutex); - if (!_stopped) - { - HTTPServerResponseImpl response(session); - HTTPServerRequestImpl request(response, session, _pParams); - - Poco::Timestamp now; - response.setDate(now); - response.setVersion(request.getVersion()); - response.setKeepAlive(_pParams->getKeepAlive() && request.getKeepAlive() && session.canKeepAlive()); - if (!server.empty()) - response.set("Server", server); - try - { -#ifndef POCO_ENABLE_CPP11 - std::auto_ptr<HTTPRequestHandler> pHandler(_pFactory->createRequestHandler(request)); -#else - std::unique_ptr<HTTPRequestHandler> pHandler(_pFactory->createRequestHandler(request)); -#endif - if (pHandler.get()) - { - if (request.getExpectContinue() && response.getStatus() == HTTPResponse::HTTP_OK) - response.sendContinue(); - - pHandler->handleRequest(request, response); - session.setKeepAlive(_pParams->getKeepAlive() && response.getKeepAlive() && session.canKeepAlive()); - } - else sendErrorResponse(session, HTTPResponse::HTTP_NOT_IMPLEMENTED); - } - catch (Poco::Exception&) - { - if (!response.sent()) - { - try - { - sendErrorResponse(session, HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); - } - catch (...) - { - } - } - throw; - } - } - } - catch (NoMessageException&) - { - break; - } - catch (MessageException&) - { - sendErrorResponse(session, HTTPResponse::HTTP_BAD_REQUEST); - } - catch (Poco::Exception&) - { - if (session.networkException()) - { - session.networkException()->rethrow(); - } - else throw; - } - } -} - - -void HTTPServerConnection::sendErrorResponse(HTTPServerSession& session, HTTPResponse::HTTPStatus status) -{ - HTTPServerResponseImpl response(session); - response.setVersion(HTTPMessage::HTTP_1_1); - response.setStatusAndReason(status); - response.setKeepAlive(false); - response.send(); - session.setKeepAlive(false); -} - - -void HTTPServerConnection::onServerStopped(const bool& abortCurrent) -{ - _stopped = true; - if (abortCurrent) - { - try - { - // Note: On Windows, select() will not return if one of its socket is being - // shut down. Therefore we have to call close(), which works better. - // On other platforms, we do the more graceful thing. -#if defined(_WIN32) - socket().close(); -#else - socket().shutdown(); -#endif - } - catch (...) - { - } - } - else - { - Poco::FastMutex::ScopedLock lock(_mutex); - - try - { -#if defined(_WIN32) - socket().close(); -#else - socket().shutdown(); -#endif - } - catch (...) - { - } - } -} - - -} } // namespace Poco::Net +// +// HTTPServerConnection.cpp +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerConnection +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPServerConnection.h" +#include "Poco/Net/HTTPServerSession.h" +#include "Poco/Net/HTTPServerRequestImpl.h" +#include "Poco/Net/HTTPServerResponseImpl.h" +#include "Poco/Net/HTTPRequestHandler.h" +#include "Poco/Net/HTTPRequestHandlerFactory.h" +#include "Poco/Net/NetException.h" +#include "Poco/NumberFormatter.h" +#include "Poco/Timestamp.h" +#include "Poco/Delegate.h" +#include <memory> + + +namespace Poco { +namespace Net { + + +HTTPServerConnection::HTTPServerConnection(const StreamSocket& socket, HTTPServerParams::Ptr pParams, HTTPRequestHandlerFactory::Ptr pFactory): + TCPServerConnection(socket), + _pParams(pParams), + _pFactory(pFactory), + _stopped(false) +{ + poco_check_ptr (pFactory); + + _pFactory->serverStopped += Poco::delegate(this, &HTTPServerConnection::onServerStopped); +} + + +HTTPServerConnection::~HTTPServerConnection() +{ + try + { + _pFactory->serverStopped -= Poco::delegate(this, &HTTPServerConnection::onServerStopped); + } + catch (...) + { + poco_unexpected(); + } +} + + +void HTTPServerConnection::run() +{ + std::string server = _pParams->getSoftwareVersion(); + HTTPServerSession session(socket(), _pParams); + while (!_stopped && session.hasMoreRequests()) + { + try + { + Poco::FastMutex::ScopedLock lock(_mutex); + if (!_stopped) + { + HTTPServerResponseImpl response(session); + HTTPServerRequestImpl request(response, session, _pParams); + + Poco::Timestamp now; + response.setDate(now); + response.setVersion(request.getVersion()); + response.setKeepAlive(_pParams->getKeepAlive() && request.getKeepAlive() && session.canKeepAlive()); + if (!server.empty()) + response.set("Server", server); + try + { +#ifndef POCO_ENABLE_CPP11 + std::auto_ptr<HTTPRequestHandler> pHandler(_pFactory->createRequestHandler(request)); +#else + std::unique_ptr<HTTPRequestHandler> pHandler(_pFactory->createRequestHandler(request)); +#endif + if (pHandler.get()) + { + if (request.getExpectContinue() && response.getStatus() == HTTPResponse::HTTP_OK) + response.sendContinue(); + + pHandler->handleRequest(request, response); + session.setKeepAlive(_pParams->getKeepAlive() && response.getKeepAlive() && session.canKeepAlive()); + } + else sendErrorResponse(session, HTTPResponse::HTTP_NOT_IMPLEMENTED); + } + catch (Poco::Exception&) + { + if (!response.sent()) + { + try + { + sendErrorResponse(session, HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); + } + catch (...) + { + } + } + throw; + } + } + } + catch (NoMessageException&) + { + break; + } + catch (MessageException&) + { + sendErrorResponse(session, HTTPResponse::HTTP_BAD_REQUEST); + } + catch (Poco::Exception&) + { + if (session.networkException()) + { + session.networkException()->rethrow(); + } + else throw; + } + } +} + + +void HTTPServerConnection::sendErrorResponse(HTTPServerSession& session, HTTPResponse::HTTPStatus status) +{ + HTTPServerResponseImpl response(session); + response.setVersion(HTTPMessage::HTTP_1_1); + response.setStatusAndReason(status); + response.setKeepAlive(false); + response.send(); + session.setKeepAlive(false); +} + + +void HTTPServerConnection::onServerStopped(const bool& abortCurrent) +{ + _stopped = true; + if (abortCurrent) + { + try + { + // Note: On Windows, select() will not return if one of its socket is being + // shut down. Therefore we have to call close(), which works better. + // On other platforms, we do the more graceful thing. +#if defined(_WIN32) + socket().close(); +#else + socket().shutdown(); +#endif + } + catch (...) + { + } + } + else + { + Poco::FastMutex::ScopedLock lock(_mutex); + + try + { +#if defined(_WIN32) + socket().close(); +#else + socket().shutdown(); +#endif + } + catch (...) + { + } + } +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPServerConnectionFactory.cpp b/contrib/libs/poco/Net/src/HTTPServerConnectionFactory.cpp index 8e17288f3b..eff734af03 100644 --- a/contrib/libs/poco/Net/src/HTTPServerConnectionFactory.cpp +++ b/contrib/libs/poco/Net/src/HTTPServerConnectionFactory.cpp @@ -1,43 +1,43 @@ -// -// HTTPServerConnectionFactory.cpp -// -// Library: Net -// Package: HTTPServer -// Module: HTTPServerConnectionFactory -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPServerConnectionFactory.h" -#include "Poco/Net/HTTPServerConnection.h" -#include "Poco/Net/HTTPRequestHandlerFactory.h" - - -namespace Poco { -namespace Net { - - -HTTPServerConnectionFactory::HTTPServerConnectionFactory(HTTPServerParams::Ptr pParams, HTTPRequestHandlerFactory::Ptr pFactory): - _pParams(pParams), - _pFactory(pFactory) -{ - poco_check_ptr (pFactory); -} - - -HTTPServerConnectionFactory::~HTTPServerConnectionFactory() -{ -} - - -TCPServerConnection* HTTPServerConnectionFactory::createConnection(const StreamSocket& socket) -{ - return new HTTPServerConnection(socket, _pParams, _pFactory); -} - - -} } // namespace Poco::Net +// +// HTTPServerConnectionFactory.cpp +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerConnectionFactory +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPServerConnectionFactory.h" +#include "Poco/Net/HTTPServerConnection.h" +#include "Poco/Net/HTTPRequestHandlerFactory.h" + + +namespace Poco { +namespace Net { + + +HTTPServerConnectionFactory::HTTPServerConnectionFactory(HTTPServerParams::Ptr pParams, HTTPRequestHandlerFactory::Ptr pFactory): + _pParams(pParams), + _pFactory(pFactory) +{ + poco_check_ptr (pFactory); +} + + +HTTPServerConnectionFactory::~HTTPServerConnectionFactory() +{ +} + + +TCPServerConnection* HTTPServerConnectionFactory::createConnection(const StreamSocket& socket) +{ + return new HTTPServerConnection(socket, _pParams, _pFactory); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPServerParams.cpp b/contrib/libs/poco/Net/src/HTTPServerParams.cpp index cc87161111..87ae54d990 100644 --- a/contrib/libs/poco/Net/src/HTTPServerParams.cpp +++ b/contrib/libs/poco/Net/src/HTTPServerParams.cpp @@ -1,73 +1,73 @@ -// -// HTTPServerParams.cpp -// -// Library: Net -// Package: HTTPServer -// Module: HTTPServerParams -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPServerParams.h" - - -namespace Poco { -namespace Net { - - -HTTPServerParams::HTTPServerParams(): - _timeout(60000000), - _keepAlive(true), - _maxKeepAliveRequests(0), - _keepAliveTimeout(15000000) -{ -} - - -HTTPServerParams::~HTTPServerParams() -{ -} - - -void HTTPServerParams::setServerName(const std::string& serverName) -{ - _serverName = serverName; -} - - -void HTTPServerParams::setSoftwareVersion(const std::string& softwareVersion) -{ - _softwareVersion = softwareVersion; -} - - -void HTTPServerParams::setTimeout(const Poco::Timespan& timeout) -{ - _timeout = timeout; -} - - -void HTTPServerParams::setKeepAlive(bool keepAlive) -{ - _keepAlive = keepAlive; -} - - -void HTTPServerParams::setKeepAliveTimeout(const Poco::Timespan& timeout) -{ - _keepAliveTimeout = timeout; -} - - -void HTTPServerParams::setMaxKeepAliveRequests(int maxKeepAliveRequests) -{ - poco_assert (maxKeepAliveRequests >= 0); - _maxKeepAliveRequests = maxKeepAliveRequests; -} - - -} } // namespace Poco::Net +// +// HTTPServerParams.cpp +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerParams +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPServerParams.h" + + +namespace Poco { +namespace Net { + + +HTTPServerParams::HTTPServerParams(): + _timeout(60000000), + _keepAlive(true), + _maxKeepAliveRequests(0), + _keepAliveTimeout(15000000) +{ +} + + +HTTPServerParams::~HTTPServerParams() +{ +} + + +void HTTPServerParams::setServerName(const std::string& serverName) +{ + _serverName = serverName; +} + + +void HTTPServerParams::setSoftwareVersion(const std::string& softwareVersion) +{ + _softwareVersion = softwareVersion; +} + + +void HTTPServerParams::setTimeout(const Poco::Timespan& timeout) +{ + _timeout = timeout; +} + + +void HTTPServerParams::setKeepAlive(bool keepAlive) +{ + _keepAlive = keepAlive; +} + + +void HTTPServerParams::setKeepAliveTimeout(const Poco::Timespan& timeout) +{ + _keepAliveTimeout = timeout; +} + + +void HTTPServerParams::setMaxKeepAliveRequests(int maxKeepAliveRequests) +{ + poco_assert (maxKeepAliveRequests >= 0); + _maxKeepAliveRequests = maxKeepAliveRequests; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPServerRequest.cpp b/contrib/libs/poco/Net/src/HTTPServerRequest.cpp index de3d46481a..f5f78f90be 100644 --- a/contrib/libs/poco/Net/src/HTTPServerRequest.cpp +++ b/contrib/libs/poco/Net/src/HTTPServerRequest.cpp @@ -1,32 +1,32 @@ -// -// HTTPServerRequest.cpp -// -// Library: Net -// Package: HTTPServer -// Module: HTTPServerRequest -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPServerRequest.h" - - -namespace Poco { -namespace Net { - - -HTTPServerRequest::HTTPServerRequest() -{ -} - - -HTTPServerRequest::~HTTPServerRequest() -{ -} - - -} } // namespace Poco::Net +// +// HTTPServerRequest.cpp +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerRequest +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPServerRequest.h" + + +namespace Poco { +namespace Net { + + +HTTPServerRequest::HTTPServerRequest() +{ +} + + +HTTPServerRequest::~HTTPServerRequest() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPServerRequestImpl.cpp b/contrib/libs/poco/Net/src/HTTPServerRequestImpl.cpp index d8ea7398c9..aee484089b 100644 --- a/contrib/libs/poco/Net/src/HTTPServerRequestImpl.cpp +++ b/contrib/libs/poco/Net/src/HTTPServerRequestImpl.cpp @@ -1,88 +1,88 @@ -// -// HTTPServerRequestImpl.cpp -// -// Library: Net -// Package: HTTPServer -// Module: HTTPServerRequestImpl -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPServerRequestImpl.h" -#include "Poco/Net/HTTPServerResponseImpl.h" -#include "Poco/Net/HTTPServerSession.h" -#include "Poco/Net/HTTPHeaderStream.h" -#include "Poco/Net/HTTPStream.h" -#include "Poco/Net/HTTPFixedLengthStream.h" -#include "Poco/Net/HTTPChunkedStream.h" -#include "Poco/Net/HTTPServerParams.h" -#include "Poco/Net/StreamSocket.h" -#include "Poco/String.h" - - -using Poco::icompare; - - -namespace Poco { -namespace Net { - - -HTTPServerRequestImpl::HTTPServerRequestImpl(HTTPServerResponseImpl& response, HTTPServerSession& session, HTTPServerParams* pParams): - _response(response), - _session(session), - _pStream(0), - _pParams(pParams, true) -{ - response.attachRequest(this); - - HTTPHeaderInputStream hs(session); - read(hs); - - // Now that we know socket is still connected, obtain addresses - _clientAddress = session.clientAddress(); - _serverAddress = session.serverAddress(); - - if (getChunkedTransferEncoding()) - _pStream = new HTTPChunkedInputStream(session); - else if (hasContentLength()) -#if defined(POCO_HAVE_INT64) - _pStream = new HTTPFixedLengthInputStream(session, getContentLength64()); -#else - _pStream = new HTTPFixedLengthInputStream(session, getContentLength()); -#endif - else if (getMethod() == HTTPRequest::HTTP_GET || getMethod() == HTTPRequest::HTTP_HEAD || getMethod() == HTTPRequest::HTTP_DELETE) - _pStream = new HTTPFixedLengthInputStream(session, 0); - else - _pStream = new HTTPInputStream(session); -} - - -HTTPServerRequestImpl::~HTTPServerRequestImpl() -{ - delete _pStream; -} - - -bool HTTPServerRequestImpl::secure() const -{ - return _session.socket().secure(); -} - - -StreamSocket& HTTPServerRequestImpl::socket() -{ - return _session.socket(); -} - - -StreamSocket HTTPServerRequestImpl::detachSocket() -{ - return _session.detachSocket(); -} - - -} } // namespace Poco::Net +// +// HTTPServerRequestImpl.cpp +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerRequestImpl +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPServerRequestImpl.h" +#include "Poco/Net/HTTPServerResponseImpl.h" +#include "Poco/Net/HTTPServerSession.h" +#include "Poco/Net/HTTPHeaderStream.h" +#include "Poco/Net/HTTPStream.h" +#include "Poco/Net/HTTPFixedLengthStream.h" +#include "Poco/Net/HTTPChunkedStream.h" +#include "Poco/Net/HTTPServerParams.h" +#include "Poco/Net/StreamSocket.h" +#include "Poco/String.h" + + +using Poco::icompare; + + +namespace Poco { +namespace Net { + + +HTTPServerRequestImpl::HTTPServerRequestImpl(HTTPServerResponseImpl& response, HTTPServerSession& session, HTTPServerParams* pParams): + _response(response), + _session(session), + _pStream(0), + _pParams(pParams, true) +{ + response.attachRequest(this); + + HTTPHeaderInputStream hs(session); + read(hs); + + // Now that we know socket is still connected, obtain addresses + _clientAddress = session.clientAddress(); + _serverAddress = session.serverAddress(); + + if (getChunkedTransferEncoding()) + _pStream = new HTTPChunkedInputStream(session); + else if (hasContentLength()) +#if defined(POCO_HAVE_INT64) + _pStream = new HTTPFixedLengthInputStream(session, getContentLength64()); +#else + _pStream = new HTTPFixedLengthInputStream(session, getContentLength()); +#endif + else if (getMethod() == HTTPRequest::HTTP_GET || getMethod() == HTTPRequest::HTTP_HEAD || getMethod() == HTTPRequest::HTTP_DELETE) + _pStream = new HTTPFixedLengthInputStream(session, 0); + else + _pStream = new HTTPInputStream(session); +} + + +HTTPServerRequestImpl::~HTTPServerRequestImpl() +{ + delete _pStream; +} + + +bool HTTPServerRequestImpl::secure() const +{ + return _session.socket().secure(); +} + + +StreamSocket& HTTPServerRequestImpl::socket() +{ + return _session.socket(); +} + + +StreamSocket HTTPServerRequestImpl::detachSocket() +{ + return _session.detachSocket(); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPServerResponse.cpp b/contrib/libs/poco/Net/src/HTTPServerResponse.cpp index e5550a3222..9208d3b2cb 100644 --- a/contrib/libs/poco/Net/src/HTTPServerResponse.cpp +++ b/contrib/libs/poco/Net/src/HTTPServerResponse.cpp @@ -1,32 +1,32 @@ -// -// HTTPServerResponse.cpp -// -// Library: Net -// Package: HTTPServer -// Module: HTTPServerResponse -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPServerResponse.h" - - -namespace Poco { -namespace Net { - - -HTTPServerResponse::HTTPServerResponse() -{ -} - - -HTTPServerResponse::~HTTPServerResponse() -{ -} - - -} } // namespace Poco::Net +// +// HTTPServerResponse.cpp +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerResponse +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPServerResponse.h" + + +namespace Poco { +namespace Net { + + +HTTPServerResponse::HTTPServerResponse() +{ +} + + +HTTPServerResponse::~HTTPServerResponse() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPServerResponseImpl.cpp b/contrib/libs/poco/Net/src/HTTPServerResponseImpl.cpp index fb6783c633..d3e5b04837 100644 --- a/contrib/libs/poco/Net/src/HTTPServerResponseImpl.cpp +++ b/contrib/libs/poco/Net/src/HTTPServerResponseImpl.cpp @@ -1,221 +1,221 @@ -// -// HTTPServerResponseImpl.cpp -// -// Library: Net -// Package: HTTPServer -// Module: HTTPServerResponseImpl -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPServerResponseImpl.h" -#include "Poco/Net/HTTPServerRequestImpl.h" -#include "Poco/Net/HTTPServerSession.h" -#include "Poco/Net/HTTPHeaderStream.h" -#include "Poco/Net/HTTPStream.h" -#include "Poco/Net/HTTPFixedLengthStream.h" -#include "Poco/Net/HTTPChunkedStream.h" -#include "Poco/File.h" -#include "Poco/Timestamp.h" -#include "Poco/NumberFormatter.h" -#include "Poco/StreamCopier.h" -#include "Poco/CountingStream.h" -#include "Poco/Exception.h" -#include "Poco/FileStream.h" -#include "Poco/DateTimeFormatter.h" -#include "Poco/DateTimeFormat.h" - - -using Poco::File; -using Poco::Timestamp; -using Poco::NumberFormatter; -using Poco::StreamCopier; -using Poco::OpenFileException; -using Poco::DateTimeFormatter; -using Poco::DateTimeFormat; - - -namespace Poco { -namespace Net { - - -HTTPServerResponseImpl::HTTPServerResponseImpl(HTTPServerSession& session): - _session(session), - _pRequest(0), - _pStream(0), - _pHeaderStream(0) -{ -} - - -HTTPServerResponseImpl::~HTTPServerResponseImpl() -{ - if (_pHeaderStream && _pHeaderStream != _pStream) - delete _pHeaderStream; - if (_pStream) - delete _pStream; -} - - -void HTTPServerResponseImpl::sendContinue() -{ - HTTPHeaderOutputStream hs(_session); - hs << getVersion() << " 100 Continue\r\n\r\n"; -} - - -std::ostream& HTTPServerResponseImpl::send() -{ - poco_assert (!_pStream); - - if ((_pRequest && _pRequest->getMethod() == HTTPRequest::HTTP_HEAD) || - getStatus() < 200 || - getStatus() == HTTPResponse::HTTP_NO_CONTENT || - getStatus() == HTTPResponse::HTTP_NOT_MODIFIED) - { - Poco::CountingOutputStream cs; - write(cs); - _pStream = new HTTPFixedLengthOutputStream(_session, cs.chars()); - write(*_pStream); - } - else if (getChunkedTransferEncoding()) - { - HTTPHeaderOutputStream hs(_session); - write(hs); - _pStream = new HTTPChunkedOutputStream(_session); - } - else if (hasContentLength()) - { - Poco::CountingOutputStream cs; - write(cs); -#if defined(POCO_HAVE_INT64) - _pStream = new HTTPFixedLengthOutputStream(_session, getContentLength64() + cs.chars()); -#else - _pStream = new HTTPFixedLengthOutputStream(_session, getContentLength() + cs.chars()); -#endif - write(*_pStream); - } - else - { - _pStream = new HTTPOutputStream(_session); - setKeepAlive(false); - write(*_pStream); - } - return *_pStream; -} - - -std::pair<std::ostream *, std::ostream *> HTTPServerResponseImpl::beginSend() -{ - poco_assert (!_pStream); - poco_assert (!_pHeaderStream); - - // NOTE Code is not exception safe. - - if ((_pRequest && _pRequest->getMethod() == HTTPRequest::HTTP_HEAD) || - getStatus() < 200 || - getStatus() == HTTPResponse::HTTP_NO_CONTENT || - getStatus() == HTTPResponse::HTTP_NOT_MODIFIED) - { - throw Exception("HTTPServerResponse::beginSend is invalid for HEAD request"); - } - else if (getChunkedTransferEncoding()) - { - _pHeaderStream = new HTTPHeaderOutputStream(_session); - beginWrite(*_pHeaderStream); - _pStream = new HTTPChunkedOutputStream(_session); - } - else if (hasContentLength()) - { - throw Exception("HTTPServerResponse::beginSend is invalid for response with Content-Length header"); - } - else - { - _pStream = new HTTPOutputStream(_session); - _pHeaderStream = _pStream; - setKeepAlive(false); - beginWrite(*_pStream); - } - - return std::make_pair(_pHeaderStream, _pStream); -} - - -void HTTPServerResponseImpl::sendFile(const std::string& path, const std::string& mediaType) -{ - poco_assert (!_pStream); - - File f(path); - Timestamp dateTime = f.getLastModified(); - File::FileSize length = f.getSize(); - set("Last-Modified", DateTimeFormatter::format(dateTime, DateTimeFormat::HTTP_FORMAT)); -#if defined(POCO_HAVE_INT64) - setContentLength64(length); -#else - setContentLength(static_cast<int>(length)); -#endif - setContentType(mediaType); - setChunkedTransferEncoding(false); - - Poco::FileInputStream istr(path); - if (istr.good()) - { - _pStream = new HTTPHeaderOutputStream(_session); - write(*_pStream); - if (_pRequest && _pRequest->getMethod() != HTTPRequest::HTTP_HEAD) - { - StreamCopier::copyStream(istr, *_pStream); - } - } - else throw OpenFileException(path); -} - - -void HTTPServerResponseImpl::sendBuffer(const void* pBuffer, std::size_t length) -{ - poco_assert (!_pStream); - - setContentLength(static_cast<int>(length)); - setChunkedTransferEncoding(false); - - _pStream = new HTTPHeaderOutputStream(_session); - write(*_pStream); - if (_pRequest && _pRequest->getMethod() != HTTPRequest::HTTP_HEAD) - { - _pStream->write(static_cast<const char*>(pBuffer), static_cast<std::streamsize>(length)); - } -} - - -void HTTPServerResponseImpl::redirect(const std::string& uri, HTTPStatus status) -{ - poco_assert (!_pStream); - - setContentLength(0); - setChunkedTransferEncoding(false); - - setStatusAndReason(status); - set("Location", uri); - - _pStream = new HTTPHeaderOutputStream(_session); - write(*_pStream); -} - - -void HTTPServerResponseImpl::requireAuthentication(const std::string& realm) -{ - poco_assert (!_pStream); - - setStatusAndReason(HTTPResponse::HTTP_UNAUTHORIZED); - std::string auth("Basic realm=\""); - auth.append(realm); - auth.append("\""); - set("WWW-Authenticate", auth); -} - - -} } // namespace Poco::Net +// +// HTTPServerResponseImpl.cpp +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerResponseImpl +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPServerResponseImpl.h" +#include "Poco/Net/HTTPServerRequestImpl.h" +#include "Poco/Net/HTTPServerSession.h" +#include "Poco/Net/HTTPHeaderStream.h" +#include "Poco/Net/HTTPStream.h" +#include "Poco/Net/HTTPFixedLengthStream.h" +#include "Poco/Net/HTTPChunkedStream.h" +#include "Poco/File.h" +#include "Poco/Timestamp.h" +#include "Poco/NumberFormatter.h" +#include "Poco/StreamCopier.h" +#include "Poco/CountingStream.h" +#include "Poco/Exception.h" +#include "Poco/FileStream.h" +#include "Poco/DateTimeFormatter.h" +#include "Poco/DateTimeFormat.h" + + +using Poco::File; +using Poco::Timestamp; +using Poco::NumberFormatter; +using Poco::StreamCopier; +using Poco::OpenFileException; +using Poco::DateTimeFormatter; +using Poco::DateTimeFormat; + + +namespace Poco { +namespace Net { + + +HTTPServerResponseImpl::HTTPServerResponseImpl(HTTPServerSession& session): + _session(session), + _pRequest(0), + _pStream(0), + _pHeaderStream(0) +{ +} + + +HTTPServerResponseImpl::~HTTPServerResponseImpl() +{ + if (_pHeaderStream && _pHeaderStream != _pStream) + delete _pHeaderStream; + if (_pStream) + delete _pStream; +} + + +void HTTPServerResponseImpl::sendContinue() +{ + HTTPHeaderOutputStream hs(_session); + hs << getVersion() << " 100 Continue\r\n\r\n"; +} + + +std::ostream& HTTPServerResponseImpl::send() +{ + poco_assert (!_pStream); + + if ((_pRequest && _pRequest->getMethod() == HTTPRequest::HTTP_HEAD) || + getStatus() < 200 || + getStatus() == HTTPResponse::HTTP_NO_CONTENT || + getStatus() == HTTPResponse::HTTP_NOT_MODIFIED) + { + Poco::CountingOutputStream cs; + write(cs); + _pStream = new HTTPFixedLengthOutputStream(_session, cs.chars()); + write(*_pStream); + } + else if (getChunkedTransferEncoding()) + { + HTTPHeaderOutputStream hs(_session); + write(hs); + _pStream = new HTTPChunkedOutputStream(_session); + } + else if (hasContentLength()) + { + Poco::CountingOutputStream cs; + write(cs); +#if defined(POCO_HAVE_INT64) + _pStream = new HTTPFixedLengthOutputStream(_session, getContentLength64() + cs.chars()); +#else + _pStream = new HTTPFixedLengthOutputStream(_session, getContentLength() + cs.chars()); +#endif + write(*_pStream); + } + else + { + _pStream = new HTTPOutputStream(_session); + setKeepAlive(false); + write(*_pStream); + } + return *_pStream; +} + + +std::pair<std::ostream *, std::ostream *> HTTPServerResponseImpl::beginSend() +{ + poco_assert (!_pStream); + poco_assert (!_pHeaderStream); + + // NOTE Code is not exception safe. + + if ((_pRequest && _pRequest->getMethod() == HTTPRequest::HTTP_HEAD) || + getStatus() < 200 || + getStatus() == HTTPResponse::HTTP_NO_CONTENT || + getStatus() == HTTPResponse::HTTP_NOT_MODIFIED) + { + throw Exception("HTTPServerResponse::beginSend is invalid for HEAD request"); + } + else if (getChunkedTransferEncoding()) + { + _pHeaderStream = new HTTPHeaderOutputStream(_session); + beginWrite(*_pHeaderStream); + _pStream = new HTTPChunkedOutputStream(_session); + } + else if (hasContentLength()) + { + throw Exception("HTTPServerResponse::beginSend is invalid for response with Content-Length header"); + } + else + { + _pStream = new HTTPOutputStream(_session); + _pHeaderStream = _pStream; + setKeepAlive(false); + beginWrite(*_pStream); + } + + return std::make_pair(_pHeaderStream, _pStream); +} + + +void HTTPServerResponseImpl::sendFile(const std::string& path, const std::string& mediaType) +{ + poco_assert (!_pStream); + + File f(path); + Timestamp dateTime = f.getLastModified(); + File::FileSize length = f.getSize(); + set("Last-Modified", DateTimeFormatter::format(dateTime, DateTimeFormat::HTTP_FORMAT)); +#if defined(POCO_HAVE_INT64) + setContentLength64(length); +#else + setContentLength(static_cast<int>(length)); +#endif + setContentType(mediaType); + setChunkedTransferEncoding(false); + + Poco::FileInputStream istr(path); + if (istr.good()) + { + _pStream = new HTTPHeaderOutputStream(_session); + write(*_pStream); + if (_pRequest && _pRequest->getMethod() != HTTPRequest::HTTP_HEAD) + { + StreamCopier::copyStream(istr, *_pStream); + } + } + else throw OpenFileException(path); +} + + +void HTTPServerResponseImpl::sendBuffer(const void* pBuffer, std::size_t length) +{ + poco_assert (!_pStream); + + setContentLength(static_cast<int>(length)); + setChunkedTransferEncoding(false); + + _pStream = new HTTPHeaderOutputStream(_session); + write(*_pStream); + if (_pRequest && _pRequest->getMethod() != HTTPRequest::HTTP_HEAD) + { + _pStream->write(static_cast<const char*>(pBuffer), static_cast<std::streamsize>(length)); + } +} + + +void HTTPServerResponseImpl::redirect(const std::string& uri, HTTPStatus status) +{ + poco_assert (!_pStream); + + setContentLength(0); + setChunkedTransferEncoding(false); + + setStatusAndReason(status); + set("Location", uri); + + _pStream = new HTTPHeaderOutputStream(_session); + write(*_pStream); +} + + +void HTTPServerResponseImpl::requireAuthentication(const std::string& realm) +{ + poco_assert (!_pStream); + + setStatusAndReason(HTTPResponse::HTTP_UNAUTHORIZED); + std::string auth("Basic realm=\""); + auth.append(realm); + auth.append("\""); + set("WWW-Authenticate", auth); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPServerSession.cpp b/contrib/libs/poco/Net/src/HTTPServerSession.cpp index f6d3c4e5b9..09ca185a41 100644 --- a/contrib/libs/poco/Net/src/HTTPServerSession.cpp +++ b/contrib/libs/poco/Net/src/HTTPServerSession.cpp @@ -1,70 +1,70 @@ -// -// HTTPServerSession.cpp -// -// Library: Net -// Package: HTTPServer -// Module: HTTPServerSession -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPServerSession.h" - - -namespace Poco { -namespace Net { - - -HTTPServerSession::HTTPServerSession(const StreamSocket& socket, HTTPServerParams::Ptr pParams): - HTTPSession(socket, pParams->getKeepAlive()), - _firstRequest(true), - _keepAliveTimeout(pParams->getKeepAliveTimeout()), - _maxKeepAliveRequests(pParams->getMaxKeepAliveRequests()) -{ - setTimeout(pParams->getTimeout()); - this->socket().setReceiveTimeout(pParams->getTimeout()); -} - - -HTTPServerSession::~HTTPServerSession() -{ -} - - -bool HTTPServerSession::hasMoreRequests() -{ - if (!socket().impl()->initialized()) return false; - - if (_firstRequest) - { - _firstRequest = false; - --_maxKeepAliveRequests; - return socket().poll(getTimeout(), Socket::SELECT_READ); - } - else if (_maxKeepAliveRequests != 0 && getKeepAlive()) - { - if (_maxKeepAliveRequests > 0) - --_maxKeepAliveRequests; - return buffered() > 0 || socket().poll(_keepAliveTimeout, Socket::SELECT_READ); - } - else return false; -} - - -SocketAddress HTTPServerSession::clientAddress() -{ - return socket().peerAddress(); -} - - -SocketAddress HTTPServerSession::serverAddress() -{ - return socket().address(); -} - - -} } // namespace Poco::Net +// +// HTTPServerSession.cpp +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerSession +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPServerSession.h" + + +namespace Poco { +namespace Net { + + +HTTPServerSession::HTTPServerSession(const StreamSocket& socket, HTTPServerParams::Ptr pParams): + HTTPSession(socket, pParams->getKeepAlive()), + _firstRequest(true), + _keepAliveTimeout(pParams->getKeepAliveTimeout()), + _maxKeepAliveRequests(pParams->getMaxKeepAliveRequests()) +{ + setTimeout(pParams->getTimeout()); + this->socket().setReceiveTimeout(pParams->getTimeout()); +} + + +HTTPServerSession::~HTTPServerSession() +{ +} + + +bool HTTPServerSession::hasMoreRequests() +{ + if (!socket().impl()->initialized()) return false; + + if (_firstRequest) + { + _firstRequest = false; + --_maxKeepAliveRequests; + return socket().poll(getTimeout(), Socket::SELECT_READ); + } + else if (_maxKeepAliveRequests != 0 && getKeepAlive()) + { + if (_maxKeepAliveRequests > 0) + --_maxKeepAliveRequests; + return buffered() > 0 || socket().poll(_keepAliveTimeout, Socket::SELECT_READ); + } + else return false; +} + + +SocketAddress HTTPServerSession::clientAddress() +{ + return socket().peerAddress(); +} + + +SocketAddress HTTPServerSession::serverAddress() +{ + return socket().address(); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPSession.cpp b/contrib/libs/poco/Net/src/HTTPSession.cpp index cb6fdc25e9..eaf1e9188d 100644 --- a/contrib/libs/poco/Net/src/HTTPSession.cpp +++ b/contrib/libs/poco/Net/src/HTTPSession.cpp @@ -1,261 +1,261 @@ -// -// HTTPSession.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPSession -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPSession.h" -#include "Poco/Net/HTTPBufferAllocator.h" -#include "Poco/Net/NetException.h" -#include <cstring> - - -using Poco::TimeoutException; - - -namespace Poco { -namespace Net { - - -HTTPSession::HTTPSession(): - _pBuffer(0), - _pCurrent(0), - _pEnd(0), - _keepAlive(false), - _connectionTimeout(HTTP_DEFAULT_CONNECTION_TIMEOUT), - _receiveTimeout(HTTP_DEFAULT_TIMEOUT), - _sendTimeout(HTTP_DEFAULT_TIMEOUT), - _pException(0) -{ -} - - -HTTPSession::HTTPSession(const StreamSocket& socket): - _socket(socket), - _pBuffer(0), - _pCurrent(0), - _pEnd(0), - _keepAlive(false), - _connectionTimeout(HTTP_DEFAULT_CONNECTION_TIMEOUT), - _receiveTimeout(HTTP_DEFAULT_TIMEOUT), - _sendTimeout(HTTP_DEFAULT_TIMEOUT), - _pException(0) -{ -} - - -HTTPSession::HTTPSession(const StreamSocket& socket, bool keepAlive): - _socket(socket), - _pBuffer(0), - _pCurrent(0), - _pEnd(0), - _keepAlive(keepAlive), - _connectionTimeout(HTTP_DEFAULT_CONNECTION_TIMEOUT), - _receiveTimeout(HTTP_DEFAULT_TIMEOUT), - _sendTimeout(HTTP_DEFAULT_TIMEOUT), - _pException(0) -{ -} - - -HTTPSession::~HTTPSession() -{ - try - { - if (_pBuffer) HTTPBufferAllocator::deallocate(_pBuffer, HTTPBufferAllocator::BUFFER_SIZE); - } - catch (...) - { - poco_unexpected(); - } - try - { - close(); - } - catch (...) - { - } - delete _pException; -} - - -void HTTPSession::setKeepAlive(bool keepAlive) -{ - _keepAlive = keepAlive; -} - - -void HTTPSession::setTimeout(const Poco::Timespan& timeout) -{ - setTimeout(timeout, timeout, timeout); -} - - -void HTTPSession::setTimeout(const Poco::Timespan& connectionTimeout, const Poco::Timespan& sendTimeout, const Poco::Timespan& receiveTimeout) -{ - _connectionTimeout = connectionTimeout; - _sendTimeout = sendTimeout; - _receiveTimeout = receiveTimeout; -} - - -int HTTPSession::get() -{ - if (_pCurrent == _pEnd) - refill(); - - if (_pCurrent < _pEnd) - return *_pCurrent++; - else - return std::char_traits<char>::eof(); -} - - -int HTTPSession::peek() -{ - if (_pCurrent == _pEnd) - refill(); - - if (_pCurrent < _pEnd) - return *_pCurrent; - else - return std::char_traits<char>::eof(); -} - - -int HTTPSession::read(char* buffer, std::streamsize length) -{ - if (_pCurrent < _pEnd) - { - int n = (int) (_pEnd - _pCurrent); - if (n > length) n = (int) length; - std::memcpy(buffer, _pCurrent, n); - _pCurrent += n; - return n; - } - else return receive(buffer, (int) length); -} - - -int HTTPSession::write(const char* buffer, std::streamsize length) -{ - try - { - return _socket.sendBytes(buffer, (int) length); - } - catch (Poco::Exception& exc) - { - setException(exc); - throw; - } -} - - -int HTTPSession::receive(char* buffer, int length) -{ - try - { - return _socket.receiveBytes(buffer, length); - } - catch (Poco::Exception& exc) - { - setException(exc); - throw; - } -} - - -void HTTPSession::refill() -{ - if (!_pBuffer) - { - _pBuffer = HTTPBufferAllocator::allocate(HTTPBufferAllocator::BUFFER_SIZE); - } - _pCurrent = _pEnd = _pBuffer; - int n = receive(_pBuffer, HTTPBufferAllocator::BUFFER_SIZE); - _pEnd += n; -} - - -bool HTTPSession::connected() const -{ - return _socket.impl()->initialized(); -} - - -void HTTPSession::connect(const SocketAddress& address) -{ - _socket.connect(address, _connectionTimeout); - _socket.setReceiveTimeout(_receiveTimeout); - _socket.setSendTimeout(_sendTimeout); - _socket.setNoDelay(true); - // There may be leftover data from a previous (failed) request in the buffer, - // so we clear it. - _pCurrent = _pEnd = _pBuffer; -} - - -void HTTPSession::abort() -{ - _socket.shutdown(); - close(); -} - - -void HTTPSession::close() -{ - _socket.close(); -} - - -void HTTPSession::setException(const Poco::Exception& exc) -{ - delete _pException; - _pException = exc.clone(); -} - - -void HTTPSession::clearException() -{ - delete _pException; - _pException = 0; -} - - -StreamSocket HTTPSession::detachSocket() -{ - StreamSocket oldSocket(_socket); - StreamSocket newSocket; - _socket = newSocket; - return oldSocket; -} - - -void HTTPSession::attachSocket(const StreamSocket& socket) -{ - _socket = socket; -} - - -void HTTPSession::attachSessionData(const Poco::Any& data) -{ - _data = data; -} - - -void HTTPSession::drainBuffer(Poco::Buffer<char>& buffer) -{ - buffer.assign(_pCurrent, static_cast<std::size_t>(_pEnd - _pCurrent)); - _pCurrent = _pEnd; -} - - -} } // namespace Poco::Net +// +// HTTPSession.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPSession +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPSession.h" +#include "Poco/Net/HTTPBufferAllocator.h" +#include "Poco/Net/NetException.h" +#include <cstring> + + +using Poco::TimeoutException; + + +namespace Poco { +namespace Net { + + +HTTPSession::HTTPSession(): + _pBuffer(0), + _pCurrent(0), + _pEnd(0), + _keepAlive(false), + _connectionTimeout(HTTP_DEFAULT_CONNECTION_TIMEOUT), + _receiveTimeout(HTTP_DEFAULT_TIMEOUT), + _sendTimeout(HTTP_DEFAULT_TIMEOUT), + _pException(0) +{ +} + + +HTTPSession::HTTPSession(const StreamSocket& socket): + _socket(socket), + _pBuffer(0), + _pCurrent(0), + _pEnd(0), + _keepAlive(false), + _connectionTimeout(HTTP_DEFAULT_CONNECTION_TIMEOUT), + _receiveTimeout(HTTP_DEFAULT_TIMEOUT), + _sendTimeout(HTTP_DEFAULT_TIMEOUT), + _pException(0) +{ +} + + +HTTPSession::HTTPSession(const StreamSocket& socket, bool keepAlive): + _socket(socket), + _pBuffer(0), + _pCurrent(0), + _pEnd(0), + _keepAlive(keepAlive), + _connectionTimeout(HTTP_DEFAULT_CONNECTION_TIMEOUT), + _receiveTimeout(HTTP_DEFAULT_TIMEOUT), + _sendTimeout(HTTP_DEFAULT_TIMEOUT), + _pException(0) +{ +} + + +HTTPSession::~HTTPSession() +{ + try + { + if (_pBuffer) HTTPBufferAllocator::deallocate(_pBuffer, HTTPBufferAllocator::BUFFER_SIZE); + } + catch (...) + { + poco_unexpected(); + } + try + { + close(); + } + catch (...) + { + } + delete _pException; +} + + +void HTTPSession::setKeepAlive(bool keepAlive) +{ + _keepAlive = keepAlive; +} + + +void HTTPSession::setTimeout(const Poco::Timespan& timeout) +{ + setTimeout(timeout, timeout, timeout); +} + + +void HTTPSession::setTimeout(const Poco::Timespan& connectionTimeout, const Poco::Timespan& sendTimeout, const Poco::Timespan& receiveTimeout) +{ + _connectionTimeout = connectionTimeout; + _sendTimeout = sendTimeout; + _receiveTimeout = receiveTimeout; +} + + +int HTTPSession::get() +{ + if (_pCurrent == _pEnd) + refill(); + + if (_pCurrent < _pEnd) + return *_pCurrent++; + else + return std::char_traits<char>::eof(); +} + + +int HTTPSession::peek() +{ + if (_pCurrent == _pEnd) + refill(); + + if (_pCurrent < _pEnd) + return *_pCurrent; + else + return std::char_traits<char>::eof(); +} + + +int HTTPSession::read(char* buffer, std::streamsize length) +{ + if (_pCurrent < _pEnd) + { + int n = (int) (_pEnd - _pCurrent); + if (n > length) n = (int) length; + std::memcpy(buffer, _pCurrent, n); + _pCurrent += n; + return n; + } + else return receive(buffer, (int) length); +} + + +int HTTPSession::write(const char* buffer, std::streamsize length) +{ + try + { + return _socket.sendBytes(buffer, (int) length); + } + catch (Poco::Exception& exc) + { + setException(exc); + throw; + } +} + + +int HTTPSession::receive(char* buffer, int length) +{ + try + { + return _socket.receiveBytes(buffer, length); + } + catch (Poco::Exception& exc) + { + setException(exc); + throw; + } +} + + +void HTTPSession::refill() +{ + if (!_pBuffer) + { + _pBuffer = HTTPBufferAllocator::allocate(HTTPBufferAllocator::BUFFER_SIZE); + } + _pCurrent = _pEnd = _pBuffer; + int n = receive(_pBuffer, HTTPBufferAllocator::BUFFER_SIZE); + _pEnd += n; +} + + +bool HTTPSession::connected() const +{ + return _socket.impl()->initialized(); +} + + +void HTTPSession::connect(const SocketAddress& address) +{ + _socket.connect(address, _connectionTimeout); + _socket.setReceiveTimeout(_receiveTimeout); + _socket.setSendTimeout(_sendTimeout); + _socket.setNoDelay(true); + // There may be leftover data from a previous (failed) request in the buffer, + // so we clear it. + _pCurrent = _pEnd = _pBuffer; +} + + +void HTTPSession::abort() +{ + _socket.shutdown(); + close(); +} + + +void HTTPSession::close() +{ + _socket.close(); +} + + +void HTTPSession::setException(const Poco::Exception& exc) +{ + delete _pException; + _pException = exc.clone(); +} + + +void HTTPSession::clearException() +{ + delete _pException; + _pException = 0; +} + + +StreamSocket HTTPSession::detachSocket() +{ + StreamSocket oldSocket(_socket); + StreamSocket newSocket; + _socket = newSocket; + return oldSocket; +} + + +void HTTPSession::attachSocket(const StreamSocket& socket) +{ + _socket = socket; +} + + +void HTTPSession::attachSessionData(const Poco::Any& data) +{ + _data = data; +} + + +void HTTPSession::drainBuffer(Poco::Buffer<char>& buffer) +{ + buffer.assign(_pCurrent, static_cast<std::size_t>(_pEnd - _pCurrent)); + _pCurrent = _pEnd; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPSessionFactory.cpp b/contrib/libs/poco/Net/src/HTTPSessionFactory.cpp index e4a62da68b..9e12c0a3ff 100644 --- a/contrib/libs/poco/Net/src/HTTPSessionFactory.cpp +++ b/contrib/libs/poco/Net/src/HTTPSessionFactory.cpp @@ -1,146 +1,146 @@ -// -// HTTPSessionFactory.cpp -// -// Library: Net -// Package: HTTPClient -// Module: HTTPSessionFactory -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPSessionFactory.h" -#include "Poco/Net/HTTPSessionInstantiator.h" -#include "Poco/Exception.h" - - -using Poco::SingletonHolder; -using Poco::FastMutex; -using Poco::NotFoundException; -using Poco::ExistsException; - - -namespace Poco { -namespace Net { - - -HTTPSessionFactory::HTTPSessionFactory(): - _proxyPort(0) -{ -} - - -HTTPSessionFactory::HTTPSessionFactory(const std::string& proxyHost, Poco::UInt16 proxyPort): - _proxyHost(proxyHost), - _proxyPort(proxyPort) -{ -} - - -HTTPSessionFactory::~HTTPSessionFactory() -{ - for (Instantiators::iterator it = _instantiators.begin(); it != _instantiators.end(); ++it) - { - delete it->second.pIn; - } -} - - -void HTTPSessionFactory::registerProtocol(const std::string& protocol, HTTPSessionInstantiator* pSessionInstantiator) -{ - poco_assert_dbg(pSessionInstantiator); - - FastMutex::ScopedLock lock(_mutex); - std::pair<Instantiators::iterator, bool> tmp = _instantiators.insert(make_pair(protocol, InstantiatorInfo(pSessionInstantiator))); - if (!tmp.second) - { - ++tmp.first->second.cnt; - delete pSessionInstantiator; - } -} - - -void HTTPSessionFactory::unregisterProtocol(const std::string& protocol) -{ - FastMutex::ScopedLock lock(_mutex); - - Instantiators::iterator it = _instantiators.find(protocol); - if (it != _instantiators.end()) - { - if (it->second.cnt == 1) - { - delete it->second.pIn; - _instantiators.erase(it); - } - else --it->second.cnt; - } - else throw NotFoundException("No HTTPSessionInstantiator registered for", protocol); -} - - -bool HTTPSessionFactory::supportsProtocol(const std::string& protocol) -{ - FastMutex::ScopedLock lock(_mutex); - - Instantiators::iterator it = _instantiators.find(protocol); - return it != _instantiators.end(); -} - - -HTTPClientSession* HTTPSessionFactory::createClientSession(const Poco::URI& uri) -{ - FastMutex::ScopedLock lock(_mutex); - - if (uri.isRelative()) throw Poco::UnknownURISchemeException("Relative URIs are not supported by HTTPSessionFactory."); - - Instantiators::iterator it = _instantiators.find(uri.getScheme()); - if (it != _instantiators.end()) - { - it->second.pIn->setProxy(_proxyHost, _proxyPort); - it->second.pIn->setProxyCredentials(_proxyUsername, _proxyPassword); - return it->second.pIn->createClientSession(uri); - } - else throw Poco::UnknownURISchemeException(uri.getScheme()); -} - - -void HTTPSessionFactory::setProxy(const std::string& host, Poco::UInt16 port) -{ - FastMutex::ScopedLock lock(_mutex); - - _proxyHost = host; - _proxyPort = port; -} - - -void HTTPSessionFactory::setProxyCredentials(const std::string& username, const std::string& password) -{ - FastMutex::ScopedLock lock(_mutex); - - _proxyUsername = username; - _proxyPassword = password; -} - - -namespace -{ - static SingletonHolder<HTTPSessionFactory> singleton; -} - - -HTTPSessionFactory& HTTPSessionFactory::defaultFactory() -{ - return *singleton.get(); -} - - -HTTPSessionFactory::InstantiatorInfo::InstantiatorInfo(HTTPSessionInstantiator* pInst): pIn(pInst), cnt(1) -{ - poco_check_ptr (pIn); -} - - -} } // namespace Poco::Net +// +// HTTPSessionFactory.cpp +// +// Library: Net +// Package: HTTPClient +// Module: HTTPSessionFactory +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPSessionFactory.h" +#include "Poco/Net/HTTPSessionInstantiator.h" +#include "Poco/Exception.h" + + +using Poco::SingletonHolder; +using Poco::FastMutex; +using Poco::NotFoundException; +using Poco::ExistsException; + + +namespace Poco { +namespace Net { + + +HTTPSessionFactory::HTTPSessionFactory(): + _proxyPort(0) +{ +} + + +HTTPSessionFactory::HTTPSessionFactory(const std::string& proxyHost, Poco::UInt16 proxyPort): + _proxyHost(proxyHost), + _proxyPort(proxyPort) +{ +} + + +HTTPSessionFactory::~HTTPSessionFactory() +{ + for (Instantiators::iterator it = _instantiators.begin(); it != _instantiators.end(); ++it) + { + delete it->second.pIn; + } +} + + +void HTTPSessionFactory::registerProtocol(const std::string& protocol, HTTPSessionInstantiator* pSessionInstantiator) +{ + poco_assert_dbg(pSessionInstantiator); + + FastMutex::ScopedLock lock(_mutex); + std::pair<Instantiators::iterator, bool> tmp = _instantiators.insert(make_pair(protocol, InstantiatorInfo(pSessionInstantiator))); + if (!tmp.second) + { + ++tmp.first->second.cnt; + delete pSessionInstantiator; + } +} + + +void HTTPSessionFactory::unregisterProtocol(const std::string& protocol) +{ + FastMutex::ScopedLock lock(_mutex); + + Instantiators::iterator it = _instantiators.find(protocol); + if (it != _instantiators.end()) + { + if (it->second.cnt == 1) + { + delete it->second.pIn; + _instantiators.erase(it); + } + else --it->second.cnt; + } + else throw NotFoundException("No HTTPSessionInstantiator registered for", protocol); +} + + +bool HTTPSessionFactory::supportsProtocol(const std::string& protocol) +{ + FastMutex::ScopedLock lock(_mutex); + + Instantiators::iterator it = _instantiators.find(protocol); + return it != _instantiators.end(); +} + + +HTTPClientSession* HTTPSessionFactory::createClientSession(const Poco::URI& uri) +{ + FastMutex::ScopedLock lock(_mutex); + + if (uri.isRelative()) throw Poco::UnknownURISchemeException("Relative URIs are not supported by HTTPSessionFactory."); + + Instantiators::iterator it = _instantiators.find(uri.getScheme()); + if (it != _instantiators.end()) + { + it->second.pIn->setProxy(_proxyHost, _proxyPort); + it->second.pIn->setProxyCredentials(_proxyUsername, _proxyPassword); + return it->second.pIn->createClientSession(uri); + } + else throw Poco::UnknownURISchemeException(uri.getScheme()); +} + + +void HTTPSessionFactory::setProxy(const std::string& host, Poco::UInt16 port) +{ + FastMutex::ScopedLock lock(_mutex); + + _proxyHost = host; + _proxyPort = port; +} + + +void HTTPSessionFactory::setProxyCredentials(const std::string& username, const std::string& password) +{ + FastMutex::ScopedLock lock(_mutex); + + _proxyUsername = username; + _proxyPassword = password; +} + + +namespace +{ + static SingletonHolder<HTTPSessionFactory> singleton; +} + + +HTTPSessionFactory& HTTPSessionFactory::defaultFactory() +{ + return *singleton.get(); +} + + +HTTPSessionFactory::InstantiatorInfo::InstantiatorInfo(HTTPSessionInstantiator* pInst): pIn(pInst), cnt(1) +{ + poco_check_ptr (pIn); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPSessionInstantiator.cpp b/contrib/libs/poco/Net/src/HTTPSessionInstantiator.cpp index d2f291f6b5..5f7145fe76 100644 --- a/contrib/libs/poco/Net/src/HTTPSessionInstantiator.cpp +++ b/contrib/libs/poco/Net/src/HTTPSessionInstantiator.cpp @@ -1,77 +1,77 @@ -// -// HTTPSessionInstantiator.cpp -// -// Library: Net -// Package: HTTPClient -// Module: HTTPSessionInstantiator -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPSessionInstantiator.h" -#include "Poco/Net/HTTPSessionFactory.h" -#include "Poco/Net/HTTPClientSession.h" - - -using Poco::URI; - - -namespace Poco { -namespace Net { - - -HTTPSessionInstantiator::HTTPSessionInstantiator(): - _proxyPort(0) -{ -} - - -HTTPSessionInstantiator::~HTTPSessionInstantiator() -{ -} - - -HTTPClientSession* HTTPSessionInstantiator::createClientSession(const Poco::URI& uri) -{ - poco_assert (uri.getScheme() == "http"); - HTTPClientSession* pSession = new HTTPClientSession(uri.getHost(), uri.getPort()); - if (!proxyHost().empty()) - { - pSession->setProxy(proxyHost(), proxyPort()); - pSession->setProxyCredentials(proxyUsername(), proxyPassword()); - } - return pSession; -} - - -void HTTPSessionInstantiator::registerInstantiator() -{ - HTTPSessionFactory::defaultFactory().registerProtocol("http", new HTTPSessionInstantiator); -} - - -void HTTPSessionInstantiator::unregisterInstantiator() -{ - HTTPSessionFactory::defaultFactory().unregisterProtocol("http"); -} - - -void HTTPSessionInstantiator::setProxy(const std::string& host, Poco::UInt16 port) -{ - _proxyHost = host; - _proxyPort = port; -} - - -void HTTPSessionInstantiator::setProxyCredentials(const std::string& username, const std::string& password) -{ - _proxyUsername = username; - _proxyPassword = password; -} - - -} } // namespace Poco::Net +// +// HTTPSessionInstantiator.cpp +// +// Library: Net +// Package: HTTPClient +// Module: HTTPSessionInstantiator +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPSessionInstantiator.h" +#include "Poco/Net/HTTPSessionFactory.h" +#include "Poco/Net/HTTPClientSession.h" + + +using Poco::URI; + + +namespace Poco { +namespace Net { + + +HTTPSessionInstantiator::HTTPSessionInstantiator(): + _proxyPort(0) +{ +} + + +HTTPSessionInstantiator::~HTTPSessionInstantiator() +{ +} + + +HTTPClientSession* HTTPSessionInstantiator::createClientSession(const Poco::URI& uri) +{ + poco_assert (uri.getScheme() == "http"); + HTTPClientSession* pSession = new HTTPClientSession(uri.getHost(), uri.getPort()); + if (!proxyHost().empty()) + { + pSession->setProxy(proxyHost(), proxyPort()); + pSession->setProxyCredentials(proxyUsername(), proxyPassword()); + } + return pSession; +} + + +void HTTPSessionInstantiator::registerInstantiator() +{ + HTTPSessionFactory::defaultFactory().registerProtocol("http", new HTTPSessionInstantiator); +} + + +void HTTPSessionInstantiator::unregisterInstantiator() +{ + HTTPSessionFactory::defaultFactory().unregisterProtocol("http"); +} + + +void HTTPSessionInstantiator::setProxy(const std::string& host, Poco::UInt16 port) +{ + _proxyHost = host; + _proxyPort = port; +} + + +void HTTPSessionInstantiator::setProxyCredentials(const std::string& username, const std::string& password) +{ + _proxyUsername = username; + _proxyPassword = password; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPStream.cpp b/contrib/libs/poco/Net/src/HTTPStream.cpp index 2faeb422b0..67e76945c4 100644 --- a/contrib/libs/poco/Net/src/HTTPStream.cpp +++ b/contrib/libs/poco/Net/src/HTTPStream.cpp @@ -1,173 +1,173 @@ -// -// HTTPStream.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPStream -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPStream.h" -#include "Poco/Net/HTTPSession.h" - - -namespace Poco { -namespace Net { - - -// -// HTTPStreamBuf -// - - -HTTPStreamBuf::HTTPStreamBuf(HTTPSession& session, openmode mode): - HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode), - _session(session), - _mode(mode) -{ -} - - -HTTPStreamBuf::~HTTPStreamBuf() -{ -} - - -void HTTPStreamBuf::close() -{ - if (_mode & std::ios::out) - { - sync(); - if (!_session.getKeepAlive()) - _session.socket().shutdownSend(); - } -} - - -int HTTPStreamBuf::readFromDevice(char* buffer, std::streamsize length) -{ - return _session.read(buffer, length); -} - - -int HTTPStreamBuf::writeToDevice(const char* buffer, std::streamsize length) -{ - - return _session.write(buffer, length); -} - - -// -// HTTPIOS -// - - -HTTPIOS::HTTPIOS(HTTPSession& session, HTTPStreamBuf::openmode mode): - _buf(session, mode) -{ - poco_ios_init(&_buf); -} - - -HTTPIOS::~HTTPIOS() -{ - try - { - _buf.close(); - } - catch (...) - { - } -} - - -HTTPStreamBuf* HTTPIOS::rdbuf() -{ - return &_buf; -} - - -// -// HTTPInputStream -// - - -Poco::MemoryPool HTTPInputStream::_pool(sizeof(HTTPInputStream)); - - -HTTPInputStream::HTTPInputStream(HTTPSession& session): - HTTPIOS(session, std::ios::in), - std::istream(&_buf) -{ -} - - -HTTPInputStream::~HTTPInputStream() -{ -} - - -void* HTTPInputStream::operator new(std::size_t /*size*/) -{ - return _pool.get(); -} - - -void HTTPInputStream::operator delete(void* ptr) -{ - try - { - _pool.release(ptr); - } - catch (...) - { - poco_unexpected(); - } -} - - -// -// HTTPOutputStream -// - - -Poco::MemoryPool HTTPOutputStream::_pool(sizeof(HTTPOutputStream)); - - -HTTPOutputStream::HTTPOutputStream(HTTPSession& session): - HTTPIOS(session, std::ios::out), - std::ostream(&_buf) -{ -} - - -HTTPOutputStream::~HTTPOutputStream() -{ -} - - -void* HTTPOutputStream::operator new(std::size_t /*size*/) -{ - return _pool.get(); -} - - -void HTTPOutputStream::operator delete(void* ptr) -{ - try - { - _pool.release(ptr); - } - catch (...) - { - poco_unexpected(); - } -} - - -} } // namespace Poco::Net +// +// HTTPStream.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPStream.h" +#include "Poco/Net/HTTPSession.h" + + +namespace Poco { +namespace Net { + + +// +// HTTPStreamBuf +// + + +HTTPStreamBuf::HTTPStreamBuf(HTTPSession& session, openmode mode): + HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode), + _session(session), + _mode(mode) +{ +} + + +HTTPStreamBuf::~HTTPStreamBuf() +{ +} + + +void HTTPStreamBuf::close() +{ + if (_mode & std::ios::out) + { + sync(); + if (!_session.getKeepAlive()) + _session.socket().shutdownSend(); + } +} + + +int HTTPStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + return _session.read(buffer, length); +} + + +int HTTPStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + + return _session.write(buffer, length); +} + + +// +// HTTPIOS +// + + +HTTPIOS::HTTPIOS(HTTPSession& session, HTTPStreamBuf::openmode mode): + _buf(session, mode) +{ + poco_ios_init(&_buf); +} + + +HTTPIOS::~HTTPIOS() +{ + try + { + _buf.close(); + } + catch (...) + { + } +} + + +HTTPStreamBuf* HTTPIOS::rdbuf() +{ + return &_buf; +} + + +// +// HTTPInputStream +// + + +Poco::MemoryPool HTTPInputStream::_pool(sizeof(HTTPInputStream)); + + +HTTPInputStream::HTTPInputStream(HTTPSession& session): + HTTPIOS(session, std::ios::in), + std::istream(&_buf) +{ +} + + +HTTPInputStream::~HTTPInputStream() +{ +} + + +void* HTTPInputStream::operator new(std::size_t /*size*/) +{ + return _pool.get(); +} + + +void HTTPInputStream::operator delete(void* ptr) +{ + try + { + _pool.release(ptr); + } + catch (...) + { + poco_unexpected(); + } +} + + +// +// HTTPOutputStream +// + + +Poco::MemoryPool HTTPOutputStream::_pool(sizeof(HTTPOutputStream)); + + +HTTPOutputStream::HTTPOutputStream(HTTPSession& session): + HTTPIOS(session, std::ios::out), + std::ostream(&_buf) +{ +} + + +HTTPOutputStream::~HTTPOutputStream() +{ +} + + +void* HTTPOutputStream::operator new(std::size_t /*size*/) +{ + return _pool.get(); +} + + +void HTTPOutputStream::operator delete(void* ptr) +{ + try + { + _pool.release(ptr); + } + catch (...) + { + poco_unexpected(); + } +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HTTPStreamFactory.cpp b/contrib/libs/poco/Net/src/HTTPStreamFactory.cpp index ee77d98ec4..5832cf1cc8 100644 --- a/contrib/libs/poco/Net/src/HTTPStreamFactory.cpp +++ b/contrib/libs/poco/Net/src/HTTPStreamFactory.cpp @@ -1,187 +1,187 @@ -// -// HTTPStreamFactory.cpp -// -// Library: Net -// Package: HTTP -// Module: HTTPStreamFactory -// -// Copyright (c) 2005-2012, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HTTPStreamFactory.h" -#include "Poco/Net/HTTPClientSession.h" -#include "Poco/Net/HTTPIOStream.h" -#include "Poco/Net/HTTPRequest.h" -#include "Poco/Net/HTTPResponse.h" -#include "Poco/Net/HTTPCredentials.h" -#include "Poco/Net/NetException.h" -#include "Poco/URI.h" -#include "Poco/URIStreamOpener.h" -#include "Poco/UnbufferedStreamBuf.h" -#include "Poco/NullStream.h" -#include "Poco/StreamCopier.h" -#include "Poco/Format.h" -#include "Poco/Version.h" - - -using Poco::URIStreamFactory; -using Poco::URI; -using Poco::URIStreamOpener; -using Poco::UnbufferedStreamBuf; - - -namespace Poco { -namespace Net { - - -HTTPStreamFactory::HTTPStreamFactory(): - _proxyPort(HTTPSession::HTTP_PORT) -{ -} - - -HTTPStreamFactory::HTTPStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort): - _proxyHost(proxyHost), - _proxyPort(proxyPort) -{ -} - - -HTTPStreamFactory::HTTPStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort, const std::string& proxyUsername, const std::string& proxyPassword): - _proxyHost(proxyHost), - _proxyPort(proxyPort), - _proxyUsername(proxyUsername), - _proxyPassword(proxyPassword) -{ -} - - -HTTPStreamFactory::~HTTPStreamFactory() -{ -} - - -std::istream* HTTPStreamFactory::open(const URI& uri) -{ - poco_assert (uri.getScheme() == "http"); - - URI resolvedURI(uri); - URI proxyUri; - HTTPClientSession* pSession = 0; - HTTPResponse res; - bool retry = false; - bool authorize = false; - std::string username; - std::string password; - - try - { - do - { - if (!pSession) - { - pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort()); - - if (proxyUri.empty()) - { - if (!_proxyHost.empty()) - { - pSession->setProxy(_proxyHost, _proxyPort); - pSession->setProxyCredentials(_proxyUsername, _proxyPassword); - } - } - else - { - pSession->setProxy(proxyUri.getHost(), proxyUri.getPort()); - if (!_proxyUsername.empty()) - { - pSession->setProxyCredentials(_proxyUsername, _proxyPassword); - } - } - } - - std::string path = resolvedURI.getPathAndQuery(); - if (path.empty()) path = "/"; - HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1); - - if (authorize) - { - HTTPCredentials::extractCredentials(uri, username, password); - HTTPCredentials cred(username, password); - cred.authenticate(req, res); - } - - req.set("User-Agent", Poco::format("poco/%d.%d.%d", - (POCO_VERSION >> 24) & 0xFF, - (POCO_VERSION >> 16) & 0xFF, - (POCO_VERSION >> 8) & 0xFF)); - req.set("Accept", "*/*"); - - pSession->sendRequest(req); - std::istream& rs = pSession->receiveResponse(res); - bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY || - res.getStatus() == HTTPResponse::HTTP_FOUND || - res.getStatus() == HTTPResponse::HTTP_SEE_OTHER || - res.getStatus() == HTTPResponse::HTTP_TEMPORARY_REDIRECT); - if (moved) - { - resolvedURI.resolve(res.get("Location")); - if (!username.empty()) - { - resolvedURI.setUserInfo(username + ":" + password); - } - throw URIRedirection(resolvedURI.toString()); - } - else if (res.getStatus() == HTTPResponse::HTTP_OK) - { - return new HTTPResponseStream(rs, pSession); - } - else if (res.getStatus() == HTTPResponse::HTTP_USE_PROXY && !retry) - { - // The requested resource MUST be accessed through the proxy - // given by the Location field. The Location field gives the - // URI of the proxy. The recipient is expected to repeat this - // single request via the proxy. 305 responses MUST only be generated by origin servers. - // only use for one single request! - proxyUri.resolve(res.get("Location")); - delete pSession; - pSession = 0; - retry = true; // only allow useproxy once - } - else if (res.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED && !authorize) - { - authorize = true; - retry = true; - Poco::NullOutputStream null; - Poco::StreamCopier::copyStream(rs, null); - } - else throw HTTPException(res.getReason(), uri.toString()); - } - while (retry); - throw HTTPException("Too many redirects", uri.toString()); - } - catch (...) - { - delete pSession; - throw; - } -} - - -void HTTPStreamFactory::registerFactory() -{ - URIStreamOpener::defaultOpener().registerStreamFactory("http", new HTTPStreamFactory); -} - - -void HTTPStreamFactory::unregisterFactory() -{ - URIStreamOpener::defaultOpener().unregisterStreamFactory("http"); -} - - -} } // namespace Poco::Net +// +// HTTPStreamFactory.cpp +// +// Library: Net +// Package: HTTP +// Module: HTTPStreamFactory +// +// Copyright (c) 2005-2012, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HTTPStreamFactory.h" +#include "Poco/Net/HTTPClientSession.h" +#include "Poco/Net/HTTPIOStream.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/HTTPResponse.h" +#include "Poco/Net/HTTPCredentials.h" +#include "Poco/Net/NetException.h" +#include "Poco/URI.h" +#include "Poco/URIStreamOpener.h" +#include "Poco/UnbufferedStreamBuf.h" +#include "Poco/NullStream.h" +#include "Poco/StreamCopier.h" +#include "Poco/Format.h" +#include "Poco/Version.h" + + +using Poco::URIStreamFactory; +using Poco::URI; +using Poco::URIStreamOpener; +using Poco::UnbufferedStreamBuf; + + +namespace Poco { +namespace Net { + + +HTTPStreamFactory::HTTPStreamFactory(): + _proxyPort(HTTPSession::HTTP_PORT) +{ +} + + +HTTPStreamFactory::HTTPStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort): + _proxyHost(proxyHost), + _proxyPort(proxyPort) +{ +} + + +HTTPStreamFactory::HTTPStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort, const std::string& proxyUsername, const std::string& proxyPassword): + _proxyHost(proxyHost), + _proxyPort(proxyPort), + _proxyUsername(proxyUsername), + _proxyPassword(proxyPassword) +{ +} + + +HTTPStreamFactory::~HTTPStreamFactory() +{ +} + + +std::istream* HTTPStreamFactory::open(const URI& uri) +{ + poco_assert (uri.getScheme() == "http"); + + URI resolvedURI(uri); + URI proxyUri; + HTTPClientSession* pSession = 0; + HTTPResponse res; + bool retry = false; + bool authorize = false; + std::string username; + std::string password; + + try + { + do + { + if (!pSession) + { + pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort()); + + if (proxyUri.empty()) + { + if (!_proxyHost.empty()) + { + pSession->setProxy(_proxyHost, _proxyPort); + pSession->setProxyCredentials(_proxyUsername, _proxyPassword); + } + } + else + { + pSession->setProxy(proxyUri.getHost(), proxyUri.getPort()); + if (!_proxyUsername.empty()) + { + pSession->setProxyCredentials(_proxyUsername, _proxyPassword); + } + } + } + + std::string path = resolvedURI.getPathAndQuery(); + if (path.empty()) path = "/"; + HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1); + + if (authorize) + { + HTTPCredentials::extractCredentials(uri, username, password); + HTTPCredentials cred(username, password); + cred.authenticate(req, res); + } + + req.set("User-Agent", Poco::format("poco/%d.%d.%d", + (POCO_VERSION >> 24) & 0xFF, + (POCO_VERSION >> 16) & 0xFF, + (POCO_VERSION >> 8) & 0xFF)); + req.set("Accept", "*/*"); + + pSession->sendRequest(req); + std::istream& rs = pSession->receiveResponse(res); + bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY || + res.getStatus() == HTTPResponse::HTTP_FOUND || + res.getStatus() == HTTPResponse::HTTP_SEE_OTHER || + res.getStatus() == HTTPResponse::HTTP_TEMPORARY_REDIRECT); + if (moved) + { + resolvedURI.resolve(res.get("Location")); + if (!username.empty()) + { + resolvedURI.setUserInfo(username + ":" + password); + } + throw URIRedirection(resolvedURI.toString()); + } + else if (res.getStatus() == HTTPResponse::HTTP_OK) + { + return new HTTPResponseStream(rs, pSession); + } + else if (res.getStatus() == HTTPResponse::HTTP_USE_PROXY && !retry) + { + // The requested resource MUST be accessed through the proxy + // given by the Location field. The Location field gives the + // URI of the proxy. The recipient is expected to repeat this + // single request via the proxy. 305 responses MUST only be generated by origin servers. + // only use for one single request! + proxyUri.resolve(res.get("Location")); + delete pSession; + pSession = 0; + retry = true; // only allow useproxy once + } + else if (res.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED && !authorize) + { + authorize = true; + retry = true; + Poco::NullOutputStream null; + Poco::StreamCopier::copyStream(rs, null); + } + else throw HTTPException(res.getReason(), uri.toString()); + } + while (retry); + throw HTTPException("Too many redirects", uri.toString()); + } + catch (...) + { + delete pSession; + throw; + } +} + + +void HTTPStreamFactory::registerFactory() +{ + URIStreamOpener::defaultOpener().registerStreamFactory("http", new HTTPStreamFactory); +} + + +void HTTPStreamFactory::unregisterFactory() +{ + URIStreamOpener::defaultOpener().unregisterStreamFactory("http"); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/HostEntry.cpp b/contrib/libs/poco/Net/src/HostEntry.cpp index 3257c70311..212b2837d6 100644 --- a/contrib/libs/poco/Net/src/HostEntry.cpp +++ b/contrib/libs/poco/Net/src/HostEntry.cpp @@ -1,135 +1,135 @@ -// -// HostEntry.cpp -// -// Library: Net -// Package: NetCore -// Module: HostEntry -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/HostEntry.h" -#include "Poco/Exception.h" -#include <algorithm> - - -namespace Poco { -namespace Net { - - -HostEntry::HostEntry() -{ -} - - -HostEntry::HostEntry(struct hostent* entry) -{ - poco_check_ptr (entry); - - _name = entry->h_name; - char** alias = entry->h_aliases; - if (alias) - { - while (*alias) - { - _aliases.push_back(std::string(*alias)); - ++alias; - } - } - char** address = entry->h_addr_list; - if (address) - { - while (*address) - { - _addresses.push_back(IPAddress(*address, entry->h_length)); - ++address; - } - } -} - - -#if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO) - - -HostEntry::HostEntry(struct addrinfo* ainfo) -{ - poco_check_ptr (ainfo); - - for (struct addrinfo* ai = ainfo; ai; ai = ai->ai_next) - { - if (ai->ai_canonname) - { - _name.assign(ai->ai_canonname); - } - if (ai->ai_addrlen && ai->ai_addr) - { - switch (ai->ai_addr->sa_family) - { - case AF_INET: - _addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in*>(ai->ai_addr)->sin_addr, sizeof(in_addr))); - break; -#if defined(POCO_HAVE_IPv6) - case AF_INET6: - _addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_addr, sizeof(in6_addr), reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_scope_id)); - break; -#endif - } - } - } -} - - -#endif // POCO_HAVE_IPv6 - - -#if defined(POCO_VXWORKS) - - -HostEntry::HostEntry(const std::string& name, const IPAddress& addr): - _name(name) -{ - _addresses.push_back(addr); -} - - -#endif // POCO_VXWORKS - - -HostEntry::HostEntry(const HostEntry& entry): - _name(entry._name), - _aliases(entry._aliases), - _addresses(entry._addresses) -{ -} - - -HostEntry& HostEntry::operator = (const HostEntry& entry) -{ - if (&entry != this) - { - _name = entry._name; - _aliases = entry._aliases; - _addresses = entry._addresses; - } - return *this; -} - - -void HostEntry::swap(HostEntry& hostEntry) -{ - std::swap(_name, hostEntry._name); - std::swap(_aliases, hostEntry._aliases); - std::swap(_addresses, hostEntry._addresses); -} - - -HostEntry::~HostEntry() -{ -} - - -} } // namespace Poco::Net +// +// HostEntry.cpp +// +// Library: Net +// Package: NetCore +// Module: HostEntry +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/HostEntry.h" +#include "Poco/Exception.h" +#include <algorithm> + + +namespace Poco { +namespace Net { + + +HostEntry::HostEntry() +{ +} + + +HostEntry::HostEntry(struct hostent* entry) +{ + poco_check_ptr (entry); + + _name = entry->h_name; + char** alias = entry->h_aliases; + if (alias) + { + while (*alias) + { + _aliases.push_back(std::string(*alias)); + ++alias; + } + } + char** address = entry->h_addr_list; + if (address) + { + while (*address) + { + _addresses.push_back(IPAddress(*address, entry->h_length)); + ++address; + } + } +} + + +#if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO) + + +HostEntry::HostEntry(struct addrinfo* ainfo) +{ + poco_check_ptr (ainfo); + + for (struct addrinfo* ai = ainfo; ai; ai = ai->ai_next) + { + if (ai->ai_canonname) + { + _name.assign(ai->ai_canonname); + } + if (ai->ai_addrlen && ai->ai_addr) + { + switch (ai->ai_addr->sa_family) + { + case AF_INET: + _addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in*>(ai->ai_addr)->sin_addr, sizeof(in_addr))); + break; +#if defined(POCO_HAVE_IPv6) + case AF_INET6: + _addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_addr, sizeof(in6_addr), reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_scope_id)); + break; +#endif + } + } + } +} + + +#endif // POCO_HAVE_IPv6 + + +#if defined(POCO_VXWORKS) + + +HostEntry::HostEntry(const std::string& name, const IPAddress& addr): + _name(name) +{ + _addresses.push_back(addr); +} + + +#endif // POCO_VXWORKS + + +HostEntry::HostEntry(const HostEntry& entry): + _name(entry._name), + _aliases(entry._aliases), + _addresses(entry._addresses) +{ +} + + +HostEntry& HostEntry::operator = (const HostEntry& entry) +{ + if (&entry != this) + { + _name = entry._name; + _aliases = entry._aliases; + _addresses = entry._addresses; + } + return *this; +} + + +void HostEntry::swap(HostEntry& hostEntry) +{ + std::swap(_name, hostEntry._name); + std::swap(_aliases, hostEntry._aliases); + std::swap(_addresses, hostEntry._addresses); +} + + +HostEntry::~HostEntry() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/ICMPClient.cpp b/contrib/libs/poco/Net/src/ICMPClient.cpp index 4639d6a5fa..40596b835e 100644 --- a/contrib/libs/poco/Net/src/ICMPClient.cpp +++ b/contrib/libs/poco/Net/src/ICMPClient.cpp @@ -1,150 +1,150 @@ -// -// ICMPClient.cpp -// -// Library: Net -// Package: ICMP -// Module: ICMPClient -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/SocketAddress.h" -#include "Poco/Net/ICMPClient.h" -#include "Poco/Net/ICMPSocket.h" -#include "Poco/Net/NetException.h" -#include "Poco/Channel.h" -#include "Poco/Message.h" -#include "Poco/Exception.h" -#include <sstream> - - -using Poco::Channel; -using Poco::Message; -using Poco::InvalidArgumentException; -using Poco::NotImplementedException; -using Poco::TimeoutException; -using Poco::Exception; - - -namespace Poco { -namespace Net { - - -ICMPClient::ICMPClient(SocketAddress::Family family, int dataSize, int ttl, int timeout): - _family(family), - _dataSize(dataSize), - _ttl(ttl), - _timeout(timeout) -{ -} - - -ICMPClient::~ICMPClient() -{ -} - - -int ICMPClient::ping(const std::string& address, int repeat) const -{ - if (repeat <= 0) return 0; - - SocketAddress addr(address, 0); - return ping(addr, repeat); -} - - -int ICMPClient::ping(SocketAddress& address, int repeat) const -{ - if (repeat <= 0) return 0; - - ICMPSocket icmpSocket(_family, _dataSize, _ttl, _timeout); - SocketAddress returnAddress; - - ICMPEventArgs eventArgs(address, repeat, icmpSocket.dataSize(), icmpSocket.ttl()); - pingBegin.notify(this, eventArgs); - - for (int i = 0; i < repeat; ++i) - { - icmpSocket.sendTo(address); - ++eventArgs; - - try - { - int t = icmpSocket.receiveFrom(returnAddress); - eventArgs.setReplyTime(i, t); - pingReply.notify(this, eventArgs); - } - catch (TimeoutException&) - { - std::ostringstream os; - os << address.host().toString() << ": Request timed out."; - eventArgs.setError(i, os.str()); - pingError.notify(this, eventArgs); - continue; - } - catch (ICMPException& ex) - { - std::ostringstream os; - os << address.host().toString() << ": " << ex.what(); - eventArgs.setError(i, os.str()); - pingError.notify(this, eventArgs); - continue; - } - catch (Exception& ex) - { - std::ostringstream os; - os << ex.displayText(); - eventArgs.setError(i, os.str()); - pingError.notify(this, eventArgs); - continue; - } - } - pingEnd.notify(this, eventArgs); - return eventArgs.received(); -} - - -int ICMPClient::pingIPv4(const std::string& address, int repeat, - int dataSize, int ttl, int timeout) -{ - if (repeat <= 0) return 0; - - SocketAddress a(address, 0); - return ping(a, IPAddress::IPv4, repeat, dataSize, ttl, timeout); -} - - -int ICMPClient::ping(SocketAddress& address, - IPAddress::Family family, int repeat, - int dataSize, int ttl, int timeout) -{ - if (repeat <= 0) return 0; - - ICMPSocket icmpSocket(family, dataSize, ttl, timeout); - SocketAddress returnAddress; - int received = 0; - - for (int i = 0; i < repeat; ++i) - { - icmpSocket.sendTo(address); - try - { - icmpSocket.receiveFrom(returnAddress); - ++received; - } - catch (TimeoutException&) - { - } - catch (ICMPException&) - { - } - } - return received; -} - - -} } // namespace Poco::Net +// +// ICMPClient.cpp +// +// Library: Net +// Package: ICMP +// Module: ICMPClient +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/SocketAddress.h" +#include "Poco/Net/ICMPClient.h" +#include "Poco/Net/ICMPSocket.h" +#include "Poco/Net/NetException.h" +#include "Poco/Channel.h" +#include "Poco/Message.h" +#include "Poco/Exception.h" +#include <sstream> + + +using Poco::Channel; +using Poco::Message; +using Poco::InvalidArgumentException; +using Poco::NotImplementedException; +using Poco::TimeoutException; +using Poco::Exception; + + +namespace Poco { +namespace Net { + + +ICMPClient::ICMPClient(SocketAddress::Family family, int dataSize, int ttl, int timeout): + _family(family), + _dataSize(dataSize), + _ttl(ttl), + _timeout(timeout) +{ +} + + +ICMPClient::~ICMPClient() +{ +} + + +int ICMPClient::ping(const std::string& address, int repeat) const +{ + if (repeat <= 0) return 0; + + SocketAddress addr(address, 0); + return ping(addr, repeat); +} + + +int ICMPClient::ping(SocketAddress& address, int repeat) const +{ + if (repeat <= 0) return 0; + + ICMPSocket icmpSocket(_family, _dataSize, _ttl, _timeout); + SocketAddress returnAddress; + + ICMPEventArgs eventArgs(address, repeat, icmpSocket.dataSize(), icmpSocket.ttl()); + pingBegin.notify(this, eventArgs); + + for (int i = 0; i < repeat; ++i) + { + icmpSocket.sendTo(address); + ++eventArgs; + + try + { + int t = icmpSocket.receiveFrom(returnAddress); + eventArgs.setReplyTime(i, t); + pingReply.notify(this, eventArgs); + } + catch (TimeoutException&) + { + std::ostringstream os; + os << address.host().toString() << ": Request timed out."; + eventArgs.setError(i, os.str()); + pingError.notify(this, eventArgs); + continue; + } + catch (ICMPException& ex) + { + std::ostringstream os; + os << address.host().toString() << ": " << ex.what(); + eventArgs.setError(i, os.str()); + pingError.notify(this, eventArgs); + continue; + } + catch (Exception& ex) + { + std::ostringstream os; + os << ex.displayText(); + eventArgs.setError(i, os.str()); + pingError.notify(this, eventArgs); + continue; + } + } + pingEnd.notify(this, eventArgs); + return eventArgs.received(); +} + + +int ICMPClient::pingIPv4(const std::string& address, int repeat, + int dataSize, int ttl, int timeout) +{ + if (repeat <= 0) return 0; + + SocketAddress a(address, 0); + return ping(a, IPAddress::IPv4, repeat, dataSize, ttl, timeout); +} + + +int ICMPClient::ping(SocketAddress& address, + IPAddress::Family family, int repeat, + int dataSize, int ttl, int timeout) +{ + if (repeat <= 0) return 0; + + ICMPSocket icmpSocket(family, dataSize, ttl, timeout); + SocketAddress returnAddress; + int received = 0; + + for (int i = 0; i < repeat; ++i) + { + icmpSocket.sendTo(address); + try + { + icmpSocket.receiveFrom(returnAddress); + ++received; + } + catch (TimeoutException&) + { + } + catch (ICMPException&) + { + } + } + return received; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/ICMPEventArgs.cpp b/contrib/libs/poco/Net/src/ICMPEventArgs.cpp index 3a219f9d74..202f9cc0c5 100644 --- a/contrib/libs/poco/Net/src/ICMPEventArgs.cpp +++ b/contrib/libs/poco/Net/src/ICMPEventArgs.cpp @@ -1,168 +1,168 @@ -// -// ICMPEventArgs.cpp -// -// Library: Net -// Package: ICMP -// Module: ICMPEventArgs -// -// Implementation of ICMPEventArgs -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/ICMPEventArgs.h" -#include "Poco/Net/SocketAddress.h" -#include "Poco/Net/DNS.h" -#include "Poco/Exception.h" -#include "Poco/Net/NetException.h" -#include <numeric> - - -using Poco::IOException; -using Poco::InvalidArgumentException; - - -namespace Poco { -namespace Net { - - -ICMPEventArgs::ICMPEventArgs(const SocketAddress& address, int repetitions, int dataSize, int ttl): - _address(address), - _sent(0), - _dataSize(dataSize), - _ttl(ttl), - _rtt(repetitions, 0), - _errors(repetitions) -{ -} - - -ICMPEventArgs::~ICMPEventArgs() -{ -} - - -std::string ICMPEventArgs::hostName() const -{ - try - { - return DNS::resolve(_address.host().toString()).name(); - } - catch (HostNotFoundException&) - { - } - catch (NoAddressFoundException&) - { - } - catch (DNSException&) - { - } - catch (IOException&) - { - } - return _address.host().toString(); -} - - -std::string ICMPEventArgs::hostAddress() const -{ - return _address.host().toString(); -} - - -void ICMPEventArgs::setRepetitions(int repetitions) -{ - _rtt.clear(); - _rtt.resize(repetitions, 0); - _errors.assign(repetitions, ""); -} - - -ICMPEventArgs& ICMPEventArgs::operator ++ () -{ - ++_sent; - return *this; -} - - -ICMPEventArgs ICMPEventArgs::operator ++ (int) -{ - ICMPEventArgs prev(*this); - operator ++ (); - return prev; -} - - -int ICMPEventArgs::received() const -{ - int received = 0; - - for (int i = 0; i < _rtt.size(); ++i) - { - if (_rtt[i]) ++received; - } - return received; -} - - -void ICMPEventArgs::setError(int index, const std::string& text) -{ - if (index >= _errors.size()) - throw InvalidArgumentException("Supplied index exceeds vector capacity."); - - _errors[index] = text; -} - - -const std::string& ICMPEventArgs::error(int index) const -{ - if (0 == _errors.size()) - throw InvalidArgumentException("Supplied index exceeds vector capacity."); - - if (-1 == index) index = _sent - 1; - - return _errors[index]; -} - - -void ICMPEventArgs::setReplyTime(int index, int time) -{ - if (index >= _rtt.size()) - throw InvalidArgumentException("Supplied index exceeds array capacity."); - if (0 == time) time = 1; - _rtt[index] = time; -} - - -int ICMPEventArgs::replyTime(int index) const -{ - if (0 == _rtt.size()) - throw InvalidArgumentException("Supplied index exceeds array capacity."); - - if (-1 == index) index = _sent - 1; - - return _rtt[index]; -} - - -int ICMPEventArgs::avgRTT() const -{ - if (0 == _rtt.size()) return 0; - - return (int) (std::accumulate(_rtt.begin(), _rtt.end(), 0) / _rtt.size()); -} - - -float ICMPEventArgs::percent() const -{ - if (0 == _rtt.size()) return 0; - - return ((float) received() / (float) _rtt.size()) * (float) 100.0; -} - - -} } // namespace Poco::Net +// +// ICMPEventArgs.cpp +// +// Library: Net +// Package: ICMP +// Module: ICMPEventArgs +// +// Implementation of ICMPEventArgs +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/ICMPEventArgs.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/Net/DNS.h" +#include "Poco/Exception.h" +#include "Poco/Net/NetException.h" +#include <numeric> + + +using Poco::IOException; +using Poco::InvalidArgumentException; + + +namespace Poco { +namespace Net { + + +ICMPEventArgs::ICMPEventArgs(const SocketAddress& address, int repetitions, int dataSize, int ttl): + _address(address), + _sent(0), + _dataSize(dataSize), + _ttl(ttl), + _rtt(repetitions, 0), + _errors(repetitions) +{ +} + + +ICMPEventArgs::~ICMPEventArgs() +{ +} + + +std::string ICMPEventArgs::hostName() const +{ + try + { + return DNS::resolve(_address.host().toString()).name(); + } + catch (HostNotFoundException&) + { + } + catch (NoAddressFoundException&) + { + } + catch (DNSException&) + { + } + catch (IOException&) + { + } + return _address.host().toString(); +} + + +std::string ICMPEventArgs::hostAddress() const +{ + return _address.host().toString(); +} + + +void ICMPEventArgs::setRepetitions(int repetitions) +{ + _rtt.clear(); + _rtt.resize(repetitions, 0); + _errors.assign(repetitions, ""); +} + + +ICMPEventArgs& ICMPEventArgs::operator ++ () +{ + ++_sent; + return *this; +} + + +ICMPEventArgs ICMPEventArgs::operator ++ (int) +{ + ICMPEventArgs prev(*this); + operator ++ (); + return prev; +} + + +int ICMPEventArgs::received() const +{ + int received = 0; + + for (int i = 0; i < _rtt.size(); ++i) + { + if (_rtt[i]) ++received; + } + return received; +} + + +void ICMPEventArgs::setError(int index, const std::string& text) +{ + if (index >= _errors.size()) + throw InvalidArgumentException("Supplied index exceeds vector capacity."); + + _errors[index] = text; +} + + +const std::string& ICMPEventArgs::error(int index) const +{ + if (0 == _errors.size()) + throw InvalidArgumentException("Supplied index exceeds vector capacity."); + + if (-1 == index) index = _sent - 1; + + return _errors[index]; +} + + +void ICMPEventArgs::setReplyTime(int index, int time) +{ + if (index >= _rtt.size()) + throw InvalidArgumentException("Supplied index exceeds array capacity."); + if (0 == time) time = 1; + _rtt[index] = time; +} + + +int ICMPEventArgs::replyTime(int index) const +{ + if (0 == _rtt.size()) + throw InvalidArgumentException("Supplied index exceeds array capacity."); + + if (-1 == index) index = _sent - 1; + + return _rtt[index]; +} + + +int ICMPEventArgs::avgRTT() const +{ + if (0 == _rtt.size()) return 0; + + return (int) (std::accumulate(_rtt.begin(), _rtt.end(), 0) / _rtt.size()); +} + + +float ICMPEventArgs::percent() const +{ + if (0 == _rtt.size()) return 0; + + return ((float) received() / (float) _rtt.size()) * (float) 100.0; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/ICMPPacket.cpp b/contrib/libs/poco/Net/src/ICMPPacket.cpp index a05f7260f4..a24b77cd78 100644 --- a/contrib/libs/poco/Net/src/ICMPPacket.cpp +++ b/contrib/libs/poco/Net/src/ICMPPacket.cpp @@ -1,110 +1,110 @@ -// -// ICMPPacket.cpp -// -// Library: Net -// Package: ICMP -// Module: ICMPPacket -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/ICMPPacket.h" -#include "Poco/Net/ICMPv4PacketImpl.h" -#include "Poco/Net/NetException.h" -#include "Poco/Timestamp.h" -#include "Poco/Timespan.h" -#include "Poco/NumberFormatter.h" -#include <sstream> - - -using Poco::InvalidArgumentException; -using Poco::NotImplementedException; -using Poco::Timestamp; -using Poco::Timespan; -using Poco::NumberFormatter; -using Poco::UInt8; -using Poco::UInt16; -using Poco::Int32; - - -namespace Poco { -namespace Net { - - -ICMPPacket::ICMPPacket(IPAddress::Family family, int dataSize):_pImpl(0) -{ - if (family == IPAddress::IPv4) - _pImpl = new ICMPv4PacketImpl(dataSize); -#if defined(POCO_HAVE_IPv6) - else if (family == IPAddress::IPv6) - throw NotImplementedException("ICMPv6 packets not implemented."); -#endif - else throw InvalidArgumentException("Invalid or unsupported address family passed to ICMPPacket"); -} - - -ICMPPacket::~ICMPPacket() -{ - delete _pImpl; -} - - -void ICMPPacket::setDataSize(int dataSize) -{ - _pImpl->setDataSize(dataSize); -} - - -int ICMPPacket::getDataSize() const -{ - return _pImpl->getDataSize(); -} - - -int ICMPPacket::packetSize() const -{ - return _pImpl->packetSize(); -} - - -int ICMPPacket::maxPacketSize() const -{ - return _pImpl->maxPacketSize(); -} - - -const Poco::UInt8* ICMPPacket::packet() -{ - return _pImpl->packet(); -} - - -struct timeval ICMPPacket::time(Poco::UInt8* buffer, int length) const -{ - return _pImpl->time(buffer, length); -} - - -bool ICMPPacket::validReplyID(Poco::UInt8* buffer, int length) const -{ - return _pImpl->validReplyID(buffer, length); -} - - -std::string ICMPPacket::errorDescription(Poco::UInt8* buffer, int length) -{ - return _pImpl->errorDescription(buffer, length); -} - - -std::string ICMPPacket::typeDescription(int typeId) -{ - return _pImpl->typeDescription(typeId); -} - - -} } // namespace Poco::Net +// +// ICMPPacket.cpp +// +// Library: Net +// Package: ICMP +// Module: ICMPPacket +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/ICMPPacket.h" +#include "Poco/Net/ICMPv4PacketImpl.h" +#include "Poco/Net/NetException.h" +#include "Poco/Timestamp.h" +#include "Poco/Timespan.h" +#include "Poco/NumberFormatter.h" +#include <sstream> + + +using Poco::InvalidArgumentException; +using Poco::NotImplementedException; +using Poco::Timestamp; +using Poco::Timespan; +using Poco::NumberFormatter; +using Poco::UInt8; +using Poco::UInt16; +using Poco::Int32; + + +namespace Poco { +namespace Net { + + +ICMPPacket::ICMPPacket(IPAddress::Family family, int dataSize):_pImpl(0) +{ + if (family == IPAddress::IPv4) + _pImpl = new ICMPv4PacketImpl(dataSize); +#if defined(POCO_HAVE_IPv6) + else if (family == IPAddress::IPv6) + throw NotImplementedException("ICMPv6 packets not implemented."); +#endif + else throw InvalidArgumentException("Invalid or unsupported address family passed to ICMPPacket"); +} + + +ICMPPacket::~ICMPPacket() +{ + delete _pImpl; +} + + +void ICMPPacket::setDataSize(int dataSize) +{ + _pImpl->setDataSize(dataSize); +} + + +int ICMPPacket::getDataSize() const +{ + return _pImpl->getDataSize(); +} + + +int ICMPPacket::packetSize() const +{ + return _pImpl->packetSize(); +} + + +int ICMPPacket::maxPacketSize() const +{ + return _pImpl->maxPacketSize(); +} + + +const Poco::UInt8* ICMPPacket::packet() +{ + return _pImpl->packet(); +} + + +struct timeval ICMPPacket::time(Poco::UInt8* buffer, int length) const +{ + return _pImpl->time(buffer, length); +} + + +bool ICMPPacket::validReplyID(Poco::UInt8* buffer, int length) const +{ + return _pImpl->validReplyID(buffer, length); +} + + +std::string ICMPPacket::errorDescription(Poco::UInt8* buffer, int length) +{ + return _pImpl->errorDescription(buffer, length); +} + + +std::string ICMPPacket::typeDescription(int typeId) +{ + return _pImpl->typeDescription(typeId); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/ICMPPacketImpl.cpp b/contrib/libs/poco/Net/src/ICMPPacketImpl.cpp index 48092c0094..d0f2592f61 100644 --- a/contrib/libs/poco/Net/src/ICMPPacketImpl.cpp +++ b/contrib/libs/poco/Net/src/ICMPPacketImpl.cpp @@ -1,103 +1,103 @@ -// -// ICMPPacketImpl.cpp -// -// Library: Net -// Package: ICMP -// Module: ICMPPacketImpl -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/ICMPPacketImpl.h" -#include "Poco/Net/NetException.h" -#include "Poco/Timestamp.h" -#include "Poco/Timespan.h" -#include "Poco/NumberFormatter.h" -#include <sstream> - - -using Poco::InvalidArgumentException; -using Poco::Timestamp; -using Poco::Timespan; -using Poco::NumberFormatter; -using Poco::UInt8; -using Poco::UInt16; -using Poco::Int32; - - -namespace Poco { -namespace Net { - - -const UInt16 ICMPPacketImpl::MAX_PACKET_SIZE = 4096; -const UInt16 ICMPPacketImpl::MAX_SEQ_VALUE = 65535; - - -ICMPPacketImpl::ICMPPacketImpl(int dataSize): - _seq(0), - _pPacket(new UInt8[MAX_PACKET_SIZE]), - _dataSize(dataSize) -{ - if (_dataSize > MAX_PACKET_SIZE) - throw InvalidArgumentException("Packet size must be <= " + NumberFormatter::format(MAX_PACKET_SIZE)); -} - - -ICMPPacketImpl::~ICMPPacketImpl() -{ - delete [] _pPacket; -} - - -void ICMPPacketImpl::setDataSize(int dataSize) -{ - _dataSize = dataSize; - initPacket(); -} - - -int ICMPPacketImpl::getDataSize() const -{ - return _dataSize; -} - - -const Poco::UInt8* ICMPPacketImpl::packet(bool init) -{ - if (init) initPacket(); - return _pPacket; -} - - -unsigned short ICMPPacketImpl::checksum(UInt16 *addr, Int32 len) -{ - Int32 nleft = len; - UInt16* w = addr; - UInt16 answer; - Int32 sum = 0; - - while (nleft > 1) - { - sum += *w++; - nleft -= sizeof(UInt16); - } - - if (nleft == 1) - { - UInt16 u = 0; - *(UInt8*) (&u) = *(UInt8*) w; - sum += u; - } - - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); - answer = static_cast<UInt16>(~sum); - return answer; -} - - -} } // namespace Poco::Net +// +// ICMPPacketImpl.cpp +// +// Library: Net +// Package: ICMP +// Module: ICMPPacketImpl +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/ICMPPacketImpl.h" +#include "Poco/Net/NetException.h" +#include "Poco/Timestamp.h" +#include "Poco/Timespan.h" +#include "Poco/NumberFormatter.h" +#include <sstream> + + +using Poco::InvalidArgumentException; +using Poco::Timestamp; +using Poco::Timespan; +using Poco::NumberFormatter; +using Poco::UInt8; +using Poco::UInt16; +using Poco::Int32; + + +namespace Poco { +namespace Net { + + +const UInt16 ICMPPacketImpl::MAX_PACKET_SIZE = 4096; +const UInt16 ICMPPacketImpl::MAX_SEQ_VALUE = 65535; + + +ICMPPacketImpl::ICMPPacketImpl(int dataSize): + _seq(0), + _pPacket(new UInt8[MAX_PACKET_SIZE]), + _dataSize(dataSize) +{ + if (_dataSize > MAX_PACKET_SIZE) + throw InvalidArgumentException("Packet size must be <= " + NumberFormatter::format(MAX_PACKET_SIZE)); +} + + +ICMPPacketImpl::~ICMPPacketImpl() +{ + delete [] _pPacket; +} + + +void ICMPPacketImpl::setDataSize(int dataSize) +{ + _dataSize = dataSize; + initPacket(); +} + + +int ICMPPacketImpl::getDataSize() const +{ + return _dataSize; +} + + +const Poco::UInt8* ICMPPacketImpl::packet(bool init) +{ + if (init) initPacket(); + return _pPacket; +} + + +unsigned short ICMPPacketImpl::checksum(UInt16 *addr, Int32 len) +{ + Int32 nleft = len; + UInt16* w = addr; + UInt16 answer; + Int32 sum = 0; + + while (nleft > 1) + { + sum += *w++; + nleft -= sizeof(UInt16); + } + + if (nleft == 1) + { + UInt16 u = 0; + *(UInt8*) (&u) = *(UInt8*) w; + sum += u; + } + + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + answer = static_cast<UInt16>(~sum); + return answer; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/ICMPSocket.cpp b/contrib/libs/poco/Net/src/ICMPSocket.cpp index 4e66c237ae..d09e8c0ef1 100644 --- a/contrib/libs/poco/Net/src/ICMPSocket.cpp +++ b/contrib/libs/poco/Net/src/ICMPSocket.cpp @@ -1,94 +1,94 @@ -// -// ICMPSocket.cpp -// -// Library: Net -// Package: ICMP -// Module: ICMPSocket -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/ICMPSocket.h" -#include "Poco/Net/ICMPSocketImpl.h" -#include "Poco/Exception.h" - - -using Poco::InvalidArgumentException; - - -namespace Poco { -namespace Net { - - -ICMPSocket::ICMPSocket(IPAddress::Family family, int dataSize, int ttl, int timeout): - Socket(new ICMPSocketImpl(family, dataSize, ttl, timeout)) -{ -} - - -ICMPSocket::ICMPSocket(const Socket& socket): - Socket(socket) -{ - if (!dynamic_cast<ICMPSocketImpl*>(impl())) - throw InvalidArgumentException("Cannot assign incompatible socket"); -} - - -ICMPSocket::ICMPSocket(SocketImpl* pImpl): - Socket(pImpl) -{ - if (!dynamic_cast<ICMPSocketImpl*>(impl())) - throw InvalidArgumentException("Cannot assign incompatible socket"); -} - - -ICMPSocket::~ICMPSocket() -{ -} - - -ICMPSocket& ICMPSocket::operator = (const Socket& socket) -{ - if (dynamic_cast<ICMPSocketImpl*>(socket.impl())) - Socket::operator = (socket); - else - throw InvalidArgumentException("Cannot assign incompatible socket"); - return *this; -} - - -int ICMPSocket::sendTo(const SocketAddress& address, int flags) -{ - return impl()->sendTo(0, 0, address, flags); -} - - -int ICMPSocket::receiveFrom(SocketAddress& address, int flags) -{ - return impl()->receiveFrom(0, 0, address, flags); -} - - -int ICMPSocket::dataSize() const -{ - return static_cast<ICMPSocketImpl*>(impl())->dataSize(); -} - - -int ICMPSocket::ttl() const -{ - return static_cast<ICMPSocketImpl*>(impl())->ttl(); -} - - -int ICMPSocket::timeout() const -{ - return static_cast<ICMPSocketImpl*>(impl())->timeout(); -} - - -} } // namespace Poco::Net +// +// ICMPSocket.cpp +// +// Library: Net +// Package: ICMP +// Module: ICMPSocket +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/ICMPSocket.h" +#include "Poco/Net/ICMPSocketImpl.h" +#include "Poco/Exception.h" + + +using Poco::InvalidArgumentException; + + +namespace Poco { +namespace Net { + + +ICMPSocket::ICMPSocket(IPAddress::Family family, int dataSize, int ttl, int timeout): + Socket(new ICMPSocketImpl(family, dataSize, ttl, timeout)) +{ +} + + +ICMPSocket::ICMPSocket(const Socket& socket): + Socket(socket) +{ + if (!dynamic_cast<ICMPSocketImpl*>(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +ICMPSocket::ICMPSocket(SocketImpl* pImpl): + Socket(pImpl) +{ + if (!dynamic_cast<ICMPSocketImpl*>(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +ICMPSocket::~ICMPSocket() +{ +} + + +ICMPSocket& ICMPSocket::operator = (const Socket& socket) +{ + if (dynamic_cast<ICMPSocketImpl*>(socket.impl())) + Socket::operator = (socket); + else + throw InvalidArgumentException("Cannot assign incompatible socket"); + return *this; +} + + +int ICMPSocket::sendTo(const SocketAddress& address, int flags) +{ + return impl()->sendTo(0, 0, address, flags); +} + + +int ICMPSocket::receiveFrom(SocketAddress& address, int flags) +{ + return impl()->receiveFrom(0, 0, address, flags); +} + + +int ICMPSocket::dataSize() const +{ + return static_cast<ICMPSocketImpl*>(impl())->dataSize(); +} + + +int ICMPSocket::ttl() const +{ + return static_cast<ICMPSocketImpl*>(impl())->ttl(); +} + + +int ICMPSocket::timeout() const +{ + return static_cast<ICMPSocketImpl*>(impl())->timeout(); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/ICMPSocketImpl.cpp b/contrib/libs/poco/Net/src/ICMPSocketImpl.cpp index 8c68d53030..b68748e2ab 100644 --- a/contrib/libs/poco/Net/src/ICMPSocketImpl.cpp +++ b/contrib/libs/poco/Net/src/ICMPSocketImpl.cpp @@ -1,97 +1,97 @@ -// -// ICMPSocketImpl.cpp -// -// Library: Net -// Package: ICMP -// Module: ICMPSocketImpl -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/ICMPSocketImpl.h" -#include "Poco/Net/NetException.h" -#include "Poco/Timespan.h" -#include "Poco/Timestamp.h" -#include "Poco/Exception.h" -#include "Poco/Buffer.h" - - -using Poco::TimeoutException; -using Poco::Timespan; -using Poco::Exception; - - -namespace Poco { -namespace Net { - - -ICMPSocketImpl::ICMPSocketImpl(IPAddress::Family family, int dataSize, int ttl, int timeout): - RawSocketImpl(family, IPPROTO_ICMP), - _icmpPacket(family, dataSize), - _ttl(ttl), - _timeout(timeout) -{ - setOption(IPPROTO_IP, IP_TTL, ttl); - setReceiveTimeout(Timespan(timeout)); -} - - -ICMPSocketImpl::~ICMPSocketImpl() -{ -} - - -int ICMPSocketImpl::sendTo(const void*, int, const SocketAddress& address, int flags) -{ - int n = SocketImpl::sendTo(_icmpPacket.packet(), _icmpPacket.packetSize(), address, flags); - return n; -} - - -int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags) -{ - int maxPacketSize = _icmpPacket.maxPacketSize(); - Poco::Buffer<unsigned char> buffer(maxPacketSize); - - try - { - Poco::Timestamp ts; - do - { - if (ts.isElapsed(_timeout)) - { - // This guards against a possible DoS attack, where sending - // fake ping responses will cause an endless loop. - throw TimeoutException(); - } - SocketImpl::receiveFrom(buffer.begin(), maxPacketSize, address, flags); - } - while (!_icmpPacket.validReplyID(buffer.begin(), maxPacketSize)); - } - catch (TimeoutException&) - { - throw; - } - catch (Exception&) - { - std::string err = _icmpPacket.errorDescription(buffer.begin(), maxPacketSize); - if (!err.empty()) - throw ICMPException(err); - else - throw; - } - - struct timeval then = _icmpPacket.time(buffer.begin(), maxPacketSize); - struct timeval now = _icmpPacket.time(); - - int elapsed = (((now.tv_sec * 1000000) + now.tv_usec) - ((then.tv_sec * 1000000) + then.tv_usec))/1000; - - return elapsed; -} - - -} } // namespace Poco::Net +// +// ICMPSocketImpl.cpp +// +// Library: Net +// Package: ICMP +// Module: ICMPSocketImpl +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/ICMPSocketImpl.h" +#include "Poco/Net/NetException.h" +#include "Poco/Timespan.h" +#include "Poco/Timestamp.h" +#include "Poco/Exception.h" +#include "Poco/Buffer.h" + + +using Poco::TimeoutException; +using Poco::Timespan; +using Poco::Exception; + + +namespace Poco { +namespace Net { + + +ICMPSocketImpl::ICMPSocketImpl(IPAddress::Family family, int dataSize, int ttl, int timeout): + RawSocketImpl(family, IPPROTO_ICMP), + _icmpPacket(family, dataSize), + _ttl(ttl), + _timeout(timeout) +{ + setOption(IPPROTO_IP, IP_TTL, ttl); + setReceiveTimeout(Timespan(timeout)); +} + + +ICMPSocketImpl::~ICMPSocketImpl() +{ +} + + +int ICMPSocketImpl::sendTo(const void*, int, const SocketAddress& address, int flags) +{ + int n = SocketImpl::sendTo(_icmpPacket.packet(), _icmpPacket.packetSize(), address, flags); + return n; +} + + +int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags) +{ + int maxPacketSize = _icmpPacket.maxPacketSize(); + Poco::Buffer<unsigned char> buffer(maxPacketSize); + + try + { + Poco::Timestamp ts; + do + { + if (ts.isElapsed(_timeout)) + { + // This guards against a possible DoS attack, where sending + // fake ping responses will cause an endless loop. + throw TimeoutException(); + } + SocketImpl::receiveFrom(buffer.begin(), maxPacketSize, address, flags); + } + while (!_icmpPacket.validReplyID(buffer.begin(), maxPacketSize)); + } + catch (TimeoutException&) + { + throw; + } + catch (Exception&) + { + std::string err = _icmpPacket.errorDescription(buffer.begin(), maxPacketSize); + if (!err.empty()) + throw ICMPException(err); + else + throw; + } + + struct timeval then = _icmpPacket.time(buffer.begin(), maxPacketSize); + struct timeval now = _icmpPacket.time(); + + int elapsed = (((now.tv_sec * 1000000) + now.tv_usec) - ((then.tv_sec * 1000000) + then.tv_usec))/1000; + + return elapsed; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/ICMPv4PacketImpl.cpp b/contrib/libs/poco/Net/src/ICMPv4PacketImpl.cpp index 7df987a6fd..851e4d7ce5 100644 --- a/contrib/libs/poco/Net/src/ICMPv4PacketImpl.cpp +++ b/contrib/libs/poco/Net/src/ICMPv4PacketImpl.cpp @@ -1,263 +1,263 @@ -// -// ICMPv4PacketImpl.cpp -// -// Library: Net -// Package: ICMP -// Module: ICMPv4PacketImpl -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/ICMPv4PacketImpl.h" -#include "Poco/Net/NetException.h" -#include "Poco/Timestamp.h" -#include "Poco/Timespan.h" -#include "Poco/NumberFormatter.h" -#if !defined(POCO_VXWORKS) -#include "Poco/Process.h" -#endif -#include <sstream> - - -using Poco::InvalidArgumentException; -using Poco::Timestamp; -using Poco::Timespan; -using Poco::NumberFormatter; -using Poco::UInt8; -using Poco::UInt16; -using Poco::Int32; - - -namespace Poco { -namespace Net { - - -const UInt8 ICMPv4PacketImpl::DESTINATION_UNREACHABLE_TYPE = 3; -const Poco::UInt8 ICMPv4PacketImpl::SOURCE_QUENCH_TYPE = 4; -const Poco::UInt8 ICMPv4PacketImpl::REDIRECT_MESSAGE_TYPE = 5; -const UInt8 ICMPv4PacketImpl::TIME_EXCEEDED_TYPE = 11; -const Poco::UInt8 ICMPv4PacketImpl::PARAMETER_PROBLEM_TYPE = 12; - - -const std::string ICMPv4PacketImpl::MESSAGE_TYPE[] = -{ - "Echo Reply", - "ICMP 1", - "ICMP 2", - "Dest Unreachable", - "Source Quench", - "Redirect", - "ICMP 6", - "ICMP 7", - "Echo", - "ICMP 9", - "ICMP 10", - "Time Exceeded", - "Parameter Problem", - "Timestamp", - "Timestamp Reply", - "Info Request", - "Info Reply", - "Unknown type" -}; - - -const std::string ICMPv4PacketImpl::DESTINATION_UNREACHABLE_CODE[] = -{ - "Net unreachable", - "Host unreachable", - "Protocol unreachable", - "Port unreachable", - "Fragmentation needed and DF set", - "Source route failed", - "Unknown code" -}; - - -const std::string ICMPv4PacketImpl::REDIRECT_MESSAGE_CODE[] = -{ - "Redirect datagrams for the network", - "Redirect datagrams for the host", - "Redirect datagrams for the type of service and network", - "Redirect datagrams for the type of service and host", - "Unknown code" -}; - - -const std::string ICMPv4PacketImpl::TIME_EXCEEDED_CODE[] = -{ - "Time to live exceeded in transit", - "Fragment reassembly time exceeded", - "Unknown code" -}; - - -const std::string ICMPv4PacketImpl::PARAMETER_PROBLEM_CODE[] = -{ - "Pointer indicates the error", - "Unknown code" -}; - - -ICMPv4PacketImpl::ICMPv4PacketImpl(int dataSize) - : ICMPPacketImpl(dataSize), - _seq(0) -{ - initPacket(); -} - - -ICMPv4PacketImpl::~ICMPv4PacketImpl() -{ -} - - -int ICMPv4PacketImpl::packetSize() const -{ - return getDataSize() + sizeof(Header); -} - - -void ICMPv4PacketImpl::initPacket() -{ - if (_seq >= MAX_SEQ_VALUE) resetSequence(); - - Header* icp = (Header*) packet(false); - icp->type = ECHO_REQUEST; - icp->code = 0; - icp->checksum = 0; - icp->seq = ++_seq; -#if defined(POCO_VXWORKS) - icp->id = 0; -#else - icp->id = static_cast<UInt16>(Poco::Process::id()); -#endif - - struct timeval* ptp = (struct timeval *) (icp + 1); - *ptp = time(); - - icp->checksum = checksum((UInt16*) icp, getDataSize() + sizeof(Header)); -} - - -struct timeval ICMPv4PacketImpl::time(Poco::UInt8* buffer, int length) const -{ - struct timeval tv; - - if (0 == buffer || 0 == length) - { - Timespan value(Timestamp().epochMicroseconds()); - tv.tv_sec = (long) value.totalSeconds(); - tv.tv_usec = (long) value.useconds(); - } - else - { - struct timeval* ptv = (struct timeval*) data(buffer, length); - if (ptv) tv = *ptv; - else throw InvalidArgumentException("Invalid packet."); - } - return tv; -} - - -ICMPv4PacketImpl::Header* ICMPv4PacketImpl::header(Poco::UInt8* buffer, int length) const -{ - poco_check_ptr (buffer); - - int offset = (buffer[0] & 0x0F) * 4; - if ((offset + sizeof(Header)) > length) return 0; - - buffer += offset; - return (Header *) buffer; -} - - -Poco::UInt8* ICMPv4PacketImpl::data(Poco::UInt8* buffer, int length) const -{ - return ((Poco::UInt8*) header(buffer, length)) + sizeof(Header); -} - - -bool ICMPv4PacketImpl::validReplyID(Poco::UInt8* buffer, int length) const -{ - Header *icp = header(buffer, length); -#if defined(POCO_VXWORKS) - return icp && icp->id == 0; -#else - return icp && (static_cast<Poco::UInt16>(Process::id()) == icp->id); -#endif -} - - -std::string ICMPv4PacketImpl::errorDescription(unsigned char* buffer, int length) -{ - Header *icp = header(buffer, length); - - if (!icp) return "Invalid header."; - if (ECHO_REPLY == icp->type) return std::string(); // not an error - - UInt8 pointer = 0; - if (PARAMETER_PROBLEM == icp->type) - { - UInt8 mask = 0x00FF; - pointer = icp->id & mask; - } - - MessageType type = static_cast<MessageType>(icp->type); - int code = icp->code; - std::ostringstream err; - - switch (type) - { - case DESTINATION_UNREACHABLE_TYPE: - if (code >= NET_UNREACHABLE && code < DESTINATION_UNREACHABLE_UNKNOWN) - err << DESTINATION_UNREACHABLE_CODE[code]; - else - err << DESTINATION_UNREACHABLE_CODE[DESTINATION_UNREACHABLE_UNKNOWN]; - break; - - case SOURCE_QUENCH_TYPE: - err << "Source quench"; - break; - - case REDIRECT_MESSAGE_TYPE: - if (code >= REDIRECT_NETWORK && code < REDIRECT_MESSAGE_UNKNOWN) - err << REDIRECT_MESSAGE_CODE[code]; - else - err << REDIRECT_MESSAGE_CODE[REDIRECT_MESSAGE_UNKNOWN]; - break; - - case TIME_EXCEEDED_TYPE: - if (code >= TIME_TO_LIVE || code < TIME_EXCEEDED_UNKNOWN) - err << TIME_EXCEEDED_CODE[code]; - else - err << TIME_EXCEEDED_CODE[TIME_EXCEEDED_UNKNOWN]; - break; - - case PARAMETER_PROBLEM_TYPE: - if (POINTER_INDICATES_THE_ERROR != code) - code = PARAMETER_PROBLEM_UNKNOWN; - err << PARAMETER_PROBLEM_CODE[code] << ": error in octet #" << pointer; - break; - - default: - err << "Unknown type."; - break; - } - - return err.str(); -} - -std::string ICMPv4PacketImpl::typeDescription(int typeId) -{ - poco_assert (typeId >= ECHO_REPLY && typeId < MESSAGE_TYPE_LENGTH); - - return MESSAGE_TYPE[typeId]; -} - - -} } // namespace Poco::Net +// +// ICMPv4PacketImpl.cpp +// +// Library: Net +// Package: ICMP +// Module: ICMPv4PacketImpl +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/ICMPv4PacketImpl.h" +#include "Poco/Net/NetException.h" +#include "Poco/Timestamp.h" +#include "Poco/Timespan.h" +#include "Poco/NumberFormatter.h" +#if !defined(POCO_VXWORKS) +#include "Poco/Process.h" +#endif +#include <sstream> + + +using Poco::InvalidArgumentException; +using Poco::Timestamp; +using Poco::Timespan; +using Poco::NumberFormatter; +using Poco::UInt8; +using Poco::UInt16; +using Poco::Int32; + + +namespace Poco { +namespace Net { + + +const UInt8 ICMPv4PacketImpl::DESTINATION_UNREACHABLE_TYPE = 3; +const Poco::UInt8 ICMPv4PacketImpl::SOURCE_QUENCH_TYPE = 4; +const Poco::UInt8 ICMPv4PacketImpl::REDIRECT_MESSAGE_TYPE = 5; +const UInt8 ICMPv4PacketImpl::TIME_EXCEEDED_TYPE = 11; +const Poco::UInt8 ICMPv4PacketImpl::PARAMETER_PROBLEM_TYPE = 12; + + +const std::string ICMPv4PacketImpl::MESSAGE_TYPE[] = +{ + "Echo Reply", + "ICMP 1", + "ICMP 2", + "Dest Unreachable", + "Source Quench", + "Redirect", + "ICMP 6", + "ICMP 7", + "Echo", + "ICMP 9", + "ICMP 10", + "Time Exceeded", + "Parameter Problem", + "Timestamp", + "Timestamp Reply", + "Info Request", + "Info Reply", + "Unknown type" +}; + + +const std::string ICMPv4PacketImpl::DESTINATION_UNREACHABLE_CODE[] = +{ + "Net unreachable", + "Host unreachable", + "Protocol unreachable", + "Port unreachable", + "Fragmentation needed and DF set", + "Source route failed", + "Unknown code" +}; + + +const std::string ICMPv4PacketImpl::REDIRECT_MESSAGE_CODE[] = +{ + "Redirect datagrams for the network", + "Redirect datagrams for the host", + "Redirect datagrams for the type of service and network", + "Redirect datagrams for the type of service and host", + "Unknown code" +}; + + +const std::string ICMPv4PacketImpl::TIME_EXCEEDED_CODE[] = +{ + "Time to live exceeded in transit", + "Fragment reassembly time exceeded", + "Unknown code" +}; + + +const std::string ICMPv4PacketImpl::PARAMETER_PROBLEM_CODE[] = +{ + "Pointer indicates the error", + "Unknown code" +}; + + +ICMPv4PacketImpl::ICMPv4PacketImpl(int dataSize) + : ICMPPacketImpl(dataSize), + _seq(0) +{ + initPacket(); +} + + +ICMPv4PacketImpl::~ICMPv4PacketImpl() +{ +} + + +int ICMPv4PacketImpl::packetSize() const +{ + return getDataSize() + sizeof(Header); +} + + +void ICMPv4PacketImpl::initPacket() +{ + if (_seq >= MAX_SEQ_VALUE) resetSequence(); + + Header* icp = (Header*) packet(false); + icp->type = ECHO_REQUEST; + icp->code = 0; + icp->checksum = 0; + icp->seq = ++_seq; +#if defined(POCO_VXWORKS) + icp->id = 0; +#else + icp->id = static_cast<UInt16>(Poco::Process::id()); +#endif + + struct timeval* ptp = (struct timeval *) (icp + 1); + *ptp = time(); + + icp->checksum = checksum((UInt16*) icp, getDataSize() + sizeof(Header)); +} + + +struct timeval ICMPv4PacketImpl::time(Poco::UInt8* buffer, int length) const +{ + struct timeval tv; + + if (0 == buffer || 0 == length) + { + Timespan value(Timestamp().epochMicroseconds()); + tv.tv_sec = (long) value.totalSeconds(); + tv.tv_usec = (long) value.useconds(); + } + else + { + struct timeval* ptv = (struct timeval*) data(buffer, length); + if (ptv) tv = *ptv; + else throw InvalidArgumentException("Invalid packet."); + } + return tv; +} + + +ICMPv4PacketImpl::Header* ICMPv4PacketImpl::header(Poco::UInt8* buffer, int length) const +{ + poco_check_ptr (buffer); + + int offset = (buffer[0] & 0x0F) * 4; + if ((offset + sizeof(Header)) > length) return 0; + + buffer += offset; + return (Header *) buffer; +} + + +Poco::UInt8* ICMPv4PacketImpl::data(Poco::UInt8* buffer, int length) const +{ + return ((Poco::UInt8*) header(buffer, length)) + sizeof(Header); +} + + +bool ICMPv4PacketImpl::validReplyID(Poco::UInt8* buffer, int length) const +{ + Header *icp = header(buffer, length); +#if defined(POCO_VXWORKS) + return icp && icp->id == 0; +#else + return icp && (static_cast<Poco::UInt16>(Process::id()) == icp->id); +#endif +} + + +std::string ICMPv4PacketImpl::errorDescription(unsigned char* buffer, int length) +{ + Header *icp = header(buffer, length); + + if (!icp) return "Invalid header."; + if (ECHO_REPLY == icp->type) return std::string(); // not an error + + UInt8 pointer = 0; + if (PARAMETER_PROBLEM == icp->type) + { + UInt8 mask = 0x00FF; + pointer = icp->id & mask; + } + + MessageType type = static_cast<MessageType>(icp->type); + int code = icp->code; + std::ostringstream err; + + switch (type) + { + case DESTINATION_UNREACHABLE_TYPE: + if (code >= NET_UNREACHABLE && code < DESTINATION_UNREACHABLE_UNKNOWN) + err << DESTINATION_UNREACHABLE_CODE[code]; + else + err << DESTINATION_UNREACHABLE_CODE[DESTINATION_UNREACHABLE_UNKNOWN]; + break; + + case SOURCE_QUENCH_TYPE: + err << "Source quench"; + break; + + case REDIRECT_MESSAGE_TYPE: + if (code >= REDIRECT_NETWORK && code < REDIRECT_MESSAGE_UNKNOWN) + err << REDIRECT_MESSAGE_CODE[code]; + else + err << REDIRECT_MESSAGE_CODE[REDIRECT_MESSAGE_UNKNOWN]; + break; + + case TIME_EXCEEDED_TYPE: + if (code >= TIME_TO_LIVE || code < TIME_EXCEEDED_UNKNOWN) + err << TIME_EXCEEDED_CODE[code]; + else + err << TIME_EXCEEDED_CODE[TIME_EXCEEDED_UNKNOWN]; + break; + + case PARAMETER_PROBLEM_TYPE: + if (POINTER_INDICATES_THE_ERROR != code) + code = PARAMETER_PROBLEM_UNKNOWN; + err << PARAMETER_PROBLEM_CODE[code] << ": error in octet #" << pointer; + break; + + default: + err << "Unknown type."; + break; + } + + return err.str(); +} + +std::string ICMPv4PacketImpl::typeDescription(int typeId) +{ + poco_assert (typeId >= ECHO_REPLY && typeId < MESSAGE_TYPE_LENGTH); + + return MESSAGE_TYPE[typeId]; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/IPAddress.cpp b/contrib/libs/poco/Net/src/IPAddress.cpp index e34a02181b..69e433e1b8 100644 --- a/contrib/libs/poco/Net/src/IPAddress.cpp +++ b/contrib/libs/poco/Net/src/IPAddress.cpp @@ -1,601 +1,601 @@ -// -// IPAddress.cpp -// -// Library: Net -// Package: NetCore -// Module: IPAddress -// -// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/IPAddress.h" -#include "Poco/Net/NetException.h" -#include "Poco/RefCountedObject.h" -#include "Poco/NumberFormatter.h" -#include "Poco/BinaryReader.h" -#include "Poco/BinaryWriter.h" -#include "Poco/String.h" -#include "Poco/Types.h" - - -using Poco::RefCountedObject; -using Poco::NumberFormatter; -using Poco::BinaryReader; -using Poco::BinaryWriter; -using Poco::toLower; -using Poco::trim; -using Poco::UInt8; -using Poco::UInt16; -using Poco::UInt32; -using Poco::Net::Impl::IPAddressImpl; -using Poco::Net::Impl::IPv4AddressImpl; -#if defined(POCO_HAVE_IPv6) -using Poco::Net::Impl::IPv6AddressImpl; -#endif - - -namespace Poco { -namespace Net { - - -#if !defined(_MSC_VER) || defined(__STDC__) -// Go home MSVC, you're drunk... -// See http://stackoverflow.com/questions/5899857/multiple-definition-error-for-static-const-class-members -const IPAddress::Family IPAddress::IPv4; -#if defined(POCO_HAVE_IPv6) -const IPAddress::Family IPAddress::IPv6; -#endif -#endif - - -IPAddress::IPAddress() -{ - newIPv4(); -} - - -IPAddress::IPAddress(const IPAddress& addr) -{ - if (addr.family() == IPv4) - newIPv4(addr.addr()); -#if defined(POCO_HAVE_IPv6) - else - newIPv6(addr.addr(), addr.scope()); -#endif -} - - -IPAddress::IPAddress(Family family) -{ - if (family == IPv4) - newIPv4(); -#if defined(POCO_HAVE_IPv6) - else if (family == IPv6) - newIPv6(); -#endif - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); -} - - -IPAddress::IPAddress(const std::string& addr) -{ - IPv4AddressImpl empty4 = IPv4AddressImpl(); - if (addr.empty() || trim(addr) == "0.0.0.0") - { - newIPv4(empty4.addr()); - return; - } - - IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); - if (addr4 != empty4) - { - newIPv4(addr4.addr()); - return; - } - -#if defined(POCO_HAVE_IPv6) - IPv6AddressImpl empty6 = IPv6AddressImpl(); - if (addr.empty() || trim(addr) == "::") - { - newIPv6(empty6.addr()); - return; - } - - IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); - if (addr6 != IPv6AddressImpl()) - { - newIPv6(addr6.addr(), addr6.scope()); - return; - } -#endif - - throw InvalidAddressException(addr); -} - - -IPAddress::IPAddress(const std::string& addr, Family family) -{ - if (family == IPv4) - { - IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); - newIPv4(addr4.addr()); - return; - } -#if defined(POCO_HAVE_IPv6) - else if (family == IPv6) - { - IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); - newIPv6(addr6.addr(), addr6.scope()); - return; - } -#endif - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); -} - - -IPAddress::IPAddress(const void* addr, poco_socklen_t length) - : _pImpl(0) -{ - if (length == sizeof(struct in_addr)) - newIPv4(addr); -#if defined(POCO_HAVE_IPv6) - else if (length == sizeof(struct in6_addr)) - newIPv6(addr); -#endif - else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()"); -} - - -IPAddress::IPAddress(const void* addr, poco_socklen_t length, Poco::UInt32 scope) -{ - if (length == sizeof(struct in_addr)) - newIPv4(addr); -#if defined(POCO_HAVE_IPv6) - else if (length == sizeof(struct in6_addr)) - newIPv6(addr, scope); -#endif - else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()"); -} - - -IPAddress::IPAddress(unsigned prefix, Family family) -{ - if (family == IPv4) - { - if (prefix <= 32) - newIPv4(prefix); - else - throw Poco::InvalidArgumentException("Invalid prefix length passed to IPAddress()"); - } -#if defined(POCO_HAVE_IPv6) - else if (family == IPv6) - { - if (prefix <= 128) - newIPv6(prefix); - else - throw Poco::InvalidArgumentException("Invalid prefix length passed to IPAddress()"); - } -#endif - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); -} - - -#if defined(_WIN32) -IPAddress::IPAddress(const SOCKET_ADDRESS& socket_address) - : _pImpl(0) -{ - ADDRESS_FAMILY family = socket_address.lpSockaddr->sa_family; - if (family == AF_INET) - newIPv4(&reinterpret_cast<const struct sockaddr_in*>(socket_address.lpSockaddr)->sin_addr); -#if defined(POCO_HAVE_IPv6) - else if (family == AF_INET6) - newIPv6(&reinterpret_cast<const struct sockaddr_in6*>(socket_address.lpSockaddr)->sin6_addr, - reinterpret_cast<const struct sockaddr_in6*>(socket_address.lpSockaddr)->sin6_scope_id); -#endif - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); -} -#endif - - -IPAddress::IPAddress(const struct sockaddr& sockaddr) -{ - unsigned short family = sockaddr.sa_family; - if (family == AF_INET) - newIPv4(&reinterpret_cast<const struct sockaddr_in*>(&sockaddr)->sin_addr); -#if defined(POCO_HAVE_IPv6) - else if (family == AF_INET6) - newIPv6(&reinterpret_cast<const struct sockaddr_in6*>(&sockaddr)->sin6_addr, - reinterpret_cast<const struct sockaddr_in6*>(&sockaddr)->sin6_scope_id); -#endif - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); -} - - -IPAddress::~IPAddress() -{ -} - - -IPAddress& IPAddress::operator = (const IPAddress& addr) -{ - if (&addr != this) - { - if (addr.family() == IPAddress::IPv4) - newIPv4(addr.addr()); -#if defined(POCO_HAVE_IPv6) - else if (addr.family() == IPAddress::IPv6) - newIPv6(addr.addr(), addr.scope()); -#endif +// +// IPAddress.cpp +// +// Library: Net +// Package: NetCore +// Module: IPAddress +// +// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/IPAddress.h" +#include "Poco/Net/NetException.h" +#include "Poco/RefCountedObject.h" +#include "Poco/NumberFormatter.h" +#include "Poco/BinaryReader.h" +#include "Poco/BinaryWriter.h" +#include "Poco/String.h" +#include "Poco/Types.h" + + +using Poco::RefCountedObject; +using Poco::NumberFormatter; +using Poco::BinaryReader; +using Poco::BinaryWriter; +using Poco::toLower; +using Poco::trim; +using Poco::UInt8; +using Poco::UInt16; +using Poco::UInt32; +using Poco::Net::Impl::IPAddressImpl; +using Poco::Net::Impl::IPv4AddressImpl; +#if defined(POCO_HAVE_IPv6) +using Poco::Net::Impl::IPv6AddressImpl; +#endif + + +namespace Poco { +namespace Net { + + +#if !defined(_MSC_VER) || defined(__STDC__) +// Go home MSVC, you're drunk... +// See http://stackoverflow.com/questions/5899857/multiple-definition-error-for-static-const-class-members +const IPAddress::Family IPAddress::IPv4; +#if defined(POCO_HAVE_IPv6) +const IPAddress::Family IPAddress::IPv6; +#endif +#endif + + +IPAddress::IPAddress() +{ + newIPv4(); +} + + +IPAddress::IPAddress(const IPAddress& addr) +{ + if (addr.family() == IPv4) + newIPv4(addr.addr()); +#if defined(POCO_HAVE_IPv6) + else + newIPv6(addr.addr(), addr.scope()); +#endif +} + + +IPAddress::IPAddress(Family family) +{ + if (family == IPv4) + newIPv4(); +#if defined(POCO_HAVE_IPv6) + else if (family == IPv6) + newIPv6(); +#endif + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); +} + + +IPAddress::IPAddress(const std::string& addr) +{ + IPv4AddressImpl empty4 = IPv4AddressImpl(); + if (addr.empty() || trim(addr) == "0.0.0.0") + { + newIPv4(empty4.addr()); + return; + } + + IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); + if (addr4 != empty4) + { + newIPv4(addr4.addr()); + return; + } + +#if defined(POCO_HAVE_IPv6) + IPv6AddressImpl empty6 = IPv6AddressImpl(); + if (addr.empty() || trim(addr) == "::") + { + newIPv6(empty6.addr()); + return; + } + + IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); + if (addr6 != IPv6AddressImpl()) + { + newIPv6(addr6.addr(), addr6.scope()); + return; + } +#endif + + throw InvalidAddressException(addr); +} + + +IPAddress::IPAddress(const std::string& addr, Family family) +{ + if (family == IPv4) + { + IPv4AddressImpl addr4(IPv4AddressImpl::parse(addr)); + newIPv4(addr4.addr()); + return; + } +#if defined(POCO_HAVE_IPv6) + else if (family == IPv6) + { + IPv6AddressImpl addr6(IPv6AddressImpl::parse(addr)); + newIPv6(addr6.addr(), addr6.scope()); + return; + } +#endif + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); +} + + +IPAddress::IPAddress(const void* addr, poco_socklen_t length) + : _pImpl(0) +{ + if (length == sizeof(struct in_addr)) + newIPv4(addr); +#if defined(POCO_HAVE_IPv6) + else if (length == sizeof(struct in6_addr)) + newIPv6(addr); +#endif + else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()"); +} + + +IPAddress::IPAddress(const void* addr, poco_socklen_t length, Poco::UInt32 scope) +{ + if (length == sizeof(struct in_addr)) + newIPv4(addr); +#if defined(POCO_HAVE_IPv6) + else if (length == sizeof(struct in6_addr)) + newIPv6(addr, scope); +#endif + else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()"); +} + + +IPAddress::IPAddress(unsigned prefix, Family family) +{ + if (family == IPv4) + { + if (prefix <= 32) + newIPv4(prefix); else - throw Poco::InvalidArgumentException("Invalid or unsupported address family"); - } - return *this; -} - - -IPAddress::Family IPAddress::family() const -{ - return pImpl()->family(); -} - - -Poco::UInt32 IPAddress::scope() const -{ - return pImpl()->scope(); -} - - -std::string IPAddress::toString() const -{ - return pImpl()->toString(); -} - - -bool IPAddress::isWildcard() const -{ - return pImpl()->isWildcard(); -} - - -bool IPAddress::isBroadcast() const -{ - return pImpl()->isBroadcast(); -} - - -bool IPAddress::isLoopback() const -{ - return pImpl()->isLoopback(); -} - - -bool IPAddress::isMulticast() const -{ - return pImpl()->isMulticast(); -} - - -bool IPAddress::isUnicast() const -{ - return !isWildcard() && !isBroadcast() && !isMulticast(); -} - - -bool IPAddress::isLinkLocal() const -{ - return pImpl()->isLinkLocal(); -} - - -bool IPAddress::isSiteLocal() const -{ - return pImpl()->isSiteLocal(); -} - - -bool IPAddress::isIPv4Compatible() const -{ - return pImpl()->isIPv4Compatible(); -} - - -bool IPAddress::isIPv4Mapped() const -{ - return pImpl()->isIPv4Mapped(); -} - - -bool IPAddress::isWellKnownMC() const -{ - return pImpl()->isWellKnownMC(); -} - - -bool IPAddress::isNodeLocalMC() const -{ - return pImpl()->isNodeLocalMC(); -} - - -bool IPAddress::isLinkLocalMC() const -{ - return pImpl()->isLinkLocalMC(); -} - - -bool IPAddress::isSiteLocalMC() const -{ - return pImpl()->isSiteLocalMC(); -} - - -bool IPAddress::isOrgLocalMC() const -{ - return pImpl()->isOrgLocalMC(); -} - - -bool IPAddress::isGlobalMC() const -{ - return pImpl()->isGlobalMC(); -} - - -bool IPAddress::operator == (const IPAddress& a) const -{ - poco_socklen_t l1 = length(); - poco_socklen_t l2 = a.length(); - if (l1 == l2) - { -#if defined(POCO_HAVE_IPv6) - if ( scope() != a.scope() ) - return false; -#endif - return std::memcmp(addr(), a.addr(), l1) == 0; - } - else return false; -} - - -bool IPAddress::operator != (const IPAddress& a) const -{ - return !(*this == a); -} - - -bool IPAddress::operator < (const IPAddress& a) const -{ - poco_socklen_t l1 = length(); - poco_socklen_t l2 = a.length(); - if (l1 == l2) - { -#if defined(POCO_HAVE_IPv6) - if ( scope() != a.scope() ) - return scope() < a.scope(); -#endif - return std::memcmp(addr(), a.addr(), l1) < 0; - } - else return l1 < l2; -} - - -bool IPAddress::operator <= (const IPAddress& a) const -{ - return !(a < *this); -} - - -bool IPAddress::operator > (const IPAddress& a) const -{ - return a < *this; -} - - -bool IPAddress::operator >= (const IPAddress& a) const -{ - return !(*this < a); -} - - -IPAddress IPAddress::operator & (const IPAddress& other) const -{ - if (family() == other.family()) - { - if (family() == IPv4) - { - IPv4AddressImpl t(pImpl()->addr()); - IPv4AddressImpl o(other.pImpl()->addr()); - return IPAddress((t & o).addr(), sizeof(struct in_addr)); - } -#if defined(POCO_HAVE_IPv6) - else if (family() == IPv6) - { - const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); - const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); - const IPv6AddressImpl r = t & o; - return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); - } -#endif - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); - } - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); -} - - -IPAddress IPAddress::operator | (const IPAddress& other) const -{ - if (family() == other.family()) - { - if (family() == IPv4) - { - IPv4AddressImpl t(pImpl()->addr()); - IPv4AddressImpl o(other.pImpl()->addr()); - return IPAddress((t | o).addr(), sizeof(struct in_addr)); - } -#if defined(POCO_HAVE_IPv6) - else if (family() == IPv6) - { - const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); - const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); - const IPv6AddressImpl r = t | o; - return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); - } -#endif - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); - } - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); -} - - -IPAddress IPAddress::operator ^ (const IPAddress& other) const -{ - if (family() == other.family()) - { - if (family() == IPv4) - { - IPv4AddressImpl t(pImpl()->addr()); - IPv4AddressImpl o(other.pImpl()->addr()); - return IPAddress((t ^ o).addr(), sizeof(struct in_addr)); - } -#if defined(POCO_HAVE_IPv6) - else if (family() == IPv6) - { - const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); - const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); - const IPv6AddressImpl r = t ^ o; - return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); - } -#endif - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); - } - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); -} - - -IPAddress IPAddress::operator ~ () const -{ - if (family() == IPv4) - { - IPv4AddressImpl self(this->pImpl()->addr()); - return IPAddress((~self).addr(), sizeof(struct in_addr)); - } -#if defined(POCO_HAVE_IPv6) - else if (family() == IPv6) - { - const IPv6AddressImpl self(pImpl()->addr(), pImpl()->scope()); - const IPv6AddressImpl r = ~self; - return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); - } -#endif - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); -} - - -poco_socklen_t IPAddress::length() const -{ - return pImpl()->length(); -} - - -const void* IPAddress::addr() const -{ - return pImpl()->addr(); -} - - -int IPAddress::af() const -{ - return pImpl()->af(); -} - - -unsigned IPAddress::prefixLength() const -{ - return pImpl()->prefixLength(); -} - - -IPAddress IPAddress::parse(const std::string& addr) -{ - return IPAddress(addr); -} - - -bool IPAddress::tryParse(const std::string& addr, IPAddress& result) -{ - IPv4AddressImpl impl4(IPv4AddressImpl::parse(addr)); - if (impl4 != IPv4AddressImpl() || trim(addr) == "0.0.0.0") - { - result.newIPv4(impl4.addr()); - return true; - } -#if defined(POCO_HAVE_IPv6) - IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr)); - if (impl6 != IPv6AddressImpl()) - { - result.newIPv6(impl6.addr(), impl6.scope()); - return true; - } -#endif - return false; -} - - -void IPAddress::mask(const IPAddress& mask) -{ - IPAddress null; - pImpl()->mask(mask.pImpl(), null.pImpl()); -} - - -void IPAddress::mask(const IPAddress& mask, const IPAddress& set) -{ - pImpl()->mask(mask.pImpl(), set.pImpl()); -} - - -IPAddress IPAddress::wildcard(Family family) -{ - return IPAddress(family); -} - - -IPAddress IPAddress::broadcast() -{ - struct in_addr ia; - ia.s_addr = INADDR_NONE; - return IPAddress(&ia, sizeof(ia)); -} - - -} } // namespace Poco::Net - - -Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::IPAddress& value) -{ - writer << static_cast<Poco::UInt8>(value.length()); - writer.writeRaw(reinterpret_cast<const char*>(value.addr()), value.length()); - return writer; -} - - -Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::IPAddress& value) -{ - char buf[Poco::Net::IPAddress::MAX_ADDRESS_LENGTH]; - Poco::UInt8 length; - reader >> length; - reader.readRaw(buf, length); - value = Poco::Net::IPAddress(buf, length); - return reader; -} - - -std::ostream& operator << (std::ostream& ostr, const Poco::Net::IPAddress& addr) -{ - ostr << addr.toString(); - return ostr; -} + throw Poco::InvalidArgumentException("Invalid prefix length passed to IPAddress()"); + } +#if defined(POCO_HAVE_IPv6) + else if (family == IPv6) + { + if (prefix <= 128) + newIPv6(prefix); + else + throw Poco::InvalidArgumentException("Invalid prefix length passed to IPAddress()"); + } +#endif + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); +} + + +#if defined(_WIN32) +IPAddress::IPAddress(const SOCKET_ADDRESS& socket_address) + : _pImpl(0) +{ + ADDRESS_FAMILY family = socket_address.lpSockaddr->sa_family; + if (family == AF_INET) + newIPv4(&reinterpret_cast<const struct sockaddr_in*>(socket_address.lpSockaddr)->sin_addr); +#if defined(POCO_HAVE_IPv6) + else if (family == AF_INET6) + newIPv6(&reinterpret_cast<const struct sockaddr_in6*>(socket_address.lpSockaddr)->sin6_addr, + reinterpret_cast<const struct sockaddr_in6*>(socket_address.lpSockaddr)->sin6_scope_id); +#endif + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); +} +#endif + + +IPAddress::IPAddress(const struct sockaddr& sockaddr) +{ + unsigned short family = sockaddr.sa_family; + if (family == AF_INET) + newIPv4(&reinterpret_cast<const struct sockaddr_in*>(&sockaddr)->sin_addr); +#if defined(POCO_HAVE_IPv6) + else if (family == AF_INET6) + newIPv6(&reinterpret_cast<const struct sockaddr_in6*>(&sockaddr)->sin6_addr, + reinterpret_cast<const struct sockaddr_in6*>(&sockaddr)->sin6_scope_id); +#endif + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); +} + + +IPAddress::~IPAddress() +{ +} + + +IPAddress& IPAddress::operator = (const IPAddress& addr) +{ + if (&addr != this) + { + if (addr.family() == IPAddress::IPv4) + newIPv4(addr.addr()); +#if defined(POCO_HAVE_IPv6) + else if (addr.family() == IPAddress::IPv6) + newIPv6(addr.addr(), addr.scope()); +#endif + else + throw Poco::InvalidArgumentException("Invalid or unsupported address family"); + } + return *this; +} + + +IPAddress::Family IPAddress::family() const +{ + return pImpl()->family(); +} + + +Poco::UInt32 IPAddress::scope() const +{ + return pImpl()->scope(); +} + + +std::string IPAddress::toString() const +{ + return pImpl()->toString(); +} + + +bool IPAddress::isWildcard() const +{ + return pImpl()->isWildcard(); +} + + +bool IPAddress::isBroadcast() const +{ + return pImpl()->isBroadcast(); +} + + +bool IPAddress::isLoopback() const +{ + return pImpl()->isLoopback(); +} + + +bool IPAddress::isMulticast() const +{ + return pImpl()->isMulticast(); +} + + +bool IPAddress::isUnicast() const +{ + return !isWildcard() && !isBroadcast() && !isMulticast(); +} + + +bool IPAddress::isLinkLocal() const +{ + return pImpl()->isLinkLocal(); +} + + +bool IPAddress::isSiteLocal() const +{ + return pImpl()->isSiteLocal(); +} + + +bool IPAddress::isIPv4Compatible() const +{ + return pImpl()->isIPv4Compatible(); +} + + +bool IPAddress::isIPv4Mapped() const +{ + return pImpl()->isIPv4Mapped(); +} + + +bool IPAddress::isWellKnownMC() const +{ + return pImpl()->isWellKnownMC(); +} + + +bool IPAddress::isNodeLocalMC() const +{ + return pImpl()->isNodeLocalMC(); +} + + +bool IPAddress::isLinkLocalMC() const +{ + return pImpl()->isLinkLocalMC(); +} + + +bool IPAddress::isSiteLocalMC() const +{ + return pImpl()->isSiteLocalMC(); +} + + +bool IPAddress::isOrgLocalMC() const +{ + return pImpl()->isOrgLocalMC(); +} + + +bool IPAddress::isGlobalMC() const +{ + return pImpl()->isGlobalMC(); +} + + +bool IPAddress::operator == (const IPAddress& a) const +{ + poco_socklen_t l1 = length(); + poco_socklen_t l2 = a.length(); + if (l1 == l2) + { +#if defined(POCO_HAVE_IPv6) + if ( scope() != a.scope() ) + return false; +#endif + return std::memcmp(addr(), a.addr(), l1) == 0; + } + else return false; +} + + +bool IPAddress::operator != (const IPAddress& a) const +{ + return !(*this == a); +} + + +bool IPAddress::operator < (const IPAddress& a) const +{ + poco_socklen_t l1 = length(); + poco_socklen_t l2 = a.length(); + if (l1 == l2) + { +#if defined(POCO_HAVE_IPv6) + if ( scope() != a.scope() ) + return scope() < a.scope(); +#endif + return std::memcmp(addr(), a.addr(), l1) < 0; + } + else return l1 < l2; +} + + +bool IPAddress::operator <= (const IPAddress& a) const +{ + return !(a < *this); +} + + +bool IPAddress::operator > (const IPAddress& a) const +{ + return a < *this; +} + + +bool IPAddress::operator >= (const IPAddress& a) const +{ + return !(*this < a); +} + + +IPAddress IPAddress::operator & (const IPAddress& other) const +{ + if (family() == other.family()) + { + if (family() == IPv4) + { + IPv4AddressImpl t(pImpl()->addr()); + IPv4AddressImpl o(other.pImpl()->addr()); + return IPAddress((t & o).addr(), sizeof(struct in_addr)); + } +#if defined(POCO_HAVE_IPv6) + else if (family() == IPv6) + { + const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); + const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); + const IPv6AddressImpl r = t & o; + return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); + } +#endif + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); + } + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); +} + + +IPAddress IPAddress::operator | (const IPAddress& other) const +{ + if (family() == other.family()) + { + if (family() == IPv4) + { + IPv4AddressImpl t(pImpl()->addr()); + IPv4AddressImpl o(other.pImpl()->addr()); + return IPAddress((t | o).addr(), sizeof(struct in_addr)); + } +#if defined(POCO_HAVE_IPv6) + else if (family() == IPv6) + { + const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); + const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); + const IPv6AddressImpl r = t | o; + return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); + } +#endif + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); + } + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); +} + + +IPAddress IPAddress::operator ^ (const IPAddress& other) const +{ + if (family() == other.family()) + { + if (family() == IPv4) + { + IPv4AddressImpl t(pImpl()->addr()); + IPv4AddressImpl o(other.pImpl()->addr()); + return IPAddress((t ^ o).addr(), sizeof(struct in_addr)); + } +#if defined(POCO_HAVE_IPv6) + else if (family() == IPv6) + { + const IPv6AddressImpl t(pImpl()->addr(), pImpl()->scope()); + const IPv6AddressImpl o(other.pImpl()->addr(), other.pImpl()->scope()); + const IPv6AddressImpl r = t ^ o; + return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); + } +#endif + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); + } + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); +} + + +IPAddress IPAddress::operator ~ () const +{ + if (family() == IPv4) + { + IPv4AddressImpl self(this->pImpl()->addr()); + return IPAddress((~self).addr(), sizeof(struct in_addr)); + } +#if defined(POCO_HAVE_IPv6) + else if (family() == IPv6) + { + const IPv6AddressImpl self(pImpl()->addr(), pImpl()->scope()); + const IPv6AddressImpl r = ~self; + return IPAddress(r.addr(), sizeof(struct in6_addr), r.scope()); + } +#endif + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()"); +} + + +poco_socklen_t IPAddress::length() const +{ + return pImpl()->length(); +} + + +const void* IPAddress::addr() const +{ + return pImpl()->addr(); +} + + +int IPAddress::af() const +{ + return pImpl()->af(); +} + + +unsigned IPAddress::prefixLength() const +{ + return pImpl()->prefixLength(); +} + + +IPAddress IPAddress::parse(const std::string& addr) +{ + return IPAddress(addr); +} + + +bool IPAddress::tryParse(const std::string& addr, IPAddress& result) +{ + IPv4AddressImpl impl4(IPv4AddressImpl::parse(addr)); + if (impl4 != IPv4AddressImpl() || trim(addr) == "0.0.0.0") + { + result.newIPv4(impl4.addr()); + return true; + } +#if defined(POCO_HAVE_IPv6) + IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr)); + if (impl6 != IPv6AddressImpl()) + { + result.newIPv6(impl6.addr(), impl6.scope()); + return true; + } +#endif + return false; +} + + +void IPAddress::mask(const IPAddress& mask) +{ + IPAddress null; + pImpl()->mask(mask.pImpl(), null.pImpl()); +} + + +void IPAddress::mask(const IPAddress& mask, const IPAddress& set) +{ + pImpl()->mask(mask.pImpl(), set.pImpl()); +} + + +IPAddress IPAddress::wildcard(Family family) +{ + return IPAddress(family); +} + + +IPAddress IPAddress::broadcast() +{ + struct in_addr ia; + ia.s_addr = INADDR_NONE; + return IPAddress(&ia, sizeof(ia)); +} + + +} } // namespace Poco::Net + + +Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::IPAddress& value) +{ + writer << static_cast<Poco::UInt8>(value.length()); + writer.writeRaw(reinterpret_cast<const char*>(value.addr()), value.length()); + return writer; +} + + +Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::IPAddress& value) +{ + char buf[Poco::Net::IPAddress::MAX_ADDRESS_LENGTH]; + Poco::UInt8 length; + reader >> length; + reader.readRaw(buf, length); + value = Poco::Net::IPAddress(buf, length); + return reader; +} + + +std::ostream& operator << (std::ostream& ostr, const Poco::Net::IPAddress& addr) +{ + ostr << addr.toString(); + return ostr; +} diff --git a/contrib/libs/poco/Net/src/IPAddressImpl.cpp b/contrib/libs/poco/Net/src/IPAddressImpl.cpp index 316bba33f3..ab7b7ab702 100644 --- a/contrib/libs/poco/Net/src/IPAddressImpl.cpp +++ b/contrib/libs/poco/Net/src/IPAddressImpl.cpp @@ -1,815 +1,815 @@ -// -// IPAddress.cpp -// -// Library: Net -// Package: NetCore -// Module: IPAddress -// -// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/IPAddressImpl.h" -#include "Poco/Net/NetException.h" -#include "Poco/RefCountedObject.h" -#include "Poco/NumberFormatter.h" -#include "Poco/ByteOrder.h" -#include "Poco/String.h" -#include "Poco/Types.h" - - -using Poco::RefCountedObject; -using Poco::NumberFormatter; -using Poco::toLower; -using Poco::UInt8; -using Poco::UInt16; -using Poco::UInt32; - - -namespace { - - -template <typename T> -unsigned maskBits(T val, unsigned size) - /// Returns the length of the mask (number of bits set in val). - /// The val should be either all zeros or two contiguos areas of 1s and 0s. - /// The algorithm ignores invalid non-contiguous series of 1s and treats val - /// as if all bits between MSb and last non-zero bit are set to 1. -{ - unsigned count = 0; - if (val) - { - val = (val ^ (val - 1)) >> 1; - for (count = 0; val; ++count) val >>= 1; - } - else count = size; - return size - count; -} - - -} // namespace - - -namespace Poco { -namespace Net { -namespace Impl { - - -// -// IPAddressImpl -// - - -IPAddressImpl::IPAddressImpl() -{ -} - - -IPAddressImpl::~IPAddressImpl() -{ -} - - -// -// IPv4AddressImpl -// - - -IPv4AddressImpl::IPv4AddressImpl() -{ - std::memset(&_addr, 0, sizeof(_addr)); -} - - -IPv4AddressImpl::IPv4AddressImpl(const void* addr) -{ - std::memcpy(&_addr, addr, sizeof(_addr)); -} - - -IPv4AddressImpl::IPv4AddressImpl(unsigned prefix) -{ - UInt32 addr = (prefix == 32) ? 0xffffffff : ~(0xffffffff >> prefix); - _addr.s_addr = ByteOrder::toNetwork(addr); -} - - -IPv4AddressImpl::IPv4AddressImpl(const IPv4AddressImpl& addr) -{ - std::memcpy(&_addr, &addr._addr, sizeof(_addr)); -} - - -IPv4AddressImpl& IPv4AddressImpl::operator = (const IPv4AddressImpl& addr) -{ - if (this == &addr) - return *this; - - std::memcpy(&_addr, &addr._addr, sizeof(_addr)); - return *this; -} - - -std::string IPv4AddressImpl::toString() const -{ - const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr); - std::string result; - result.reserve(16); - NumberFormatter::append(result, bytes[0]); - result.append("."); - NumberFormatter::append(result, bytes[1]); - result.append("."); - NumberFormatter::append(result, bytes[2]); - result.append("."); - NumberFormatter::append(result, bytes[3]); - return result; -} - - -poco_socklen_t IPv4AddressImpl::length() const -{ - return sizeof(_addr); -} - - -const void* IPv4AddressImpl::addr() const -{ - return &_addr; -} - - -IPAddressImpl::Family IPv4AddressImpl::family() const -{ - return AddressFamily::IPv4; -} - - -int IPv4AddressImpl::af() const -{ - return AF_INET; -} - - -unsigned IPv4AddressImpl::prefixLength() const -{ - return maskBits(ntohl(_addr.s_addr), 32); -} - - -Poco::UInt32 IPv4AddressImpl::scope() const -{ - return 0; -} - - -bool IPv4AddressImpl::isWildcard() const -{ - return _addr.s_addr == INADDR_ANY; -} - - -bool IPv4AddressImpl::isBroadcast() const -{ - return _addr.s_addr == INADDR_NONE; -} - - -bool IPv4AddressImpl::isLoopback() const -{ - return (ntohl(_addr.s_addr) & 0xFF000000) == 0x7F000000; // 127.0.0.1 to 127.255.255.255 -} - - -bool IPv4AddressImpl::isMulticast() const -{ - return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/24 to 239.0.0.0/24 -} - - -bool IPv4AddressImpl::isLinkLocal() const -{ - return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16 -} - - -bool IPv4AddressImpl::isSiteLocal() const -{ - UInt32 addr = ntohl(_addr.s_addr); - return (addr & 0xFF000000) == 0x0A000000 || // 10.0.0.0/24 - (addr & 0xFFFF0000) == 0xC0A80000 || // 192.68.0.0/16 - (addr >= 0xAC100000 && addr <= 0xAC1FFFFF); // 172.16.0.0 to 172.31.255.255 -} - - -bool IPv4AddressImpl::isIPv4Compatible() const -{ - return true; -} - - -bool IPv4AddressImpl::isIPv4Mapped() const -{ - return true; -} - - -bool IPv4AddressImpl::isWellKnownMC() const -{ - return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8 -} - - -bool IPv4AddressImpl::isNodeLocalMC() const -{ - return false; -} - - -bool IPv4AddressImpl::isLinkLocalMC() const -{ - return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24 -} - - -bool IPv4AddressImpl::isSiteLocalMC() const -{ - return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16 -} - - -bool IPv4AddressImpl::isOrgLocalMC() const -{ - return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16 -} - - -bool IPv4AddressImpl::isGlobalMC() const -{ - UInt32 addr = ntohl(_addr.s_addr); - return addr >= 0xE0000100 && addr <= 0xEE000000; // 224.0.1.0 to 238.255.255.255 -} - - -IPv4AddressImpl IPv4AddressImpl::parse(const std::string& addr) -{ - if (addr.empty()) return IPv4AddressImpl(); +// +// IPAddress.cpp +// +// Library: Net +// Package: NetCore +// Module: IPAddress +// +// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/IPAddressImpl.h" +#include "Poco/Net/NetException.h" +#include "Poco/RefCountedObject.h" +#include "Poco/NumberFormatter.h" +#include "Poco/ByteOrder.h" +#include "Poco/String.h" +#include "Poco/Types.h" + + +using Poco::RefCountedObject; +using Poco::NumberFormatter; +using Poco::toLower; +using Poco::UInt8; +using Poco::UInt16; +using Poco::UInt32; + + +namespace { + + +template <typename T> +unsigned maskBits(T val, unsigned size) + /// Returns the length of the mask (number of bits set in val). + /// The val should be either all zeros or two contiguos areas of 1s and 0s. + /// The algorithm ignores invalid non-contiguous series of 1s and treats val + /// as if all bits between MSb and last non-zero bit are set to 1. +{ + unsigned count = 0; + if (val) + { + val = (val ^ (val - 1)) >> 1; + for (count = 0; val; ++count) val >>= 1; + } + else count = size; + return size - count; +} + + +} // namespace + + +namespace Poco { +namespace Net { +namespace Impl { + + +// +// IPAddressImpl +// + + +IPAddressImpl::IPAddressImpl() +{ +} + + +IPAddressImpl::~IPAddressImpl() +{ +} + + +// +// IPv4AddressImpl +// + + +IPv4AddressImpl::IPv4AddressImpl() +{ + std::memset(&_addr, 0, sizeof(_addr)); +} + + +IPv4AddressImpl::IPv4AddressImpl(const void* addr) +{ + std::memcpy(&_addr, addr, sizeof(_addr)); +} + + +IPv4AddressImpl::IPv4AddressImpl(unsigned prefix) +{ + UInt32 addr = (prefix == 32) ? 0xffffffff : ~(0xffffffff >> prefix); + _addr.s_addr = ByteOrder::toNetwork(addr); +} + + +IPv4AddressImpl::IPv4AddressImpl(const IPv4AddressImpl& addr) +{ + std::memcpy(&_addr, &addr._addr, sizeof(_addr)); +} + + +IPv4AddressImpl& IPv4AddressImpl::operator = (const IPv4AddressImpl& addr) +{ + if (this == &addr) + return *this; + + std::memcpy(&_addr, &addr._addr, sizeof(_addr)); + return *this; +} + + +std::string IPv4AddressImpl::toString() const +{ + const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr); + std::string result; + result.reserve(16); + NumberFormatter::append(result, bytes[0]); + result.append("."); + NumberFormatter::append(result, bytes[1]); + result.append("."); + NumberFormatter::append(result, bytes[2]); + result.append("."); + NumberFormatter::append(result, bytes[3]); + return result; +} + + +poco_socklen_t IPv4AddressImpl::length() const +{ + return sizeof(_addr); +} + + +const void* IPv4AddressImpl::addr() const +{ + return &_addr; +} + + +IPAddressImpl::Family IPv4AddressImpl::family() const +{ + return AddressFamily::IPv4; +} + + +int IPv4AddressImpl::af() const +{ + return AF_INET; +} + + +unsigned IPv4AddressImpl::prefixLength() const +{ + return maskBits(ntohl(_addr.s_addr), 32); +} + + +Poco::UInt32 IPv4AddressImpl::scope() const +{ + return 0; +} + + +bool IPv4AddressImpl::isWildcard() const +{ + return _addr.s_addr == INADDR_ANY; +} + + +bool IPv4AddressImpl::isBroadcast() const +{ + return _addr.s_addr == INADDR_NONE; +} + + +bool IPv4AddressImpl::isLoopback() const +{ + return (ntohl(_addr.s_addr) & 0xFF000000) == 0x7F000000; // 127.0.0.1 to 127.255.255.255 +} + + +bool IPv4AddressImpl::isMulticast() const +{ + return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/24 to 239.0.0.0/24 +} + + +bool IPv4AddressImpl::isLinkLocal() const +{ + return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16 +} + + +bool IPv4AddressImpl::isSiteLocal() const +{ + UInt32 addr = ntohl(_addr.s_addr); + return (addr & 0xFF000000) == 0x0A000000 || // 10.0.0.0/24 + (addr & 0xFFFF0000) == 0xC0A80000 || // 192.68.0.0/16 + (addr >= 0xAC100000 && addr <= 0xAC1FFFFF); // 172.16.0.0 to 172.31.255.255 +} + + +bool IPv4AddressImpl::isIPv4Compatible() const +{ + return true; +} + + +bool IPv4AddressImpl::isIPv4Mapped() const +{ + return true; +} + + +bool IPv4AddressImpl::isWellKnownMC() const +{ + return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8 +} + + +bool IPv4AddressImpl::isNodeLocalMC() const +{ + return false; +} + + +bool IPv4AddressImpl::isLinkLocalMC() const +{ + return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24 +} + + +bool IPv4AddressImpl::isSiteLocalMC() const +{ + return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16 +} + + +bool IPv4AddressImpl::isOrgLocalMC() const +{ + return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16 +} + + +bool IPv4AddressImpl::isGlobalMC() const +{ + UInt32 addr = ntohl(_addr.s_addr); + return addr >= 0xE0000100 && addr <= 0xEE000000; // 224.0.1.0 to 238.255.255.255 +} + + +IPv4AddressImpl IPv4AddressImpl::parse(const std::string& addr) +{ + if (addr.empty()) return IPv4AddressImpl(); +#if defined(_WIN32) + struct in_addr ia; + ia.s_addr = inet_addr(addr.c_str()); + if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255") + return IPv4AddressImpl(); + else + return IPv4AddressImpl(&ia); +#else +#if __GNUC__ < 3 || defined(POCO_VXWORKS) + struct in_addr ia; + ia.s_addr = inet_addr(const_cast<char*>(addr.c_str())); + if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255") + return IPv4AddressImpl(); + else + return IPv4AddressImpl(&ia); +#else + struct in_addr ia; + if (inet_aton(addr.c_str(), &ia)) + return IPv4AddressImpl(&ia); + else + return IPv4AddressImpl(); +#endif +#endif +} + + +void IPv4AddressImpl::mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) +{ + poco_assert (pMask->af() == AF_INET && pSet->af() == AF_INET); + + _addr.s_addr &= static_cast<const IPv4AddressImpl*>(pMask)->_addr.s_addr; + _addr.s_addr |= static_cast<const IPv4AddressImpl*>(pSet)->_addr.s_addr & ~static_cast<const IPv4AddressImpl*>(pMask)->_addr.s_addr; +} + + +IPAddressImpl* IPv4AddressImpl::clone() const +{ + return new IPv4AddressImpl(&_addr); +} + + +IPv4AddressImpl IPv4AddressImpl::operator & (const IPv4AddressImpl& addr) const +{ + IPv4AddressImpl result(&_addr); + result._addr.s_addr &= addr._addr.s_addr; + return result; +} + + +IPv4AddressImpl IPv4AddressImpl::operator | (const IPv4AddressImpl& addr) const +{ + IPv4AddressImpl result(&_addr); + result._addr.s_addr |= addr._addr.s_addr; + return result; +} + + +IPv4AddressImpl IPv4AddressImpl::operator ^ (const IPv4AddressImpl& addr) const +{ + IPv4AddressImpl result(&_addr); + result._addr.s_addr ^= addr._addr.s_addr; + return result; +} + + +IPv4AddressImpl IPv4AddressImpl::operator ~ () const +{ +IPv4AddressImpl result(&_addr); + result._addr.s_addr ^= 0xffffffff; + return result; +} + + +bool IPv4AddressImpl::operator == (const IPv4AddressImpl& addr) const +{ + return 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr)); +} + + +bool IPv4AddressImpl::operator != (const IPv4AddressImpl& addr) const +{ + return !(*this == addr); +} + + +#if defined(POCO_HAVE_IPv6) + + +// +// IPv6AddressImpl +// + + +IPv6AddressImpl::IPv6AddressImpl(): _scope(0) +{ + std::memset(&_addr, 0, sizeof(_addr)); +} + + +IPv6AddressImpl::IPv6AddressImpl(const void* addr): _scope(0) +{ + std::memcpy(&_addr, addr, sizeof(_addr)); +} + + +IPv6AddressImpl::IPv6AddressImpl(const void* addr, Poco::UInt32 scope): _scope(scope) +{ + std::memcpy(&_addr, addr, sizeof(_addr)); +} + + +IPv6AddressImpl::IPv6AddressImpl(const IPv6AddressImpl& addr): _scope(addr._scope) +{ + std::memcpy((void*) &_addr, (void*) &addr._addr, sizeof(_addr)); +} + + +IPv6AddressImpl& IPv6AddressImpl::operator = (const IPv6AddressImpl& addr) +{ + if (this == &addr) + return *this; + + _scope = addr._scope; + std::memcpy(&_addr, &addr._addr, sizeof(_addr)); + return *this; +} + + +IPv6AddressImpl::IPv6AddressImpl(unsigned prefix): + _scope(0) +{ + unsigned i = 0; +#ifdef POCO_OS_FAMILY_WINDOWS + for (; prefix >= 16; ++i, prefix -= 16) + { + _addr.s6_addr16[i] = 0xffff; + } + if (prefix > 0) + { + _addr.s6_addr16[i++] = ByteOrder::toNetwork(static_cast<Poco::UInt16>(~(0xffff >> prefix))); + } + while (i < 8) + { + _addr.s6_addr16[i++] = 0; + } +#else + for (; prefix >= 32; ++i, prefix -= 32) + { + _addr.s6_addr32[i] = 0xffffffff; + } + if (prefix > 0) + { + _addr.s6_addr32[i++] = ByteOrder::toNetwork(~(0xffffffffU >> prefix)); + } + while (i < 4) + { + _addr.s6_addr32[i++] = 0; + } +#endif +} + + +std::string IPv6AddressImpl::toString() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + if ((isIPv4Compatible() && !isLoopback()) || isIPv4Mapped()) + { + std::string result; + result.reserve(24); + if (words[5] == 0) + result.append("::"); + else + result.append("::ffff:"); + const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr); + if (bytes[12] != 0) // only 0.0.0.0 can start with zero + { + NumberFormatter::append(result, bytes[12]); + result.append("."); + NumberFormatter::append(result, bytes[13]); + result.append("."); + NumberFormatter::append(result, bytes[14]); + result.append("."); + NumberFormatter::append(result, bytes[15]); + } + return result; + } + else + { + std::string result; + result.reserve(64); + bool zeroSequence = false; + int i = 0; + while (i < 8) + { + if (!zeroSequence && words[i] == 0) + { + int zi = i; + while (zi < 8 && words[zi] == 0) ++zi; + if (zi > i + 1) + { + i = zi; + result.append(":"); + zeroSequence = true; + } + } + if (i > 0) result.append(":"); + if (i < 8) NumberFormatter::appendHex(result, ByteOrder::fromNetwork(words[i++])); + } + if (_scope > 0) + { + result.append("%"); #if defined(_WIN32) - struct in_addr ia; - ia.s_addr = inet_addr(addr.c_str()); - if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255") - return IPv4AddressImpl(); - else - return IPv4AddressImpl(&ia); -#else -#if __GNUC__ < 3 || defined(POCO_VXWORKS) - struct in_addr ia; - ia.s_addr = inet_addr(const_cast<char*>(addr.c_str())); - if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255") - return IPv4AddressImpl(); - else - return IPv4AddressImpl(&ia); -#else - struct in_addr ia; - if (inet_aton(addr.c_str(), &ia)) - return IPv4AddressImpl(&ia); - else - return IPv4AddressImpl(); -#endif -#endif -} - - -void IPv4AddressImpl::mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) -{ - poco_assert (pMask->af() == AF_INET && pSet->af() == AF_INET); - - _addr.s_addr &= static_cast<const IPv4AddressImpl*>(pMask)->_addr.s_addr; - _addr.s_addr |= static_cast<const IPv4AddressImpl*>(pSet)->_addr.s_addr & ~static_cast<const IPv4AddressImpl*>(pMask)->_addr.s_addr; -} - - -IPAddressImpl* IPv4AddressImpl::clone() const -{ - return new IPv4AddressImpl(&_addr); -} - - -IPv4AddressImpl IPv4AddressImpl::operator & (const IPv4AddressImpl& addr) const -{ - IPv4AddressImpl result(&_addr); - result._addr.s_addr &= addr._addr.s_addr; - return result; -} - - -IPv4AddressImpl IPv4AddressImpl::operator | (const IPv4AddressImpl& addr) const -{ - IPv4AddressImpl result(&_addr); - result._addr.s_addr |= addr._addr.s_addr; - return result; -} - - -IPv4AddressImpl IPv4AddressImpl::operator ^ (const IPv4AddressImpl& addr) const -{ - IPv4AddressImpl result(&_addr); - result._addr.s_addr ^= addr._addr.s_addr; - return result; -} - - -IPv4AddressImpl IPv4AddressImpl::operator ~ () const -{ -IPv4AddressImpl result(&_addr); - result._addr.s_addr ^= 0xffffffff; - return result; -} - - -bool IPv4AddressImpl::operator == (const IPv4AddressImpl& addr) const -{ - return 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr)); -} - - -bool IPv4AddressImpl::operator != (const IPv4AddressImpl& addr) const -{ - return !(*this == addr); -} - - -#if defined(POCO_HAVE_IPv6) - - -// -// IPv6AddressImpl -// - - -IPv6AddressImpl::IPv6AddressImpl(): _scope(0) -{ - std::memset(&_addr, 0, sizeof(_addr)); -} - - -IPv6AddressImpl::IPv6AddressImpl(const void* addr): _scope(0) -{ - std::memcpy(&_addr, addr, sizeof(_addr)); -} - - -IPv6AddressImpl::IPv6AddressImpl(const void* addr, Poco::UInt32 scope): _scope(scope) -{ - std::memcpy(&_addr, addr, sizeof(_addr)); -} - - -IPv6AddressImpl::IPv6AddressImpl(const IPv6AddressImpl& addr): _scope(addr._scope) -{ - std::memcpy((void*) &_addr, (void*) &addr._addr, sizeof(_addr)); -} - - -IPv6AddressImpl& IPv6AddressImpl::operator = (const IPv6AddressImpl& addr) -{ - if (this == &addr) - return *this; - - _scope = addr._scope; - std::memcpy(&_addr, &addr._addr, sizeof(_addr)); - return *this; -} - - -IPv6AddressImpl::IPv6AddressImpl(unsigned prefix): - _scope(0) -{ - unsigned i = 0; -#ifdef POCO_OS_FAMILY_WINDOWS - for (; prefix >= 16; ++i, prefix -= 16) - { - _addr.s6_addr16[i] = 0xffff; - } - if (prefix > 0) - { - _addr.s6_addr16[i++] = ByteOrder::toNetwork(static_cast<Poco::UInt16>(~(0xffff >> prefix))); - } - while (i < 8) - { - _addr.s6_addr16[i++] = 0; - } -#else - for (; prefix >= 32; ++i, prefix -= 32) - { - _addr.s6_addr32[i] = 0xffffffff; - } - if (prefix > 0) - { - _addr.s6_addr32[i++] = ByteOrder::toNetwork(~(0xffffffffU >> prefix)); - } - while (i < 4) - { - _addr.s6_addr32[i++] = 0; - } -#endif -} - - -std::string IPv6AddressImpl::toString() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - if ((isIPv4Compatible() && !isLoopback()) || isIPv4Mapped()) - { - std::string result; - result.reserve(24); - if (words[5] == 0) - result.append("::"); - else - result.append("::ffff:"); - const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr); - if (bytes[12] != 0) // only 0.0.0.0 can start with zero - { - NumberFormatter::append(result, bytes[12]); - result.append("."); - NumberFormatter::append(result, bytes[13]); - result.append("."); - NumberFormatter::append(result, bytes[14]); - result.append("."); - NumberFormatter::append(result, bytes[15]); - } - return result; - } - else - { - std::string result; - result.reserve(64); - bool zeroSequence = false; - int i = 0; - while (i < 8) - { - if (!zeroSequence && words[i] == 0) - { - int zi = i; - while (zi < 8 && words[zi] == 0) ++zi; - if (zi > i + 1) - { - i = zi; - result.append(":"); - zeroSequence = true; - } - } - if (i > 0) result.append(":"); - if (i < 8) NumberFormatter::appendHex(result, ByteOrder::fromNetwork(words[i++])); - } - if (_scope > 0) - { - result.append("%"); -#if defined(_WIN32) - NumberFormatter::append(result, _scope); -#else - char buffer[IFNAMSIZ]; - if (if_indextoname(_scope, buffer)) - { - result.append(buffer); - } - else - { - NumberFormatter::append(result, _scope); - } -#endif - } - return toLower(result); - } -} - - -poco_socklen_t IPv6AddressImpl::length() const -{ - return sizeof(_addr); -} - - -const void* IPv6AddressImpl::addr() const -{ - return &_addr; -} - - -IPAddressImpl::Family IPv6AddressImpl::family() const -{ - return AddressFamily::IPv6; -} - - -int IPv6AddressImpl::af() const -{ - return AF_INET6; -} - - -unsigned IPv6AddressImpl::prefixLength() const -{ - unsigned bits = 0; - unsigned bitPos = 128; -#if defined(POCO_OS_FAMILY_UNIX) - for (int i = 3; i >= 0; --i) - { - unsigned addr = ntohl(_addr.s6_addr32[i]); - if ((bits = maskBits(addr, 32))) return (bitPos - (32 - bits)); - bitPos -= 32; - } - return 0; -#elif defined(POCO_OS_FAMILY_WINDOWS) - for (int i = 7; i >= 0; --i) - { - unsigned short addr = ByteOrder::fromNetwork(_addr.s6_addr16[i]); - bits = maskBits(addr, 16); - if (bits) - return (bitPos - (16 - bits)); - bitPos -= 16; - } - return 0; -#else -#warning prefixLength() not implemented - throw NotImplementedException("prefixLength() not implemented"); -#endif -} - - -Poco::UInt32 IPv6AddressImpl::scope() const -{ - return _scope; -} - - -bool IPv6AddressImpl::isWildcard() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && - words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0; -} - - -bool IPv6AddressImpl::isBroadcast() const -{ - return false; -} - - -bool IPv6AddressImpl::isLoopback() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && - words[4] == 0 && words[5] == 0 && words[6] == 0 && ByteOrder::fromNetwork(words[7]) == 0x0001; -} - - -bool IPv6AddressImpl::isMulticast() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return (ByteOrder::fromNetwork(words[0]) & 0xFFE0) == 0xFF00; -} - - -bool IPv6AddressImpl::isLinkLocal() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return (ByteOrder::fromNetwork(words[0]) & 0xFFE0) == 0xFE80; -} - - -bool IPv6AddressImpl::isSiteLocal() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return ((ByteOrder::fromNetwork(words[0]) & 0xFFE0) == 0xFEC0) || ((ByteOrder::fromNetwork(words[0]) & 0xFF00) == 0xFC00); -} - - -bool IPv6AddressImpl::isIPv4Compatible() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0; -} - - -bool IPv6AddressImpl::isIPv4Mapped() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && ByteOrder::fromNetwork(words[5]) == 0xFFFF; -} - - -bool IPv6AddressImpl::isWellKnownMC() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return (ByteOrder::fromNetwork(words[0]) & 0xFFF0) == 0xFF00; -} - - -bool IPv6AddressImpl::isNodeLocalMC() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF01; -} - - -bool IPv6AddressImpl::isLinkLocalMC() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF02; -} - - -bool IPv6AddressImpl::isSiteLocalMC() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF05; -} - - -bool IPv6AddressImpl::isOrgLocalMC() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF08; -} - - -bool IPv6AddressImpl::isGlobalMC() const -{ - const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); - return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF0F; -} - - -IPv6AddressImpl IPv6AddressImpl::parse(const std::string& addr) -{ - if (addr.empty()) return IPv6AddressImpl(); -#if defined(_WIN32) - struct addrinfo* pAI; - struct addrinfo hints; - std::memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_NUMERICHOST; - int rc = getaddrinfo(addr.c_str(), NULL, &hints, &pAI); - if (rc == 0) - { - IPv6AddressImpl result = IPv6AddressImpl(&reinterpret_cast<struct sockaddr_in6*>(pAI->ai_addr)->sin6_addr, static_cast<int>(reinterpret_cast<struct sockaddr_in6*>(pAI->ai_addr)->sin6_scope_id)); - freeaddrinfo(pAI); - return result; - } - else return IPv6AddressImpl(); -#else - struct in6_addr ia; - std::string::size_type pos = addr.find('%'); - if (std::string::npos != pos) - { - std::string::size_type start = ('[' == addr[0]) ? 1 : 0; - std::string unscopedAddr(addr, start, pos - start); - std::string scope(addr, pos + 1, addr.size() - start - pos); - Poco::UInt32 scopeId(0); - if (!(scopeId = if_nametoindex(scope.c_str()))) - return IPv6AddressImpl(); - if (inet_pton(AF_INET6, unscopedAddr.c_str(), &ia) == 1) - return IPv6AddressImpl(&ia, scopeId); - else - return IPv6AddressImpl(); - } - else - { - if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1) - return IPv6AddressImpl(&ia); - else - return IPv6AddressImpl(); - } -#endif -} - - -void IPv6AddressImpl::mask(const IPAddressImpl* /*pMask*/, const IPAddressImpl* /*pSet*/) -{ - throw Poco::NotImplementedException("mask() is only supported for IPv4 addresses"); -} - - -IPAddressImpl* IPv6AddressImpl::clone() const -{ - return new IPv6AddressImpl(*this); -} - - -IPv6AddressImpl IPv6AddressImpl::operator & (const IPv6AddressImpl& addr) const -{ - if (_scope != addr._scope) - throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match with the source one."); - - IPv6AddressImpl result(*this); -#ifdef POCO_OS_FAMILY_WINDOWS - result._addr.s6_addr16[0] &= addr._addr.s6_addr16[0]; - result._addr.s6_addr16[1] &= addr._addr.s6_addr16[1]; - result._addr.s6_addr16[2] &= addr._addr.s6_addr16[2]; - result._addr.s6_addr16[3] &= addr._addr.s6_addr16[3]; - result._addr.s6_addr16[4] &= addr._addr.s6_addr16[4]; - result._addr.s6_addr16[5] &= addr._addr.s6_addr16[5]; - result._addr.s6_addr16[6] &= addr._addr.s6_addr16[6]; - result._addr.s6_addr16[7] &= addr._addr.s6_addr16[7]; -#else - result._addr.s6_addr32[0] &= addr._addr.s6_addr32[0]; - result._addr.s6_addr32[1] &= addr._addr.s6_addr32[1]; - result._addr.s6_addr32[2] &= addr._addr.s6_addr32[2]; - result._addr.s6_addr32[3] &= addr._addr.s6_addr32[3]; -#endif - return result; -} - - -IPv6AddressImpl IPv6AddressImpl::operator | (const IPv6AddressImpl& addr) const -{ + NumberFormatter::append(result, _scope); +#else + char buffer[IFNAMSIZ]; + if (if_indextoname(_scope, buffer)) + { + result.append(buffer); + } + else + { + NumberFormatter::append(result, _scope); + } +#endif + } + return toLower(result); + } +} + + +poco_socklen_t IPv6AddressImpl::length() const +{ + return sizeof(_addr); +} + + +const void* IPv6AddressImpl::addr() const +{ + return &_addr; +} + + +IPAddressImpl::Family IPv6AddressImpl::family() const +{ + return AddressFamily::IPv6; +} + + +int IPv6AddressImpl::af() const +{ + return AF_INET6; +} + + +unsigned IPv6AddressImpl::prefixLength() const +{ + unsigned bits = 0; + unsigned bitPos = 128; +#if defined(POCO_OS_FAMILY_UNIX) + for (int i = 3; i >= 0; --i) + { + unsigned addr = ntohl(_addr.s6_addr32[i]); + if ((bits = maskBits(addr, 32))) return (bitPos - (32 - bits)); + bitPos -= 32; + } + return 0; +#elif defined(POCO_OS_FAMILY_WINDOWS) + for (int i = 7; i >= 0; --i) + { + unsigned short addr = ByteOrder::fromNetwork(_addr.s6_addr16[i]); + bits = maskBits(addr, 16); + if (bits) + return (bitPos - (16 - bits)); + bitPos -= 16; + } + return 0; +#else +#warning prefixLength() not implemented + throw NotImplementedException("prefixLength() not implemented"); +#endif +} + + +Poco::UInt32 IPv6AddressImpl::scope() const +{ + return _scope; +} + + +bool IPv6AddressImpl::isWildcard() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && + words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0; +} + + +bool IPv6AddressImpl::isBroadcast() const +{ + return false; +} + + +bool IPv6AddressImpl::isLoopback() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && + words[4] == 0 && words[5] == 0 && words[6] == 0 && ByteOrder::fromNetwork(words[7]) == 0x0001; +} + + +bool IPv6AddressImpl::isMulticast() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return (ByteOrder::fromNetwork(words[0]) & 0xFFE0) == 0xFF00; +} + + +bool IPv6AddressImpl::isLinkLocal() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return (ByteOrder::fromNetwork(words[0]) & 0xFFE0) == 0xFE80; +} + + +bool IPv6AddressImpl::isSiteLocal() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return ((ByteOrder::fromNetwork(words[0]) & 0xFFE0) == 0xFEC0) || ((ByteOrder::fromNetwork(words[0]) & 0xFF00) == 0xFC00); +} + + +bool IPv6AddressImpl::isIPv4Compatible() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0; +} + + +bool IPv6AddressImpl::isIPv4Mapped() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && ByteOrder::fromNetwork(words[5]) == 0xFFFF; +} + + +bool IPv6AddressImpl::isWellKnownMC() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return (ByteOrder::fromNetwork(words[0]) & 0xFFF0) == 0xFF00; +} + + +bool IPv6AddressImpl::isNodeLocalMC() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF01; +} + + +bool IPv6AddressImpl::isLinkLocalMC() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF02; +} + + +bool IPv6AddressImpl::isSiteLocalMC() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF05; +} + + +bool IPv6AddressImpl::isOrgLocalMC() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF08; +} + + +bool IPv6AddressImpl::isGlobalMC() const +{ + const UInt16* words = reinterpret_cast<const UInt16*>(&_addr); + return (ByteOrder::fromNetwork(words[0]) & 0xFFEF) == 0xFF0F; +} + + +IPv6AddressImpl IPv6AddressImpl::parse(const std::string& addr) +{ + if (addr.empty()) return IPv6AddressImpl(); +#if defined(_WIN32) + struct addrinfo* pAI; + struct addrinfo hints; + std::memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST; + int rc = getaddrinfo(addr.c_str(), NULL, &hints, &pAI); + if (rc == 0) + { + IPv6AddressImpl result = IPv6AddressImpl(&reinterpret_cast<struct sockaddr_in6*>(pAI->ai_addr)->sin6_addr, static_cast<int>(reinterpret_cast<struct sockaddr_in6*>(pAI->ai_addr)->sin6_scope_id)); + freeaddrinfo(pAI); + return result; + } + else return IPv6AddressImpl(); +#else + struct in6_addr ia; + std::string::size_type pos = addr.find('%'); + if (std::string::npos != pos) + { + std::string::size_type start = ('[' == addr[0]) ? 1 : 0; + std::string unscopedAddr(addr, start, pos - start); + std::string scope(addr, pos + 1, addr.size() - start - pos); + Poco::UInt32 scopeId(0); + if (!(scopeId = if_nametoindex(scope.c_str()))) + return IPv6AddressImpl(); + if (inet_pton(AF_INET6, unscopedAddr.c_str(), &ia) == 1) + return IPv6AddressImpl(&ia, scopeId); + else + return IPv6AddressImpl(); + } + else + { + if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1) + return IPv6AddressImpl(&ia); + else + return IPv6AddressImpl(); + } +#endif +} + + +void IPv6AddressImpl::mask(const IPAddressImpl* /*pMask*/, const IPAddressImpl* /*pSet*/) +{ + throw Poco::NotImplementedException("mask() is only supported for IPv4 addresses"); +} + + +IPAddressImpl* IPv6AddressImpl::clone() const +{ + return new IPv6AddressImpl(*this); +} + + +IPv6AddressImpl IPv6AddressImpl::operator & (const IPv6AddressImpl& addr) const +{ + if (_scope != addr._scope) + throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match with the source one."); + + IPv6AddressImpl result(*this); +#ifdef POCO_OS_FAMILY_WINDOWS + result._addr.s6_addr16[0] &= addr._addr.s6_addr16[0]; + result._addr.s6_addr16[1] &= addr._addr.s6_addr16[1]; + result._addr.s6_addr16[2] &= addr._addr.s6_addr16[2]; + result._addr.s6_addr16[3] &= addr._addr.s6_addr16[3]; + result._addr.s6_addr16[4] &= addr._addr.s6_addr16[4]; + result._addr.s6_addr16[5] &= addr._addr.s6_addr16[5]; + result._addr.s6_addr16[6] &= addr._addr.s6_addr16[6]; + result._addr.s6_addr16[7] &= addr._addr.s6_addr16[7]; +#else + result._addr.s6_addr32[0] &= addr._addr.s6_addr32[0]; + result._addr.s6_addr32[1] &= addr._addr.s6_addr32[1]; + result._addr.s6_addr32[2] &= addr._addr.s6_addr32[2]; + result._addr.s6_addr32[3] &= addr._addr.s6_addr32[3]; +#endif + return result; +} + + +IPv6AddressImpl IPv6AddressImpl::operator | (const IPv6AddressImpl& addr) const +{ + if (_scope != addr._scope) + throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match with the source one."); + + IPv6AddressImpl result(*this); +#ifdef POCO_OS_FAMILY_WINDOWS + result._addr.s6_addr16[0] |= addr._addr.s6_addr16[0]; + result._addr.s6_addr16[1] |= addr._addr.s6_addr16[1]; + result._addr.s6_addr16[2] |= addr._addr.s6_addr16[2]; + result._addr.s6_addr16[3] |= addr._addr.s6_addr16[3]; + result._addr.s6_addr16[4] |= addr._addr.s6_addr16[4]; + result._addr.s6_addr16[5] |= addr._addr.s6_addr16[5]; + result._addr.s6_addr16[6] |= addr._addr.s6_addr16[6]; + result._addr.s6_addr16[7] |= addr._addr.s6_addr16[7]; +#else + result._addr.s6_addr32[0] |= addr._addr.s6_addr32[0]; + result._addr.s6_addr32[1] |= addr._addr.s6_addr32[1]; + result._addr.s6_addr32[2] |= addr._addr.s6_addr32[2]; + result._addr.s6_addr32[3] |= addr._addr.s6_addr32[3]; +#endif + return result; +} + + +IPv6AddressImpl IPv6AddressImpl::operator ^ (const IPv6AddressImpl& addr) const +{ if (_scope != addr._scope) - throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match with the source one."); - - IPv6AddressImpl result(*this); -#ifdef POCO_OS_FAMILY_WINDOWS - result._addr.s6_addr16[0] |= addr._addr.s6_addr16[0]; - result._addr.s6_addr16[1] |= addr._addr.s6_addr16[1]; - result._addr.s6_addr16[2] |= addr._addr.s6_addr16[2]; - result._addr.s6_addr16[3] |= addr._addr.s6_addr16[3]; - result._addr.s6_addr16[4] |= addr._addr.s6_addr16[4]; - result._addr.s6_addr16[5] |= addr._addr.s6_addr16[5]; - result._addr.s6_addr16[6] |= addr._addr.s6_addr16[6]; - result._addr.s6_addr16[7] |= addr._addr.s6_addr16[7]; -#else - result._addr.s6_addr32[0] |= addr._addr.s6_addr32[0]; - result._addr.s6_addr32[1] |= addr._addr.s6_addr32[1]; - result._addr.s6_addr32[2] |= addr._addr.s6_addr32[2]; - result._addr.s6_addr32[3] |= addr._addr.s6_addr32[3]; -#endif - return result; -} - - -IPv6AddressImpl IPv6AddressImpl::operator ^ (const IPv6AddressImpl& addr) const -{ - if (_scope != addr._scope) - throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match with the source one."); - - IPv6AddressImpl result(*this); - -#ifdef POCO_OS_FAMILY_WINDOWS - result._addr.s6_addr16[0] ^= addr._addr.s6_addr16[0]; - result._addr.s6_addr16[1] ^= addr._addr.s6_addr16[1]; - result._addr.s6_addr16[2] ^= addr._addr.s6_addr16[2]; - result._addr.s6_addr16[3] ^= addr._addr.s6_addr16[3]; - result._addr.s6_addr16[4] ^= addr._addr.s6_addr16[4]; - result._addr.s6_addr16[5] ^= addr._addr.s6_addr16[5]; - result._addr.s6_addr16[6] ^= addr._addr.s6_addr16[6]; - result._addr.s6_addr16[7] ^= addr._addr.s6_addr16[7]; -#else - result._addr.s6_addr32[0] ^= addr._addr.s6_addr32[0]; - result._addr.s6_addr32[1] ^= addr._addr.s6_addr32[1]; - result._addr.s6_addr32[2] ^= addr._addr.s6_addr32[2]; - result._addr.s6_addr32[3] ^= addr._addr.s6_addr32[3]; -#endif - return result; -} - - -IPv6AddressImpl IPv6AddressImpl::operator ~ () const -{ - IPv6AddressImpl result(*this); -#ifdef POCO_OS_FAMILY_WINDOWS - result._addr.s6_addr16[0] ^= 0xffff; - result._addr.s6_addr16[1] ^= 0xffff; - result._addr.s6_addr16[2] ^= 0xffff; - result._addr.s6_addr16[3] ^= 0xffff; - result._addr.s6_addr16[4] ^= 0xffff; - result._addr.s6_addr16[5] ^= 0xffff; - result._addr.s6_addr16[6] ^= 0xffff; - result._addr.s6_addr16[7] ^= 0xffff; -#else - result._addr.s6_addr32[0] ^= 0xffffffff; - result._addr.s6_addr32[1] ^= 0xffffffff; - result._addr.s6_addr32[2] ^= 0xffffffff; - result._addr.s6_addr32[3] ^= 0xffffffff; -#endif - return result; -} - - -bool IPv6AddressImpl::operator == (const IPv6AddressImpl& addr) const -{ - return _scope == addr._scope && 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr)); -} - - -bool IPv6AddressImpl::operator != (const IPv6AddressImpl& addr) const -{ - return !(*this == addr); -} - - -#endif // POCO_HAVE_IPv6 - - -} } } // namespace Poco::Net::Impl + throw Poco::InvalidArgumentException("Scope ID of passed IPv6 address does not match with the source one."); + + IPv6AddressImpl result(*this); + +#ifdef POCO_OS_FAMILY_WINDOWS + result._addr.s6_addr16[0] ^= addr._addr.s6_addr16[0]; + result._addr.s6_addr16[1] ^= addr._addr.s6_addr16[1]; + result._addr.s6_addr16[2] ^= addr._addr.s6_addr16[2]; + result._addr.s6_addr16[3] ^= addr._addr.s6_addr16[3]; + result._addr.s6_addr16[4] ^= addr._addr.s6_addr16[4]; + result._addr.s6_addr16[5] ^= addr._addr.s6_addr16[5]; + result._addr.s6_addr16[6] ^= addr._addr.s6_addr16[6]; + result._addr.s6_addr16[7] ^= addr._addr.s6_addr16[7]; +#else + result._addr.s6_addr32[0] ^= addr._addr.s6_addr32[0]; + result._addr.s6_addr32[1] ^= addr._addr.s6_addr32[1]; + result._addr.s6_addr32[2] ^= addr._addr.s6_addr32[2]; + result._addr.s6_addr32[3] ^= addr._addr.s6_addr32[3]; +#endif + return result; +} + + +IPv6AddressImpl IPv6AddressImpl::operator ~ () const +{ + IPv6AddressImpl result(*this); +#ifdef POCO_OS_FAMILY_WINDOWS + result._addr.s6_addr16[0] ^= 0xffff; + result._addr.s6_addr16[1] ^= 0xffff; + result._addr.s6_addr16[2] ^= 0xffff; + result._addr.s6_addr16[3] ^= 0xffff; + result._addr.s6_addr16[4] ^= 0xffff; + result._addr.s6_addr16[5] ^= 0xffff; + result._addr.s6_addr16[6] ^= 0xffff; + result._addr.s6_addr16[7] ^= 0xffff; +#else + result._addr.s6_addr32[0] ^= 0xffffffff; + result._addr.s6_addr32[1] ^= 0xffffffff; + result._addr.s6_addr32[2] ^= 0xffffffff; + result._addr.s6_addr32[3] ^= 0xffffffff; +#endif + return result; +} + + +bool IPv6AddressImpl::operator == (const IPv6AddressImpl& addr) const +{ + return _scope == addr._scope && 0 == std::memcmp(&addr._addr, &_addr, sizeof(_addr)); +} + + +bool IPv6AddressImpl::operator != (const IPv6AddressImpl& addr) const +{ + return !(*this == addr); +} + + +#endif // POCO_HAVE_IPv6 + + +} } } // namespace Poco::Net::Impl diff --git a/contrib/libs/poco/Net/src/MailMessage.cpp b/contrib/libs/poco/Net/src/MailMessage.cpp index 6246f9e90b..3bc82e0f0c 100644 --- a/contrib/libs/poco/Net/src/MailMessage.cpp +++ b/contrib/libs/poco/Net/src/MailMessage.cpp @@ -1,695 +1,695 @@ -// -// MailMessage.cpp -// -// Library: Net -// Package: Mail -// Module: MailMessage -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/MailMessage.h" -#include "Poco/Net/MediaType.h" -#include "Poco/Net/MultipartReader.h" -#include "Poco/Net/MultipartWriter.h" -#include "Poco/Net/PartSource.h" -#include "Poco/Net/PartHandler.h" -#include "Poco/Net/StringPartSource.h" -#include "Poco/Net/QuotedPrintableEncoder.h" -#include "Poco/Net/QuotedPrintableDecoder.h" -#include "Poco/Net/NameValueCollection.h" -#include "Poco/Base64Encoder.h" -#include "Poco/Base64Decoder.h" -#include "Poco/StreamCopier.h" -#include "Poco/DateTimeFormat.h" -#include "Poco/DateTimeFormatter.h" -#include "Poco/DateTimeParser.h" -#include "Poco/String.h" -#include "Poco/StringTokenizer.h" -#include "Poco/StreamCopier.h" -#include "Poco/NumberFormatter.h" -#include <sstream> - - -using Poco::Base64Encoder; -using Poco::Base64Decoder; -using Poco::StreamCopier; -using Poco::DateTimeFormat; -using Poco::DateTimeFormatter; -using Poco::DateTimeParser; -using Poco::StringTokenizer; -using Poco::icompare; - - -namespace Poco { -namespace Net { - - -namespace -{ - class MultiPartHandler: public PartHandler - /// This is a default part handler for multipart messages, used when there - /// is no external handler provided to he MailMessage. This handler - /// will handle all types of message parts, including attachments. - { - public: - MultiPartHandler(MailMessage* pMsg): _pMsg(pMsg) - /// Creates multi part handler. - /// The pMsg pointer points to the calling MailMessage - /// and will be used to properly populate it, so the - /// message content could be written out unmodified - /// in its entirety, including attachments. - { - } - - ~MultiPartHandler() - /// Destroys string part handler. - { - } - - void handlePart(const MessageHeader& header, std::istream& stream) - /// Handles a part. If message pointer was provided at construction time, - /// the message pointed to will be properly populated so it could be written - /// back out at a later point in time. - { - std::string tmp; - Poco::StreamCopier::copyToString(stream, tmp); - if (_pMsg) - { - MailMessage::ContentTransferEncoding cte = MailMessage::ENCODING_7BIT; - if (header.has(MailMessage::HEADER_CONTENT_TRANSFER_ENCODING)) - { - std::string enc = header[MailMessage::HEADER_CONTENT_TRANSFER_ENCODING]; - if (enc == MailMessage::CTE_8BIT) - cte = MailMessage::ENCODING_8BIT; - else if (enc == MailMessage::CTE_QUOTED_PRINTABLE) - cte = MailMessage::ENCODING_QUOTED_PRINTABLE; - else if (enc == MailMessage::CTE_BASE64) - cte = MailMessage::ENCODING_BASE64; - } - - std::string contentType = header.get(MailMessage::HEADER_CONTENT_TYPE, ""); - std::string contentDisp = header.get(MailMessage::HEADER_CONTENT_DISPOSITION, ""); - std::string filename; - if (!contentDisp.empty()) - filename = getParamFromHeader(contentDisp, "filename"); - if (filename.empty()) - filename = getParamFromHeader(contentType, "name"); - PartSource* pPS = _pMsg->createPartStore(tmp, contentType, filename); - poco_check_ptr (pPS); - NameValueCollection::ConstIterator it = header.begin(); - NameValueCollection::ConstIterator end = header.end(); - bool added = false; - for (; it != end; ++it) - { - if (!added && MailMessage::HEADER_CONTENT_DISPOSITION == it->first) - { - if (it->second == "inline") - _pMsg->addContent(pPS, cte); - else - _pMsg->addAttachment("", pPS, cte); - added = true; - } - - pPS->headers().set(it->first, it->second); - } - - if (contentDisp.empty()) - { - _pMsg->addContent(pPS, cte); - added = true; - } - - if (!added) delete pPS; - } - } - - private: - std::string getParamFromHeader(const std::string& header, const std::string& param) - { - StringTokenizer st(header, ";=", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); - StringTokenizer::Iterator it = st.begin(); - StringTokenizer::Iterator end = st.end(); - for (; it != end; ++it) { if (*it == param) break; } - if (it != end) - { - ++it; - if (it == end) return ""; - return *it; - } - return ""; - } - - MailMessage* _pMsg; - }; - - - class StringPartHandler: public PartHandler - /// This is a default part handler, used when there is no - /// external handler provided to the MailMessage. This handler - /// handles only single-part messages. - { - public: - StringPartHandler(std::string& content): _str(content) - /// Creates string part handler. - /// The content parameter represents the part content. - { - } - - ~StringPartHandler() - /// Destroys string part handler. - { - } - - void handlePart(const MessageHeader& /*header*/, std::istream& stream) - /// Handles a part. - { - std::string tmp; - Poco::StreamCopier::copyToString(stream, tmp); - _str.append(tmp); - } - - private: - std::string& _str; - }; -} - - -const std::string MailMessage::HEADER_SUBJECT("Subject"); -const std::string MailMessage::HEADER_FROM("From"); -const std::string MailMessage::HEADER_TO("To"); -const std::string MailMessage::HEADER_CC("CC"); -const std::string MailMessage::HEADER_BCC("BCC"); -const std::string MailMessage::HEADER_DATE("Date"); -const std::string MailMessage::HEADER_CONTENT_TYPE("Content-Type"); -const std::string MailMessage::HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding"); -const std::string MailMessage::HEADER_CONTENT_DISPOSITION("Content-Disposition"); -const std::string MailMessage::HEADER_CONTENT_ID("Content-ID"); -const std::string MailMessage::HEADER_MIME_VERSION("Mime-Version"); -const std::string MailMessage::EMPTY_HEADER; -const std::string MailMessage::TEXT_PLAIN("text/plain"); -const std::string MailMessage::CTE_7BIT("7bit"); -const std::string MailMessage::CTE_8BIT("8bit"); -const std::string MailMessage::CTE_QUOTED_PRINTABLE("quoted-printable"); -const std::string MailMessage::CTE_BASE64("base64"); - - -MailMessage::MailMessage(PartStoreFactory* pStoreFactory): - _encoding(), - _pStoreFactory(pStoreFactory) -{ - Poco::Timestamp now; - setDate(now); - setContentType("text/plain"); -} - - -MailMessage::~MailMessage() -{ - for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it) - { - delete it->pSource; - } -} - - -void MailMessage::addRecipient(const MailRecipient& recipient) -{ - _recipients.push_back(recipient); -} - - -void MailMessage::setRecipients(const Recipients& recipients) -{ - _recipients.assign(recipients.begin(), recipients.end()); -} - - -void MailMessage::setSender(const std::string& sender) -{ - set(HEADER_FROM, sender); -} - - -const std::string& MailMessage::getSender() const -{ - if (has(HEADER_FROM)) - return get(HEADER_FROM); - else - return EMPTY_HEADER; -} - - -void MailMessage::setSubject(const std::string& subject) -{ - set(HEADER_SUBJECT, subject); -} - - -const std::string& MailMessage::getSubject() const -{ - if (has(HEADER_SUBJECT)) - return get(HEADER_SUBJECT); - else - return EMPTY_HEADER; -} - - -void MailMessage::setContent(const std::string& content, ContentTransferEncoding encoding) -{ - _content = content; - _encoding = encoding; - set(HEADER_CONTENT_TRANSFER_ENCODING, contentTransferEncodingToString(encoding)); -} - - -void MailMessage::setContentType(const std::string& mediaType) -{ - set(HEADER_CONTENT_TYPE, mediaType); -} - - -void MailMessage::setContentType(const MediaType& mediaType) -{ - setContentType(mediaType.toString()); -} - - -const std::string& MailMessage::getContentType() const -{ - if (has(HEADER_CONTENT_TYPE)) - return get(HEADER_CONTENT_TYPE); - else - return TEXT_PLAIN; -} - - -void MailMessage::setDate(const Poco::Timestamp& dateTime) -{ - set(HEADER_DATE, DateTimeFormatter::format(dateTime, DateTimeFormat::RFC1123_FORMAT)); -} - - -Poco::Timestamp MailMessage::getDate() const -{ - const std::string& dateTime = get(HEADER_DATE); - int tzd; - return DateTimeParser::parse(dateTime, tzd).timestamp(); -} - - -bool MailMessage::isMultipart() const -{ - MediaType mediaType = getContentType(); - return mediaType.matches("multipart"); -} - - -void MailMessage::addPart(const std::string& name, PartSource* pSource, ContentDisposition disposition, ContentTransferEncoding encoding) -{ - poco_check_ptr (pSource); - - makeMultipart(); - Part part; - part.name = name; - part.pSource = pSource; - part.disposition = disposition; - part.encoding = encoding; - _parts.push_back(part); -} - - -void MailMessage::addContent(PartSource* pSource, ContentTransferEncoding encoding) -{ - addPart("", pSource, CONTENT_INLINE, encoding); -} - - -void MailMessage::addAttachment(const std::string& name, PartSource* pSource, ContentTransferEncoding encoding) -{ - addPart(name, pSource, CONTENT_ATTACHMENT, encoding); -} - - -void MailMessage::read(std::istream& istr, PartHandler& handler) -{ - readHeader(istr); - if (isMultipart()) - { - readMultipart(istr, handler); - } - else - { - StringPartHandler handler2(_content); - readPart(istr, *this, handler2); - } -} - - -void MailMessage::read(std::istream& istr) -{ - readHeader(istr); - if (isMultipart()) - { - MultiPartHandler handler(this); - readMultipart(istr, handler); - } - else - { - StringPartHandler handler(_content); - readPart(istr, *this, handler); - } -} - - -void MailMessage::write(std::ostream& ostr) const -{ - MessageHeader header(*this); - setRecipientHeaders(header); - if (isMultipart()) - { - writeMultipart(header, ostr); - } - else - { - writeHeader(header, ostr); - std::istringstream istr(_content); - writeEncoded(istr, ostr, _encoding); - } -} - - -void MailMessage::makeMultipart() -{ - if (!isMultipart()) - { - MediaType mediaType("multipart", "mixed"); - setContentType(mediaType); - } -} - - -void MailMessage::writeHeader(const MessageHeader& header, std::ostream& ostr) const -{ - header.write(ostr); - ostr << "\r\n"; -} - - -void MailMessage::writeMultipart(MessageHeader& header, std::ostream& ostr) const -{ - if (_boundary.empty()) _boundary = MultipartWriter::createBoundary(); - MediaType mediaType(getContentType()); - mediaType.setParameter("boundary", _boundary); - header.set(HEADER_CONTENT_TYPE, mediaType.toString()); - header.set(HEADER_MIME_VERSION, "1.0"); - writeHeader(header, ostr); - - MultipartWriter writer(ostr, _boundary); - for (PartVec::const_iterator it = _parts.begin(); it != _parts.end(); ++it) - { - writePart(writer, *it); - } - writer.close(); -} - - -void MailMessage::writePart(MultipartWriter& writer, const Part& part) const -{ - MessageHeader partHeader(part.pSource->headers()); - MediaType mediaType(part.pSource->mediaType()); - if (!part.name.empty()) - mediaType.setParameter("name", part.name); - partHeader.set(HEADER_CONTENT_TYPE, mediaType.toString()); - partHeader.set(HEADER_CONTENT_TRANSFER_ENCODING, contentTransferEncodingToString(part.encoding)); - std::string disposition; - if (part.disposition == CONTENT_ATTACHMENT) - { - disposition = "attachment"; - const std::string& filename = part.pSource->filename(); - if (!filename.empty()) - { - disposition.append("; filename="); - quote(filename, disposition); - } - } - else disposition = "inline"; - partHeader.set(HEADER_CONTENT_DISPOSITION, disposition); - writer.nextPart(partHeader); - writeEncoded(part.pSource->stream(), writer.stream(), part.encoding); -} - - -void MailMessage::writeEncoded(std::istream& istr, std::ostream& ostr, ContentTransferEncoding encoding) const -{ - switch (encoding) - { - case ENCODING_7BIT: - case ENCODING_8BIT: - StreamCopier::copyStream(istr, ostr); - break; - case ENCODING_QUOTED_PRINTABLE: - { - QuotedPrintableEncoder encoder(ostr); - StreamCopier::copyStream(istr, encoder); - encoder.close(); - } - break; - case ENCODING_BASE64: - { - Base64Encoder encoder(ostr); - StreamCopier::copyStream(istr, encoder); - encoder.close(); - } - break; - } -} - - -void MailMessage::readHeader(std::istream& istr) -{ - clear(); - MessageHeader::read(istr); - istr.get(); // \r - if ('\n' == istr.peek()) istr.get(); // \n -} - - -void MailMessage::readMultipart(std::istream& istr, PartHandler& handler) -{ - MediaType contentType(getContentType()); - _boundary = contentType.getParameter("boundary"); - MultipartReader reader(istr, _boundary); - while (reader.hasNextPart()) - { - MessageHeader partHeader; - reader.nextPart(partHeader); - readPart(reader.stream(), partHeader, handler); - } -} - - -void MailMessage::readPart(std::istream& istr, const MessageHeader& header, PartHandler& handler) -{ - std::string encoding; - if (header.has(HEADER_CONTENT_TRANSFER_ENCODING)) - { - encoding = header.get(HEADER_CONTENT_TRANSFER_ENCODING); - // get rid of a parameter if one is set - std::string::size_type pos = encoding.find(';'); - if (pos != std::string::npos) - encoding.resize(pos); - } - if (icompare(encoding, CTE_QUOTED_PRINTABLE) == 0) - { - QuotedPrintableDecoder decoder(istr); - handlePart(decoder, header, handler); - _encoding = ENCODING_QUOTED_PRINTABLE; - } - else if (icompare(encoding, CTE_BASE64) == 0) - { - Base64Decoder decoder(istr); - handlePart(decoder, header, handler); - _encoding = ENCODING_BASE64; - } - else - { - if (icompare(encoding, CTE_7BIT) == 0) - _encoding = ENCODING_7BIT; - else if (icompare(encoding, CTE_8BIT) == 0) - _encoding = ENCODING_8BIT; - - handlePart(istr, header, handler); - } -} - - -void MailMessage::handlePart(std::istream& istr, const MessageHeader& header, PartHandler& handler) -{ - handler.handlePart(header, istr); - // Read remaining characters from stream in case - // the handler failed to read the complete stream. - while (istr.good()) istr.get(); -} - - -void MailMessage::setRecipientHeaders(MessageHeader& headers) const -{ - std::string to; - std::string cc; - std::string bcc; - - for (Recipients::const_iterator it = _recipients.begin(); it != _recipients.end(); ++it) - { - switch (it->getType()) - { - case MailRecipient::PRIMARY_RECIPIENT: - appendRecipient(*it, to); - break; - case MailRecipient::CC_RECIPIENT: - appendRecipient(*it, cc); - break; - case MailRecipient::BCC_RECIPIENT: - break; - } - } - if (!to.empty()) headers.set(HEADER_TO, to); - if (!cc.empty()) headers.set(HEADER_CC, cc); -} - - -const std::string& MailMessage::contentTransferEncodingToString(ContentTransferEncoding encoding) -{ - switch (encoding) - { - case ENCODING_7BIT: - return CTE_7BIT; - case ENCODING_8BIT: - return CTE_8BIT; - case ENCODING_QUOTED_PRINTABLE: - return CTE_QUOTED_PRINTABLE; - case ENCODING_BASE64: - return CTE_BASE64; - default: - poco_bugcheck(); - } - return CTE_7BIT; -} - - -int MailMessage::lineLength(const std::string& str) -{ - int n = 0; - std::string::const_reverse_iterator it = str.rbegin(); - std::string::const_reverse_iterator end = str.rend(); - while (it != end && *it != '\n') { ++n; ++it; } - return n; -} - - -void MailMessage::appendRecipient(const MailRecipient& recipient, std::string& str) -{ - if (!str.empty()) str.append(", "); - const std::string& realName = recipient.getRealName(); - const std::string& address = recipient.getAddress(); - std::string rec; - if (!realName.empty()) - { - quote(realName, rec, true); - rec.append(" "); - } - rec.append("<"); - rec.append(address); - rec.append(">"); - if (lineLength(str) + rec.length() > 70) str.append("\r\n\t"); - str.append(rec); -} - - -std::string MailMessage::encodeWord(const std::string& text, const std::string& charset) -{ - bool containsNonASCII = false; - for (std::string::const_iterator it = text.begin(); it != text.end(); ++it) - { - if (static_cast<unsigned char>(*it) > 127) - { - containsNonASCII = true; - break; - } - } - if (!containsNonASCII) return text; - - std::string encodedText; - std::string::size_type lineLength = 0; - for (std::string::const_iterator it = text.begin(); it != text.end(); ++it) - { - if (lineLength == 0) - { - encodedText += "=?"; - encodedText += charset; - encodedText += "?q?"; - lineLength += charset.length() + 5; - } - switch (*it) - { - case ' ': - encodedText += '_'; - lineLength++; - break; - case '=': - case '?': - case '_': - case '(': - case ')': - case '[': - case ']': - case '<': - case '>': - case ',': - case ';': - case ':': - case '.': - case '@': - encodedText += '='; - NumberFormatter::appendHex(encodedText, static_cast<unsigned>(static_cast<unsigned char>(*it)), 2); - lineLength += 3; - break; - default: - if (*it > 32 && *it < 127) - { - encodedText += *it; - lineLength++; - } - else - { - encodedText += '='; - NumberFormatter::appendHex(encodedText, static_cast<unsigned>(static_cast<unsigned char>(*it)), 2); - lineLength += 3; - } - } - if ((lineLength >= 64 && (*it == ' ' || *it == '\t' || *it == '\r' || *it == '\n')) || lineLength >= 72) - { - encodedText += "?=\r\n "; - lineLength = 0; - } - } - if (lineLength > 0) - { - encodedText += "?="; - } - return encodedText; -} - - -PartSource* MailMessage::createPartStore(const std::string& content, const std::string& mediaType, const std::string& filename) -{ - if (!_pStoreFactory) return new StringPartSource(content, mediaType, filename); - else return _pStoreFactory->createPartStore(content, mediaType, filename); -} - - -} } // namespace Poco::Net +// +// MailMessage.cpp +// +// Library: Net +// Package: Mail +// Module: MailMessage +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/MailMessage.h" +#include "Poco/Net/MediaType.h" +#include "Poco/Net/MultipartReader.h" +#include "Poco/Net/MultipartWriter.h" +#include "Poco/Net/PartSource.h" +#include "Poco/Net/PartHandler.h" +#include "Poco/Net/StringPartSource.h" +#include "Poco/Net/QuotedPrintableEncoder.h" +#include "Poco/Net/QuotedPrintableDecoder.h" +#include "Poco/Net/NameValueCollection.h" +#include "Poco/Base64Encoder.h" +#include "Poco/Base64Decoder.h" +#include "Poco/StreamCopier.h" +#include "Poco/DateTimeFormat.h" +#include "Poco/DateTimeFormatter.h" +#include "Poco/DateTimeParser.h" +#include "Poco/String.h" +#include "Poco/StringTokenizer.h" +#include "Poco/StreamCopier.h" +#include "Poco/NumberFormatter.h" +#include <sstream> + + +using Poco::Base64Encoder; +using Poco::Base64Decoder; +using Poco::StreamCopier; +using Poco::DateTimeFormat; +using Poco::DateTimeFormatter; +using Poco::DateTimeParser; +using Poco::StringTokenizer; +using Poco::icompare; + + +namespace Poco { +namespace Net { + + +namespace +{ + class MultiPartHandler: public PartHandler + /// This is a default part handler for multipart messages, used when there + /// is no external handler provided to he MailMessage. This handler + /// will handle all types of message parts, including attachments. + { + public: + MultiPartHandler(MailMessage* pMsg): _pMsg(pMsg) + /// Creates multi part handler. + /// The pMsg pointer points to the calling MailMessage + /// and will be used to properly populate it, so the + /// message content could be written out unmodified + /// in its entirety, including attachments. + { + } + + ~MultiPartHandler() + /// Destroys string part handler. + { + } + + void handlePart(const MessageHeader& header, std::istream& stream) + /// Handles a part. If message pointer was provided at construction time, + /// the message pointed to will be properly populated so it could be written + /// back out at a later point in time. + { + std::string tmp; + Poco::StreamCopier::copyToString(stream, tmp); + if (_pMsg) + { + MailMessage::ContentTransferEncoding cte = MailMessage::ENCODING_7BIT; + if (header.has(MailMessage::HEADER_CONTENT_TRANSFER_ENCODING)) + { + std::string enc = header[MailMessage::HEADER_CONTENT_TRANSFER_ENCODING]; + if (enc == MailMessage::CTE_8BIT) + cte = MailMessage::ENCODING_8BIT; + else if (enc == MailMessage::CTE_QUOTED_PRINTABLE) + cte = MailMessage::ENCODING_QUOTED_PRINTABLE; + else if (enc == MailMessage::CTE_BASE64) + cte = MailMessage::ENCODING_BASE64; + } + + std::string contentType = header.get(MailMessage::HEADER_CONTENT_TYPE, ""); + std::string contentDisp = header.get(MailMessage::HEADER_CONTENT_DISPOSITION, ""); + std::string filename; + if (!contentDisp.empty()) + filename = getParamFromHeader(contentDisp, "filename"); + if (filename.empty()) + filename = getParamFromHeader(contentType, "name"); + PartSource* pPS = _pMsg->createPartStore(tmp, contentType, filename); + poco_check_ptr (pPS); + NameValueCollection::ConstIterator it = header.begin(); + NameValueCollection::ConstIterator end = header.end(); + bool added = false; + for (; it != end; ++it) + { + if (!added && MailMessage::HEADER_CONTENT_DISPOSITION == it->first) + { + if (it->second == "inline") + _pMsg->addContent(pPS, cte); + else + _pMsg->addAttachment("", pPS, cte); + added = true; + } + + pPS->headers().set(it->first, it->second); + } + + if (contentDisp.empty()) + { + _pMsg->addContent(pPS, cte); + added = true; + } + + if (!added) delete pPS; + } + } + + private: + std::string getParamFromHeader(const std::string& header, const std::string& param) + { + StringTokenizer st(header, ";=", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); + StringTokenizer::Iterator it = st.begin(); + StringTokenizer::Iterator end = st.end(); + for (; it != end; ++it) { if (*it == param) break; } + if (it != end) + { + ++it; + if (it == end) return ""; + return *it; + } + return ""; + } + + MailMessage* _pMsg; + }; + + + class StringPartHandler: public PartHandler + /// This is a default part handler, used when there is no + /// external handler provided to the MailMessage. This handler + /// handles only single-part messages. + { + public: + StringPartHandler(std::string& content): _str(content) + /// Creates string part handler. + /// The content parameter represents the part content. + { + } + + ~StringPartHandler() + /// Destroys string part handler. + { + } + + void handlePart(const MessageHeader& /*header*/, std::istream& stream) + /// Handles a part. + { + std::string tmp; + Poco::StreamCopier::copyToString(stream, tmp); + _str.append(tmp); + } + + private: + std::string& _str; + }; +} + + +const std::string MailMessage::HEADER_SUBJECT("Subject"); +const std::string MailMessage::HEADER_FROM("From"); +const std::string MailMessage::HEADER_TO("To"); +const std::string MailMessage::HEADER_CC("CC"); +const std::string MailMessage::HEADER_BCC("BCC"); +const std::string MailMessage::HEADER_DATE("Date"); +const std::string MailMessage::HEADER_CONTENT_TYPE("Content-Type"); +const std::string MailMessage::HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding"); +const std::string MailMessage::HEADER_CONTENT_DISPOSITION("Content-Disposition"); +const std::string MailMessage::HEADER_CONTENT_ID("Content-ID"); +const std::string MailMessage::HEADER_MIME_VERSION("Mime-Version"); +const std::string MailMessage::EMPTY_HEADER; +const std::string MailMessage::TEXT_PLAIN("text/plain"); +const std::string MailMessage::CTE_7BIT("7bit"); +const std::string MailMessage::CTE_8BIT("8bit"); +const std::string MailMessage::CTE_QUOTED_PRINTABLE("quoted-printable"); +const std::string MailMessage::CTE_BASE64("base64"); + + +MailMessage::MailMessage(PartStoreFactory* pStoreFactory): + _encoding(), + _pStoreFactory(pStoreFactory) +{ + Poco::Timestamp now; + setDate(now); + setContentType("text/plain"); +} + + +MailMessage::~MailMessage() +{ + for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it) + { + delete it->pSource; + } +} + + +void MailMessage::addRecipient(const MailRecipient& recipient) +{ + _recipients.push_back(recipient); +} + + +void MailMessage::setRecipients(const Recipients& recipients) +{ + _recipients.assign(recipients.begin(), recipients.end()); +} + + +void MailMessage::setSender(const std::string& sender) +{ + set(HEADER_FROM, sender); +} + + +const std::string& MailMessage::getSender() const +{ + if (has(HEADER_FROM)) + return get(HEADER_FROM); + else + return EMPTY_HEADER; +} + + +void MailMessage::setSubject(const std::string& subject) +{ + set(HEADER_SUBJECT, subject); +} + + +const std::string& MailMessage::getSubject() const +{ + if (has(HEADER_SUBJECT)) + return get(HEADER_SUBJECT); + else + return EMPTY_HEADER; +} + + +void MailMessage::setContent(const std::string& content, ContentTransferEncoding encoding) +{ + _content = content; + _encoding = encoding; + set(HEADER_CONTENT_TRANSFER_ENCODING, contentTransferEncodingToString(encoding)); +} + + +void MailMessage::setContentType(const std::string& mediaType) +{ + set(HEADER_CONTENT_TYPE, mediaType); +} + + +void MailMessage::setContentType(const MediaType& mediaType) +{ + setContentType(mediaType.toString()); +} + + +const std::string& MailMessage::getContentType() const +{ + if (has(HEADER_CONTENT_TYPE)) + return get(HEADER_CONTENT_TYPE); + else + return TEXT_PLAIN; +} + + +void MailMessage::setDate(const Poco::Timestamp& dateTime) +{ + set(HEADER_DATE, DateTimeFormatter::format(dateTime, DateTimeFormat::RFC1123_FORMAT)); +} + + +Poco::Timestamp MailMessage::getDate() const +{ + const std::string& dateTime = get(HEADER_DATE); + int tzd; + return DateTimeParser::parse(dateTime, tzd).timestamp(); +} + + +bool MailMessage::isMultipart() const +{ + MediaType mediaType = getContentType(); + return mediaType.matches("multipart"); +} + + +void MailMessage::addPart(const std::string& name, PartSource* pSource, ContentDisposition disposition, ContentTransferEncoding encoding) +{ + poco_check_ptr (pSource); + + makeMultipart(); + Part part; + part.name = name; + part.pSource = pSource; + part.disposition = disposition; + part.encoding = encoding; + _parts.push_back(part); +} + + +void MailMessage::addContent(PartSource* pSource, ContentTransferEncoding encoding) +{ + addPart("", pSource, CONTENT_INLINE, encoding); +} + + +void MailMessage::addAttachment(const std::string& name, PartSource* pSource, ContentTransferEncoding encoding) +{ + addPart(name, pSource, CONTENT_ATTACHMENT, encoding); +} + + +void MailMessage::read(std::istream& istr, PartHandler& handler) +{ + readHeader(istr); + if (isMultipart()) + { + readMultipart(istr, handler); + } + else + { + StringPartHandler handler2(_content); + readPart(istr, *this, handler2); + } +} + + +void MailMessage::read(std::istream& istr) +{ + readHeader(istr); + if (isMultipart()) + { + MultiPartHandler handler(this); + readMultipart(istr, handler); + } + else + { + StringPartHandler handler(_content); + readPart(istr, *this, handler); + } +} + + +void MailMessage::write(std::ostream& ostr) const +{ + MessageHeader header(*this); + setRecipientHeaders(header); + if (isMultipart()) + { + writeMultipart(header, ostr); + } + else + { + writeHeader(header, ostr); + std::istringstream istr(_content); + writeEncoded(istr, ostr, _encoding); + } +} + + +void MailMessage::makeMultipart() +{ + if (!isMultipart()) + { + MediaType mediaType("multipart", "mixed"); + setContentType(mediaType); + } +} + + +void MailMessage::writeHeader(const MessageHeader& header, std::ostream& ostr) const +{ + header.write(ostr); + ostr << "\r\n"; +} + + +void MailMessage::writeMultipart(MessageHeader& header, std::ostream& ostr) const +{ + if (_boundary.empty()) _boundary = MultipartWriter::createBoundary(); + MediaType mediaType(getContentType()); + mediaType.setParameter("boundary", _boundary); + header.set(HEADER_CONTENT_TYPE, mediaType.toString()); + header.set(HEADER_MIME_VERSION, "1.0"); + writeHeader(header, ostr); + + MultipartWriter writer(ostr, _boundary); + for (PartVec::const_iterator it = _parts.begin(); it != _parts.end(); ++it) + { + writePart(writer, *it); + } + writer.close(); +} + + +void MailMessage::writePart(MultipartWriter& writer, const Part& part) const +{ + MessageHeader partHeader(part.pSource->headers()); + MediaType mediaType(part.pSource->mediaType()); + if (!part.name.empty()) + mediaType.setParameter("name", part.name); + partHeader.set(HEADER_CONTENT_TYPE, mediaType.toString()); + partHeader.set(HEADER_CONTENT_TRANSFER_ENCODING, contentTransferEncodingToString(part.encoding)); + std::string disposition; + if (part.disposition == CONTENT_ATTACHMENT) + { + disposition = "attachment"; + const std::string& filename = part.pSource->filename(); + if (!filename.empty()) + { + disposition.append("; filename="); + quote(filename, disposition); + } + } + else disposition = "inline"; + partHeader.set(HEADER_CONTENT_DISPOSITION, disposition); + writer.nextPart(partHeader); + writeEncoded(part.pSource->stream(), writer.stream(), part.encoding); +} + + +void MailMessage::writeEncoded(std::istream& istr, std::ostream& ostr, ContentTransferEncoding encoding) const +{ + switch (encoding) + { + case ENCODING_7BIT: + case ENCODING_8BIT: + StreamCopier::copyStream(istr, ostr); + break; + case ENCODING_QUOTED_PRINTABLE: + { + QuotedPrintableEncoder encoder(ostr); + StreamCopier::copyStream(istr, encoder); + encoder.close(); + } + break; + case ENCODING_BASE64: + { + Base64Encoder encoder(ostr); + StreamCopier::copyStream(istr, encoder); + encoder.close(); + } + break; + } +} + + +void MailMessage::readHeader(std::istream& istr) +{ + clear(); + MessageHeader::read(istr); + istr.get(); // \r + if ('\n' == istr.peek()) istr.get(); // \n +} + + +void MailMessage::readMultipart(std::istream& istr, PartHandler& handler) +{ + MediaType contentType(getContentType()); + _boundary = contentType.getParameter("boundary"); + MultipartReader reader(istr, _boundary); + while (reader.hasNextPart()) + { + MessageHeader partHeader; + reader.nextPart(partHeader); + readPart(reader.stream(), partHeader, handler); + } +} + + +void MailMessage::readPart(std::istream& istr, const MessageHeader& header, PartHandler& handler) +{ + std::string encoding; + if (header.has(HEADER_CONTENT_TRANSFER_ENCODING)) + { + encoding = header.get(HEADER_CONTENT_TRANSFER_ENCODING); + // get rid of a parameter if one is set + std::string::size_type pos = encoding.find(';'); + if (pos != std::string::npos) + encoding.resize(pos); + } + if (icompare(encoding, CTE_QUOTED_PRINTABLE) == 0) + { + QuotedPrintableDecoder decoder(istr); + handlePart(decoder, header, handler); + _encoding = ENCODING_QUOTED_PRINTABLE; + } + else if (icompare(encoding, CTE_BASE64) == 0) + { + Base64Decoder decoder(istr); + handlePart(decoder, header, handler); + _encoding = ENCODING_BASE64; + } + else + { + if (icompare(encoding, CTE_7BIT) == 0) + _encoding = ENCODING_7BIT; + else if (icompare(encoding, CTE_8BIT) == 0) + _encoding = ENCODING_8BIT; + + handlePart(istr, header, handler); + } +} + + +void MailMessage::handlePart(std::istream& istr, const MessageHeader& header, PartHandler& handler) +{ + handler.handlePart(header, istr); + // Read remaining characters from stream in case + // the handler failed to read the complete stream. + while (istr.good()) istr.get(); +} + + +void MailMessage::setRecipientHeaders(MessageHeader& headers) const +{ + std::string to; + std::string cc; + std::string bcc; + + for (Recipients::const_iterator it = _recipients.begin(); it != _recipients.end(); ++it) + { + switch (it->getType()) + { + case MailRecipient::PRIMARY_RECIPIENT: + appendRecipient(*it, to); + break; + case MailRecipient::CC_RECIPIENT: + appendRecipient(*it, cc); + break; + case MailRecipient::BCC_RECIPIENT: + break; + } + } + if (!to.empty()) headers.set(HEADER_TO, to); + if (!cc.empty()) headers.set(HEADER_CC, cc); +} + + +const std::string& MailMessage::contentTransferEncodingToString(ContentTransferEncoding encoding) +{ + switch (encoding) + { + case ENCODING_7BIT: + return CTE_7BIT; + case ENCODING_8BIT: + return CTE_8BIT; + case ENCODING_QUOTED_PRINTABLE: + return CTE_QUOTED_PRINTABLE; + case ENCODING_BASE64: + return CTE_BASE64; + default: + poco_bugcheck(); + } + return CTE_7BIT; +} + + +int MailMessage::lineLength(const std::string& str) +{ + int n = 0; + std::string::const_reverse_iterator it = str.rbegin(); + std::string::const_reverse_iterator end = str.rend(); + while (it != end && *it != '\n') { ++n; ++it; } + return n; +} + + +void MailMessage::appendRecipient(const MailRecipient& recipient, std::string& str) +{ + if (!str.empty()) str.append(", "); + const std::string& realName = recipient.getRealName(); + const std::string& address = recipient.getAddress(); + std::string rec; + if (!realName.empty()) + { + quote(realName, rec, true); + rec.append(" "); + } + rec.append("<"); + rec.append(address); + rec.append(">"); + if (lineLength(str) + rec.length() > 70) str.append("\r\n\t"); + str.append(rec); +} + + +std::string MailMessage::encodeWord(const std::string& text, const std::string& charset) +{ + bool containsNonASCII = false; + for (std::string::const_iterator it = text.begin(); it != text.end(); ++it) + { + if (static_cast<unsigned char>(*it) > 127) + { + containsNonASCII = true; + break; + } + } + if (!containsNonASCII) return text; + + std::string encodedText; + std::string::size_type lineLength = 0; + for (std::string::const_iterator it = text.begin(); it != text.end(); ++it) + { + if (lineLength == 0) + { + encodedText += "=?"; + encodedText += charset; + encodedText += "?q?"; + lineLength += charset.length() + 5; + } + switch (*it) + { + case ' ': + encodedText += '_'; + lineLength++; + break; + case '=': + case '?': + case '_': + case '(': + case ')': + case '[': + case ']': + case '<': + case '>': + case ',': + case ';': + case ':': + case '.': + case '@': + encodedText += '='; + NumberFormatter::appendHex(encodedText, static_cast<unsigned>(static_cast<unsigned char>(*it)), 2); + lineLength += 3; + break; + default: + if (*it > 32 && *it < 127) + { + encodedText += *it; + lineLength++; + } + else + { + encodedText += '='; + NumberFormatter::appendHex(encodedText, static_cast<unsigned>(static_cast<unsigned char>(*it)), 2); + lineLength += 3; + } + } + if ((lineLength >= 64 && (*it == ' ' || *it == '\t' || *it == '\r' || *it == '\n')) || lineLength >= 72) + { + encodedText += "?=\r\n "; + lineLength = 0; + } + } + if (lineLength > 0) + { + encodedText += "?="; + } + return encodedText; +} + + +PartSource* MailMessage::createPartStore(const std::string& content, const std::string& mediaType, const std::string& filename) +{ + if (!_pStoreFactory) return new StringPartSource(content, mediaType, filename); + else return _pStoreFactory->createPartStore(content, mediaType, filename); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/MailRecipient.cpp b/contrib/libs/poco/Net/src/MailRecipient.cpp index 1f6672810b..3b204a113c 100644 --- a/contrib/libs/poco/Net/src/MailRecipient.cpp +++ b/contrib/libs/poco/Net/src/MailRecipient.cpp @@ -1,94 +1,94 @@ -// -// MailRecipient.cpp -// -// Library: Net -// Package: Mail -// Module: MailRecipient -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/MailRecipient.h" -#include <algorithm> - - -namespace Poco { -namespace Net { - - -MailRecipient::MailRecipient(): - _type(PRIMARY_RECIPIENT) -{ -} - - -MailRecipient::MailRecipient(const MailRecipient& recipient): - _address(recipient._address), - _realName(recipient._realName), - _type(recipient._type) -{ -} - - -MailRecipient::MailRecipient(RecipientType type, const std::string& address): - _address(address), - _type(type) -{ -} - - -MailRecipient::MailRecipient(RecipientType type, const std::string& address, const std::string& realName): - _address(address), - _realName(realName), - _type(type) -{ -} - - -MailRecipient::~MailRecipient() -{ -} - - -MailRecipient& MailRecipient::operator = (const MailRecipient& recipient) -{ - if (this != &recipient) - { - MailRecipient tmp(recipient); - swap(tmp); - } - return *this; -} - - -void MailRecipient::swap(MailRecipient& recipient) -{ - std::swap(_type, recipient._type); - std::swap(_address, recipient._address); - std::swap(_realName, recipient._realName); -} - - -void MailRecipient::setType(RecipientType type) -{ - _type = type; -} - - -void MailRecipient::setAddress(const std::string& address) -{ - _address = address; -} - - -void MailRecipient::setRealName(const std::string& realName) -{ - _realName = realName; -} - - -} } // namespace Poco::Net +// +// MailRecipient.cpp +// +// Library: Net +// Package: Mail +// Module: MailRecipient +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/MailRecipient.h" +#include <algorithm> + + +namespace Poco { +namespace Net { + + +MailRecipient::MailRecipient(): + _type(PRIMARY_RECIPIENT) +{ +} + + +MailRecipient::MailRecipient(const MailRecipient& recipient): + _address(recipient._address), + _realName(recipient._realName), + _type(recipient._type) +{ +} + + +MailRecipient::MailRecipient(RecipientType type, const std::string& address): + _address(address), + _type(type) +{ +} + + +MailRecipient::MailRecipient(RecipientType type, const std::string& address, const std::string& realName): + _address(address), + _realName(realName), + _type(type) +{ +} + + +MailRecipient::~MailRecipient() +{ +} + + +MailRecipient& MailRecipient::operator = (const MailRecipient& recipient) +{ + if (this != &recipient) + { + MailRecipient tmp(recipient); + swap(tmp); + } + return *this; +} + + +void MailRecipient::swap(MailRecipient& recipient) +{ + std::swap(_type, recipient._type); + std::swap(_address, recipient._address); + std::swap(_realName, recipient._realName); +} + + +void MailRecipient::setType(RecipientType type) +{ + _type = type; +} + + +void MailRecipient::setAddress(const std::string& address) +{ + _address = address; +} + + +void MailRecipient::setRealName(const std::string& realName) +{ + _realName = realName; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/MailStream.cpp b/contrib/libs/poco/Net/src/MailStream.cpp index 8cd8fa44d8..b498ca2894 100644 --- a/contrib/libs/poco/Net/src/MailStream.cpp +++ b/contrib/libs/poco/Net/src/MailStream.cpp @@ -1,221 +1,221 @@ -// -// MailStream.cpp -// -// Library: Net -// Package: Mail -// Module: MailStream -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/MailStream.h" - - -namespace Poco { -namespace Net { - - -MailStreamBuf::MailStreamBuf(std::istream& istr): - _pIstr(&istr), - _pOstr(0), - _state(ST_CR_LF) -{ -} - - -MailStreamBuf::MailStreamBuf(std::ostream& ostr): - _pIstr(0), - _pOstr(&ostr), - _state(ST_CR_LF) -{ -} - - -MailStreamBuf::~MailStreamBuf() -{ -} - - -void MailStreamBuf::close() -{ - if (_pOstr && _state != ST_CR_LF_DOT_CR_LF) - { - if (!_buffer.empty()) - _pOstr->write(_buffer.data(), (std::streamsize) _buffer.length()); - if (_state != ST_CR_LF) - _pOstr->write("\r\n", 2); - _pOstr->write(".\r\n", 3); - _state = ST_CR_LF_DOT_CR_LF; - } -} - - -int MailStreamBuf::readFromDevice() -{ - int c = std::char_traits<char>::eof(); - if (!_buffer.empty()) - { - c = _buffer[0]; - _buffer.erase(0, 1); - } - else - { - c = readOne(); - while (c != std::char_traits<char>::eof() && _state != ST_DATA && _state != ST_CR_LF_DOT_CR_LF) - c = readOne(); - if (!_buffer.empty()) - { - c = _buffer[0]; - _buffer.erase(0, 1); - } - } - return c; -} - - -int MailStreamBuf::readOne() -{ - int c = std::char_traits<char>::eof(); - if (_state != ST_CR_LF_DOT_CR_LF) - { - c = _pIstr->get(); - switch (c) - { - case '\r': - if (_state == ST_CR_LF_DOT) - _state = ST_CR_LF_DOT_CR; - else - _state = ST_CR; - break; - case '\n': - if (_state == ST_CR) - _state = ST_CR_LF; - else if (_state == ST_CR_LF_DOT_CR) - _state = ST_CR_LF_DOT_CR_LF; - else - _state = ST_DATA; - break; - case '.': - if (_state == ST_CR_LF) - _state = ST_CR_LF_DOT; - else if (_state == ST_CR_LF_DOT) - _state = ST_CR_LF_DOT_DOT; - else - _state = ST_DATA; - break; - default: - _state = ST_DATA; - } - if (_state == ST_CR_LF_DOT_DOT) - _state = ST_DATA; - else if (_state == ST_CR_LF_DOT_CR_LF) - _buffer.resize(_buffer.size() - 2); - else if (c != std::char_traits<char>::eof()) - _buffer += (char) c; - } - return c; -} - - -int MailStreamBuf::writeToDevice(char c) -{ - switch (c) - { - case '\r': - _state = ST_CR; - break; - case '\n': - if (_state == ST_CR) - _state = ST_CR_LF; - else - _state = ST_DATA; - break; - case '.': - if (_state == ST_CR_LF) - _state = ST_CR_LF_DOT; - else - _state = ST_DATA; - break; - default: - _state = ST_DATA; - } - if (_state == ST_DATA) - { - if (!_buffer.empty()) - { - _pOstr->write(_buffer.data(), (std::streamsize) _buffer.length()); - _buffer.clear(); - } - _pOstr->put(c); - } - else if (_state == ST_CR_LF_DOT) - { - // buffer contains one or more CR-LF pairs - _pOstr->write(_buffer.data(), (std::streamsize) _buffer.length()); - _pOstr->write("..", 2); - _state = ST_DATA; - _buffer.clear(); - } - else _buffer += c; - return charToInt(c); -} - - -MailIOS::MailIOS(std::istream& istr): _buf(istr) -{ - poco_ios_init(&_buf); -} - - -MailIOS::MailIOS(std::ostream& ostr): _buf(ostr) -{ - poco_ios_init(&_buf); -} - - -MailIOS::~MailIOS() -{ -} - - -void MailIOS::close() -{ - _buf.close(); -} - - -MailStreamBuf* MailIOS::rdbuf() -{ - return &_buf; -} - - -MailInputStream::MailInputStream(std::istream& istr): - MailIOS(istr), - std::istream(&_buf) -{ -} - - -MailInputStream::~MailInputStream() -{ -} - - -MailOutputStream::MailOutputStream(std::ostream& ostr): - MailIOS(ostr), - std::ostream(&_buf) -{ -} - - -MailOutputStream::~MailOutputStream() -{ -} - - -} } // namespace Poco::Net +// +// MailStream.cpp +// +// Library: Net +// Package: Mail +// Module: MailStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/MailStream.h" + + +namespace Poco { +namespace Net { + + +MailStreamBuf::MailStreamBuf(std::istream& istr): + _pIstr(&istr), + _pOstr(0), + _state(ST_CR_LF) +{ +} + + +MailStreamBuf::MailStreamBuf(std::ostream& ostr): + _pIstr(0), + _pOstr(&ostr), + _state(ST_CR_LF) +{ +} + + +MailStreamBuf::~MailStreamBuf() +{ +} + + +void MailStreamBuf::close() +{ + if (_pOstr && _state != ST_CR_LF_DOT_CR_LF) + { + if (!_buffer.empty()) + _pOstr->write(_buffer.data(), (std::streamsize) _buffer.length()); + if (_state != ST_CR_LF) + _pOstr->write("\r\n", 2); + _pOstr->write(".\r\n", 3); + _state = ST_CR_LF_DOT_CR_LF; + } +} + + +int MailStreamBuf::readFromDevice() +{ + int c = std::char_traits<char>::eof(); + if (!_buffer.empty()) + { + c = _buffer[0]; + _buffer.erase(0, 1); + } + else + { + c = readOne(); + while (c != std::char_traits<char>::eof() && _state != ST_DATA && _state != ST_CR_LF_DOT_CR_LF) + c = readOne(); + if (!_buffer.empty()) + { + c = _buffer[0]; + _buffer.erase(0, 1); + } + } + return c; +} + + +int MailStreamBuf::readOne() +{ + int c = std::char_traits<char>::eof(); + if (_state != ST_CR_LF_DOT_CR_LF) + { + c = _pIstr->get(); + switch (c) + { + case '\r': + if (_state == ST_CR_LF_DOT) + _state = ST_CR_LF_DOT_CR; + else + _state = ST_CR; + break; + case '\n': + if (_state == ST_CR) + _state = ST_CR_LF; + else if (_state == ST_CR_LF_DOT_CR) + _state = ST_CR_LF_DOT_CR_LF; + else + _state = ST_DATA; + break; + case '.': + if (_state == ST_CR_LF) + _state = ST_CR_LF_DOT; + else if (_state == ST_CR_LF_DOT) + _state = ST_CR_LF_DOT_DOT; + else + _state = ST_DATA; + break; + default: + _state = ST_DATA; + } + if (_state == ST_CR_LF_DOT_DOT) + _state = ST_DATA; + else if (_state == ST_CR_LF_DOT_CR_LF) + _buffer.resize(_buffer.size() - 2); + else if (c != std::char_traits<char>::eof()) + _buffer += (char) c; + } + return c; +} + + +int MailStreamBuf::writeToDevice(char c) +{ + switch (c) + { + case '\r': + _state = ST_CR; + break; + case '\n': + if (_state == ST_CR) + _state = ST_CR_LF; + else + _state = ST_DATA; + break; + case '.': + if (_state == ST_CR_LF) + _state = ST_CR_LF_DOT; + else + _state = ST_DATA; + break; + default: + _state = ST_DATA; + } + if (_state == ST_DATA) + { + if (!_buffer.empty()) + { + _pOstr->write(_buffer.data(), (std::streamsize) _buffer.length()); + _buffer.clear(); + } + _pOstr->put(c); + } + else if (_state == ST_CR_LF_DOT) + { + // buffer contains one or more CR-LF pairs + _pOstr->write(_buffer.data(), (std::streamsize) _buffer.length()); + _pOstr->write("..", 2); + _state = ST_DATA; + _buffer.clear(); + } + else _buffer += c; + return charToInt(c); +} + + +MailIOS::MailIOS(std::istream& istr): _buf(istr) +{ + poco_ios_init(&_buf); +} + + +MailIOS::MailIOS(std::ostream& ostr): _buf(ostr) +{ + poco_ios_init(&_buf); +} + + +MailIOS::~MailIOS() +{ +} + + +void MailIOS::close() +{ + _buf.close(); +} + + +MailStreamBuf* MailIOS::rdbuf() +{ + return &_buf; +} + + +MailInputStream::MailInputStream(std::istream& istr): + MailIOS(istr), + std::istream(&_buf) +{ +} + + +MailInputStream::~MailInputStream() +{ +} + + +MailOutputStream::MailOutputStream(std::ostream& ostr): + MailIOS(ostr), + std::ostream(&_buf) +{ +} + + +MailOutputStream::~MailOutputStream() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/MediaType.cpp b/contrib/libs/poco/Net/src/MediaType.cpp index d8a23c9ef2..b4e9f5ea32 100644 --- a/contrib/libs/poco/Net/src/MediaType.cpp +++ b/contrib/libs/poco/Net/src/MediaType.cpp @@ -1,191 +1,191 @@ -// -// MediaType.cpp -// -// Library: Net -// Package: Messages -// Module: MediaType -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/MediaType.h" -#include "Poco/Net/MessageHeader.h" -#include "Poco/String.h" -#include "Poco/Ascii.h" -#include <algorithm> - - -using Poco::icompare; - - -namespace Poco { -namespace Net { - - -MediaType::MediaType(const std::string& mediaType) -{ - parse(mediaType); -} - - -MediaType::MediaType(const std::string& type, const std::string& subType): - _type(type), - _subType(subType) -{ -} - - -MediaType::MediaType(const MediaType& mediaType): - _type(mediaType._type), - _subType(mediaType._subType), - _parameters(mediaType._parameters) -{ -} - - -MediaType::~MediaType() -{ -} - - -MediaType& MediaType::operator = (const MediaType& mediaType) -{ - if (&mediaType != this) - { - _type = mediaType._type; - _subType = mediaType._subType; - _parameters = mediaType._parameters; - } - return *this; -} - - -MediaType& MediaType::operator = (const std::string& mediaType) -{ - parse(mediaType); - return *this; -} - - -void MediaType::swap(MediaType& mediaType) -{ - std::swap(_type, mediaType._type); - std::swap(_subType, mediaType._subType); - _parameters.swap(mediaType._parameters); -} - - -void MediaType::setType(const std::string& type) -{ - _type = type; -} - - -void MediaType::setSubType(const std::string& subType) -{ - _subType = subType; -} - - -void MediaType::setParameter(const std::string& name, const std::string& value) -{ - _parameters.set(name, value); -} - - -const std::string& MediaType::getParameter(const std::string& name) const -{ - return _parameters.get(name); -} - - -bool MediaType::hasParameter(const std::string& name) const -{ - return _parameters.has(name); -} - - -void MediaType::removeParameter(const std::string& name) -{ - _parameters.erase(name); -} - - -std::string MediaType::toString() const -{ - std::string result; - result.append(_type); - result.append("/"); - result.append(_subType); - for (NameValueCollection::ConstIterator it = _parameters.begin(); it != _parameters.end(); ++it) - { - result.append("; "); - result.append(it->first); - result.append("="); - MessageHeader::quote(it->second, result); - } - return result; -} - - -bool MediaType::matches(const MediaType& mediaType) const -{ - return matches(mediaType._type, mediaType._subType); -} - - -bool MediaType::matches(const std::string& type, const std::string& subType) const -{ - return icompare(_type, type) == 0 && icompare(_subType, subType) == 0; -} - - -bool MediaType::matches(const std::string& type) const -{ - return icompare(_type, type) == 0; -} - - -bool MediaType::matchesRange(const MediaType& mediaType) const -{ - return matchesRange(mediaType._type, mediaType._subType); -} - - -bool MediaType::matchesRange(const std::string& type, const std::string& subType) const -{ - if (_type == "*" || type == "*" || icompare(_type, type) == 0) - { - return _subType == "*" || subType == "*" || icompare(_subType, subType) == 0; - } - else return false; -} - - -bool MediaType::matchesRange(const std::string& type) const -{ - return _type == "*" || type == "*" || matches(type); -} - - -void MediaType::parse(const std::string& mediaType) -{ - _type.clear(); - _subType.clear(); - _parameters.clear(); - std::string::const_iterator it = mediaType.begin(); - std::string::const_iterator end = mediaType.end(); - while (it != end && Poco::Ascii::isSpace(*it)) ++it; - while (it != end && *it != '/') _type += *it++; - if (it != end) ++it; - while (it != end && *it != ';' && !Poco::Ascii::isSpace(*it)) _subType += *it++; - while (it != end && *it != ';') ++it; - MessageHeader::splitParameters(it, end, _parameters); -} - - -} } // namespace Poco::Net +// +// MediaType.cpp +// +// Library: Net +// Package: Messages +// Module: MediaType +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/MediaType.h" +#include "Poco/Net/MessageHeader.h" +#include "Poco/String.h" +#include "Poco/Ascii.h" +#include <algorithm> + + +using Poco::icompare; + + +namespace Poco { +namespace Net { + + +MediaType::MediaType(const std::string& mediaType) +{ + parse(mediaType); +} + + +MediaType::MediaType(const std::string& type, const std::string& subType): + _type(type), + _subType(subType) +{ +} + + +MediaType::MediaType(const MediaType& mediaType): + _type(mediaType._type), + _subType(mediaType._subType), + _parameters(mediaType._parameters) +{ +} + + +MediaType::~MediaType() +{ +} + + +MediaType& MediaType::operator = (const MediaType& mediaType) +{ + if (&mediaType != this) + { + _type = mediaType._type; + _subType = mediaType._subType; + _parameters = mediaType._parameters; + } + return *this; +} + + +MediaType& MediaType::operator = (const std::string& mediaType) +{ + parse(mediaType); + return *this; +} + + +void MediaType::swap(MediaType& mediaType) +{ + std::swap(_type, mediaType._type); + std::swap(_subType, mediaType._subType); + _parameters.swap(mediaType._parameters); +} + + +void MediaType::setType(const std::string& type) +{ + _type = type; +} + + +void MediaType::setSubType(const std::string& subType) +{ + _subType = subType; +} + + +void MediaType::setParameter(const std::string& name, const std::string& value) +{ + _parameters.set(name, value); +} + + +const std::string& MediaType::getParameter(const std::string& name) const +{ + return _parameters.get(name); +} + + +bool MediaType::hasParameter(const std::string& name) const +{ + return _parameters.has(name); +} + + +void MediaType::removeParameter(const std::string& name) +{ + _parameters.erase(name); +} + + +std::string MediaType::toString() const +{ + std::string result; + result.append(_type); + result.append("/"); + result.append(_subType); + for (NameValueCollection::ConstIterator it = _parameters.begin(); it != _parameters.end(); ++it) + { + result.append("; "); + result.append(it->first); + result.append("="); + MessageHeader::quote(it->second, result); + } + return result; +} + + +bool MediaType::matches(const MediaType& mediaType) const +{ + return matches(mediaType._type, mediaType._subType); +} + + +bool MediaType::matches(const std::string& type, const std::string& subType) const +{ + return icompare(_type, type) == 0 && icompare(_subType, subType) == 0; +} + + +bool MediaType::matches(const std::string& type) const +{ + return icompare(_type, type) == 0; +} + + +bool MediaType::matchesRange(const MediaType& mediaType) const +{ + return matchesRange(mediaType._type, mediaType._subType); +} + + +bool MediaType::matchesRange(const std::string& type, const std::string& subType) const +{ + if (_type == "*" || type == "*" || icompare(_type, type) == 0) + { + return _subType == "*" || subType == "*" || icompare(_subType, subType) == 0; + } + else return false; +} + + +bool MediaType::matchesRange(const std::string& type) const +{ + return _type == "*" || type == "*" || matches(type); +} + + +void MediaType::parse(const std::string& mediaType) +{ + _type.clear(); + _subType.clear(); + _parameters.clear(); + std::string::const_iterator it = mediaType.begin(); + std::string::const_iterator end = mediaType.end(); + while (it != end && Poco::Ascii::isSpace(*it)) ++it; + while (it != end && *it != '/') _type += *it++; + if (it != end) ++it; + while (it != end && *it != ';' && !Poco::Ascii::isSpace(*it)) _subType += *it++; + while (it != end && *it != ';') ++it; + MessageHeader::splitParameters(it, end, _parameters); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/MessageHeader.cpp b/contrib/libs/poco/Net/src/MessageHeader.cpp index a684b3cf5d..d98531487b 100644 --- a/contrib/libs/poco/Net/src/MessageHeader.cpp +++ b/contrib/libs/poco/Net/src/MessageHeader.cpp @@ -1,394 +1,394 @@ -// -// MessageHeader.cpp -// -// Library: Net -// Package: Messages -// Module: MessageHeader -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/MessageHeader.h" -#include "Poco/Net/NetException.h" -#include "Poco/String.h" -#include "Poco/Ascii.h" -#include "Poco/TextConverter.h" -#include "Poco/StringTokenizer.h" -#include "Poco/Base64Decoder.h" -#include "Poco/UTF8Encoding.h" -#include <sstream> - - -namespace Poco { -namespace Net { - - -MessageHeader::MessageHeader(): - _fieldLimit(DFL_FIELD_LIMIT) -{ -} - - -MessageHeader::MessageHeader(const MessageHeader& messageHeader): - NameValueCollection(messageHeader), - _fieldLimit(DFL_FIELD_LIMIT) -{ -} - - -MessageHeader::~MessageHeader() -{ -} - - -MessageHeader& MessageHeader::operator = (const MessageHeader& messageHeader) -{ - NameValueCollection::operator = (messageHeader); - return *this; -} - - -void MessageHeader::write(std::ostream& ostr) const -{ - NameValueCollection::ConstIterator it = begin(); - while (it != end()) - { - ostr << it->first << ": " << it->second << "\r\n"; - ++it; - } -} - - -void MessageHeader::read(std::istream& istr) -{ - static const int eof = std::char_traits<char>::eof(); - std::streambuf& buf = *istr.rdbuf(); - - std::string name; - std::string value; - name.reserve(32); - value.reserve(64); - int ch = buf.sbumpc(); - int fields = 0; - while (ch != eof && ch != '\r' && ch != '\n') - { - if (_fieldLimit > 0 && fields == _fieldLimit) - throw MessageException("Too many header fields"); - name.clear(); - value.clear(); - while (ch != eof && ch != ':' && ch != '\n' && name.length() < MAX_NAME_LENGTH) { name += static_cast<char>(ch); ch = buf.sbumpc(); } - if (ch == '\n') { ch = buf.sbumpc(); continue; } // ignore invalid header lines - if (ch != ':') throw MessageException("Field name too long/no colon found"); - if (ch != eof) ch = buf.sbumpc(); // ':' - while (ch != eof && Poco::Ascii::isSpace(ch) && ch != '\r' && ch != '\n') ch = buf.sbumpc(); - while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += static_cast<char>(ch); ch = buf.sbumpc(); } - if (ch == '\r') ch = buf.sbumpc(); - if (ch == '\n') - ch = buf.sbumpc(); - else if (ch != eof) - throw MessageException("Field value too long/no CRLF found"); - while (ch == ' ' || ch == '\t') // folding - { - while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += static_cast<char>(ch); ch = buf.sbumpc(); } - if (ch == '\r') ch = buf.sbumpc(); - if (ch == '\n') - ch = buf.sbumpc(); - else if (ch != eof) - throw MessageException("Folded field value too long/no CRLF found"); - } - Poco::trimRightInPlace(value); - add(name, decodeWord(value)); - ++fields; - } - istr.putback(static_cast<char>(ch)); -} - - -int MessageHeader::getFieldLimit() const -{ - return _fieldLimit; -} - - -void MessageHeader::setFieldLimit(int limit) -{ - poco_assert (limit >= 0); - - _fieldLimit = limit; -} - - -bool MessageHeader::hasToken(const std::string& fieldName, const std::string& token) const -{ - std::string field = get(fieldName, ""); - std::vector<std::string> tokens; - splitElements(field, tokens, true); - for (std::vector<std::string>::const_iterator it = tokens.begin(); it != tokens.end(); ++it) - { - if (Poco::icompare(*it, token) == 0) - return true; - } - return false; -} - - -void MessageHeader::splitElements(const std::string& s, std::vector<std::string>& elements, bool ignoreEmpty) -{ - elements.clear(); - std::string::const_iterator it = s.begin(); - std::string::const_iterator end = s.end(); - std::string elem; - elem.reserve(64); - while (it != end) - { - if (*it == '"') - { - elem += *it++; - while (it != end && *it != '"') - { - if (*it == '\\') - { - ++it; - if (it != end) elem += *it++; - } - else elem += *it++; - } - if (it != end) elem += *it++; - } - else if (*it == '\\') - { - ++it; - if (it != end) elem += *it++; - } - else if (*it == ',') - { - Poco::trimInPlace(elem); - if (!ignoreEmpty || !elem.empty()) - elements.push_back(elem); - elem.clear(); - ++it; - } - else elem += *it++; - } - if (!elem.empty()) - { - Poco::trimInPlace(elem); - if (!ignoreEmpty || !elem.empty()) - elements.push_back(elem); - } -} - - -void MessageHeader::splitParameters(const std::string& s, std::string& value, NameValueCollection& parameters) -{ - value.clear(); - parameters.clear(); - std::string::const_iterator it = s.begin(); - std::string::const_iterator end = s.end(); - while (it != end && Poco::Ascii::isSpace(*it)) ++it; - while (it != end && *it != ';') value += *it++; - Poco::trimRightInPlace(value); - if (it != end) ++it; - splitParameters(it, end, parameters); -} - - -void MessageHeader::splitParameters(const std::string::const_iterator& begin, const std::string::const_iterator& end, NameValueCollection& parameters) -{ - std::string pname; - std::string pvalue; - pname.reserve(32); - pvalue.reserve(64); - std::string::const_iterator it = begin; - while (it != end) - { - pname.clear(); - pvalue.clear(); - while (it != end && Poco::Ascii::isSpace(*it)) ++it; - while (it != end && *it != '=' && *it != ';') pname += *it++; - Poco::trimRightInPlace(pname); - if (it != end && *it != ';') ++it; - while (it != end && Poco::Ascii::isSpace(*it)) ++it; - while (it != end && *it != ';') - { - if (*it == '"') - { - ++it; - while (it != end && *it != '"') - { - if (*it == '\\') - { - ++it; - if (it != end) pvalue += *it++; - } - else pvalue += *it++; - } - if (it != end) ++it; - } - else if (*it == '\\') - { - ++it; - if (it != end) pvalue += *it++; - } - else pvalue += *it++; - } - Poco::trimRightInPlace(pvalue); - if (!pname.empty()) parameters.add(pname, pvalue); - if (it != end) ++it; - } -} - - -void MessageHeader::quote(const std::string& value, std::string& result, bool allowSpace) -{ - bool mustQuote = false; - for (std::string::const_iterator it = value.begin(); !mustQuote && it != value.end(); ++it) - { - if (!Poco::Ascii::isAlphaNumeric(*it) && *it != '.' && *it != '_' && *it != '-' && !(Poco::Ascii::isSpace(*it) && allowSpace)) - mustQuote = true; - } - if (mustQuote) result += '"'; - result.append(value); - if (mustQuote) result += '"'; -} - - -void MessageHeader::decodeRFC2047(const std::string& ins, std::string& outs, const std::string& charset_to) -{ - std::string tempout; - StringTokenizer tokens(ins, "?"); - - std::string charset = toUpper(tokens[0]); - std::string encoding = toUpper(tokens[1]); - std::string text = tokens[2]; - - std::istringstream istr(text); - - if (encoding == "B") - { - // Base64 encoding. - Base64Decoder decoder(istr); - for (char c; decoder.get(c); tempout += c) {} - } - else if (encoding == "Q") - { - // Quoted encoding. - for (char c; istr.get(c);) - { - if (c == '_') - { - //RFC 2047 _ is a space. - tempout += " "; - continue; - } - - // FIXME: check that we have enought chars- - if (c == '=') - { - // The next two chars are hex representation of the complete byte. - std::string hex; - for (int i = 0; i < 2; i++) - { - istr.get(c); - hex += c; - } - hex = toUpper(hex); - tempout += (char)(int)strtol(hex.c_str(), 0, 16); - continue; - } - tempout += c; - } - } - else - { - // Wrong encoding - outs = ins; - return; - } - - // convert to the right charset. - if (charset != charset_to) - { - try - { - TextEncoding& enc = TextEncoding::byName(charset); - TextEncoding& dec = TextEncoding::byName(charset_to); - TextConverter converter(enc, dec); - converter.convert(tempout, outs); - } - catch (...) - { - // FIXME: Unsuported encoding... - outs = tempout; - } - } - else - { - // Not conversion necesary. - outs = tempout; - } -} - - -std::string MessageHeader::decodeWord(const std::string& text, const std::string& charset) -{ - std::string outs, tmp = text; - do { - std::string tmp2; - // find the begining of the next rfc2047 chunk - size_t pos = tmp.find("=?"); - if (pos == std::string::npos) { - // No more found, return - outs += tmp; - break; - } - - // check if there are standar text before the rfc2047 chunk, and if so, copy it. - if (pos > 0) { - outs += tmp.substr(0, pos); - } - - // remove text already copied. - tmp = tmp.substr(pos + 2); - - // find the first separator - size_t pos1 = tmp.find("?"); - if (pos1 == std::string::npos) { - // not found. - outs += tmp; - break; - } - - // find the second separator - size_t pos2 = tmp.find("?", pos1 + 1); - if (pos2 == std::string::npos) { - // not found - outs += tmp; - break; - } - - // find the end of the actual rfc2047 chunk - size_t pos3 = tmp.find("?=", pos2 + 1); - if (pos3 == std::string::npos) { - // not found. - outs += tmp; - break; - - } - // At this place, there are a valid rfc2047 chunk, so decode and copy the result. - decodeRFC2047(tmp.substr(0, pos3), tmp2, charset); - outs += tmp2; - - // Jump at the rest of the string and repeat the whole process. - tmp = tmp.substr(pos3 + 2); - } while (true); - - return outs; -} - - -} } // namespace Poco::Net +// +// MessageHeader.cpp +// +// Library: Net +// Package: Messages +// Module: MessageHeader +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/MessageHeader.h" +#include "Poco/Net/NetException.h" +#include "Poco/String.h" +#include "Poco/Ascii.h" +#include "Poco/TextConverter.h" +#include "Poco/StringTokenizer.h" +#include "Poco/Base64Decoder.h" +#include "Poco/UTF8Encoding.h" +#include <sstream> + + +namespace Poco { +namespace Net { + + +MessageHeader::MessageHeader(): + _fieldLimit(DFL_FIELD_LIMIT) +{ +} + + +MessageHeader::MessageHeader(const MessageHeader& messageHeader): + NameValueCollection(messageHeader), + _fieldLimit(DFL_FIELD_LIMIT) +{ +} + + +MessageHeader::~MessageHeader() +{ +} + + +MessageHeader& MessageHeader::operator = (const MessageHeader& messageHeader) +{ + NameValueCollection::operator = (messageHeader); + return *this; +} + + +void MessageHeader::write(std::ostream& ostr) const +{ + NameValueCollection::ConstIterator it = begin(); + while (it != end()) + { + ostr << it->first << ": " << it->second << "\r\n"; + ++it; + } +} + + +void MessageHeader::read(std::istream& istr) +{ + static const int eof = std::char_traits<char>::eof(); + std::streambuf& buf = *istr.rdbuf(); + + std::string name; + std::string value; + name.reserve(32); + value.reserve(64); + int ch = buf.sbumpc(); + int fields = 0; + while (ch != eof && ch != '\r' && ch != '\n') + { + if (_fieldLimit > 0 && fields == _fieldLimit) + throw MessageException("Too many header fields"); + name.clear(); + value.clear(); + while (ch != eof && ch != ':' && ch != '\n' && name.length() < MAX_NAME_LENGTH) { name += static_cast<char>(ch); ch = buf.sbumpc(); } + if (ch == '\n') { ch = buf.sbumpc(); continue; } // ignore invalid header lines + if (ch != ':') throw MessageException("Field name too long/no colon found"); + if (ch != eof) ch = buf.sbumpc(); // ':' + while (ch != eof && Poco::Ascii::isSpace(ch) && ch != '\r' && ch != '\n') ch = buf.sbumpc(); + while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += static_cast<char>(ch); ch = buf.sbumpc(); } + if (ch == '\r') ch = buf.sbumpc(); + if (ch == '\n') + ch = buf.sbumpc(); + else if (ch != eof) + throw MessageException("Field value too long/no CRLF found"); + while (ch == ' ' || ch == '\t') // folding + { + while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += static_cast<char>(ch); ch = buf.sbumpc(); } + if (ch == '\r') ch = buf.sbumpc(); + if (ch == '\n') + ch = buf.sbumpc(); + else if (ch != eof) + throw MessageException("Folded field value too long/no CRLF found"); + } + Poco::trimRightInPlace(value); + add(name, decodeWord(value)); + ++fields; + } + istr.putback(static_cast<char>(ch)); +} + + +int MessageHeader::getFieldLimit() const +{ + return _fieldLimit; +} + + +void MessageHeader::setFieldLimit(int limit) +{ + poco_assert (limit >= 0); + + _fieldLimit = limit; +} + + +bool MessageHeader::hasToken(const std::string& fieldName, const std::string& token) const +{ + std::string field = get(fieldName, ""); + std::vector<std::string> tokens; + splitElements(field, tokens, true); + for (std::vector<std::string>::const_iterator it = tokens.begin(); it != tokens.end(); ++it) + { + if (Poco::icompare(*it, token) == 0) + return true; + } + return false; +} + + +void MessageHeader::splitElements(const std::string& s, std::vector<std::string>& elements, bool ignoreEmpty) +{ + elements.clear(); + std::string::const_iterator it = s.begin(); + std::string::const_iterator end = s.end(); + std::string elem; + elem.reserve(64); + while (it != end) + { + if (*it == '"') + { + elem += *it++; + while (it != end && *it != '"') + { + if (*it == '\\') + { + ++it; + if (it != end) elem += *it++; + } + else elem += *it++; + } + if (it != end) elem += *it++; + } + else if (*it == '\\') + { + ++it; + if (it != end) elem += *it++; + } + else if (*it == ',') + { + Poco::trimInPlace(elem); + if (!ignoreEmpty || !elem.empty()) + elements.push_back(elem); + elem.clear(); + ++it; + } + else elem += *it++; + } + if (!elem.empty()) + { + Poco::trimInPlace(elem); + if (!ignoreEmpty || !elem.empty()) + elements.push_back(elem); + } +} + + +void MessageHeader::splitParameters(const std::string& s, std::string& value, NameValueCollection& parameters) +{ + value.clear(); + parameters.clear(); + std::string::const_iterator it = s.begin(); + std::string::const_iterator end = s.end(); + while (it != end && Poco::Ascii::isSpace(*it)) ++it; + while (it != end && *it != ';') value += *it++; + Poco::trimRightInPlace(value); + if (it != end) ++it; + splitParameters(it, end, parameters); +} + + +void MessageHeader::splitParameters(const std::string::const_iterator& begin, const std::string::const_iterator& end, NameValueCollection& parameters) +{ + std::string pname; + std::string pvalue; + pname.reserve(32); + pvalue.reserve(64); + std::string::const_iterator it = begin; + while (it != end) + { + pname.clear(); + pvalue.clear(); + while (it != end && Poco::Ascii::isSpace(*it)) ++it; + while (it != end && *it != '=' && *it != ';') pname += *it++; + Poco::trimRightInPlace(pname); + if (it != end && *it != ';') ++it; + while (it != end && Poco::Ascii::isSpace(*it)) ++it; + while (it != end && *it != ';') + { + if (*it == '"') + { + ++it; + while (it != end && *it != '"') + { + if (*it == '\\') + { + ++it; + if (it != end) pvalue += *it++; + } + else pvalue += *it++; + } + if (it != end) ++it; + } + else if (*it == '\\') + { + ++it; + if (it != end) pvalue += *it++; + } + else pvalue += *it++; + } + Poco::trimRightInPlace(pvalue); + if (!pname.empty()) parameters.add(pname, pvalue); + if (it != end) ++it; + } +} + + +void MessageHeader::quote(const std::string& value, std::string& result, bool allowSpace) +{ + bool mustQuote = false; + for (std::string::const_iterator it = value.begin(); !mustQuote && it != value.end(); ++it) + { + if (!Poco::Ascii::isAlphaNumeric(*it) && *it != '.' && *it != '_' && *it != '-' && !(Poco::Ascii::isSpace(*it) && allowSpace)) + mustQuote = true; + } + if (mustQuote) result += '"'; + result.append(value); + if (mustQuote) result += '"'; +} + + +void MessageHeader::decodeRFC2047(const std::string& ins, std::string& outs, const std::string& charset_to) +{ + std::string tempout; + StringTokenizer tokens(ins, "?"); + + std::string charset = toUpper(tokens[0]); + std::string encoding = toUpper(tokens[1]); + std::string text = tokens[2]; + + std::istringstream istr(text); + + if (encoding == "B") + { + // Base64 encoding. + Base64Decoder decoder(istr); + for (char c; decoder.get(c); tempout += c) {} + } + else if (encoding == "Q") + { + // Quoted encoding. + for (char c; istr.get(c);) + { + if (c == '_') + { + //RFC 2047 _ is a space. + tempout += " "; + continue; + } + + // FIXME: check that we have enought chars- + if (c == '=') + { + // The next two chars are hex representation of the complete byte. + std::string hex; + for (int i = 0; i < 2; i++) + { + istr.get(c); + hex += c; + } + hex = toUpper(hex); + tempout += (char)(int)strtol(hex.c_str(), 0, 16); + continue; + } + tempout += c; + } + } + else + { + // Wrong encoding + outs = ins; + return; + } + + // convert to the right charset. + if (charset != charset_to) + { + try + { + TextEncoding& enc = TextEncoding::byName(charset); + TextEncoding& dec = TextEncoding::byName(charset_to); + TextConverter converter(enc, dec); + converter.convert(tempout, outs); + } + catch (...) + { + // FIXME: Unsuported encoding... + outs = tempout; + } + } + else + { + // Not conversion necesary. + outs = tempout; + } +} + + +std::string MessageHeader::decodeWord(const std::string& text, const std::string& charset) +{ + std::string outs, tmp = text; + do { + std::string tmp2; + // find the begining of the next rfc2047 chunk + size_t pos = tmp.find("=?"); + if (pos == std::string::npos) { + // No more found, return + outs += tmp; + break; + } + + // check if there are standar text before the rfc2047 chunk, and if so, copy it. + if (pos > 0) { + outs += tmp.substr(0, pos); + } + + // remove text already copied. + tmp = tmp.substr(pos + 2); + + // find the first separator + size_t pos1 = tmp.find("?"); + if (pos1 == std::string::npos) { + // not found. + outs += tmp; + break; + } + + // find the second separator + size_t pos2 = tmp.find("?", pos1 + 1); + if (pos2 == std::string::npos) { + // not found + outs += tmp; + break; + } + + // find the end of the actual rfc2047 chunk + size_t pos3 = tmp.find("?=", pos2 + 1); + if (pos3 == std::string::npos) { + // not found. + outs += tmp; + break; + + } + // At this place, there are a valid rfc2047 chunk, so decode and copy the result. + decodeRFC2047(tmp.substr(0, pos3), tmp2, charset); + outs += tmp2; + + // Jump at the rest of the string and repeat the whole process. + tmp = tmp.substr(pos3 + 2); + } while (true); + + return outs; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/MulticastSocket.cpp b/contrib/libs/poco/Net/src/MulticastSocket.cpp index e302f6a818..5a4eec3028 100644 --- a/contrib/libs/poco/Net/src/MulticastSocket.cpp +++ b/contrib/libs/poco/Net/src/MulticastSocket.cpp @@ -1,289 +1,289 @@ -// -// MulticastSocket.cpp -// -// Library: Net -// Package: Sockets -// Module: MulticastSocket -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/MulticastSocket.h" - - -#ifdef POCO_NET_HAS_INTERFACE - - -#include "Poco/Net/NetException.h" -#include <cstring> - - -#if defined(hpux) && defined(_XOPEN_SOURCE_EXTENDED) && defined(POCO_HPUX_IP_MREQ_HACK) -// netinet/in.h does not define struct ip_mreq if -// _XOPEN_SOURCE_EXTENDED is #define'd in HP-UX 11.x -// versions prior to 11.30. Compile with -DPOCO_HPUX_IP_MREQ_HACK -// if you experience problems. -struct ip_mreq -{ - struct in_addr imr_multiaddr; - struct in_addr imr_interface; -}; -#endif - - -// some Unix variants don't have IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP -#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) -#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP -#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP -#endif - - -namespace Poco { -namespace Net { - - -MulticastSocket::MulticastSocket() -{ -} - - -MulticastSocket::MulticastSocket(SocketAddress::Family family): DatagramSocket(family) -{ -#if defined(POCO_OS_FAMILY_UNIX) - if (family == SocketAddress::UNIX_LOCAL) - throw Poco::InvalidArgumentException("Cannot create a MulticastSocket with UNIX_LOCAL socket"); -#endif -} - - -MulticastSocket::MulticastSocket(const SocketAddress& address, bool reuseAddress): DatagramSocket(address, reuseAddress) -{ -} - - -MulticastSocket::MulticastSocket(const Socket& socket): DatagramSocket(socket) -{ -} - - -MulticastSocket::~MulticastSocket() -{ -} - - -MulticastSocket& MulticastSocket::operator = (const Socket& socket) -{ - DatagramSocket::operator = (socket); - return *this; -} - - -void MulticastSocket::setInterface(const NetworkInterface& interfc) -{ - if (address().family() == SocketAddress::IPv4) - { - impl()->setOption(IPPROTO_IP, IP_MULTICAST_IF, interfc.firstAddress(IPAddress::IPv4)); - } -#if defined(POCO_HAVE_IPv6) - else if (address().family() == SocketAddress::IPv6) - { - impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, interfc.index()); - } -#endif - else throw UnsupportedFamilyException("Unknown or unsupported socket family."); -} - - -NetworkInterface MulticastSocket::getInterface() const -{ - try - { - IPAddress addr; - impl()->getOption(IPPROTO_IP, IP_MULTICAST_IF, addr); - return NetworkInterface::forAddress(addr); - } - catch (Poco::Exception&) - { -#if defined(POCO_HAVE_IPv6) - int ix; - impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, ix); - return NetworkInterface::forIndex(ix); -#else - throw; -#endif - } -} - - -void MulticastSocket::setLoopback(bool flag) -{ - if (address().af() == AF_INET) - { - unsigned char uflag = flag ? 1 : 0; - impl()->setOption(IPPROTO_IP, IP_MULTICAST_LOOP, uflag); - } - else - { -#if defined(POCO_HAVE_IPv6) - unsigned uflag = flag ? 1 : 0; - impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_LOOP, uflag); -#endif - } -} - - -bool MulticastSocket::getLoopback() const -{ - bool flag = false; - if (address().af() == AF_INET) - { - unsigned char uflag; - impl()->getOption(IPPROTO_IP, IP_MULTICAST_LOOP, uflag); - flag = uflag != 0; - } - else - { -#if defined(POCO_HAVE_IPv6) - unsigned uflag; - impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_LOOP, uflag); - flag = uflag != 0; -#endif - } - return flag; -} - - -void MulticastSocket::setTimeToLive(unsigned value) -{ - if (address().af() == AF_INET) - { - unsigned char ttl = (unsigned char) value; - impl()->setOption(IPPROTO_IP, IP_MULTICAST_TTL, ttl); - } - else - { -#if defined(POCO_HAVE_IPv6) - impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_HOPS, value); -#endif - } -} - - -unsigned MulticastSocket::getTimeToLive() const -{ - unsigned ttl(0); - if (address().af() == AF_INET) - { - unsigned char cttl; - impl()->getOption(IPPROTO_IP, IP_MULTICAST_TTL, cttl); - ttl = cttl; - } - else - { -#if defined(POCO_HAVE_IPv6) - impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ttl); -#endif - } - return ttl; -} - - -void MulticastSocket::joinGroup(const IPAddress& groupAddress) -{ - joinGroup(groupAddress, findFirstInterface(groupAddress)); -} - - -void MulticastSocket::joinGroup(const IPAddress& groupAddress, const NetworkInterface& interfc) -{ - if (groupAddress.af() == AF_INET) - { - struct ip_mreq mr; - std::memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length()); - std::memcpy(&mr.imr_interface, interfc.firstAddress(IPAddress::IPv4).addr(), interfc.firstAddress(IPAddress::IPv4).length()); - impl()->setRawOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)); - } - else - { -#if defined(POCO_HAVE_IPv6) - struct ipv6_mreq mr; - std::memcpy(&mr.ipv6mr_multiaddr, groupAddress.addr(), groupAddress.length()); - mr.ipv6mr_interface = interfc.index(); - impl()->setRawOption(IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr, sizeof(mr)); -#endif - } -} - - -NetworkInterface MulticastSocket::findFirstInterface(const IPAddress& groupAddress) -{ - NetworkInterface::Map m = NetworkInterface::map(); - if (groupAddress.family() == IPAddress::IPv4) - { - for (NetworkInterface::Map::const_iterator it = m.begin(); it != m.end(); ++it) - { - if (it->second.supportsIPv4() && - it->second.firstAddress(IPAddress::IPv4).isUnicast() && - !it->second.isLoopback() && - !it->second.isPointToPoint()) - { - return it->second; - } - } - } -#ifdef POCO_HAVE_IPv6 - else if (groupAddress.family() == IPAddress::IPv6) - { - for (NetworkInterface::Map::const_iterator it = m.begin(); it != m.end(); ++it) - { - if (it->second.supportsIPv6() && - it->second.firstAddress(IPAddress::IPv6).isUnicast() && - !it->second.isLoopback() && - !it->second.isPointToPoint()) - { - return it->second; - } - } - } -#endif // POCO_HAVE_IPv6 - - throw NotFoundException("No multicast-eligible network interface found."); -} - - -void MulticastSocket::leaveGroup(const IPAddress& groupAddress) -{ - NetworkInterface intf; - leaveGroup(groupAddress, intf); -} - - -void MulticastSocket::leaveGroup(const IPAddress& groupAddress, const NetworkInterface& interfc) -{ - if (groupAddress.af() == AF_INET) - { - struct ip_mreq mr; - std::memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length()); - std::memcpy(&mr.imr_interface, interfc.firstAddress(IPAddress::IPv4).addr(), interfc.firstAddress(IPAddress::IPv4).length()); - impl()->setRawOption(IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)); - } - else - { -#if defined(POCO_HAVE_IPv6) - struct ipv6_mreq mr; - std::memcpy(&mr.ipv6mr_multiaddr, groupAddress.addr(), groupAddress.length()); - mr.ipv6mr_interface = interfc.index(); - impl()->setRawOption(IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mr, sizeof(mr)); -#endif - } -} - - -} } // namespace Poco::Net - - -#endif // POCO_NET_HAS_INTERFACE +// +// MulticastSocket.cpp +// +// Library: Net +// Package: Sockets +// Module: MulticastSocket +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/MulticastSocket.h" + + +#ifdef POCO_NET_HAS_INTERFACE + + +#include "Poco/Net/NetException.h" +#include <cstring> + + +#if defined(hpux) && defined(_XOPEN_SOURCE_EXTENDED) && defined(POCO_HPUX_IP_MREQ_HACK) +// netinet/in.h does not define struct ip_mreq if +// _XOPEN_SOURCE_EXTENDED is #define'd in HP-UX 11.x +// versions prior to 11.30. Compile with -DPOCO_HPUX_IP_MREQ_HACK +// if you experience problems. +struct ip_mreq +{ + struct in_addr imr_multiaddr; + struct in_addr imr_interface; +}; +#endif + + +// some Unix variants don't have IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP +#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) +#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP +#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP +#endif + + +namespace Poco { +namespace Net { + + +MulticastSocket::MulticastSocket() +{ +} + + +MulticastSocket::MulticastSocket(SocketAddress::Family family): DatagramSocket(family) +{ +#if defined(POCO_OS_FAMILY_UNIX) + if (family == SocketAddress::UNIX_LOCAL) + throw Poco::InvalidArgumentException("Cannot create a MulticastSocket with UNIX_LOCAL socket"); +#endif +} + + +MulticastSocket::MulticastSocket(const SocketAddress& address, bool reuseAddress): DatagramSocket(address, reuseAddress) +{ +} + + +MulticastSocket::MulticastSocket(const Socket& socket): DatagramSocket(socket) +{ +} + + +MulticastSocket::~MulticastSocket() +{ +} + + +MulticastSocket& MulticastSocket::operator = (const Socket& socket) +{ + DatagramSocket::operator = (socket); + return *this; +} + + +void MulticastSocket::setInterface(const NetworkInterface& interfc) +{ + if (address().family() == SocketAddress::IPv4) + { + impl()->setOption(IPPROTO_IP, IP_MULTICAST_IF, interfc.firstAddress(IPAddress::IPv4)); + } +#if defined(POCO_HAVE_IPv6) + else if (address().family() == SocketAddress::IPv6) + { + impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, interfc.index()); + } +#endif + else throw UnsupportedFamilyException("Unknown or unsupported socket family."); +} + + +NetworkInterface MulticastSocket::getInterface() const +{ + try + { + IPAddress addr; + impl()->getOption(IPPROTO_IP, IP_MULTICAST_IF, addr); + return NetworkInterface::forAddress(addr); + } + catch (Poco::Exception&) + { +#if defined(POCO_HAVE_IPv6) + int ix; + impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, ix); + return NetworkInterface::forIndex(ix); +#else + throw; +#endif + } +} + + +void MulticastSocket::setLoopback(bool flag) +{ + if (address().af() == AF_INET) + { + unsigned char uflag = flag ? 1 : 0; + impl()->setOption(IPPROTO_IP, IP_MULTICAST_LOOP, uflag); + } + else + { +#if defined(POCO_HAVE_IPv6) + unsigned uflag = flag ? 1 : 0; + impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_LOOP, uflag); +#endif + } +} + + +bool MulticastSocket::getLoopback() const +{ + bool flag = false; + if (address().af() == AF_INET) + { + unsigned char uflag; + impl()->getOption(IPPROTO_IP, IP_MULTICAST_LOOP, uflag); + flag = uflag != 0; + } + else + { +#if defined(POCO_HAVE_IPv6) + unsigned uflag; + impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_LOOP, uflag); + flag = uflag != 0; +#endif + } + return flag; +} + + +void MulticastSocket::setTimeToLive(unsigned value) +{ + if (address().af() == AF_INET) + { + unsigned char ttl = (unsigned char) value; + impl()->setOption(IPPROTO_IP, IP_MULTICAST_TTL, ttl); + } + else + { +#if defined(POCO_HAVE_IPv6) + impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_HOPS, value); +#endif + } +} + + +unsigned MulticastSocket::getTimeToLive() const +{ + unsigned ttl(0); + if (address().af() == AF_INET) + { + unsigned char cttl; + impl()->getOption(IPPROTO_IP, IP_MULTICAST_TTL, cttl); + ttl = cttl; + } + else + { +#if defined(POCO_HAVE_IPv6) + impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ttl); +#endif + } + return ttl; +} + + +void MulticastSocket::joinGroup(const IPAddress& groupAddress) +{ + joinGroup(groupAddress, findFirstInterface(groupAddress)); +} + + +void MulticastSocket::joinGroup(const IPAddress& groupAddress, const NetworkInterface& interfc) +{ + if (groupAddress.af() == AF_INET) + { + struct ip_mreq mr; + std::memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length()); + std::memcpy(&mr.imr_interface, interfc.firstAddress(IPAddress::IPv4).addr(), interfc.firstAddress(IPAddress::IPv4).length()); + impl()->setRawOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)); + } + else + { +#if defined(POCO_HAVE_IPv6) + struct ipv6_mreq mr; + std::memcpy(&mr.ipv6mr_multiaddr, groupAddress.addr(), groupAddress.length()); + mr.ipv6mr_interface = interfc.index(); + impl()->setRawOption(IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr, sizeof(mr)); +#endif + } +} + + +NetworkInterface MulticastSocket::findFirstInterface(const IPAddress& groupAddress) +{ + NetworkInterface::Map m = NetworkInterface::map(); + if (groupAddress.family() == IPAddress::IPv4) + { + for (NetworkInterface::Map::const_iterator it = m.begin(); it != m.end(); ++it) + { + if (it->second.supportsIPv4() && + it->second.firstAddress(IPAddress::IPv4).isUnicast() && + !it->second.isLoopback() && + !it->second.isPointToPoint()) + { + return it->second; + } + } + } +#ifdef POCO_HAVE_IPv6 + else if (groupAddress.family() == IPAddress::IPv6) + { + for (NetworkInterface::Map::const_iterator it = m.begin(); it != m.end(); ++it) + { + if (it->second.supportsIPv6() && + it->second.firstAddress(IPAddress::IPv6).isUnicast() && + !it->second.isLoopback() && + !it->second.isPointToPoint()) + { + return it->second; + } + } + } +#endif // POCO_HAVE_IPv6 + + throw NotFoundException("No multicast-eligible network interface found."); +} + + +void MulticastSocket::leaveGroup(const IPAddress& groupAddress) +{ + NetworkInterface intf; + leaveGroup(groupAddress, intf); +} + + +void MulticastSocket::leaveGroup(const IPAddress& groupAddress, const NetworkInterface& interfc) +{ + if (groupAddress.af() == AF_INET) + { + struct ip_mreq mr; + std::memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length()); + std::memcpy(&mr.imr_interface, interfc.firstAddress(IPAddress::IPv4).addr(), interfc.firstAddress(IPAddress::IPv4).length()); + impl()->setRawOption(IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)); + } + else + { +#if defined(POCO_HAVE_IPv6) + struct ipv6_mreq mr; + std::memcpy(&mr.ipv6mr_multiaddr, groupAddress.addr(), groupAddress.length()); + mr.ipv6mr_interface = interfc.index(); + impl()->setRawOption(IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mr, sizeof(mr)); +#endif + } +} + + +} } // namespace Poco::Net + + +#endif // POCO_NET_HAS_INTERFACE diff --git a/contrib/libs/poco/Net/src/MultipartReader.cpp b/contrib/libs/poco/Net/src/MultipartReader.cpp index a41b2d61c5..072de3d5ca 100644 --- a/contrib/libs/poco/Net/src/MultipartReader.cpp +++ b/contrib/libs/poco/Net/src/MultipartReader.cpp @@ -1,310 +1,310 @@ -// -// MultipartReader.cpp -// -// Library: Net -// Package: Messages -// Module: MultipartReader -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/MultipartReader.h" -#include "Poco/Net/MessageHeader.h" -#include "Poco/Net/NetException.h" -#include "Poco/Ascii.h" - - -using Poco::BufferedStreamBuf; - - -namespace Poco { -namespace Net { - - -// -// MultipartStreamBuf -// - - -MultipartStreamBuf::MultipartStreamBuf(std::istream& istr, const std::string& boundary): - BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in), - _istr(istr), - _boundary(boundary), - _lastPart(false) -{ - poco_assert (!boundary.empty() && boundary.length() < STREAM_BUFFER_SIZE - 6); -} - - -MultipartStreamBuf::~MultipartStreamBuf() -{ -} - - -int MultipartStreamBuf::readFromDevice(char* buffer, std::streamsize length) -{ - poco_assert_dbg (length >= _boundary.length() + 6); - - static const int eof = std::char_traits<char>::eof(); - std::streambuf& buf = *_istr.rdbuf(); - - int n = 0; - int ch = buf.sbumpc(); - if (ch == eof) return -1; - *buffer++ = (char) ch; ++n; - if (ch == '\n' || (ch == '\r' && buf.sgetc() == '\n')) - { - if (ch == '\r') - { - ch = buf.sbumpc(); // '\n' - *buffer++ = (char) ch; ++n; - } - ch = buf.sgetc(); - if (ch == '\r' || ch == '\n') return n; - *buffer++ = (char) buf.sbumpc(); ++n; - if (ch == '-' && buf.sgetc() == '-') - { - ch = buf.sbumpc(); // '-' - *buffer++ = (char) ch; ++n; - std::string::const_iterator it = _boundary.begin(); - std::string::const_iterator end = _boundary.end(); - ch = buf.sbumpc(); - *buffer++ = (char) ch; ++n; - while (it != end && ch == *it) - { - ++it; - ch = buf.sbumpc(); - *buffer++ = (char) ch; ++n; - } - if (it == end) - { - if (ch == '\n' || (ch == '\r' && buf.sgetc() == '\n')) - { - if (ch == '\r') - { - buf.sbumpc(); // '\n' - } - return 0; - } - else if (ch == '-' && buf.sgetc() == '-') - { - buf.sbumpc(); // '-' - _lastPart = true; - return 0; - } - } - } - } - ch = buf.sgetc(); - while (ch != eof && ch != '\r' && ch != '\n' && n < length) - { - *buffer++ = (char) buf.sbumpc(); ++n; - ch = buf.sgetc(); - } - return n; -} - - -bool MultipartStreamBuf::lastPart() const -{ - return _lastPart; -} - - -// -// MultipartIOS -// - - -MultipartIOS::MultipartIOS(std::istream& istr, const std::string& boundary): - _buf(istr, boundary) -{ - poco_ios_init(&_buf); -} - - -MultipartIOS::~MultipartIOS() -{ - try - { - _buf.sync(); - } - catch (...) - { - } -} - - -MultipartStreamBuf* MultipartIOS::rdbuf() -{ - return &_buf; -} - - -bool MultipartIOS::lastPart() const -{ - return _buf.lastPart(); -} - - -// -// MultipartInputStream -// - - -MultipartInputStream::MultipartInputStream(std::istream& istr, const std::string& boundary): - MultipartIOS(istr, boundary), - std::istream(&_buf) -{ -} - - -MultipartInputStream::~MultipartInputStream() -{ -} - - -// -// MultipartReader -// - - -MultipartReader::MultipartReader(std::istream& istr): - _istr(istr), - _pMPI(0) -{ -} - - -MultipartReader::MultipartReader(std::istream& istr, const std::string& boundary): - _istr(istr), - _boundary(boundary), - _pMPI(0) -{ -} - - -MultipartReader::~MultipartReader() -{ - delete _pMPI; -} - - -void MultipartReader::nextPart(MessageHeader& messageHeader) -{ - if (!_pMPI) - { - if (_boundary.empty()) - guessBoundary(); - else - findFirstBoundary(); - } - else if (_pMPI->lastPart()) - { - throw MultipartException("No more parts available"); - } - parseHeader(messageHeader); - delete _pMPI; - _pMPI = new MultipartInputStream(_istr, _boundary); -} - - -bool MultipartReader::hasNextPart() -{ - return (!_pMPI || !_pMPI->lastPart()) && _istr.good(); -} - - -std::istream& MultipartReader::stream() const -{ - poco_check_ptr (_pMPI); - - return *_pMPI; -} - - -const std::string& MultipartReader::boundary() const -{ - return _boundary; -} - - -void MultipartReader::findFirstBoundary() -{ - std::string expect("--"); - expect.append(_boundary); - std::string line; - line.reserve(expect.length()); - bool ok = true; - do - { - ok = readLine(line, expect.length()); - } - while (ok && line != expect); - - if (!ok) throw MultipartException("No boundary line found"); -} - - -void MultipartReader::guessBoundary() -{ - static const int eof = std::char_traits<char>::eof(); - int ch = _istr.get(); - while (Poco::Ascii::isSpace(ch)) - ch = _istr.get(); - if (ch == '-' && _istr.peek() == '-') - { - _istr.get(); - ch = _istr.peek(); - while (ch != eof && ch != '\r' && ch != '\n' && _boundary.size() < 128) // Note: should be no longer than 70 chars acc. to RFC 2046 - { - _boundary += (char) _istr.get(); - ch = _istr.peek(); - } - if (ch != '\r' && ch != '\n') - throw MultipartException("Invalid boundary line found"); - if (ch == '\r' || ch == '\n') - _istr.get(); - if (_istr.peek() == '\n') - _istr.get(); - } - else throw MultipartException("No boundary line found"); -} - - -void MultipartReader::parseHeader(MessageHeader& messageHeader) -{ - messageHeader.clear(); - messageHeader.read(_istr); - int ch = _istr.get(); - if (ch == '\r' && _istr.peek() == '\n') _istr.get(); -} - - -bool MultipartReader::readLine(std::string& line, std::string::size_type n) -{ - static const int eof = std::char_traits<char>::eof(); - static const int maxLength = 1024; - - line.clear(); - int ch = _istr.peek(); - int length = 0; - while (ch != eof && ch != '\r' && ch != '\n' && length < maxLength) - { - ch = (char) _istr.get(); - if (line.length() < n) - line += static_cast<char>(ch); - ch = _istr.peek(); - length++; - } - if (ch != eof) _istr.get(); - if (ch == '\r' && _istr.peek() == '\n') _istr.get(); - return ch != eof && length < maxLength; -} - - -} } // namespace Poco::Net +// +// MultipartReader.cpp +// +// Library: Net +// Package: Messages +// Module: MultipartReader +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/MultipartReader.h" +#include "Poco/Net/MessageHeader.h" +#include "Poco/Net/NetException.h" +#include "Poco/Ascii.h" + + +using Poco::BufferedStreamBuf; + + +namespace Poco { +namespace Net { + + +// +// MultipartStreamBuf +// + + +MultipartStreamBuf::MultipartStreamBuf(std::istream& istr, const std::string& boundary): + BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in), + _istr(istr), + _boundary(boundary), + _lastPart(false) +{ + poco_assert (!boundary.empty() && boundary.length() < STREAM_BUFFER_SIZE - 6); +} + + +MultipartStreamBuf::~MultipartStreamBuf() +{ +} + + +int MultipartStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + poco_assert_dbg (length >= _boundary.length() + 6); + + static const int eof = std::char_traits<char>::eof(); + std::streambuf& buf = *_istr.rdbuf(); + + int n = 0; + int ch = buf.sbumpc(); + if (ch == eof) return -1; + *buffer++ = (char) ch; ++n; + if (ch == '\n' || (ch == '\r' && buf.sgetc() == '\n')) + { + if (ch == '\r') + { + ch = buf.sbumpc(); // '\n' + *buffer++ = (char) ch; ++n; + } + ch = buf.sgetc(); + if (ch == '\r' || ch == '\n') return n; + *buffer++ = (char) buf.sbumpc(); ++n; + if (ch == '-' && buf.sgetc() == '-') + { + ch = buf.sbumpc(); // '-' + *buffer++ = (char) ch; ++n; + std::string::const_iterator it = _boundary.begin(); + std::string::const_iterator end = _boundary.end(); + ch = buf.sbumpc(); + *buffer++ = (char) ch; ++n; + while (it != end && ch == *it) + { + ++it; + ch = buf.sbumpc(); + *buffer++ = (char) ch; ++n; + } + if (it == end) + { + if (ch == '\n' || (ch == '\r' && buf.sgetc() == '\n')) + { + if (ch == '\r') + { + buf.sbumpc(); // '\n' + } + return 0; + } + else if (ch == '-' && buf.sgetc() == '-') + { + buf.sbumpc(); // '-' + _lastPart = true; + return 0; + } + } + } + } + ch = buf.sgetc(); + while (ch != eof && ch != '\r' && ch != '\n' && n < length) + { + *buffer++ = (char) buf.sbumpc(); ++n; + ch = buf.sgetc(); + } + return n; +} + + +bool MultipartStreamBuf::lastPart() const +{ + return _lastPart; +} + + +// +// MultipartIOS +// + + +MultipartIOS::MultipartIOS(std::istream& istr, const std::string& boundary): + _buf(istr, boundary) +{ + poco_ios_init(&_buf); +} + + +MultipartIOS::~MultipartIOS() +{ + try + { + _buf.sync(); + } + catch (...) + { + } +} + + +MultipartStreamBuf* MultipartIOS::rdbuf() +{ + return &_buf; +} + + +bool MultipartIOS::lastPart() const +{ + return _buf.lastPart(); +} + + +// +// MultipartInputStream +// + + +MultipartInputStream::MultipartInputStream(std::istream& istr, const std::string& boundary): + MultipartIOS(istr, boundary), + std::istream(&_buf) +{ +} + + +MultipartInputStream::~MultipartInputStream() +{ +} + + +// +// MultipartReader +// + + +MultipartReader::MultipartReader(std::istream& istr): + _istr(istr), + _pMPI(0) +{ +} + + +MultipartReader::MultipartReader(std::istream& istr, const std::string& boundary): + _istr(istr), + _boundary(boundary), + _pMPI(0) +{ +} + + +MultipartReader::~MultipartReader() +{ + delete _pMPI; +} + + +void MultipartReader::nextPart(MessageHeader& messageHeader) +{ + if (!_pMPI) + { + if (_boundary.empty()) + guessBoundary(); + else + findFirstBoundary(); + } + else if (_pMPI->lastPart()) + { + throw MultipartException("No more parts available"); + } + parseHeader(messageHeader); + delete _pMPI; + _pMPI = new MultipartInputStream(_istr, _boundary); +} + + +bool MultipartReader::hasNextPart() +{ + return (!_pMPI || !_pMPI->lastPart()) && _istr.good(); +} + + +std::istream& MultipartReader::stream() const +{ + poco_check_ptr (_pMPI); + + return *_pMPI; +} + + +const std::string& MultipartReader::boundary() const +{ + return _boundary; +} + + +void MultipartReader::findFirstBoundary() +{ + std::string expect("--"); + expect.append(_boundary); + std::string line; + line.reserve(expect.length()); + bool ok = true; + do + { + ok = readLine(line, expect.length()); + } + while (ok && line != expect); + + if (!ok) throw MultipartException("No boundary line found"); +} + + +void MultipartReader::guessBoundary() +{ + static const int eof = std::char_traits<char>::eof(); + int ch = _istr.get(); + while (Poco::Ascii::isSpace(ch)) + ch = _istr.get(); + if (ch == '-' && _istr.peek() == '-') + { + _istr.get(); + ch = _istr.peek(); + while (ch != eof && ch != '\r' && ch != '\n' && _boundary.size() < 128) // Note: should be no longer than 70 chars acc. to RFC 2046 + { + _boundary += (char) _istr.get(); + ch = _istr.peek(); + } + if (ch != '\r' && ch != '\n') + throw MultipartException("Invalid boundary line found"); + if (ch == '\r' || ch == '\n') + _istr.get(); + if (_istr.peek() == '\n') + _istr.get(); + } + else throw MultipartException("No boundary line found"); +} + + +void MultipartReader::parseHeader(MessageHeader& messageHeader) +{ + messageHeader.clear(); + messageHeader.read(_istr); + int ch = _istr.get(); + if (ch == '\r' && _istr.peek() == '\n') _istr.get(); +} + + +bool MultipartReader::readLine(std::string& line, std::string::size_type n) +{ + static const int eof = std::char_traits<char>::eof(); + static const int maxLength = 1024; + + line.clear(); + int ch = _istr.peek(); + int length = 0; + while (ch != eof && ch != '\r' && ch != '\n' && length < maxLength) + { + ch = (char) _istr.get(); + if (line.length() < n) + line += static_cast<char>(ch); + ch = _istr.peek(); + length++; + } + if (ch != eof) _istr.get(); + if (ch == '\r' && _istr.peek() == '\n') _istr.get(); + return ch != eof && length < maxLength; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/MultipartWriter.cpp b/contrib/libs/poco/Net/src/MultipartWriter.cpp index 831fae1071..a73e6d3d3d 100644 --- a/contrib/libs/poco/Net/src/MultipartWriter.cpp +++ b/contrib/libs/poco/Net/src/MultipartWriter.cpp @@ -1,87 +1,87 @@ -// -// MultipartWriter.cpp -// -// Library: Net -// Package: Messages -// Module: MultipartWriter -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/MultipartWriter.h" -#include "Poco/Net/MessageHeader.h" -#include "Poco/Random.h" -#include "Poco/NumberFormatter.h" - - -using Poco::Random; -using Poco::NumberFormatter; - - -namespace Poco { -namespace Net { - - -MultipartWriter::MultipartWriter(std::ostream& ostr): - _ostr(ostr), - _boundary(createBoundary()), - _firstPart(true) -{ -} - - -MultipartWriter::MultipartWriter(std::ostream& ostr, const std::string& boundary): - _ostr(ostr), - _boundary(boundary), - _firstPart(true) -{ - if (_boundary.empty()) - _boundary = createBoundary(); -} - - -MultipartWriter::~MultipartWriter() -{ -} - - -void MultipartWriter::nextPart(const MessageHeader& header) -{ - if (_firstPart) - _firstPart = false; - else - _ostr << "\r\n"; - _ostr << "--" << _boundary << "\r\n"; - header.write(_ostr); - _ostr << "\r\n"; -} - - -void MultipartWriter::close() -{ - _ostr << "\r\n--" << _boundary << "--\r\n"; -} - - -const std::string& MultipartWriter::boundary() const -{ - return _boundary; -} - - -std::string MultipartWriter::createBoundary() -{ - std::string boundary("MIME_boundary_"); - Random rnd; - rnd.seed(); - NumberFormatter::appendHex(boundary, rnd.next(), 8); - NumberFormatter::appendHex(boundary, rnd.next(), 8); - return boundary; -} - - -} } // namespace Poco::Net +// +// MultipartWriter.cpp +// +// Library: Net +// Package: Messages +// Module: MultipartWriter +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/MultipartWriter.h" +#include "Poco/Net/MessageHeader.h" +#include "Poco/Random.h" +#include "Poco/NumberFormatter.h" + + +using Poco::Random; +using Poco::NumberFormatter; + + +namespace Poco { +namespace Net { + + +MultipartWriter::MultipartWriter(std::ostream& ostr): + _ostr(ostr), + _boundary(createBoundary()), + _firstPart(true) +{ +} + + +MultipartWriter::MultipartWriter(std::ostream& ostr, const std::string& boundary): + _ostr(ostr), + _boundary(boundary), + _firstPart(true) +{ + if (_boundary.empty()) + _boundary = createBoundary(); +} + + +MultipartWriter::~MultipartWriter() +{ +} + + +void MultipartWriter::nextPart(const MessageHeader& header) +{ + if (_firstPart) + _firstPart = false; + else + _ostr << "\r\n"; + _ostr << "--" << _boundary << "\r\n"; + header.write(_ostr); + _ostr << "\r\n"; +} + + +void MultipartWriter::close() +{ + _ostr << "\r\n--" << _boundary << "--\r\n"; +} + + +const std::string& MultipartWriter::boundary() const +{ + return _boundary; +} + + +std::string MultipartWriter::createBoundary() +{ + std::string boundary("MIME_boundary_"); + Random rnd; + rnd.seed(); + NumberFormatter::appendHex(boundary, rnd.next(), 8); + NumberFormatter::appendHex(boundary, rnd.next(), 8); + return boundary; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/NTPClient.cpp b/contrib/libs/poco/Net/src/NTPClient.cpp index b370388767..47be7e8fbc 100644 --- a/contrib/libs/poco/Net/src/NTPClient.cpp +++ b/contrib/libs/poco/Net/src/NTPClient.cpp @@ -1,87 +1,87 @@ -// -// NTPClient.cpp -// -// Library: Net -// Package: NTP -// Module: NTPClient -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/SocketAddress.h" -#include "Poco/Net/NTPClient.h" -#include "Poco/Net/NTPPacket.h" -#include "Poco/Net/DatagramSocket.h" -#include "Poco/Net/NetException.h" - - -using Poco::TimeoutException; - - -namespace Poco { -namespace Net { - - -NTPClient::NTPClient(IPAddress::Family family, int timeout): - _family(family), _timeout(timeout) -{ -} - - -NTPClient::~NTPClient() -{ -} - - -int NTPClient::request(const std::string& address) const -{ - SocketAddress addr(address, 123); - return request(addr); -} - - -int NTPClient::request(SocketAddress& address) const -{ - Poco::Net::SocketAddress sa; - DatagramSocket ntpSocket(_family); - ntpSocket.setReceiveTimeout(_timeout); - ntpSocket.bind(sa); - - SocketAddress returnAddress; - - NTPEventArgs eventArgs(address); - - NTPPacket packet; - Poco::UInt8 p[1024]; - packet.packet(&p[0]); - - ntpSocket.sendTo(p, 48, address); - - int received = 0; - try - { - Poco::Net::SocketAddress sender; - int n = ntpSocket.receiveFrom(p, sizeof(p)-1, sender); - - if (n < 48) // NTP packet must have at least 48 bytes - throw Poco::Net::NTPException("Invalid response received"); - - packet.setPacket(p); - eventArgs.setPacket(packet); - ++received; - response.notify(this, eventArgs); - } - catch (Poco::TimeoutException &) - { - // ignore - } - - return received; -} - - -} } // namespace Poco::Net +// +// NTPClient.cpp +// +// Library: Net +// Package: NTP +// Module: NTPClient +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/SocketAddress.h" +#include "Poco/Net/NTPClient.h" +#include "Poco/Net/NTPPacket.h" +#include "Poco/Net/DatagramSocket.h" +#include "Poco/Net/NetException.h" + + +using Poco::TimeoutException; + + +namespace Poco { +namespace Net { + + +NTPClient::NTPClient(IPAddress::Family family, int timeout): + _family(family), _timeout(timeout) +{ +} + + +NTPClient::~NTPClient() +{ +} + + +int NTPClient::request(const std::string& address) const +{ + SocketAddress addr(address, 123); + return request(addr); +} + + +int NTPClient::request(SocketAddress& address) const +{ + Poco::Net::SocketAddress sa; + DatagramSocket ntpSocket(_family); + ntpSocket.setReceiveTimeout(_timeout); + ntpSocket.bind(sa); + + SocketAddress returnAddress; + + NTPEventArgs eventArgs(address); + + NTPPacket packet; + Poco::UInt8 p[1024]; + packet.packet(&p[0]); + + ntpSocket.sendTo(p, 48, address); + + int received = 0; + try + { + Poco::Net::SocketAddress sender; + int n = ntpSocket.receiveFrom(p, sizeof(p)-1, sender); + + if (n < 48) // NTP packet must have at least 48 bytes + throw Poco::Net::NTPException("Invalid response received"); + + packet.setPacket(p); + eventArgs.setPacket(packet); + ++received; + response.notify(this, eventArgs); + } + catch (Poco::TimeoutException &) + { + // ignore + } + + return received; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/NTPEventArgs.cpp b/contrib/libs/poco/Net/src/NTPEventArgs.cpp index 21c57b8779..fd86cc0233 100644 --- a/contrib/libs/poco/Net/src/NTPEventArgs.cpp +++ b/contrib/libs/poco/Net/src/NTPEventArgs.cpp @@ -1,71 +1,71 @@ -// -// NTPEventArgs.cpp -// -// Library: Net -// Package: NTP -// Module: NTPEventArgs -// -// Implementation of NTPEventArgs -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/NTPEventArgs.h" -#include "Poco/Net/SocketAddress.h" -#include "Poco/Net/DNS.h" -#include "Poco/Exception.h" -#include "Poco/Net/NetException.h" - - -using Poco::IOException; -using Poco::InvalidArgumentException; - - -namespace Poco { -namespace Net { - - -NTPEventArgs::NTPEventArgs(const SocketAddress& address): - _address(address), _packet() -{ -} - - -NTPEventArgs::~NTPEventArgs() -{ -} - - -std::string NTPEventArgs::hostName() const -{ - try - { - return DNS::resolve(_address.host().toString()).name(); - } - catch (HostNotFoundException&) - { - } - catch (NoAddressFoundException&) - { - } - catch (DNSException&) - { - } - catch (IOException&) - { - } - return _address.host().toString(); -} - - -std::string NTPEventArgs::hostAddress() const -{ - return _address.host().toString(); -} - - -} } // namespace Poco::Net +// +// NTPEventArgs.cpp +// +// Library: Net +// Package: NTP +// Module: NTPEventArgs +// +// Implementation of NTPEventArgs +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/NTPEventArgs.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/Net/DNS.h" +#include "Poco/Exception.h" +#include "Poco/Net/NetException.h" + + +using Poco::IOException; +using Poco::InvalidArgumentException; + + +namespace Poco { +namespace Net { + + +NTPEventArgs::NTPEventArgs(const SocketAddress& address): + _address(address), _packet() +{ +} + + +NTPEventArgs::~NTPEventArgs() +{ +} + + +std::string NTPEventArgs::hostName() const +{ + try + { + return DNS::resolve(_address.host().toString()).name(); + } + catch (HostNotFoundException&) + { + } + catch (NoAddressFoundException&) + { + } + catch (DNSException&) + { + } + catch (IOException&) + { + } + return _address.host().toString(); +} + + +std::string NTPEventArgs::hostAddress() const +{ + return _address.host().toString(); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/NTPPacket.cpp b/contrib/libs/poco/Net/src/NTPPacket.cpp index 2f7aec830c..f6da1856b4 100644 --- a/contrib/libs/poco/Net/src/NTPPacket.cpp +++ b/contrib/libs/poco/Net/src/NTPPacket.cpp @@ -1,158 +1,158 @@ -// -// NTPPacket.cpp -// -// Library: Net -// Package: NTP -// Module: NTPPacket -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/NTPPacket.h" -#include "Poco/Net/NetException.h" -#include "Poco/Timestamp.h" -#include "Poco/ByteOrder.h" - - -namespace Poco { -namespace Net { - - -#if !defined(POCO_COMPILER_SUN) -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif -struct NTPPacketData -{ - Poco::Int8 mode:3; - Poco::Int8 vn:3; - Poco::Int8 li:2; - Poco::Int8 stratum; - Poco::Int8 pool; - Poco::Int8 prec; - Poco::Int32 rootdelay; - Poco::Int32 rootdisp; - Poco::Int32 refid; - Poco::Int64 rts; - Poco::Int64 ots; - Poco::Int64 vts; - Poco::Int64 tts; -}; -#if !defined(POCO_COMPILER_SUN) -#pragma pack(pop) -#else -#pragma pack() -#endif - - -NTPPacket::NTPPacket() : - // the next 3 fields must be in reverse order from spec - _leapIndicator(3), - _version(4), - _mode(3), - - _stratum(0), - _pool(6), - _precision(-18), - _rootDelay(0), - _rootDispersion(0), - _referenceId(0), - _referenceTimestamp(0), - _receiveTimestamp(0), - _transmitTimestamp(0) -{ - Poco::Timestamp ts; - _originateTimestamp = ts.utcTime() - 2874597888; -} - - -NTPPacket::NTPPacket(Poco::UInt8 *packet) -{ - setPacket(packet); -} - - -NTPPacket::~NTPPacket() -{ -} - - -void NTPPacket::packet(Poco::UInt8 *packet) const -{ - NTPPacketData *p = (NTPPacketData*)packet; - - p->li = _leapIndicator; - p->vn = _version; - p->mode = _mode; - p->stratum = _stratum; - p->pool = _pool; - p->prec = _precision; - p->rootdelay = Poco::ByteOrder::toNetwork(_rootDelay); - p->rootdisp = Poco::ByteOrder::toNetwork(_rootDispersion); - p->refid = Poco::ByteOrder::toNetwork(_referenceId); - p->rts = Poco::ByteOrder::toNetwork(_referenceTimestamp); - p->ots = Poco::ByteOrder::toNetwork(_originateTimestamp); - p->vts = Poco::ByteOrder::toNetwork(_receiveTimestamp); - p->tts = Poco::ByteOrder::toNetwork(_transmitTimestamp); -} - - -void NTPPacket::setPacket(Poco::UInt8 *packet) -{ - NTPPacketData *p = (NTPPacketData*)packet; - - _leapIndicator = p->li; - _version = p->vn; - _mode = p->mode; - _stratum = p->stratum; - _pool = p->pool; - _precision = p->prec; - _rootDelay = Poco::ByteOrder::fromNetwork(p->rootdelay); - _rootDispersion = Poco::ByteOrder::fromNetwork(p->rootdisp); - _referenceId = Poco::ByteOrder::fromNetwork(p->refid); - _referenceTimestamp = Poco::ByteOrder::fromNetwork(p->rts); - _originateTimestamp = Poco::ByteOrder::fromNetwork(p->ots); - _receiveTimestamp = Poco::ByteOrder::fromNetwork(p->vts); - _transmitTimestamp = Poco::ByteOrder::fromNetwork(p->tts); -} - - -Poco::Timestamp NTPPacket::referenceTime() const -{ - return convertTime(_referenceTimestamp); -} - - -Poco::Timestamp NTPPacket::originateTime() const -{ - return convertTime(_originateTimestamp); -} - - -Poco::Timestamp NTPPacket::receiveTime() const -{ - return convertTime(_receiveTimestamp); -} - - -Poco::Timestamp NTPPacket::transmitTime() const -{ - return convertTime(_transmitTimestamp); -} - - -Poco::Timestamp NTPPacket::convertTime(Poco::Int64 tm) const -{ - const unsigned long seventyYears = 2208988800UL; - Poco::UInt32 secsSince1900 = UInt32(Poco::ByteOrder::toLittleEndian(tm) >> 32); - unsigned long epoch = secsSince1900 - seventyYears; - return Poco::Timestamp::fromEpochTime(epoch); -} - - -} } // namespace Poco::Net +// +// NTPPacket.cpp +// +// Library: Net +// Package: NTP +// Module: NTPPacket +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/NTPPacket.h" +#include "Poco/Net/NetException.h" +#include "Poco/Timestamp.h" +#include "Poco/ByteOrder.h" + + +namespace Poco { +namespace Net { + + +#if !defined(POCO_COMPILER_SUN) +#pragma pack(push, 1) +#else +#pragma pack(1) +#endif +struct NTPPacketData +{ + Poco::Int8 mode:3; + Poco::Int8 vn:3; + Poco::Int8 li:2; + Poco::Int8 stratum; + Poco::Int8 pool; + Poco::Int8 prec; + Poco::Int32 rootdelay; + Poco::Int32 rootdisp; + Poco::Int32 refid; + Poco::Int64 rts; + Poco::Int64 ots; + Poco::Int64 vts; + Poco::Int64 tts; +}; +#if !defined(POCO_COMPILER_SUN) +#pragma pack(pop) +#else +#pragma pack() +#endif + + +NTPPacket::NTPPacket() : + // the next 3 fields must be in reverse order from spec + _leapIndicator(3), + _version(4), + _mode(3), + + _stratum(0), + _pool(6), + _precision(-18), + _rootDelay(0), + _rootDispersion(0), + _referenceId(0), + _referenceTimestamp(0), + _receiveTimestamp(0), + _transmitTimestamp(0) +{ + Poco::Timestamp ts; + _originateTimestamp = ts.utcTime() - 2874597888; +} + + +NTPPacket::NTPPacket(Poco::UInt8 *packet) +{ + setPacket(packet); +} + + +NTPPacket::~NTPPacket() +{ +} + + +void NTPPacket::packet(Poco::UInt8 *packet) const +{ + NTPPacketData *p = (NTPPacketData*)packet; + + p->li = _leapIndicator; + p->vn = _version; + p->mode = _mode; + p->stratum = _stratum; + p->pool = _pool; + p->prec = _precision; + p->rootdelay = Poco::ByteOrder::toNetwork(_rootDelay); + p->rootdisp = Poco::ByteOrder::toNetwork(_rootDispersion); + p->refid = Poco::ByteOrder::toNetwork(_referenceId); + p->rts = Poco::ByteOrder::toNetwork(_referenceTimestamp); + p->ots = Poco::ByteOrder::toNetwork(_originateTimestamp); + p->vts = Poco::ByteOrder::toNetwork(_receiveTimestamp); + p->tts = Poco::ByteOrder::toNetwork(_transmitTimestamp); +} + + +void NTPPacket::setPacket(Poco::UInt8 *packet) +{ + NTPPacketData *p = (NTPPacketData*)packet; + + _leapIndicator = p->li; + _version = p->vn; + _mode = p->mode; + _stratum = p->stratum; + _pool = p->pool; + _precision = p->prec; + _rootDelay = Poco::ByteOrder::fromNetwork(p->rootdelay); + _rootDispersion = Poco::ByteOrder::fromNetwork(p->rootdisp); + _referenceId = Poco::ByteOrder::fromNetwork(p->refid); + _referenceTimestamp = Poco::ByteOrder::fromNetwork(p->rts); + _originateTimestamp = Poco::ByteOrder::fromNetwork(p->ots); + _receiveTimestamp = Poco::ByteOrder::fromNetwork(p->vts); + _transmitTimestamp = Poco::ByteOrder::fromNetwork(p->tts); +} + + +Poco::Timestamp NTPPacket::referenceTime() const +{ + return convertTime(_referenceTimestamp); +} + + +Poco::Timestamp NTPPacket::originateTime() const +{ + return convertTime(_originateTimestamp); +} + + +Poco::Timestamp NTPPacket::receiveTime() const +{ + return convertTime(_receiveTimestamp); +} + + +Poco::Timestamp NTPPacket::transmitTime() const +{ + return convertTime(_transmitTimestamp); +} + + +Poco::Timestamp NTPPacket::convertTime(Poco::Int64 tm) const +{ + const unsigned long seventyYears = 2208988800UL; + Poco::UInt32 secsSince1900 = UInt32(Poco::ByteOrder::toLittleEndian(tm) >> 32); + unsigned long epoch = secsSince1900 - seventyYears; + return Poco::Timestamp::fromEpochTime(epoch); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/NameValueCollection.cpp b/contrib/libs/poco/Net/src/NameValueCollection.cpp index def4814a16..11c882ac77 100644 --- a/contrib/libs/poco/Net/src/NameValueCollection.cpp +++ b/contrib/libs/poco/Net/src/NameValueCollection.cpp @@ -1,153 +1,153 @@ -// -// NameValueCollection.cpp -// -// Library: Net -// Package: Messages -// Module: NameValueCollection -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/NameValueCollection.h" -#include "Poco/Exception.h" -#include <algorithm> - - -using Poco::NotFoundException; - - -namespace Poco { -namespace Net { - - -NameValueCollection::NameValueCollection() -{ -} - - -NameValueCollection::NameValueCollection(const NameValueCollection& nvc): - _map(nvc._map) -{ -} - - -NameValueCollection::~NameValueCollection() -{ -} - - -NameValueCollection& NameValueCollection::operator = (const NameValueCollection& nvc) -{ - if (&nvc != this) - { - _map = nvc._map; - } - return *this; -} - - -void NameValueCollection::swap(NameValueCollection& nvc) -{ - std::swap(_map, nvc._map); -} - - -const std::string& NameValueCollection::operator [] (const std::string& name) const -{ - ConstIterator it = _map.find(name); - if (it != _map.end()) - return it->second; - else - throw NotFoundException(name); -} - - -void NameValueCollection::set(const std::string& name, const std::string& value) -{ - Iterator it = _map.find(name); - if (it != _map.end()) - it->second = value; - else - _map.insert(HeaderMap::ValueType(name, value)); -} - - -void NameValueCollection::add(const std::string& name, const std::string& value) -{ - _map.insert(HeaderMap::ValueType(name, value)); -} - - -const std::string& NameValueCollection::get(const std::string& name) const -{ - ConstIterator it = _map.find(name); - if (it != _map.end()) - return it->second; - else - throw NotFoundException(name); -} - - -const std::string& NameValueCollection::get(const std::string& name, const std::string& defaultValue) const -{ - ConstIterator it = _map.find(name); - if (it != _map.end()) - return it->second; - else - return defaultValue; -} - - -bool NameValueCollection::has(const std::string& name) const -{ - return _map.find(name) != _map.end(); -} - - -NameValueCollection::ConstIterator NameValueCollection::find(const std::string& name) const -{ - return _map.find(name); -} - - -NameValueCollection::ConstIterator NameValueCollection::begin() const -{ - return _map.begin(); -} - - -NameValueCollection::ConstIterator NameValueCollection::end() const -{ - return _map.end(); -} - - -bool NameValueCollection::empty() const -{ - return _map.empty(); -} - - -std::size_t NameValueCollection::size() const -{ - return _map.size(); -} - - -void NameValueCollection::erase(const std::string& name) -{ - _map.erase(name); -} - - -void NameValueCollection::clear() -{ - _map.clear(); -} - - -} } // namespace Poco::Net +// +// NameValueCollection.cpp +// +// Library: Net +// Package: Messages +// Module: NameValueCollection +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/NameValueCollection.h" +#include "Poco/Exception.h" +#include <algorithm> + + +using Poco::NotFoundException; + + +namespace Poco { +namespace Net { + + +NameValueCollection::NameValueCollection() +{ +} + + +NameValueCollection::NameValueCollection(const NameValueCollection& nvc): + _map(nvc._map) +{ +} + + +NameValueCollection::~NameValueCollection() +{ +} + + +NameValueCollection& NameValueCollection::operator = (const NameValueCollection& nvc) +{ + if (&nvc != this) + { + _map = nvc._map; + } + return *this; +} + + +void NameValueCollection::swap(NameValueCollection& nvc) +{ + std::swap(_map, nvc._map); +} + + +const std::string& NameValueCollection::operator [] (const std::string& name) const +{ + ConstIterator it = _map.find(name); + if (it != _map.end()) + return it->second; + else + throw NotFoundException(name); +} + + +void NameValueCollection::set(const std::string& name, const std::string& value) +{ + Iterator it = _map.find(name); + if (it != _map.end()) + it->second = value; + else + _map.insert(HeaderMap::ValueType(name, value)); +} + + +void NameValueCollection::add(const std::string& name, const std::string& value) +{ + _map.insert(HeaderMap::ValueType(name, value)); +} + + +const std::string& NameValueCollection::get(const std::string& name) const +{ + ConstIterator it = _map.find(name); + if (it != _map.end()) + return it->second; + else + throw NotFoundException(name); +} + + +const std::string& NameValueCollection::get(const std::string& name, const std::string& defaultValue) const +{ + ConstIterator it = _map.find(name); + if (it != _map.end()) + return it->second; + else + return defaultValue; +} + + +bool NameValueCollection::has(const std::string& name) const +{ + return _map.find(name) != _map.end(); +} + + +NameValueCollection::ConstIterator NameValueCollection::find(const std::string& name) const +{ + return _map.find(name); +} + + +NameValueCollection::ConstIterator NameValueCollection::begin() const +{ + return _map.begin(); +} + + +NameValueCollection::ConstIterator NameValueCollection::end() const +{ + return _map.end(); +} + + +bool NameValueCollection::empty() const +{ + return _map.empty(); +} + + +std::size_t NameValueCollection::size() const +{ + return _map.size(); +} + + +void NameValueCollection::erase(const std::string& name) +{ + _map.erase(name); +} + + +void NameValueCollection::clear() +{ + _map.clear(); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/Net.cpp b/contrib/libs/poco/Net/src/Net.cpp index e81b4b5459..5365f19b10 100644 --- a/contrib/libs/poco/Net/src/Net.cpp +++ b/contrib/libs/poco/Net/src/Net.cpp @@ -1,76 +1,76 @@ -// -// Net.cpp -// -// Library: Net -// Package: NetCore -// Module: NetCore -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/Net.h" - - -#include "Poco/Net/SocketDefs.h" -#include "Poco/Net/NetException.h" - - -namespace Poco { -namespace Net { - - -void Net_API initializeNetwork() -{ -#if defined(POCO_OS_FAMILY_WINDOWS) - WORD version = MAKEWORD(2, 2); - WSADATA data; - if (WSAStartup(version, &data) != 0) - throw NetException("Failed to initialize network subsystem"); -#endif -} - - -void Net_API uninitializeNetwork() -{ -#if defined(POCO_OS_FAMILY_WINDOWS) - WSACleanup(); -#endif -} - - -} } // namespace Poco::Net - - -#if defined(POCO_OS_FAMILY_WINDOWS) && !defined(POCO_NO_AUTOMATIC_LIB_INIT) - - struct NetworkInitializer - /// Network initializer for windows statically - /// linked library. - { - NetworkInitializer() - /// Calls Poco::Net::initializeNetwork(); - { - Poco::Net::initializeNetwork(); - } - - ~NetworkInitializer() - /// Calls Poco::Net::uninitializeNetwork(); - { - try - { - Poco::Net::uninitializeNetwork(); - } - catch (...) - { - poco_unexpected(); - } - } - }; - - const NetworkInitializer pocoNetworkInitializer; - -#endif +// +// Net.cpp +// +// Library: Net +// Package: NetCore +// Module: NetCore +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/Net.h" + + +#include "Poco/Net/SocketDefs.h" +#include "Poco/Net/NetException.h" + + +namespace Poco { +namespace Net { + + +void Net_API initializeNetwork() +{ +#if defined(POCO_OS_FAMILY_WINDOWS) + WORD version = MAKEWORD(2, 2); + WSADATA data; + if (WSAStartup(version, &data) != 0) + throw NetException("Failed to initialize network subsystem"); +#endif +} + + +void Net_API uninitializeNetwork() +{ +#if defined(POCO_OS_FAMILY_WINDOWS) + WSACleanup(); +#endif +} + + +} } // namespace Poco::Net + + +#if defined(POCO_OS_FAMILY_WINDOWS) && !defined(POCO_NO_AUTOMATIC_LIB_INIT) + + struct NetworkInitializer + /// Network initializer for windows statically + /// linked library. + { + NetworkInitializer() + /// Calls Poco::Net::initializeNetwork(); + { + Poco::Net::initializeNetwork(); + } + + ~NetworkInitializer() + /// Calls Poco::Net::uninitializeNetwork(); + { + try + { + Poco::Net::uninitializeNetwork(); + } + catch (...) + { + poco_unexpected(); + } + } + }; + + const NetworkInitializer pocoNetworkInitializer; + +#endif diff --git a/contrib/libs/poco/Net/src/NetException.cpp b/contrib/libs/poco/Net/src/NetException.cpp index a167642b2a..88ee7e1e34 100644 --- a/contrib/libs/poco/Net/src/NetException.cpp +++ b/contrib/libs/poco/Net/src/NetException.cpp @@ -1,54 +1,54 @@ -// -// NetException.cpp -// -// Library: Net -// Package: NetCore -// Module: NetException -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/NetException.h" -#include <typeinfo> - - -using Poco::IOException; - - -namespace Poco { -namespace Net { - - -POCO_IMPLEMENT_EXCEPTION(NetException, IOException, "Net Exception") -POCO_IMPLEMENT_EXCEPTION(InvalidAddressException, NetException, "Invalid address") -POCO_IMPLEMENT_EXCEPTION(InvalidSocketException, NetException, "Invalid socket") -POCO_IMPLEMENT_EXCEPTION(ServiceNotFoundException, NetException, "Service not found") -POCO_IMPLEMENT_EXCEPTION(ConnectionAbortedException, NetException, "Software caused connection abort") -POCO_IMPLEMENT_EXCEPTION(ConnectionResetException, NetException, "Connection reset by peer") -POCO_IMPLEMENT_EXCEPTION(ConnectionRefusedException, NetException, "Connection refused") -POCO_IMPLEMENT_EXCEPTION(DNSException, NetException, "DNS error") -POCO_IMPLEMENT_EXCEPTION(HostNotFoundException, DNSException, "Host not found") -POCO_IMPLEMENT_EXCEPTION(NoAddressFoundException, DNSException, "No address found") -POCO_IMPLEMENT_EXCEPTION(InterfaceNotFoundException, NetException, "Interface not found") -POCO_IMPLEMENT_EXCEPTION(NoMessageException, NetException, "No message received") -POCO_IMPLEMENT_EXCEPTION(MessageException, NetException, "Malformed message") -POCO_IMPLEMENT_EXCEPTION(MultipartException, MessageException, "Malformed multipart message") -POCO_IMPLEMENT_EXCEPTION(HTTPException, NetException, "HTTP Exception") -POCO_IMPLEMENT_EXCEPTION(NotAuthenticatedException, HTTPException, "No authentication information found") -POCO_IMPLEMENT_EXCEPTION(UnsupportedRedirectException, HTTPException, "Unsupported HTTP redirect (protocol change)") -POCO_IMPLEMENT_EXCEPTION(FTPException, NetException, "FTP Exception") -POCO_IMPLEMENT_EXCEPTION(SMTPException, NetException, "SMTP Exception") -POCO_IMPLEMENT_EXCEPTION(POP3Exception, NetException, "POP3 Exception") -POCO_IMPLEMENT_EXCEPTION(ICMPException, NetException, "ICMP Exception") -POCO_IMPLEMENT_EXCEPTION(NTPException, NetException, "NTP Exception") -POCO_IMPLEMENT_EXCEPTION(HTMLFormException, NetException, "HTML Form Exception") -POCO_IMPLEMENT_EXCEPTION(WebSocketException, NetException, "WebSocket Exception") -POCO_IMPLEMENT_EXCEPTION(UnsupportedFamilyException, NetException, "Unknown or unsupported socket family") -POCO_IMPLEMENT_EXCEPTION(AddressFamilyMismatchException, NetException, "Address family mismatch") - - -} } // namespace Poco::Net +// +// NetException.cpp +// +// Library: Net +// Package: NetCore +// Module: NetException +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/NetException.h" +#include <typeinfo> + + +using Poco::IOException; + + +namespace Poco { +namespace Net { + + +POCO_IMPLEMENT_EXCEPTION(NetException, IOException, "Net Exception") +POCO_IMPLEMENT_EXCEPTION(InvalidAddressException, NetException, "Invalid address") +POCO_IMPLEMENT_EXCEPTION(InvalidSocketException, NetException, "Invalid socket") +POCO_IMPLEMENT_EXCEPTION(ServiceNotFoundException, NetException, "Service not found") +POCO_IMPLEMENT_EXCEPTION(ConnectionAbortedException, NetException, "Software caused connection abort") +POCO_IMPLEMENT_EXCEPTION(ConnectionResetException, NetException, "Connection reset by peer") +POCO_IMPLEMENT_EXCEPTION(ConnectionRefusedException, NetException, "Connection refused") +POCO_IMPLEMENT_EXCEPTION(DNSException, NetException, "DNS error") +POCO_IMPLEMENT_EXCEPTION(HostNotFoundException, DNSException, "Host not found") +POCO_IMPLEMENT_EXCEPTION(NoAddressFoundException, DNSException, "No address found") +POCO_IMPLEMENT_EXCEPTION(InterfaceNotFoundException, NetException, "Interface not found") +POCO_IMPLEMENT_EXCEPTION(NoMessageException, NetException, "No message received") +POCO_IMPLEMENT_EXCEPTION(MessageException, NetException, "Malformed message") +POCO_IMPLEMENT_EXCEPTION(MultipartException, MessageException, "Malformed multipart message") +POCO_IMPLEMENT_EXCEPTION(HTTPException, NetException, "HTTP Exception") +POCO_IMPLEMENT_EXCEPTION(NotAuthenticatedException, HTTPException, "No authentication information found") +POCO_IMPLEMENT_EXCEPTION(UnsupportedRedirectException, HTTPException, "Unsupported HTTP redirect (protocol change)") +POCO_IMPLEMENT_EXCEPTION(FTPException, NetException, "FTP Exception") +POCO_IMPLEMENT_EXCEPTION(SMTPException, NetException, "SMTP Exception") +POCO_IMPLEMENT_EXCEPTION(POP3Exception, NetException, "POP3 Exception") +POCO_IMPLEMENT_EXCEPTION(ICMPException, NetException, "ICMP Exception") +POCO_IMPLEMENT_EXCEPTION(NTPException, NetException, "NTP Exception") +POCO_IMPLEMENT_EXCEPTION(HTMLFormException, NetException, "HTML Form Exception") +POCO_IMPLEMENT_EXCEPTION(WebSocketException, NetException, "WebSocket Exception") +POCO_IMPLEMENT_EXCEPTION(UnsupportedFamilyException, NetException, "Unknown or unsupported socket family") +POCO_IMPLEMENT_EXCEPTION(AddressFamilyMismatchException, NetException, "Address family mismatch") + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/NetworkInterface.cpp b/contrib/libs/poco/Net/src/NetworkInterface.cpp index e3b1c24f7b..bf56b38a10 100644 --- a/contrib/libs/poco/Net/src/NetworkInterface.cpp +++ b/contrib/libs/poco/Net/src/NetworkInterface.cpp @@ -1,1827 +1,1827 @@ -// -// NetworkInterface.cpp -// -// Library: Net -// Package: NetCore -// Module: NetworkInterface -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/NetworkInterface.h" - - -#ifdef POCO_NET_HAS_INTERFACE - - -#include "Poco/Net/DatagramSocket.h" -#include "Poco/Net/NetException.h" -#include "Poco/NumberFormatter.h" -#include "Poco/NumberParser.h" -#include "Poco/StringTokenizer.h" -#include "Poco/RefCountedObject.h" -#include "Poco/Format.h" -#if defined(POCO_OS_FAMILY_WINDOWS) - #if defined(POCO_WIN32_UTF8) - #include "Poco/UnicodeConverter.h" - #endif - #include "Poco/Error.h" - #include <wincrypt.h> - #include <iphlpapi.h> - #include <ipifcons.h> -#endif -#include <cstring> -#include <fstream> -#include <iostream> -#include <iomanip> - - -using Poco::NumberFormatter; -using Poco::FastMutex; -using Poco::format; - - -std::ostream& operator << (std::ostream& os, const Poco::Net::NetworkInterface::MACAddress& mac) -{ - std::ios state(0); - state.copyfmt(os); - for (unsigned i = 0; i < mac.size(); ++i) - { - if (i > 0) os << Poco::Net::NetworkInterface::MAC_SEPARATOR; - os << std::hex << std::setw(2) << std::setfill('0') << (unsigned) mac[i]; - } - os.copyfmt(state); - return os; -} - - -namespace Poco { -namespace Net { - - -// -// NetworkInterfaceImpl -// - -class NetworkInterfaceImpl: public Poco::RefCountedObject -{ -public: - typedef NetworkInterface::AddressTuple AddressTuple; - typedef NetworkInterface::AddressList AddressList; - typedef NetworkInterface::Type Type; - - NetworkInterfaceImpl(unsigned index); - NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, NetworkInterface::MACAddress* pMACAddress = 0); - NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index = 0, NetworkInterface::MACAddress* pMACAddress = 0); - NetworkInterfaceImpl(const std::string& name, - const std::string& displayName, - const std::string& adapterName, - const IPAddress& address, - const IPAddress& subnetMask, - const IPAddress& broadcastAddress, - unsigned index, - NetworkInterface::MACAddress* pMACAddress = 0); - - unsigned index() const; - const std::string& name() const; - const std::string& displayName() const; - const std::string& adapterName() const; - const IPAddress& firstAddress(IPAddress::Family family) const; - void addAddress(const AddressTuple& address); - const IPAddress& address(unsigned index) const; - const NetworkInterface::AddressList& addressList() const; - bool hasAddress(const IPAddress& address) const; - const IPAddress& subnetMask(unsigned index) const; - const IPAddress& broadcastAddress(unsigned index) const; - const IPAddress& destAddress(unsigned index) const; - const NetworkInterface::MACAddress& macAddress() const; - bool supportsIPv4() const; - bool supportsIPv6() const; - - void setName(const std::string& name); - void setDisplayName(const std::string& name); - void setAdapterName(const std::string& name); - void addAddress(const IPAddress& addr); - void setMACAddress(const NetworkInterface::MACAddress& addr); - void setMACAddress(const void *addr, std::size_t len); - - unsigned mtu() const; - unsigned ifindex() const; - Type type() const; - - bool broadcast() const; - bool loopback() const; - bool multicast() const; - bool pointToPoint() const; - bool running() const; - bool up() const; - -#if defined(POCO_OS_FAMILY_WINDOWS) - void setFlags(DWORD flags, DWORD iftype); - void setRunning(bool running); -#else - void setFlags(short flags); -#endif - - void setUp(bool up); - void setMTU(unsigned mtu); - void setType(Type type); - void setIndex(unsigned index); - void setPhyParams(); - -protected: - ~NetworkInterfaceImpl(); - -private: - std::string _name; - std::string _displayName; - std::string _adapterName; - AddressList _addressList; - unsigned _index; - bool _broadcast; - bool _loopback; - bool _multicast; - bool _pointToPoint; - bool _up; - bool _running; - unsigned _mtu; - Type _type; - - NetworkInterface::MACAddress _macAddress; - - friend class NetworkInterface; -}; - - -NetworkInterfaceImpl::NetworkInterfaceImpl(unsigned index): - _index(index), - _broadcast(false), - _loopback(false), - _multicast(false), - _pointToPoint(false), - _up(false), - _running(false), - _mtu(0), - _type(NetworkInterface::NI_TYPE_OTHER) -{ -} - - -NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, NetworkInterface::MACAddress* pMACAddress): - _name(name), - _displayName(displayName), - _adapterName(adapterName), - _index(index), - _broadcast(false), - _loopback(false), - _multicast(false), - _pointToPoint(false), - _up(false), - _running(false), - _mtu(0), - _type(NetworkInterface::NI_TYPE_OTHER) -{ - _addressList.push_back(AddressTuple(address, IPAddress(), IPAddress())); - setPhyParams(); - if (pMACAddress) setMACAddress(*pMACAddress); -} - - -NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index, NetworkInterface::MACAddress* pMACAddress): - _name(name), - _displayName(displayName), - _adapterName(adapterName), - _index(index), - _broadcast(false), - _loopback(false), - _multicast(false), - _pointToPoint(false), - _up(false), - _running(false), - _mtu(0), - _type(NetworkInterface::NI_TYPE_OTHER) -{ - setPhyParams(); - if (pMACAddress) setMACAddress(*pMACAddress); -} - - -NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, - const std::string& displayName, - const std::string& adapterName, - const IPAddress& address, - const IPAddress& subnetMask, - const IPAddress& broadcastAddress, - unsigned index, - NetworkInterface::MACAddress* pMACAddress): - _name(name), - _displayName(displayName), - _adapterName(adapterName), - _index(index), - _broadcast(false), - _loopback(false), - _multicast(false), - _pointToPoint(false), - _up(false), - _running(false), - _mtu(0), - _type(NetworkInterface::NI_TYPE_OTHER) -{ - _addressList.push_back(AddressTuple(address, subnetMask, broadcastAddress)); - setPhyParams(); - if (pMACAddress) setMACAddress(*pMACAddress); -} - - -void NetworkInterfaceImpl::setPhyParams() -{ -#if !defined(POCO_OS_FAMILY_WINDOWS) && !defined(POCO_VXWORKS) - struct ifreq ifr; - std::strncpy(ifr.ifr_name, _name.c_str(), IFNAMSIZ); - DatagramSocket ds(SocketAddress::IPv4); - - ds.impl()->ioctl(SIOCGIFFLAGS, &ifr); - setFlags(ifr.ifr_flags); - - ds.impl()->ioctl(SIOCGIFMTU, &ifr); - setMTU(ifr.ifr_mtu); -#endif -} - - -NetworkInterfaceImpl::~NetworkInterfaceImpl() -{ -} - - -bool NetworkInterfaceImpl::supportsIPv4() const -{ - AddressList::const_iterator it = _addressList.begin(); - AddressList::const_iterator end = _addressList.end(); - for (; it != end; ++it) - { - if (IPAddress::IPv4 == it->get<NetworkInterface::IP_ADDRESS>().family()) - return true; - } - - return false; -} - - -bool NetworkInterfaceImpl::supportsIPv6() const -{ -#ifdef POCO_HAVE_IPv6 - AddressList::const_iterator it = _addressList.begin(); - AddressList::const_iterator end = _addressList.end(); - for (; it != end; ++it) - { - if (IPAddress::IPv6 == it->get<NetworkInterface::IP_ADDRESS>().family()) - return true; - } -#endif - return false; -} - - -inline unsigned NetworkInterfaceImpl::index() const -{ - return _index; -} - - -inline const std::string& NetworkInterfaceImpl::name() const -{ - return _name; -} - - -inline const std::string& NetworkInterfaceImpl::displayName() const -{ - return _displayName; -} - - -inline const std::string& NetworkInterfaceImpl::adapterName() const -{ - return _adapterName; -} - - -const IPAddress& NetworkInterfaceImpl::firstAddress(IPAddress::Family family) const -{ - AddressList::const_iterator it = _addressList.begin(); - AddressList::const_iterator end = _addressList.end(); - for (;it != end; ++it) - { - const IPAddress& addr = it->get<NetworkInterface::IP_ADDRESS>(); - if (addr.family() == family) return addr; - } - - throw NotFoundException(format("%s family address not found.", (family == IPAddress::IPv4) ? std::string("IPv4") : std::string("IPv6"))); -} - - -inline void NetworkInterfaceImpl::addAddress(const AddressTuple& address) -{ - _addressList.push_back(address); -} - - -bool NetworkInterfaceImpl::hasAddress(const IPAddress& address) const -{ - NetworkInterface::ConstAddressIterator it = _addressList.begin(); - NetworkInterface::ConstAddressIterator end = _addressList.end(); - for (; it != end; ++it) - { - if (it->get<NetworkInterface::IP_ADDRESS>() == address) - return true; - } - return false; -} - - -inline const IPAddress& NetworkInterfaceImpl::address(unsigned index) const -{ - if (index < _addressList.size()) return _addressList[index].get<NetworkInterface::IP_ADDRESS>(); - else throw NotFoundException(Poco::format("No address with index %u.", index)); -} - - -inline const NetworkInterface::AddressList& NetworkInterfaceImpl::addressList() const -{ - return _addressList; -} - - -const IPAddress& NetworkInterfaceImpl::subnetMask(unsigned index) const -{ - if (index < _addressList.size()) - return _addressList[index].get<NetworkInterface::SUBNET_MASK>(); - - throw NotFoundException(Poco::format("No subnet mask with index %u.", index)); -} - - -const IPAddress& NetworkInterfaceImpl::broadcastAddress(unsigned index) const -{ - if (index < _addressList.size()) - return _addressList[index].get<NetworkInterface::BROADCAST_ADDRESS>(); - - throw NotFoundException(Poco::format("No subnet mask with index %u.", index)); -} - - -const IPAddress& NetworkInterfaceImpl::destAddress(unsigned index) const -{ - if (!pointToPoint()) - throw InvalidAccessException("Only PPP addresses have destination address."); - else if (index < _addressList.size()) - return _addressList[index].get<NetworkInterface::BROADCAST_ADDRESS>(); - - throw NotFoundException(Poco::format("No address with index %u.", index)); -} - - -const NetworkInterface::MACAddress& NetworkInterfaceImpl::macAddress() const -{ - return _macAddress; -} - - -inline unsigned NetworkInterfaceImpl::mtu() const -{ - return _mtu; -} - - -inline NetworkInterface::Type NetworkInterfaceImpl::type() const -{ - return _type; -} - - -inline bool NetworkInterfaceImpl::broadcast() const -{ - return _broadcast; -} - - -inline bool NetworkInterfaceImpl::loopback() const -{ - return _loopback; -} - - -inline bool NetworkInterfaceImpl::multicast() const -{ - return _multicast; -} - - -inline bool NetworkInterfaceImpl::pointToPoint() const -{ - return _pointToPoint; -} - - -inline bool NetworkInterfaceImpl::running() const -{ - return _running; -} - - -inline bool NetworkInterfaceImpl::up() const -{ - return _up; -} - - -#if defined(POCO_OS_FAMILY_WINDOWS) - - -void NetworkInterfaceImpl::setFlags(DWORD flags, DWORD iftype) -{ - _running = _up = false; - switch (iftype) { - case IF_TYPE_ETHERNET_CSMACD: - case IF_TYPE_ISO88025_TOKENRING: - case IF_TYPE_IEEE80211: - _multicast = _broadcast = true; - break; - case IF_TYPE_SOFTWARE_LOOPBACK: - _loopback = true; - break; - case IF_TYPE_PPP: - case IF_TYPE_ATM: - case IF_TYPE_TUNNEL: - case IF_TYPE_IEEE1394: - _pointToPoint = true; - break; - } - if (!(flags & IP_ADAPTER_NO_MULTICAST)) - _multicast = true; -} - - -void NetworkInterfaceImpl::setRunning(bool running) -{ - _running = running; -} - - -#else - - -void NetworkInterfaceImpl::setFlags(short flags) -{ -#ifdef POCO_OS_FAMILY_UNIX - _broadcast = ((flags & IFF_BROADCAST) != 0); - _loopback = ((flags & IFF_LOOPBACK) != 0); - _multicast = ((flags & IFF_MULTICAST) != 0); - _pointToPoint = ((flags & IFF_POINTOPOINT) != 0); - _running = ((flags & IFF_RUNNING) != 0); - _up = ((flags & IFF_UP) != 0); -#endif -} - - -#endif - - -inline void NetworkInterfaceImpl::setUp(bool up) -{ - _up = up; -} - - -inline void NetworkInterfaceImpl::setMTU(unsigned mtu) -{ - _mtu = mtu; -} - - -inline void NetworkInterfaceImpl::setType(Type type) -{ - _type = type; -} - - -inline void NetworkInterfaceImpl::setIndex(unsigned index) -{ - _index = index; -} - - -inline void NetworkInterfaceImpl::setName(const std::string& name) -{ - _name = name; -} - - -inline void NetworkInterfaceImpl::setDisplayName(const std::string& name) -{ - _displayName = name; -} - - -inline void NetworkInterfaceImpl::setAdapterName(const std::string& name) -{ - _adapterName = name; -} - - -inline void NetworkInterfaceImpl::addAddress(const IPAddress& addr) -{ - _addressList.push_back(addr); -} - - -inline void NetworkInterfaceImpl::setMACAddress(const NetworkInterface::MACAddress& addr) -{ - _macAddress = addr; -} - - -inline void NetworkInterfaceImpl::setMACAddress(const void *addr, std::size_t len) -{ - _macAddress.clear(); - _macAddress.insert(_macAddress.end(), static_cast<const unsigned char*>(addr), static_cast<const unsigned char*>(addr) + len); -} - - -// -// NetworkInterface -// - - -FastMutex NetworkInterface::_mutex; - - -NetworkInterface::NetworkInterface(unsigned index): - _pImpl(new NetworkInterfaceImpl(index)) -{ -} - - -NetworkInterface::NetworkInterface(const NetworkInterface& interfc): - _pImpl(interfc._pImpl) -{ - _pImpl->duplicate(); -} - - -NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, MACAddress* pMACAddress): - _pImpl(new NetworkInterfaceImpl(name, displayName, adapterName, address, index, pMACAddress)) -{ -} - - -NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index, MACAddress* pMACAddress): - _pImpl(new NetworkInterfaceImpl(name, displayName, adapterName, index, pMACAddress)) -{ -} - - -NetworkInterface::NetworkInterface(const std::string& name, const IPAddress& address, unsigned index, MACAddress* pMACAddress): - _pImpl(new NetworkInterfaceImpl(name, name, name, address, index, pMACAddress)) -{ -} - - -NetworkInterface::NetworkInterface(const std::string& name, - const std::string& displayName, - const std::string& adapterName, - const IPAddress& address, - const IPAddress& subnetMask, - const IPAddress& broadcastAddress, - unsigned index, - MACAddress* pMACAddress): - _pImpl(new NetworkInterfaceImpl(name, displayName, adapterName, address, subnetMask, broadcastAddress, index, pMACAddress)) -{ -} - - -NetworkInterface::NetworkInterface(const std::string& name, - const IPAddress& address, - const IPAddress& subnetMask, - const IPAddress& broadcastAddress, - unsigned index, - MACAddress* pMACAddress): - _pImpl(new NetworkInterfaceImpl(name, name, name, address, subnetMask, broadcastAddress, index, pMACAddress)) -{ -} - - -NetworkInterface::~NetworkInterface() -{ - _pImpl->release(); -} - - -NetworkInterface& NetworkInterface::operator = (const NetworkInterface& interfc) -{ - NetworkInterface tmp(interfc); - swap(tmp); - return *this; -} - - -void NetworkInterface::swap(NetworkInterface& other) -{ - using std::swap; - swap(_pImpl, other._pImpl); -} - - -unsigned NetworkInterface::index() const -{ - return _pImpl->index(); -} - - -const std::string& NetworkInterface::name() const -{ - return _pImpl->name(); -} - - -const std::string& NetworkInterface::displayName() const -{ - return _pImpl->displayName(); -} - - -const std::string& NetworkInterface::adapterName() const -{ - return _pImpl->adapterName(); -} - - -const IPAddress& NetworkInterface::firstAddress(IPAddress::Family family) const -{ - return _pImpl->firstAddress(family); -} - - -void NetworkInterface::firstAddress(IPAddress& addr, IPAddress::Family family) const -{ - try - { - addr = firstAddress(family); - } - catch (NotFoundException&) - { - addr = IPAddress(family); - } -} - - -void NetworkInterface::addAddress(const IPAddress& address) -{ - _pImpl->addAddress(AddressTuple(address, IPAddress(), IPAddress())); -} - - -void NetworkInterface::addAddress(const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress) -{ - _pImpl->addAddress(AddressTuple(address, subnetMask, broadcastAddress)); -} - - -const IPAddress& NetworkInterface::address(unsigned index) const -{ - return _pImpl->address(index); -} - - -const NetworkInterface::AddressList& NetworkInterface::addressList() const -{ - return _pImpl->addressList(); -} - - -const IPAddress& NetworkInterface::subnetMask(unsigned index) const -{ - return _pImpl->subnetMask(index); -} - - -const IPAddress& NetworkInterface::broadcastAddress(unsigned index) const -{ - return _pImpl->broadcastAddress(index); -} - - -const NetworkInterface::MACAddress& NetworkInterface::macAddress() const -{ - return _pImpl->macAddress(); -} - - -const IPAddress& NetworkInterface::destAddress(unsigned index) const -{ - return _pImpl->destAddress(index); -} - - -unsigned NetworkInterface::mtu() const -{ - return _pImpl->mtu(); -} - - -NetworkInterface::Type NetworkInterface::type() const -{ - return _pImpl->type(); -} - - -bool NetworkInterface::supportsIP() const -{ - return _pImpl->supportsIPv4() || _pImpl->supportsIPv6(); -} - - -bool NetworkInterface::supportsIPv4() const -{ - return _pImpl->supportsIPv4(); -} - - -bool NetworkInterface::supportsIPv6() const -{ - return _pImpl->supportsIPv6(); -} - - -bool NetworkInterface::supportsBroadcast() const -{ - return _pImpl->broadcast(); -} - - -bool NetworkInterface::supportsMulticast() const -{ - return _pImpl->multicast(); -} - - -bool NetworkInterface::isLoopback() const -{ - return _pImpl->loopback(); -} - - -bool NetworkInterface::isPointToPoint() const -{ - return _pImpl->pointToPoint(); -} - - -bool NetworkInterface::isRunning() const -{ - return _pImpl->running(); -} - - -bool NetworkInterface::isUp() const -{ - return _pImpl->up(); -} - - -NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6) -{ - if (requireIPv6) - return forName(name, IPv6_ONLY); +// +// NetworkInterface.cpp +// +// Library: Net +// Package: NetCore +// Module: NetworkInterface +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/NetworkInterface.h" + + +#ifdef POCO_NET_HAS_INTERFACE + + +#include "Poco/Net/DatagramSocket.h" +#include "Poco/Net/NetException.h" +#include "Poco/NumberFormatter.h" +#include "Poco/NumberParser.h" +#include "Poco/StringTokenizer.h" +#include "Poco/RefCountedObject.h" +#include "Poco/Format.h" +#if defined(POCO_OS_FAMILY_WINDOWS) + #if defined(POCO_WIN32_UTF8) + #include "Poco/UnicodeConverter.h" + #endif + #include "Poco/Error.h" + #include <wincrypt.h> + #include <iphlpapi.h> + #include <ipifcons.h> +#endif +#include <cstring> +#include <fstream> +#include <iostream> +#include <iomanip> + + +using Poco::NumberFormatter; +using Poco::FastMutex; +using Poco::format; + + +std::ostream& operator << (std::ostream& os, const Poco::Net::NetworkInterface::MACAddress& mac) +{ + std::ios state(0); + state.copyfmt(os); + for (unsigned i = 0; i < mac.size(); ++i) + { + if (i > 0) os << Poco::Net::NetworkInterface::MAC_SEPARATOR; + os << std::hex << std::setw(2) << std::setfill('0') << (unsigned) mac[i]; + } + os.copyfmt(state); + return os; +} + + +namespace Poco { +namespace Net { + + +// +// NetworkInterfaceImpl +// + +class NetworkInterfaceImpl: public Poco::RefCountedObject +{ +public: + typedef NetworkInterface::AddressTuple AddressTuple; + typedef NetworkInterface::AddressList AddressList; + typedef NetworkInterface::Type Type; + + NetworkInterfaceImpl(unsigned index); + NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, NetworkInterface::MACAddress* pMACAddress = 0); + NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index = 0, NetworkInterface::MACAddress* pMACAddress = 0); + NetworkInterfaceImpl(const std::string& name, + const std::string& displayName, + const std::string& adapterName, + const IPAddress& address, + const IPAddress& subnetMask, + const IPAddress& broadcastAddress, + unsigned index, + NetworkInterface::MACAddress* pMACAddress = 0); + + unsigned index() const; + const std::string& name() const; + const std::string& displayName() const; + const std::string& adapterName() const; + const IPAddress& firstAddress(IPAddress::Family family) const; + void addAddress(const AddressTuple& address); + const IPAddress& address(unsigned index) const; + const NetworkInterface::AddressList& addressList() const; + bool hasAddress(const IPAddress& address) const; + const IPAddress& subnetMask(unsigned index) const; + const IPAddress& broadcastAddress(unsigned index) const; + const IPAddress& destAddress(unsigned index) const; + const NetworkInterface::MACAddress& macAddress() const; + bool supportsIPv4() const; + bool supportsIPv6() const; + + void setName(const std::string& name); + void setDisplayName(const std::string& name); + void setAdapterName(const std::string& name); + void addAddress(const IPAddress& addr); + void setMACAddress(const NetworkInterface::MACAddress& addr); + void setMACAddress(const void *addr, std::size_t len); + + unsigned mtu() const; + unsigned ifindex() const; + Type type() const; + + bool broadcast() const; + bool loopback() const; + bool multicast() const; + bool pointToPoint() const; + bool running() const; + bool up() const; + +#if defined(POCO_OS_FAMILY_WINDOWS) + void setFlags(DWORD flags, DWORD iftype); + void setRunning(bool running); +#else + void setFlags(short flags); +#endif + + void setUp(bool up); + void setMTU(unsigned mtu); + void setType(Type type); + void setIndex(unsigned index); + void setPhyParams(); + +protected: + ~NetworkInterfaceImpl(); + +private: + std::string _name; + std::string _displayName; + std::string _adapterName; + AddressList _addressList; + unsigned _index; + bool _broadcast; + bool _loopback; + bool _multicast; + bool _pointToPoint; + bool _up; + bool _running; + unsigned _mtu; + Type _type; + + NetworkInterface::MACAddress _macAddress; + + friend class NetworkInterface; +}; + + +NetworkInterfaceImpl::NetworkInterfaceImpl(unsigned index): + _index(index), + _broadcast(false), + _loopback(false), + _multicast(false), + _pointToPoint(false), + _up(false), + _running(false), + _mtu(0), + _type(NetworkInterface::NI_TYPE_OTHER) +{ +} + + +NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, NetworkInterface::MACAddress* pMACAddress): + _name(name), + _displayName(displayName), + _adapterName(adapterName), + _index(index), + _broadcast(false), + _loopback(false), + _multicast(false), + _pointToPoint(false), + _up(false), + _running(false), + _mtu(0), + _type(NetworkInterface::NI_TYPE_OTHER) +{ + _addressList.push_back(AddressTuple(address, IPAddress(), IPAddress())); + setPhyParams(); + if (pMACAddress) setMACAddress(*pMACAddress); +} + + +NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index, NetworkInterface::MACAddress* pMACAddress): + _name(name), + _displayName(displayName), + _adapterName(adapterName), + _index(index), + _broadcast(false), + _loopback(false), + _multicast(false), + _pointToPoint(false), + _up(false), + _running(false), + _mtu(0), + _type(NetworkInterface::NI_TYPE_OTHER) +{ + setPhyParams(); + if (pMACAddress) setMACAddress(*pMACAddress); +} + + +NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, + const std::string& displayName, + const std::string& adapterName, + const IPAddress& address, + const IPAddress& subnetMask, + const IPAddress& broadcastAddress, + unsigned index, + NetworkInterface::MACAddress* pMACAddress): + _name(name), + _displayName(displayName), + _adapterName(adapterName), + _index(index), + _broadcast(false), + _loopback(false), + _multicast(false), + _pointToPoint(false), + _up(false), + _running(false), + _mtu(0), + _type(NetworkInterface::NI_TYPE_OTHER) +{ + _addressList.push_back(AddressTuple(address, subnetMask, broadcastAddress)); + setPhyParams(); + if (pMACAddress) setMACAddress(*pMACAddress); +} + + +void NetworkInterfaceImpl::setPhyParams() +{ +#if !defined(POCO_OS_FAMILY_WINDOWS) && !defined(POCO_VXWORKS) + struct ifreq ifr; + std::strncpy(ifr.ifr_name, _name.c_str(), IFNAMSIZ); + DatagramSocket ds(SocketAddress::IPv4); + + ds.impl()->ioctl(SIOCGIFFLAGS, &ifr); + setFlags(ifr.ifr_flags); + + ds.impl()->ioctl(SIOCGIFMTU, &ifr); + setMTU(ifr.ifr_mtu); +#endif +} + + +NetworkInterfaceImpl::~NetworkInterfaceImpl() +{ +} + + +bool NetworkInterfaceImpl::supportsIPv4() const +{ + AddressList::const_iterator it = _addressList.begin(); + AddressList::const_iterator end = _addressList.end(); + for (; it != end; ++it) + { + if (IPAddress::IPv4 == it->get<NetworkInterface::IP_ADDRESS>().family()) + return true; + } + + return false; +} + + +bool NetworkInterfaceImpl::supportsIPv6() const +{ +#ifdef POCO_HAVE_IPv6 + AddressList::const_iterator it = _addressList.begin(); + AddressList::const_iterator end = _addressList.end(); + for (; it != end; ++it) + { + if (IPAddress::IPv6 == it->get<NetworkInterface::IP_ADDRESS>().family()) + return true; + } +#endif + return false; +} + + +inline unsigned NetworkInterfaceImpl::index() const +{ + return _index; +} + + +inline const std::string& NetworkInterfaceImpl::name() const +{ + return _name; +} + + +inline const std::string& NetworkInterfaceImpl::displayName() const +{ + return _displayName; +} + + +inline const std::string& NetworkInterfaceImpl::adapterName() const +{ + return _adapterName; +} + + +const IPAddress& NetworkInterfaceImpl::firstAddress(IPAddress::Family family) const +{ + AddressList::const_iterator it = _addressList.begin(); + AddressList::const_iterator end = _addressList.end(); + for (;it != end; ++it) + { + const IPAddress& addr = it->get<NetworkInterface::IP_ADDRESS>(); + if (addr.family() == family) return addr; + } + + throw NotFoundException(format("%s family address not found.", (family == IPAddress::IPv4) ? std::string("IPv4") : std::string("IPv6"))); +} + + +inline void NetworkInterfaceImpl::addAddress(const AddressTuple& address) +{ + _addressList.push_back(address); +} + + +bool NetworkInterfaceImpl::hasAddress(const IPAddress& address) const +{ + NetworkInterface::ConstAddressIterator it = _addressList.begin(); + NetworkInterface::ConstAddressIterator end = _addressList.end(); + for (; it != end; ++it) + { + if (it->get<NetworkInterface::IP_ADDRESS>() == address) + return true; + } + return false; +} + + +inline const IPAddress& NetworkInterfaceImpl::address(unsigned index) const +{ + if (index < _addressList.size()) return _addressList[index].get<NetworkInterface::IP_ADDRESS>(); + else throw NotFoundException(Poco::format("No address with index %u.", index)); +} + + +inline const NetworkInterface::AddressList& NetworkInterfaceImpl::addressList() const +{ + return _addressList; +} + + +const IPAddress& NetworkInterfaceImpl::subnetMask(unsigned index) const +{ + if (index < _addressList.size()) + return _addressList[index].get<NetworkInterface::SUBNET_MASK>(); + + throw NotFoundException(Poco::format("No subnet mask with index %u.", index)); +} + + +const IPAddress& NetworkInterfaceImpl::broadcastAddress(unsigned index) const +{ + if (index < _addressList.size()) + return _addressList[index].get<NetworkInterface::BROADCAST_ADDRESS>(); + + throw NotFoundException(Poco::format("No subnet mask with index %u.", index)); +} + + +const IPAddress& NetworkInterfaceImpl::destAddress(unsigned index) const +{ + if (!pointToPoint()) + throw InvalidAccessException("Only PPP addresses have destination address."); + else if (index < _addressList.size()) + return _addressList[index].get<NetworkInterface::BROADCAST_ADDRESS>(); + + throw NotFoundException(Poco::format("No address with index %u.", index)); +} + + +const NetworkInterface::MACAddress& NetworkInterfaceImpl::macAddress() const +{ + return _macAddress; +} + + +inline unsigned NetworkInterfaceImpl::mtu() const +{ + return _mtu; +} + + +inline NetworkInterface::Type NetworkInterfaceImpl::type() const +{ + return _type; +} + + +inline bool NetworkInterfaceImpl::broadcast() const +{ + return _broadcast; +} + + +inline bool NetworkInterfaceImpl::loopback() const +{ + return _loopback; +} + + +inline bool NetworkInterfaceImpl::multicast() const +{ + return _multicast; +} + + +inline bool NetworkInterfaceImpl::pointToPoint() const +{ + return _pointToPoint; +} + + +inline bool NetworkInterfaceImpl::running() const +{ + return _running; +} + + +inline bool NetworkInterfaceImpl::up() const +{ + return _up; +} + + +#if defined(POCO_OS_FAMILY_WINDOWS) + + +void NetworkInterfaceImpl::setFlags(DWORD flags, DWORD iftype) +{ + _running = _up = false; + switch (iftype) { + case IF_TYPE_ETHERNET_CSMACD: + case IF_TYPE_ISO88025_TOKENRING: + case IF_TYPE_IEEE80211: + _multicast = _broadcast = true; + break; + case IF_TYPE_SOFTWARE_LOOPBACK: + _loopback = true; + break; + case IF_TYPE_PPP: + case IF_TYPE_ATM: + case IF_TYPE_TUNNEL: + case IF_TYPE_IEEE1394: + _pointToPoint = true; + break; + } + if (!(flags & IP_ADAPTER_NO_MULTICAST)) + _multicast = true; +} + + +void NetworkInterfaceImpl::setRunning(bool running) +{ + _running = running; +} + + +#else + + +void NetworkInterfaceImpl::setFlags(short flags) +{ +#ifdef POCO_OS_FAMILY_UNIX + _broadcast = ((flags & IFF_BROADCAST) != 0); + _loopback = ((flags & IFF_LOOPBACK) != 0); + _multicast = ((flags & IFF_MULTICAST) != 0); + _pointToPoint = ((flags & IFF_POINTOPOINT) != 0); + _running = ((flags & IFF_RUNNING) != 0); + _up = ((flags & IFF_UP) != 0); +#endif +} + + +#endif + + +inline void NetworkInterfaceImpl::setUp(bool up) +{ + _up = up; +} + + +inline void NetworkInterfaceImpl::setMTU(unsigned mtu) +{ + _mtu = mtu; +} + + +inline void NetworkInterfaceImpl::setType(Type type) +{ + _type = type; +} + + +inline void NetworkInterfaceImpl::setIndex(unsigned index) +{ + _index = index; +} + + +inline void NetworkInterfaceImpl::setName(const std::string& name) +{ + _name = name; +} + + +inline void NetworkInterfaceImpl::setDisplayName(const std::string& name) +{ + _displayName = name; +} + + +inline void NetworkInterfaceImpl::setAdapterName(const std::string& name) +{ + _adapterName = name; +} + + +inline void NetworkInterfaceImpl::addAddress(const IPAddress& addr) +{ + _addressList.push_back(addr); +} + + +inline void NetworkInterfaceImpl::setMACAddress(const NetworkInterface::MACAddress& addr) +{ + _macAddress = addr; +} + + +inline void NetworkInterfaceImpl::setMACAddress(const void *addr, std::size_t len) +{ + _macAddress.clear(); + _macAddress.insert(_macAddress.end(), static_cast<const unsigned char*>(addr), static_cast<const unsigned char*>(addr) + len); +} + + +// +// NetworkInterface +// + + +FastMutex NetworkInterface::_mutex; + + +NetworkInterface::NetworkInterface(unsigned index): + _pImpl(new NetworkInterfaceImpl(index)) +{ +} + + +NetworkInterface::NetworkInterface(const NetworkInterface& interfc): + _pImpl(interfc._pImpl) +{ + _pImpl->duplicate(); +} + + +NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, MACAddress* pMACAddress): + _pImpl(new NetworkInterfaceImpl(name, displayName, adapterName, address, index, pMACAddress)) +{ +} + + +NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index, MACAddress* pMACAddress): + _pImpl(new NetworkInterfaceImpl(name, displayName, adapterName, index, pMACAddress)) +{ +} + + +NetworkInterface::NetworkInterface(const std::string& name, const IPAddress& address, unsigned index, MACAddress* pMACAddress): + _pImpl(new NetworkInterfaceImpl(name, name, name, address, index, pMACAddress)) +{ +} + + +NetworkInterface::NetworkInterface(const std::string& name, + const std::string& displayName, + const std::string& adapterName, + const IPAddress& address, + const IPAddress& subnetMask, + const IPAddress& broadcastAddress, + unsigned index, + MACAddress* pMACAddress): + _pImpl(new NetworkInterfaceImpl(name, displayName, adapterName, address, subnetMask, broadcastAddress, index, pMACAddress)) +{ +} + + +NetworkInterface::NetworkInterface(const std::string& name, + const IPAddress& address, + const IPAddress& subnetMask, + const IPAddress& broadcastAddress, + unsigned index, + MACAddress* pMACAddress): + _pImpl(new NetworkInterfaceImpl(name, name, name, address, subnetMask, broadcastAddress, index, pMACAddress)) +{ +} + + +NetworkInterface::~NetworkInterface() +{ + _pImpl->release(); +} + + +NetworkInterface& NetworkInterface::operator = (const NetworkInterface& interfc) +{ + NetworkInterface tmp(interfc); + swap(tmp); + return *this; +} + + +void NetworkInterface::swap(NetworkInterface& other) +{ + using std::swap; + swap(_pImpl, other._pImpl); +} + + +unsigned NetworkInterface::index() const +{ + return _pImpl->index(); +} + + +const std::string& NetworkInterface::name() const +{ + return _pImpl->name(); +} + + +const std::string& NetworkInterface::displayName() const +{ + return _pImpl->displayName(); +} + + +const std::string& NetworkInterface::adapterName() const +{ + return _pImpl->adapterName(); +} + + +const IPAddress& NetworkInterface::firstAddress(IPAddress::Family family) const +{ + return _pImpl->firstAddress(family); +} + + +void NetworkInterface::firstAddress(IPAddress& addr, IPAddress::Family family) const +{ + try + { + addr = firstAddress(family); + } + catch (NotFoundException&) + { + addr = IPAddress(family); + } +} + + +void NetworkInterface::addAddress(const IPAddress& address) +{ + _pImpl->addAddress(AddressTuple(address, IPAddress(), IPAddress())); +} + + +void NetworkInterface::addAddress(const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress) +{ + _pImpl->addAddress(AddressTuple(address, subnetMask, broadcastAddress)); +} + + +const IPAddress& NetworkInterface::address(unsigned index) const +{ + return _pImpl->address(index); +} + + +const NetworkInterface::AddressList& NetworkInterface::addressList() const +{ + return _pImpl->addressList(); +} + + +const IPAddress& NetworkInterface::subnetMask(unsigned index) const +{ + return _pImpl->subnetMask(index); +} + + +const IPAddress& NetworkInterface::broadcastAddress(unsigned index) const +{ + return _pImpl->broadcastAddress(index); +} + + +const NetworkInterface::MACAddress& NetworkInterface::macAddress() const +{ + return _pImpl->macAddress(); +} + + +const IPAddress& NetworkInterface::destAddress(unsigned index) const +{ + return _pImpl->destAddress(index); +} + + +unsigned NetworkInterface::mtu() const +{ + return _pImpl->mtu(); +} + + +NetworkInterface::Type NetworkInterface::type() const +{ + return _pImpl->type(); +} + + +bool NetworkInterface::supportsIP() const +{ + return _pImpl->supportsIPv4() || _pImpl->supportsIPv6(); +} + + +bool NetworkInterface::supportsIPv4() const +{ + return _pImpl->supportsIPv4(); +} + + +bool NetworkInterface::supportsIPv6() const +{ + return _pImpl->supportsIPv6(); +} + + +bool NetworkInterface::supportsBroadcast() const +{ + return _pImpl->broadcast(); +} + + +bool NetworkInterface::supportsMulticast() const +{ + return _pImpl->multicast(); +} + + +bool NetworkInterface::isLoopback() const +{ + return _pImpl->loopback(); +} + + +bool NetworkInterface::isPointToPoint() const +{ + return _pImpl->pointToPoint(); +} + + +bool NetworkInterface::isRunning() const +{ + return _pImpl->running(); +} + + +bool NetworkInterface::isUp() const +{ + return _pImpl->up(); +} + + +NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6) +{ + if (requireIPv6) + return forName(name, IPv6_ONLY); + else + return forName(name, IPv4_OR_IPv6); +} + + +NetworkInterface NetworkInterface::forName(const std::string& name, IPVersion ipVersion) +{ + Map map = NetworkInterface::map(false, false); + Map::const_iterator it = map.begin(); + Map::const_iterator end = map.end(); + + for (; it != end; ++it) + { + if (it->second.name() == name) + { + if (ipVersion == IPv4_ONLY && it->second.supportsIPv4()) + return it->second; + else if (ipVersion == IPv6_ONLY && it->second.supportsIPv6()) + return it->second; + else if (ipVersion == IPv4_OR_IPv6) + return it->second; + } + } + throw InterfaceNotFoundException(name); +} + + +NetworkInterface NetworkInterface::forAddress(const IPAddress& addr) +{ + Map map = NetworkInterface::map(true, false); + Map::const_iterator it = map.begin(); + Map::const_iterator end = map.end(); + + for (; it != end; ++it) + { + const std::size_t count = it->second.addressList().size(); + for (int i = 0; i < count; ++i) + { + if (it->second.address(i) == addr) + return it->second; + } + } + throw InterfaceNotFoundException(addr.toString()); +} + + +NetworkInterface NetworkInterface::forIndex(unsigned i) +{ + if (i != NetworkInterface::NO_INDEX) + { + Map map = NetworkInterface::map(false, false); + Map::const_iterator it = map.find(i); + if (it != map.end()) + return it->second; + else + throw InterfaceNotFoundException("#" + NumberFormatter::format(i)); + } + throw InterfaceNotFoundException("#" + NumberFormatter::format(i)); +} + + +NetworkInterface::List NetworkInterface::list(bool ipOnly, bool upOnly) +{ + List list; + Map m = map(ipOnly, upOnly); + NetworkInterface::Map::const_iterator it = m.begin(); + NetworkInterface::Map::const_iterator end = m.end(); + for (; it != end; ++it) + { + int index = it->second.index(); + std::string name = it->second.name(); + std::string displayName = it->second.displayName(); + std::string adapterName = it->second.adapterName(); + NetworkInterface::MACAddress mac = it->second.macAddress(); + + typedef NetworkInterface::AddressList AddrList; + const AddrList& ipList = it->second.addressList(); + if (ipList.size() > 0) + { + AddrList::const_iterator ipIt = ipList.begin(); + AddrList::const_iterator ipEnd = ipList.end(); + for(; ipIt != ipEnd; ++ipIt) + { + IPAddress addr = ipIt->get<NetworkInterface::IP_ADDRESS>(); + IPAddress mask = ipIt->get<NetworkInterface::SUBNET_MASK>(); + NetworkInterface ni; + if(mask.isWildcard()) + { + ni = NetworkInterface(name, displayName, adapterName, addr, index, &mac); + } + else + { + IPAddress broadcast = ipIt->get<NetworkInterface::BROADCAST_ADDRESS>(); + ni = NetworkInterface(name, displayName, adapterName, addr, mask, broadcast, index, &mac); + } + + ni._pImpl->_broadcast = it->second._pImpl->_broadcast; + ni._pImpl->_loopback = it->second._pImpl->_loopback; + ni._pImpl->_multicast = it->second._pImpl->_multicast; + ni._pImpl->_pointToPoint = it->second._pImpl->_pointToPoint; + ni._pImpl->_up = it->second._pImpl->_up; + ni._pImpl->_running = it->second._pImpl->_running; + ni._pImpl->_mtu = it->second._pImpl->_mtu; + ni._pImpl->_type = it->second._pImpl->_type; + + list.push_back(ni); + } + } + else + { + list.push_back(NetworkInterface(name, displayName, adapterName, index, &mac)); + } + } + + return list; +} + + +} } // namespace Poco::Net + + +// +// platform-specific code below +// + + +#if defined(POCO_OS_FAMILY_WINDOWS) +// +// Windows +// + + +#include "Poco/Buffer.h" +#include <iterator> + + +namespace Poco { +namespace Net { + + +namespace { + + +IPAddress getBroadcastAddress(PIP_ADAPTER_PREFIX pPrefix, const IPAddress& addr, ULONG* pprefix = 0) + /// This function relies on (1) subnet prefix being at the position + /// immediately preceding and (2) broadcast address being at the position + /// immediately succeeding the IPv4 unicast address. + /// + /// Since there is no explicit guarantee on order, to ensure correctness, + /// the above constraints are checked prior to returning the result. + /// Additionally, on pre-Vista versions on Windows, the main structure does + /// not contain prefix length; for those platforms, this function + /// returns prefix through pprefix argument. +{ + PIP_ADAPTER_PREFIX pPrev = 0; + for (int i = 0; pPrefix; pPrefix = pPrefix->Next, ++i) + { + ADDRESS_FAMILY family = pPrefix->Address.lpSockaddr->sa_family; + if ((family == AF_INET) && (addr == IPAddress(pPrefix->Address))) + break; + pPrev = pPrefix; + } + + if (pPrefix && pPrefix->Next && pPrev) + { + IPAddress ipPrefix(pPrev->PrefixLength, IPAddress::IPv4); + IPAddress mask(pPrefix->Next->Address); + if ((ipPrefix & mask) == (ipPrefix & addr)) + { + if (pprefix) *pprefix = pPrefix->PrefixLength; + return IPAddress(pPrefix->Next->Address); + } + } + + return IPAddress(IPAddress::IPv4); +} + + +NetworkInterface::Type fromNative(DWORD type) +{ + switch (type) + { + case IF_TYPE_ETHERNET_CSMACD: return NetworkInterface::NI_TYPE_ETHERNET_CSMACD; + case IF_TYPE_ISO88025_TOKENRING: return NetworkInterface::NI_TYPE_ISO88025_TOKENRING; + case IF_TYPE_FRAMERELAY: return NetworkInterface::NI_TYPE_FRAMERELAY; + case IF_TYPE_PPP: return NetworkInterface::NI_TYPE_PPP; + case IF_TYPE_SOFTWARE_LOOPBACK: return NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK; + case IF_TYPE_ATM: return NetworkInterface::NI_TYPE_ATM; + case IF_TYPE_IEEE80211: return NetworkInterface::NI_TYPE_IEEE80211; + case IF_TYPE_TUNNEL: return NetworkInterface::NI_TYPE_TUNNEL; + case IF_TYPE_IEEE1394: return NetworkInterface::NI_TYPE_IEEE1394; + default: return NetworkInterface::NI_TYPE_OTHER; + } +} + + +IPAddress subnetMaskForInterface(const std::string& name, bool isLoopback) +{ + if (isLoopback) + { + return IPAddress::parse("255.0.0.0"); + } else - return forName(name, IPv4_OR_IPv6); -} - - -NetworkInterface NetworkInterface::forName(const std::string& name, IPVersion ipVersion) -{ - Map map = NetworkInterface::map(false, false); - Map::const_iterator it = map.begin(); - Map::const_iterator end = map.end(); - - for (; it != end; ++it) - { - if (it->second.name() == name) - { - if (ipVersion == IPv4_ONLY && it->second.supportsIPv4()) - return it->second; - else if (ipVersion == IPv6_ONLY && it->second.supportsIPv6()) - return it->second; - else if (ipVersion == IPv4_OR_IPv6) - return it->second; - } - } - throw InterfaceNotFoundException(name); -} - - -NetworkInterface NetworkInterface::forAddress(const IPAddress& addr) -{ - Map map = NetworkInterface::map(true, false); - Map::const_iterator it = map.begin(); - Map::const_iterator end = map.end(); - - for (; it != end; ++it) - { - const std::size_t count = it->second.addressList().size(); - for (int i = 0; i < count; ++i) - { - if (it->second.address(i) == addr) - return it->second; - } - } - throw InterfaceNotFoundException(addr.toString()); -} - - -NetworkInterface NetworkInterface::forIndex(unsigned i) -{ - if (i != NetworkInterface::NO_INDEX) - { - Map map = NetworkInterface::map(false, false); - Map::const_iterator it = map.find(i); - if (it != map.end()) - return it->second; - else - throw InterfaceNotFoundException("#" + NumberFormatter::format(i)); - } - throw InterfaceNotFoundException("#" + NumberFormatter::format(i)); -} - - -NetworkInterface::List NetworkInterface::list(bool ipOnly, bool upOnly) -{ - List list; - Map m = map(ipOnly, upOnly); - NetworkInterface::Map::const_iterator it = m.begin(); - NetworkInterface::Map::const_iterator end = m.end(); - for (; it != end; ++it) - { - int index = it->second.index(); - std::string name = it->second.name(); - std::string displayName = it->second.displayName(); - std::string adapterName = it->second.adapterName(); - NetworkInterface::MACAddress mac = it->second.macAddress(); - - typedef NetworkInterface::AddressList AddrList; - const AddrList& ipList = it->second.addressList(); - if (ipList.size() > 0) - { - AddrList::const_iterator ipIt = ipList.begin(); - AddrList::const_iterator ipEnd = ipList.end(); - for(; ipIt != ipEnd; ++ipIt) - { - IPAddress addr = ipIt->get<NetworkInterface::IP_ADDRESS>(); - IPAddress mask = ipIt->get<NetworkInterface::SUBNET_MASK>(); - NetworkInterface ni; - if(mask.isWildcard()) - { - ni = NetworkInterface(name, displayName, adapterName, addr, index, &mac); - } - else - { - IPAddress broadcast = ipIt->get<NetworkInterface::BROADCAST_ADDRESS>(); - ni = NetworkInterface(name, displayName, adapterName, addr, mask, broadcast, index, &mac); - } - - ni._pImpl->_broadcast = it->second._pImpl->_broadcast; - ni._pImpl->_loopback = it->second._pImpl->_loopback; - ni._pImpl->_multicast = it->second._pImpl->_multicast; - ni._pImpl->_pointToPoint = it->second._pImpl->_pointToPoint; - ni._pImpl->_up = it->second._pImpl->_up; - ni._pImpl->_running = it->second._pImpl->_running; - ni._pImpl->_mtu = it->second._pImpl->_mtu; - ni._pImpl->_type = it->second._pImpl->_type; - - list.push_back(ni); - } - } - else - { - list.push_back(NetworkInterface(name, displayName, adapterName, index, &mac)); - } - } - - return list; -} - - -} } // namespace Poco::Net - - -// -// platform-specific code below -// - - -#if defined(POCO_OS_FAMILY_WINDOWS) -// -// Windows -// - - -#include "Poco/Buffer.h" -#include <iterator> - - -namespace Poco { -namespace Net { - - -namespace { - - -IPAddress getBroadcastAddress(PIP_ADAPTER_PREFIX pPrefix, const IPAddress& addr, ULONG* pprefix = 0) - /// This function relies on (1) subnet prefix being at the position - /// immediately preceding and (2) broadcast address being at the position - /// immediately succeeding the IPv4 unicast address. - /// - /// Since there is no explicit guarantee on order, to ensure correctness, - /// the above constraints are checked prior to returning the result. - /// Additionally, on pre-Vista versions on Windows, the main structure does - /// not contain prefix length; for those platforms, this function - /// returns prefix through pprefix argument. -{ - PIP_ADAPTER_PREFIX pPrev = 0; - for (int i = 0; pPrefix; pPrefix = pPrefix->Next, ++i) - { - ADDRESS_FAMILY family = pPrefix->Address.lpSockaddr->sa_family; - if ((family == AF_INET) && (addr == IPAddress(pPrefix->Address))) - break; - pPrev = pPrefix; - } - - if (pPrefix && pPrefix->Next && pPrev) - { - IPAddress ipPrefix(pPrev->PrefixLength, IPAddress::IPv4); - IPAddress mask(pPrefix->Next->Address); - if ((ipPrefix & mask) == (ipPrefix & addr)) - { - if (pprefix) *pprefix = pPrefix->PrefixLength; - return IPAddress(pPrefix->Next->Address); - } - } - - return IPAddress(IPAddress::IPv4); -} - - -NetworkInterface::Type fromNative(DWORD type) -{ - switch (type) - { - case IF_TYPE_ETHERNET_CSMACD: return NetworkInterface::NI_TYPE_ETHERNET_CSMACD; - case IF_TYPE_ISO88025_TOKENRING: return NetworkInterface::NI_TYPE_ISO88025_TOKENRING; - case IF_TYPE_FRAMERELAY: return NetworkInterface::NI_TYPE_FRAMERELAY; - case IF_TYPE_PPP: return NetworkInterface::NI_TYPE_PPP; - case IF_TYPE_SOFTWARE_LOOPBACK: return NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK; - case IF_TYPE_ATM: return NetworkInterface::NI_TYPE_ATM; - case IF_TYPE_IEEE80211: return NetworkInterface::NI_TYPE_IEEE80211; - case IF_TYPE_TUNNEL: return NetworkInterface::NI_TYPE_TUNNEL; - case IF_TYPE_IEEE1394: return NetworkInterface::NI_TYPE_IEEE1394; - default: return NetworkInterface::NI_TYPE_OTHER; - } -} - - -IPAddress subnetMaskForInterface(const std::string& name, bool isLoopback) -{ - if (isLoopback) - { - return IPAddress::parse("255.0.0.0"); - } - else - { -#if !defined(_WIN32_WCE) - std::string subKey("SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces\\"); - subKey += name; - std::string netmask; - HKEY hKey; -#if defined(POCO_WIN32_UTF8) && !defined(POCO_NO_WSTRING) - std::wstring usubKey; - Poco::UnicodeConverter::toUTF16(subKey, usubKey); - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, usubKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS) - return IPAddress(); - wchar_t unetmask[16]; - DWORD size = sizeof(unetmask); - if (RegQueryValueExW(hKey, L"DhcpSubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS) - { - if (RegQueryValueExW(hKey, L"SubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS) - { - RegCloseKey(hKey); - return IPAddress(); - } - } - Poco::UnicodeConverter::toUTF8(unetmask, netmask); -#else - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, subKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS) - return IPAddress(); - char unetmask[16]; - DWORD size = sizeof(unetmask); - if (RegQueryValueExA(hKey, "DhcpSubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS) - { - if (RegQueryValueExA(hKey, "SubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS) - { - RegCloseKey(hKey); - return IPAddress(); - } - } - netmask = unetmask; -#endif - RegCloseKey(hKey); - return IPAddress::parse(netmask); -#else - return IPAddress(); -#endif // !defined(_WIN32_WCE) - } -} - - -} /// namespace - - -NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly) -{ - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - - FastMutex::ScopedLock lock(_mutex); - Map result; - ULONG outBufLen = 16384; - Poco::Buffer<UCHAR> memory(outBufLen); - ULONG flags = (GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX); -#ifdef GAA_FLAG_INCLUDE_ALL_INTERFACES - flags |= GAA_FLAG_INCLUDE_ALL_INTERFACES; -#endif -#if defined(POCO_HAVE_IPv6) - const unsigned family = AF_UNSPEC; //IPv4 and IPv6 -#else - const unsigned family = AF_INET; //IPv4 only -#endif - DWORD dwRetVal = 0; - ULONG iterations = 0; - PIP_ADAPTER_ADDRESSES pAddress = 0; - do - { - pAddress = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(memory.begin()); // leave in the loop, begin may change after resize - poco_assert (memory.capacity() >= outBufLen); - if (ERROR_BUFFER_OVERFLOW == (dwRetVal = GetAdaptersAddresses(family, flags, 0, pAddress, &outBufLen))) - memory.resize(outBufLen, false); // adjust size and try again - else if (ERROR_NO_DATA == dwRetVal) // no network interfaces found - return result; - else if (NO_ERROR != dwRetVal) // error occurred - throw SystemException(format("An error occurred while trying to obtain list of network interfaces: [%s]", Error::getMessage(dwRetVal))); - else - break; + { +#if !defined(_WIN32_WCE) + std::string subKey("SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces\\"); + subKey += name; + std::string netmask; + HKEY hKey; +#if defined(POCO_WIN32_UTF8) && !defined(POCO_NO_WSTRING) + std::wstring usubKey; + Poco::UnicodeConverter::toUTF16(subKey, usubKey); + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, usubKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS) + return IPAddress(); + wchar_t unetmask[16]; + DWORD size = sizeof(unetmask); + if (RegQueryValueExW(hKey, L"DhcpSubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS) + { + if (RegQueryValueExW(hKey, L"SubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS) + { + RegCloseKey(hKey); + return IPAddress(); + } + } + Poco::UnicodeConverter::toUTF8(unetmask, netmask); +#else + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, subKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS) + return IPAddress(); + char unetmask[16]; + DWORD size = sizeof(unetmask); + if (RegQueryValueExA(hKey, "DhcpSubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS) + { + if (RegQueryValueExA(hKey, "SubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS) + { + RegCloseKey(hKey); + return IPAddress(); + } + } + netmask = unetmask; +#endif + RegCloseKey(hKey); + return IPAddress::parse(netmask); +#else + return IPAddress(); +#endif // !defined(_WIN32_WCE) + } +} + + +} /// namespace + + +NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly) +{ + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + + FastMutex::ScopedLock lock(_mutex); + Map result; + ULONG outBufLen = 16384; + Poco::Buffer<UCHAR> memory(outBufLen); + ULONG flags = (GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX); +#ifdef GAA_FLAG_INCLUDE_ALL_INTERFACES + flags |= GAA_FLAG_INCLUDE_ALL_INTERFACES; +#endif +#if defined(POCO_HAVE_IPv6) + const unsigned family = AF_UNSPEC; //IPv4 and IPv6 +#else + const unsigned family = AF_INET; //IPv4 only +#endif + DWORD dwRetVal = 0; + ULONG iterations = 0; + PIP_ADAPTER_ADDRESSES pAddress = 0; + do + { + pAddress = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(memory.begin()); // leave in the loop, begin may change after resize + poco_assert (memory.capacity() >= outBufLen); + if (ERROR_BUFFER_OVERFLOW == (dwRetVal = GetAdaptersAddresses(family, flags, 0, pAddress, &outBufLen))) + memory.resize(outBufLen, false); // adjust size and try again + else if (ERROR_NO_DATA == dwRetVal) // no network interfaces found + return result; + else if (NO_ERROR != dwRetVal) // error occurred + throw SystemException(format("An error occurred while trying to obtain list of network interfaces: [%s]", Error::getMessage(dwRetVal))); + else + break; + } + while ((ERROR_BUFFER_OVERFLOW == dwRetVal) && (++iterations <= 2)); + + poco_assert (NO_ERROR == dwRetVal); + for (; pAddress; pAddress = pAddress->Next) + { + IPAddress address; + IPAddress subnetMask; + IPAddress broadcastAddress; + unsigned ifIndex = 0; + +#if defined(POCO_HAVE_IPv6) + #if defined(_WIN32_WCE) + ifIndex = pAddress->Ipv6IfIndex; + #elif (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) // Win XP SP1 + #if defined (IP_ADAPTER_IPV6_ENABLED) // Vista + if(osvi.dwMajorVersion>=6)//vista + { + if ((pAddress->Flags & IP_ADAPTER_IPV6_ENABLED) && + (osvi.dwMajorVersion >= 5) && + (osvi.dwMinorVersion >= 1) && + (osvi.dwBuildNumber >=1)) + { + ifIndex = pAddress->Ipv6IfIndex; + } + } + else + { + if ((osvi.dwMajorVersion >= 5) && + (osvi.dwMinorVersion >= 1) && + (osvi.dwBuildNumber >= 1)) + { + ifIndex = pAddress->Ipv6IfIndex; + } + } + #else // !defined(IP_ADAPTER_IPV6_ENABLED) + if ((osvi.dwMajorVersion >= 5) && + (osvi.dwMinorVersion >= 1) && + (osvi.dwBuildNumber >= 1)) + { + ifIndex = pAddress->Ipv6IfIndex; + } + #endif // defined(IP_ADAPTER_IPV6_ENABLED) + #endif // (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) +#endif // POCO_HAVE_IPv6 + +#if defined (IP_ADAPTER_IPV4_ENABLED) + if(osvi.dwMajorVersion>=6) + {//vista + if (pAddress->Flags & IP_ADAPTER_IPV4_ENABLED) + { + ifIndex = pAddress->IfIndex; + } + } + else + { + ifIndex = pAddress->IfIndex; + } +#else // !IP_ADAPTER_IPV4_ENABLED + ifIndex = pAddress->IfIndex; +#endif + if (ifIndex == 0) continue; + + std::string name; + std::string displayName; + std::string adapterName(pAddress->AdapterName); +#ifdef POCO_WIN32_UTF8 + Poco::UnicodeConverter::toUTF8(pAddress->FriendlyName, name); + Poco::UnicodeConverter::toUTF8(pAddress->Description, displayName); +#else + char nameBuffer[1024]; + int rc = WideCharToMultiByte(CP_ACP, 0, pAddress->FriendlyName, -1, nameBuffer, sizeof(nameBuffer), NULL, NULL); + if (rc) name = nameBuffer; + char displayNameBuffer[1024]; + rc = WideCharToMultiByte(CP_ACP, 0, pAddress->Description, -1, displayNameBuffer, sizeof(displayNameBuffer), NULL, NULL); + if (rc) displayName = displayNameBuffer; +#endif + + bool isUp = (pAddress->OperStatus == IfOperStatusUp); + bool isIP = (0 != pAddress->FirstUnicastAddress); + if (((ipOnly && isIP) || !ipOnly) && ((upOnly && isUp) || !upOnly)) + { + NetworkInterface ni(name, displayName, adapterName, ifIndex); + // Create interface even if it has an empty list of addresses; also, set + // physical attributes which are protocol independent (name, media type, + // MAC address, MTU, operational status, etc). + Map::iterator ifIt = result.find(ifIndex); + if (ifIt == result.end()) + ifIt = result.insert(Map::value_type(ifIndex, ni)).first; + + ifIt->second.impl().setFlags(pAddress->Flags, pAddress->IfType); + ifIt->second.impl().setMTU(pAddress->Mtu); + ifIt->second.impl().setUp(pAddress->OperStatus == IfOperStatusUp); +#if (_WIN32_WINNT >= 0x0600) // Vista and newer only + if ((osvi.dwMajorVersion >= 6) && + (osvi.dwMinorVersion >= 0) && + (osvi.dwBuildNumber >= 0)) + { + ifIt->second.impl().setRunning(pAddress->ReceiveLinkSpeed > 0 || pAddress->TransmitLinkSpeed > 0); + } +#endif + ifIt->second.impl().setType(fromNative(pAddress->IfType)); + if (pAddress->PhysicalAddressLength) + ifIt->second.impl().setMACAddress(pAddress->PhysicalAddress, pAddress->PhysicalAddressLength); + + for (PIP_ADAPTER_UNICAST_ADDRESS pUniAddr = pAddress->FirstUnicastAddress; + pUniAddr; + pUniAddr = pUniAddr->Next) + { + address = IPAddress(pUniAddr->Address); + ADDRESS_FAMILY family2 = pUniAddr->Address.lpSockaddr->sa_family; + switch (family2) + { + case AF_INET: + { + // Windows lists broadcast address on localhost + bool hasBroadcast = (pAddress->IfType == IF_TYPE_ETHERNET_CSMACD) || (pAddress->IfType == IF_TYPE_SOFTWARE_LOOPBACK) || (pAddress->IfType == IF_TYPE_IEEE80211); + if (hasBroadcast) + { + // On Windows, a valid broadcast address will be all 1's (== address | ~subnetMask); additionaly, on pre-Vista versions of + // OS, master address structure does not contain member for prefix length; we go an extra mile here in order to make sure + // we reflect the actual values held by system and protect against misconfiguration (e.g. bad DHCP config entry) + ULONG prefixLength = 0; +#if defined(_WIN32_WCE) + #if _WIN32_WCE >= 0x0800 + prefixLength = pUniAddr->OnLinkPrefixLength; + broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address); + #else + broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength); + #endif + // if previous call did not do it, make last-ditch attempt for prefix and broadcast + if (prefixLength == 0 && pAddress->FirstPrefix) + prefixLength = pAddress->FirstPrefix->PrefixLength; + poco_assert (prefixLength <= 32); + if (broadcastAddress.isWildcard()) + { + IPAddress mask(static_cast<unsigned>(prefixLength), IPAddress::IPv4); + IPAddress host(mask & address); + broadcastAddress = host | ~mask; + } +#elif (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) // Win XP SP1 + #if (_WIN32_WINNT >= 0x0600) // Vista and newer + if (osvi.dwMajorVersion >= 6) + { + prefixLength = pUniAddr->OnLinkPrefixLength; + broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address); + } + else + { + broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength); + } + #else + broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength); + #endif + poco_assert (prefixLength <= 32); + if (broadcastAddress.isWildcard()) + { + IPAddress mask(static_cast<unsigned>(prefixLength), IPAddress::IPv4); + IPAddress host(mask & address); + broadcastAddress = host | ~mask; + } +#endif // (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) + if (prefixLength) + { + subnetMask = IPAddress(static_cast<unsigned>(prefixLength), IPAddress::IPv4); + } + else // if all of the above fails, look up the subnet mask in the registry + { + address = IPAddress(&reinterpret_cast<struct sockaddr_in*>(pUniAddr->Address.lpSockaddr)->sin_addr, sizeof(in_addr)); + subnetMask = subnetMaskForInterface(name, address.isLoopback()); + if (!address.isLoopback()) + { + broadcastAddress = address; + broadcastAddress.mask(subnetMask, IPAddress::broadcast()); + } + } + ifIt->second.addAddress(address, subnetMask, broadcastAddress); + } + else + { + ifIt->second.addAddress(address); + } + } + break; +#if defined(POCO_HAVE_IPv6) + case AF_INET6: + ifIt->second.addAddress(address); + break; +#endif + } // switch family + } // for addresses + } // if ipOnly/upOnly + } // for adapters + return result; +} + + +} } // namespace Poco::Net + + +#elif defined(POCO_VXWORKS) +// +// VxWorks +// + +#error TODO + +/* +namespace Poco { +namespace Net { + + +NetworkInterface::NetworkInterfaceList NetworkInterface::list() +{ + FastMutex::ScopedLock lock(_mutex); + NetworkInterfaceList result; + + int ifIndex = 1; + char ifName[32]; + char ifAddr[INET_ADDR_LEN]; + + for (;;) + { + if (ifIndexToIfName(ifIndex, ifName) == OK) + { + std::string name(ifName); + IPAddress addr; + IPAddress mask; + IPAddress bcst; + if (ifAddrGet(ifName, ifAddr) == OK) + { + addr = IPAddress(std::string(ifAddr)); + } + int ifMask; + if (ifMaskGet(ifName, &ifMask) == OK) + { + mask = IPAddress(&ifMask, sizeof(ifMask)); + } + if (ifBroadcastGet(ifName, ifAddr) == OK) + { + bcst = IPAddress(std::string(ifAddr)); + } + result.push_back(NetworkInterface(name, name, name, addr, mask, bcst)); + ifIndex++; + } + else break; + } + + return result; +} + + +} } // namespace Poco::Net +*/ + +#elif defined(POCO_OS_FAMILY_BSD) || (POCO_OS == POCO_OS_QNX) || (POCO_OS == POCO_OS_SOLARIS) +// +// BSD variants, QNX(?) and Solaris +// +#include <sys/types.h> +#include <sys/socket.h> +#include <ifaddrs.h> +#include <net/if.h> +#include <net/if_dl.h> +#ifndef POCO_NO_NET_IFTYPES +#include <net/if_types.h> +#endif + + +namespace Poco { +namespace Net { + + +namespace { + + +NetworkInterface::Type fromNative(u_char nativeType) +{ + switch (nativeType) + { +#ifndef POCO_NO_NET_IFTYPES + case IFT_ETHER: return NetworkInterface::NI_TYPE_ETHERNET_CSMACD; + case IFT_ISO88025: return NetworkInterface::NI_TYPE_ISO88025_TOKENRING; + case IFT_FRELAY: return NetworkInterface::NI_TYPE_FRAMERELAY; + case IFT_PPP: return NetworkInterface::NI_TYPE_PPP; + case IFT_LOOP: return NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK; + case IFT_ATM: return NetworkInterface::NI_TYPE_ATM; +#if (POCO_OS != POCO_OS_SOLARIS) + case IFT_IEEE1394: return NetworkInterface::NI_TYPE_IEEE1394; +#endif +#endif + default: return NetworkInterface::NI_TYPE_OTHER; + } - while ((ERROR_BUFFER_OVERFLOW == dwRetVal) && (++iterations <= 2)); - - poco_assert (NO_ERROR == dwRetVal); - for (; pAddress; pAddress = pAddress->Next) - { - IPAddress address; - IPAddress subnetMask; - IPAddress broadcastAddress; - unsigned ifIndex = 0; - -#if defined(POCO_HAVE_IPv6) - #if defined(_WIN32_WCE) - ifIndex = pAddress->Ipv6IfIndex; - #elif (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) // Win XP SP1 - #if defined (IP_ADAPTER_IPV6_ENABLED) // Vista - if(osvi.dwMajorVersion>=6)//vista - { - if ((pAddress->Flags & IP_ADAPTER_IPV6_ENABLED) && - (osvi.dwMajorVersion >= 5) && - (osvi.dwMinorVersion >= 1) && - (osvi.dwBuildNumber >=1)) - { - ifIndex = pAddress->Ipv6IfIndex; - } - } - else - { - if ((osvi.dwMajorVersion >= 5) && - (osvi.dwMinorVersion >= 1) && - (osvi.dwBuildNumber >= 1)) - { - ifIndex = pAddress->Ipv6IfIndex; - } - } - #else // !defined(IP_ADAPTER_IPV6_ENABLED) - if ((osvi.dwMajorVersion >= 5) && - (osvi.dwMinorVersion >= 1) && - (osvi.dwBuildNumber >= 1)) - { - ifIndex = pAddress->Ipv6IfIndex; - } - #endif // defined(IP_ADAPTER_IPV6_ENABLED) - #endif // (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) -#endif // POCO_HAVE_IPv6 - -#if defined (IP_ADAPTER_IPV4_ENABLED) - if(osvi.dwMajorVersion>=6) - {//vista - if (pAddress->Flags & IP_ADAPTER_IPV4_ENABLED) - { - ifIndex = pAddress->IfIndex; - } - } - else - { - ifIndex = pAddress->IfIndex; - } -#else // !IP_ADAPTER_IPV4_ENABLED - ifIndex = pAddress->IfIndex; -#endif - if (ifIndex == 0) continue; - - std::string name; - std::string displayName; - std::string adapterName(pAddress->AdapterName); -#ifdef POCO_WIN32_UTF8 - Poco::UnicodeConverter::toUTF8(pAddress->FriendlyName, name); - Poco::UnicodeConverter::toUTF8(pAddress->Description, displayName); -#else - char nameBuffer[1024]; - int rc = WideCharToMultiByte(CP_ACP, 0, pAddress->FriendlyName, -1, nameBuffer, sizeof(nameBuffer), NULL, NULL); - if (rc) name = nameBuffer; - char displayNameBuffer[1024]; - rc = WideCharToMultiByte(CP_ACP, 0, pAddress->Description, -1, displayNameBuffer, sizeof(displayNameBuffer), NULL, NULL); - if (rc) displayName = displayNameBuffer; -#endif - - bool isUp = (pAddress->OperStatus == IfOperStatusUp); - bool isIP = (0 != pAddress->FirstUnicastAddress); - if (((ipOnly && isIP) || !ipOnly) && ((upOnly && isUp) || !upOnly)) - { - NetworkInterface ni(name, displayName, adapterName, ifIndex); - // Create interface even if it has an empty list of addresses; also, set - // physical attributes which are protocol independent (name, media type, - // MAC address, MTU, operational status, etc). - Map::iterator ifIt = result.find(ifIndex); - if (ifIt == result.end()) - ifIt = result.insert(Map::value_type(ifIndex, ni)).first; - - ifIt->second.impl().setFlags(pAddress->Flags, pAddress->IfType); - ifIt->second.impl().setMTU(pAddress->Mtu); - ifIt->second.impl().setUp(pAddress->OperStatus == IfOperStatusUp); -#if (_WIN32_WINNT >= 0x0600) // Vista and newer only - if ((osvi.dwMajorVersion >= 6) && - (osvi.dwMinorVersion >= 0) && - (osvi.dwBuildNumber >= 0)) - { - ifIt->second.impl().setRunning(pAddress->ReceiveLinkSpeed > 0 || pAddress->TransmitLinkSpeed > 0); - } -#endif - ifIt->second.impl().setType(fromNative(pAddress->IfType)); - if (pAddress->PhysicalAddressLength) - ifIt->second.impl().setMACAddress(pAddress->PhysicalAddress, pAddress->PhysicalAddressLength); - - for (PIP_ADAPTER_UNICAST_ADDRESS pUniAddr = pAddress->FirstUnicastAddress; - pUniAddr; - pUniAddr = pUniAddr->Next) - { - address = IPAddress(pUniAddr->Address); - ADDRESS_FAMILY family2 = pUniAddr->Address.lpSockaddr->sa_family; - switch (family2) - { - case AF_INET: - { - // Windows lists broadcast address on localhost - bool hasBroadcast = (pAddress->IfType == IF_TYPE_ETHERNET_CSMACD) || (pAddress->IfType == IF_TYPE_SOFTWARE_LOOPBACK) || (pAddress->IfType == IF_TYPE_IEEE80211); - if (hasBroadcast) - { - // On Windows, a valid broadcast address will be all 1's (== address | ~subnetMask); additionaly, on pre-Vista versions of - // OS, master address structure does not contain member for prefix length; we go an extra mile here in order to make sure - // we reflect the actual values held by system and protect against misconfiguration (e.g. bad DHCP config entry) - ULONG prefixLength = 0; -#if defined(_WIN32_WCE) - #if _WIN32_WCE >= 0x0800 - prefixLength = pUniAddr->OnLinkPrefixLength; - broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address); - #else - broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength); - #endif - // if previous call did not do it, make last-ditch attempt for prefix and broadcast - if (prefixLength == 0 && pAddress->FirstPrefix) - prefixLength = pAddress->FirstPrefix->PrefixLength; - poco_assert (prefixLength <= 32); - if (broadcastAddress.isWildcard()) - { - IPAddress mask(static_cast<unsigned>(prefixLength), IPAddress::IPv4); - IPAddress host(mask & address); - broadcastAddress = host | ~mask; - } -#elif (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) // Win XP SP1 - #if (_WIN32_WINNT >= 0x0600) // Vista and newer - if (osvi.dwMajorVersion >= 6) - { - prefixLength = pUniAddr->OnLinkPrefixLength; - broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address); - } - else - { - broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength); - } - #else - broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength); - #endif - poco_assert (prefixLength <= 32); - if (broadcastAddress.isWildcard()) - { - IPAddress mask(static_cast<unsigned>(prefixLength), IPAddress::IPv4); - IPAddress host(mask & address); - broadcastAddress = host | ~mask; - } -#endif // (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) - if (prefixLength) - { - subnetMask = IPAddress(static_cast<unsigned>(prefixLength), IPAddress::IPv4); - } - else // if all of the above fails, look up the subnet mask in the registry - { - address = IPAddress(&reinterpret_cast<struct sockaddr_in*>(pUniAddr->Address.lpSockaddr)->sin_addr, sizeof(in_addr)); - subnetMask = subnetMaskForInterface(name, address.isLoopback()); - if (!address.isLoopback()) - { - broadcastAddress = address; - broadcastAddress.mask(subnetMask, IPAddress::broadcast()); - } - } - ifIt->second.addAddress(address, subnetMask, broadcastAddress); - } - else - { - ifIt->second.addAddress(address); - } +} + + +void setInterfaceParams(struct ifaddrs* iface, NetworkInterfaceImpl& impl) +{ + struct sockaddr_dl* sdl = (struct sockaddr_dl*) iface->ifa_addr; + impl.setName(iface->ifa_name); + impl.setDisplayName(iface->ifa_name); + impl.setAdapterName(iface->ifa_name); + impl.setPhyParams(); + + impl.setMACAddress(LLADDR(sdl), sdl->sdl_alen); + impl.setType(fromNative(sdl->sdl_type)); +} + + +} // namespace + + +NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly) +{ + FastMutex::ScopedLock lock(_mutex); + Map result; + unsigned ifIndex = 0; + NetworkInterface intf; + Map::iterator ifIt; + + struct ifaddrs* ifaces = 0; + struct ifaddrs* currIface = 0; + + if (getifaddrs(&ifaces) < 0) + throw NetException("cannot get network adapter list"); + + try + { + for (currIface = ifaces; currIface != 0; currIface = currIface->ifa_next) + { + if (!currIface->ifa_addr) continue; + + IPAddress address, subnetMask, broadcastAddress; + unsigned family = currIface->ifa_addr->sa_family; + switch (family) + { +#if defined(POCO_OS_FAMILY_BSD) + case AF_LINK: + { + struct sockaddr_dl* sdl = (struct sockaddr_dl*) currIface->ifa_addr; + ifIndex = sdl->sdl_index; + intf = NetworkInterface(ifIndex); + setInterfaceParams(currIface, intf.impl()); + if ((result.find(ifIndex) == result.end()) && ((upOnly && intf.isUp()) || !upOnly)) + ifIt = result.insert(Map::value_type(ifIndex, intf)).first; + break; + } +#endif + case AF_INET: + ifIndex = if_nametoindex(currIface->ifa_name); + ifIt = result.find(ifIndex); + intf = NetworkInterface(ifIndex); + setInterfaceParams(currIface, intf.impl()); + if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly)) + ifIt = result.insert(Map::value_type(ifIndex, intf)).first; + + address = IPAddress(*(currIface->ifa_addr)); + + if (( currIface->ifa_flags & IFF_LOOPBACK ) == 0 && currIface->ifa_netmask) + subnetMask = IPAddress(*(currIface->ifa_netmask)); + + if (currIface->ifa_flags & IFF_BROADCAST && currIface->ifa_broadaddr) + broadcastAddress = IPAddress(*(currIface->ifa_broadaddr)); + else if (currIface->ifa_flags & IFF_POINTOPOINT && currIface->ifa_dstaddr) + broadcastAddress = IPAddress(*(currIface->ifa_dstaddr)); + else + broadcastAddress = IPAddress(); + break; +#if defined(POCO_HAVE_IPv6) + case AF_INET6: + ifIndex = if_nametoindex(currIface->ifa_name); + ifIt = result.find(ifIndex); + intf = NetworkInterface(ifIndex); + setInterfaceParams(currIface, intf.impl()); + if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly)) + ifIt = result.insert(Map::value_type(ifIndex, intf)).first; + + address = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(currIface->ifa_addr)->sin6_addr, + sizeof(struct in6_addr), ifIndex); + subnetMask = IPAddress(*(currIface->ifa_netmask)); + broadcastAddress = IPAddress(); + break; +#endif + default: + continue; + } + + if (family == AF_INET +#ifdef POCO_HAVE_IPv6 + || family == AF_INET6 +#endif + ) + { + if ((upOnly && intf.isUp()) || !upOnly) + { + if ((ifIt = result.find(ifIndex)) != result.end()) + ifIt->second.addAddress(address, subnetMask, broadcastAddress); } - break; -#if defined(POCO_HAVE_IPv6) - case AF_INET6: - ifIt->second.addAddress(address); - break; -#endif - } // switch family - } // for addresses - } // if ipOnly/upOnly - } // for adapters - return result; -} - - -} } // namespace Poco::Net - - -#elif defined(POCO_VXWORKS) -// -// VxWorks -// - -#error TODO - -/* -namespace Poco { -namespace Net { - - -NetworkInterface::NetworkInterfaceList NetworkInterface::list() -{ - FastMutex::ScopedLock lock(_mutex); - NetworkInterfaceList result; - - int ifIndex = 1; - char ifName[32]; - char ifAddr[INET_ADDR_LEN]; - - for (;;) - { - if (ifIndexToIfName(ifIndex, ifName) == OK) - { - std::string name(ifName); - IPAddress addr; - IPAddress mask; - IPAddress bcst; - if (ifAddrGet(ifName, ifAddr) == OK) - { - addr = IPAddress(std::string(ifAddr)); - } - int ifMask; - if (ifMaskGet(ifName, &ifMask) == OK) - { - mask = IPAddress(&ifMask, sizeof(ifMask)); - } - if (ifBroadcastGet(ifName, ifAddr) == OK) - { - bcst = IPAddress(std::string(ifAddr)); - } - result.push_back(NetworkInterface(name, name, name, addr, mask, bcst)); - ifIndex++; - } - else break; - } - - return result; -} - - -} } // namespace Poco::Net -*/ - -#elif defined(POCO_OS_FAMILY_BSD) || (POCO_OS == POCO_OS_QNX) || (POCO_OS == POCO_OS_SOLARIS) -// -// BSD variants, QNX(?) and Solaris -// -#include <sys/types.h> -#include <sys/socket.h> -#include <ifaddrs.h> -#include <net/if.h> -#include <net/if_dl.h> -#ifndef POCO_NO_NET_IFTYPES -#include <net/if_types.h> -#endif - - -namespace Poco { -namespace Net { - - -namespace { - - -NetworkInterface::Type fromNative(u_char nativeType) -{ - switch (nativeType) - { -#ifndef POCO_NO_NET_IFTYPES - case IFT_ETHER: return NetworkInterface::NI_TYPE_ETHERNET_CSMACD; - case IFT_ISO88025: return NetworkInterface::NI_TYPE_ISO88025_TOKENRING; - case IFT_FRELAY: return NetworkInterface::NI_TYPE_FRAMERELAY; - case IFT_PPP: return NetworkInterface::NI_TYPE_PPP; - case IFT_LOOP: return NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK; - case IFT_ATM: return NetworkInterface::NI_TYPE_ATM; -#if (POCO_OS != POCO_OS_SOLARIS) - case IFT_IEEE1394: return NetworkInterface::NI_TYPE_IEEE1394; -#endif -#endif - default: return NetworkInterface::NI_TYPE_OTHER; - - } -} - - -void setInterfaceParams(struct ifaddrs* iface, NetworkInterfaceImpl& impl) -{ - struct sockaddr_dl* sdl = (struct sockaddr_dl*) iface->ifa_addr; - impl.setName(iface->ifa_name); - impl.setDisplayName(iface->ifa_name); - impl.setAdapterName(iface->ifa_name); - impl.setPhyParams(); - - impl.setMACAddress(LLADDR(sdl), sdl->sdl_alen); - impl.setType(fromNative(sdl->sdl_type)); -} - - -} // namespace - - -NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly) -{ - FastMutex::ScopedLock lock(_mutex); - Map result; - unsigned ifIndex = 0; - NetworkInterface intf; - Map::iterator ifIt; - - struct ifaddrs* ifaces = 0; - struct ifaddrs* currIface = 0; - - if (getifaddrs(&ifaces) < 0) - throw NetException("cannot get network adapter list"); - - try - { - for (currIface = ifaces; currIface != 0; currIface = currIface->ifa_next) - { - if (!currIface->ifa_addr) continue; - - IPAddress address, subnetMask, broadcastAddress; - unsigned family = currIface->ifa_addr->sa_family; - switch (family) - { -#if defined(POCO_OS_FAMILY_BSD) - case AF_LINK: - { - struct sockaddr_dl* sdl = (struct sockaddr_dl*) currIface->ifa_addr; - ifIndex = sdl->sdl_index; - intf = NetworkInterface(ifIndex); - setInterfaceParams(currIface, intf.impl()); - if ((result.find(ifIndex) == result.end()) && ((upOnly && intf.isUp()) || !upOnly)) - ifIt = result.insert(Map::value_type(ifIndex, intf)).first; - break; - } -#endif - case AF_INET: - ifIndex = if_nametoindex(currIface->ifa_name); - ifIt = result.find(ifIndex); - intf = NetworkInterface(ifIndex); - setInterfaceParams(currIface, intf.impl()); - if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly)) - ifIt = result.insert(Map::value_type(ifIndex, intf)).first; - - address = IPAddress(*(currIface->ifa_addr)); - - if (( currIface->ifa_flags & IFF_LOOPBACK ) == 0 && currIface->ifa_netmask) - subnetMask = IPAddress(*(currIface->ifa_netmask)); - - if (currIface->ifa_flags & IFF_BROADCAST && currIface->ifa_broadaddr) - broadcastAddress = IPAddress(*(currIface->ifa_broadaddr)); - else if (currIface->ifa_flags & IFF_POINTOPOINT && currIface->ifa_dstaddr) - broadcastAddress = IPAddress(*(currIface->ifa_dstaddr)); - else - broadcastAddress = IPAddress(); - break; -#if defined(POCO_HAVE_IPv6) - case AF_INET6: - ifIndex = if_nametoindex(currIface->ifa_name); - ifIt = result.find(ifIndex); - intf = NetworkInterface(ifIndex); - setInterfaceParams(currIface, intf.impl()); - if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly)) - ifIt = result.insert(Map::value_type(ifIndex, intf)).first; - - address = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(currIface->ifa_addr)->sin6_addr, - sizeof(struct in6_addr), ifIndex); - subnetMask = IPAddress(*(currIface->ifa_netmask)); - broadcastAddress = IPAddress(); - break; -#endif - default: - continue; - } - - if (family == AF_INET -#ifdef POCO_HAVE_IPv6 - || family == AF_INET6 -#endif - ) - { - if ((upOnly && intf.isUp()) || !upOnly) - { - if ((ifIt = result.find(ifIndex)) != result.end()) - ifIt->second.addAddress(address, subnetMask, broadcastAddress); - } - } - } - } - catch (...) - { - } - if (ifaces) freeifaddrs(ifaces); - - if (ipOnly) - { - Map::iterator it = result.begin(); - Map::iterator end = result.end(); - for (; it != end;) - { - if (!it->second.supportsIPv4() && !it->second.supportsIPv6()) - result.erase(it++); - else ++it; - } - } - - return result; -} - - -} } // namespace Poco::Net - - -#elif POCO_OS == POCO_OS_LINUX || POCO_OS == POCO_OS_ANDROID -// -// Linux -// - - -#include <sys/types.h> -#if POCO_OS != POCO_OS_ANDROID // Android doesn't have <ifaddrs.h> -#include <ifaddrs.h> -#endif -#include <net/if.h> -#ifndef POCO_NO_LINUX_IF_PACKET_H -#include <linux/if_packet.h> -#endif -#include <net/if_arp.h> -#include <iostream> - -namespace Poco { -namespace Net { - - -namespace { - - -static NetworkInterface::Type fromNative(unsigned arphrd) -{ - switch (arphrd) - { - case ARPHRD_ETHER: return NetworkInterface::NI_TYPE_ETHERNET_CSMACD; - case ARPHRD_IEEE802: return NetworkInterface::NI_TYPE_ISO88025_TOKENRING; - case ARPHRD_DLCI: return NetworkInterface::NI_TYPE_FRAMERELAY; - case ARPHRD_PPP: return NetworkInterface::NI_TYPE_PPP; - case ARPHRD_LOOPBACK: return NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK; - case ARPHRD_ATM: return NetworkInterface::NI_TYPE_ATM; - case ARPHRD_IEEE80211: return NetworkInterface::NI_TYPE_IEEE80211; - case ARPHRD_TUNNEL: - case ARPHRD_TUNNEL6: return NetworkInterface::NI_TYPE_TUNNEL; - case ARPHRD_IEEE1394: return NetworkInterface::NI_TYPE_IEEE1394; - default: return NetworkInterface::NI_TYPE_OTHER; - } -} - -#if POCO_OS != POCO_OS_ANDROID - -void setInterfaceParams(struct ifaddrs* iface, NetworkInterfaceImpl& impl) -{ - impl.setName(iface->ifa_name); - impl.setDisplayName(iface->ifa_name); - impl.setAdapterName(iface->ifa_name); - impl.setPhyParams(); - -#ifndef POCO_NO_LINUX_IF_PACKET_H - struct sockaddr_ll* sdl = (struct sockaddr_ll*) iface->ifa_addr; - impl.setMACAddress(sdl->sll_addr, sdl->sll_halen); - impl.setType(fromNative(sdl->sll_hatype)); -#else - std::string ifPath("/sys/class/net/"); - ifPath += iface->ifa_name; - - std::string addrPath(ifPath); - addrPath += "/address"; - - std::ifstream addrStream(addrPath.c_str()); - if (addrStream.good()) - { - std::string addr; - std::getline(addrStream, addr); - Poco::StringTokenizer tok(addr, ":"); - std::vector<unsigned char> mac; - for (Poco::StringTokenizer::Iterator it = tok.begin(); it != tok.end(); ++it) - { - mac.push_back(static_cast<unsigned char>(Poco::NumberParser::parseHex(*it))); - } - impl.setMACAddress(&mac[0], mac.size()); - addrStream.close(); - } - - std::string typePath(ifPath); - typePath += "/type"; - std::ifstream typeStream(typePath.c_str()); - if (typeStream.good()) - { - int type; - typeStream >> type; - impl.setType(fromNative(type)); - typeStream.close(); - } -#endif // POCO_NO_LINUX_IF_PACKET_H -} - -#endif - - -} - - -NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly) -{ -#if POCO_OS != POCO_OS_ANDROID - FastMutex::ScopedLock lock(_mutex); - Map result; - unsigned ifIndex = 0; - NetworkInterface intf; - Map::iterator ifIt; - - struct ifaddrs* ifaces = 0; - struct ifaddrs* iface = 0; - - if (getifaddrs(&ifaces) < 0) - throw NetException("cannot get network adapter list"); - - try - { - for (iface = ifaces; iface; iface = iface->ifa_next) - { - if (!iface->ifa_addr) continue; - - IPAddress address, subnetMask, broadcastAddress; - unsigned family = iface->ifa_addr->sa_family; - switch (family) - { -#ifndef POCO_NO_LINUX_IF_PACKET_H - case AF_PACKET: - { - struct sockaddr_ll* sll = (struct sockaddr_ll*)iface->ifa_addr; - ifIndex = sll->sll_ifindex; - intf = NetworkInterface(ifIndex); - setInterfaceParams(iface, intf.impl()); - - if ((result.find(ifIndex) == result.end()) && ((upOnly && intf.isUp()) || !upOnly)) - ifIt = result.insert(Map::value_type(ifIndex, intf)).first; - - break; - } -#endif // POCO_NO_LINUX_IF_PACKET_H - case AF_INET: - ifIndex = if_nametoindex(iface->ifa_name); - ifIt = result.find(ifIndex); - intf = NetworkInterface(ifIndex); - setInterfaceParams(iface, intf.impl()); - - if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly)) - ifIt = result.insert(Map::value_type(ifIndex, intf)).first; - - address = IPAddress(*(iface->ifa_addr)); - subnetMask = IPAddress(*(iface->ifa_netmask)); - - if (iface->ifa_flags & IFF_BROADCAST && iface->ifa_broadaddr) - broadcastAddress = IPAddress(*(iface->ifa_broadaddr)); - else if (iface->ifa_flags & IFF_POINTOPOINT && iface->ifa_dstaddr) - broadcastAddress = IPAddress(*(iface->ifa_dstaddr)); - else - broadcastAddress = IPAddress(); - - break; -#if defined(POCO_HAVE_IPv6) - case AF_INET6: - ifIndex = if_nametoindex(iface->ifa_name); - ifIt = result.find(ifIndex); - intf = NetworkInterface(ifIndex); - setInterfaceParams(iface, intf.impl()); - - if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly)) - result.insert(Map::value_type(ifIndex, intf)); - - address = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(iface->ifa_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex); - subnetMask = IPAddress(*(iface->ifa_netmask)); - broadcastAddress = IPAddress(); - - break; -#endif - default: - continue; - } - - if (family == AF_INET -#ifdef POCO_HAVE_IPv6 - || family == AF_INET6 -#endif - ) - { - intf = NetworkInterface(std::string(iface->ifa_name), address, subnetMask, broadcastAddress, ifIndex); - if ((upOnly && intf.isUp()) || !upOnly) - { - if ((ifIt = result.find(ifIndex)) != result.end()) - ifIt->second.addAddress(address, subnetMask, broadcastAddress); - } - } - } // for interface - } - catch (...) - { - if (ifaces) freeifaddrs(ifaces); - throw; - } - - if (ifaces) freeifaddrs(ifaces); - - if (ipOnly) - { - Map::iterator it = result.begin(); - Map::iterator end = result.end(); - for (; it != end;) - { - if (!it->second.supportsIPv4() && !it->second.supportsIPv6()) - result.erase(it++); - else ++it; - } - } - - return result; -#else - throw Poco::NotImplementedException("Not implemented in Android"); -#endif -} - - -} } // namespace Poco::Net - - -#else -// -// Non-BSD Unix variants -// -#error TODO -/* -NetworkInterface::NetworkInterfaceList NetworkInterface::list() -{ - FastMutex::ScopedLock lock(_mutex); - NetworkInterfaceList result; - DatagramSocket socket; - // the following code is loosely based - // on W. Richard Stevens, UNIX Network Programming, pp 434ff. - int lastlen = 0; - int len = 100*sizeof(struct ifreq); - char* buf = 0; - try - { - struct ifconf ifc; - for (;;) - { - buf = new char[len]; - ifc.ifc_len = len; - ifc.ifc_buf = buf; - if (::ioctl(socket.impl()->sockfd(), SIOCGIFCONF, &ifc) < 0) - { - if (errno != EINVAL || lastlen != 0) - throw NetException("cannot get network adapter list"); - } - else - { - if (ifc.ifc_len == lastlen) - break; - lastlen = ifc.ifc_len; - } - len += 10*sizeof(struct ifreq); - delete [] buf; - } - for (const char* ptr = buf; ptr < buf + ifc.ifc_len;) - { - const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr); -#if defined(POCO_HAVE_SALEN) - len = ifr->ifr_addr.sa_len; - if (sizeof(struct sockaddr) > len) len = sizeof(struct sockaddr); -#else - len = sizeof(struct sockaddr); -#endif - IPAddress addr; - bool haveAddr = false; - int ifIndex(-1); - switch (ifr->ifr_addr.sa_family) - { -#if defined(POCO_HAVE_IPv6) - case AF_INET6: - ifIndex = if_nametoindex(ifr->ifr_name); - if (len < sizeof(struct sockaddr_in6)) len = sizeof(struct sockaddr_in6); - addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex); - haveAddr = true; - break; -#endif - case AF_INET: - if (len < sizeof(struct sockaddr_in)) len = sizeof(struct sockaddr_in); - addr = IPAddress(ifr->ifr_addr); - haveAddr = true; - break; - default: - break; - } - if (haveAddr) - { - std::string name(ifr->ifr_name); - result.push_back(NetworkInterface(name, name, name, addr, ifIndex)); - } - len += sizeof(ifr->ifr_name); - ptr += len; - } - } - catch (...) - { - delete [] buf; - throw; - } - delete [] buf; - return result; -} -*/ - -} } // namespace Poco::Net - - -#endif - - -#endif // POCO_NET_HAS_INTERFACE + } + } + } + catch (...) + { + } + if (ifaces) freeifaddrs(ifaces); + + if (ipOnly) + { + Map::iterator it = result.begin(); + Map::iterator end = result.end(); + for (; it != end;) + { + if (!it->second.supportsIPv4() && !it->second.supportsIPv6()) + result.erase(it++); + else ++it; + } + } + + return result; +} + + +} } // namespace Poco::Net + + +#elif POCO_OS == POCO_OS_LINUX || POCO_OS == POCO_OS_ANDROID +// +// Linux +// + + +#include <sys/types.h> +#if POCO_OS != POCO_OS_ANDROID // Android doesn't have <ifaddrs.h> +#include <ifaddrs.h> +#endif +#include <net/if.h> +#ifndef POCO_NO_LINUX_IF_PACKET_H +#include <linux/if_packet.h> +#endif +#include <net/if_arp.h> +#include <iostream> + +namespace Poco { +namespace Net { + + +namespace { + + +static NetworkInterface::Type fromNative(unsigned arphrd) +{ + switch (arphrd) + { + case ARPHRD_ETHER: return NetworkInterface::NI_TYPE_ETHERNET_CSMACD; + case ARPHRD_IEEE802: return NetworkInterface::NI_TYPE_ISO88025_TOKENRING; + case ARPHRD_DLCI: return NetworkInterface::NI_TYPE_FRAMERELAY; + case ARPHRD_PPP: return NetworkInterface::NI_TYPE_PPP; + case ARPHRD_LOOPBACK: return NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK; + case ARPHRD_ATM: return NetworkInterface::NI_TYPE_ATM; + case ARPHRD_IEEE80211: return NetworkInterface::NI_TYPE_IEEE80211; + case ARPHRD_TUNNEL: + case ARPHRD_TUNNEL6: return NetworkInterface::NI_TYPE_TUNNEL; + case ARPHRD_IEEE1394: return NetworkInterface::NI_TYPE_IEEE1394; + default: return NetworkInterface::NI_TYPE_OTHER; + } +} + +#if POCO_OS != POCO_OS_ANDROID + +void setInterfaceParams(struct ifaddrs* iface, NetworkInterfaceImpl& impl) +{ + impl.setName(iface->ifa_name); + impl.setDisplayName(iface->ifa_name); + impl.setAdapterName(iface->ifa_name); + impl.setPhyParams(); + +#ifndef POCO_NO_LINUX_IF_PACKET_H + struct sockaddr_ll* sdl = (struct sockaddr_ll*) iface->ifa_addr; + impl.setMACAddress(sdl->sll_addr, sdl->sll_halen); + impl.setType(fromNative(sdl->sll_hatype)); +#else + std::string ifPath("/sys/class/net/"); + ifPath += iface->ifa_name; + + std::string addrPath(ifPath); + addrPath += "/address"; + + std::ifstream addrStream(addrPath.c_str()); + if (addrStream.good()) + { + std::string addr; + std::getline(addrStream, addr); + Poco::StringTokenizer tok(addr, ":"); + std::vector<unsigned char> mac; + for (Poco::StringTokenizer::Iterator it = tok.begin(); it != tok.end(); ++it) + { + mac.push_back(static_cast<unsigned char>(Poco::NumberParser::parseHex(*it))); + } + impl.setMACAddress(&mac[0], mac.size()); + addrStream.close(); + } + + std::string typePath(ifPath); + typePath += "/type"; + std::ifstream typeStream(typePath.c_str()); + if (typeStream.good()) + { + int type; + typeStream >> type; + impl.setType(fromNative(type)); + typeStream.close(); + } +#endif // POCO_NO_LINUX_IF_PACKET_H +} + +#endif + + +} + + +NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly) +{ +#if POCO_OS != POCO_OS_ANDROID + FastMutex::ScopedLock lock(_mutex); + Map result; + unsigned ifIndex = 0; + NetworkInterface intf; + Map::iterator ifIt; + + struct ifaddrs* ifaces = 0; + struct ifaddrs* iface = 0; + + if (getifaddrs(&ifaces) < 0) + throw NetException("cannot get network adapter list"); + + try + { + for (iface = ifaces; iface; iface = iface->ifa_next) + { + if (!iface->ifa_addr) continue; + + IPAddress address, subnetMask, broadcastAddress; + unsigned family = iface->ifa_addr->sa_family; + switch (family) + { +#ifndef POCO_NO_LINUX_IF_PACKET_H + case AF_PACKET: + { + struct sockaddr_ll* sll = (struct sockaddr_ll*)iface->ifa_addr; + ifIndex = sll->sll_ifindex; + intf = NetworkInterface(ifIndex); + setInterfaceParams(iface, intf.impl()); + + if ((result.find(ifIndex) == result.end()) && ((upOnly && intf.isUp()) || !upOnly)) + ifIt = result.insert(Map::value_type(ifIndex, intf)).first; + + break; + } +#endif // POCO_NO_LINUX_IF_PACKET_H + case AF_INET: + ifIndex = if_nametoindex(iface->ifa_name); + ifIt = result.find(ifIndex); + intf = NetworkInterface(ifIndex); + setInterfaceParams(iface, intf.impl()); + + if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly)) + ifIt = result.insert(Map::value_type(ifIndex, intf)).first; + + address = IPAddress(*(iface->ifa_addr)); + subnetMask = IPAddress(*(iface->ifa_netmask)); + + if (iface->ifa_flags & IFF_BROADCAST && iface->ifa_broadaddr) + broadcastAddress = IPAddress(*(iface->ifa_broadaddr)); + else if (iface->ifa_flags & IFF_POINTOPOINT && iface->ifa_dstaddr) + broadcastAddress = IPAddress(*(iface->ifa_dstaddr)); + else + broadcastAddress = IPAddress(); + + break; +#if defined(POCO_HAVE_IPv6) + case AF_INET6: + ifIndex = if_nametoindex(iface->ifa_name); + ifIt = result.find(ifIndex); + intf = NetworkInterface(ifIndex); + setInterfaceParams(iface, intf.impl()); + + if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly)) + result.insert(Map::value_type(ifIndex, intf)); + + address = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(iface->ifa_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex); + subnetMask = IPAddress(*(iface->ifa_netmask)); + broadcastAddress = IPAddress(); + + break; +#endif + default: + continue; + } + + if (family == AF_INET +#ifdef POCO_HAVE_IPv6 + || family == AF_INET6 +#endif + ) + { + intf = NetworkInterface(std::string(iface->ifa_name), address, subnetMask, broadcastAddress, ifIndex); + if ((upOnly && intf.isUp()) || !upOnly) + { + if ((ifIt = result.find(ifIndex)) != result.end()) + ifIt->second.addAddress(address, subnetMask, broadcastAddress); + } + } + } // for interface + } + catch (...) + { + if (ifaces) freeifaddrs(ifaces); + throw; + } + + if (ifaces) freeifaddrs(ifaces); + + if (ipOnly) + { + Map::iterator it = result.begin(); + Map::iterator end = result.end(); + for (; it != end;) + { + if (!it->second.supportsIPv4() && !it->second.supportsIPv6()) + result.erase(it++); + else ++it; + } + } + + return result; +#else + throw Poco::NotImplementedException("Not implemented in Android"); +#endif +} + + +} } // namespace Poco::Net + + +#else +// +// Non-BSD Unix variants +// +#error TODO +/* +NetworkInterface::NetworkInterfaceList NetworkInterface::list() +{ + FastMutex::ScopedLock lock(_mutex); + NetworkInterfaceList result; + DatagramSocket socket; + // the following code is loosely based + // on W. Richard Stevens, UNIX Network Programming, pp 434ff. + int lastlen = 0; + int len = 100*sizeof(struct ifreq); + char* buf = 0; + try + { + struct ifconf ifc; + for (;;) + { + buf = new char[len]; + ifc.ifc_len = len; + ifc.ifc_buf = buf; + if (::ioctl(socket.impl()->sockfd(), SIOCGIFCONF, &ifc) < 0) + { + if (errno != EINVAL || lastlen != 0) + throw NetException("cannot get network adapter list"); + } + else + { + if (ifc.ifc_len == lastlen) + break; + lastlen = ifc.ifc_len; + } + len += 10*sizeof(struct ifreq); + delete [] buf; + } + for (const char* ptr = buf; ptr < buf + ifc.ifc_len;) + { + const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr); +#if defined(POCO_HAVE_SALEN) + len = ifr->ifr_addr.sa_len; + if (sizeof(struct sockaddr) > len) len = sizeof(struct sockaddr); +#else + len = sizeof(struct sockaddr); +#endif + IPAddress addr; + bool haveAddr = false; + int ifIndex(-1); + switch (ifr->ifr_addr.sa_family) + { +#if defined(POCO_HAVE_IPv6) + case AF_INET6: + ifIndex = if_nametoindex(ifr->ifr_name); + if (len < sizeof(struct sockaddr_in6)) len = sizeof(struct sockaddr_in6); + addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex); + haveAddr = true; + break; +#endif + case AF_INET: + if (len < sizeof(struct sockaddr_in)) len = sizeof(struct sockaddr_in); + addr = IPAddress(ifr->ifr_addr); + haveAddr = true; + break; + default: + break; + } + if (haveAddr) + { + std::string name(ifr->ifr_name); + result.push_back(NetworkInterface(name, name, name, addr, ifIndex)); + } + len += sizeof(ifr->ifr_name); + ptr += len; + } + } + catch (...) + { + delete [] buf; + throw; + } + delete [] buf; + return result; +} +*/ + +} } // namespace Poco::Net + + +#endif + + +#endif // POCO_NET_HAS_INTERFACE diff --git a/contrib/libs/poco/Net/src/NullPartHandler.cpp b/contrib/libs/poco/Net/src/NullPartHandler.cpp index 0a8cbf9794..e7453a1c06 100644 --- a/contrib/libs/poco/Net/src/NullPartHandler.cpp +++ b/contrib/libs/poco/Net/src/NullPartHandler.cpp @@ -1,46 +1,46 @@ -// -// NullPartHandler.cpp -// -// Library: Net -// Package: Messages -// Module: NullPartHandler -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/NullPartHandler.h" -#include "Poco/Net/MessageHeader.h" -#include "Poco/NullStream.h" -#include "Poco/StreamCopier.h" - - -using Poco::NullOutputStream; -using Poco::StreamCopier; - - -namespace Poco { -namespace Net { - - -NullPartHandler::NullPartHandler() -{ -} - - -NullPartHandler::~NullPartHandler() -{ -} - - -void NullPartHandler::handlePart(const MessageHeader& /*header*/, std::istream& stream) -{ - NullOutputStream ostr; - StreamCopier::copyStream(stream, ostr); -} - - -} } // namespace Poco::Net +// +// NullPartHandler.cpp +// +// Library: Net +// Package: Messages +// Module: NullPartHandler +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/NullPartHandler.h" +#include "Poco/Net/MessageHeader.h" +#include "Poco/NullStream.h" +#include "Poco/StreamCopier.h" + + +using Poco::NullOutputStream; +using Poco::StreamCopier; + + +namespace Poco { +namespace Net { + + +NullPartHandler::NullPartHandler() +{ +} + + +NullPartHandler::~NullPartHandler() +{ +} + + +void NullPartHandler::handlePart(const MessageHeader& /*header*/, std::istream& stream) +{ + NullOutputStream ostr; + StreamCopier::copyStream(stream, ostr); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/OAuth10Credentials.cpp b/contrib/libs/poco/Net/src/OAuth10Credentials.cpp index 71ec0f736b..6588599782 100644 --- a/contrib/libs/poco/Net/src/OAuth10Credentials.cpp +++ b/contrib/libs/poco/Net/src/OAuth10Credentials.cpp @@ -1,365 +1,365 @@ -// -// OAuth10Credentials.cpp -// -// Library: Net -// Package: OAuth -// Module: OAuth10Credentials -// -// Copyright (c) 2014, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/OAuth10Credentials.h" -#include "Poco/Net/HTTPRequest.h" -#include "Poco/Net/HTMLForm.h" -#include "Poco/Net/NetException.h" -#include "Poco/Net/HTTPAuthenticationParams.h" -#include "Poco/SHA1Engine.h" -#include "Poco/HMACEngine.h" -#include "Poco/Base64Encoder.h" -#include "Poco/RandomStream.h" -#include "Poco/Timestamp.h" -#include "Poco/NumberParser.h" -#include "Poco/NumberFormatter.h" -#include "Poco/Format.h" -#include "Poco/String.h" -#include <map> -#include <sstream> - - -namespace Poco { -namespace Net { - - -const std::string OAuth10Credentials::SCHEME = "OAuth"; - - -OAuth10Credentials::OAuth10Credentials() -{ -} - - -OAuth10Credentials::OAuth10Credentials(const std::string& consumerKey, const std::string& consumerSecret): - _consumerKey(consumerKey), - _consumerSecret(consumerSecret) -{ -} - - -OAuth10Credentials::OAuth10Credentials(const std::string& consumerKey, const std::string& consumerSecret, const std::string& token, const std::string& tokenSecret): - _consumerKey(consumerKey), - _consumerSecret(consumerSecret), - _token(token), - _tokenSecret(tokenSecret) -{ -} - - -OAuth10Credentials::OAuth10Credentials(const Poco::Net::HTTPRequest& request) -{ - if (request.hasCredentials()) - { - std::string authScheme; - std::string authParams; - request.getCredentials(authScheme, authParams); - if (icompare(authScheme, SCHEME) == 0) - { - HTTPAuthenticationParams params(authParams); - std::string consumerKey = params.get("oauth_consumer_key", ""); - URI::decode(consumerKey, _consumerKey); - std::string token = params.get("oauth_token", ""); - URI::decode(token, _token); - std::string callback = params.get("oauth_callback", ""); - URI::decode(callback, _callback); - } - else throw NotAuthenticatedException("No OAuth credentials in Authorization header", authScheme); - } - else throw NotAuthenticatedException("No Authorization header found"); -} - - -OAuth10Credentials::~OAuth10Credentials() -{ -} - - -void OAuth10Credentials::setConsumerKey(const std::string& consumerKey) -{ - _consumerKey = consumerKey; -} - - -void OAuth10Credentials::setConsumerSecret(const std::string& consumerSecret) -{ - _consumerSecret = consumerSecret; -} - - -void OAuth10Credentials::setToken(const std::string& token) -{ - _token = token; -} - - -void OAuth10Credentials::setTokenSecret(const std::string& tokenSecret) -{ - _tokenSecret = tokenSecret; -} - - -void OAuth10Credentials::setRealm(const std::string& realm) -{ - _realm = realm; -} - - -void OAuth10Credentials::setCallback(const std::string& callback) -{ - _callback = callback; -} - - -void OAuth10Credentials::authenticate(HTTPRequest& request, const Poco::URI& uri, SignatureMethod method) -{ - HTMLForm emptyParams; - authenticate(request, uri, emptyParams, method); -} - - -void OAuth10Credentials::authenticate(HTTPRequest& request, const Poco::URI& uri, const Poco::Net::HTMLForm& params, SignatureMethod method) -{ - if (method == SIGN_PLAINTEXT) - { - signPlaintext(request); - } - else - { - URI uriWithoutQuery(uri); - uriWithoutQuery.setQuery(""); - uriWithoutQuery.setFragment(""); - signHMACSHA1(request, uriWithoutQuery.toString(), params); - } -} - - -bool OAuth10Credentials::verify(const HTTPRequest& request, const Poco::URI& uri) -{ - HTMLForm params; - return verify(request, uri, params); -} - - -bool OAuth10Credentials::verify(const HTTPRequest& request, const Poco::URI& uri, const Poco::Net::HTMLForm& params) -{ - if (request.hasCredentials()) - { - std::string authScheme; - std::string authParams; - request.getCredentials(authScheme, authParams); - if (icompare(authScheme, SCHEME) == 0) - { - HTTPAuthenticationParams oauthParams(authParams); - - std::string version = oauthParams.get("oauth_version", "1.0"); - if (version != "1.0") throw NotAuthenticatedException("Unsupported OAuth version", version); - - _consumerKey.clear(); - std::string consumerKey = oauthParams.get("oauth_consumer_key", ""); - URI::decode(consumerKey, _consumerKey); - - _token.clear(); - std::string token = oauthParams.get("oauth_token", ""); - URI::decode(token, _token); - - _callback.clear(); - std::string callback = oauthParams.get("oauth_callback", ""); - URI::decode(callback, _callback); - - std::string nonceEnc = oauthParams.get("oauth_nonce", ""); - std::string nonce; - URI::decode(nonceEnc, nonce); - - std::string timestamp = oauthParams.get("oauth_timestamp", ""); - - std::string method = oauthParams.get("oauth_signature_method", ""); - - std::string signatureEnc = oauthParams.get("oauth_signature", ""); - std::string signature; - URI::decode(signatureEnc, signature); - - std::string refSignature; - if (icompare(method, "PLAINTEXT") == 0) - { - refSignature = percentEncode(_consumerSecret); - refSignature += '&'; - refSignature += percentEncode(_tokenSecret); - } - else if (icompare(method, "HMAC-SHA1") == 0) - { - URI uriWithoutQuery(uri); - uriWithoutQuery.setQuery(""); - uriWithoutQuery.setFragment(""); - refSignature = createSignature(request, uriWithoutQuery.toString(), params, nonce, timestamp); - } - else throw NotAuthenticatedException("Unsupported OAuth signature method", method); - - return refSignature == signature; - } - else throw NotAuthenticatedException("No OAuth credentials found in Authorization header"); - } - else throw NotAuthenticatedException("No Authorization header found"); -} - - -void OAuth10Credentials::nonceAndTimestampForTesting(const std::string& nonce, const std::string& timestamp) -{ - _nonce = nonce; - _timestamp = timestamp; -} - - -void OAuth10Credentials::signPlaintext(Poco::Net::HTTPRequest& request) const -{ - std::string signature(percentEncode(_consumerSecret)); - signature += '&'; - signature += percentEncode(_tokenSecret); - - std::string authorization(SCHEME); - if (!_realm.empty()) - { - Poco::format(authorization, " realm=\"%s\",", _realm); - } - Poco::format(authorization, " oauth_consumer_key=\"%s\"", percentEncode(_consumerKey)); - Poco::format(authorization, ", oauth_signature=\"%s\"", percentEncode(signature)); - authorization += ", oauth_signature_method=\"PLAINTEXT\""; - if (!_token.empty()) - { - Poco::format(authorization, ", oauth_token=\"%s\"", percentEncode(_token)); - } - if (!_callback.empty()) - { - Poco::format(authorization, ", oauth_callback=\"%s\"", percentEncode(_callback)); - } - authorization += ", oauth_version=\"1.0\""; - - request.set(HTTPRequest::AUTHORIZATION, authorization); -} - - -void OAuth10Credentials::signHMACSHA1(Poco::Net::HTTPRequest& request, const std::string& uri, const Poco::Net::HTMLForm& params) const -{ - std::string nonce(_nonce); - if (nonce.empty()) - { - nonce = createNonce(); - } - std::string timestamp(_timestamp); - if (timestamp.empty()) - { - timestamp = Poco::NumberFormatter::format(Poco::Timestamp().epochTime()); - } - std::string signature(createSignature(request, uri, params, nonce, timestamp)); - - std::string authorization(SCHEME); - if (!_realm.empty()) - { - Poco::format(authorization, " realm=\"%s\",", _realm); - } - Poco::format(authorization, " oauth_consumer_key=\"%s\"", percentEncode(_consumerKey)); - Poco::format(authorization, ", oauth_nonce=\"%s\"", percentEncode(nonce)); - Poco::format(authorization, ", oauth_signature=\"%s\"", percentEncode(signature)); - authorization += ", oauth_signature_method=\"HMAC-SHA1\""; - Poco::format(authorization, ", oauth_timestamp=\"%s\"", timestamp); - if (!_token.empty()) - { - Poco::format(authorization, ", oauth_token=\"%s\"", percentEncode(_token)); - } - if (!_callback.empty()) - { - Poco::format(authorization, ", oauth_callback=\"%s\"", percentEncode(_callback)); - } - authorization += ", oauth_version=\"1.0\""; - - request.set(HTTPRequest::AUTHORIZATION, authorization); -} - - -std::string OAuth10Credentials::createNonce() const -{ - std::ostringstream base64Nonce; - Poco::Base64Encoder base64Encoder(base64Nonce); - Poco::RandomInputStream randomStream; - for (int i = 0; i < 32; i++) - { - base64Encoder.put(static_cast<char>(randomStream.get())); - } - base64Encoder.close(); - std::string nonce = base64Nonce.str(); - return Poco::translate(nonce, "+/=", ""); -} - - -std::string OAuth10Credentials::createSignature(const Poco::Net::HTTPRequest& request, const std::string& uri, const Poco::Net::HTMLForm& params, const std::string& nonce, const std::string& timestamp) const -{ - std::map<std::string, std::string> paramsMap; - paramsMap["oauth_version"] = "1.0"; - paramsMap["oauth_consumer_key"] = percentEncode(_consumerKey); - paramsMap["oauth_nonce"] = percentEncode(nonce); - paramsMap["oauth_signature_method"] = "HMAC-SHA1"; - paramsMap["oauth_timestamp"] = timestamp; - if (!_token.empty()) - { - paramsMap["oauth_token"] = percentEncode(_token); - } - if (!_callback.empty()) - { - paramsMap["oauth_callback"] = percentEncode(_callback); - } - for (Poco::Net::HTMLForm::ConstIterator it = params.begin(); it != params.end(); ++it) - { - paramsMap[percentEncode(it->first)] = percentEncode(it->second); - } - - std::string paramsString; - for (std::map<std::string, std::string>::const_iterator it = paramsMap.begin(); it != paramsMap.end(); ++it) - { - if (it != paramsMap.begin()) paramsString += '&'; - paramsString += it->first; - paramsString += "="; - paramsString += it->second; - } - - std::string signatureBase = request.getMethod(); - signatureBase += '&'; - signatureBase += percentEncode(uri); - signatureBase += '&'; - signatureBase += percentEncode(paramsString); - - std::string signingKey; - signingKey += percentEncode(_consumerSecret); - signingKey += '&'; - signingKey += percentEncode(_tokenSecret); - - Poco::HMACEngine<Poco::SHA1Engine> hmacEngine(signingKey); - hmacEngine.update(signatureBase); - Poco::DigestEngine::Digest digest = hmacEngine.digest(); - std::ostringstream digestBase64; - Poco::Base64Encoder base64Encoder(digestBase64); - base64Encoder.write(reinterpret_cast<char*>(&digest[0]), digest.size()); - base64Encoder.close(); - return digestBase64.str(); -} - - -std::string OAuth10Credentials::percentEncode(const std::string& str) -{ - std::string encoded; - Poco::URI::encode(str, "!?#/'\",;:$&()[]*+=@", encoded); - return encoded; -} - - -} } // namespace Poco::Net +// +// OAuth10Credentials.cpp +// +// Library: Net +// Package: OAuth +// Module: OAuth10Credentials +// +// Copyright (c) 2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/OAuth10Credentials.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/HTMLForm.h" +#include "Poco/Net/NetException.h" +#include "Poco/Net/HTTPAuthenticationParams.h" +#include "Poco/SHA1Engine.h" +#include "Poco/HMACEngine.h" +#include "Poco/Base64Encoder.h" +#include "Poco/RandomStream.h" +#include "Poco/Timestamp.h" +#include "Poco/NumberParser.h" +#include "Poco/NumberFormatter.h" +#include "Poco/Format.h" +#include "Poco/String.h" +#include <map> +#include <sstream> + + +namespace Poco { +namespace Net { + + +const std::string OAuth10Credentials::SCHEME = "OAuth"; + + +OAuth10Credentials::OAuth10Credentials() +{ +} + + +OAuth10Credentials::OAuth10Credentials(const std::string& consumerKey, const std::string& consumerSecret): + _consumerKey(consumerKey), + _consumerSecret(consumerSecret) +{ +} + + +OAuth10Credentials::OAuth10Credentials(const std::string& consumerKey, const std::string& consumerSecret, const std::string& token, const std::string& tokenSecret): + _consumerKey(consumerKey), + _consumerSecret(consumerSecret), + _token(token), + _tokenSecret(tokenSecret) +{ +} + + +OAuth10Credentials::OAuth10Credentials(const Poco::Net::HTTPRequest& request) +{ + if (request.hasCredentials()) + { + std::string authScheme; + std::string authParams; + request.getCredentials(authScheme, authParams); + if (icompare(authScheme, SCHEME) == 0) + { + HTTPAuthenticationParams params(authParams); + std::string consumerKey = params.get("oauth_consumer_key", ""); + URI::decode(consumerKey, _consumerKey); + std::string token = params.get("oauth_token", ""); + URI::decode(token, _token); + std::string callback = params.get("oauth_callback", ""); + URI::decode(callback, _callback); + } + else throw NotAuthenticatedException("No OAuth credentials in Authorization header", authScheme); + } + else throw NotAuthenticatedException("No Authorization header found"); +} + + +OAuth10Credentials::~OAuth10Credentials() +{ +} + + +void OAuth10Credentials::setConsumerKey(const std::string& consumerKey) +{ + _consumerKey = consumerKey; +} + + +void OAuth10Credentials::setConsumerSecret(const std::string& consumerSecret) +{ + _consumerSecret = consumerSecret; +} + + +void OAuth10Credentials::setToken(const std::string& token) +{ + _token = token; +} + + +void OAuth10Credentials::setTokenSecret(const std::string& tokenSecret) +{ + _tokenSecret = tokenSecret; +} + + +void OAuth10Credentials::setRealm(const std::string& realm) +{ + _realm = realm; +} + + +void OAuth10Credentials::setCallback(const std::string& callback) +{ + _callback = callback; +} + + +void OAuth10Credentials::authenticate(HTTPRequest& request, const Poco::URI& uri, SignatureMethod method) +{ + HTMLForm emptyParams; + authenticate(request, uri, emptyParams, method); +} + + +void OAuth10Credentials::authenticate(HTTPRequest& request, const Poco::URI& uri, const Poco::Net::HTMLForm& params, SignatureMethod method) +{ + if (method == SIGN_PLAINTEXT) + { + signPlaintext(request); + } + else + { + URI uriWithoutQuery(uri); + uriWithoutQuery.setQuery(""); + uriWithoutQuery.setFragment(""); + signHMACSHA1(request, uriWithoutQuery.toString(), params); + } +} + + +bool OAuth10Credentials::verify(const HTTPRequest& request, const Poco::URI& uri) +{ + HTMLForm params; + return verify(request, uri, params); +} + + +bool OAuth10Credentials::verify(const HTTPRequest& request, const Poco::URI& uri, const Poco::Net::HTMLForm& params) +{ + if (request.hasCredentials()) + { + std::string authScheme; + std::string authParams; + request.getCredentials(authScheme, authParams); + if (icompare(authScheme, SCHEME) == 0) + { + HTTPAuthenticationParams oauthParams(authParams); + + std::string version = oauthParams.get("oauth_version", "1.0"); + if (version != "1.0") throw NotAuthenticatedException("Unsupported OAuth version", version); + + _consumerKey.clear(); + std::string consumerKey = oauthParams.get("oauth_consumer_key", ""); + URI::decode(consumerKey, _consumerKey); + + _token.clear(); + std::string token = oauthParams.get("oauth_token", ""); + URI::decode(token, _token); + + _callback.clear(); + std::string callback = oauthParams.get("oauth_callback", ""); + URI::decode(callback, _callback); + + std::string nonceEnc = oauthParams.get("oauth_nonce", ""); + std::string nonce; + URI::decode(nonceEnc, nonce); + + std::string timestamp = oauthParams.get("oauth_timestamp", ""); + + std::string method = oauthParams.get("oauth_signature_method", ""); + + std::string signatureEnc = oauthParams.get("oauth_signature", ""); + std::string signature; + URI::decode(signatureEnc, signature); + + std::string refSignature; + if (icompare(method, "PLAINTEXT") == 0) + { + refSignature = percentEncode(_consumerSecret); + refSignature += '&'; + refSignature += percentEncode(_tokenSecret); + } + else if (icompare(method, "HMAC-SHA1") == 0) + { + URI uriWithoutQuery(uri); + uriWithoutQuery.setQuery(""); + uriWithoutQuery.setFragment(""); + refSignature = createSignature(request, uriWithoutQuery.toString(), params, nonce, timestamp); + } + else throw NotAuthenticatedException("Unsupported OAuth signature method", method); + + return refSignature == signature; + } + else throw NotAuthenticatedException("No OAuth credentials found in Authorization header"); + } + else throw NotAuthenticatedException("No Authorization header found"); +} + + +void OAuth10Credentials::nonceAndTimestampForTesting(const std::string& nonce, const std::string& timestamp) +{ + _nonce = nonce; + _timestamp = timestamp; +} + + +void OAuth10Credentials::signPlaintext(Poco::Net::HTTPRequest& request) const +{ + std::string signature(percentEncode(_consumerSecret)); + signature += '&'; + signature += percentEncode(_tokenSecret); + + std::string authorization(SCHEME); + if (!_realm.empty()) + { + Poco::format(authorization, " realm=\"%s\",", _realm); + } + Poco::format(authorization, " oauth_consumer_key=\"%s\"", percentEncode(_consumerKey)); + Poco::format(authorization, ", oauth_signature=\"%s\"", percentEncode(signature)); + authorization += ", oauth_signature_method=\"PLAINTEXT\""; + if (!_token.empty()) + { + Poco::format(authorization, ", oauth_token=\"%s\"", percentEncode(_token)); + } + if (!_callback.empty()) + { + Poco::format(authorization, ", oauth_callback=\"%s\"", percentEncode(_callback)); + } + authorization += ", oauth_version=\"1.0\""; + + request.set(HTTPRequest::AUTHORIZATION, authorization); +} + + +void OAuth10Credentials::signHMACSHA1(Poco::Net::HTTPRequest& request, const std::string& uri, const Poco::Net::HTMLForm& params) const +{ + std::string nonce(_nonce); + if (nonce.empty()) + { + nonce = createNonce(); + } + std::string timestamp(_timestamp); + if (timestamp.empty()) + { + timestamp = Poco::NumberFormatter::format(Poco::Timestamp().epochTime()); + } + std::string signature(createSignature(request, uri, params, nonce, timestamp)); + + std::string authorization(SCHEME); + if (!_realm.empty()) + { + Poco::format(authorization, " realm=\"%s\",", _realm); + } + Poco::format(authorization, " oauth_consumer_key=\"%s\"", percentEncode(_consumerKey)); + Poco::format(authorization, ", oauth_nonce=\"%s\"", percentEncode(nonce)); + Poco::format(authorization, ", oauth_signature=\"%s\"", percentEncode(signature)); + authorization += ", oauth_signature_method=\"HMAC-SHA1\""; + Poco::format(authorization, ", oauth_timestamp=\"%s\"", timestamp); + if (!_token.empty()) + { + Poco::format(authorization, ", oauth_token=\"%s\"", percentEncode(_token)); + } + if (!_callback.empty()) + { + Poco::format(authorization, ", oauth_callback=\"%s\"", percentEncode(_callback)); + } + authorization += ", oauth_version=\"1.0\""; + + request.set(HTTPRequest::AUTHORIZATION, authorization); +} + + +std::string OAuth10Credentials::createNonce() const +{ + std::ostringstream base64Nonce; + Poco::Base64Encoder base64Encoder(base64Nonce); + Poco::RandomInputStream randomStream; + for (int i = 0; i < 32; i++) + { + base64Encoder.put(static_cast<char>(randomStream.get())); + } + base64Encoder.close(); + std::string nonce = base64Nonce.str(); + return Poco::translate(nonce, "+/=", ""); +} + + +std::string OAuth10Credentials::createSignature(const Poco::Net::HTTPRequest& request, const std::string& uri, const Poco::Net::HTMLForm& params, const std::string& nonce, const std::string& timestamp) const +{ + std::map<std::string, std::string> paramsMap; + paramsMap["oauth_version"] = "1.0"; + paramsMap["oauth_consumer_key"] = percentEncode(_consumerKey); + paramsMap["oauth_nonce"] = percentEncode(nonce); + paramsMap["oauth_signature_method"] = "HMAC-SHA1"; + paramsMap["oauth_timestamp"] = timestamp; + if (!_token.empty()) + { + paramsMap["oauth_token"] = percentEncode(_token); + } + if (!_callback.empty()) + { + paramsMap["oauth_callback"] = percentEncode(_callback); + } + for (Poco::Net::HTMLForm::ConstIterator it = params.begin(); it != params.end(); ++it) + { + paramsMap[percentEncode(it->first)] = percentEncode(it->second); + } + + std::string paramsString; + for (std::map<std::string, std::string>::const_iterator it = paramsMap.begin(); it != paramsMap.end(); ++it) + { + if (it != paramsMap.begin()) paramsString += '&'; + paramsString += it->first; + paramsString += "="; + paramsString += it->second; + } + + std::string signatureBase = request.getMethod(); + signatureBase += '&'; + signatureBase += percentEncode(uri); + signatureBase += '&'; + signatureBase += percentEncode(paramsString); + + std::string signingKey; + signingKey += percentEncode(_consumerSecret); + signingKey += '&'; + signingKey += percentEncode(_tokenSecret); + + Poco::HMACEngine<Poco::SHA1Engine> hmacEngine(signingKey); + hmacEngine.update(signatureBase); + Poco::DigestEngine::Digest digest = hmacEngine.digest(); + std::ostringstream digestBase64; + Poco::Base64Encoder base64Encoder(digestBase64); + base64Encoder.write(reinterpret_cast<char*>(&digest[0]), digest.size()); + base64Encoder.close(); + return digestBase64.str(); +} + + +std::string OAuth10Credentials::percentEncode(const std::string& str) +{ + std::string encoded; + Poco::URI::encode(str, "!?#/'\",;:$&()[]*+=@", encoded); + return encoded; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/OAuth20Credentials.cpp b/contrib/libs/poco/Net/src/OAuth20Credentials.cpp index 392115ad5f..4c95e2b71f 100644 --- a/contrib/libs/poco/Net/src/OAuth20Credentials.cpp +++ b/contrib/libs/poco/Net/src/OAuth20Credentials.cpp @@ -1,105 +1,105 @@ -// -// OAuth20Credentials.cpp -// -// Library: Net -// Package: OAuth -// Module: OAuth20Credentials -// -// Copyright (c) 2014, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/OAuth20Credentials.h" -#include "Poco/Net/HTTPRequest.h" -#include "Poco/Net/NetException.h" -#include "Poco/String.h" - - -namespace Poco { -namespace Net { - - -const std::string OAuth20Credentials::SCHEME = "Bearer"; - - -OAuth20Credentials::OAuth20Credentials(): - _scheme(SCHEME) -{ -} - - -OAuth20Credentials::OAuth20Credentials(const std::string& bearerToken): - _bearerToken(bearerToken), - _scheme(SCHEME) -{ -} - - -OAuth20Credentials::OAuth20Credentials(const std::string& bearerToken, const std::string& scheme): - _bearerToken(bearerToken), - _scheme(scheme) -{ -} - - -OAuth20Credentials::OAuth20Credentials(const HTTPRequest& request): - _scheme(SCHEME) -{ - extractBearerToken(request); -} - - -OAuth20Credentials::OAuth20Credentials(const HTTPRequest& request, const std::string& scheme): - _scheme(scheme) -{ - extractBearerToken(request); -} - - -OAuth20Credentials::~OAuth20Credentials() -{ -} - - -void OAuth20Credentials::setBearerToken(const std::string& bearerToken) -{ - _bearerToken = bearerToken; -} - - -void OAuth20Credentials::setScheme(const std::string& scheme) -{ - _scheme = scheme; -} - - -void OAuth20Credentials::authenticate(HTTPRequest& request) -{ - std::string auth(_scheme); - auth += ' '; - auth += _bearerToken; - request.set(HTTPRequest::AUTHORIZATION, auth); -} - - -void OAuth20Credentials::extractBearerToken(const HTTPRequest& request) -{ - if (request.hasCredentials()) - { - std::string authScheme; - std::string authInfo; - request.getCredentials(authScheme, authInfo); - if (icompare(authScheme, _scheme) == 0) - { - _bearerToken = authInfo; - } - else throw NotAuthenticatedException("No bearer token in Authorization header", authScheme); - } - else throw NotAuthenticatedException("No Authorization header found"); -} - - -} } // namespace Poco::Net +// +// OAuth20Credentials.cpp +// +// Library: Net +// Package: OAuth +// Module: OAuth20Credentials +// +// Copyright (c) 2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/OAuth20Credentials.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/NetException.h" +#include "Poco/String.h" + + +namespace Poco { +namespace Net { + + +const std::string OAuth20Credentials::SCHEME = "Bearer"; + + +OAuth20Credentials::OAuth20Credentials(): + _scheme(SCHEME) +{ +} + + +OAuth20Credentials::OAuth20Credentials(const std::string& bearerToken): + _bearerToken(bearerToken), + _scheme(SCHEME) +{ +} + + +OAuth20Credentials::OAuth20Credentials(const std::string& bearerToken, const std::string& scheme): + _bearerToken(bearerToken), + _scheme(scheme) +{ +} + + +OAuth20Credentials::OAuth20Credentials(const HTTPRequest& request): + _scheme(SCHEME) +{ + extractBearerToken(request); +} + + +OAuth20Credentials::OAuth20Credentials(const HTTPRequest& request, const std::string& scheme): + _scheme(scheme) +{ + extractBearerToken(request); +} + + +OAuth20Credentials::~OAuth20Credentials() +{ +} + + +void OAuth20Credentials::setBearerToken(const std::string& bearerToken) +{ + _bearerToken = bearerToken; +} + + +void OAuth20Credentials::setScheme(const std::string& scheme) +{ + _scheme = scheme; +} + + +void OAuth20Credentials::authenticate(HTTPRequest& request) +{ + std::string auth(_scheme); + auth += ' '; + auth += _bearerToken; + request.set(HTTPRequest::AUTHORIZATION, auth); +} + + +void OAuth20Credentials::extractBearerToken(const HTTPRequest& request) +{ + if (request.hasCredentials()) + { + std::string authScheme; + std::string authInfo; + request.getCredentials(authScheme, authInfo); + if (icompare(authScheme, _scheme) == 0) + { + _bearerToken = authInfo; + } + else throw NotAuthenticatedException("No bearer token in Authorization header", authScheme); + } + else throw NotAuthenticatedException("No Authorization header found"); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/POP3ClientSession.cpp b/contrib/libs/poco/Net/src/POP3ClientSession.cpp index 159f2108c5..d6936c9991 100644 --- a/contrib/libs/poco/Net/src/POP3ClientSession.cpp +++ b/contrib/libs/poco/Net/src/POP3ClientSession.cpp @@ -1,280 +1,280 @@ -// -// POP3ClientSession.cpp -// -// Library: Net -// Package: Mail -// Module: POP3ClientSession -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/POP3ClientSession.h" -#include "Poco/Net/MailMessage.h" -#include "Poco/Net/MailStream.h" -#include "Poco/Net/SocketAddress.h" -#include "Poco/Net/NetException.h" -#include "Poco/StreamCopier.h" -#include "Poco/NumberFormatter.h" -#include "Poco/UnbufferedStreamBuf.h" -#include "Poco/Ascii.h" -#include <istream> - - -using Poco::NumberFormatter; -using Poco::StreamCopier; - - -namespace Poco { -namespace Net { - - -class DialogStreamBuf: public Poco::UnbufferedStreamBuf -{ -public: - DialogStreamBuf(DialogSocket& socket): - _socket(socket) - { - } - - ~DialogStreamBuf() - { - } - -private: - int readFromDevice() - { - return _socket.get(); - } - - DialogSocket& _socket; -}; - - -class DialogIOS: public virtual std::ios -{ -public: - DialogIOS(DialogSocket& socket): - _buf(socket) - { - poco_ios_init(&_buf); - } - - ~DialogIOS() - { - } - - DialogStreamBuf* rdbuf() - { - return &_buf; - } - -protected: - DialogStreamBuf _buf; -}; - - -class DialogInputStream: public DialogIOS, public std::istream -{ -public: - DialogInputStream(DialogSocket& socket): - DialogIOS(socket), - std::istream(&_buf) - { - } - - ~DialogInputStream() - { - } -}; - - -POP3ClientSession::POP3ClientSession(const StreamSocket& socket): - _socket(socket), - _isOpen(true) -{ -} - - -POP3ClientSession::POP3ClientSession(const std::string& host, Poco::UInt16 port): - _socket(SocketAddress(host, port)), - _isOpen(true) -{ -} - - -POP3ClientSession::~POP3ClientSession() -{ - try - { - close(); - } - catch (...) - { - } -} - - -void POP3ClientSession::setTimeout(const Poco::Timespan& timeout) -{ - _socket.setReceiveTimeout(timeout); -} - - -Poco::Timespan POP3ClientSession::getTimeout() const -{ - return _socket.getReceiveTimeout(); -} - - -void POP3ClientSession::login(const std::string& username, const std::string& password) -{ - std::string response; - _socket.receiveMessage(response); - if (!isPositive(response)) throw POP3Exception("The POP3 service is unavailable", response); - sendCommand("USER", username, response); - if (!isPositive(response)) throw POP3Exception("Login rejected for user", response); - sendCommand("PASS", password, response); - if (!isPositive(response)) throw POP3Exception("Password rejected for user", response); -} - - -void POP3ClientSession::close() -{ - if (_isOpen) - { - std::string response; - sendCommand("QUIT", response); - _socket.close(); - _isOpen = false; - } -} - - -int POP3ClientSession::messageCount() -{ - std::string response; - sendCommand("STAT", response); - if (!isPositive(response)) throw POP3Exception("Cannot determine message count", response); - std::string::const_iterator it = response.begin(); - std::string::const_iterator end = response.end(); - int count = 0; - while (it != end && !Poco::Ascii::isSpace(*it)) ++it; - while (it != end && Poco::Ascii::isSpace(*it)) ++it; - while (it != end && Poco::Ascii::isDigit(*it)) count = count*10 + *it++ - '0'; - return count; -} - - -void POP3ClientSession::listMessages(MessageInfoVec& messages) -{ - messages.clear(); - std::string response; - sendCommand("LIST", response); - if (!isPositive(response)) throw POP3Exception("Cannot get message list", response); - _socket.receiveMessage(response); - while (response != ".") - { - MessageInfo info = {0, 0}; - std::string::const_iterator it = response.begin(); - std::string::const_iterator end = response.end(); - while (it != end && Poco::Ascii::isDigit(*it)) info.id = info.id*10 + *it++ - '0'; - while (it != end && Poco::Ascii::isSpace(*it)) ++it; - while (it != end && Poco::Ascii::isDigit(*it)) info.size = info.size*10 + *it++ - '0'; - messages.push_back(info); - _socket.receiveMessage(response); - } -} - - -void POP3ClientSession::retrieveMessage(int id, MailMessage& message) -{ - std::string response; - sendCommand("RETR", NumberFormatter::format(id), response); - if (!isPositive(response)) throw POP3Exception("Cannot retrieve message", response); - DialogInputStream sis(_socket); - MailInputStream mis(sis); - message.read(mis); - while (mis.good()) mis.get(); // read any remaining junk -} - - -void POP3ClientSession::retrieveMessage(int id, MailMessage& message, PartHandler& handler) -{ - std::string response; - sendCommand("RETR", NumberFormatter::format(id), response); - if (!isPositive(response)) throw POP3Exception("Cannot retrieve message", response); - DialogInputStream sis(_socket); - MailInputStream mis(sis); - message.read(mis, handler); - while (mis.good()) mis.get(); // read any remaining junk -} - - -void POP3ClientSession::retrieveMessage(int id, std::ostream& ostr) -{ - std::string response; - sendCommand("RETR", NumberFormatter::format(id), response); - if (!isPositive(response)) throw POP3Exception("Cannot retrieve message", response); - DialogInputStream sis(_socket); - MailInputStream mis(sis); - StreamCopier::copyStream(mis, ostr); -} - - -void POP3ClientSession::retrieveHeader(int id, MessageHeader& header) -{ - std::string response; - sendCommand("TOP", NumberFormatter::format(id), "0", response); - if (!isPositive(response)) throw POP3Exception("Cannot retrieve header", response); - DialogInputStream sis(_socket); - MailInputStream mis(sis); - header.read(mis); - // skip stuff following header - mis.get(); // \r - mis.get(); // \n -} - - -void POP3ClientSession::deleteMessage(int id) -{ - std::string response; - sendCommand("DELE", NumberFormatter::format(id), response); - if (!isPositive(response)) throw POP3Exception("Cannot mark message for deletion", response); -} - - -bool POP3ClientSession::sendCommand(const std::string& command, std::string& response) -{ - _socket.sendMessage(command); - _socket.receiveMessage(response); - return isPositive(response); -} - - -bool POP3ClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response) -{ - _socket.sendMessage(command, arg); - _socket.receiveMessage(response); - return isPositive(response); -} - - -bool POP3ClientSession::sendCommand(const std::string& command, const std::string& arg1, const std::string& arg2, std::string& response) -{ - _socket.sendMessage(command, arg1, arg2); - _socket.receiveMessage(response); - return isPositive(response); -} - - -bool POP3ClientSession::isPositive(const std::string& response) -{ - return response.length() > 0 && response[0] == '+'; -} - - -} } // namespace Poco::Net +// +// POP3ClientSession.cpp +// +// Library: Net +// Package: Mail +// Module: POP3ClientSession +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/POP3ClientSession.h" +#include "Poco/Net/MailMessage.h" +#include "Poco/Net/MailStream.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/Net/NetException.h" +#include "Poco/StreamCopier.h" +#include "Poco/NumberFormatter.h" +#include "Poco/UnbufferedStreamBuf.h" +#include "Poco/Ascii.h" +#include <istream> + + +using Poco::NumberFormatter; +using Poco::StreamCopier; + + +namespace Poco { +namespace Net { + + +class DialogStreamBuf: public Poco::UnbufferedStreamBuf +{ +public: + DialogStreamBuf(DialogSocket& socket): + _socket(socket) + { + } + + ~DialogStreamBuf() + { + } + +private: + int readFromDevice() + { + return _socket.get(); + } + + DialogSocket& _socket; +}; + + +class DialogIOS: public virtual std::ios +{ +public: + DialogIOS(DialogSocket& socket): + _buf(socket) + { + poco_ios_init(&_buf); + } + + ~DialogIOS() + { + } + + DialogStreamBuf* rdbuf() + { + return &_buf; + } + +protected: + DialogStreamBuf _buf; +}; + + +class DialogInputStream: public DialogIOS, public std::istream +{ +public: + DialogInputStream(DialogSocket& socket): + DialogIOS(socket), + std::istream(&_buf) + { + } + + ~DialogInputStream() + { + } +}; + + +POP3ClientSession::POP3ClientSession(const StreamSocket& socket): + _socket(socket), + _isOpen(true) +{ +} + + +POP3ClientSession::POP3ClientSession(const std::string& host, Poco::UInt16 port): + _socket(SocketAddress(host, port)), + _isOpen(true) +{ +} + + +POP3ClientSession::~POP3ClientSession() +{ + try + { + close(); + } + catch (...) + { + } +} + + +void POP3ClientSession::setTimeout(const Poco::Timespan& timeout) +{ + _socket.setReceiveTimeout(timeout); +} + + +Poco::Timespan POP3ClientSession::getTimeout() const +{ + return _socket.getReceiveTimeout(); +} + + +void POP3ClientSession::login(const std::string& username, const std::string& password) +{ + std::string response; + _socket.receiveMessage(response); + if (!isPositive(response)) throw POP3Exception("The POP3 service is unavailable", response); + sendCommand("USER", username, response); + if (!isPositive(response)) throw POP3Exception("Login rejected for user", response); + sendCommand("PASS", password, response); + if (!isPositive(response)) throw POP3Exception("Password rejected for user", response); +} + + +void POP3ClientSession::close() +{ + if (_isOpen) + { + std::string response; + sendCommand("QUIT", response); + _socket.close(); + _isOpen = false; + } +} + + +int POP3ClientSession::messageCount() +{ + std::string response; + sendCommand("STAT", response); + if (!isPositive(response)) throw POP3Exception("Cannot determine message count", response); + std::string::const_iterator it = response.begin(); + std::string::const_iterator end = response.end(); + int count = 0; + while (it != end && !Poco::Ascii::isSpace(*it)) ++it; + while (it != end && Poco::Ascii::isSpace(*it)) ++it; + while (it != end && Poco::Ascii::isDigit(*it)) count = count*10 + *it++ - '0'; + return count; +} + + +void POP3ClientSession::listMessages(MessageInfoVec& messages) +{ + messages.clear(); + std::string response; + sendCommand("LIST", response); + if (!isPositive(response)) throw POP3Exception("Cannot get message list", response); + _socket.receiveMessage(response); + while (response != ".") + { + MessageInfo info = {0, 0}; + std::string::const_iterator it = response.begin(); + std::string::const_iterator end = response.end(); + while (it != end && Poco::Ascii::isDigit(*it)) info.id = info.id*10 + *it++ - '0'; + while (it != end && Poco::Ascii::isSpace(*it)) ++it; + while (it != end && Poco::Ascii::isDigit(*it)) info.size = info.size*10 + *it++ - '0'; + messages.push_back(info); + _socket.receiveMessage(response); + } +} + + +void POP3ClientSession::retrieveMessage(int id, MailMessage& message) +{ + std::string response; + sendCommand("RETR", NumberFormatter::format(id), response); + if (!isPositive(response)) throw POP3Exception("Cannot retrieve message", response); + DialogInputStream sis(_socket); + MailInputStream mis(sis); + message.read(mis); + while (mis.good()) mis.get(); // read any remaining junk +} + + +void POP3ClientSession::retrieveMessage(int id, MailMessage& message, PartHandler& handler) +{ + std::string response; + sendCommand("RETR", NumberFormatter::format(id), response); + if (!isPositive(response)) throw POP3Exception("Cannot retrieve message", response); + DialogInputStream sis(_socket); + MailInputStream mis(sis); + message.read(mis, handler); + while (mis.good()) mis.get(); // read any remaining junk +} + + +void POP3ClientSession::retrieveMessage(int id, std::ostream& ostr) +{ + std::string response; + sendCommand("RETR", NumberFormatter::format(id), response); + if (!isPositive(response)) throw POP3Exception("Cannot retrieve message", response); + DialogInputStream sis(_socket); + MailInputStream mis(sis); + StreamCopier::copyStream(mis, ostr); +} + + +void POP3ClientSession::retrieveHeader(int id, MessageHeader& header) +{ + std::string response; + sendCommand("TOP", NumberFormatter::format(id), "0", response); + if (!isPositive(response)) throw POP3Exception("Cannot retrieve header", response); + DialogInputStream sis(_socket); + MailInputStream mis(sis); + header.read(mis); + // skip stuff following header + mis.get(); // \r + mis.get(); // \n +} + + +void POP3ClientSession::deleteMessage(int id) +{ + std::string response; + sendCommand("DELE", NumberFormatter::format(id), response); + if (!isPositive(response)) throw POP3Exception("Cannot mark message for deletion", response); +} + + +bool POP3ClientSession::sendCommand(const std::string& command, std::string& response) +{ + _socket.sendMessage(command); + _socket.receiveMessage(response); + return isPositive(response); +} + + +bool POP3ClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response) +{ + _socket.sendMessage(command, arg); + _socket.receiveMessage(response); + return isPositive(response); +} + + +bool POP3ClientSession::sendCommand(const std::string& command, const std::string& arg1, const std::string& arg2, std::string& response) +{ + _socket.sendMessage(command, arg1, arg2); + _socket.receiveMessage(response); + return isPositive(response); +} + + +bool POP3ClientSession::isPositive(const std::string& response) +{ + return response.length() > 0 && response[0] == '+'; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/PartHandler.cpp b/contrib/libs/poco/Net/src/PartHandler.cpp index 945cf318b5..5eab4770bb 100644 --- a/contrib/libs/poco/Net/src/PartHandler.cpp +++ b/contrib/libs/poco/Net/src/PartHandler.cpp @@ -1,32 +1,32 @@ -// -// PartHandler.cpp -// -// Library: Net -// Package: Messages -// Module: PartHandler -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/PartHandler.h" - - -namespace Poco { -namespace Net { - - -PartHandler::PartHandler() -{ -} - - -PartHandler::~PartHandler() -{ -} - - -} } // namespace Poco::Net +// +// PartHandler.cpp +// +// Library: Net +// Package: Messages +// Module: PartHandler +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/PartHandler.h" + + +namespace Poco { +namespace Net { + + +PartHandler::PartHandler() +{ +} + + +PartHandler::~PartHandler() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/PartSource.cpp b/contrib/libs/poco/Net/src/PartSource.cpp index 22f6c66828..240b9fbaa0 100644 --- a/contrib/libs/poco/Net/src/PartSource.cpp +++ b/contrib/libs/poco/Net/src/PartSource.cpp @@ -1,58 +1,58 @@ -// -// PartSource.cpp -// -// Library: Net -// Package: Messages -// Module: PartSource -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/PartSource.h" - - -namespace Poco { -namespace Net { - - -const int PartSource::UNKNOWN_CONTENT_LENGTH = -1; - - -PartSource::PartSource(): - _mediaType("application/octet-stream") -{ -} - - -PartSource::PartSource(const std::string& mediaType): - _mediaType(mediaType) -{ -} - - -PartSource::~PartSource() -{ -} - - -namespace -{ - static const std::string EMPTY; -} - - -const std::string& PartSource::filename() const -{ - return EMPTY; -} - -std::streamsize PartSource::getContentLength() const -{ - return UNKNOWN_CONTENT_LENGTH; -} - -} } // namespace Poco::Net +// +// PartSource.cpp +// +// Library: Net +// Package: Messages +// Module: PartSource +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/PartSource.h" + + +namespace Poco { +namespace Net { + + +const int PartSource::UNKNOWN_CONTENT_LENGTH = -1; + + +PartSource::PartSource(): + _mediaType("application/octet-stream") +{ +} + + +PartSource::PartSource(const std::string& mediaType): + _mediaType(mediaType) +{ +} + + +PartSource::~PartSource() +{ +} + + +namespace +{ + static const std::string EMPTY; +} + + +const std::string& PartSource::filename() const +{ + return EMPTY; +} + +std::streamsize PartSource::getContentLength() const +{ + return UNKNOWN_CONTENT_LENGTH; +} + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/PartStore.cpp b/contrib/libs/poco/Net/src/PartStore.cpp index 3b0b0251d0..14179f429a 100644 --- a/contrib/libs/poco/Net/src/PartStore.cpp +++ b/contrib/libs/poco/Net/src/PartStore.cpp @@ -1,87 +1,87 @@ -// -// PartStore.cpp -// -// Library: Net -// Package: Messages -// Module: PartStore -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/PartStore.h" -#include "Poco/TemporaryFile.h" -#include "Poco/File.h" -#include "Poco/Exception.h" - - -namespace Poco { -namespace Net { - - -// -// PartStore -// - - -PartStore::PartStore(const std::string& mediaType): PartSource(mediaType) -{ -} - - -PartStore::~PartStore() -{ -} - - -// -// FilePartStore -// - - -FilePartStore::FilePartStore(const std::string& content, const std::string& mediaType, const std::string& filename): - PartStore(mediaType), - _filename(filename), - _path(TemporaryFile::tempName()), - _fstr(_path) -{ - _fstr << content << std::flush; - _fstr.seekg(0, std::ios::beg); -} - - -FilePartStore::~FilePartStore() -{ - try - { - _fstr.close(); - File(_path).remove(); - } - catch (...) - { - } -} - - -std::istream& FilePartStore::stream() -{ - return _fstr; -} - - -const std::string& FilePartStore::filename() const -{ - return _filename; -} - - -const std::string& FilePartStore::path() const -{ - return _path; -} - - -} } // namespace Poco::Net +// +// PartStore.cpp +// +// Library: Net +// Package: Messages +// Module: PartStore +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/PartStore.h" +#include "Poco/TemporaryFile.h" +#include "Poco/File.h" +#include "Poco/Exception.h" + + +namespace Poco { +namespace Net { + + +// +// PartStore +// + + +PartStore::PartStore(const std::string& mediaType): PartSource(mediaType) +{ +} + + +PartStore::~PartStore() +{ +} + + +// +// FilePartStore +// + + +FilePartStore::FilePartStore(const std::string& content, const std::string& mediaType, const std::string& filename): + PartStore(mediaType), + _filename(filename), + _path(TemporaryFile::tempName()), + _fstr(_path) +{ + _fstr << content << std::flush; + _fstr.seekg(0, std::ios::beg); +} + + +FilePartStore::~FilePartStore() +{ + try + { + _fstr.close(); + File(_path).remove(); + } + catch (...) + { + } +} + + +std::istream& FilePartStore::stream() +{ + return _fstr; +} + + +const std::string& FilePartStore::filename() const +{ + return _filename; +} + + +const std::string& FilePartStore::path() const +{ + return _path; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/PollSet.cpp b/contrib/libs/poco/Net/src/PollSet.cpp index 57d481d23e..25e911bf9e 100644 --- a/contrib/libs/poco/Net/src/PollSet.cpp +++ b/contrib/libs/poco/Net/src/PollSet.cpp @@ -1,529 +1,529 @@ -// -// PollSet.cpp -// -// Library: Net -// Package: Sockets -// Module: PollSet -// -// Copyright (c) 2016, Applied Informatics Software Engineering GmbH. -// All rights reserved. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/PollSet.h" -#include "Poco/Net/SocketImpl.h" -#include "Poco/Mutex.h" -#include <set> - - -#if defined(_WIN32) && _WIN32_WINNT >= 0x0600 -#ifndef POCO_HAVE_FD_POLL -#define POCO_HAVE_FD_POLL 1 -#endif -#elif defined(POCO_OS_FAMILY_BSD) -#ifndef POCO_HAVE_FD_POLL -#define POCO_HAVE_FD_POLL 1 -#endif -#endif - - -#if defined(POCO_HAVE_FD_EPOLL) -#include <sys/epoll.h> -#elif defined(POCO_HAVE_FD_POLL) -#ifndef _WIN32 -#include <poll.h> -#endif -#endif - - -namespace Poco { -namespace Net { - - -#if defined(POCO_HAVE_FD_EPOLL) - - -// -// Linux implementation using epoll -// -class PollSetImpl -{ -public: - PollSetImpl(): - _epollfd(-1), - _events(1024) - { - _epollfd = epoll_create(1); - if (_epollfd < 0) - { - SocketImpl::error(); - } - } - - ~PollSetImpl() - { - if (_epollfd >= 0) - ::close(_epollfd); - } - - void add(const Socket& socket, int mode) - { - Poco::FastMutex::ScopedLock lock(_mutex); - - SocketImpl* sockImpl = socket.impl(); - poco_socket_t fd = sockImpl->sockfd(); - struct epoll_event ev; - ev.events = 0; - if (mode & PollSet::POLL_READ) - ev.events |= EPOLLIN; - if (mode & PollSet::POLL_WRITE) - ev.events |= EPOLLOUT; - if (mode & PollSet::POLL_ERROR) - ev.events |= EPOLLERR; - ev.data.ptr = socket.impl(); - int err = epoll_ctl(_epollfd, EPOLL_CTL_ADD, fd, &ev); - - if (err) - { - if (errno == EEXIST) update(socket, mode); - else SocketImpl::error(); - } - - if (_socketMap.find(sockImpl) == _socketMap.end()) - _socketMap[sockImpl] = socket; - } - - void remove(const Socket& socket) - { - Poco::FastMutex::ScopedLock lock(_mutex); - - poco_socket_t fd = socket.impl()->sockfd(); - struct epoll_event ev; - ev.events = 0; - ev.data.ptr = 0; - int err = epoll_ctl(_epollfd, EPOLL_CTL_DEL, fd, &ev); - if (err) SocketImpl::error(); - - _socketMap.erase(socket.impl()); - } - - void update(const Socket& socket, int mode) - { - poco_socket_t fd = socket.impl()->sockfd(); - struct epoll_event ev; - ev.events = 0; - if (mode & PollSet::POLL_READ) - ev.events |= EPOLLIN; - if (mode & PollSet::POLL_WRITE) - ev.events |= EPOLLOUT; - if (mode & PollSet::POLL_ERROR) - ev.events |= EPOLLERR; - ev.data.ptr = socket.impl(); - int err = epoll_ctl(_epollfd, EPOLL_CTL_MOD, fd, &ev); - if (err) - { - SocketImpl::error(); - } - } - - void clear() - { - Poco::FastMutex::ScopedLock lock(_mutex); - - ::close(_epollfd); - _socketMap.clear(); - _epollfd = epoll_create(1); - if (_epollfd < 0) - { - SocketImpl::error(); - } - } - - PollSet::SocketModeMap poll(const Poco::Timespan& timeout) - { - PollSet::SocketModeMap result; - - if (_socketMap.empty()) return result; - - Poco::Timespan remainingTime(timeout); - int rc; - do - { - Poco::Timestamp start; - rc = epoll_wait(_epollfd, &_events[0], _events.size(), remainingTime.totalMilliseconds()); - if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) - { - Poco::Timestamp end; - Poco::Timespan waited = end - start; - if (waited < remainingTime) - remainingTime -= waited; - else - remainingTime = 0; - } - } - while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); - if (rc < 0) SocketImpl::error(); - - Poco::FastMutex::ScopedLock lock(_mutex); - - for (int i = 0; i < rc; i++) - { - std::map<void*, Socket>::iterator it = _socketMap.find(_events[i].data.ptr); - if (it != _socketMap.end()) - { - if (_events[i].events & EPOLLIN) - result[it->second] |= PollSet::POLL_READ; - if (_events[i].events & EPOLLOUT) - result[it->second] |= PollSet::POLL_WRITE; - if (_events[i].events & EPOLLERR) - result[it->second] |= PollSet::POLL_ERROR; - } - } - - return result; - } - -private: - Poco::FastMutex _mutex; - int _epollfd; - std::map<void*, Socket> _socketMap; - std::vector<struct epoll_event> _events; -}; - - -#elif defined(POCO_HAVE_FD_POLL) - - -// -// BSD implementation using poll -// -class PollSetImpl -{ -public: - void add(const Socket& socket, int mode) - { - Poco::FastMutex::ScopedLock lock(_mutex); - - poco_socket_t fd = socket.impl()->sockfd(); - _addMap[fd] = mode; - _removeSet.erase(fd); - _socketMap[fd] = socket; - } - - void remove(const Socket& socket) - { - Poco::FastMutex::ScopedLock lock(_mutex); - - poco_socket_t fd = socket.impl()->sockfd(); - _removeSet.insert(fd); - _addMap.erase(fd); - _socketMap.erase(fd); - } - - void update(const Socket& socket, int mode) - { - Poco::FastMutex::ScopedLock lock(_mutex); - - poco_socket_t fd = socket.impl()->sockfd(); - for (std::vector<pollfd>::iterator it = _pollfds.begin(); it != _pollfds.end(); ++it) - { - if (it->fd == fd) - { - it->events = 0; - if (mode & PollSet::POLL_READ) - it->events |= POLLIN; - if (mode & PollSet::POLL_WRITE) - it->events |= POLLOUT; - } - } - } - - void clear() - { - Poco::FastMutex::ScopedLock lock(_mutex); - - _socketMap.clear(); - _addMap.clear(); - _removeSet.clear(); - _pollfds.clear(); - } - - PollSet::SocketModeMap poll(const Poco::Timespan& timeout) - { - PollSet::SocketModeMap result; - { - Poco::FastMutex::ScopedLock lock(_mutex); - - if (!_removeSet.empty()) - { - for (std::vector<pollfd>::iterator it = _pollfds.begin(); it != _pollfds.end();) - { - if (_removeSet.find(it->fd) != _removeSet.end()) - { - it = _pollfds.erase(it); - } - else ++it; - } - _removeSet.clear(); - } - - _pollfds.reserve(_pollfds.size() + _addMap.size()); - for (std::map<poco_socket_t, int>::iterator it = _addMap.begin(); it != _addMap.end(); ++it) - { - pollfd pfd; - pfd.fd = it->first; - pfd.events = 0; - pfd.revents = 0; - if (it->second & PollSet::POLL_READ) - pfd.events |= POLLIN; - if (it->second & PollSet::POLL_WRITE) - pfd.events |= POLLOUT; - - _pollfds.push_back(pfd); - } - _addMap.clear(); - } - - if (_pollfds.empty()) return result; - - Poco::Timespan remainingTime(timeout); - int rc; - do - { - Poco::Timestamp start; -#ifdef _WIN32 - rc = WSAPoll(&_pollfds[0], _pollfds.size(), static_cast<INT>(timeout.totalMilliseconds())); -#else - rc = ::poll(&_pollfds[0], _pollfds.size(), timeout.totalMilliseconds()); -#endif - if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) - { - Poco::Timestamp end; - Poco::Timespan waited = end - start; - if (waited < remainingTime) - remainingTime -= waited; - else - remainingTime = 0; - } - } - while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); - if (rc < 0) SocketImpl::error(); - - { - Poco::FastMutex::ScopedLock lock(_mutex); - - if (!_socketMap.empty()) - { - for (std::vector<pollfd>::iterator it = _pollfds.begin(); it != _pollfds.end(); ++it) - { - std::map<poco_socket_t, Socket>::const_iterator its = _socketMap.find(it->fd); - if (its != _socketMap.end()) - { - if (it->revents & POLLIN) - result[its->second] |= PollSet::POLL_READ; - if (it->revents & POLLOUT) - result[its->second] |= PollSet::POLL_WRITE; - if (it->revents & POLLERR) - result[its->second] |= PollSet::POLL_ERROR; -#ifdef _WIN32 - if (it->revents & POLLHUP) - result[its->second] |= PollSet::POLL_READ; -#endif - } - it->revents = 0; - } - } - } - - return result; - } - -private: - Poco::FastMutex _mutex; - std::map<poco_socket_t, Socket> _socketMap; - std::map<poco_socket_t, int> _addMap; - std::set<poco_socket_t> _removeSet; - std::vector<pollfd> _pollfds; -}; - - -#else - - -// -// Fallback implementation using select() -// -class PollSetImpl -{ -public: - void add(const Socket& socket, int mode) - { - Poco::FastMutex::ScopedLock lock(_mutex); - - _map[socket] = mode; - } - - void remove(const Socket& socket) - { - Poco::FastMutex::ScopedLock lock(_mutex); - - _map.erase(socket); - } - - void update(const Socket& socket, int mode) - { - Poco::FastMutex::ScopedLock lock(_mutex); - - _map[socket] = mode; - } - - void clear() - { - Poco::FastMutex::ScopedLock lock(_mutex); - - _map.clear(); - } - - PollSet::SocketModeMap poll(const Poco::Timespan& timeout) - { - fd_set fdRead; - fd_set fdWrite; - fd_set fdExcept; - int nfd = 0; - - FD_ZERO(&fdRead); - FD_ZERO(&fdWrite); - FD_ZERO(&fdExcept); - - { - Poco::FastMutex::ScopedLock lock(_mutex); - - for (PollSet::SocketModeMap::const_iterator it = _map.begin(); it != _map.end(); ++it) - { - poco_socket_t fd = it->first.impl()->sockfd(); - if (fd != POCO_INVALID_SOCKET && it->second) - { - if (int(fd) > nfd) nfd = int(fd); - - if (it->second & PollSet::POLL_READ) - { - FD_SET(fd, &fdRead); - } - if (it->second & PollSet::POLL_WRITE) - { - FD_SET(fd, &fdWrite); - } - if (it->second & PollSet::POLL_ERROR) - { - FD_SET(fd, &fdExcept); - } - } - } - } - - PollSet::SocketModeMap result; - if (nfd == 0) return result; - - Poco::Timespan remainingTime(timeout); - int rc; - do - { - struct timeval tv; - tv.tv_sec = (long) remainingTime.totalSeconds(); - tv.tv_usec = (long) remainingTime.useconds(); - Poco::Timestamp start; - rc = ::select(nfd + 1, &fdRead, &fdWrite, &fdExcept, &tv); - if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) - { - Poco::Timestamp end; - Poco::Timespan waited = end - start; - if (waited < remainingTime) - remainingTime -= waited; - else - remainingTime = 0; - } - } - while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); - if (rc < 0) SocketImpl::error(); - - { - Poco::FastMutex::ScopedLock lock(_mutex); - - for (PollSet::SocketModeMap::const_iterator it = _map.begin(); it != _map.end(); ++it) - { - poco_socket_t fd = it->first.impl()->sockfd(); - if (fd != POCO_INVALID_SOCKET) - { - if (FD_ISSET(fd, &fdRead)) - { - result[it->first] |= PollSet::POLL_READ; - } - if (FD_ISSET(fd, &fdWrite)) - { - result[it->first] |= PollSet::POLL_WRITE; - } - if (FD_ISSET(fd, &fdExcept)) - { - result[it->first] |= PollSet::POLL_ERROR; - } - } - } - } - - return result; - } - -private: - Poco::FastMutex _mutex; - PollSet::SocketModeMap _map; -}; - - -#endif - - -PollSet::PollSet(): - _pImpl(new PollSetImpl) -{ -} - - -PollSet::~PollSet() -{ - delete _pImpl; -} - - -void PollSet::add(const Socket& socket, int mode) -{ - _pImpl->add(socket, mode); -} - - -void PollSet::remove(const Socket& socket) -{ - _pImpl->remove(socket); -} - - -void PollSet::update(const Socket& socket, int mode) -{ - _pImpl->update(socket, mode); -} - - -void PollSet::clear() -{ - _pImpl->clear(); -} - - -PollSet::SocketModeMap PollSet::poll(const Poco::Timespan& timeout) -{ - return _pImpl->poll(timeout); -} - - -} } // namespace Poco::Net +// +// PollSet.cpp +// +// Library: Net +// Package: Sockets +// Module: PollSet +// +// Copyright (c) 2016, Applied Informatics Software Engineering GmbH. +// All rights reserved. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/PollSet.h" +#include "Poco/Net/SocketImpl.h" +#include "Poco/Mutex.h" +#include <set> + + +#if defined(_WIN32) && _WIN32_WINNT >= 0x0600 +#ifndef POCO_HAVE_FD_POLL +#define POCO_HAVE_FD_POLL 1 +#endif +#elif defined(POCO_OS_FAMILY_BSD) +#ifndef POCO_HAVE_FD_POLL +#define POCO_HAVE_FD_POLL 1 +#endif +#endif + + +#if defined(POCO_HAVE_FD_EPOLL) +#include <sys/epoll.h> +#elif defined(POCO_HAVE_FD_POLL) +#ifndef _WIN32 +#include <poll.h> +#endif +#endif + + +namespace Poco { +namespace Net { + + +#if defined(POCO_HAVE_FD_EPOLL) + + +// +// Linux implementation using epoll +// +class PollSetImpl +{ +public: + PollSetImpl(): + _epollfd(-1), + _events(1024) + { + _epollfd = epoll_create(1); + if (_epollfd < 0) + { + SocketImpl::error(); + } + } + + ~PollSetImpl() + { + if (_epollfd >= 0) + ::close(_epollfd); + } + + void add(const Socket& socket, int mode) + { + Poco::FastMutex::ScopedLock lock(_mutex); + + SocketImpl* sockImpl = socket.impl(); + poco_socket_t fd = sockImpl->sockfd(); + struct epoll_event ev; + ev.events = 0; + if (mode & PollSet::POLL_READ) + ev.events |= EPOLLIN; + if (mode & PollSet::POLL_WRITE) + ev.events |= EPOLLOUT; + if (mode & PollSet::POLL_ERROR) + ev.events |= EPOLLERR; + ev.data.ptr = socket.impl(); + int err = epoll_ctl(_epollfd, EPOLL_CTL_ADD, fd, &ev); + + if (err) + { + if (errno == EEXIST) update(socket, mode); + else SocketImpl::error(); + } + + if (_socketMap.find(sockImpl) == _socketMap.end()) + _socketMap[sockImpl] = socket; + } + + void remove(const Socket& socket) + { + Poco::FastMutex::ScopedLock lock(_mutex); + + poco_socket_t fd = socket.impl()->sockfd(); + struct epoll_event ev; + ev.events = 0; + ev.data.ptr = 0; + int err = epoll_ctl(_epollfd, EPOLL_CTL_DEL, fd, &ev); + if (err) SocketImpl::error(); + + _socketMap.erase(socket.impl()); + } + + void update(const Socket& socket, int mode) + { + poco_socket_t fd = socket.impl()->sockfd(); + struct epoll_event ev; + ev.events = 0; + if (mode & PollSet::POLL_READ) + ev.events |= EPOLLIN; + if (mode & PollSet::POLL_WRITE) + ev.events |= EPOLLOUT; + if (mode & PollSet::POLL_ERROR) + ev.events |= EPOLLERR; + ev.data.ptr = socket.impl(); + int err = epoll_ctl(_epollfd, EPOLL_CTL_MOD, fd, &ev); + if (err) + { + SocketImpl::error(); + } + } + + void clear() + { + Poco::FastMutex::ScopedLock lock(_mutex); + + ::close(_epollfd); + _socketMap.clear(); + _epollfd = epoll_create(1); + if (_epollfd < 0) + { + SocketImpl::error(); + } + } + + PollSet::SocketModeMap poll(const Poco::Timespan& timeout) + { + PollSet::SocketModeMap result; + + if (_socketMap.empty()) return result; + + Poco::Timespan remainingTime(timeout); + int rc; + do + { + Poco::Timestamp start; + rc = epoll_wait(_epollfd, &_events[0], _events.size(), remainingTime.totalMilliseconds()); + if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) + { + Poco::Timestamp end; + Poco::Timespan waited = end - start; + if (waited < remainingTime) + remainingTime -= waited; + else + remainingTime = 0; + } + } + while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); + if (rc < 0) SocketImpl::error(); + + Poco::FastMutex::ScopedLock lock(_mutex); + + for (int i = 0; i < rc; i++) + { + std::map<void*, Socket>::iterator it = _socketMap.find(_events[i].data.ptr); + if (it != _socketMap.end()) + { + if (_events[i].events & EPOLLIN) + result[it->second] |= PollSet::POLL_READ; + if (_events[i].events & EPOLLOUT) + result[it->second] |= PollSet::POLL_WRITE; + if (_events[i].events & EPOLLERR) + result[it->second] |= PollSet::POLL_ERROR; + } + } + + return result; + } + +private: + Poco::FastMutex _mutex; + int _epollfd; + std::map<void*, Socket> _socketMap; + std::vector<struct epoll_event> _events; +}; + + +#elif defined(POCO_HAVE_FD_POLL) + + +// +// BSD implementation using poll +// +class PollSetImpl +{ +public: + void add(const Socket& socket, int mode) + { + Poco::FastMutex::ScopedLock lock(_mutex); + + poco_socket_t fd = socket.impl()->sockfd(); + _addMap[fd] = mode; + _removeSet.erase(fd); + _socketMap[fd] = socket; + } + + void remove(const Socket& socket) + { + Poco::FastMutex::ScopedLock lock(_mutex); + + poco_socket_t fd = socket.impl()->sockfd(); + _removeSet.insert(fd); + _addMap.erase(fd); + _socketMap.erase(fd); + } + + void update(const Socket& socket, int mode) + { + Poco::FastMutex::ScopedLock lock(_mutex); + + poco_socket_t fd = socket.impl()->sockfd(); + for (std::vector<pollfd>::iterator it = _pollfds.begin(); it != _pollfds.end(); ++it) + { + if (it->fd == fd) + { + it->events = 0; + if (mode & PollSet::POLL_READ) + it->events |= POLLIN; + if (mode & PollSet::POLL_WRITE) + it->events |= POLLOUT; + } + } + } + + void clear() + { + Poco::FastMutex::ScopedLock lock(_mutex); + + _socketMap.clear(); + _addMap.clear(); + _removeSet.clear(); + _pollfds.clear(); + } + + PollSet::SocketModeMap poll(const Poco::Timespan& timeout) + { + PollSet::SocketModeMap result; + { + Poco::FastMutex::ScopedLock lock(_mutex); + + if (!_removeSet.empty()) + { + for (std::vector<pollfd>::iterator it = _pollfds.begin(); it != _pollfds.end();) + { + if (_removeSet.find(it->fd) != _removeSet.end()) + { + it = _pollfds.erase(it); + } + else ++it; + } + _removeSet.clear(); + } + + _pollfds.reserve(_pollfds.size() + _addMap.size()); + for (std::map<poco_socket_t, int>::iterator it = _addMap.begin(); it != _addMap.end(); ++it) + { + pollfd pfd; + pfd.fd = it->first; + pfd.events = 0; + pfd.revents = 0; + if (it->second & PollSet::POLL_READ) + pfd.events |= POLLIN; + if (it->second & PollSet::POLL_WRITE) + pfd.events |= POLLOUT; + + _pollfds.push_back(pfd); + } + _addMap.clear(); + } + + if (_pollfds.empty()) return result; + + Poco::Timespan remainingTime(timeout); + int rc; + do + { + Poco::Timestamp start; +#ifdef _WIN32 + rc = WSAPoll(&_pollfds[0], _pollfds.size(), static_cast<INT>(timeout.totalMilliseconds())); +#else + rc = ::poll(&_pollfds[0], _pollfds.size(), timeout.totalMilliseconds()); +#endif + if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) + { + Poco::Timestamp end; + Poco::Timespan waited = end - start; + if (waited < remainingTime) + remainingTime -= waited; + else + remainingTime = 0; + } + } + while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); + if (rc < 0) SocketImpl::error(); + + { + Poco::FastMutex::ScopedLock lock(_mutex); + + if (!_socketMap.empty()) + { + for (std::vector<pollfd>::iterator it = _pollfds.begin(); it != _pollfds.end(); ++it) + { + std::map<poco_socket_t, Socket>::const_iterator its = _socketMap.find(it->fd); + if (its != _socketMap.end()) + { + if (it->revents & POLLIN) + result[its->second] |= PollSet::POLL_READ; + if (it->revents & POLLOUT) + result[its->second] |= PollSet::POLL_WRITE; + if (it->revents & POLLERR) + result[its->second] |= PollSet::POLL_ERROR; +#ifdef _WIN32 + if (it->revents & POLLHUP) + result[its->second] |= PollSet::POLL_READ; +#endif + } + it->revents = 0; + } + } + } + + return result; + } + +private: + Poco::FastMutex _mutex; + std::map<poco_socket_t, Socket> _socketMap; + std::map<poco_socket_t, int> _addMap; + std::set<poco_socket_t> _removeSet; + std::vector<pollfd> _pollfds; +}; + + +#else + + +// +// Fallback implementation using select() +// +class PollSetImpl +{ +public: + void add(const Socket& socket, int mode) + { + Poco::FastMutex::ScopedLock lock(_mutex); + + _map[socket] = mode; + } + + void remove(const Socket& socket) + { + Poco::FastMutex::ScopedLock lock(_mutex); + + _map.erase(socket); + } + + void update(const Socket& socket, int mode) + { + Poco::FastMutex::ScopedLock lock(_mutex); + + _map[socket] = mode; + } + + void clear() + { + Poco::FastMutex::ScopedLock lock(_mutex); + + _map.clear(); + } + + PollSet::SocketModeMap poll(const Poco::Timespan& timeout) + { + fd_set fdRead; + fd_set fdWrite; + fd_set fdExcept; + int nfd = 0; + + FD_ZERO(&fdRead); + FD_ZERO(&fdWrite); + FD_ZERO(&fdExcept); + + { + Poco::FastMutex::ScopedLock lock(_mutex); + + for (PollSet::SocketModeMap::const_iterator it = _map.begin(); it != _map.end(); ++it) + { + poco_socket_t fd = it->first.impl()->sockfd(); + if (fd != POCO_INVALID_SOCKET && it->second) + { + if (int(fd) > nfd) nfd = int(fd); + + if (it->second & PollSet::POLL_READ) + { + FD_SET(fd, &fdRead); + } + if (it->second & PollSet::POLL_WRITE) + { + FD_SET(fd, &fdWrite); + } + if (it->second & PollSet::POLL_ERROR) + { + FD_SET(fd, &fdExcept); + } + } + } + } + + PollSet::SocketModeMap result; + if (nfd == 0) return result; + + Poco::Timespan remainingTime(timeout); + int rc; + do + { + struct timeval tv; + tv.tv_sec = (long) remainingTime.totalSeconds(); + tv.tv_usec = (long) remainingTime.useconds(); + Poco::Timestamp start; + rc = ::select(nfd + 1, &fdRead, &fdWrite, &fdExcept, &tv); + if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) + { + Poco::Timestamp end; + Poco::Timespan waited = end - start; + if (waited < remainingTime) + remainingTime -= waited; + else + remainingTime = 0; + } + } + while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); + if (rc < 0) SocketImpl::error(); + + { + Poco::FastMutex::ScopedLock lock(_mutex); + + for (PollSet::SocketModeMap::const_iterator it = _map.begin(); it != _map.end(); ++it) + { + poco_socket_t fd = it->first.impl()->sockfd(); + if (fd != POCO_INVALID_SOCKET) + { + if (FD_ISSET(fd, &fdRead)) + { + result[it->first] |= PollSet::POLL_READ; + } + if (FD_ISSET(fd, &fdWrite)) + { + result[it->first] |= PollSet::POLL_WRITE; + } + if (FD_ISSET(fd, &fdExcept)) + { + result[it->first] |= PollSet::POLL_ERROR; + } + } + } + } + + return result; + } + +private: + Poco::FastMutex _mutex; + PollSet::SocketModeMap _map; +}; + + +#endif + + +PollSet::PollSet(): + _pImpl(new PollSetImpl) +{ +} + + +PollSet::~PollSet() +{ + delete _pImpl; +} + + +void PollSet::add(const Socket& socket, int mode) +{ + _pImpl->add(socket, mode); +} + + +void PollSet::remove(const Socket& socket) +{ + _pImpl->remove(socket); +} + + +void PollSet::update(const Socket& socket, int mode) +{ + _pImpl->update(socket, mode); +} + + +void PollSet::clear() +{ + _pImpl->clear(); +} + + +PollSet::SocketModeMap PollSet::poll(const Poco::Timespan& timeout) +{ + return _pImpl->poll(timeout); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/QuotedPrintableDecoder.cpp b/contrib/libs/poco/Net/src/QuotedPrintableDecoder.cpp index 4f8b3c6726..c3c0ed5880 100644 --- a/contrib/libs/poco/Net/src/QuotedPrintableDecoder.cpp +++ b/contrib/libs/poco/Net/src/QuotedPrintableDecoder.cpp @@ -1,102 +1,102 @@ -// -// QuotedPrintableDecoder.cpp -// -// Library: Net -// Package: Messages -// Module: QuotedPrintableDecoder -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/QuotedPrintableDecoder.h" -#include "Poco/NumberParser.h" -#include "Poco/Exception.h" -#include "Poco/Ascii.h" - - -using Poco::UnbufferedStreamBuf; -using Poco::NumberParser; -using Poco::DataFormatException; - - -namespace Poco { -namespace Net { - - -QuotedPrintableDecoderBuf::QuotedPrintableDecoderBuf(std::istream& istr): - _buf(*istr.rdbuf()) -{ -} - - -QuotedPrintableDecoderBuf::~QuotedPrintableDecoderBuf() -{ -} - - -int QuotedPrintableDecoderBuf::readFromDevice() -{ - int ch = _buf.sbumpc(); - while (ch == '=') - { - ch = _buf.sbumpc(); - if (ch == '\r') - { - _buf.sbumpc(); // read \n - } - else if (Poco::Ascii::isHexDigit(ch)) - { - std::string hex = "0x"; - hex += (char) ch; - ch = _buf.sbumpc(); - if (Poco::Ascii::isHexDigit(ch)) - { - hex += (char) ch; - return NumberParser::parseHex(hex); - } - throw DataFormatException("Incomplete hex number in quoted-printable encoded stream"); - } - else if (ch != '\n') - { - throw DataFormatException("Invalid occurrence of '=' in quoted-printable encoded stream"); - } - ch = _buf.sbumpc(); - } - return ch; -} - - -QuotedPrintableDecoderIOS::QuotedPrintableDecoderIOS(std::istream& istr): _buf(istr) -{ - poco_ios_init(&_buf); -} - - -QuotedPrintableDecoderIOS::~QuotedPrintableDecoderIOS() -{ -} - - -QuotedPrintableDecoderBuf* QuotedPrintableDecoderIOS::rdbuf() -{ - return &_buf; -} - - -QuotedPrintableDecoder::QuotedPrintableDecoder(std::istream& istr): - QuotedPrintableDecoderIOS(istr), - std::istream(&_buf) -{ -} - - -QuotedPrintableDecoder::~QuotedPrintableDecoder() -{ -} - - -} } // namespace Poco::Net +// +// QuotedPrintableDecoder.cpp +// +// Library: Net +// Package: Messages +// Module: QuotedPrintableDecoder +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/QuotedPrintableDecoder.h" +#include "Poco/NumberParser.h" +#include "Poco/Exception.h" +#include "Poco/Ascii.h" + + +using Poco::UnbufferedStreamBuf; +using Poco::NumberParser; +using Poco::DataFormatException; + + +namespace Poco { +namespace Net { + + +QuotedPrintableDecoderBuf::QuotedPrintableDecoderBuf(std::istream& istr): + _buf(*istr.rdbuf()) +{ +} + + +QuotedPrintableDecoderBuf::~QuotedPrintableDecoderBuf() +{ +} + + +int QuotedPrintableDecoderBuf::readFromDevice() +{ + int ch = _buf.sbumpc(); + while (ch == '=') + { + ch = _buf.sbumpc(); + if (ch == '\r') + { + _buf.sbumpc(); // read \n + } + else if (Poco::Ascii::isHexDigit(ch)) + { + std::string hex = "0x"; + hex += (char) ch; + ch = _buf.sbumpc(); + if (Poco::Ascii::isHexDigit(ch)) + { + hex += (char) ch; + return NumberParser::parseHex(hex); + } + throw DataFormatException("Incomplete hex number in quoted-printable encoded stream"); + } + else if (ch != '\n') + { + throw DataFormatException("Invalid occurrence of '=' in quoted-printable encoded stream"); + } + ch = _buf.sbumpc(); + } + return ch; +} + + +QuotedPrintableDecoderIOS::QuotedPrintableDecoderIOS(std::istream& istr): _buf(istr) +{ + poco_ios_init(&_buf); +} + + +QuotedPrintableDecoderIOS::~QuotedPrintableDecoderIOS() +{ +} + + +QuotedPrintableDecoderBuf* QuotedPrintableDecoderIOS::rdbuf() +{ + return &_buf; +} + + +QuotedPrintableDecoder::QuotedPrintableDecoder(std::istream& istr): + QuotedPrintableDecoderIOS(istr), + std::istream(&_buf) +{ +} + + +QuotedPrintableDecoder::~QuotedPrintableDecoder() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/QuotedPrintableEncoder.cpp b/contrib/libs/poco/Net/src/QuotedPrintableEncoder.cpp index a71eb154f5..d34f1bd58f 100644 --- a/contrib/libs/poco/Net/src/QuotedPrintableEncoder.cpp +++ b/contrib/libs/poco/Net/src/QuotedPrintableEncoder.cpp @@ -1,150 +1,150 @@ -// -// QuotedPrintableEncoder.cpp -// -// Library: Net -// Package: Messages -// Module: QuotedPrintableEncoder -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/QuotedPrintableEncoder.h" -#include "Poco/NumberFormatter.h" - - -using Poco::UnbufferedStreamBuf; -using Poco::NumberFormatter; - - -namespace Poco { -namespace Net { - - -QuotedPrintableEncoderBuf::QuotedPrintableEncoderBuf(std::ostream& ostr): - _pending(-1), - _lineLength(0), - _ostr(ostr) -{ -} - - -QuotedPrintableEncoderBuf::~QuotedPrintableEncoderBuf() -{ - try - { - close(); - } - catch (...) - { - } -} - - -int QuotedPrintableEncoderBuf::writeToDevice(char c) -{ - if (_pending != -1) - { - if (_pending == '\r' && c == '\n') - writeRaw((char) _pending); - else if (c == '\r' || c == '\n') - writeEncoded((char) _pending); - else - writeRaw((char) _pending); - _pending = -1; - } - if (c == '\t' || c == ' ') - { - _pending = charToInt(c); - return _pending; - } - else if (c == '\r' || c == '\n' || (c > 32 && c < 127 && c != '=')) - { - writeRaw(c); - } - else - { - writeEncoded(c); - } - return charToInt(c); -} - - -void QuotedPrintableEncoderBuf::writeEncoded(char c) -{ - if (_lineLength >= 73) - { - _ostr << "=\r\n"; - _lineLength = 3; - } - else _lineLength += 3; - _ostr << '=' << NumberFormatter::formatHex((unsigned) charToInt(c), 2); -} - - -void QuotedPrintableEncoderBuf::writeRaw(char c) -{ - if (c == '\r' || c == '\n') - { - _ostr.put(c); - _lineLength = 0; - } - else if (_lineLength < 75) - { - _ostr.put(c); - ++_lineLength; - } - else - { - _ostr << "=\r\n" << c; - _lineLength = 1; - } -} - - -int QuotedPrintableEncoderBuf::close() -{ - sync(); - return _ostr ? 0 : -1; -} - - -QuotedPrintableEncoderIOS::QuotedPrintableEncoderIOS(std::ostream& ostr): _buf(ostr) -{ - poco_ios_init(&_buf); -} - - -QuotedPrintableEncoderIOS::~QuotedPrintableEncoderIOS() -{ -} - - -int QuotedPrintableEncoderIOS::close() -{ - return _buf.close(); -} - - -QuotedPrintableEncoderBuf* QuotedPrintableEncoderIOS::rdbuf() -{ - return &_buf; -} - - -QuotedPrintableEncoder::QuotedPrintableEncoder(std::ostream& ostr): - QuotedPrintableEncoderIOS(ostr), - std::ostream(&_buf) -{ -} - - -QuotedPrintableEncoder::~QuotedPrintableEncoder() -{ -} - - -} } // namespace Poco::Net +// +// QuotedPrintableEncoder.cpp +// +// Library: Net +// Package: Messages +// Module: QuotedPrintableEncoder +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/QuotedPrintableEncoder.h" +#include "Poco/NumberFormatter.h" + + +using Poco::UnbufferedStreamBuf; +using Poco::NumberFormatter; + + +namespace Poco { +namespace Net { + + +QuotedPrintableEncoderBuf::QuotedPrintableEncoderBuf(std::ostream& ostr): + _pending(-1), + _lineLength(0), + _ostr(ostr) +{ +} + + +QuotedPrintableEncoderBuf::~QuotedPrintableEncoderBuf() +{ + try + { + close(); + } + catch (...) + { + } +} + + +int QuotedPrintableEncoderBuf::writeToDevice(char c) +{ + if (_pending != -1) + { + if (_pending == '\r' && c == '\n') + writeRaw((char) _pending); + else if (c == '\r' || c == '\n') + writeEncoded((char) _pending); + else + writeRaw((char) _pending); + _pending = -1; + } + if (c == '\t' || c == ' ') + { + _pending = charToInt(c); + return _pending; + } + else if (c == '\r' || c == '\n' || (c > 32 && c < 127 && c != '=')) + { + writeRaw(c); + } + else + { + writeEncoded(c); + } + return charToInt(c); +} + + +void QuotedPrintableEncoderBuf::writeEncoded(char c) +{ + if (_lineLength >= 73) + { + _ostr << "=\r\n"; + _lineLength = 3; + } + else _lineLength += 3; + _ostr << '=' << NumberFormatter::formatHex((unsigned) charToInt(c), 2); +} + + +void QuotedPrintableEncoderBuf::writeRaw(char c) +{ + if (c == '\r' || c == '\n') + { + _ostr.put(c); + _lineLength = 0; + } + else if (_lineLength < 75) + { + _ostr.put(c); + ++_lineLength; + } + else + { + _ostr << "=\r\n" << c; + _lineLength = 1; + } +} + + +int QuotedPrintableEncoderBuf::close() +{ + sync(); + return _ostr ? 0 : -1; +} + + +QuotedPrintableEncoderIOS::QuotedPrintableEncoderIOS(std::ostream& ostr): _buf(ostr) +{ + poco_ios_init(&_buf); +} + + +QuotedPrintableEncoderIOS::~QuotedPrintableEncoderIOS() +{ +} + + +int QuotedPrintableEncoderIOS::close() +{ + return _buf.close(); +} + + +QuotedPrintableEncoderBuf* QuotedPrintableEncoderIOS::rdbuf() +{ + return &_buf; +} + + +QuotedPrintableEncoder::QuotedPrintableEncoder(std::ostream& ostr): + QuotedPrintableEncoderIOS(ostr), + std::ostream(&_buf) +{ +} + + +QuotedPrintableEncoder::~QuotedPrintableEncoder() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/RawSocket.cpp b/contrib/libs/poco/Net/src/RawSocket.cpp index 7605dcac39..4cd1602ce2 100644 --- a/contrib/libs/poco/Net/src/RawSocket.cpp +++ b/contrib/libs/poco/Net/src/RawSocket.cpp @@ -1,117 +1,117 @@ -// -// RawSocket.cpp -// -// Library: Net -// Package: Sockets -// Module: RawSocket -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/RawSocket.h" -#include "Poco/Net/RawSocketImpl.h" -#include "Poco/Exception.h" - - -using Poco::InvalidArgumentException; - - -namespace Poco { -namespace Net { - - -RawSocket::RawSocket(): - Socket(new RawSocketImpl) -{ -} - - -RawSocket::RawSocket(SocketAddress::Family family, int proto): - Socket(new RawSocketImpl(family, proto)) -{ -} - - -RawSocket::RawSocket(const SocketAddress& address, bool reuseAddress): - Socket(new RawSocketImpl(address.family())) -{ - bind(address, reuseAddress); -} - - -RawSocket::RawSocket(const Socket& socket): Socket(socket) -{ - if (!dynamic_cast<RawSocketImpl*>(impl())) - throw InvalidArgumentException("Cannot assign incompatible socket"); -} - - -RawSocket::RawSocket(SocketImpl* pImpl): Socket(pImpl) -{ - if (!dynamic_cast<RawSocketImpl*>(impl())) - throw InvalidArgumentException("Cannot assign incompatible socket"); -} - - -RawSocket::~RawSocket() -{ -} - - -RawSocket& RawSocket::operator = (const Socket& socket) -{ - if (dynamic_cast<RawSocketImpl*>(socket.impl())) - Socket::operator = (socket); - else - throw InvalidArgumentException("Cannot assign incompatible socket"); - return *this; -} - - -void RawSocket::connect(const SocketAddress& address) -{ - impl()->connect(address); -} - - -void RawSocket::bind(const SocketAddress& address, bool reuseAddress) -{ - impl()->bind(address, reuseAddress); -} - - -void RawSocket::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) -{ - impl()->bind(address, reuseAddress, reusePort); -} - - -int RawSocket::sendBytes(const void* buffer, int length, int flags) -{ - return impl()->sendBytes(buffer, length, flags); -} - - -int RawSocket::receiveBytes(void* buffer, int length, int flags) -{ - return impl()->receiveBytes(buffer, length, flags); -} - - -int RawSocket::sendTo(const void* buffer, int length, const SocketAddress& address, int flags) -{ - return impl()->sendTo(buffer, length, address, flags); -} - - -int RawSocket::receiveFrom(void* buffer, int length, SocketAddress& address, int flags) -{ - return impl()->receiveFrom(buffer, length, address, flags); -} - - -} } // namespace Poco::Net +// +// RawSocket.cpp +// +// Library: Net +// Package: Sockets +// Module: RawSocket +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/RawSocket.h" +#include "Poco/Net/RawSocketImpl.h" +#include "Poco/Exception.h" + + +using Poco::InvalidArgumentException; + + +namespace Poco { +namespace Net { + + +RawSocket::RawSocket(): + Socket(new RawSocketImpl) +{ +} + + +RawSocket::RawSocket(SocketAddress::Family family, int proto): + Socket(new RawSocketImpl(family, proto)) +{ +} + + +RawSocket::RawSocket(const SocketAddress& address, bool reuseAddress): + Socket(new RawSocketImpl(address.family())) +{ + bind(address, reuseAddress); +} + + +RawSocket::RawSocket(const Socket& socket): Socket(socket) +{ + if (!dynamic_cast<RawSocketImpl*>(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +RawSocket::RawSocket(SocketImpl* pImpl): Socket(pImpl) +{ + if (!dynamic_cast<RawSocketImpl*>(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +RawSocket::~RawSocket() +{ +} + + +RawSocket& RawSocket::operator = (const Socket& socket) +{ + if (dynamic_cast<RawSocketImpl*>(socket.impl())) + Socket::operator = (socket); + else + throw InvalidArgumentException("Cannot assign incompatible socket"); + return *this; +} + + +void RawSocket::connect(const SocketAddress& address) +{ + impl()->connect(address); +} + + +void RawSocket::bind(const SocketAddress& address, bool reuseAddress) +{ + impl()->bind(address, reuseAddress); +} + + +void RawSocket::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) +{ + impl()->bind(address, reuseAddress, reusePort); +} + + +int RawSocket::sendBytes(const void* buffer, int length, int flags) +{ + return impl()->sendBytes(buffer, length, flags); +} + + +int RawSocket::receiveBytes(void* buffer, int length, int flags) +{ + return impl()->receiveBytes(buffer, length, flags); +} + + +int RawSocket::sendTo(const void* buffer, int length, const SocketAddress& address, int flags) +{ + return impl()->sendTo(buffer, length, address, flags); +} + + +int RawSocket::receiveFrom(void* buffer, int length, SocketAddress& address, int flags) +{ + return impl()->receiveFrom(buffer, length, address, flags); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/RawSocketImpl.cpp b/contrib/libs/poco/Net/src/RawSocketImpl.cpp index c7fb248ef7..73dc78818f 100644 --- a/contrib/libs/poco/Net/src/RawSocketImpl.cpp +++ b/contrib/libs/poco/Net/src/RawSocketImpl.cpp @@ -1,69 +1,69 @@ -// -// RawSocketImpl.cpp -// -// Library: Net -// Package: Sockets -// Module: RawSocketImpl -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/RawSocketImpl.h" -#include "Poco/Net/NetException.h" - - -using Poco::InvalidArgumentException; - - -namespace Poco { -namespace Net { - - -RawSocketImpl::RawSocketImpl() -{ - init(AF_INET); -} - - -RawSocketImpl::RawSocketImpl(SocketAddress::Family family, int proto) -{ - if (family == SocketAddress::IPv4) - init2(AF_INET, proto); -#if defined(POCO_HAVE_IPv6) - else if (family == SocketAddress::IPv6) - init2(AF_INET6, proto); -#endif - else throw InvalidArgumentException("Invalid or unsupported address family passed to RawSocketImpl"); - -} - - -RawSocketImpl::RawSocketImpl(poco_socket_t sockfd): - SocketImpl(sockfd) -{ -} - - -RawSocketImpl::~RawSocketImpl() -{ -} - - -void RawSocketImpl::init(int af) -{ - init2(af, IPPROTO_RAW); -} - - -void RawSocketImpl::init2(int af, int proto) -{ - initSocket(af, SOCK_RAW, proto); - setOption(IPPROTO_IP, IP_HDRINCL, 0); -} - - -} } // namespace Poco::Net +// +// RawSocketImpl.cpp +// +// Library: Net +// Package: Sockets +// Module: RawSocketImpl +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/RawSocketImpl.h" +#include "Poco/Net/NetException.h" + + +using Poco::InvalidArgumentException; + + +namespace Poco { +namespace Net { + + +RawSocketImpl::RawSocketImpl() +{ + init(AF_INET); +} + + +RawSocketImpl::RawSocketImpl(SocketAddress::Family family, int proto) +{ + if (family == SocketAddress::IPv4) + init2(AF_INET, proto); +#if defined(POCO_HAVE_IPv6) + else if (family == SocketAddress::IPv6) + init2(AF_INET6, proto); +#endif + else throw InvalidArgumentException("Invalid or unsupported address family passed to RawSocketImpl"); + +} + + +RawSocketImpl::RawSocketImpl(poco_socket_t sockfd): + SocketImpl(sockfd) +{ +} + + +RawSocketImpl::~RawSocketImpl() +{ +} + + +void RawSocketImpl::init(int af) +{ + init2(af, IPPROTO_RAW); +} + + +void RawSocketImpl::init2(int af, int proto) +{ + initSocket(af, SOCK_RAW, proto); + setOption(IPPROTO_IP, IP_HDRINCL, 0); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/RemoteSyslogChannel.cpp b/contrib/libs/poco/Net/src/RemoteSyslogChannel.cpp index 8ad6d5b2d0..3337e786df 100644 --- a/contrib/libs/poco/Net/src/RemoteSyslogChannel.cpp +++ b/contrib/libs/poco/Net/src/RemoteSyslogChannel.cpp @@ -1,356 +1,356 @@ -// -// RemoteSyslogChannel.cpp -// -// Library: Net -// Package: Logging -// Module: RemoteSyslogChannel -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/RemoteSyslogChannel.h" -#include "Poco/Message.h" -#include "Poco/DateTimeFormatter.h" -#include "Poco/NumberFormatter.h" -#include "Poco/Net/SocketAddress.h" -#include "Poco/Net/DNS.h" -#include "Poco/LoggingFactory.h" -#include "Poco/Instantiator.h" -#include "Poco/String.h" - - -namespace Poco { -namespace Net { - - -const std::string RemoteSyslogChannel::BSD_TIMEFORMAT("%b %f %H:%M:%S"); -const std::string RemoteSyslogChannel::SYSLOG_TIMEFORMAT("%Y-%m-%dT%H:%M:%S.%i%z"); -const std::string RemoteSyslogChannel::PROP_NAME("name"); -const std::string RemoteSyslogChannel::PROP_FACILITY("facility"); -const std::string RemoteSyslogChannel::PROP_FORMAT("format"); -const std::string RemoteSyslogChannel::PROP_LOGHOST("loghost"); -const std::string RemoteSyslogChannel::PROP_HOST("host"); -const std::string RemoteSyslogChannel::STRUCTURED_DATA("structured-data"); - - -RemoteSyslogChannel::RemoteSyslogChannel(): - _logHost("localhost"), - _name("-"), - _facility(SYSLOG_USER), - _bsdFormat(false), - _open(false) -{ -} - - -RemoteSyslogChannel::RemoteSyslogChannel(const std::string& address, const std::string& name, int facility, bool bsdFormat): - _logHost(address), - _name(name), - _facility(facility), - _bsdFormat(bsdFormat), - _open(false) -{ - if (_name.empty()) _name = "-"; -} - - -RemoteSyslogChannel::~RemoteSyslogChannel() -{ - try - { - close(); - } - catch (...) - { - poco_unexpected(); - } -} - - -void RemoteSyslogChannel::open() -{ - if (_open) return; - - if (_logHost.find(':') != std::string::npos) - _socketAddress = SocketAddress(_logHost); - else - _socketAddress = SocketAddress(_logHost, SYSLOG_PORT); - - // reset socket for the case that it has been previously closed - _socket = DatagramSocket(_socketAddress.family()); - - if (_host.empty()) - { - try - { - _host = DNS::thisHost().name(); - } - catch (Poco::Exception&) - { - _host = _socket.address().host().toString(); - } - } - - _open = true; -} - - -void RemoteSyslogChannel::close() -{ - if (_open) - { - _socket.close(); - _open = false; - } -} - - -void RemoteSyslogChannel::log(const Message& msg) -{ - Poco::FastMutex::ScopedLock lock(_mutex); - - if (!_open) open(); - - std::string m; - m.reserve(1024); - m += '<'; - Poco::NumberFormatter::append(m, getPrio(msg) + _facility); - m += '>'; - if (_bsdFormat) - { - Poco::DateTimeFormatter::append(m, msg.getTime(), BSD_TIMEFORMAT); - m += ' '; - m += _host; - } - else - { - m += "1 "; // version - Poco::DateTimeFormatter::append(m, msg.getTime(), SYSLOG_TIMEFORMAT); - m += ' '; - m += _host; - m += ' '; - m += _name; - m += ' '; - Poco::NumberFormatter::append(m, msg.getPid()); - m += ' '; - m += msg.getSource(); - m += ' '; - if (msg.has(STRUCTURED_DATA)) - { - m += msg.get(STRUCTURED_DATA); - } - else - { - m += "-"; - } - } - m += ' '; - m += msg.getText(); - - _socket.sendTo(m.data(), static_cast<int>(m.size()), _socketAddress); -} - - -void RemoteSyslogChannel::setProperty(const std::string& name, const std::string& value) -{ - if (name == PROP_NAME) - { - _name = value; - if (_name.empty()) _name = "-"; - } - else if (name == PROP_FACILITY) - { - std::string facility; - if (Poco::icompare(value, 4, "LOG_") == 0) - facility = Poco::toUpper(value.substr(4)); - else if (Poco::icompare(value, 4, "SYSLOG_") == 0) - facility = Poco::toUpper(value.substr(7)); - else - facility = Poco::toUpper(value); - - if (facility == "KERN") - _facility = SYSLOG_KERN; - else if (facility == "USER") - _facility = SYSLOG_USER; - else if (facility == "MAIL") - _facility = SYSLOG_MAIL; - else if (facility == "DAEMON") - _facility = SYSLOG_DAEMON; - else if (facility == "AUTH") - _facility = SYSLOG_AUTH; - else if (facility == "AUTHPRIV") - _facility = SYSLOG_AUTHPRIV; - else if (facility == "SYSLOG") - _facility = SYSLOG_SYSLOG; - else if (facility == "LPR") - _facility = SYSLOG_LPR; - else if (facility == "NEWS") - _facility = SYSLOG_NEWS; - else if (facility == "UUCP") - _facility = SYSLOG_UUCP; - else if (facility == "CRON") - _facility = SYSLOG_CRON; - else if (facility == "FTP") - _facility = SYSLOG_FTP; - else if (facility == "NTP") - _facility = SYSLOG_NTP; - else if (facility == "LOGAUDIT") - _facility = SYSLOG_LOGAUDIT; - else if (facility == "LOGALERT") - _facility = SYSLOG_LOGALERT; - else if (facility == "CLOCK") - _facility = SYSLOG_CLOCK; - else if (facility == "LOCAL0") - _facility = SYSLOG_LOCAL0; - else if (facility == "LOCAL1") - _facility = SYSLOG_LOCAL1; - else if (facility == "LOCAL2") - _facility = SYSLOG_LOCAL2; - else if (facility == "LOCAL3") - _facility = SYSLOG_LOCAL3; - else if (facility == "LOCAL4") - _facility = SYSLOG_LOCAL4; - else if (facility == "LOCAL5") - _facility = SYSLOG_LOCAL5; - else if (facility == "LOCAL6") - _facility = SYSLOG_LOCAL6; - else if (facility == "LOCAL7") - _facility = SYSLOG_LOCAL7; - } - else if (name == PROP_LOGHOST) - { - _logHost = value; - } - else if (name == PROP_HOST) - { - _host = value; - } - else if (name == PROP_FORMAT) - { - _bsdFormat = (value == "bsd" || value == "rfc3164"); - } - else - { - Channel::setProperty(name, value); - } -} - - -std::string RemoteSyslogChannel::getProperty(const std::string& name) const -{ - if (name == PROP_NAME) - { - if (_name != "-") - return _name; - else - return ""; - } - else if (name == PROP_FACILITY) - { - if (_facility == SYSLOG_KERN) - return "KERN"; - else if (_facility == SYSLOG_USER) - return "USER"; - else if (_facility == SYSLOG_MAIL) - return "MAIL"; - else if (_facility == SYSLOG_DAEMON) - return "DAEMON"; - else if (_facility == SYSLOG_AUTH) - return "AUTH"; - else if (_facility == SYSLOG_AUTHPRIV) - return "AUTHPRIV"; - else if (_facility == SYSLOG_SYSLOG) - return "SYSLOG"; - else if (_facility == SYSLOG_LPR) - return "LPR"; - else if (_facility == SYSLOG_NEWS) - return "NEWS"; - else if (_facility == SYSLOG_UUCP) - return "UUCP"; - else if (_facility == SYSLOG_CRON) - return "CRON"; - else if (_facility == SYSLOG_FTP) - return "FTP"; - else if (_facility == SYSLOG_NTP) - return "NTP"; - else if (_facility == SYSLOG_LOGAUDIT) - return "LOGAUDIT"; - else if (_facility == SYSLOG_LOGALERT) - return "LOGALERT"; - else if (_facility == SYSLOG_CLOCK) - return "CLOCK"; - else if (_facility == SYSLOG_LOCAL0) - return "LOCAL0"; - else if (_facility == SYSLOG_LOCAL1) - return "LOCAL1"; - else if (_facility == SYSLOG_LOCAL2) - return "LOCAL2"; - else if (_facility == SYSLOG_LOCAL3) - return "LOCAL3"; - else if (_facility == SYSLOG_LOCAL4) - return "LOCAL4"; - else if (_facility == SYSLOG_LOCAL5) - return "LOCAL5"; - else if (_facility == SYSLOG_LOCAL6) - return "LOCAL6"; - else if (_facility == SYSLOG_LOCAL7) - return "LOCAL7"; - else - return ""; - } - else if (name == PROP_LOGHOST) - { - return _logHost; - } - else if (name == PROP_HOST) - { - return _host; - } - else if (name == PROP_FORMAT) - { - return _bsdFormat ? "rfc3164" : "rfc5424"; - } - else - { - return Channel::getProperty(name); - } -} - - -int RemoteSyslogChannel::getPrio(const Message& msg) -{ - switch (msg.getPriority()) - { +// +// RemoteSyslogChannel.cpp +// +// Library: Net +// Package: Logging +// Module: RemoteSyslogChannel +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/RemoteSyslogChannel.h" +#include "Poco/Message.h" +#include "Poco/DateTimeFormatter.h" +#include "Poco/NumberFormatter.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/Net/DNS.h" +#include "Poco/LoggingFactory.h" +#include "Poco/Instantiator.h" +#include "Poco/String.h" + + +namespace Poco { +namespace Net { + + +const std::string RemoteSyslogChannel::BSD_TIMEFORMAT("%b %f %H:%M:%S"); +const std::string RemoteSyslogChannel::SYSLOG_TIMEFORMAT("%Y-%m-%dT%H:%M:%S.%i%z"); +const std::string RemoteSyslogChannel::PROP_NAME("name"); +const std::string RemoteSyslogChannel::PROP_FACILITY("facility"); +const std::string RemoteSyslogChannel::PROP_FORMAT("format"); +const std::string RemoteSyslogChannel::PROP_LOGHOST("loghost"); +const std::string RemoteSyslogChannel::PROP_HOST("host"); +const std::string RemoteSyslogChannel::STRUCTURED_DATA("structured-data"); + + +RemoteSyslogChannel::RemoteSyslogChannel(): + _logHost("localhost"), + _name("-"), + _facility(SYSLOG_USER), + _bsdFormat(false), + _open(false) +{ +} + + +RemoteSyslogChannel::RemoteSyslogChannel(const std::string& address, const std::string& name, int facility, bool bsdFormat): + _logHost(address), + _name(name), + _facility(facility), + _bsdFormat(bsdFormat), + _open(false) +{ + if (_name.empty()) _name = "-"; +} + + +RemoteSyslogChannel::~RemoteSyslogChannel() +{ + try + { + close(); + } + catch (...) + { + poco_unexpected(); + } +} + + +void RemoteSyslogChannel::open() +{ + if (_open) return; + + if (_logHost.find(':') != std::string::npos) + _socketAddress = SocketAddress(_logHost); + else + _socketAddress = SocketAddress(_logHost, SYSLOG_PORT); + + // reset socket for the case that it has been previously closed + _socket = DatagramSocket(_socketAddress.family()); + + if (_host.empty()) + { + try + { + _host = DNS::thisHost().name(); + } + catch (Poco::Exception&) + { + _host = _socket.address().host().toString(); + } + } + + _open = true; +} + + +void RemoteSyslogChannel::close() +{ + if (_open) + { + _socket.close(); + _open = false; + } +} + + +void RemoteSyslogChannel::log(const Message& msg) +{ + Poco::FastMutex::ScopedLock lock(_mutex); + + if (!_open) open(); + + std::string m; + m.reserve(1024); + m += '<'; + Poco::NumberFormatter::append(m, getPrio(msg) + _facility); + m += '>'; + if (_bsdFormat) + { + Poco::DateTimeFormatter::append(m, msg.getTime(), BSD_TIMEFORMAT); + m += ' '; + m += _host; + } + else + { + m += "1 "; // version + Poco::DateTimeFormatter::append(m, msg.getTime(), SYSLOG_TIMEFORMAT); + m += ' '; + m += _host; + m += ' '; + m += _name; + m += ' '; + Poco::NumberFormatter::append(m, msg.getPid()); + m += ' '; + m += msg.getSource(); + m += ' '; + if (msg.has(STRUCTURED_DATA)) + { + m += msg.get(STRUCTURED_DATA); + } + else + { + m += "-"; + } + } + m += ' '; + m += msg.getText(); + + _socket.sendTo(m.data(), static_cast<int>(m.size()), _socketAddress); +} + + +void RemoteSyslogChannel::setProperty(const std::string& name, const std::string& value) +{ + if (name == PROP_NAME) + { + _name = value; + if (_name.empty()) _name = "-"; + } + else if (name == PROP_FACILITY) + { + std::string facility; + if (Poco::icompare(value, 4, "LOG_") == 0) + facility = Poco::toUpper(value.substr(4)); + else if (Poco::icompare(value, 4, "SYSLOG_") == 0) + facility = Poco::toUpper(value.substr(7)); + else + facility = Poco::toUpper(value); + + if (facility == "KERN") + _facility = SYSLOG_KERN; + else if (facility == "USER") + _facility = SYSLOG_USER; + else if (facility == "MAIL") + _facility = SYSLOG_MAIL; + else if (facility == "DAEMON") + _facility = SYSLOG_DAEMON; + else if (facility == "AUTH") + _facility = SYSLOG_AUTH; + else if (facility == "AUTHPRIV") + _facility = SYSLOG_AUTHPRIV; + else if (facility == "SYSLOG") + _facility = SYSLOG_SYSLOG; + else if (facility == "LPR") + _facility = SYSLOG_LPR; + else if (facility == "NEWS") + _facility = SYSLOG_NEWS; + else if (facility == "UUCP") + _facility = SYSLOG_UUCP; + else if (facility == "CRON") + _facility = SYSLOG_CRON; + else if (facility == "FTP") + _facility = SYSLOG_FTP; + else if (facility == "NTP") + _facility = SYSLOG_NTP; + else if (facility == "LOGAUDIT") + _facility = SYSLOG_LOGAUDIT; + else if (facility == "LOGALERT") + _facility = SYSLOG_LOGALERT; + else if (facility == "CLOCK") + _facility = SYSLOG_CLOCK; + else if (facility == "LOCAL0") + _facility = SYSLOG_LOCAL0; + else if (facility == "LOCAL1") + _facility = SYSLOG_LOCAL1; + else if (facility == "LOCAL2") + _facility = SYSLOG_LOCAL2; + else if (facility == "LOCAL3") + _facility = SYSLOG_LOCAL3; + else if (facility == "LOCAL4") + _facility = SYSLOG_LOCAL4; + else if (facility == "LOCAL5") + _facility = SYSLOG_LOCAL5; + else if (facility == "LOCAL6") + _facility = SYSLOG_LOCAL6; + else if (facility == "LOCAL7") + _facility = SYSLOG_LOCAL7; + } + else if (name == PROP_LOGHOST) + { + _logHost = value; + } + else if (name == PROP_HOST) + { + _host = value; + } + else if (name == PROP_FORMAT) + { + _bsdFormat = (value == "bsd" || value == "rfc3164"); + } + else + { + Channel::setProperty(name, value); + } +} + + +std::string RemoteSyslogChannel::getProperty(const std::string& name) const +{ + if (name == PROP_NAME) + { + if (_name != "-") + return _name; + else + return ""; + } + else if (name == PROP_FACILITY) + { + if (_facility == SYSLOG_KERN) + return "KERN"; + else if (_facility == SYSLOG_USER) + return "USER"; + else if (_facility == SYSLOG_MAIL) + return "MAIL"; + else if (_facility == SYSLOG_DAEMON) + return "DAEMON"; + else if (_facility == SYSLOG_AUTH) + return "AUTH"; + else if (_facility == SYSLOG_AUTHPRIV) + return "AUTHPRIV"; + else if (_facility == SYSLOG_SYSLOG) + return "SYSLOG"; + else if (_facility == SYSLOG_LPR) + return "LPR"; + else if (_facility == SYSLOG_NEWS) + return "NEWS"; + else if (_facility == SYSLOG_UUCP) + return "UUCP"; + else if (_facility == SYSLOG_CRON) + return "CRON"; + else if (_facility == SYSLOG_FTP) + return "FTP"; + else if (_facility == SYSLOG_NTP) + return "NTP"; + else if (_facility == SYSLOG_LOGAUDIT) + return "LOGAUDIT"; + else if (_facility == SYSLOG_LOGALERT) + return "LOGALERT"; + else if (_facility == SYSLOG_CLOCK) + return "CLOCK"; + else if (_facility == SYSLOG_LOCAL0) + return "LOCAL0"; + else if (_facility == SYSLOG_LOCAL1) + return "LOCAL1"; + else if (_facility == SYSLOG_LOCAL2) + return "LOCAL2"; + else if (_facility == SYSLOG_LOCAL3) + return "LOCAL3"; + else if (_facility == SYSLOG_LOCAL4) + return "LOCAL4"; + else if (_facility == SYSLOG_LOCAL5) + return "LOCAL5"; + else if (_facility == SYSLOG_LOCAL6) + return "LOCAL6"; + else if (_facility == SYSLOG_LOCAL7) + return "LOCAL7"; + else + return ""; + } + else if (name == PROP_LOGHOST) + { + return _logHost; + } + else if (name == PROP_HOST) + { + return _host; + } + else if (name == PROP_FORMAT) + { + return _bsdFormat ? "rfc3164" : "rfc5424"; + } + else + { + return Channel::getProperty(name); + } +} + + +int RemoteSyslogChannel::getPrio(const Message& msg) +{ + switch (msg.getPriority()) + { case Message::PRIO_TEST: - case Message::PRIO_TRACE: - case Message::PRIO_DEBUG: - return SYSLOG_DEBUG; - case Message::PRIO_INFORMATION: - return SYSLOG_INFORMATIONAL; - case Message::PRIO_NOTICE: - return SYSLOG_NOTICE; - case Message::PRIO_WARNING: - return SYSLOG_WARNING; - case Message::PRIO_ERROR: - return SYSLOG_ERROR; - case Message::PRIO_CRITICAL: - return SYSLOG_CRITICAL; - case Message::PRIO_FATAL: - return SYSLOG_ALERT; - default: - return 0; - } -} - - -void RemoteSyslogChannel::registerChannel() -{ - Poco::LoggingFactory::defaultFactory().registerChannelClass("RemoteSyslogChannel", new Poco::Instantiator<RemoteSyslogChannel, Poco::Channel>); -} - - -} } // namespace Poco::Net + case Message::PRIO_TRACE: + case Message::PRIO_DEBUG: + return SYSLOG_DEBUG; + case Message::PRIO_INFORMATION: + return SYSLOG_INFORMATIONAL; + case Message::PRIO_NOTICE: + return SYSLOG_NOTICE; + case Message::PRIO_WARNING: + return SYSLOG_WARNING; + case Message::PRIO_ERROR: + return SYSLOG_ERROR; + case Message::PRIO_CRITICAL: + return SYSLOG_CRITICAL; + case Message::PRIO_FATAL: + return SYSLOG_ALERT; + default: + return 0; + } +} + + +void RemoteSyslogChannel::registerChannel() +{ + Poco::LoggingFactory::defaultFactory().registerChannelClass("RemoteSyslogChannel", new Poco::Instantiator<RemoteSyslogChannel, Poco::Channel>); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/RemoteSyslogListener.cpp b/contrib/libs/poco/Net/src/RemoteSyslogListener.cpp index c33a4e49da..ac17391324 100644 --- a/contrib/libs/poco/Net/src/RemoteSyslogListener.cpp +++ b/contrib/libs/poco/Net/src/RemoteSyslogListener.cpp @@ -1,630 +1,630 @@ -// -// RemoteSyslogListener.cpp -// -// Library: Net -// Package: Logging -// Module: RemoteSyslogListener -// -// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/RemoteSyslogListener.h" -#include "Poco/Net/RemoteSyslogChannel.h" -#include "Poco/Net/DatagramSocket.h" -#include "Poco/Net/SocketAddress.h" -#include "Poco/Runnable.h" -#include "Poco/Notification.h" -#include "Poco/AutoPtr.h" -#include "Poco/NumberParser.h" -#include "Poco/NumberFormatter.h" -#include "Poco/DateTimeParser.h" -#include "Poco/Message.h" -#include "Poco/LoggingFactory.h" -#include "Poco/Buffer.h" -#include "Poco/Ascii.h" -#include <cstddef> - - -namespace Poco { -namespace Net { - - -// -// MessageNotification -// - - -class MessageNotification: public Poco::Notification -{ -public: - MessageNotification(const char* buffer, std::size_t length, const Poco::Net::SocketAddress& sourceAddress): - _message(buffer, length), - _sourceAddress(sourceAddress) - { - } - - MessageNotification(const std::string& message, const Poco::Net::SocketAddress& sourceAddress): - _message(message), - _sourceAddress(sourceAddress) - { - } - - ~MessageNotification() - { - } - - const std::string& message() const - { - return _message; - } - - const Poco::Net::SocketAddress& sourceAddress() const - { - return _sourceAddress; - } - -private: - std::string _message; - Poco::Net::SocketAddress _sourceAddress; -}; - - -// -// RemoteUDPListener -// - - -class RemoteUDPListener: public Poco::Runnable -{ -public: - enum - { - WAITTIME_MILLISEC = 1000, - BUFFER_SIZE = 65536 - }; - - RemoteUDPListener(Poco::NotificationQueue& queue, Poco::UInt16 port); - ~RemoteUDPListener(); - - void run(); - void safeStop(); - -private: - Poco::NotificationQueue& _queue; - DatagramSocket _socket; - bool _stopped; -}; - - -RemoteUDPListener::RemoteUDPListener(Poco::NotificationQueue& queue, Poco::UInt16 port): - _queue(queue), - _socket(Poco::Net::SocketAddress(Poco::Net::IPAddress(), port)), - _stopped(false) -{ -} - - -RemoteUDPListener::~RemoteUDPListener() -{ -} - - -void RemoteUDPListener::run() -{ - Poco::Buffer<char> buffer(BUFFER_SIZE); - Poco::Timespan waitTime(WAITTIME_MILLISEC* 1000); - while (!_stopped) - { - try - { - if (_socket.poll(waitTime, Socket::SELECT_READ)) - { - Poco::Net::SocketAddress sourceAddress; - int n = _socket.receiveFrom(buffer.begin(), BUFFER_SIZE, sourceAddress); - if (n > 0) - { - _queue.enqueueNotification(new MessageNotification(buffer.begin(), n, sourceAddress)); - } - } - } - catch (...) - { - // lazy exception catching - } - } -} - - -void RemoteUDPListener::safeStop() -{ - _stopped = true; -} - - -// -// SyslogParser -// - - -class SyslogParser: public Poco::Runnable -{ -public: - static const std::string NILVALUE; - - enum - { - WAITTIME_MILLISEC = 1000 - }; - - SyslogParser(Poco::NotificationQueue& queue, RemoteSyslogListener* pListener); - ~SyslogParser(); - - void parse(const std::string& line, Poco::Message& message); - void run(); - void safeStop(); - - static Poco::Message::Priority convert(RemoteSyslogChannel::Severity severity); - -private: - void parsePrio(const std::string& line, std::size_t& pos, RemoteSyslogChannel::Severity& severity, RemoteSyslogChannel::Facility& fac); - void parseNew(const std::string& line, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos, Poco::Message& message); - void parseBSD(const std::string& line, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos, Poco::Message& message); - - static std::string parseUntilSpace(const std::string& line, std::size_t& pos); - /// Parses until it encounters the next space char, returns the string from pos, excluding space - /// pos will point past the space char - - static std::string parseStructuredData(const std::string& line, std::size_t& pos); - /// Parses the structured data field. - - static std::string parseStructuredDataToken(const std::string& line, std::size_t& pos); - /// Parses a token from the structured data field. - -private: - Poco::NotificationQueue& _queue; - bool _stopped; - RemoteSyslogListener* _pListener; -}; - - -const std::string SyslogParser::NILVALUE("-"); - - -SyslogParser::SyslogParser(Poco::NotificationQueue& queue, RemoteSyslogListener* pListener): - _queue(queue), - _stopped(false), - _pListener(pListener) -{ - poco_check_ptr (_pListener); -} - - -SyslogParser::~SyslogParser() -{ -} - - -void SyslogParser::run() -{ - while (!_stopped) - { - try - { - Poco::AutoPtr<Poco::Notification> pNf(_queue.waitDequeueNotification(WAITTIME_MILLISEC)); - if (pNf) - { - Poco::AutoPtr<MessageNotification> pMsgNf = pNf.cast<MessageNotification>(); - Poco::Message message; - parse(pMsgNf->message(), message); - message["addr"] =pMsgNf->sourceAddress().host().toString(); - _pListener->log(message); - } - } - catch (Poco::Exception&) - { - // parsing exception, what should we do? - } - catch (...) - { - } - } -} - - -void SyslogParser::safeStop() -{ - _stopped = true; -} - - -void SyslogParser::parse(const std::string& line, Poco::Message& message) -{ - // <int> -> int: lower 3 bits severity, upper bits: facility - std::size_t pos = 0; - RemoteSyslogChannel::Severity severity; - RemoteSyslogChannel::Facility fac; - parsePrio(line, pos, severity, fac); - - // the next field decide if we parse an old BSD message or a new syslog message - // BSD: expects a month value in string form: Jan, Feb... - // SYSLOG expects a version number: 1 - - if (Poco::Ascii::isDigit(line[pos])) - { - parseNew(line, severity, fac, pos, message); - } - else - { - parseBSD(line, severity, fac, pos, message); - } - poco_assert (pos == line.size()); -} - - -void SyslogParser::parsePrio(const std::string& line, std::size_t& pos, RemoteSyslogChannel::Severity& severity, RemoteSyslogChannel::Facility& fac) -{ - poco_assert (pos < line.size()); - poco_assert (line[pos] == '<'); - ++pos; - std::size_t start = pos; - - while (pos < line.size() && Poco::Ascii::isDigit(line[pos])) - ++pos; - - poco_assert (line[pos] == '>'); - poco_assert (pos - start > 0); - std::string valStr = line.substr(start, pos - start); - ++pos; // skip the > - - int val = Poco::NumberParser::parse(valStr); - poco_assert (val >= 0 && val <= (RemoteSyslogChannel::SYSLOG_LOCAL7 + RemoteSyslogChannel::SYSLOG_DEBUG)); - - Poco::UInt16 pri = static_cast<Poco::UInt16>(val); - // now get the lowest 3 bits - severity = static_cast<RemoteSyslogChannel::Severity>(pri & 0x0007u); - fac = static_cast<RemoteSyslogChannel::Facility>(pri & 0xfff8u); -} - - -void SyslogParser::parseNew(const std::string& line, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility /*fac*/, std::size_t& pos, Poco::Message& message) -{ - Poco::Message::Priority prio = convert(severity); - // rest of the unparsed header is: - // VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID - std::string versionStr(parseUntilSpace(line, pos)); - std::string timeStr(parseUntilSpace(line, pos)); // can be the nilvalue! - std::string hostName(parseUntilSpace(line, pos)); - std::string appName(parseUntilSpace(line, pos)); - std::string procId(parseUntilSpace(line, pos)); - std::string msgId(parseUntilSpace(line, pos)); - std::string sd(parseStructuredData(line, pos)); - std::string messageText(line.substr(pos)); - pos = line.size(); - Poco::DateTime date; - int tzd = 0; - bool hasDate = Poco::DateTimeParser::tryParse(RemoteSyslogChannel::SYSLOG_TIMEFORMAT, timeStr, date, tzd); - Poco::Message logEntry(msgId, messageText, prio); - logEntry[RemoteSyslogListener::LOG_PROP_HOST] = hostName; - logEntry[RemoteSyslogListener::LOG_PROP_APP] = appName; - logEntry[RemoteSyslogListener::LOG_PROP_STRUCTURED_DATA] = sd; - - if (hasDate) - logEntry.setTime(date.timestamp()); - int lval(0); - Poco::NumberParser::tryParse(procId, lval); - logEntry.setPid(lval); - message.swap(logEntry); -} - - -void SyslogParser::parseBSD(const std::string& line, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility /*fac*/, std::size_t& pos, Poco::Message& message) -{ - Poco::Message::Priority prio = convert(severity); - // rest of the unparsed header is: - // "%b %f %H:%M:%S" SP hostname|ipaddress - // detect three spaces - int spaceCnt = 0; - std::size_t start = pos; - while (spaceCnt < 3 && pos < line.size()) - { - if (line[pos] == ' ') - { - spaceCnt++; - if (spaceCnt == 1) - { - // size must be 3 chars for month - if (pos - start != 3) - { - // probably a shortened time value, or the hostname - // assume hostName - Poco::Message logEntry(line.substr(start, pos-start), line.substr(pos+1), prio); - message.swap(logEntry); - return; - } - } - else if (spaceCnt == 2) - { - // a day value! - if (!(Poco::Ascii::isDigit(line[pos-1]) && (Poco::Ascii::isDigit(line[pos-2]) || Poco::Ascii::isSpace(line[pos-2])))) - { - // assume the next field is a hostname - spaceCnt = 3; - } - } - if (pos + 1 < line.size() && line[pos+1] == ' ') - { - // we have two spaces when the day value is smaller than 10! - ++pos; // skip one - } - } - ++pos; - } - std::string timeStr(line.substr(start, pos-start-1)); - int tzd(0); - Poco::DateTime date; - int year = date.year(); // year is not included, use the current one - bool hasDate = Poco::DateTimeParser::tryParse(RemoteSyslogChannel::BSD_TIMEFORMAT, timeStr, date, tzd); - if (hasDate) - { - int m = date.month(); - int d = date.day(); - int h = date.hour(); - int min = date.minute(); - int sec = date.second(); - date = Poco::DateTime(year, m, d, h, min, sec); - } - // next entry is host SP - std::string hostName(parseUntilSpace(line, pos)); - - // TAG: at most 32 alphanumeric chars, ANY non alphannumeric indicates start of message content - // ignore: treat everything as content - std::string messageText(line.substr(pos)); - pos = line.size(); - Poco::Message logEntry(hostName, messageText, prio); - logEntry.setTime(date.timestamp()); - message.swap(logEntry); -} - - -std::string SyslogParser::parseUntilSpace(const std::string& line, std::size_t& pos) -{ - std::size_t start = pos; - while (pos < line.size() && !Poco::Ascii::isSpace(line[pos])) - ++pos; - // skip space - ++pos; - return line.substr(start, pos-start-1); -} - - -std::string SyslogParser::parseStructuredData(const std::string& line, std::size_t& pos) -{ - std::string sd; - if (pos < line.size()) - { - if (line[pos] == '-') - { - ++pos; - } - else if (line[pos] == '[') - { - std::string tok = parseStructuredDataToken(line, pos); - while (tok == "[") - { - sd += tok; - tok = parseStructuredDataToken(line, pos); - while (tok != "]" && !tok.empty()) - { - sd += tok; - tok = parseStructuredDataToken(line, pos); - } - sd += tok; - if (pos < line.size() && line[pos] == '[') tok = parseStructuredDataToken(line, pos); - } - } - if (pos < line.size() && Poco::Ascii::isSpace(line[pos])) ++pos; - } - return sd; -} - - -std::string SyslogParser::parseStructuredDataToken(const std::string& line, std::size_t& pos) -{ - std::string tok; - if (pos < line.size()) - { - if (Poco::Ascii::isSpace(line[pos]) || line[pos] == '=' || line[pos] == '[' || line[pos] == ']') - { - tok += line[pos++]; - } - else if (line[pos] == '"') - { - tok += line[pos++]; - while (pos < line.size() && line[pos] != '"') - { - tok += line[pos++]; - } - tok += '"'; - if (pos < line.size()) pos++; - } - else - { - while (pos < line.size() && !Poco::Ascii::isSpace(line[pos]) && line[pos] != '=') - { - tok += line[pos++]; - } - } - } - return tok; -} - -Poco::Message::Priority SyslogParser::convert(RemoteSyslogChannel::Severity severity) -{ - switch (severity) - { - case RemoteSyslogChannel::SYSLOG_EMERGENCY: - return Poco::Message::PRIO_FATAL; - case RemoteSyslogChannel::SYSLOG_ALERT: - return Poco::Message::PRIO_FATAL; - case RemoteSyslogChannel::SYSLOG_CRITICAL: - return Poco::Message::PRIO_CRITICAL; - case RemoteSyslogChannel::SYSLOG_ERROR: - return Poco::Message::PRIO_ERROR; - case RemoteSyslogChannel::SYSLOG_WARNING: - return Poco::Message::PRIO_WARNING; - case RemoteSyslogChannel::SYSLOG_NOTICE: - return Poco::Message::PRIO_NOTICE; - case RemoteSyslogChannel::SYSLOG_INFORMATIONAL: - return Poco::Message::PRIO_INFORMATION; - case RemoteSyslogChannel::SYSLOG_DEBUG: - return Poco::Message::PRIO_DEBUG; - } - throw Poco::LogicException("Illegal severity value in message"); -} - - -// -// RemoteSyslogListener -// - - -const std::string RemoteSyslogListener::PROP_PORT("port"); -const std::string RemoteSyslogListener::PROP_THREADS("threads"); - -const std::string RemoteSyslogListener::LOG_PROP_APP("app"); -const std::string RemoteSyslogListener::LOG_PROP_HOST("host"); -const std::string RemoteSyslogListener::LOG_PROP_STRUCTURED_DATA("structured-data"); - - -RemoteSyslogListener::RemoteSyslogListener(): - _pListener(0), - _pParser(0), - _port(RemoteSyslogChannel::SYSLOG_PORT), - _threads(1) -{ -} - - -RemoteSyslogListener::RemoteSyslogListener(Poco::UInt16 port): - _pListener(0), - _pParser(0), - _port(port), - _threads(1) -{ -} - - -RemoteSyslogListener::RemoteSyslogListener(Poco::UInt16 port, int threads): - _pListener(0), - _pParser(0), - _port(port), - _threads(threads) -{ -} - - -RemoteSyslogListener::~RemoteSyslogListener() -{ -} - - -void RemoteSyslogListener::processMessage(const std::string& messageText) -{ - Poco::Message message; - _pParser->parse(messageText, message); - log(message); -} - - -void RemoteSyslogListener::enqueueMessage(const std::string& messageText, const Poco::Net::SocketAddress& senderAddress) -{ - _queue.enqueueNotification(new MessageNotification(messageText, senderAddress)); -} - - -void RemoteSyslogListener::setProperty(const std::string& name, const std::string& value) -{ - if (name == PROP_PORT) - { - int val = Poco::NumberParser::parse(value); - if (val >= 0 && val < 65536) - _port = static_cast<Poco::UInt16>(val); - else - throw Poco::InvalidArgumentException("Not a valid port number", value); - } - else if (name == PROP_THREADS) - { - int val = Poco::NumberParser::parse(value); - if (val > 0 && val < 16) - _threads = val; - else - throw Poco::InvalidArgumentException("Invalid number of threads", value); - } +// +// RemoteSyslogListener.cpp +// +// Library: Net +// Package: Logging +// Module: RemoteSyslogListener +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/RemoteSyslogListener.h" +#include "Poco/Net/RemoteSyslogChannel.h" +#include "Poco/Net/DatagramSocket.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/Runnable.h" +#include "Poco/Notification.h" +#include "Poco/AutoPtr.h" +#include "Poco/NumberParser.h" +#include "Poco/NumberFormatter.h" +#include "Poco/DateTimeParser.h" +#include "Poco/Message.h" +#include "Poco/LoggingFactory.h" +#include "Poco/Buffer.h" +#include "Poco/Ascii.h" +#include <cstddef> + + +namespace Poco { +namespace Net { + + +// +// MessageNotification +// + + +class MessageNotification: public Poco::Notification +{ +public: + MessageNotification(const char* buffer, std::size_t length, const Poco::Net::SocketAddress& sourceAddress): + _message(buffer, length), + _sourceAddress(sourceAddress) + { + } + + MessageNotification(const std::string& message, const Poco::Net::SocketAddress& sourceAddress): + _message(message), + _sourceAddress(sourceAddress) + { + } + + ~MessageNotification() + { + } + + const std::string& message() const + { + return _message; + } + + const Poco::Net::SocketAddress& sourceAddress() const + { + return _sourceAddress; + } + +private: + std::string _message; + Poco::Net::SocketAddress _sourceAddress; +}; + + +// +// RemoteUDPListener +// + + +class RemoteUDPListener: public Poco::Runnable +{ +public: + enum + { + WAITTIME_MILLISEC = 1000, + BUFFER_SIZE = 65536 + }; + + RemoteUDPListener(Poco::NotificationQueue& queue, Poco::UInt16 port); + ~RemoteUDPListener(); + + void run(); + void safeStop(); + +private: + Poco::NotificationQueue& _queue; + DatagramSocket _socket; + bool _stopped; +}; + + +RemoteUDPListener::RemoteUDPListener(Poco::NotificationQueue& queue, Poco::UInt16 port): + _queue(queue), + _socket(Poco::Net::SocketAddress(Poco::Net::IPAddress(), port)), + _stopped(false) +{ +} + + +RemoteUDPListener::~RemoteUDPListener() +{ +} + + +void RemoteUDPListener::run() +{ + Poco::Buffer<char> buffer(BUFFER_SIZE); + Poco::Timespan waitTime(WAITTIME_MILLISEC* 1000); + while (!_stopped) + { + try + { + if (_socket.poll(waitTime, Socket::SELECT_READ)) + { + Poco::Net::SocketAddress sourceAddress; + int n = _socket.receiveFrom(buffer.begin(), BUFFER_SIZE, sourceAddress); + if (n > 0) + { + _queue.enqueueNotification(new MessageNotification(buffer.begin(), n, sourceAddress)); + } + } + } + catch (...) + { + // lazy exception catching + } + } +} + + +void RemoteUDPListener::safeStop() +{ + _stopped = true; +} + + +// +// SyslogParser +// + + +class SyslogParser: public Poco::Runnable +{ +public: + static const std::string NILVALUE; + + enum + { + WAITTIME_MILLISEC = 1000 + }; + + SyslogParser(Poco::NotificationQueue& queue, RemoteSyslogListener* pListener); + ~SyslogParser(); + + void parse(const std::string& line, Poco::Message& message); + void run(); + void safeStop(); + + static Poco::Message::Priority convert(RemoteSyslogChannel::Severity severity); + +private: + void parsePrio(const std::string& line, std::size_t& pos, RemoteSyslogChannel::Severity& severity, RemoteSyslogChannel::Facility& fac); + void parseNew(const std::string& line, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos, Poco::Message& message); + void parseBSD(const std::string& line, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos, Poco::Message& message); + + static std::string parseUntilSpace(const std::string& line, std::size_t& pos); + /// Parses until it encounters the next space char, returns the string from pos, excluding space + /// pos will point past the space char + + static std::string parseStructuredData(const std::string& line, std::size_t& pos); + /// Parses the structured data field. + + static std::string parseStructuredDataToken(const std::string& line, std::size_t& pos); + /// Parses a token from the structured data field. + +private: + Poco::NotificationQueue& _queue; + bool _stopped; + RemoteSyslogListener* _pListener; +}; + + +const std::string SyslogParser::NILVALUE("-"); + + +SyslogParser::SyslogParser(Poco::NotificationQueue& queue, RemoteSyslogListener* pListener): + _queue(queue), + _stopped(false), + _pListener(pListener) +{ + poco_check_ptr (_pListener); +} + + +SyslogParser::~SyslogParser() +{ +} + + +void SyslogParser::run() +{ + while (!_stopped) + { + try + { + Poco::AutoPtr<Poco::Notification> pNf(_queue.waitDequeueNotification(WAITTIME_MILLISEC)); + if (pNf) + { + Poco::AutoPtr<MessageNotification> pMsgNf = pNf.cast<MessageNotification>(); + Poco::Message message; + parse(pMsgNf->message(), message); + message["addr"] =pMsgNf->sourceAddress().host().toString(); + _pListener->log(message); + } + } + catch (Poco::Exception&) + { + // parsing exception, what should we do? + } + catch (...) + { + } + } +} + + +void SyslogParser::safeStop() +{ + _stopped = true; +} + + +void SyslogParser::parse(const std::string& line, Poco::Message& message) +{ + // <int> -> int: lower 3 bits severity, upper bits: facility + std::size_t pos = 0; + RemoteSyslogChannel::Severity severity; + RemoteSyslogChannel::Facility fac; + parsePrio(line, pos, severity, fac); + + // the next field decide if we parse an old BSD message or a new syslog message + // BSD: expects a month value in string form: Jan, Feb... + // SYSLOG expects a version number: 1 + + if (Poco::Ascii::isDigit(line[pos])) + { + parseNew(line, severity, fac, pos, message); + } else - { - SplitterChannel::setProperty(name, value); - } -} - - -std::string RemoteSyslogListener::getProperty(const std::string& name) const -{ - if (name == PROP_PORT) - return Poco::NumberFormatter::format(_port); - else if (name == PROP_THREADS) - return Poco::NumberFormatter::format(_threads); - else - return SplitterChannel::getProperty(name); -} - - -void RemoteSyslogListener::open() -{ - SplitterChannel::open(); - _pParser = new SyslogParser(_queue, this); - if (_port > 0) - { - _pListener = new RemoteUDPListener(_queue, _port); - } - for (int i = 0; i < _threads; i++) - { - _threadPool.start(*_pParser); - } - if (_pListener) - { - _threadPool.start(*_pListener); - } -} - - -void RemoteSyslogListener::close() -{ - if (_pListener) - { - _pListener->safeStop(); - } - if (_pParser) - { - _pParser->safeStop(); - } - _queue.clear(); - _threadPool.joinAll(); - delete _pListener; - delete _pParser; - _pListener = 0; - _pParser = 0; - SplitterChannel::close(); -} - - -void RemoteSyslogListener::registerChannel() -{ - Poco::LoggingFactory::defaultFactory().registerChannelClass("RemoteSyslogListener", new Poco::Instantiator<RemoteSyslogListener, Poco::Channel>); -} - - -} } // namespace Poco::Net + { + parseBSD(line, severity, fac, pos, message); + } + poco_assert (pos == line.size()); +} + + +void SyslogParser::parsePrio(const std::string& line, std::size_t& pos, RemoteSyslogChannel::Severity& severity, RemoteSyslogChannel::Facility& fac) +{ + poco_assert (pos < line.size()); + poco_assert (line[pos] == '<'); + ++pos; + std::size_t start = pos; + + while (pos < line.size() && Poco::Ascii::isDigit(line[pos])) + ++pos; + + poco_assert (line[pos] == '>'); + poco_assert (pos - start > 0); + std::string valStr = line.substr(start, pos - start); + ++pos; // skip the > + + int val = Poco::NumberParser::parse(valStr); + poco_assert (val >= 0 && val <= (RemoteSyslogChannel::SYSLOG_LOCAL7 + RemoteSyslogChannel::SYSLOG_DEBUG)); + + Poco::UInt16 pri = static_cast<Poco::UInt16>(val); + // now get the lowest 3 bits + severity = static_cast<RemoteSyslogChannel::Severity>(pri & 0x0007u); + fac = static_cast<RemoteSyslogChannel::Facility>(pri & 0xfff8u); +} + + +void SyslogParser::parseNew(const std::string& line, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility /*fac*/, std::size_t& pos, Poco::Message& message) +{ + Poco::Message::Priority prio = convert(severity); + // rest of the unparsed header is: + // VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID + std::string versionStr(parseUntilSpace(line, pos)); + std::string timeStr(parseUntilSpace(line, pos)); // can be the nilvalue! + std::string hostName(parseUntilSpace(line, pos)); + std::string appName(parseUntilSpace(line, pos)); + std::string procId(parseUntilSpace(line, pos)); + std::string msgId(parseUntilSpace(line, pos)); + std::string sd(parseStructuredData(line, pos)); + std::string messageText(line.substr(pos)); + pos = line.size(); + Poco::DateTime date; + int tzd = 0; + bool hasDate = Poco::DateTimeParser::tryParse(RemoteSyslogChannel::SYSLOG_TIMEFORMAT, timeStr, date, tzd); + Poco::Message logEntry(msgId, messageText, prio); + logEntry[RemoteSyslogListener::LOG_PROP_HOST] = hostName; + logEntry[RemoteSyslogListener::LOG_PROP_APP] = appName; + logEntry[RemoteSyslogListener::LOG_PROP_STRUCTURED_DATA] = sd; + + if (hasDate) + logEntry.setTime(date.timestamp()); + int lval(0); + Poco::NumberParser::tryParse(procId, lval); + logEntry.setPid(lval); + message.swap(logEntry); +} + + +void SyslogParser::parseBSD(const std::string& line, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility /*fac*/, std::size_t& pos, Poco::Message& message) +{ + Poco::Message::Priority prio = convert(severity); + // rest of the unparsed header is: + // "%b %f %H:%M:%S" SP hostname|ipaddress + // detect three spaces + int spaceCnt = 0; + std::size_t start = pos; + while (spaceCnt < 3 && pos < line.size()) + { + if (line[pos] == ' ') + { + spaceCnt++; + if (spaceCnt == 1) + { + // size must be 3 chars for month + if (pos - start != 3) + { + // probably a shortened time value, or the hostname + // assume hostName + Poco::Message logEntry(line.substr(start, pos-start), line.substr(pos+1), prio); + message.swap(logEntry); + return; + } + } + else if (spaceCnt == 2) + { + // a day value! + if (!(Poco::Ascii::isDigit(line[pos-1]) && (Poco::Ascii::isDigit(line[pos-2]) || Poco::Ascii::isSpace(line[pos-2])))) + { + // assume the next field is a hostname + spaceCnt = 3; + } + } + if (pos + 1 < line.size() && line[pos+1] == ' ') + { + // we have two spaces when the day value is smaller than 10! + ++pos; // skip one + } + } + ++pos; + } + std::string timeStr(line.substr(start, pos-start-1)); + int tzd(0); + Poco::DateTime date; + int year = date.year(); // year is not included, use the current one + bool hasDate = Poco::DateTimeParser::tryParse(RemoteSyslogChannel::BSD_TIMEFORMAT, timeStr, date, tzd); + if (hasDate) + { + int m = date.month(); + int d = date.day(); + int h = date.hour(); + int min = date.minute(); + int sec = date.second(); + date = Poco::DateTime(year, m, d, h, min, sec); + } + // next entry is host SP + std::string hostName(parseUntilSpace(line, pos)); + + // TAG: at most 32 alphanumeric chars, ANY non alphannumeric indicates start of message content + // ignore: treat everything as content + std::string messageText(line.substr(pos)); + pos = line.size(); + Poco::Message logEntry(hostName, messageText, prio); + logEntry.setTime(date.timestamp()); + message.swap(logEntry); +} + + +std::string SyslogParser::parseUntilSpace(const std::string& line, std::size_t& pos) +{ + std::size_t start = pos; + while (pos < line.size() && !Poco::Ascii::isSpace(line[pos])) + ++pos; + // skip space + ++pos; + return line.substr(start, pos-start-1); +} + + +std::string SyslogParser::parseStructuredData(const std::string& line, std::size_t& pos) +{ + std::string sd; + if (pos < line.size()) + { + if (line[pos] == '-') + { + ++pos; + } + else if (line[pos] == '[') + { + std::string tok = parseStructuredDataToken(line, pos); + while (tok == "[") + { + sd += tok; + tok = parseStructuredDataToken(line, pos); + while (tok != "]" && !tok.empty()) + { + sd += tok; + tok = parseStructuredDataToken(line, pos); + } + sd += tok; + if (pos < line.size() && line[pos] == '[') tok = parseStructuredDataToken(line, pos); + } + } + if (pos < line.size() && Poco::Ascii::isSpace(line[pos])) ++pos; + } + return sd; +} + + +std::string SyslogParser::parseStructuredDataToken(const std::string& line, std::size_t& pos) +{ + std::string tok; + if (pos < line.size()) + { + if (Poco::Ascii::isSpace(line[pos]) || line[pos] == '=' || line[pos] == '[' || line[pos] == ']') + { + tok += line[pos++]; + } + else if (line[pos] == '"') + { + tok += line[pos++]; + while (pos < line.size() && line[pos] != '"') + { + tok += line[pos++]; + } + tok += '"'; + if (pos < line.size()) pos++; + } + else + { + while (pos < line.size() && !Poco::Ascii::isSpace(line[pos]) && line[pos] != '=') + { + tok += line[pos++]; + } + } + } + return tok; +} + +Poco::Message::Priority SyslogParser::convert(RemoteSyslogChannel::Severity severity) +{ + switch (severity) + { + case RemoteSyslogChannel::SYSLOG_EMERGENCY: + return Poco::Message::PRIO_FATAL; + case RemoteSyslogChannel::SYSLOG_ALERT: + return Poco::Message::PRIO_FATAL; + case RemoteSyslogChannel::SYSLOG_CRITICAL: + return Poco::Message::PRIO_CRITICAL; + case RemoteSyslogChannel::SYSLOG_ERROR: + return Poco::Message::PRIO_ERROR; + case RemoteSyslogChannel::SYSLOG_WARNING: + return Poco::Message::PRIO_WARNING; + case RemoteSyslogChannel::SYSLOG_NOTICE: + return Poco::Message::PRIO_NOTICE; + case RemoteSyslogChannel::SYSLOG_INFORMATIONAL: + return Poco::Message::PRIO_INFORMATION; + case RemoteSyslogChannel::SYSLOG_DEBUG: + return Poco::Message::PRIO_DEBUG; + } + throw Poco::LogicException("Illegal severity value in message"); +} + + +// +// RemoteSyslogListener +// + + +const std::string RemoteSyslogListener::PROP_PORT("port"); +const std::string RemoteSyslogListener::PROP_THREADS("threads"); + +const std::string RemoteSyslogListener::LOG_PROP_APP("app"); +const std::string RemoteSyslogListener::LOG_PROP_HOST("host"); +const std::string RemoteSyslogListener::LOG_PROP_STRUCTURED_DATA("structured-data"); + + +RemoteSyslogListener::RemoteSyslogListener(): + _pListener(0), + _pParser(0), + _port(RemoteSyslogChannel::SYSLOG_PORT), + _threads(1) +{ +} + + +RemoteSyslogListener::RemoteSyslogListener(Poco::UInt16 port): + _pListener(0), + _pParser(0), + _port(port), + _threads(1) +{ +} + + +RemoteSyslogListener::RemoteSyslogListener(Poco::UInt16 port, int threads): + _pListener(0), + _pParser(0), + _port(port), + _threads(threads) +{ +} + + +RemoteSyslogListener::~RemoteSyslogListener() +{ +} + + +void RemoteSyslogListener::processMessage(const std::string& messageText) +{ + Poco::Message message; + _pParser->parse(messageText, message); + log(message); +} + + +void RemoteSyslogListener::enqueueMessage(const std::string& messageText, const Poco::Net::SocketAddress& senderAddress) +{ + _queue.enqueueNotification(new MessageNotification(messageText, senderAddress)); +} + + +void RemoteSyslogListener::setProperty(const std::string& name, const std::string& value) +{ + if (name == PROP_PORT) + { + int val = Poco::NumberParser::parse(value); + if (val >= 0 && val < 65536) + _port = static_cast<Poco::UInt16>(val); + else + throw Poco::InvalidArgumentException("Not a valid port number", value); + } + else if (name == PROP_THREADS) + { + int val = Poco::NumberParser::parse(value); + if (val > 0 && val < 16) + _threads = val; + else + throw Poco::InvalidArgumentException("Invalid number of threads", value); + } + else + { + SplitterChannel::setProperty(name, value); + } +} + + +std::string RemoteSyslogListener::getProperty(const std::string& name) const +{ + if (name == PROP_PORT) + return Poco::NumberFormatter::format(_port); + else if (name == PROP_THREADS) + return Poco::NumberFormatter::format(_threads); + else + return SplitterChannel::getProperty(name); +} + + +void RemoteSyslogListener::open() +{ + SplitterChannel::open(); + _pParser = new SyslogParser(_queue, this); + if (_port > 0) + { + _pListener = new RemoteUDPListener(_queue, _port); + } + for (int i = 0; i < _threads; i++) + { + _threadPool.start(*_pParser); + } + if (_pListener) + { + _threadPool.start(*_pListener); + } +} + + +void RemoteSyslogListener::close() +{ + if (_pListener) + { + _pListener->safeStop(); + } + if (_pParser) + { + _pParser->safeStop(); + } + _queue.clear(); + _threadPool.joinAll(); + delete _pListener; + delete _pParser; + _pListener = 0; + _pParser = 0; + SplitterChannel::close(); +} + + +void RemoteSyslogListener::registerChannel() +{ + Poco::LoggingFactory::defaultFactory().registerChannelClass("RemoteSyslogListener", new Poco::Instantiator<RemoteSyslogListener, Poco::Channel>); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/SMTPChannel.cpp b/contrib/libs/poco/Net/src/SMTPChannel.cpp index a498179a44..f4b6a9f169 100644 --- a/contrib/libs/poco/Net/src/SMTPChannel.cpp +++ b/contrib/libs/poco/Net/src/SMTPChannel.cpp @@ -1,210 +1,210 @@ -// -// SMTPChannel.cpp -// -// Library: Net -// Package: Logging -// Module: SMTPChannel -// -// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/SMTPChannel.h" -#include "Poco/Net/MailMessage.h" -#include "Poco/Net/MailRecipient.h" -#include "Poco/Net/SMTPClientSession.h" -#include "Poco/Net/StringPartSource.h" -#include "Poco/Message.h" -#include "Poco/DateTimeFormatter.h" -#include "Poco/DateTimeFormat.h" -#include "Poco/LocalDateTime.h" -#include "Poco/LoggingFactory.h" -#include "Poco/Instantiator.h" -#include "Poco/NumberFormatter.h" -#include "Poco/FileStream.h" -#include "Poco/File.h" -#include "Poco/Environment.h" - - -namespace Poco { -namespace Net { - - -const std::string SMTPChannel::PROP_MAILHOST("mailhost"); -const std::string SMTPChannel::PROP_SENDER("sender"); -const std::string SMTPChannel::PROP_RECIPIENT("recipient"); -const std::string SMTPChannel::PROP_LOCAL("local"); -const std::string SMTPChannel::PROP_ATTACHMENT("attachment"); -const std::string SMTPChannel::PROP_TYPE("type"); -const std::string SMTPChannel::PROP_DELETE("delete"); -const std::string SMTPChannel::PROP_THROW("throw"); - - -SMTPChannel::SMTPChannel(): - _mailHost("localhost"), - _local(true), - _type("text/plain"), - _delete(false), - _throw(false) -{ -} - - -SMTPChannel::SMTPChannel(const std::string& mailhost, const std::string& sender, const std::string& recipient): - _mailHost(mailhost), - _sender(sender), - _recipient(recipient), - _local(true), - _type("text/plain"), - _delete(false), - _throw(false) -{ -} - - -SMTPChannel::~SMTPChannel() -{ - try - { - close(); - } - catch (...) - { - poco_unexpected(); - } -} - - -void SMTPChannel::open() -{ -} - - -void SMTPChannel::close() -{ -} - - -void SMTPChannel::log(const Message& msg) -{ - try - { - MailMessage message; - message.setSender(_sender); - message.addRecipient(MailRecipient(MailRecipient::PRIMARY_RECIPIENT, _recipient)); - message.setSubject("Log Message from " + _sender); - std::stringstream content; - content << "Log Message\r\n" - << "===========\r\n\r\n" - << "Host: " << Environment::nodeName() << "\r\n" - << "Logger: " << msg.getSource() << "\r\n"; - - if (_local) - { - DateTime dt(msg.getTime()); - content << "Timestamp: " << DateTimeFormatter::format(LocalDateTime(dt), DateTimeFormat::RFC822_FORMAT) << "\r\n"; - } - else - content << "Timestamp: " << DateTimeFormatter::format(msg.getTime(), DateTimeFormat::RFC822_FORMAT) << "\r\n"; - - content << "Priority: " << NumberFormatter::format(msg.getPriority()) << "\r\n" - << "Process ID: " << NumberFormatter::format(msg.getPid()) << "\r\n" - << "Thread: " << msg.getThread() << " (ID: " << msg.getTid() << ")\r\n" - << "Message text: " << msg.getText() << "\r\n\r\n"; - - message.addContent(new StringPartSource(content.str())); - - if (!_attachment.empty()) - { - { - Poco::FileInputStream fis(_attachment, std::ios::in | std::ios::binary | std::ios::ate); - if (fis.good()) - { - typedef std::allocator<std::string::value_type>::size_type SST; - - std::streamoff size = fis.tellg(); - poco_assert (std::numeric_limits<unsigned int>::max() >= size); - poco_assert (std::numeric_limits<SST>::max() >= size); - char* pMem = new char [static_cast<unsigned int>(size)]; - fis.seekg(std::ios::beg); - fis.read(pMem, size); - message.addAttachment(_attachment, - new StringPartSource(std::string(pMem, static_cast<SST>(size)), - _type, - _attachment)); - - delete [] pMem; - } - } - if (_delete) File(_attachment).remove(); - } - - SMTPClientSession session(_mailHost); - session.login(); - session.sendMessage(message); - session.close(); +// +// SMTPChannel.cpp +// +// Library: Net +// Package: Logging +// Module: SMTPChannel +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/SMTPChannel.h" +#include "Poco/Net/MailMessage.h" +#include "Poco/Net/MailRecipient.h" +#include "Poco/Net/SMTPClientSession.h" +#include "Poco/Net/StringPartSource.h" +#include "Poco/Message.h" +#include "Poco/DateTimeFormatter.h" +#include "Poco/DateTimeFormat.h" +#include "Poco/LocalDateTime.h" +#include "Poco/LoggingFactory.h" +#include "Poco/Instantiator.h" +#include "Poco/NumberFormatter.h" +#include "Poco/FileStream.h" +#include "Poco/File.h" +#include "Poco/Environment.h" + + +namespace Poco { +namespace Net { + + +const std::string SMTPChannel::PROP_MAILHOST("mailhost"); +const std::string SMTPChannel::PROP_SENDER("sender"); +const std::string SMTPChannel::PROP_RECIPIENT("recipient"); +const std::string SMTPChannel::PROP_LOCAL("local"); +const std::string SMTPChannel::PROP_ATTACHMENT("attachment"); +const std::string SMTPChannel::PROP_TYPE("type"); +const std::string SMTPChannel::PROP_DELETE("delete"); +const std::string SMTPChannel::PROP_THROW("throw"); + + +SMTPChannel::SMTPChannel(): + _mailHost("localhost"), + _local(true), + _type("text/plain"), + _delete(false), + _throw(false) +{ +} + + +SMTPChannel::SMTPChannel(const std::string& mailhost, const std::string& sender, const std::string& recipient): + _mailHost(mailhost), + _sender(sender), + _recipient(recipient), + _local(true), + _type("text/plain"), + _delete(false), + _throw(false) +{ +} + + +SMTPChannel::~SMTPChannel() +{ + try + { + close(); + } + catch (...) + { + poco_unexpected(); } - catch (Exception&) +} + + +void SMTPChannel::open() +{ +} + + +void SMTPChannel::close() +{ +} + + +void SMTPChannel::log(const Message& msg) +{ + try { - if (_throw) throw; - } -} - - -void SMTPChannel::setProperty(const std::string& name, const std::string& value) -{ - if (name == PROP_MAILHOST) - _mailHost = value; - else if (name == PROP_SENDER) - _sender = value; - else if (name == PROP_RECIPIENT) - _recipient = value; - else if (name == PROP_LOCAL) - _local = isTrue(value); - else if (name == PROP_ATTACHMENT) - _attachment = value; - else if (name == PROP_TYPE) - _type = value; - else if (name == PROP_DELETE) - _delete = isTrue(value); - else if (name == PROP_THROW) - _throw = isTrue(value); + MailMessage message; + message.setSender(_sender); + message.addRecipient(MailRecipient(MailRecipient::PRIMARY_RECIPIENT, _recipient)); + message.setSubject("Log Message from " + _sender); + std::stringstream content; + content << "Log Message\r\n" + << "===========\r\n\r\n" + << "Host: " << Environment::nodeName() << "\r\n" + << "Logger: " << msg.getSource() << "\r\n"; + + if (_local) + { + DateTime dt(msg.getTime()); + content << "Timestamp: " << DateTimeFormatter::format(LocalDateTime(dt), DateTimeFormat::RFC822_FORMAT) << "\r\n"; + } + else + content << "Timestamp: " << DateTimeFormatter::format(msg.getTime(), DateTimeFormat::RFC822_FORMAT) << "\r\n"; + + content << "Priority: " << NumberFormatter::format(msg.getPriority()) << "\r\n" + << "Process ID: " << NumberFormatter::format(msg.getPid()) << "\r\n" + << "Thread: " << msg.getThread() << " (ID: " << msg.getTid() << ")\r\n" + << "Message text: " << msg.getText() << "\r\n\r\n"; + + message.addContent(new StringPartSource(content.str())); + + if (!_attachment.empty()) + { + { + Poco::FileInputStream fis(_attachment, std::ios::in | std::ios::binary | std::ios::ate); + if (fis.good()) + { + typedef std::allocator<std::string::value_type>::size_type SST; + + std::streamoff size = fis.tellg(); + poco_assert (std::numeric_limits<unsigned int>::max() >= size); + poco_assert (std::numeric_limits<SST>::max() >= size); + char* pMem = new char [static_cast<unsigned int>(size)]; + fis.seekg(std::ios::beg); + fis.read(pMem, size); + message.addAttachment(_attachment, + new StringPartSource(std::string(pMem, static_cast<SST>(size)), + _type, + _attachment)); + + delete [] pMem; + } + } + if (_delete) File(_attachment).remove(); + } + + SMTPClientSession session(_mailHost); + session.login(); + session.sendMessage(message); + session.close(); + } + catch (Exception&) + { + if (_throw) throw; + } +} + + +void SMTPChannel::setProperty(const std::string& name, const std::string& value) +{ + if (name == PROP_MAILHOST) + _mailHost = value; + else if (name == PROP_SENDER) + _sender = value; + else if (name == PROP_RECIPIENT) + _recipient = value; + else if (name == PROP_LOCAL) + _local = isTrue(value); + else if (name == PROP_ATTACHMENT) + _attachment = value; + else if (name == PROP_TYPE) + _type = value; + else if (name == PROP_DELETE) + _delete = isTrue(value); + else if (name == PROP_THROW) + _throw = isTrue(value); + else + Channel::setProperty(name, value); +} + + +std::string SMTPChannel::getProperty(const std::string& name) const +{ + if (name == PROP_MAILHOST) + return _mailHost; + else if (name == PROP_SENDER) + return _sender; + else if (name == PROP_RECIPIENT) + return _recipient; + else if (name == PROP_LOCAL) + return _local ? "true" : "false"; + else if (name == PROP_ATTACHMENT) + return _attachment; + else if (name == PROP_TYPE) + return _type; + else if (name == PROP_DELETE) + return _delete ? "true" : "false"; + else if (name == PROP_THROW) + return _throw ? "true" : "false"; else - Channel::setProperty(name, value); -} - - -std::string SMTPChannel::getProperty(const std::string& name) const -{ - if (name == PROP_MAILHOST) - return _mailHost; - else if (name == PROP_SENDER) - return _sender; - else if (name == PROP_RECIPIENT) - return _recipient; - else if (name == PROP_LOCAL) - return _local ? "true" : "false"; - else if (name == PROP_ATTACHMENT) - return _attachment; - else if (name == PROP_TYPE) - return _type; - else if (name == PROP_DELETE) - return _delete ? "true" : "false"; - else if (name == PROP_THROW) - return _throw ? "true" : "false"; - else - return Channel::getProperty(name); -} - - -void SMTPChannel::registerChannel() -{ - Poco::LoggingFactory::defaultFactory().registerChannelClass("SMTPChannel", - new Poco::Instantiator<SMTPChannel, Poco::Channel>); -} - - -} } // namespace Poco::Net + return Channel::getProperty(name); +} + + +void SMTPChannel::registerChannel() +{ + Poco::LoggingFactory::defaultFactory().registerChannelClass("SMTPChannel", + new Poco::Instantiator<SMTPChannel, Poco::Channel>); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/SMTPClientSession.cpp b/contrib/libs/poco/Net/src/SMTPClientSession.cpp index 35612381ee..78ba2784a7 100644 --- a/contrib/libs/poco/Net/src/SMTPClientSession.cpp +++ b/contrib/libs/poco/Net/src/SMTPClientSession.cpp @@ -1,466 +1,466 @@ -// -// SMTPClientSession.cpp -// -// Library: Net -// Package: Mail -// Module: SMTPClientSession -// -// Copyright (c) 2005-2008, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/SMTPClientSession.h" -#include "Poco/Net/MailMessage.h" -#include "Poco/Net/MailRecipient.h" -#include "Poco/Net/MailStream.h" -#include "Poco/Net/SocketAddress.h" -#include "Poco/Net/SocketStream.h" -#include "Poco/Net/NetException.h" -#include "Poco/Environment.h" -#include "Poco/Net/NetworkInterface.h" -#include "Poco/HMACEngine.h" -#include "Poco/MD5Engine.h" -#include "Poco/SHA1Engine.h" -#include "Poco/DigestStream.h" -#include "Poco/StreamCopier.h" -#include "Poco/Base64Encoder.h" -#include "Poco/Base64Decoder.h" -#include "Poco/String.h" -#include <sstream> -#include <fstream> -#include <iostream> - - -using Poco::DigestEngine; -using Poco::HMACEngine; -using Poco::MD5Engine; -using Poco::SHA1Engine; -using Poco::DigestOutputStream; -using Poco::StreamCopier; -using Poco::Base64Encoder; -using Poco::Base64Decoder; -using Poco::Environment; - - -namespace Poco { -namespace Net { - - -SMTPClientSession::SMTPClientSession(const StreamSocket& socket): - _socket(socket), - _isOpen(false) -{ -} - - -SMTPClientSession::SMTPClientSession(const std::string& host, Poco::UInt16 port): - _socket(SocketAddress(host, port)), - _isOpen(false) -{ -} - - -SMTPClientSession::~SMTPClientSession() -{ - try - { - close(); - } - catch (...) - { - } -} - - -void SMTPClientSession::setTimeout(const Poco::Timespan& timeout) -{ - _socket.setReceiveTimeout(timeout); -} - - -Poco::Timespan SMTPClientSession::getTimeout() const -{ - return _socket.getReceiveTimeout(); -} - - -void SMTPClientSession::login(const std::string& hostname, std::string& response) -{ - open(); - int status = sendCommand("EHLO", hostname, response); - if (isPermanentNegative(status)) - status = sendCommand("HELO", hostname, response); - if (!isPositiveCompletion(status)) throw SMTPException("Login failed", response, status); -} - - -void SMTPClientSession::login(const std::string& hostname) -{ - std::string response; - login(hostname, response); -} - - -void SMTPClientSession::login() -{ - login(Environment::nodeName()); -} - - -void SMTPClientSession::loginUsingCRAMMD5(const std::string& username, const std::string& password) -{ - HMACEngine<MD5Engine> hmac(password); - loginUsingCRAM(username, "CRAM-MD5", hmac); -} - - -void SMTPClientSession::loginUsingCRAMSHA1(const std::string& username, const std::string& password) -{ - HMACEngine<SHA1Engine> hmac(password); - loginUsingCRAM(username, "CRAM-SHA1", hmac); -} - - -void SMTPClientSession::loginUsingCRAM(const std::string& username, const std::string& method, Poco::DigestEngine& hmac) -{ - std::string response; - int status = sendCommand(std::string("AUTH ") + method, response); - - if (!isPositiveIntermediate(status)) throw SMTPException(std::string("Cannot authenticate using ") + method, response, status); - std::string challengeBase64 = response.substr(4); - - std::istringstream istr(challengeBase64); - Base64Decoder decoder(istr); - std::string challenge; - StreamCopier::copyToString(decoder, challenge); - - hmac.update(challenge); - - const DigestEngine::Digest& digest = hmac.digest(); - std::string digestString(DigestEngine::digestToHex(digest)); - - std::string challengeResponse = username + " " + digestString; - - std::ostringstream challengeResponseBase64; - Base64Encoder encoder(challengeResponseBase64); - encoder.rdbuf()->setLineLength(0); - encoder << challengeResponse; - encoder.close(); - - status = sendCommand(challengeResponseBase64.str(), response); - if (!isPositiveCompletion(status)) throw SMTPException(std::string("Login using ") + method + " failed", response, status); -} - - -void SMTPClientSession::loginUsingLogin(const std::string& username, const std::string& password) -{ - std::string response; - int status = sendCommand("AUTH LOGIN", response); - if (!isPositiveIntermediate(status)) throw SMTPException("Cannot authenticate using LOGIN", response, status); - - std::ostringstream usernameBase64; - Base64Encoder usernameEncoder(usernameBase64); - usernameEncoder.rdbuf()->setLineLength(0); - usernameEncoder << username; - usernameEncoder.close(); - - std::ostringstream passwordBase64; - Base64Encoder passwordEncoder(passwordBase64); - passwordEncoder.rdbuf()->setLineLength(0); - passwordEncoder << password; - passwordEncoder.close(); - - //Server request for username/password not defined could be either - //S: login: - //C: user_login - //S: password: - //C: user_password - //or - //S: password: - //C: user_password - //S: login: - //C: user_login - - std::string decodedResponse; - std::istringstream responseStream(response.substr(4)); - Base64Decoder responseDecoder(responseStream); - StreamCopier::copyToString(responseDecoder, decodedResponse); - - if (Poco::icompare(decodedResponse, 0, 8, "username") == 0) // username first (md5("Username:")) - { - status = sendCommand(usernameBase64.str(), response); - if (!isPositiveIntermediate(status)) throw SMTPException("Login using LOGIN username failed", response, status); - - status = sendCommand(passwordBase64.str(), response); - if (!isPositiveCompletion(status)) throw SMTPException("Login using LOGIN password failed", response, status); - } - else if (Poco::icompare(decodedResponse, 0, 8, "password") == 0) // password first (md5("Password:")) - { - status = sendCommand(passwordBase64.str(), response); - if (!isPositiveIntermediate(status)) throw SMTPException("Login using LOGIN password failed", response, status); - - status = sendCommand(usernameBase64.str(), response); - if (!isPositiveCompletion(status)) throw SMTPException("Login using LOGIN username failed", response, status); - } -} - - -void SMTPClientSession::loginUsingPlain(const std::string& username, const std::string& password) -{ - std::ostringstream credentialsBase64; - Base64Encoder credentialsEncoder(credentialsBase64); - credentialsEncoder.rdbuf()->setLineLength(0); - credentialsEncoder << '\0' << username << '\0' << password; - credentialsEncoder.close(); - - std::string response; - int status = sendCommand("AUTH PLAIN", credentialsBase64.str(), response); - if (!isPositiveCompletion(status)) throw SMTPException("Login using PLAIN failed", response, status); -} - - -void SMTPClientSession::loginUsingXOAUTH2(const std::string& username, const std::string& password) -{ - std::ostringstream credentialsBase64; - Base64Encoder credentialsEncoder(credentialsBase64); - credentialsEncoder.rdbuf()->setLineLength(0); - credentialsEncoder << "user=" << username << "\001auth=Bearer " << password << "\001\001"; - credentialsEncoder.close(); - - std::string response; - int status = sendCommand("AUTH XOAUTH2", credentialsBase64.str(), response); - if (!isPositiveCompletion(status)) throw SMTPException("Login using XOAUTH2 failed", response, status); -} - - -void SMTPClientSession::login(LoginMethod loginMethod, const std::string& username, const std::string& password) -{ - login(Environment::nodeName(), loginMethod, username, password); -} - - -void SMTPClientSession::login(const std::string& hostname, LoginMethod loginMethod, const std::string& username, const std::string& password) -{ - std::string response; - login(hostname, response); - - if (loginMethod == AUTH_CRAM_MD5) - { - if (response.find("CRAM-MD5", 0) != std::string::npos) - { - loginUsingCRAMMD5(username, password); - } - else throw SMTPException("The mail service does not support CRAM-MD5 authentication", response); - } - else if (loginMethod == AUTH_CRAM_SHA1) - { - if (response.find("CRAM-SHA1", 0) != std::string::npos) - { - loginUsingCRAMSHA1(username, password); - } - else throw SMTPException("The mail service does not support CRAM-SHA1 authentication", response); - } - else if (loginMethod == AUTH_LOGIN) - { - if (response.find("LOGIN", 0) != std::string::npos) - { - loginUsingLogin(username, password); - } - else throw SMTPException("The mail service does not support LOGIN authentication", response); - } - else if (loginMethod == AUTH_PLAIN) - { - if (response.find("PLAIN", 0) != std::string::npos) - { - loginUsingPlain(username, password); - } - else throw SMTPException("The mail service does not support PLAIN authentication", response); - } - else if (loginMethod == AUTH_XOAUTH2) - { - if (response.find("XOAUTH2", 0) != std::string::npos) - { - loginUsingXOAUTH2(username, password); - } - else throw SMTPException("The mail service does not support XOAUTH2 authentication", response); - } - else if (loginMethod != AUTH_NONE) - { - throw SMTPException("The autentication method is not supported"); - } -} - - -void SMTPClientSession::open() -{ - if (!_isOpen) - { - std::string response; - int status = _socket.receiveStatusMessage(response); - if (!isPositiveCompletion(status)) throw SMTPException("The mail service is unavailable", response, status); - _isOpen = true; - } -} - - -void SMTPClientSession::close() -{ - if (_isOpen) - { - std::string response; - sendCommand("QUIT", response); - _socket.close(); - _isOpen = false; - } -} - - -void SMTPClientSession::sendCommands(const MailMessage& message, const Recipients* pRecipients) -{ - std::string response; - int status = 0; - const std::string& fromField = message.getSender(); - std::string::size_type emailPos = fromField.find('<'); - if (emailPos == std::string::npos) - { - std::string sender("<"); - sender.append(fromField); - sender.append(">"); - status = sendCommand("MAIL FROM:", sender, response); - } - else - { - status = sendCommand("MAIL FROM:", fromField.substr(emailPos, fromField.size() - emailPos), response); - } - - if (!isPositiveCompletion(status)) throw SMTPException("Cannot send message", response, status); - - std::ostringstream recipient; - if (pRecipients) - { - for (Recipients::const_iterator it = pRecipients->begin(); it != pRecipients->end(); ++it) - { - recipient << '<' << *it << '>'; - int status2 = sendCommand("RCPT TO:", recipient.str(), response); - if (!isPositiveCompletion(status2)) throw SMTPException(std::string("Recipient rejected: ") + recipient.str(), response, status2); - recipient.str(""); - } - } - else - { - for (MailMessage::Recipients::const_iterator it = message.recipients().begin(); it != message.recipients().end(); ++it) - { - recipient << '<' << it->getAddress() << '>'; - int status2 = sendCommand("RCPT TO:", recipient.str(), response); - if (!isPositiveCompletion(status2)) throw SMTPException(std::string("Recipient rejected: ") + recipient.str(), response, status2); - recipient.str(""); - } - } - - status = sendCommand("DATA", response); - if (!isPositiveIntermediate(status)) throw SMTPException("Cannot send message data", response, status); -} - - -void SMTPClientSession::sendAddresses(const std::string& from, const Recipients& recipients) -{ - std::string response; - int status = 0; - - std::string::size_type emailPos = from.find('<'); - if (emailPos == std::string::npos) - { - std::string sender("<"); - sender.append(from); - sender.append(">"); - status = sendCommand("MAIL FROM:", sender, response); - } - else - { - status = sendCommand("MAIL FROM:", from.substr(emailPos, from.size() - emailPos), response); - } - - if (!isPositiveCompletion(status)) throw SMTPException("Cannot send message", response, status); - - std::ostringstream recipient; - - for (Recipients::const_iterator it = recipients.begin(); it != recipients.end(); ++it) - { - - recipient << '<' << *it << '>'; - int status2 = sendCommand("RCPT TO:", recipient.str(), response); - if (!isPositiveCompletion(status2)) throw SMTPException(std::string("Recipient rejected: ") + recipient.str(), response, status2); - recipient.str(""); - } -} - - -void SMTPClientSession::sendData() -{ - std::string response; - int status = sendCommand("DATA", response); - if (!isPositiveIntermediate(status)) throw SMTPException("Cannot send message data", response, status); -} - - -void SMTPClientSession::sendMessage(const MailMessage& message) -{ - sendCommands(message); - transportMessage(message); -} - - -void SMTPClientSession::sendMessage(const MailMessage& message, const Recipients& recipients) -{ - sendCommands(message, &recipients); - transportMessage(message); -} - - -void SMTPClientSession::transportMessage(const MailMessage& message) -{ - SocketOutputStream socketStream(_socket); - MailOutputStream mailStream(socketStream); - message.write(mailStream); - mailStream.close(); - socketStream.flush(); - - std::string response; - int status = _socket.receiveStatusMessage(response); - if (!isPositiveCompletion(status)) throw SMTPException("The server rejected the message", response, status); -} - - -int SMTPClientSession::sendCommand(const std::string& command, std::string& response) -{ - _socket.sendMessage(command); - return _socket.receiveStatusMessage(response); -} - - -int SMTPClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response) -{ - _socket.sendMessage(command, arg); - return _socket.receiveStatusMessage(response); -} - - -void SMTPClientSession::sendMessage(std::istream& istr) -{ - std::string response; - int status = 0; - - SocketOutputStream socketStream(_socket); - MailOutputStream mailStream(socketStream); - StreamCopier::copyStream(istr, mailStream); - mailStream.close(); - socketStream.flush(); - status = _socket.receiveStatusMessage(response); - if (!isPositiveCompletion(status)) throw SMTPException("The server rejected the message", response, status); -} - - -} } // namespace Poco::Net +// +// SMTPClientSession.cpp +// +// Library: Net +// Package: Mail +// Module: SMTPClientSession +// +// Copyright (c) 2005-2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/SMTPClientSession.h" +#include "Poco/Net/MailMessage.h" +#include "Poco/Net/MailRecipient.h" +#include "Poco/Net/MailStream.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/Net/SocketStream.h" +#include "Poco/Net/NetException.h" +#include "Poco/Environment.h" +#include "Poco/Net/NetworkInterface.h" +#include "Poco/HMACEngine.h" +#include "Poco/MD5Engine.h" +#include "Poco/SHA1Engine.h" +#include "Poco/DigestStream.h" +#include "Poco/StreamCopier.h" +#include "Poco/Base64Encoder.h" +#include "Poco/Base64Decoder.h" +#include "Poco/String.h" +#include <sstream> +#include <fstream> +#include <iostream> + + +using Poco::DigestEngine; +using Poco::HMACEngine; +using Poco::MD5Engine; +using Poco::SHA1Engine; +using Poco::DigestOutputStream; +using Poco::StreamCopier; +using Poco::Base64Encoder; +using Poco::Base64Decoder; +using Poco::Environment; + + +namespace Poco { +namespace Net { + + +SMTPClientSession::SMTPClientSession(const StreamSocket& socket): + _socket(socket), + _isOpen(false) +{ +} + + +SMTPClientSession::SMTPClientSession(const std::string& host, Poco::UInt16 port): + _socket(SocketAddress(host, port)), + _isOpen(false) +{ +} + + +SMTPClientSession::~SMTPClientSession() +{ + try + { + close(); + } + catch (...) + { + } +} + + +void SMTPClientSession::setTimeout(const Poco::Timespan& timeout) +{ + _socket.setReceiveTimeout(timeout); +} + + +Poco::Timespan SMTPClientSession::getTimeout() const +{ + return _socket.getReceiveTimeout(); +} + + +void SMTPClientSession::login(const std::string& hostname, std::string& response) +{ + open(); + int status = sendCommand("EHLO", hostname, response); + if (isPermanentNegative(status)) + status = sendCommand("HELO", hostname, response); + if (!isPositiveCompletion(status)) throw SMTPException("Login failed", response, status); +} + + +void SMTPClientSession::login(const std::string& hostname) +{ + std::string response; + login(hostname, response); +} + + +void SMTPClientSession::login() +{ + login(Environment::nodeName()); +} + + +void SMTPClientSession::loginUsingCRAMMD5(const std::string& username, const std::string& password) +{ + HMACEngine<MD5Engine> hmac(password); + loginUsingCRAM(username, "CRAM-MD5", hmac); +} + + +void SMTPClientSession::loginUsingCRAMSHA1(const std::string& username, const std::string& password) +{ + HMACEngine<SHA1Engine> hmac(password); + loginUsingCRAM(username, "CRAM-SHA1", hmac); +} + + +void SMTPClientSession::loginUsingCRAM(const std::string& username, const std::string& method, Poco::DigestEngine& hmac) +{ + std::string response; + int status = sendCommand(std::string("AUTH ") + method, response); + + if (!isPositiveIntermediate(status)) throw SMTPException(std::string("Cannot authenticate using ") + method, response, status); + std::string challengeBase64 = response.substr(4); + + std::istringstream istr(challengeBase64); + Base64Decoder decoder(istr); + std::string challenge; + StreamCopier::copyToString(decoder, challenge); + + hmac.update(challenge); + + const DigestEngine::Digest& digest = hmac.digest(); + std::string digestString(DigestEngine::digestToHex(digest)); + + std::string challengeResponse = username + " " + digestString; + + std::ostringstream challengeResponseBase64; + Base64Encoder encoder(challengeResponseBase64); + encoder.rdbuf()->setLineLength(0); + encoder << challengeResponse; + encoder.close(); + + status = sendCommand(challengeResponseBase64.str(), response); + if (!isPositiveCompletion(status)) throw SMTPException(std::string("Login using ") + method + " failed", response, status); +} + + +void SMTPClientSession::loginUsingLogin(const std::string& username, const std::string& password) +{ + std::string response; + int status = sendCommand("AUTH LOGIN", response); + if (!isPositiveIntermediate(status)) throw SMTPException("Cannot authenticate using LOGIN", response, status); + + std::ostringstream usernameBase64; + Base64Encoder usernameEncoder(usernameBase64); + usernameEncoder.rdbuf()->setLineLength(0); + usernameEncoder << username; + usernameEncoder.close(); + + std::ostringstream passwordBase64; + Base64Encoder passwordEncoder(passwordBase64); + passwordEncoder.rdbuf()->setLineLength(0); + passwordEncoder << password; + passwordEncoder.close(); + + //Server request for username/password not defined could be either + //S: login: + //C: user_login + //S: password: + //C: user_password + //or + //S: password: + //C: user_password + //S: login: + //C: user_login + + std::string decodedResponse; + std::istringstream responseStream(response.substr(4)); + Base64Decoder responseDecoder(responseStream); + StreamCopier::copyToString(responseDecoder, decodedResponse); + + if (Poco::icompare(decodedResponse, 0, 8, "username") == 0) // username first (md5("Username:")) + { + status = sendCommand(usernameBase64.str(), response); + if (!isPositiveIntermediate(status)) throw SMTPException("Login using LOGIN username failed", response, status); + + status = sendCommand(passwordBase64.str(), response); + if (!isPositiveCompletion(status)) throw SMTPException("Login using LOGIN password failed", response, status); + } + else if (Poco::icompare(decodedResponse, 0, 8, "password") == 0) // password first (md5("Password:")) + { + status = sendCommand(passwordBase64.str(), response); + if (!isPositiveIntermediate(status)) throw SMTPException("Login using LOGIN password failed", response, status); + + status = sendCommand(usernameBase64.str(), response); + if (!isPositiveCompletion(status)) throw SMTPException("Login using LOGIN username failed", response, status); + } +} + + +void SMTPClientSession::loginUsingPlain(const std::string& username, const std::string& password) +{ + std::ostringstream credentialsBase64; + Base64Encoder credentialsEncoder(credentialsBase64); + credentialsEncoder.rdbuf()->setLineLength(0); + credentialsEncoder << '\0' << username << '\0' << password; + credentialsEncoder.close(); + + std::string response; + int status = sendCommand("AUTH PLAIN", credentialsBase64.str(), response); + if (!isPositiveCompletion(status)) throw SMTPException("Login using PLAIN failed", response, status); +} + + +void SMTPClientSession::loginUsingXOAUTH2(const std::string& username, const std::string& password) +{ + std::ostringstream credentialsBase64; + Base64Encoder credentialsEncoder(credentialsBase64); + credentialsEncoder.rdbuf()->setLineLength(0); + credentialsEncoder << "user=" << username << "\001auth=Bearer " << password << "\001\001"; + credentialsEncoder.close(); + + std::string response; + int status = sendCommand("AUTH XOAUTH2", credentialsBase64.str(), response); + if (!isPositiveCompletion(status)) throw SMTPException("Login using XOAUTH2 failed", response, status); +} + + +void SMTPClientSession::login(LoginMethod loginMethod, const std::string& username, const std::string& password) +{ + login(Environment::nodeName(), loginMethod, username, password); +} + + +void SMTPClientSession::login(const std::string& hostname, LoginMethod loginMethod, const std::string& username, const std::string& password) +{ + std::string response; + login(hostname, response); + + if (loginMethod == AUTH_CRAM_MD5) + { + if (response.find("CRAM-MD5", 0) != std::string::npos) + { + loginUsingCRAMMD5(username, password); + } + else throw SMTPException("The mail service does not support CRAM-MD5 authentication", response); + } + else if (loginMethod == AUTH_CRAM_SHA1) + { + if (response.find("CRAM-SHA1", 0) != std::string::npos) + { + loginUsingCRAMSHA1(username, password); + } + else throw SMTPException("The mail service does not support CRAM-SHA1 authentication", response); + } + else if (loginMethod == AUTH_LOGIN) + { + if (response.find("LOGIN", 0) != std::string::npos) + { + loginUsingLogin(username, password); + } + else throw SMTPException("The mail service does not support LOGIN authentication", response); + } + else if (loginMethod == AUTH_PLAIN) + { + if (response.find("PLAIN", 0) != std::string::npos) + { + loginUsingPlain(username, password); + } + else throw SMTPException("The mail service does not support PLAIN authentication", response); + } + else if (loginMethod == AUTH_XOAUTH2) + { + if (response.find("XOAUTH2", 0) != std::string::npos) + { + loginUsingXOAUTH2(username, password); + } + else throw SMTPException("The mail service does not support XOAUTH2 authentication", response); + } + else if (loginMethod != AUTH_NONE) + { + throw SMTPException("The autentication method is not supported"); + } +} + + +void SMTPClientSession::open() +{ + if (!_isOpen) + { + std::string response; + int status = _socket.receiveStatusMessage(response); + if (!isPositiveCompletion(status)) throw SMTPException("The mail service is unavailable", response, status); + _isOpen = true; + } +} + + +void SMTPClientSession::close() +{ + if (_isOpen) + { + std::string response; + sendCommand("QUIT", response); + _socket.close(); + _isOpen = false; + } +} + + +void SMTPClientSession::sendCommands(const MailMessage& message, const Recipients* pRecipients) +{ + std::string response; + int status = 0; + const std::string& fromField = message.getSender(); + std::string::size_type emailPos = fromField.find('<'); + if (emailPos == std::string::npos) + { + std::string sender("<"); + sender.append(fromField); + sender.append(">"); + status = sendCommand("MAIL FROM:", sender, response); + } + else + { + status = sendCommand("MAIL FROM:", fromField.substr(emailPos, fromField.size() - emailPos), response); + } + + if (!isPositiveCompletion(status)) throw SMTPException("Cannot send message", response, status); + + std::ostringstream recipient; + if (pRecipients) + { + for (Recipients::const_iterator it = pRecipients->begin(); it != pRecipients->end(); ++it) + { + recipient << '<' << *it << '>'; + int status2 = sendCommand("RCPT TO:", recipient.str(), response); + if (!isPositiveCompletion(status2)) throw SMTPException(std::string("Recipient rejected: ") + recipient.str(), response, status2); + recipient.str(""); + } + } + else + { + for (MailMessage::Recipients::const_iterator it = message.recipients().begin(); it != message.recipients().end(); ++it) + { + recipient << '<' << it->getAddress() << '>'; + int status2 = sendCommand("RCPT TO:", recipient.str(), response); + if (!isPositiveCompletion(status2)) throw SMTPException(std::string("Recipient rejected: ") + recipient.str(), response, status2); + recipient.str(""); + } + } + + status = sendCommand("DATA", response); + if (!isPositiveIntermediate(status)) throw SMTPException("Cannot send message data", response, status); +} + + +void SMTPClientSession::sendAddresses(const std::string& from, const Recipients& recipients) +{ + std::string response; + int status = 0; + + std::string::size_type emailPos = from.find('<'); + if (emailPos == std::string::npos) + { + std::string sender("<"); + sender.append(from); + sender.append(">"); + status = sendCommand("MAIL FROM:", sender, response); + } + else + { + status = sendCommand("MAIL FROM:", from.substr(emailPos, from.size() - emailPos), response); + } + + if (!isPositiveCompletion(status)) throw SMTPException("Cannot send message", response, status); + + std::ostringstream recipient; + + for (Recipients::const_iterator it = recipients.begin(); it != recipients.end(); ++it) + { + + recipient << '<' << *it << '>'; + int status2 = sendCommand("RCPT TO:", recipient.str(), response); + if (!isPositiveCompletion(status2)) throw SMTPException(std::string("Recipient rejected: ") + recipient.str(), response, status2); + recipient.str(""); + } +} + + +void SMTPClientSession::sendData() +{ + std::string response; + int status = sendCommand("DATA", response); + if (!isPositiveIntermediate(status)) throw SMTPException("Cannot send message data", response, status); +} + + +void SMTPClientSession::sendMessage(const MailMessage& message) +{ + sendCommands(message); + transportMessage(message); +} + + +void SMTPClientSession::sendMessage(const MailMessage& message, const Recipients& recipients) +{ + sendCommands(message, &recipients); + transportMessage(message); +} + + +void SMTPClientSession::transportMessage(const MailMessage& message) +{ + SocketOutputStream socketStream(_socket); + MailOutputStream mailStream(socketStream); + message.write(mailStream); + mailStream.close(); + socketStream.flush(); + + std::string response; + int status = _socket.receiveStatusMessage(response); + if (!isPositiveCompletion(status)) throw SMTPException("The server rejected the message", response, status); +} + + +int SMTPClientSession::sendCommand(const std::string& command, std::string& response) +{ + _socket.sendMessage(command); + return _socket.receiveStatusMessage(response); +} + + +int SMTPClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response) +{ + _socket.sendMessage(command, arg); + return _socket.receiveStatusMessage(response); +} + + +void SMTPClientSession::sendMessage(std::istream& istr) +{ + std::string response; + int status = 0; + + SocketOutputStream socketStream(_socket); + MailOutputStream mailStream(socketStream); + StreamCopier::copyStream(istr, mailStream); + mailStream.close(); + socketStream.flush(); + status = _socket.receiveStatusMessage(response); + if (!isPositiveCompletion(status)) throw SMTPException("The server rejected the message", response, status); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/ServerSocket.cpp b/contrib/libs/poco/Net/src/ServerSocket.cpp index c44a52b5b5..cac0e8fa0a 100644 --- a/contrib/libs/poco/Net/src/ServerSocket.cpp +++ b/contrib/libs/poco/Net/src/ServerSocket.cpp @@ -1,158 +1,158 @@ -// -// ServerSocket.cpp -// -// Library: Net -// Package: Sockets -// Module: ServerSocket -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/ServerSocket.h" -#include "Poco/Net/ServerSocketImpl.h" -#include "Poco/Exception.h" - - -using Poco::InvalidArgumentException; - - -namespace Poco { -namespace Net { - - -ServerSocket::ServerSocket(): Socket(new ServerSocketImpl) -{ -} - - -ServerSocket::ServerSocket(const Socket& socket): Socket(socket) -{ - if (!dynamic_cast<ServerSocketImpl*>(impl())) - throw InvalidArgumentException("Cannot assign incompatible socket"); -} - - -ServerSocket::ServerSocket(const SocketAddress& address, int backlog): Socket(new ServerSocketImpl) -{ - impl()->bind(address, true); - impl()->listen(backlog); -} - - -ServerSocket::ServerSocket(Poco::UInt16 port, int backlog): Socket(new ServerSocketImpl) -{ - IPAddress wildcardAddr; - SocketAddress address(wildcardAddr, port); - impl()->bind(address, true); - impl()->listen(backlog); -} - - -ServerSocket::ServerSocket(SocketImpl* pImpl, bool /*ignore*/): Socket(pImpl) -{ -} - - -ServerSocket::~ServerSocket() -{ -} - - -ServerSocket& ServerSocket::operator = (const Socket& socket) -{ - if (dynamic_cast<ServerSocketImpl*>(socket.impl())) - Socket::operator = (socket); - else - throw InvalidArgumentException("Cannot assign incompatible socket"); - return *this; -} - - -void ServerSocket::bind(const SocketAddress& address, bool reuseAddress) -{ - impl()->bind(address, reuseAddress); -} - - -void ServerSocket::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) -{ - impl()->bind(address, reuseAddress, reusePort); -} - - -void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress) -{ - IPAddress wildcardAddr; - SocketAddress address(wildcardAddr, port); - impl()->bind(address, reuseAddress); -} - - -void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress, bool reusePort) -{ - IPAddress wildcardAddr; - SocketAddress address(wildcardAddr, port); - impl()->bind(address, reuseAddress, reusePort); -} - - -void ServerSocket::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only) -{ - impl()->bind6(address, reuseAddress, ipV6Only); -} - - -void ServerSocket::bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only) -{ - impl()->bind6(address, reuseAddress, reusePort, ipV6Only); -} - - -void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool ipV6Only) -{ -#if defined(POCO_HAVE_IPv6) - IPAddress wildcardAddr(IPAddress::IPv6); - SocketAddress address(wildcardAddr, port); - impl()->bind6(address, reuseAddress, ipV6Only); -#else - throw Poco::NotImplementedException("No IPv6 support available"); -#endif // POCO_HAVE_IPv6 -} - - -void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool reusePort, bool ipV6Only) -{ -#if defined(POCO_HAVE_IPv6) - IPAddress wildcardAddr(IPAddress::IPv6); - SocketAddress address(wildcardAddr, port); - impl()->bind6(address, reuseAddress, reusePort, ipV6Only); -#else - throw Poco::NotImplementedException("No IPv6 support available"); -#endif // POCO_HAVE_IPv6 -} - - -void ServerSocket::listen(int backlog) -{ - impl()->listen(backlog); -} - - -StreamSocket ServerSocket::acceptConnection(SocketAddress& clientAddr) -{ - return StreamSocket(impl()->acceptConnection(clientAddr)); -} - - -StreamSocket ServerSocket::acceptConnection() -{ - SocketAddress clientAddr; - return StreamSocket(impl()->acceptConnection(clientAddr)); -} - - -} } // namespace Poco::Net +// +// ServerSocket.cpp +// +// Library: Net +// Package: Sockets +// Module: ServerSocket +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/ServerSocket.h" +#include "Poco/Net/ServerSocketImpl.h" +#include "Poco/Exception.h" + + +using Poco::InvalidArgumentException; + + +namespace Poco { +namespace Net { + + +ServerSocket::ServerSocket(): Socket(new ServerSocketImpl) +{ +} + + +ServerSocket::ServerSocket(const Socket& socket): Socket(socket) +{ + if (!dynamic_cast<ServerSocketImpl*>(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +ServerSocket::ServerSocket(const SocketAddress& address, int backlog): Socket(new ServerSocketImpl) +{ + impl()->bind(address, true); + impl()->listen(backlog); +} + + +ServerSocket::ServerSocket(Poco::UInt16 port, int backlog): Socket(new ServerSocketImpl) +{ + IPAddress wildcardAddr; + SocketAddress address(wildcardAddr, port); + impl()->bind(address, true); + impl()->listen(backlog); +} + + +ServerSocket::ServerSocket(SocketImpl* pImpl, bool /*ignore*/): Socket(pImpl) +{ +} + + +ServerSocket::~ServerSocket() +{ +} + + +ServerSocket& ServerSocket::operator = (const Socket& socket) +{ + if (dynamic_cast<ServerSocketImpl*>(socket.impl())) + Socket::operator = (socket); + else + throw InvalidArgumentException("Cannot assign incompatible socket"); + return *this; +} + + +void ServerSocket::bind(const SocketAddress& address, bool reuseAddress) +{ + impl()->bind(address, reuseAddress); +} + + +void ServerSocket::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) +{ + impl()->bind(address, reuseAddress, reusePort); +} + + +void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress) +{ + IPAddress wildcardAddr; + SocketAddress address(wildcardAddr, port); + impl()->bind(address, reuseAddress); +} + + +void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress, bool reusePort) +{ + IPAddress wildcardAddr; + SocketAddress address(wildcardAddr, port); + impl()->bind(address, reuseAddress, reusePort); +} + + +void ServerSocket::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only) +{ + impl()->bind6(address, reuseAddress, ipV6Only); +} + + +void ServerSocket::bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only) +{ + impl()->bind6(address, reuseAddress, reusePort, ipV6Only); +} + + +void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool ipV6Only) +{ +#if defined(POCO_HAVE_IPv6) + IPAddress wildcardAddr(IPAddress::IPv6); + SocketAddress address(wildcardAddr, port); + impl()->bind6(address, reuseAddress, ipV6Only); +#else + throw Poco::NotImplementedException("No IPv6 support available"); +#endif // POCO_HAVE_IPv6 +} + + +void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool reusePort, bool ipV6Only) +{ +#if defined(POCO_HAVE_IPv6) + IPAddress wildcardAddr(IPAddress::IPv6); + SocketAddress address(wildcardAddr, port); + impl()->bind6(address, reuseAddress, reusePort, ipV6Only); +#else + throw Poco::NotImplementedException("No IPv6 support available"); +#endif // POCO_HAVE_IPv6 +} + + +void ServerSocket::listen(int backlog) +{ + impl()->listen(backlog); +} + + +StreamSocket ServerSocket::acceptConnection(SocketAddress& clientAddr) +{ + return StreamSocket(impl()->acceptConnection(clientAddr)); +} + + +StreamSocket ServerSocket::acceptConnection() +{ + SocketAddress clientAddr; + return StreamSocket(impl()->acceptConnection(clientAddr)); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/ServerSocketImpl.cpp b/contrib/libs/poco/Net/src/ServerSocketImpl.cpp index 7f6cd41bbf..b80b558a1f 100644 --- a/contrib/libs/poco/Net/src/ServerSocketImpl.cpp +++ b/contrib/libs/poco/Net/src/ServerSocketImpl.cpp @@ -1,32 +1,32 @@ -// -// ServerSocketImpl.cpp -// -// Library: Net -// Package: Sockets -// Module: ServerSocketImpl -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/ServerSocketImpl.h" - - -namespace Poco { -namespace Net { - - -ServerSocketImpl::ServerSocketImpl() -{ -} - - -ServerSocketImpl::~ServerSocketImpl() -{ -} - - -} } // namespace Poco::Net +// +// ServerSocketImpl.cpp +// +// Library: Net +// Package: Sockets +// Module: ServerSocketImpl +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/ServerSocketImpl.h" + + +namespace Poco { +namespace Net { + + +ServerSocketImpl::ServerSocketImpl() +{ +} + + +ServerSocketImpl::~ServerSocketImpl() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/Socket.cpp b/contrib/libs/poco/Net/src/Socket.cpp index 72a8bd9e2f..a64a9c40d2 100644 --- a/contrib/libs/poco/Net/src/Socket.cpp +++ b/contrib/libs/poco/Net/src/Socket.cpp @@ -1,392 +1,392 @@ -// -// Socket.cpp -// -// Library: Net -// Package: Sockets -// Module: Socket -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/Socket.h" -#include "Poco/Net/StreamSocketImpl.h" -#include "Poco/Timestamp.h" -#include <algorithm> -#include <string.h> // FD_SET needs memset on some platforms, so we can't use <cstring> -#if defined(POCO_HAVE_FD_EPOLL) -#include <sys/epoll.h> -#elif defined(POCO_HAVE_FD_POLL) -#include "Poco/SharedPtr.h" -#include <poll.h> -#endif - - -namespace Poco { -namespace Net { - - -Socket::Socket(): - _pImpl(new StreamSocketImpl) -{ -} - - -Socket::Socket(SocketImpl* pImpl): - _pImpl(pImpl) -{ - poco_check_ptr (_pImpl); -} - - -Socket::Socket(const Socket& socket): - _pImpl(socket._pImpl) -{ - poco_check_ptr (_pImpl); - - _pImpl->duplicate(); -} - - -Socket& Socket::operator = (const Socket& socket) -{ - if (&socket != this) - { - if (_pImpl) _pImpl->release(); - _pImpl = socket._pImpl; - if (_pImpl) _pImpl->duplicate(); - } - return *this; -} - - -Socket::~Socket() -{ - _pImpl->release(); -} - - -int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Poco::Timespan& timeout) -{ -#if defined(POCO_HAVE_FD_EPOLL) - - int epollSize = readList.size() + writeList.size() + exceptList.size(); - if (epollSize == 0) return 0; - - int epollfd = -1; - { - struct epoll_event eventsIn[epollSize]; - memset(eventsIn, 0, sizeof(eventsIn)); - struct epoll_event* eventLast = eventsIn; - for (SocketList::iterator it = readList.begin(); it != readList.end(); ++it) - { - poco_socket_t sockfd = it->sockfd(); - if (sockfd != POCO_INVALID_SOCKET) - { - struct epoll_event* e = eventsIn; - for (; e != eventLast; ++e) - { - if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd) - break; - } - if (e == eventLast) - { - e->data.ptr = &(*it); - ++eventLast; - } - e->events |= EPOLLIN; - } - } - - for (SocketList::iterator it = writeList.begin(); it != writeList.end(); ++it) - { - poco_socket_t sockfd = it->sockfd(); - if (sockfd != POCO_INVALID_SOCKET) - { - struct epoll_event* e = eventsIn; - for (; e != eventLast; ++e) - { - if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd) - break; - } - if (e == eventLast) - { - e->data.ptr = &(*it); - ++eventLast; - } - e->events |= EPOLLOUT; - } - } - - for (SocketList::iterator it = exceptList.begin(); it != exceptList.end(); ++it) - { - poco_socket_t sockfd = it->sockfd(); - if (sockfd != POCO_INVALID_SOCKET) - { - struct epoll_event* e = eventsIn; - for (; e != eventLast; ++e) - { - if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd) - break; - } - if (e == eventLast) - { - e->data.ptr = &(*it); - ++eventLast; - } - e->events |= EPOLLERR; - } - } - - epollSize = eventLast - eventsIn; - if (epollSize == 0) return 0; - - epollfd = epoll_create(1); - if (epollfd < 0) - { - SocketImpl::error("Can't create epoll queue"); - } - - for (struct epoll_event* e = eventsIn; e != eventLast; ++e) - { - poco_socket_t sockfd = reinterpret_cast<Socket*>(e->data.ptr)->sockfd(); - if (sockfd != POCO_INVALID_SOCKET) - { - if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, e) < 0) - { - ::close(epollfd); - SocketImpl::error("Can't insert socket to epoll queue"); - } - } - } - } - - struct epoll_event eventsOut[epollSize]; - memset(eventsOut, 0, sizeof(eventsOut)); - - Poco::Timespan remainingTime(timeout); - int rc; - do - { - Poco::Timestamp start; - rc = epoll_wait(epollfd, eventsOut, epollSize, remainingTime.totalMilliseconds()); - if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) - { - Poco::Timestamp end; - Poco::Timespan waited = end - start; - if (waited < remainingTime) - remainingTime -= waited; - else - remainingTime = 0; - } - } - while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); - - ::close(epollfd); - if (rc < 0) SocketImpl::error(); - - SocketList readyReadList; - SocketList readyWriteList; - SocketList readyExceptList; - for (int n = 0; n < rc; ++n) - { - if (eventsOut[n].events & EPOLLERR) - readyExceptList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr)); - if (eventsOut[n].events & EPOLLIN) - readyReadList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr)); - if (eventsOut[n].events & EPOLLOUT) - readyWriteList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr)); - } - std::swap(readList, readyReadList); - std::swap(writeList, readyWriteList); - std::swap(exceptList, readyExceptList); - return readList.size() + writeList.size() + exceptList.size(); - -#elif defined(POCO_HAVE_FD_POLL) - typedef Poco::SharedPtr<pollfd, Poco::ReferenceCounter, Poco::ReleaseArrayPolicy<pollfd> > SharedPollArray; - - nfds_t nfd = readList.size() + writeList.size() + exceptList.size(); - if (0 == nfd) return 0; - - SharedPollArray pPollArr = new pollfd[nfd](); - - int idx = 0; - for (SocketList::iterator it = readList.begin(); it != readList.end(); ++it) - { - pPollArr[idx].fd = int(it->sockfd()); - pPollArr[idx++].events |= POLLIN; - } - - SocketList::iterator begR = readList.begin(); - SocketList::iterator endR = readList.end(); - for (SocketList::iterator it = writeList.begin(); it != writeList.end(); ++it) - { - SocketList::iterator pos = std::find(begR, endR, *it); - if (pos != endR) - { - pPollArr[pos-begR].events |= POLLOUT; - --nfd; - } - else - { - pPollArr[idx].fd = int(it->sockfd()); - pPollArr[idx++].events |= POLLOUT; - } - } - - SocketList::iterator begW = writeList.begin(); - SocketList::iterator endW = writeList.end(); - for (SocketList::iterator it = exceptList.begin(); it != exceptList.end(); ++it) - { - SocketList::iterator pos = std::find(begR, endR, *it); - if (pos != endR) --nfd; - else - { - SocketList::iterator pos = std::find(begW, endW, *it); - if (pos != endW) --nfd; - else pPollArr[idx++].fd = int(it->sockfd()); - } - } - - Poco::Timespan remainingTime(timeout); - int rc; - do - { - Poco::Timestamp start; - rc = ::poll(pPollArr, nfd, remainingTime.totalMilliseconds()); - if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) - { - Poco::Timestamp end; - Poco::Timespan waited = end - start; - if (waited < remainingTime) remainingTime -= waited; - else remainingTime = 0; - } - } - while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); - if (rc < 0) SocketImpl::error(); - - SocketList readyReadList; - SocketList readyWriteList; - SocketList readyExceptList; - - SocketList::iterator begE = exceptList.begin(); - SocketList::iterator endE = exceptList.end(); - for (int idx = 0; idx < nfd; ++idx) - { - SocketList::iterator slIt = std::find_if(begR, endR, Socket::FDCompare(pPollArr[idx].fd)); - if (POLLIN & pPollArr[idx].revents && slIt != endR) readyReadList.push_back(*slIt); - slIt = std::find_if(begW, endW, Socket::FDCompare(pPollArr[idx].fd)); - if (POLLOUT & pPollArr[idx].revents && slIt != endW) readyWriteList.push_back(*slIt); - slIt = std::find_if(begE, endE, Socket::FDCompare(pPollArr[idx].fd)); - if (POLLERR & pPollArr[idx].revents && slIt != endE) readyExceptList.push_back(*slIt); - } - std::swap(readList, readyReadList); - std::swap(writeList, readyWriteList); - std::swap(exceptList, readyExceptList); - return readList.size() + writeList.size() + exceptList.size(); - -#else - - fd_set fdRead; - fd_set fdWrite; - fd_set fdExcept; - int nfd = 0; - FD_ZERO(&fdRead); - for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it) - { - poco_socket_t fd = it->sockfd(); - if (fd != POCO_INVALID_SOCKET) - { - if (int(fd) > nfd) - nfd = int(fd); - FD_SET(fd, &fdRead); - } - } - FD_ZERO(&fdWrite); - for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it) - { - poco_socket_t fd = it->sockfd(); - if (fd != POCO_INVALID_SOCKET) - { - if (int(fd) > nfd) - nfd = int(fd); - FD_SET(fd, &fdWrite); - } - } - FD_ZERO(&fdExcept); - for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it) - { - poco_socket_t fd = it->sockfd(); - if (fd != POCO_INVALID_SOCKET) - { - if (int(fd) > nfd) - nfd = int(fd); - FD_SET(fd, &fdExcept); - } - } - if (nfd == 0) return 0; - Poco::Timespan remainingTime(timeout); - int rc; - do - { - struct timeval tv; - tv.tv_sec = (long) remainingTime.totalSeconds(); - tv.tv_usec = (long) remainingTime.useconds(); - Poco::Timestamp start; - rc = ::select(nfd + 1, &fdRead, &fdWrite, &fdExcept, &tv); - if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) - { - Poco::Timestamp end; - Poco::Timespan waited = end - start; - if (waited < remainingTime) - remainingTime -= waited; - else - remainingTime = 0; - } - } - while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); - if (rc < 0) SocketImpl::error(); - - SocketList readyReadList; - for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it) - { - poco_socket_t fd = it->sockfd(); - if (fd != POCO_INVALID_SOCKET) - { - if (FD_ISSET(fd, &fdRead)) - readyReadList.push_back(*it); - } - } - std::swap(readList, readyReadList); - SocketList readyWriteList; - for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it) - { - poco_socket_t fd = it->sockfd(); - if (fd != POCO_INVALID_SOCKET) - { - if (FD_ISSET(fd, &fdWrite)) - readyWriteList.push_back(*it); - } - } - std::swap(writeList, readyWriteList); - SocketList readyExceptList; - for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it) - { - poco_socket_t fd = it->sockfd(); - if (fd != POCO_INVALID_SOCKET) - { - if (FD_ISSET(fd, &fdExcept)) - readyExceptList.push_back(*it); - } - } - std::swap(exceptList, readyExceptList); - return rc; - -#endif // POCO_HAVE_FD_EPOLL -} - - -} } // namespace Poco::Net +// +// Socket.cpp +// +// Library: Net +// Package: Sockets +// Module: Socket +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/Socket.h" +#include "Poco/Net/StreamSocketImpl.h" +#include "Poco/Timestamp.h" +#include <algorithm> +#include <string.h> // FD_SET needs memset on some platforms, so we can't use <cstring> +#if defined(POCO_HAVE_FD_EPOLL) +#include <sys/epoll.h> +#elif defined(POCO_HAVE_FD_POLL) +#include "Poco/SharedPtr.h" +#include <poll.h> +#endif + + +namespace Poco { +namespace Net { + + +Socket::Socket(): + _pImpl(new StreamSocketImpl) +{ +} + + +Socket::Socket(SocketImpl* pImpl): + _pImpl(pImpl) +{ + poco_check_ptr (_pImpl); +} + + +Socket::Socket(const Socket& socket): + _pImpl(socket._pImpl) +{ + poco_check_ptr (_pImpl); + + _pImpl->duplicate(); +} + + +Socket& Socket::operator = (const Socket& socket) +{ + if (&socket != this) + { + if (_pImpl) _pImpl->release(); + _pImpl = socket._pImpl; + if (_pImpl) _pImpl->duplicate(); + } + return *this; +} + + +Socket::~Socket() +{ + _pImpl->release(); +} + + +int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Poco::Timespan& timeout) +{ +#if defined(POCO_HAVE_FD_EPOLL) + + int epollSize = readList.size() + writeList.size() + exceptList.size(); + if (epollSize == 0) return 0; + + int epollfd = -1; + { + struct epoll_event eventsIn[epollSize]; + memset(eventsIn, 0, sizeof(eventsIn)); + struct epoll_event* eventLast = eventsIn; + for (SocketList::iterator it = readList.begin(); it != readList.end(); ++it) + { + poco_socket_t sockfd = it->sockfd(); + if (sockfd != POCO_INVALID_SOCKET) + { + struct epoll_event* e = eventsIn; + for (; e != eventLast; ++e) + { + if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd) + break; + } + if (e == eventLast) + { + e->data.ptr = &(*it); + ++eventLast; + } + e->events |= EPOLLIN; + } + } + + for (SocketList::iterator it = writeList.begin(); it != writeList.end(); ++it) + { + poco_socket_t sockfd = it->sockfd(); + if (sockfd != POCO_INVALID_SOCKET) + { + struct epoll_event* e = eventsIn; + for (; e != eventLast; ++e) + { + if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd) + break; + } + if (e == eventLast) + { + e->data.ptr = &(*it); + ++eventLast; + } + e->events |= EPOLLOUT; + } + } + + for (SocketList::iterator it = exceptList.begin(); it != exceptList.end(); ++it) + { + poco_socket_t sockfd = it->sockfd(); + if (sockfd != POCO_INVALID_SOCKET) + { + struct epoll_event* e = eventsIn; + for (; e != eventLast; ++e) + { + if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd) + break; + } + if (e == eventLast) + { + e->data.ptr = &(*it); + ++eventLast; + } + e->events |= EPOLLERR; + } + } + + epollSize = eventLast - eventsIn; + if (epollSize == 0) return 0; + + epollfd = epoll_create(1); + if (epollfd < 0) + { + SocketImpl::error("Can't create epoll queue"); + } + + for (struct epoll_event* e = eventsIn; e != eventLast; ++e) + { + poco_socket_t sockfd = reinterpret_cast<Socket*>(e->data.ptr)->sockfd(); + if (sockfd != POCO_INVALID_SOCKET) + { + if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, e) < 0) + { + ::close(epollfd); + SocketImpl::error("Can't insert socket to epoll queue"); + } + } + } + } + + struct epoll_event eventsOut[epollSize]; + memset(eventsOut, 0, sizeof(eventsOut)); + + Poco::Timespan remainingTime(timeout); + int rc; + do + { + Poco::Timestamp start; + rc = epoll_wait(epollfd, eventsOut, epollSize, remainingTime.totalMilliseconds()); + if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) + { + Poco::Timestamp end; + Poco::Timespan waited = end - start; + if (waited < remainingTime) + remainingTime -= waited; + else + remainingTime = 0; + } + } + while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); + + ::close(epollfd); + if (rc < 0) SocketImpl::error(); + + SocketList readyReadList; + SocketList readyWriteList; + SocketList readyExceptList; + for (int n = 0; n < rc; ++n) + { + if (eventsOut[n].events & EPOLLERR) + readyExceptList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr)); + if (eventsOut[n].events & EPOLLIN) + readyReadList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr)); + if (eventsOut[n].events & EPOLLOUT) + readyWriteList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr)); + } + std::swap(readList, readyReadList); + std::swap(writeList, readyWriteList); + std::swap(exceptList, readyExceptList); + return readList.size() + writeList.size() + exceptList.size(); + +#elif defined(POCO_HAVE_FD_POLL) + typedef Poco::SharedPtr<pollfd, Poco::ReferenceCounter, Poco::ReleaseArrayPolicy<pollfd> > SharedPollArray; + + nfds_t nfd = readList.size() + writeList.size() + exceptList.size(); + if (0 == nfd) return 0; + + SharedPollArray pPollArr = new pollfd[nfd](); + + int idx = 0; + for (SocketList::iterator it = readList.begin(); it != readList.end(); ++it) + { + pPollArr[idx].fd = int(it->sockfd()); + pPollArr[idx++].events |= POLLIN; + } + + SocketList::iterator begR = readList.begin(); + SocketList::iterator endR = readList.end(); + for (SocketList::iterator it = writeList.begin(); it != writeList.end(); ++it) + { + SocketList::iterator pos = std::find(begR, endR, *it); + if (pos != endR) + { + pPollArr[pos-begR].events |= POLLOUT; + --nfd; + } + else + { + pPollArr[idx].fd = int(it->sockfd()); + pPollArr[idx++].events |= POLLOUT; + } + } + + SocketList::iterator begW = writeList.begin(); + SocketList::iterator endW = writeList.end(); + for (SocketList::iterator it = exceptList.begin(); it != exceptList.end(); ++it) + { + SocketList::iterator pos = std::find(begR, endR, *it); + if (pos != endR) --nfd; + else + { + SocketList::iterator pos = std::find(begW, endW, *it); + if (pos != endW) --nfd; + else pPollArr[idx++].fd = int(it->sockfd()); + } + } + + Poco::Timespan remainingTime(timeout); + int rc; + do + { + Poco::Timestamp start; + rc = ::poll(pPollArr, nfd, remainingTime.totalMilliseconds()); + if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) + { + Poco::Timestamp end; + Poco::Timespan waited = end - start; + if (waited < remainingTime) remainingTime -= waited; + else remainingTime = 0; + } + } + while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); + if (rc < 0) SocketImpl::error(); + + SocketList readyReadList; + SocketList readyWriteList; + SocketList readyExceptList; + + SocketList::iterator begE = exceptList.begin(); + SocketList::iterator endE = exceptList.end(); + for (int idx = 0; idx < nfd; ++idx) + { + SocketList::iterator slIt = std::find_if(begR, endR, Socket::FDCompare(pPollArr[idx].fd)); + if (POLLIN & pPollArr[idx].revents && slIt != endR) readyReadList.push_back(*slIt); + slIt = std::find_if(begW, endW, Socket::FDCompare(pPollArr[idx].fd)); + if (POLLOUT & pPollArr[idx].revents && slIt != endW) readyWriteList.push_back(*slIt); + slIt = std::find_if(begE, endE, Socket::FDCompare(pPollArr[idx].fd)); + if (POLLERR & pPollArr[idx].revents && slIt != endE) readyExceptList.push_back(*slIt); + } + std::swap(readList, readyReadList); + std::swap(writeList, readyWriteList); + std::swap(exceptList, readyExceptList); + return readList.size() + writeList.size() + exceptList.size(); + +#else + + fd_set fdRead; + fd_set fdWrite; + fd_set fdExcept; + int nfd = 0; + FD_ZERO(&fdRead); + for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it) + { + poco_socket_t fd = it->sockfd(); + if (fd != POCO_INVALID_SOCKET) + { + if (int(fd) > nfd) + nfd = int(fd); + FD_SET(fd, &fdRead); + } + } + FD_ZERO(&fdWrite); + for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it) + { + poco_socket_t fd = it->sockfd(); + if (fd != POCO_INVALID_SOCKET) + { + if (int(fd) > nfd) + nfd = int(fd); + FD_SET(fd, &fdWrite); + } + } + FD_ZERO(&fdExcept); + for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it) + { + poco_socket_t fd = it->sockfd(); + if (fd != POCO_INVALID_SOCKET) + { + if (int(fd) > nfd) + nfd = int(fd); + FD_SET(fd, &fdExcept); + } + } + if (nfd == 0) return 0; + Poco::Timespan remainingTime(timeout); + int rc; + do + { + struct timeval tv; + tv.tv_sec = (long) remainingTime.totalSeconds(); + tv.tv_usec = (long) remainingTime.useconds(); + Poco::Timestamp start; + rc = ::select(nfd + 1, &fdRead, &fdWrite, &fdExcept, &tv); + if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) + { + Poco::Timestamp end; + Poco::Timespan waited = end - start; + if (waited < remainingTime) + remainingTime -= waited; + else + remainingTime = 0; + } + } + while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); + if (rc < 0) SocketImpl::error(); + + SocketList readyReadList; + for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it) + { + poco_socket_t fd = it->sockfd(); + if (fd != POCO_INVALID_SOCKET) + { + if (FD_ISSET(fd, &fdRead)) + readyReadList.push_back(*it); + } + } + std::swap(readList, readyReadList); + SocketList readyWriteList; + for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it) + { + poco_socket_t fd = it->sockfd(); + if (fd != POCO_INVALID_SOCKET) + { + if (FD_ISSET(fd, &fdWrite)) + readyWriteList.push_back(*it); + } + } + std::swap(writeList, readyWriteList); + SocketList readyExceptList; + for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it) + { + poco_socket_t fd = it->sockfd(); + if (fd != POCO_INVALID_SOCKET) + { + if (FD_ISSET(fd, &fdExcept)) + readyExceptList.push_back(*it); + } + } + std::swap(exceptList, readyExceptList); + return rc; + +#endif // POCO_HAVE_FD_EPOLL +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/SocketAddress.cpp b/contrib/libs/poco/Net/src/SocketAddress.cpp index 0782ca3eea..d9a53451df 100644 --- a/contrib/libs/poco/Net/src/SocketAddress.cpp +++ b/contrib/libs/poco/Net/src/SocketAddress.cpp @@ -1,435 +1,435 @@ -// -// SocketAddress.cpp -// -// Library: Net -// Package: NetCore -// Module: SocketAddress -// -// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/SocketAddress.h" -#include "Poco/Net/IPAddress.h" -#include "Poco/Net/NetException.h" -#include "Poco/Net/DNS.h" -#include "Poco/RefCountedObject.h" -#include "Poco/NumberParser.h" -#include "Poco/BinaryReader.h" -#include "Poco/BinaryWriter.h" -#include <algorithm> -#include <cstring> - - -using Poco::RefCountedObject; -using Poco::NumberParser; -using Poco::UInt16; -using Poco::InvalidArgumentException; -using Poco::Net::Impl::SocketAddressImpl; -using Poco::Net::Impl::IPv4SocketAddressImpl; -#ifdef POCO_HAVE_IPv6 -using Poco::Net::Impl::IPv6SocketAddressImpl; -#endif -#ifdef POCO_OS_FAMILY_UNIX -using Poco::Net::Impl::LocalSocketAddressImpl; -#endif - - -namespace Poco { -namespace Net { - - -struct AFLT -{ - bool operator () (const IPAddress& a1, const IPAddress& a2) - { - return a1.af() < a2.af(); - } -}; - - -// -// SocketAddress -// - - -#if !defined(_MSC_VER) || defined(__STDC__) -// Go home MSVC, you're drunk... -// See http://stackoverflow.com/questions/5899857/multiple-definition-error-for-static-const-class-members -const SocketAddress::Family SocketAddress::IPv4; -#if defined(POCO_HAVE_IPv6) -const SocketAddress::Family SocketAddress::IPv6; -#endif -#if defined(POCO_OS_FAMILY_UNIX) -const SocketAddress::Family SocketAddress::UNIX_LOCAL; -#endif -#endif - - -SocketAddress::SocketAddress() -{ - newIPv4(); -} - - -SocketAddress::SocketAddress(Family fam) -{ - init(IPAddress(fam), 0); -} - - -SocketAddress::SocketAddress(const IPAddress& hostAddress, Poco::UInt16 portNumber) -{ - init(hostAddress, portNumber); -} - - -SocketAddress::SocketAddress(Poco::UInt16 portNumber) -{ - init(IPAddress(), portNumber); -} - - -SocketAddress::SocketAddress(Family fam, Poco::UInt16 portNumber) -{ - init(IPAddress(fam), portNumber); -} - - -SocketAddress::SocketAddress(const std::string& hostAddress, Poco::UInt16 portNumber) -{ - init(hostAddress, portNumber); -} - - -SocketAddress::SocketAddress(Family fam, const std::string& hostAddress, Poco::UInt16 portNumber) -{ - init(fam, hostAddress, portNumber); -} - - -SocketAddress::SocketAddress(const std::string& hostAddress, const std::string& portNumber) -{ - init(hostAddress, resolveService(portNumber)); -} - - -SocketAddress::SocketAddress(Family fam, const std::string& hostAddress, const std::string& portNumber) -{ - init(fam, hostAddress, resolveService(portNumber)); -} - - -SocketAddress::SocketAddress(Family fam, const std::string& addr) -{ - init(fam, addr); -} - - -SocketAddress::SocketAddress(const std::string& hostAndPort) -{ - init(hostAndPort); -} - - -SocketAddress::SocketAddress(const SocketAddress& socketAddress) -{ - if (socketAddress.family() == IPv4) - newIPv4(reinterpret_cast<const sockaddr_in*>(socketAddress.addr())); -#if defined(POCO_HAVE_IPv6) - else if (socketAddress.family() == IPv6) - newIPv6(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr())); -#endif -#if defined(POCO_OS_FAMILY_UNIX) - else if (socketAddress.family() == UNIX_LOCAL) - newLocal(reinterpret_cast<const sockaddr_un*>(socketAddress.addr())); -#endif -} - - -SocketAddress::SocketAddress(const struct sockaddr* sockAddr, poco_socklen_t length) -{ - if (length == sizeof(struct sockaddr_in) && sockAddr->sa_family == AF_INET) - newIPv4(reinterpret_cast<const struct sockaddr_in*>(sockAddr)); -#if defined(POCO_HAVE_IPv6) - else if (length == sizeof(struct sockaddr_in6) && sockAddr->sa_family == AF_INET6) - newIPv6(reinterpret_cast<const struct sockaddr_in6*>(sockAddr)); -#endif -#if defined(POCO_OS_FAMILY_UNIX) - else if (length > 0 && length <= sizeof(struct sockaddr_un) && sockAddr->sa_family == AF_UNIX) - newLocal(reinterpret_cast<const sockaddr_un*>(sockAddr)); -#endif - else throw Poco::InvalidArgumentException("Invalid address length or family passed to SocketAddress()"); -} - - -SocketAddress::~SocketAddress() -{ -} - - -bool SocketAddress::operator < (const SocketAddress& socketAddress) const -{ - if (family() < socketAddress.family()) return true; - if (family() > socketAddress.family()) return false; -#if defined(POCO_OS_FAMILY_UNIX) - if (family() == UNIX_LOCAL) return toString() < socketAddress.toString(); -#endif - if (host() < socketAddress.host()) return true; - if (host() > socketAddress.host()) return false; - return (port() < socketAddress.port()); -} - - -SocketAddress& SocketAddress::operator = (const SocketAddress& socketAddress) -{ - if (&socketAddress != this) - { - if (socketAddress.family() == IPv4) - newIPv4(reinterpret_cast<const sockaddr_in*>(socketAddress.addr())); -#if defined(POCO_HAVE_IPv6) - else if (socketAddress.family() == IPv6) - newIPv6(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr())); -#endif -#if defined(POCO_OS_FAMILY_UNIX) - else if (socketAddress.family() == UNIX_LOCAL) - newLocal(reinterpret_cast<const sockaddr_un*>(socketAddress.addr())); -#endif - } - return *this; -} - - -IPAddress SocketAddress::host() const -{ - return pImpl()->host(); -} - - -Poco::UInt16 SocketAddress::port() const -{ - return ntohs(pImpl()->port()); -} - - -poco_socklen_t SocketAddress::length() const -{ - return pImpl()->length(); -} - - -const struct sockaddr* SocketAddress::addr() const -{ - return pImpl()->addr(); -} - - -int SocketAddress::af() const -{ - return pImpl()->af(); -} - - -SocketAddress::Family SocketAddress::family() const -{ - return static_cast<Family>(pImpl()->family()); -} - - -std::string SocketAddress::toString() const -{ - return pImpl()->toString(); -} - - -void SocketAddress::init(const IPAddress& hostAddress, Poco::UInt16 portNumber) -{ - if (hostAddress.family() == IPAddress::IPv4) - newIPv4(hostAddress, portNumber); -#if defined(POCO_HAVE_IPv6) - else if (hostAddress.family() == IPAddress::IPv6) - newIPv6(hostAddress, portNumber); -#endif - else throw Poco::NotImplementedException("unsupported IP address family"); -} - - -void SocketAddress::init(const std::string& hostAddress, Poco::UInt16 portNumber) -{ - IPAddress ip; - if (IPAddress::tryParse(hostAddress, ip)) - { - init(ip, portNumber); - } - else - { - HostEntry he = DNS::hostByName(hostAddress); - HostEntry::AddressList addresses = he.addresses(); - if (addresses.size() > 0) - { -#if defined(POCO_HAVE_IPv6) && defined(POCO_SOCKETADDRESS_PREFER_IPv4) - // if we get both IPv4 and IPv6 addresses, prefer IPv4 - std::stable_sort(addresses.begin(), addresses.end(), AFLT()); -#endif - init(addresses[0], portNumber); - } - else throw HostNotFoundException("No address found for host", hostAddress); - } -} - - -void SocketAddress::init(Family fam, const std::string& hostAddress, Poco::UInt16 portNumber) -{ - IPAddress ip; - if (IPAddress::tryParse(hostAddress, ip)) - { - if (ip.family() != fam) throw AddressFamilyMismatchException(hostAddress); - init(ip, portNumber); - } - else - { - HostEntry he = DNS::hostByName(hostAddress); - HostEntry::AddressList addresses = he.addresses(); - if (addresses.size() > 0) - { - for (HostEntry::AddressList::const_iterator it = addresses.begin(); it != addresses.end(); ++it) - { - if (it->family() == fam) - { - init(*it, portNumber); - return; - } - } - throw AddressFamilyMismatchException(hostAddress); - } - else throw HostNotFoundException("No address found for host", hostAddress); - } -} - - -void SocketAddress::init(Family fam, const std::string& address) -{ -#if defined(POCO_OS_FAMILY_UNIX) - if (fam == UNIX_LOCAL) - { - newLocal(address); - } - else -#endif - { - std::string host; - std::string port; - std::string::const_iterator it = address.begin(); - std::string::const_iterator end = address.end(); - - if (*it == '[') - { - ++it; - while (it != end && *it != ']') host += *it++; - if (it == end) throw InvalidArgumentException("Malformed IPv6 address"); - ++it; - } - else - { - while (it != end && *it != ':') host += *it++; - } - if (it != end && *it == ':') - { - ++it; - while (it != end) port += *it++; - } - else throw InvalidArgumentException("Missing port number"); - init(fam, host, resolveService(port)); - } -} - - -void SocketAddress::init(const std::string& hostAndPort) -{ - poco_assert (!hostAndPort.empty()); - - std::string host; - std::string port; - std::string::const_iterator it = hostAndPort.begin(); - std::string::const_iterator end = hostAndPort.end(); - -#if defined(POCO_OS_FAMILY_UNIX) - if (*it == '/') - { - newLocal(hostAndPort); - return; - } -#endif - if (*it == '[') - { - ++it; - while (it != end && *it != ']') host += *it++; - if (it == end) throw InvalidArgumentException("Malformed IPv6 address"); - ++it; - } - else - { - while (it != end && *it != ':') host += *it++; - } - if (it != end && *it == ':') - { - ++it; - while (it != end) port += *it++; - } - else throw InvalidArgumentException("Missing port number"); - init(host, resolveService(port)); -} - - -Poco::UInt16 SocketAddress::resolveService(const std::string& service) -{ - unsigned port; - if (NumberParser::tryParseUnsigned(service, port) && port <= 0xFFFF) - { - return (UInt16) port; - } - else - { -#if defined(POCO_VXWORKS) - throw ServiceNotFoundException(service); -#else - struct servent* se = getservbyname(service.c_str(), NULL); - if (se) - return ntohs(se->s_port); - else - throw ServiceNotFoundException(service); -#endif - } -} - - -} } // namespace Poco::Net - - -Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::SocketAddress& value) -{ - writer << value.host(); - writer << value.port(); - return writer; -} - - -Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::SocketAddress& value) -{ - Poco::Net::IPAddress host; - reader >> host; - Poco::UInt16 port; - reader >> port; - value = Poco::Net::SocketAddress(host, port); - return reader; -} - - -std::ostream& operator << (std::ostream& ostr, const Poco::Net::SocketAddress& address) -{ - ostr << address.toString(); - return ostr; -} +// +// SocketAddress.cpp +// +// Library: Net +// Package: NetCore +// Module: SocketAddress +// +// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/SocketAddress.h" +#include "Poco/Net/IPAddress.h" +#include "Poco/Net/NetException.h" +#include "Poco/Net/DNS.h" +#include "Poco/RefCountedObject.h" +#include "Poco/NumberParser.h" +#include "Poco/BinaryReader.h" +#include "Poco/BinaryWriter.h" +#include <algorithm> +#include <cstring> + + +using Poco::RefCountedObject; +using Poco::NumberParser; +using Poco::UInt16; +using Poco::InvalidArgumentException; +using Poco::Net::Impl::SocketAddressImpl; +using Poco::Net::Impl::IPv4SocketAddressImpl; +#ifdef POCO_HAVE_IPv6 +using Poco::Net::Impl::IPv6SocketAddressImpl; +#endif +#ifdef POCO_OS_FAMILY_UNIX +using Poco::Net::Impl::LocalSocketAddressImpl; +#endif + + +namespace Poco { +namespace Net { + + +struct AFLT +{ + bool operator () (const IPAddress& a1, const IPAddress& a2) + { + return a1.af() < a2.af(); + } +}; + + +// +// SocketAddress +// + + +#if !defined(_MSC_VER) || defined(__STDC__) +// Go home MSVC, you're drunk... +// See http://stackoverflow.com/questions/5899857/multiple-definition-error-for-static-const-class-members +const SocketAddress::Family SocketAddress::IPv4; +#if defined(POCO_HAVE_IPv6) +const SocketAddress::Family SocketAddress::IPv6; +#endif +#if defined(POCO_OS_FAMILY_UNIX) +const SocketAddress::Family SocketAddress::UNIX_LOCAL; +#endif +#endif + + +SocketAddress::SocketAddress() +{ + newIPv4(); +} + + +SocketAddress::SocketAddress(Family fam) +{ + init(IPAddress(fam), 0); +} + + +SocketAddress::SocketAddress(const IPAddress& hostAddress, Poco::UInt16 portNumber) +{ + init(hostAddress, portNumber); +} + + +SocketAddress::SocketAddress(Poco::UInt16 portNumber) +{ + init(IPAddress(), portNumber); +} + + +SocketAddress::SocketAddress(Family fam, Poco::UInt16 portNumber) +{ + init(IPAddress(fam), portNumber); +} + + +SocketAddress::SocketAddress(const std::string& hostAddress, Poco::UInt16 portNumber) +{ + init(hostAddress, portNumber); +} + + +SocketAddress::SocketAddress(Family fam, const std::string& hostAddress, Poco::UInt16 portNumber) +{ + init(fam, hostAddress, portNumber); +} + + +SocketAddress::SocketAddress(const std::string& hostAddress, const std::string& portNumber) +{ + init(hostAddress, resolveService(portNumber)); +} + + +SocketAddress::SocketAddress(Family fam, const std::string& hostAddress, const std::string& portNumber) +{ + init(fam, hostAddress, resolveService(portNumber)); +} + + +SocketAddress::SocketAddress(Family fam, const std::string& addr) +{ + init(fam, addr); +} + + +SocketAddress::SocketAddress(const std::string& hostAndPort) +{ + init(hostAndPort); +} + + +SocketAddress::SocketAddress(const SocketAddress& socketAddress) +{ + if (socketAddress.family() == IPv4) + newIPv4(reinterpret_cast<const sockaddr_in*>(socketAddress.addr())); +#if defined(POCO_HAVE_IPv6) + else if (socketAddress.family() == IPv6) + newIPv6(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr())); +#endif +#if defined(POCO_OS_FAMILY_UNIX) + else if (socketAddress.family() == UNIX_LOCAL) + newLocal(reinterpret_cast<const sockaddr_un*>(socketAddress.addr())); +#endif +} + + +SocketAddress::SocketAddress(const struct sockaddr* sockAddr, poco_socklen_t length) +{ + if (length == sizeof(struct sockaddr_in) && sockAddr->sa_family == AF_INET) + newIPv4(reinterpret_cast<const struct sockaddr_in*>(sockAddr)); +#if defined(POCO_HAVE_IPv6) + else if (length == sizeof(struct sockaddr_in6) && sockAddr->sa_family == AF_INET6) + newIPv6(reinterpret_cast<const struct sockaddr_in6*>(sockAddr)); +#endif +#if defined(POCO_OS_FAMILY_UNIX) + else if (length > 0 && length <= sizeof(struct sockaddr_un) && sockAddr->sa_family == AF_UNIX) + newLocal(reinterpret_cast<const sockaddr_un*>(sockAddr)); +#endif + else throw Poco::InvalidArgumentException("Invalid address length or family passed to SocketAddress()"); +} + + +SocketAddress::~SocketAddress() +{ +} + + +bool SocketAddress::operator < (const SocketAddress& socketAddress) const +{ + if (family() < socketAddress.family()) return true; + if (family() > socketAddress.family()) return false; +#if defined(POCO_OS_FAMILY_UNIX) + if (family() == UNIX_LOCAL) return toString() < socketAddress.toString(); +#endif + if (host() < socketAddress.host()) return true; + if (host() > socketAddress.host()) return false; + return (port() < socketAddress.port()); +} + + +SocketAddress& SocketAddress::operator = (const SocketAddress& socketAddress) +{ + if (&socketAddress != this) + { + if (socketAddress.family() == IPv4) + newIPv4(reinterpret_cast<const sockaddr_in*>(socketAddress.addr())); +#if defined(POCO_HAVE_IPv6) + else if (socketAddress.family() == IPv6) + newIPv6(reinterpret_cast<const sockaddr_in6*>(socketAddress.addr())); +#endif +#if defined(POCO_OS_FAMILY_UNIX) + else if (socketAddress.family() == UNIX_LOCAL) + newLocal(reinterpret_cast<const sockaddr_un*>(socketAddress.addr())); +#endif + } + return *this; +} + + +IPAddress SocketAddress::host() const +{ + return pImpl()->host(); +} + + +Poco::UInt16 SocketAddress::port() const +{ + return ntohs(pImpl()->port()); +} + + +poco_socklen_t SocketAddress::length() const +{ + return pImpl()->length(); +} + + +const struct sockaddr* SocketAddress::addr() const +{ + return pImpl()->addr(); +} + + +int SocketAddress::af() const +{ + return pImpl()->af(); +} + + +SocketAddress::Family SocketAddress::family() const +{ + return static_cast<Family>(pImpl()->family()); +} + + +std::string SocketAddress::toString() const +{ + return pImpl()->toString(); +} + + +void SocketAddress::init(const IPAddress& hostAddress, Poco::UInt16 portNumber) +{ + if (hostAddress.family() == IPAddress::IPv4) + newIPv4(hostAddress, portNumber); +#if defined(POCO_HAVE_IPv6) + else if (hostAddress.family() == IPAddress::IPv6) + newIPv6(hostAddress, portNumber); +#endif + else throw Poco::NotImplementedException("unsupported IP address family"); +} + + +void SocketAddress::init(const std::string& hostAddress, Poco::UInt16 portNumber) +{ + IPAddress ip; + if (IPAddress::tryParse(hostAddress, ip)) + { + init(ip, portNumber); + } + else + { + HostEntry he = DNS::hostByName(hostAddress); + HostEntry::AddressList addresses = he.addresses(); + if (addresses.size() > 0) + { +#if defined(POCO_HAVE_IPv6) && defined(POCO_SOCKETADDRESS_PREFER_IPv4) + // if we get both IPv4 and IPv6 addresses, prefer IPv4 + std::stable_sort(addresses.begin(), addresses.end(), AFLT()); +#endif + init(addresses[0], portNumber); + } + else throw HostNotFoundException("No address found for host", hostAddress); + } +} + + +void SocketAddress::init(Family fam, const std::string& hostAddress, Poco::UInt16 portNumber) +{ + IPAddress ip; + if (IPAddress::tryParse(hostAddress, ip)) + { + if (ip.family() != fam) throw AddressFamilyMismatchException(hostAddress); + init(ip, portNumber); + } + else + { + HostEntry he = DNS::hostByName(hostAddress); + HostEntry::AddressList addresses = he.addresses(); + if (addresses.size() > 0) + { + for (HostEntry::AddressList::const_iterator it = addresses.begin(); it != addresses.end(); ++it) + { + if (it->family() == fam) + { + init(*it, portNumber); + return; + } + } + throw AddressFamilyMismatchException(hostAddress); + } + else throw HostNotFoundException("No address found for host", hostAddress); + } +} + + +void SocketAddress::init(Family fam, const std::string& address) +{ +#if defined(POCO_OS_FAMILY_UNIX) + if (fam == UNIX_LOCAL) + { + newLocal(address); + } + else +#endif + { + std::string host; + std::string port; + std::string::const_iterator it = address.begin(); + std::string::const_iterator end = address.end(); + + if (*it == '[') + { + ++it; + while (it != end && *it != ']') host += *it++; + if (it == end) throw InvalidArgumentException("Malformed IPv6 address"); + ++it; + } + else + { + while (it != end && *it != ':') host += *it++; + } + if (it != end && *it == ':') + { + ++it; + while (it != end) port += *it++; + } + else throw InvalidArgumentException("Missing port number"); + init(fam, host, resolveService(port)); + } +} + + +void SocketAddress::init(const std::string& hostAndPort) +{ + poco_assert (!hostAndPort.empty()); + + std::string host; + std::string port; + std::string::const_iterator it = hostAndPort.begin(); + std::string::const_iterator end = hostAndPort.end(); + +#if defined(POCO_OS_FAMILY_UNIX) + if (*it == '/') + { + newLocal(hostAndPort); + return; + } +#endif + if (*it == '[') + { + ++it; + while (it != end && *it != ']') host += *it++; + if (it == end) throw InvalidArgumentException("Malformed IPv6 address"); + ++it; + } + else + { + while (it != end && *it != ':') host += *it++; + } + if (it != end && *it == ':') + { + ++it; + while (it != end) port += *it++; + } + else throw InvalidArgumentException("Missing port number"); + init(host, resolveService(port)); +} + + +Poco::UInt16 SocketAddress::resolveService(const std::string& service) +{ + unsigned port; + if (NumberParser::tryParseUnsigned(service, port) && port <= 0xFFFF) + { + return (UInt16) port; + } + else + { +#if defined(POCO_VXWORKS) + throw ServiceNotFoundException(service); +#else + struct servent* se = getservbyname(service.c_str(), NULL); + if (se) + return ntohs(se->s_port); + else + throw ServiceNotFoundException(service); +#endif + } +} + + +} } // namespace Poco::Net + + +Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::SocketAddress& value) +{ + writer << value.host(); + writer << value.port(); + return writer; +} + + +Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::SocketAddress& value) +{ + Poco::Net::IPAddress host; + reader >> host; + Poco::UInt16 port; + reader >> port; + value = Poco::Net::SocketAddress(host, port); + return reader; +} + + +std::ostream& operator << (std::ostream& ostr, const Poco::Net::SocketAddress& address) +{ + ostr << address.toString(); + return ostr; +} diff --git a/contrib/libs/poco/Net/src/SocketAddressImpl.cpp b/contrib/libs/poco/Net/src/SocketAddressImpl.cpp index 57690170f2..0c1b0f28d7 100644 --- a/contrib/libs/poco/Net/src/SocketAddressImpl.cpp +++ b/contrib/libs/poco/Net/src/SocketAddressImpl.cpp @@ -1,184 +1,184 @@ -// -// SocketAddressImpl.cpp -// -// Library: Net -// Package: NetCore -// Module: SocketAddressImpl -// -// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/SocketAddressImpl.h" -#include "Poco/Net/SocketDefs.h" -#include "Poco/NumberFormatter.h" -#include <cstring> - - -namespace Poco { -namespace Net { -namespace Impl { - - -// -// SocketAddressImpl -// - - -SocketAddressImpl::SocketAddressImpl() -{ -} - - -SocketAddressImpl::~SocketAddressImpl() -{ -} - - -// -// IPv4SocketAddressImpl -// - - -IPv4SocketAddressImpl::IPv4SocketAddressImpl() -{ - std::memset(&_addr, 0, sizeof(_addr)); - _addr.sin_family = AF_INET; - poco_set_sin_len(&_addr); -} - - -IPv4SocketAddressImpl::IPv4SocketAddressImpl(const struct sockaddr_in* addr) -{ - std::memcpy(&_addr, addr, sizeof(_addr)); -} - - -IPv4SocketAddressImpl::IPv4SocketAddressImpl(const void* addr, UInt16 port) -{ - std::memset(&_addr, 0, sizeof(_addr)); - _addr.sin_family = AF_INET; - poco_set_sin_len(&_addr); - std::memcpy(&_addr.sin_addr, addr, sizeof(_addr.sin_addr)); - _addr.sin_port = port; -} - - -std::string IPv4SocketAddressImpl::toString() const -{ - std::string result; - result.append(host().toString()); - result.append(":"); - NumberFormatter::append(result, ntohs(port())); - return result; -} - - -#if defined(POCO_HAVE_IPv6) - - -// -// IPv6SocketAddressImpl -// - - -IPv6SocketAddressImpl::IPv6SocketAddressImpl(const struct sockaddr_in6* addr) -{ - std::memcpy(&_addr, addr, sizeof(_addr)); -} - - -IPv6SocketAddressImpl::IPv6SocketAddressImpl(const void* addr, UInt16 port) -{ - std::memset(&_addr, 0, sizeof(_addr)); - _addr.sin6_family = AF_INET6; - poco_set_sin6_len(&_addr); - std::memcpy(&_addr.sin6_addr, addr, sizeof(_addr.sin6_addr)); - _addr.sin6_port = port; -} - - -IPv6SocketAddressImpl::IPv6SocketAddressImpl(const void* addr, UInt16 port, UInt32 scope) -{ - std::memset(&_addr, 0, sizeof(_addr)); - _addr.sin6_family = AF_INET6; - poco_set_sin6_len(&_addr); - std::memcpy(&_addr.sin6_addr, addr, sizeof(_addr.sin6_addr)); - _addr.sin6_port = port; - _addr.sin6_scope_id = scope; -} - - -std::string IPv6SocketAddressImpl::toString() const -{ - std::string result; - result.append("["); - result.append(host().toString()); - result.append("]"); - result.append(":"); - NumberFormatter::append(result, ntohs(port())); - return result; -} - - -#endif // POCO_HAVE_IPv6 - - -#if defined(POCO_OS_FAMILY_UNIX) - - -// -// LocalSocketAddressImpl -// - - -LocalSocketAddressImpl::LocalSocketAddressImpl(const struct sockaddr_un* addr) -{ - _pAddr = new sockaddr_un; - std::memcpy(_pAddr, addr, sizeof(struct sockaddr_un)); -} - - -LocalSocketAddressImpl::LocalSocketAddressImpl(const char* path) -{ - poco_assert (std::strlen(path) < sizeof(_pAddr->sun_path)); - - _pAddr = new sockaddr_un; - poco_set_sun_len(_pAddr, std::strlen(path) + sizeof(struct sockaddr_un) - sizeof(_pAddr->sun_path) + 1); - _pAddr->sun_family = AF_UNIX; - std::strcpy(_pAddr->sun_path, path); -} - - -LocalSocketAddressImpl::LocalSocketAddressImpl(const char* path, std::size_t length) -{ - poco_assert (length < sizeof(_pAddr->sun_path)); - - _pAddr = new sockaddr_un; - poco_set_sun_len(_pAddr, length + sizeof(struct sockaddr_un) - sizeof(_pAddr->sun_path) + 1); - _pAddr->sun_family = AF_UNIX; - std::memcpy(_pAddr->sun_path, path, length); - _pAddr->sun_path[length] = 0; -} - - -LocalSocketAddressImpl::~LocalSocketAddressImpl() -{ - delete _pAddr; -} - - -std::string LocalSocketAddressImpl::toString() const -{ - std::string result(path()); - return result; -} - - -#endif // POCO_OS_FAMILY_UNIX - - -} } } // namespace Poco::Net::Impl +// +// SocketAddressImpl.cpp +// +// Library: Net +// Package: NetCore +// Module: SocketAddressImpl +// +// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/SocketAddressImpl.h" +#include "Poco/Net/SocketDefs.h" +#include "Poco/NumberFormatter.h" +#include <cstring> + + +namespace Poco { +namespace Net { +namespace Impl { + + +// +// SocketAddressImpl +// + + +SocketAddressImpl::SocketAddressImpl() +{ +} + + +SocketAddressImpl::~SocketAddressImpl() +{ +} + + +// +// IPv4SocketAddressImpl +// + + +IPv4SocketAddressImpl::IPv4SocketAddressImpl() +{ + std::memset(&_addr, 0, sizeof(_addr)); + _addr.sin_family = AF_INET; + poco_set_sin_len(&_addr); +} + + +IPv4SocketAddressImpl::IPv4SocketAddressImpl(const struct sockaddr_in* addr) +{ + std::memcpy(&_addr, addr, sizeof(_addr)); +} + + +IPv4SocketAddressImpl::IPv4SocketAddressImpl(const void* addr, UInt16 port) +{ + std::memset(&_addr, 0, sizeof(_addr)); + _addr.sin_family = AF_INET; + poco_set_sin_len(&_addr); + std::memcpy(&_addr.sin_addr, addr, sizeof(_addr.sin_addr)); + _addr.sin_port = port; +} + + +std::string IPv4SocketAddressImpl::toString() const +{ + std::string result; + result.append(host().toString()); + result.append(":"); + NumberFormatter::append(result, ntohs(port())); + return result; +} + + +#if defined(POCO_HAVE_IPv6) + + +// +// IPv6SocketAddressImpl +// + + +IPv6SocketAddressImpl::IPv6SocketAddressImpl(const struct sockaddr_in6* addr) +{ + std::memcpy(&_addr, addr, sizeof(_addr)); +} + + +IPv6SocketAddressImpl::IPv6SocketAddressImpl(const void* addr, UInt16 port) +{ + std::memset(&_addr, 0, sizeof(_addr)); + _addr.sin6_family = AF_INET6; + poco_set_sin6_len(&_addr); + std::memcpy(&_addr.sin6_addr, addr, sizeof(_addr.sin6_addr)); + _addr.sin6_port = port; +} + + +IPv6SocketAddressImpl::IPv6SocketAddressImpl(const void* addr, UInt16 port, UInt32 scope) +{ + std::memset(&_addr, 0, sizeof(_addr)); + _addr.sin6_family = AF_INET6; + poco_set_sin6_len(&_addr); + std::memcpy(&_addr.sin6_addr, addr, sizeof(_addr.sin6_addr)); + _addr.sin6_port = port; + _addr.sin6_scope_id = scope; +} + + +std::string IPv6SocketAddressImpl::toString() const +{ + std::string result; + result.append("["); + result.append(host().toString()); + result.append("]"); + result.append(":"); + NumberFormatter::append(result, ntohs(port())); + return result; +} + + +#endif // POCO_HAVE_IPv6 + + +#if defined(POCO_OS_FAMILY_UNIX) + + +// +// LocalSocketAddressImpl +// + + +LocalSocketAddressImpl::LocalSocketAddressImpl(const struct sockaddr_un* addr) +{ + _pAddr = new sockaddr_un; + std::memcpy(_pAddr, addr, sizeof(struct sockaddr_un)); +} + + +LocalSocketAddressImpl::LocalSocketAddressImpl(const char* path) +{ + poco_assert (std::strlen(path) < sizeof(_pAddr->sun_path)); + + _pAddr = new sockaddr_un; + poco_set_sun_len(_pAddr, std::strlen(path) + sizeof(struct sockaddr_un) - sizeof(_pAddr->sun_path) + 1); + _pAddr->sun_family = AF_UNIX; + std::strcpy(_pAddr->sun_path, path); +} + + +LocalSocketAddressImpl::LocalSocketAddressImpl(const char* path, std::size_t length) +{ + poco_assert (length < sizeof(_pAddr->sun_path)); + + _pAddr = new sockaddr_un; + poco_set_sun_len(_pAddr, length + sizeof(struct sockaddr_un) - sizeof(_pAddr->sun_path) + 1); + _pAddr->sun_family = AF_UNIX; + std::memcpy(_pAddr->sun_path, path, length); + _pAddr->sun_path[length] = 0; +} + + +LocalSocketAddressImpl::~LocalSocketAddressImpl() +{ + delete _pAddr; +} + + +std::string LocalSocketAddressImpl::toString() const +{ + std::string result(path()); + return result; +} + + +#endif // POCO_OS_FAMILY_UNIX + + +} } } // namespace Poco::Net::Impl diff --git a/contrib/libs/poco/Net/src/SocketImpl.cpp b/contrib/libs/poco/Net/src/SocketImpl.cpp index 92c664ec82..45bb353a44 100644 --- a/contrib/libs/poco/Net/src/SocketImpl.cpp +++ b/contrib/libs/poco/Net/src/SocketImpl.cpp @@ -1,1134 +1,1134 @@ -// -// SocketImpl.cpp -// -// Library: Net -// Package: Sockets -// Module: SocketImpl -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/SocketImpl.h" -#include "Poco/Net/NetException.h" -#include "Poco/Net/StreamSocketImpl.h" -#include "Poco/NumberFormatter.h" -#include "Poco/Timestamp.h" -#include <string.h> // FD_SET needs memset on some platforms, so we can't use <cstring> - - -#if defined(_WIN32) && _WIN32_WINNT >= 0x0600 -#ifndef POCO_HAVE_FD_POLL -#define POCO_HAVE_FD_POLL 1 -#endif -#elif defined(POCO_OS_FAMILY_BSD) -#ifndef POCO_HAVE_FD_POLL -#define POCO_HAVE_FD_POLL 1 -#endif -#endif - - -#if defined(POCO_HAVE_FD_EPOLL) -#include <sys/epoll.h> -#elif defined(POCO_HAVE_FD_POLL) -#ifndef _WIN32 -#include <poll.h> -#endif -#endif - - -#if defined(sun) || defined(__sun) || defined(__sun__) -#include <unistd.h> -#include <stropts.h> -#endif - - -#ifdef POCO_OS_FAMILY_WINDOWS -#include <windows.h> -#endif - - -using Poco::IOException; -using Poco::TimeoutException; -using Poco::InvalidArgumentException; -using Poco::NumberFormatter; -using Poco::Timespan; - - -namespace Poco { -namespace Net { - - -bool checkIsBrokenTimeout() -{ -#if defined(POCO_BROKEN_TIMEOUTS) - return true; -#elif defined(POCO_OS_FAMILY_WINDOWS) - // on Windows 7 and lower, socket timeouts have a minimum of 500ms, use poll for timeouts on this case - // https://social.msdn.microsoft.com/Forums/en-US/76620f6d-22b1-4872-aaf0-833204f3f867/minimum-timeout-value-for-sorcvtimeo - OSVERSIONINFO vi; - vi.dwOSVersionInfoSize = sizeof(vi); - if (GetVersionEx(&vi) == 0) return true; //throw SystemException("Cannot get OS version information"); - return vi.dwMajorVersion < 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion < 2); -#else - return false; -#endif -} - - -SocketImpl::SocketImpl(): - _sockfd(POCO_INVALID_SOCKET), +// +// SocketImpl.cpp +// +// Library: Net +// Package: Sockets +// Module: SocketImpl +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/SocketImpl.h" +#include "Poco/Net/NetException.h" +#include "Poco/Net/StreamSocketImpl.h" +#include "Poco/NumberFormatter.h" +#include "Poco/Timestamp.h" +#include <string.h> // FD_SET needs memset on some platforms, so we can't use <cstring> + + +#if defined(_WIN32) && _WIN32_WINNT >= 0x0600 +#ifndef POCO_HAVE_FD_POLL +#define POCO_HAVE_FD_POLL 1 +#endif +#elif defined(POCO_OS_FAMILY_BSD) +#ifndef POCO_HAVE_FD_POLL +#define POCO_HAVE_FD_POLL 1 +#endif +#endif + + +#if defined(POCO_HAVE_FD_EPOLL) +#include <sys/epoll.h> +#elif defined(POCO_HAVE_FD_POLL) +#ifndef _WIN32 +#include <poll.h> +#endif +#endif + + +#if defined(sun) || defined(__sun) || defined(__sun__) +#include <unistd.h> +#include <stropts.h> +#endif + + +#ifdef POCO_OS_FAMILY_WINDOWS +#include <windows.h> +#endif + + +using Poco::IOException; +using Poco::TimeoutException; +using Poco::InvalidArgumentException; +using Poco::NumberFormatter; +using Poco::Timespan; + + +namespace Poco { +namespace Net { + + +bool checkIsBrokenTimeout() +{ +#if defined(POCO_BROKEN_TIMEOUTS) + return true; +#elif defined(POCO_OS_FAMILY_WINDOWS) + // on Windows 7 and lower, socket timeouts have a minimum of 500ms, use poll for timeouts on this case + // https://social.msdn.microsoft.com/Forums/en-US/76620f6d-22b1-4872-aaf0-833204f3f867/minimum-timeout-value-for-sorcvtimeo + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (GetVersionEx(&vi) == 0) return true; //throw SystemException("Cannot get OS version information"); + return vi.dwMajorVersion < 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion < 2); +#else + return false; +#endif +} + + +SocketImpl::SocketImpl(): + _sockfd(POCO_INVALID_SOCKET), + _blocking(true), + _isBrokenTimeout(checkIsBrokenTimeout()) +{ +} + + +SocketImpl::SocketImpl(poco_socket_t sockfd): + _sockfd(sockfd), _blocking(true), - _isBrokenTimeout(checkIsBrokenTimeout()) -{ -} - - -SocketImpl::SocketImpl(poco_socket_t sockfd): - _sockfd(sockfd), - _blocking(true), - _isBrokenTimeout(checkIsBrokenTimeout()) -{ -} - - -SocketImpl::~SocketImpl() -{ - close(); -} - - -SocketImpl* SocketImpl::acceptConnection(SocketAddress& clientAddr) -{ - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - - sockaddr_storage buffer; - struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(&buffer); - poco_socklen_t saLen = sizeof(buffer); - poco_socket_t sd; - do - { - sd = ::accept(_sockfd, pSA, &saLen); - } - while (sd == POCO_INVALID_SOCKET && lastError() == POCO_EINTR); - if (sd != POCO_INVALID_SOCKET) - { - clientAddr = SocketAddress(pSA, saLen); - return new StreamSocketImpl(sd); - } - error(); // will throw - return 0; -} - - -void SocketImpl::connect(const SocketAddress& address) -{ - if (_sockfd == POCO_INVALID_SOCKET) - { - init(address.af()); - } - int rc; - do - { -#if defined(POCO_VXWORKS) - rc = ::connect(_sockfd, (sockaddr*) address.addr(), address.length()); -#else - rc = ::connect(_sockfd, address.addr(), address.length()); -#endif - } - while (rc != 0 && lastError() == POCO_EINTR); + _isBrokenTimeout(checkIsBrokenTimeout()) +{ +} + + +SocketImpl::~SocketImpl() +{ + close(); +} + + +SocketImpl* SocketImpl::acceptConnection(SocketAddress& clientAddr) +{ + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + + sockaddr_storage buffer; + struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(&buffer); + poco_socklen_t saLen = sizeof(buffer); + poco_socket_t sd; + do + { + sd = ::accept(_sockfd, pSA, &saLen); + } + while (sd == POCO_INVALID_SOCKET && lastError() == POCO_EINTR); + if (sd != POCO_INVALID_SOCKET) + { + clientAddr = SocketAddress(pSA, saLen); + return new StreamSocketImpl(sd); + } + error(); // will throw + return 0; +} + + +void SocketImpl::connect(const SocketAddress& address) +{ + if (_sockfd == POCO_INVALID_SOCKET) + { + init(address.af()); + } + int rc; + do + { +#if defined(POCO_VXWORKS) + rc = ::connect(_sockfd, (sockaddr*) address.addr(), address.length()); +#else + rc = ::connect(_sockfd, address.addr(), address.length()); +#endif + } + while (rc != 0 && lastError() == POCO_EINTR); + if (rc != 0) + { + int err = lastError(); + error(err, address.toString()); + } +} + + +void SocketImpl::connect(const SocketAddress& address, const Poco::Timespan& timeout) +{ + if (_sockfd == POCO_INVALID_SOCKET) + { + init(address.af()); + } + setBlocking(false); + try + { +#if defined(POCO_VXWORKS) + int rc = ::connect(_sockfd, (sockaddr*) address.addr(), address.length()); +#else + int rc = ::connect(_sockfd, address.addr(), address.length()); +#endif + if (rc != 0) + { + int err = lastError(); + if (err != POCO_EINPROGRESS && err != POCO_EWOULDBLOCK) + error(err, address.toString()); + if (!poll(timeout, SELECT_READ | SELECT_WRITE | SELECT_ERROR)) + throw Poco::TimeoutException("connect timed out", address.toString()); + err = socketError(); + if (err != 0) error(err); + } + } + catch (Poco::Exception&) + { + setBlocking(true); + throw; + } + setBlocking(true); +} + + +void SocketImpl::connectNB(const SocketAddress& address) +{ + if (_sockfd == POCO_INVALID_SOCKET) + { + init(address.af()); + } + setBlocking(false); +#if defined(POCO_VXWORKS) + int rc = ::connect(_sockfd, (sockaddr*) address.addr(), address.length()); +#else + int rc = ::connect(_sockfd, address.addr(), address.length()); +#endif if (rc != 0) - { - int err = lastError(); - error(err, address.toString()); - } -} - - -void SocketImpl::connect(const SocketAddress& address, const Poco::Timespan& timeout) -{ - if (_sockfd == POCO_INVALID_SOCKET) - { - init(address.af()); - } - setBlocking(false); - try - { -#if defined(POCO_VXWORKS) - int rc = ::connect(_sockfd, (sockaddr*) address.addr(), address.length()); -#else - int rc = ::connect(_sockfd, address.addr(), address.length()); -#endif - if (rc != 0) - { - int err = lastError(); - if (err != POCO_EINPROGRESS && err != POCO_EWOULDBLOCK) - error(err, address.toString()); - if (!poll(timeout, SELECT_READ | SELECT_WRITE | SELECT_ERROR)) - throw Poco::TimeoutException("connect timed out", address.toString()); - err = socketError(); - if (err != 0) error(err); - } - } - catch (Poco::Exception&) - { - setBlocking(true); - throw; - } - setBlocking(true); -} - - -void SocketImpl::connectNB(const SocketAddress& address) -{ - if (_sockfd == POCO_INVALID_SOCKET) - { - init(address.af()); - } - setBlocking(false); -#if defined(POCO_VXWORKS) - int rc = ::connect(_sockfd, (sockaddr*) address.addr(), address.length()); -#else - int rc = ::connect(_sockfd, address.addr(), address.length()); -#endif - if (rc != 0) - { - int err = lastError(); - if (err != POCO_EINPROGRESS && err != POCO_EWOULDBLOCK) - error(err, address.toString()); - } -} - - -void SocketImpl::bind(const SocketAddress& address, bool reuseAddress) -{ - bind(address, reuseAddress, reuseAddress); -} - - -void SocketImpl::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) -{ - if (_sockfd == POCO_INVALID_SOCKET) - { - init(address.af()); - } - if (reuseAddress) - setReuseAddress(true); - if (reusePort) - setReusePort(true); -#if defined(POCO_VXWORKS) - int rc = ::bind(_sockfd, (sockaddr*) address.addr(), address.length()); -#else - int rc = ::bind(_sockfd, address.addr(), address.length()); -#endif - if (rc != 0) error(address.toString()); -} - - -void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only) -{ - bind6(address, reuseAddress, true, ipV6Only); -} - - -void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only) -{ -#if defined(POCO_HAVE_IPv6) - if (address.family() != SocketAddress::IPv6) - throw Poco::InvalidArgumentException("SocketAddress must be an IPv6 address"); - - if (_sockfd == POCO_INVALID_SOCKET) - { - init(address.af()); - } -#ifdef IPV6_V6ONLY - setOption(IPPROTO_IPV6, IPV6_V6ONLY, ipV6Only ? 1 : 0); -#else - if (ipV6Only) throw Poco::NotImplementedException("IPV6_V6ONLY not defined."); -#endif - if (reuseAddress) - setReuseAddress(true); - if (reusePort) - setReusePort(true); - int rc = ::bind(_sockfd, address.addr(), address.length()); - if (rc != 0) error(address.toString()); -#else - throw Poco::NotImplementedException("No IPv6 support available"); -#endif -} - - -void SocketImpl::listen(int backlog) -{ - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - - int rc = ::listen(_sockfd, backlog); - if (rc != 0) error(); -} - - -void SocketImpl::close() -{ - if (_sockfd != POCO_INVALID_SOCKET) - { - poco_closesocket(_sockfd); - _sockfd = POCO_INVALID_SOCKET; - } -} - - -void SocketImpl::shutdownReceive() -{ - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - - int rc = ::shutdown(_sockfd, 0); - if (rc != 0) error(); -} - - -void SocketImpl::shutdownSend() -{ - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - - int rc = ::shutdown(_sockfd, 1); - if (rc != 0) error(); -} - - -void SocketImpl::shutdown() -{ - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - - int rc = ::shutdown(_sockfd, 2); - if (rc != 0) error(); -} - - -int SocketImpl::sendBytes(const void* buffer, int length, int flags) -{ - if (_isBrokenTimeout) - { - if (_sndTimeout.totalMicroseconds() != 0) - { - if (!poll(_sndTimeout, SELECT_WRITE)) - throw TimeoutException(); - } - } - - int rc; - do - { - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - rc = ::send(_sockfd, reinterpret_cast<const char*>(buffer), length, flags); - } - while (_blocking && rc < 0 && lastError() == POCO_EINTR); - if (rc < 0) - { - int err = lastError(); - if (err == POCO_EAGAIN || err == POCO_ETIMEDOUT) - throw TimeoutException(); - else - error(err); - } - return rc; -} - - -int SocketImpl::receiveBytes(void* buffer, int length, int flags) -{ - if (_isBrokenTimeout) - { - if (_recvTimeout.totalMicroseconds() != 0) - { - if (!poll(_recvTimeout, SELECT_READ)) - throw TimeoutException(); - } - } - - int rc; - do - { - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - rc = ::recv(_sockfd, reinterpret_cast<char*>(buffer), length, flags); - } - while (_blocking && rc < 0 && lastError() == POCO_EINTR); + { + int err = lastError(); + if (err != POCO_EINPROGRESS && err != POCO_EWOULDBLOCK) + error(err, address.toString()); + } +} + + +void SocketImpl::bind(const SocketAddress& address, bool reuseAddress) +{ + bind(address, reuseAddress, reuseAddress); +} + + +void SocketImpl::bind(const SocketAddress& address, bool reuseAddress, bool reusePort) +{ + if (_sockfd == POCO_INVALID_SOCKET) + { + init(address.af()); + } + if (reuseAddress) + setReuseAddress(true); + if (reusePort) + setReusePort(true); +#if defined(POCO_VXWORKS) + int rc = ::bind(_sockfd, (sockaddr*) address.addr(), address.length()); +#else + int rc = ::bind(_sockfd, address.addr(), address.length()); +#endif + if (rc != 0) error(address.toString()); +} + + +void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only) +{ + bind6(address, reuseAddress, true, ipV6Only); +} + + +void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only) +{ +#if defined(POCO_HAVE_IPv6) + if (address.family() != SocketAddress::IPv6) + throw Poco::InvalidArgumentException("SocketAddress must be an IPv6 address"); + + if (_sockfd == POCO_INVALID_SOCKET) + { + init(address.af()); + } +#ifdef IPV6_V6ONLY + setOption(IPPROTO_IPV6, IPV6_V6ONLY, ipV6Only ? 1 : 0); +#else + if (ipV6Only) throw Poco::NotImplementedException("IPV6_V6ONLY not defined."); +#endif + if (reuseAddress) + setReuseAddress(true); + if (reusePort) + setReusePort(true); + int rc = ::bind(_sockfd, address.addr(), address.length()); + if (rc != 0) error(address.toString()); +#else + throw Poco::NotImplementedException("No IPv6 support available"); +#endif +} + + +void SocketImpl::listen(int backlog) +{ + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + + int rc = ::listen(_sockfd, backlog); + if (rc != 0) error(); +} + + +void SocketImpl::close() +{ + if (_sockfd != POCO_INVALID_SOCKET) + { + poco_closesocket(_sockfd); + _sockfd = POCO_INVALID_SOCKET; + } +} + + +void SocketImpl::shutdownReceive() +{ + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + + int rc = ::shutdown(_sockfd, 0); + if (rc != 0) error(); +} + + +void SocketImpl::shutdownSend() +{ + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + + int rc = ::shutdown(_sockfd, 1); + if (rc != 0) error(); +} + + +void SocketImpl::shutdown() +{ + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + + int rc = ::shutdown(_sockfd, 2); + if (rc != 0) error(); +} + + +int SocketImpl::sendBytes(const void* buffer, int length, int flags) +{ + if (_isBrokenTimeout) + { + if (_sndTimeout.totalMicroseconds() != 0) + { + if (!poll(_sndTimeout, SELECT_WRITE)) + throw TimeoutException(); + } + } + + int rc; + do + { + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + rc = ::send(_sockfd, reinterpret_cast<const char*>(buffer), length, flags); + } + while (_blocking && rc < 0 && lastError() == POCO_EINTR); if (rc < 0) - { - int err = lastError(); - if (err == POCO_EAGAIN && !_blocking) - ; - else if (err == POCO_EAGAIN || err == POCO_ETIMEDOUT) - throw TimeoutException(err); - else - error(err); - } - return rc; -} - - -int SocketImpl::sendTo(const void* buffer, int length, const SocketAddress& address, int flags) -{ - int rc; - do - { - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); -#if defined(POCO_VXWORKS) - rc = ::sendto(_sockfd, (char*) buffer, length, flags, (sockaddr*) address.addr(), address.length()); -#else - rc = ::sendto(_sockfd, reinterpret_cast<const char*>(buffer), length, flags, address.addr(), address.length()); -#endif - } - while (_blocking && rc < 0 && lastError() == POCO_EINTR); - if (rc < 0) error(); - return rc; -} - - -int SocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags) -{ - if (_isBrokenTimeout) - { - if (_recvTimeout.totalMicroseconds() != 0) - { - if (!poll(_recvTimeout, SELECT_READ)) - throw TimeoutException(); - } - } - - sockaddr_storage abuffer; - struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(&abuffer); - poco_socklen_t saLen = sizeof(abuffer); - int rc; - do - { - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - rc = ::recvfrom(_sockfd, reinterpret_cast<char*>(buffer), length, flags, pSA, &saLen); - } - while (_blocking && rc < 0 && lastError() == POCO_EINTR); - if (rc >= 0) - { - address = SocketAddress(pSA, saLen); - } - else - { - int err = lastError(); - if (err == POCO_EAGAIN && !_blocking) - ; - else if (err == POCO_EAGAIN || err == POCO_ETIMEDOUT) - throw TimeoutException(err); - else - error(err); - } - return rc; -} - - -void SocketImpl::sendUrgent(unsigned char data) -{ - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - - int rc = ::send(_sockfd, reinterpret_cast<const char*>(&data), sizeof(data), MSG_OOB); - if (rc < 0) error(); -} - - -int SocketImpl::available() -{ - int result = 0; - ioctl(FIONREAD, result); - return result; -} - - -bool SocketImpl::secure() const -{ - return false; -} - - + { + int err = lastError(); + if (err == POCO_EAGAIN || err == POCO_ETIMEDOUT) + throw TimeoutException(); + else + error(err); + } + return rc; +} + + +int SocketImpl::receiveBytes(void* buffer, int length, int flags) +{ + if (_isBrokenTimeout) + { + if (_recvTimeout.totalMicroseconds() != 0) + { + if (!poll(_recvTimeout, SELECT_READ)) + throw TimeoutException(); + } + } + + int rc; + do + { + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + rc = ::recv(_sockfd, reinterpret_cast<char*>(buffer), length, flags); + } + while (_blocking && rc < 0 && lastError() == POCO_EINTR); + if (rc < 0) + { + int err = lastError(); + if (err == POCO_EAGAIN && !_blocking) + ; + else if (err == POCO_EAGAIN || err == POCO_ETIMEDOUT) + throw TimeoutException(err); + else + error(err); + } + return rc; +} + + +int SocketImpl::sendTo(const void* buffer, int length, const SocketAddress& address, int flags) +{ + int rc; + do + { + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); +#if defined(POCO_VXWORKS) + rc = ::sendto(_sockfd, (char*) buffer, length, flags, (sockaddr*) address.addr(), address.length()); +#else + rc = ::sendto(_sockfd, reinterpret_cast<const char*>(buffer), length, flags, address.addr(), address.length()); +#endif + } + while (_blocking && rc < 0 && lastError() == POCO_EINTR); + if (rc < 0) error(); + return rc; +} + + +int SocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags) +{ + if (_isBrokenTimeout) + { + if (_recvTimeout.totalMicroseconds() != 0) + { + if (!poll(_recvTimeout, SELECT_READ)) + throw TimeoutException(); + } + } + + sockaddr_storage abuffer; + struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(&abuffer); + poco_socklen_t saLen = sizeof(abuffer); + int rc; + do + { + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + rc = ::recvfrom(_sockfd, reinterpret_cast<char*>(buffer), length, flags, pSA, &saLen); + } + while (_blocking && rc < 0 && lastError() == POCO_EINTR); + if (rc >= 0) + { + address = SocketAddress(pSA, saLen); + } + else + { + int err = lastError(); + if (err == POCO_EAGAIN && !_blocking) + ; + else if (err == POCO_EAGAIN || err == POCO_ETIMEDOUT) + throw TimeoutException(err); + else + error(err); + } + return rc; +} + + +void SocketImpl::sendUrgent(unsigned char data) +{ + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + + int rc = ::send(_sockfd, reinterpret_cast<const char*>(&data), sizeof(data), MSG_OOB); + if (rc < 0) error(); +} + + +int SocketImpl::available() +{ + int result = 0; + ioctl(FIONREAD, result); + return result; +} + + +bool SocketImpl::secure() const +{ + return false; +} + + bool SocketImpl::pollImpl(Poco::Timespan& remainingTime, int mode) -{ - poco_socket_t sockfd = _sockfd; - if (sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - -#if defined(POCO_HAVE_FD_EPOLL) - - int epollfd = epoll_create(1); - if (epollfd < 0) - { - error("Can't create epoll queue"); - } - - struct epoll_event evin; - memset(&evin, 0, sizeof(evin)); - - if (mode & SELECT_READ) - evin.events |= EPOLLIN; - if (mode & SELECT_WRITE) - evin.events |= EPOLLOUT; - if (mode & SELECT_ERROR) - evin.events |= EPOLLERR; - - if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &evin) < 0) - { - ::close(epollfd); - error("Can't insert socket to epoll queue"); - } - - int rc; - do - { - struct epoll_event evout; - memset(&evout, 0, sizeof(evout)); - - Poco::Timestamp start; - rc = epoll_wait(epollfd, &evout, 1, remainingTime.totalMilliseconds()); - if (rc < 0 && lastError() == POCO_EINTR) - { - Poco::Timestamp end; - Poco::Timespan waited = end - start; - if (waited < remainingTime) - remainingTime -= waited; - else - remainingTime = 0; - } - } - while (rc < 0 && lastError() == POCO_EINTR); - - ::close(epollfd); - if (rc < 0) error(); - return rc > 0; - -#elif defined(POCO_HAVE_FD_POLL) - - pollfd pollBuf; - - memset(&pollBuf, 0, sizeof(pollfd)); - pollBuf.fd = _sockfd; - if (mode & SELECT_READ) pollBuf.events |= POLLIN; - if (mode & SELECT_WRITE) pollBuf.events |= POLLOUT; - - int rc; - do - { - Poco::Timestamp start; -#ifdef _WIN32 - rc = WSAPoll(&pollBuf, 1, static_cast<INT>(remainingTime.totalMilliseconds())); -#else - rc = ::poll(&pollBuf, 1, remainingTime.totalMilliseconds()); -#endif - if (rc < 0 && lastError() == POCO_EINTR) - { - Poco::Timestamp end; - Poco::Timespan waited = end - start; - if (waited < remainingTime) - remainingTime -= waited; - else - remainingTime = 0; - } - } - while (rc < 0 && lastError() == POCO_EINTR); - if (rc < 0) error(); - return rc > 0; - -#else - - fd_set fdRead; - fd_set fdWrite; - fd_set fdExcept; - FD_ZERO(&fdRead); - FD_ZERO(&fdWrite); - FD_ZERO(&fdExcept); - if (mode & SELECT_READ) - { - FD_SET(sockfd, &fdRead); - } - if (mode & SELECT_WRITE) - { - FD_SET(sockfd, &fdWrite); - } - if (mode & SELECT_ERROR) - { - FD_SET(sockfd, &fdExcept); - } - int errorCode = POCO_ENOERR; - int rc; - do - { - struct timeval tv; - tv.tv_sec = (long) remainingTime.totalSeconds(); - tv.tv_usec = (long) remainingTime.useconds(); - Poco::Timestamp start; - rc = ::select(int(sockfd) + 1, &fdRead, &fdWrite, &fdExcept, &tv); - if (rc < 0 && (errorCode = lastError()) == POCO_EINTR) - { - Poco::Timestamp end; - Poco::Timespan waited = end - start; - if (waited < remainingTime) - remainingTime -= waited; - else - remainingTime = 0; - } - } - while (rc < 0 && errorCode == POCO_EINTR); - if (rc < 0) error(errorCode); - return rc > 0; - -#endif // POCO_HAVE_FD_EPOLL -} - +{ + poco_socket_t sockfd = _sockfd; + if (sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + +#if defined(POCO_HAVE_FD_EPOLL) + + int epollfd = epoll_create(1); + if (epollfd < 0) + { + error("Can't create epoll queue"); + } + + struct epoll_event evin; + memset(&evin, 0, sizeof(evin)); + + if (mode & SELECT_READ) + evin.events |= EPOLLIN; + if (mode & SELECT_WRITE) + evin.events |= EPOLLOUT; + if (mode & SELECT_ERROR) + evin.events |= EPOLLERR; + + if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &evin) < 0) + { + ::close(epollfd); + error("Can't insert socket to epoll queue"); + } + + int rc; + do + { + struct epoll_event evout; + memset(&evout, 0, sizeof(evout)); + + Poco::Timestamp start; + rc = epoll_wait(epollfd, &evout, 1, remainingTime.totalMilliseconds()); + if (rc < 0 && lastError() == POCO_EINTR) + { + Poco::Timestamp end; + Poco::Timespan waited = end - start; + if (waited < remainingTime) + remainingTime -= waited; + else + remainingTime = 0; + } + } + while (rc < 0 && lastError() == POCO_EINTR); + + ::close(epollfd); + if (rc < 0) error(); + return rc > 0; + +#elif defined(POCO_HAVE_FD_POLL) + + pollfd pollBuf; + + memset(&pollBuf, 0, sizeof(pollfd)); + pollBuf.fd = _sockfd; + if (mode & SELECT_READ) pollBuf.events |= POLLIN; + if (mode & SELECT_WRITE) pollBuf.events |= POLLOUT; + + int rc; + do + { + Poco::Timestamp start; +#ifdef _WIN32 + rc = WSAPoll(&pollBuf, 1, static_cast<INT>(remainingTime.totalMilliseconds())); +#else + rc = ::poll(&pollBuf, 1, remainingTime.totalMilliseconds()); +#endif + if (rc < 0 && lastError() == POCO_EINTR) + { + Poco::Timestamp end; + Poco::Timespan waited = end - start; + if (waited < remainingTime) + remainingTime -= waited; + else + remainingTime = 0; + } + } + while (rc < 0 && lastError() == POCO_EINTR); + if (rc < 0) error(); + return rc > 0; + +#else + + fd_set fdRead; + fd_set fdWrite; + fd_set fdExcept; + FD_ZERO(&fdRead); + FD_ZERO(&fdWrite); + FD_ZERO(&fdExcept); + if (mode & SELECT_READ) + { + FD_SET(sockfd, &fdRead); + } + if (mode & SELECT_WRITE) + { + FD_SET(sockfd, &fdWrite); + } + if (mode & SELECT_ERROR) + { + FD_SET(sockfd, &fdExcept); + } + int errorCode = POCO_ENOERR; + int rc; + do + { + struct timeval tv; + tv.tv_sec = (long) remainingTime.totalSeconds(); + tv.tv_usec = (long) remainingTime.useconds(); + Poco::Timestamp start; + rc = ::select(int(sockfd) + 1, &fdRead, &fdWrite, &fdExcept, &tv); + if (rc < 0 && (errorCode = lastError()) == POCO_EINTR) + { + Poco::Timestamp end; + Poco::Timespan waited = end - start; + if (waited < remainingTime) + remainingTime -= waited; + else + remainingTime = 0; + } + } + while (rc < 0 && errorCode == POCO_EINTR); + if (rc < 0) error(errorCode); + return rc > 0; + +#endif // POCO_HAVE_FD_EPOLL +} + bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) { Poco::Timespan remainingTime(timeout); return pollImpl(remainingTime, mode); } - -void SocketImpl::setSendBufferSize(int size) -{ - setOption(SOL_SOCKET, SO_SNDBUF, size); -} - - -int SocketImpl::getSendBufferSize() -{ - int result; - getOption(SOL_SOCKET, SO_SNDBUF, result); - return result; -} - - -void SocketImpl::setReceiveBufferSize(int size) -{ - setOption(SOL_SOCKET, SO_RCVBUF, size); -} - - -int SocketImpl::getReceiveBufferSize() -{ - int result; - getOption(SOL_SOCKET, SO_RCVBUF, result); - return result; -} - - -void SocketImpl::setSendTimeout(const Poco::Timespan& timeout) -{ + +void SocketImpl::setSendBufferSize(int size) +{ + setOption(SOL_SOCKET, SO_SNDBUF, size); +} + + +int SocketImpl::getSendBufferSize() +{ + int result; + getOption(SOL_SOCKET, SO_SNDBUF, result); + return result; +} + + +void SocketImpl::setReceiveBufferSize(int size) +{ + setOption(SOL_SOCKET, SO_RCVBUF, size); +} + + +int SocketImpl::getReceiveBufferSize() +{ + int result; + getOption(SOL_SOCKET, SO_RCVBUF, result); + return result; +} + + +void SocketImpl::setSendTimeout(const Poco::Timespan& timeout) +{ #if defined(_WIN32) - int value = (int) timeout.totalMilliseconds(); - setOption(SOL_SOCKET, SO_SNDTIMEO, value); + int value = (int) timeout.totalMilliseconds(); + setOption(SOL_SOCKET, SO_SNDTIMEO, value); #else - setOption(SOL_SOCKET, SO_SNDTIMEO, timeout); -#endif + setOption(SOL_SOCKET, SO_SNDTIMEO, timeout); +#endif _sndTimeout = timeout; -} - - -Poco::Timespan SocketImpl::getSendTimeout() -{ - Timespan result; -#if defined(_WIN32) && !defined(POCO_BROKEN_TIMEOUTS) - int value; - getOption(SOL_SOCKET, SO_SNDTIMEO, value); - result = Timespan::TimeDiff(value)*1000; -#elif !defined(POCO_BROKEN_TIMEOUTS) - getOption(SOL_SOCKET, SO_SNDTIMEO, result); -#endif - if (_isBrokenTimeout) - result = _sndTimeout; - return result; -} - - -void SocketImpl::setReceiveTimeout(const Poco::Timespan& timeout) -{ -#if defined(_WIN32) - int value = (int) timeout.totalMilliseconds(); - setOption(SOL_SOCKET, SO_RCVTIMEO, value); -#else - setOption(SOL_SOCKET, SO_RCVTIMEO, timeout); -#endif +} + + +Poco::Timespan SocketImpl::getSendTimeout() +{ + Timespan result; +#if defined(_WIN32) && !defined(POCO_BROKEN_TIMEOUTS) + int value; + getOption(SOL_SOCKET, SO_SNDTIMEO, value); + result = Timespan::TimeDiff(value)*1000; +#elif !defined(POCO_BROKEN_TIMEOUTS) + getOption(SOL_SOCKET, SO_SNDTIMEO, result); +#endif + if (_isBrokenTimeout) + result = _sndTimeout; + return result; +} + + +void SocketImpl::setReceiveTimeout(const Poco::Timespan& timeout) +{ +#if defined(_WIN32) + int value = (int) timeout.totalMilliseconds(); + setOption(SOL_SOCKET, SO_RCVTIMEO, value); +#else + setOption(SOL_SOCKET, SO_RCVTIMEO, timeout); +#endif _recvTimeout = timeout; -} - - -Poco::Timespan SocketImpl::getReceiveTimeout() -{ - Timespan result; -#if defined(_WIN32) && !defined(POCO_BROKEN_TIMEOUTS) - int value; - getOption(SOL_SOCKET, SO_RCVTIMEO, value); - result = Timespan::TimeDiff(value)*1000; -#elif !defined(POCO_BROKEN_TIMEOUTS) - getOption(SOL_SOCKET, SO_RCVTIMEO, result); -#endif - if (_isBrokenTimeout) - result = _recvTimeout; - return result; -} - - -SocketAddress SocketImpl::address() -{ - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - - sockaddr_storage buffer; - struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(&buffer); - poco_socklen_t saLen = sizeof(buffer); - int rc = ::getsockname(_sockfd, pSA, &saLen); - if (rc == 0) - return SocketAddress(pSA, saLen); +} + + +Poco::Timespan SocketImpl::getReceiveTimeout() +{ + Timespan result; +#if defined(_WIN32) && !defined(POCO_BROKEN_TIMEOUTS) + int value; + getOption(SOL_SOCKET, SO_RCVTIMEO, value); + result = Timespan::TimeDiff(value)*1000; +#elif !defined(POCO_BROKEN_TIMEOUTS) + getOption(SOL_SOCKET, SO_RCVTIMEO, result); +#endif + if (_isBrokenTimeout) + result = _recvTimeout; + return result; +} + + +SocketAddress SocketImpl::address() +{ + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + + sockaddr_storage buffer; + struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(&buffer); + poco_socklen_t saLen = sizeof(buffer); + int rc = ::getsockname(_sockfd, pSA, &saLen); + if (rc == 0) + return SocketAddress(pSA, saLen); + else + error(); + return SocketAddress(); +} + + +SocketAddress SocketImpl::peerAddress() +{ + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + + sockaddr_storage buffer; + struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(&buffer); + poco_socklen_t saLen = sizeof(buffer); + int rc = ::getpeername(_sockfd, pSA, &saLen); + if (rc == 0) + return SocketAddress(pSA, saLen); else - error(); - return SocketAddress(); -} - - -SocketAddress SocketImpl::peerAddress() -{ - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - - sockaddr_storage buffer; - struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(&buffer); - poco_socklen_t saLen = sizeof(buffer); - int rc = ::getpeername(_sockfd, pSA, &saLen); - if (rc == 0) - return SocketAddress(pSA, saLen); - else - error(); - return SocketAddress(); -} - - -void SocketImpl::setOption(int level, int option, int value) -{ - setRawOption(level, option, &value, sizeof(value)); -} - - -void SocketImpl::setOption(int level, int option, unsigned value) -{ - setRawOption(level, option, &value, sizeof(value)); -} - - -void SocketImpl::setOption(int level, int option, unsigned char value) -{ - setRawOption(level, option, &value, sizeof(value)); -} - - -void SocketImpl::setOption(int level, int option, const IPAddress& value) -{ - setRawOption(level, option, value.addr(), value.length()); -} - - -void SocketImpl::setOption(int level, int option, const Poco::Timespan& value) -{ - struct timeval tv; - tv.tv_sec = (long) value.totalSeconds(); - tv.tv_usec = (long) value.useconds(); - - setRawOption(level, option, &tv, sizeof(tv)); -} - - -void SocketImpl::setRawOption(int level, int option, const void* value, poco_socklen_t length) -{ - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - -#if defined(POCO_VXWORKS) - int rc = ::setsockopt(_sockfd, level, option, (char*) value, length); -#else - int rc = ::setsockopt(_sockfd, level, option, reinterpret_cast<const char*>(value), length); -#endif - if (rc == -1) error(); -} - - -void SocketImpl::getOption(int level, int option, int& value) -{ - poco_socklen_t len = sizeof(value); - getRawOption(level, option, &value, len); -} - - -void SocketImpl::getOption(int level, int option, unsigned& value) -{ - poco_socklen_t len = sizeof(value); - getRawOption(level, option, &value, len); -} - - -void SocketImpl::getOption(int level, int option, unsigned char& value) -{ - poco_socklen_t len = sizeof(value); - getRawOption(level, option, &value, len); -} - - -void SocketImpl::getOption(int level, int option, Poco::Timespan& value) -{ - struct timeval tv; - poco_socklen_t len = sizeof(tv); - getRawOption(level, option, &tv, len); - value.assign(tv.tv_sec, tv.tv_usec); -} - - -void SocketImpl::getOption(int level, int option, IPAddress& value) -{ - char buffer[IPAddress::MAX_ADDRESS_LENGTH]; - poco_socklen_t len = sizeof(buffer); - getRawOption(level, option, buffer, len); - value = IPAddress(buffer, len); -} - - -void SocketImpl::getRawOption(int level, int option, void* value, poco_socklen_t& length) -{ - if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); - - int rc = ::getsockopt(_sockfd, level, option, reinterpret_cast<char*>(value), &length); - if (rc == -1) error(); -} - - -void SocketImpl::setLinger(bool on, int seconds) -{ - struct linger l; - l.l_onoff = on ? 1 : 0; - l.l_linger = static_cast<u_short>(seconds); - setRawOption(SOL_SOCKET, SO_LINGER, &l, sizeof(l)); -} - - -void SocketImpl::getLinger(bool& on, int& seconds) -{ - struct linger l; - poco_socklen_t len = sizeof(l); - getRawOption(SOL_SOCKET, SO_LINGER, &l, len); - on = l.l_onoff != 0; - seconds = l.l_linger; -} - - -void SocketImpl::setNoDelay(bool flag) -{ - int value = flag ? 1 : 0; - setOption(IPPROTO_TCP, TCP_NODELAY, value); -} - - -bool SocketImpl::getNoDelay() -{ - int value(0); - getOption(IPPROTO_TCP, TCP_NODELAY, value); - return value != 0; -} - - -void SocketImpl::setKeepAlive(bool flag) -{ - int value = flag ? 1 : 0; - setOption(SOL_SOCKET, SO_KEEPALIVE, value); -} - - -bool SocketImpl::getKeepAlive() -{ - int value(0); - getOption(SOL_SOCKET, SO_KEEPALIVE, value); - return value != 0; -} - - -void SocketImpl::setReuseAddress(bool flag) -{ - int value = flag ? 1 : 0; - setOption(SOL_SOCKET, SO_REUSEADDR, value); -} - - -bool SocketImpl::getReuseAddress() -{ - int value(0); - getOption(SOL_SOCKET, SO_REUSEADDR, value); - return value != 0; -} - - -void SocketImpl::setReusePort(bool flag) -{ -#ifdef SO_REUSEPORT - try - { - int value = flag ? 1 : 0; - setOption(SOL_SOCKET, SO_REUSEPORT, value); - } - catch (IOException&) - { - // ignore error, since not all implementations - // support SO_REUSEPORT, even if the macro - // is defined. - } -#else - (void)flag; -#endif -} - - -bool SocketImpl::getReusePort() -{ -#ifdef SO_REUSEPORT - int value(0); - getOption(SOL_SOCKET, SO_REUSEPORT, value); - return value != 0; -#else - return false; -#endif -} - - -void SocketImpl::setOOBInline(bool flag) -{ - int value = flag ? 1 : 0; - setOption(SOL_SOCKET, SO_OOBINLINE, value); -} - - -bool SocketImpl::getOOBInline() -{ - int value(0); - getOption(SOL_SOCKET, SO_OOBINLINE, value); - return value != 0; -} - - -void SocketImpl::setBroadcast(bool flag) -{ - int value = flag ? 1 : 0; - setOption(SOL_SOCKET, SO_BROADCAST, value); -} - - -bool SocketImpl::getBroadcast() -{ - int value(0); - getOption(SOL_SOCKET, SO_BROADCAST, value); - return value != 0; -} - - -void SocketImpl::setBlocking(bool flag) -{ -#if !defined(POCO_OS_FAMILY_UNIX) - int arg = flag ? 0 : 1; - ioctl(FIONBIO, arg); -#else - int arg = fcntl(F_GETFL); - long flags = arg & ~O_NONBLOCK; - if (!flag) flags |= O_NONBLOCK; - (void) fcntl(F_SETFL, flags); -#endif - _blocking = flag; -} - - -int SocketImpl::socketError() -{ - int result(0); - getOption(SOL_SOCKET, SO_ERROR, result); - return result; -} - - -void SocketImpl::init(int af) -{ - initSocket(af, SOCK_STREAM); -} - - -void SocketImpl::initSocket(int af, int type, int proto) -{ - poco_assert (_sockfd == POCO_INVALID_SOCKET); - - _sockfd = ::socket(af, type, proto); - if (_sockfd == POCO_INVALID_SOCKET) - error(); - -#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) - // SIGPIPE sends a signal that if unhandled (which is the default) - // will crash the process. This only happens on UNIX, and not Linux. - // - // In order to have POCO sockets behave the same across platforms, it is - // best to just ignore SIGPIPE altogether. - setOption(SOL_SOCKET, SO_NOSIGPIPE, 1); -#endif -} - - -void SocketImpl::ioctl(poco_ioctl_request_t request, int& arg) -{ -#if defined(_WIN32) - int rc = ioctlsocket(_sockfd, request, reinterpret_cast<u_long*>(&arg)); -#elif defined(POCO_VXWORKS) - int rc = ::ioctl(_sockfd, request, (int) &arg); -#else - int rc = ::ioctl(_sockfd, request, &arg); -#endif - if (rc != 0) error(); -} - - -void SocketImpl::ioctl(poco_ioctl_request_t request, void* arg) -{ -#if defined(_WIN32) - int rc = ioctlsocket(_sockfd, request, reinterpret_cast<u_long*>(arg)); -#elif defined(POCO_VXWORKS) - int rc = ::ioctl(_sockfd, request, (int) arg); -#else - int rc = ::ioctl(_sockfd, request, arg); -#endif - if (rc != 0) error(); -} - - -#if defined(POCO_OS_FAMILY_UNIX) -int SocketImpl::fcntl(poco_fcntl_request_t request) -{ - int rc = ::fcntl(_sockfd, request); - if (rc == -1) error(); - return rc; -} - - -int SocketImpl::fcntl(poco_fcntl_request_t request, long arg) -{ - int rc = ::fcntl(_sockfd, request, arg); - if (rc == -1) error(); - return rc; -} -#endif - - -void SocketImpl::reset(poco_socket_t aSocket) -{ - _sockfd = aSocket; -} - - -void SocketImpl::error() -{ - int err = lastError(); - std::string empty; - error(err, empty); -} - - -void SocketImpl::error(const std::string& arg) -{ - error(lastError(), arg); -} - - -void SocketImpl::error(int code) -{ - std::string arg; - error(code, arg); -} - - -void SocketImpl::error(int code, const std::string& arg) -{ - switch (code) - { - case POCO_ENOERR: return; - case POCO_ESYSNOTREADY: - throw NetException("Net subsystem not ready", code); - case POCO_ENOTINIT: - throw NetException("Net subsystem not initialized", code); - case POCO_EINTR: - throw IOException("Interrupted", code); - case POCO_EACCES: - throw IOException("Permission denied", code); - case POCO_EFAULT: - throw IOException("Bad address", code); - case POCO_EINVAL: - throw InvalidArgumentException(code); - case POCO_EMFILE: - throw IOException("Too many open files", code); - case POCO_EWOULDBLOCK: - throw IOException("Operation would block", code); - case POCO_EINPROGRESS: - throw IOException("Operation now in progress", code); - case POCO_EALREADY: - throw IOException("Operation already in progress", code); - case POCO_ENOTSOCK: - throw IOException("Socket operation attempted on non-socket", code); - case POCO_EDESTADDRREQ: - throw NetException("Destination address required", code); - case POCO_EMSGSIZE: - throw NetException("Message too long", code); - case POCO_EPROTOTYPE: - throw NetException("Wrong protocol type", code); - case POCO_ENOPROTOOPT: - throw NetException("Protocol not available", code); - case POCO_EPROTONOSUPPORT: - throw NetException("Protocol not supported", code); - case POCO_ESOCKTNOSUPPORT: - throw NetException("Socket type not supported", code); - case POCO_ENOTSUP: - throw NetException("Operation not supported", code); - case POCO_EPFNOSUPPORT: - throw NetException("Protocol family not supported", code); - case POCO_EAFNOSUPPORT: - throw NetException("Address family not supported", code); - case POCO_EADDRINUSE: - throw NetException("Address already in use", arg, code); - case POCO_EADDRNOTAVAIL: - throw NetException("Cannot assign requested address", arg, code); - case POCO_ENETDOWN: - throw NetException("Network is down", code); - case POCO_ENETUNREACH: - throw NetException("Network is unreachable", code); - case POCO_ENETRESET: - throw NetException("Network dropped connection on reset", code); - case POCO_ECONNABORTED: - throw ConnectionAbortedException(code); - case POCO_ECONNRESET: - throw ConnectionResetException(code); - case POCO_ENOBUFS: - throw IOException("No buffer space available", code); - case POCO_EISCONN: - throw NetException("Socket is already connected", code); - case POCO_ENOTCONN: - throw NetException("Socket is not connected", code); - case POCO_ESHUTDOWN: - throw NetException("Cannot send after socket shutdown", code); - case POCO_ETIMEDOUT: - throw TimeoutException(code); - case POCO_ECONNREFUSED: - throw ConnectionRefusedException(arg, code); - case POCO_EHOSTDOWN: - throw NetException("Host is down", arg, code); - case POCO_EHOSTUNREACH: - throw NetException("No route to host", arg, code); -#if defined(POCO_OS_FAMILY_UNIX) - case EPIPE: - throw IOException("Broken pipe", code); - case EBADF: - throw IOException("Bad socket descriptor", code); - case ENOENT: - throw IOException("Not found", arg, code); -#endif - default: - throw IOException(NumberFormatter::format(code), arg, code); - } -} - - -} } // namespace Poco::Net + error(); + return SocketAddress(); +} + + +void SocketImpl::setOption(int level, int option, int value) +{ + setRawOption(level, option, &value, sizeof(value)); +} + + +void SocketImpl::setOption(int level, int option, unsigned value) +{ + setRawOption(level, option, &value, sizeof(value)); +} + + +void SocketImpl::setOption(int level, int option, unsigned char value) +{ + setRawOption(level, option, &value, sizeof(value)); +} + + +void SocketImpl::setOption(int level, int option, const IPAddress& value) +{ + setRawOption(level, option, value.addr(), value.length()); +} + + +void SocketImpl::setOption(int level, int option, const Poco::Timespan& value) +{ + struct timeval tv; + tv.tv_sec = (long) value.totalSeconds(); + tv.tv_usec = (long) value.useconds(); + + setRawOption(level, option, &tv, sizeof(tv)); +} + + +void SocketImpl::setRawOption(int level, int option, const void* value, poco_socklen_t length) +{ + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + +#if defined(POCO_VXWORKS) + int rc = ::setsockopt(_sockfd, level, option, (char*) value, length); +#else + int rc = ::setsockopt(_sockfd, level, option, reinterpret_cast<const char*>(value), length); +#endif + if (rc == -1) error(); +} + + +void SocketImpl::getOption(int level, int option, int& value) +{ + poco_socklen_t len = sizeof(value); + getRawOption(level, option, &value, len); +} + + +void SocketImpl::getOption(int level, int option, unsigned& value) +{ + poco_socklen_t len = sizeof(value); + getRawOption(level, option, &value, len); +} + + +void SocketImpl::getOption(int level, int option, unsigned char& value) +{ + poco_socklen_t len = sizeof(value); + getRawOption(level, option, &value, len); +} + + +void SocketImpl::getOption(int level, int option, Poco::Timespan& value) +{ + struct timeval tv; + poco_socklen_t len = sizeof(tv); + getRawOption(level, option, &tv, len); + value.assign(tv.tv_sec, tv.tv_usec); +} + + +void SocketImpl::getOption(int level, int option, IPAddress& value) +{ + char buffer[IPAddress::MAX_ADDRESS_LENGTH]; + poco_socklen_t len = sizeof(buffer); + getRawOption(level, option, buffer, len); + value = IPAddress(buffer, len); +} + + +void SocketImpl::getRawOption(int level, int option, void* value, poco_socklen_t& length) +{ + if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); + + int rc = ::getsockopt(_sockfd, level, option, reinterpret_cast<char*>(value), &length); + if (rc == -1) error(); +} + + +void SocketImpl::setLinger(bool on, int seconds) +{ + struct linger l; + l.l_onoff = on ? 1 : 0; + l.l_linger = static_cast<u_short>(seconds); + setRawOption(SOL_SOCKET, SO_LINGER, &l, sizeof(l)); +} + + +void SocketImpl::getLinger(bool& on, int& seconds) +{ + struct linger l; + poco_socklen_t len = sizeof(l); + getRawOption(SOL_SOCKET, SO_LINGER, &l, len); + on = l.l_onoff != 0; + seconds = l.l_linger; +} + + +void SocketImpl::setNoDelay(bool flag) +{ + int value = flag ? 1 : 0; + setOption(IPPROTO_TCP, TCP_NODELAY, value); +} + + +bool SocketImpl::getNoDelay() +{ + int value(0); + getOption(IPPROTO_TCP, TCP_NODELAY, value); + return value != 0; +} + + +void SocketImpl::setKeepAlive(bool flag) +{ + int value = flag ? 1 : 0; + setOption(SOL_SOCKET, SO_KEEPALIVE, value); +} + + +bool SocketImpl::getKeepAlive() +{ + int value(0); + getOption(SOL_SOCKET, SO_KEEPALIVE, value); + return value != 0; +} + + +void SocketImpl::setReuseAddress(bool flag) +{ + int value = flag ? 1 : 0; + setOption(SOL_SOCKET, SO_REUSEADDR, value); +} + + +bool SocketImpl::getReuseAddress() +{ + int value(0); + getOption(SOL_SOCKET, SO_REUSEADDR, value); + return value != 0; +} + + +void SocketImpl::setReusePort(bool flag) +{ +#ifdef SO_REUSEPORT + try + { + int value = flag ? 1 : 0; + setOption(SOL_SOCKET, SO_REUSEPORT, value); + } + catch (IOException&) + { + // ignore error, since not all implementations + // support SO_REUSEPORT, even if the macro + // is defined. + } +#else + (void)flag; +#endif +} + + +bool SocketImpl::getReusePort() +{ +#ifdef SO_REUSEPORT + int value(0); + getOption(SOL_SOCKET, SO_REUSEPORT, value); + return value != 0; +#else + return false; +#endif +} + + +void SocketImpl::setOOBInline(bool flag) +{ + int value = flag ? 1 : 0; + setOption(SOL_SOCKET, SO_OOBINLINE, value); +} + + +bool SocketImpl::getOOBInline() +{ + int value(0); + getOption(SOL_SOCKET, SO_OOBINLINE, value); + return value != 0; +} + + +void SocketImpl::setBroadcast(bool flag) +{ + int value = flag ? 1 : 0; + setOption(SOL_SOCKET, SO_BROADCAST, value); +} + + +bool SocketImpl::getBroadcast() +{ + int value(0); + getOption(SOL_SOCKET, SO_BROADCAST, value); + return value != 0; +} + + +void SocketImpl::setBlocking(bool flag) +{ +#if !defined(POCO_OS_FAMILY_UNIX) + int arg = flag ? 0 : 1; + ioctl(FIONBIO, arg); +#else + int arg = fcntl(F_GETFL); + long flags = arg & ~O_NONBLOCK; + if (!flag) flags |= O_NONBLOCK; + (void) fcntl(F_SETFL, flags); +#endif + _blocking = flag; +} + + +int SocketImpl::socketError() +{ + int result(0); + getOption(SOL_SOCKET, SO_ERROR, result); + return result; +} + + +void SocketImpl::init(int af) +{ + initSocket(af, SOCK_STREAM); +} + + +void SocketImpl::initSocket(int af, int type, int proto) +{ + poco_assert (_sockfd == POCO_INVALID_SOCKET); + + _sockfd = ::socket(af, type, proto); + if (_sockfd == POCO_INVALID_SOCKET) + error(); + +#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) + // SIGPIPE sends a signal that if unhandled (which is the default) + // will crash the process. This only happens on UNIX, and not Linux. + // + // In order to have POCO sockets behave the same across platforms, it is + // best to just ignore SIGPIPE altogether. + setOption(SOL_SOCKET, SO_NOSIGPIPE, 1); +#endif +} + + +void SocketImpl::ioctl(poco_ioctl_request_t request, int& arg) +{ +#if defined(_WIN32) + int rc = ioctlsocket(_sockfd, request, reinterpret_cast<u_long*>(&arg)); +#elif defined(POCO_VXWORKS) + int rc = ::ioctl(_sockfd, request, (int) &arg); +#else + int rc = ::ioctl(_sockfd, request, &arg); +#endif + if (rc != 0) error(); +} + + +void SocketImpl::ioctl(poco_ioctl_request_t request, void* arg) +{ +#if defined(_WIN32) + int rc = ioctlsocket(_sockfd, request, reinterpret_cast<u_long*>(arg)); +#elif defined(POCO_VXWORKS) + int rc = ::ioctl(_sockfd, request, (int) arg); +#else + int rc = ::ioctl(_sockfd, request, arg); +#endif + if (rc != 0) error(); +} + + +#if defined(POCO_OS_FAMILY_UNIX) +int SocketImpl::fcntl(poco_fcntl_request_t request) +{ + int rc = ::fcntl(_sockfd, request); + if (rc == -1) error(); + return rc; +} + + +int SocketImpl::fcntl(poco_fcntl_request_t request, long arg) +{ + int rc = ::fcntl(_sockfd, request, arg); + if (rc == -1) error(); + return rc; +} +#endif + + +void SocketImpl::reset(poco_socket_t aSocket) +{ + _sockfd = aSocket; +} + + +void SocketImpl::error() +{ + int err = lastError(); + std::string empty; + error(err, empty); +} + + +void SocketImpl::error(const std::string& arg) +{ + error(lastError(), arg); +} + + +void SocketImpl::error(int code) +{ + std::string arg; + error(code, arg); +} + + +void SocketImpl::error(int code, const std::string& arg) +{ + switch (code) + { + case POCO_ENOERR: return; + case POCO_ESYSNOTREADY: + throw NetException("Net subsystem not ready", code); + case POCO_ENOTINIT: + throw NetException("Net subsystem not initialized", code); + case POCO_EINTR: + throw IOException("Interrupted", code); + case POCO_EACCES: + throw IOException("Permission denied", code); + case POCO_EFAULT: + throw IOException("Bad address", code); + case POCO_EINVAL: + throw InvalidArgumentException(code); + case POCO_EMFILE: + throw IOException("Too many open files", code); + case POCO_EWOULDBLOCK: + throw IOException("Operation would block", code); + case POCO_EINPROGRESS: + throw IOException("Operation now in progress", code); + case POCO_EALREADY: + throw IOException("Operation already in progress", code); + case POCO_ENOTSOCK: + throw IOException("Socket operation attempted on non-socket", code); + case POCO_EDESTADDRREQ: + throw NetException("Destination address required", code); + case POCO_EMSGSIZE: + throw NetException("Message too long", code); + case POCO_EPROTOTYPE: + throw NetException("Wrong protocol type", code); + case POCO_ENOPROTOOPT: + throw NetException("Protocol not available", code); + case POCO_EPROTONOSUPPORT: + throw NetException("Protocol not supported", code); + case POCO_ESOCKTNOSUPPORT: + throw NetException("Socket type not supported", code); + case POCO_ENOTSUP: + throw NetException("Operation not supported", code); + case POCO_EPFNOSUPPORT: + throw NetException("Protocol family not supported", code); + case POCO_EAFNOSUPPORT: + throw NetException("Address family not supported", code); + case POCO_EADDRINUSE: + throw NetException("Address already in use", arg, code); + case POCO_EADDRNOTAVAIL: + throw NetException("Cannot assign requested address", arg, code); + case POCO_ENETDOWN: + throw NetException("Network is down", code); + case POCO_ENETUNREACH: + throw NetException("Network is unreachable", code); + case POCO_ENETRESET: + throw NetException("Network dropped connection on reset", code); + case POCO_ECONNABORTED: + throw ConnectionAbortedException(code); + case POCO_ECONNRESET: + throw ConnectionResetException(code); + case POCO_ENOBUFS: + throw IOException("No buffer space available", code); + case POCO_EISCONN: + throw NetException("Socket is already connected", code); + case POCO_ENOTCONN: + throw NetException("Socket is not connected", code); + case POCO_ESHUTDOWN: + throw NetException("Cannot send after socket shutdown", code); + case POCO_ETIMEDOUT: + throw TimeoutException(code); + case POCO_ECONNREFUSED: + throw ConnectionRefusedException(arg, code); + case POCO_EHOSTDOWN: + throw NetException("Host is down", arg, code); + case POCO_EHOSTUNREACH: + throw NetException("No route to host", arg, code); +#if defined(POCO_OS_FAMILY_UNIX) + case EPIPE: + throw IOException("Broken pipe", code); + case EBADF: + throw IOException("Bad socket descriptor", code); + case ENOENT: + throw IOException("Not found", arg, code); +#endif + default: + throw IOException(NumberFormatter::format(code), arg, code); + } +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/SocketNotification.cpp b/contrib/libs/poco/Net/src/SocketNotification.cpp index da3c922da5..337794fecd 100644 --- a/contrib/libs/poco/Net/src/SocketNotification.cpp +++ b/contrib/libs/poco/Net/src/SocketNotification.cpp @@ -1,105 +1,105 @@ -// -// SocketNotification.cpp -// -// Library: Net -// Package: Reactor -// Module: SocketNotification -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/SocketNotification.h" - - -namespace Poco { -namespace Net { - - -SocketNotification::SocketNotification(SocketReactor* pReactor): - _pReactor(pReactor) -{ -} - - -SocketNotification::~SocketNotification() -{ -} - - -void SocketNotification::setSocket(const Socket& socket) -{ - _socket = socket; -} - - -ReadableNotification::ReadableNotification(SocketReactor* pReactor): - SocketNotification(pReactor) -{ -} - - -ReadableNotification::~ReadableNotification() -{ -} - - -WritableNotification::WritableNotification(SocketReactor* pReactor): - SocketNotification(pReactor) -{ -} - - -WritableNotification::~WritableNotification() -{ -} - - -ErrorNotification::ErrorNotification(SocketReactor* pReactor): - SocketNotification(pReactor) -{ -} - - -ErrorNotification::~ErrorNotification() -{ -} - - -TimeoutNotification::TimeoutNotification(SocketReactor* pReactor): - SocketNotification(pReactor) -{ -} - - -TimeoutNotification::~TimeoutNotification() -{ -} - - -IdleNotification::IdleNotification(SocketReactor* pReactor): - SocketNotification(pReactor) -{ -} - - -IdleNotification::~IdleNotification() -{ -} - - -ShutdownNotification::ShutdownNotification(SocketReactor* pReactor): - SocketNotification(pReactor) -{ -} - - -ShutdownNotification::~ShutdownNotification() -{ -} - - -} } // namespace Poco::Net +// +// SocketNotification.cpp +// +// Library: Net +// Package: Reactor +// Module: SocketNotification +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/SocketNotification.h" + + +namespace Poco { +namespace Net { + + +SocketNotification::SocketNotification(SocketReactor* pReactor): + _pReactor(pReactor) +{ +} + + +SocketNotification::~SocketNotification() +{ +} + + +void SocketNotification::setSocket(const Socket& socket) +{ + _socket = socket; +} + + +ReadableNotification::ReadableNotification(SocketReactor* pReactor): + SocketNotification(pReactor) +{ +} + + +ReadableNotification::~ReadableNotification() +{ +} + + +WritableNotification::WritableNotification(SocketReactor* pReactor): + SocketNotification(pReactor) +{ +} + + +WritableNotification::~WritableNotification() +{ +} + + +ErrorNotification::ErrorNotification(SocketReactor* pReactor): + SocketNotification(pReactor) +{ +} + + +ErrorNotification::~ErrorNotification() +{ +} + + +TimeoutNotification::TimeoutNotification(SocketReactor* pReactor): + SocketNotification(pReactor) +{ +} + + +TimeoutNotification::~TimeoutNotification() +{ +} + + +IdleNotification::IdleNotification(SocketReactor* pReactor): + SocketNotification(pReactor) +{ +} + + +IdleNotification::~IdleNotification() +{ +} + + +ShutdownNotification::ShutdownNotification(SocketReactor* pReactor): + SocketNotification(pReactor) +{ +} + + +ShutdownNotification::~ShutdownNotification() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/SocketNotifier.cpp b/contrib/libs/poco/Net/src/SocketNotifier.cpp index 9bbf6ca826..8c9bcebe28 100644 --- a/contrib/libs/poco/Net/src/SocketNotifier.cpp +++ b/contrib/libs/poco/Net/src/SocketNotifier.cpp @@ -1,89 +1,89 @@ -// -// SocketNotifier.cpp -// -// Library: Net -// Package: Reactor -// Module: SocketNotifier -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/SocketNotifier.h" -#include "Poco/Net/SocketReactor.h" -#include "Poco/Net/SocketNotification.h" - - -namespace Poco { -namespace Net { - - -SocketNotifier::SocketNotifier(const Socket& socket): - _socket(socket) -{ -} - - -SocketNotifier::~SocketNotifier() -{ -} - - -void SocketNotifier::addObserver(SocketReactor* pReactor, const Poco::AbstractObserver& observer) -{ - _nc.addObserver(observer); - if (observer.accepts(pReactor->_pReadableNotification)) - _events.insert(pReactor->_pReadableNotification.get()); - else if (observer.accepts(pReactor->_pWritableNotification)) - _events.insert(pReactor->_pWritableNotification.get()); - else if (observer.accepts(pReactor->_pErrorNotification)) - _events.insert(pReactor->_pErrorNotification.get()); - else if (observer.accepts(pReactor->_pTimeoutNotification)) - _events.insert(pReactor->_pTimeoutNotification.get()); -} - - -void SocketNotifier::removeObserver(SocketReactor* pReactor, const Poco::AbstractObserver& observer) -{ - _nc.removeObserver(observer); - EventSet::iterator it = _events.end(); - if (observer.accepts(pReactor->_pReadableNotification)) - it = _events.find(pReactor->_pReadableNotification.get()); - else if (observer.accepts(pReactor->_pWritableNotification)) - it = _events.find(pReactor->_pWritableNotification.get()); - else if (observer.accepts(pReactor->_pErrorNotification)) - it = _events.find(pReactor->_pErrorNotification.get()); - else if (observer.accepts(pReactor->_pTimeoutNotification)) - it = _events.find(pReactor->_pTimeoutNotification.get()); - if (it != _events.end()) - _events.erase(it); -} - - -namespace -{ - static Socket nullSocket; -} - - -void SocketNotifier::dispatch(SocketNotification* pNotification) -{ - pNotification->setSocket(_socket); - pNotification->duplicate(); - try - { - _nc.postNotification(pNotification); - } - catch (...) - { - pNotification->setSocket(nullSocket); - throw; - } - pNotification->setSocket(nullSocket); -} - - -} } // namespace Poco::Net +// +// SocketNotifier.cpp +// +// Library: Net +// Package: Reactor +// Module: SocketNotifier +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/SocketNotifier.h" +#include "Poco/Net/SocketReactor.h" +#include "Poco/Net/SocketNotification.h" + + +namespace Poco { +namespace Net { + + +SocketNotifier::SocketNotifier(const Socket& socket): + _socket(socket) +{ +} + + +SocketNotifier::~SocketNotifier() +{ +} + + +void SocketNotifier::addObserver(SocketReactor* pReactor, const Poco::AbstractObserver& observer) +{ + _nc.addObserver(observer); + if (observer.accepts(pReactor->_pReadableNotification)) + _events.insert(pReactor->_pReadableNotification.get()); + else if (observer.accepts(pReactor->_pWritableNotification)) + _events.insert(pReactor->_pWritableNotification.get()); + else if (observer.accepts(pReactor->_pErrorNotification)) + _events.insert(pReactor->_pErrorNotification.get()); + else if (observer.accepts(pReactor->_pTimeoutNotification)) + _events.insert(pReactor->_pTimeoutNotification.get()); +} + + +void SocketNotifier::removeObserver(SocketReactor* pReactor, const Poco::AbstractObserver& observer) +{ + _nc.removeObserver(observer); + EventSet::iterator it = _events.end(); + if (observer.accepts(pReactor->_pReadableNotification)) + it = _events.find(pReactor->_pReadableNotification.get()); + else if (observer.accepts(pReactor->_pWritableNotification)) + it = _events.find(pReactor->_pWritableNotification.get()); + else if (observer.accepts(pReactor->_pErrorNotification)) + it = _events.find(pReactor->_pErrorNotification.get()); + else if (observer.accepts(pReactor->_pTimeoutNotification)) + it = _events.find(pReactor->_pTimeoutNotification.get()); + if (it != _events.end()) + _events.erase(it); +} + + +namespace +{ + static Socket nullSocket; +} + + +void SocketNotifier::dispatch(SocketNotification* pNotification) +{ + pNotification->setSocket(_socket); + pNotification->duplicate(); + try + { + _nc.postNotification(pNotification); + } + catch (...) + { + pNotification->setSocket(nullSocket); + throw; + } + pNotification->setSocket(nullSocket); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/SocketReactor.cpp b/contrib/libs/poco/Net/src/SocketReactor.cpp index 79150e2842..65ead0272a 100644 --- a/contrib/libs/poco/Net/src/SocketReactor.cpp +++ b/contrib/libs/poco/Net/src/SocketReactor.cpp @@ -1,297 +1,297 @@ -// -// SocketReactor.cpp -// -// Library: Net -// Package: Reactor -// Module: SocketReactor -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/SocketReactor.h" -#include "Poco/Net/SocketNotification.h" -#include "Poco/Net/SocketNotifier.h" -#include "Poco/ErrorHandler.h" -#include "Poco/Thread.h" -#include "Poco/Exception.h" - - -using Poco::FastMutex; -using Poco::Exception; -using Poco::ErrorHandler; - - -namespace Poco { -namespace Net { - - -SocketReactor::SocketReactor(): - _stop(false), - _timeout(DEFAULT_TIMEOUT), - _pReadableNotification(new ReadableNotification(this)), - _pWritableNotification(new WritableNotification(this)), - _pErrorNotification(new ErrorNotification(this)), - _pTimeoutNotification(new TimeoutNotification(this)), - _pIdleNotification(new IdleNotification(this)), - _pShutdownNotification(new ShutdownNotification(this)), - _pThread(0) -{ -} - - -SocketReactor::SocketReactor(const Poco::Timespan& timeout): - _stop(false), - _timeout(timeout), - _pReadableNotification(new ReadableNotification(this)), - _pWritableNotification(new WritableNotification(this)), - _pErrorNotification(new ErrorNotification(this)), - _pTimeoutNotification(new TimeoutNotification(this)), - _pIdleNotification(new IdleNotification(this)), - _pShutdownNotification(new ShutdownNotification(this)), - _pThread(0) -{ -} - - -SocketReactor::~SocketReactor() -{ -} - - -void SocketReactor::run() -{ - _pThread = Thread::current(); - - Socket::SocketList readable; - Socket::SocketList writable; - Socket::SocketList except; - - while (!_stop) - { - try - { - readable.clear(); - writable.clear(); - except.clear(); - int nSockets = 0; - { - FastMutex::ScopedLock lock(_mutex); - for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it) - { - if (it->second->accepts(_pReadableNotification)) - { - readable.push_back(it->first); - nSockets++; - } - if (it->second->accepts(_pWritableNotification)) - { - writable.push_back(it->first); - nSockets++; - } - if (it->second->accepts(_pErrorNotification)) - { - except.push_back(it->first); - nSockets++; - } - } - } - if (nSockets == 0) - { - onIdle(); - Thread::trySleep(static_cast<long>(_timeout.totalMilliseconds())); - } - else if (Socket::select(readable, writable, except, _timeout)) - { - onBusy(); - - for (Socket::SocketList::iterator it = readable.begin(); it != readable.end(); ++it) - dispatch(*it, _pReadableNotification); - for (Socket::SocketList::iterator it = writable.begin(); it != writable.end(); ++it) - dispatch(*it, _pWritableNotification); - for (Socket::SocketList::iterator it = except.begin(); it != except.end(); ++it) - dispatch(*it, _pErrorNotification); - } - else onTimeout(); - } - catch (Exception& exc) - { - ErrorHandler::handle(exc); - } - catch (std::exception& exc) - { - ErrorHandler::handle(exc); - } - catch (...) - { - ErrorHandler::handle(); - } - } - onShutdown(); -} - - -void SocketReactor::stop() -{ - _stop = true; -} - - -void SocketReactor::wakeUp() -{ - if (_pThread) _pThread->wakeUp(); -} - - -void SocketReactor::setTimeout(const Poco::Timespan& timeout) -{ - _timeout = timeout; -} - - -const Poco::Timespan& SocketReactor::getTimeout() const -{ - return _timeout; -} - - -void SocketReactor::addEventHandler(const Socket& socket, const Poco::AbstractObserver& observer) -{ - NotifierPtr pNotifier; - { - FastMutex::ScopedLock lock(_mutex); - - EventHandlerMap::iterator it = _handlers.find(socket); - if (it == _handlers.end()) - { - pNotifier = new SocketNotifier(socket); - _handlers[socket] = pNotifier; - } - else pNotifier = it->second; - } - if (!pNotifier->hasObserver(observer)) - pNotifier->addObserver(this, observer); -} - - -bool SocketReactor::hasEventHandler(const Socket& socket, const Poco::AbstractObserver& observer) -{ - NotifierPtr pNotifier; - { - FastMutex::ScopedLock lock(_mutex); - - EventHandlerMap::iterator it = _handlers.find(socket); - if (it != _handlers.end()) - { - if (it->second->hasObserver(observer)) - return true; - } - } - - return false; -} - - -void SocketReactor::removeEventHandler(const Socket& socket, const Poco::AbstractObserver& observer) -{ - NotifierPtr pNotifier; - { - FastMutex::ScopedLock lock(_mutex); - - EventHandlerMap::iterator it = _handlers.find(socket); - if (it != _handlers.end()) - { - pNotifier = it->second; - if (pNotifier->hasObserver(observer) && pNotifier->countObservers() == 1) - { - _handlers.erase(it); - } - } - } - if (pNotifier && pNotifier->hasObserver(observer)) - { - pNotifier->removeObserver(this, observer); - } - -} - - -void SocketReactor::onTimeout() -{ - dispatch(_pTimeoutNotification); -} - - -void SocketReactor::onIdle() -{ - dispatch(_pIdleNotification); -} - - -void SocketReactor::onShutdown() -{ - dispatch(_pShutdownNotification); -} - - -void SocketReactor::onBusy() -{ -} - - -void SocketReactor::dispatch(const Socket& socket, SocketNotification* pNotification) -{ - NotifierPtr pNotifier; - { - FastMutex::ScopedLock lock(_mutex); - EventHandlerMap::iterator it = _handlers.find(socket); - if (it != _handlers.end()) - pNotifier = it->second; - else - return; - } - dispatch(pNotifier, pNotification); -} - - -void SocketReactor::dispatch(SocketNotification* pNotification) -{ - std::vector<NotifierPtr> delegates; - delegates.reserve(_handlers.size()); - { - FastMutex::ScopedLock lock(_mutex); - for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it) - delegates.push_back(it->second); - } - for (std::vector<NotifierPtr>::iterator it = delegates.begin(); it != delegates.end(); ++it) - { - dispatch(*it, pNotification); - } -} - - -void SocketReactor::dispatch(NotifierPtr& pNotifier, SocketNotification* pNotification) -{ - try - { - pNotifier->dispatch(pNotification); - } - catch (Exception& exc) - { - ErrorHandler::handle(exc); - } - catch (std::exception& exc) - { - ErrorHandler::handle(exc); - } - catch (...) - { - ErrorHandler::handle(); - } -} - - -} } // namespace Poco::Net +// +// SocketReactor.cpp +// +// Library: Net +// Package: Reactor +// Module: SocketReactor +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/SocketReactor.h" +#include "Poco/Net/SocketNotification.h" +#include "Poco/Net/SocketNotifier.h" +#include "Poco/ErrorHandler.h" +#include "Poco/Thread.h" +#include "Poco/Exception.h" + + +using Poco::FastMutex; +using Poco::Exception; +using Poco::ErrorHandler; + + +namespace Poco { +namespace Net { + + +SocketReactor::SocketReactor(): + _stop(false), + _timeout(DEFAULT_TIMEOUT), + _pReadableNotification(new ReadableNotification(this)), + _pWritableNotification(new WritableNotification(this)), + _pErrorNotification(new ErrorNotification(this)), + _pTimeoutNotification(new TimeoutNotification(this)), + _pIdleNotification(new IdleNotification(this)), + _pShutdownNotification(new ShutdownNotification(this)), + _pThread(0) +{ +} + + +SocketReactor::SocketReactor(const Poco::Timespan& timeout): + _stop(false), + _timeout(timeout), + _pReadableNotification(new ReadableNotification(this)), + _pWritableNotification(new WritableNotification(this)), + _pErrorNotification(new ErrorNotification(this)), + _pTimeoutNotification(new TimeoutNotification(this)), + _pIdleNotification(new IdleNotification(this)), + _pShutdownNotification(new ShutdownNotification(this)), + _pThread(0) +{ +} + + +SocketReactor::~SocketReactor() +{ +} + + +void SocketReactor::run() +{ + _pThread = Thread::current(); + + Socket::SocketList readable; + Socket::SocketList writable; + Socket::SocketList except; + + while (!_stop) + { + try + { + readable.clear(); + writable.clear(); + except.clear(); + int nSockets = 0; + { + FastMutex::ScopedLock lock(_mutex); + for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it) + { + if (it->second->accepts(_pReadableNotification)) + { + readable.push_back(it->first); + nSockets++; + } + if (it->second->accepts(_pWritableNotification)) + { + writable.push_back(it->first); + nSockets++; + } + if (it->second->accepts(_pErrorNotification)) + { + except.push_back(it->first); + nSockets++; + } + } + } + if (nSockets == 0) + { + onIdle(); + Thread::trySleep(static_cast<long>(_timeout.totalMilliseconds())); + } + else if (Socket::select(readable, writable, except, _timeout)) + { + onBusy(); + + for (Socket::SocketList::iterator it = readable.begin(); it != readable.end(); ++it) + dispatch(*it, _pReadableNotification); + for (Socket::SocketList::iterator it = writable.begin(); it != writable.end(); ++it) + dispatch(*it, _pWritableNotification); + for (Socket::SocketList::iterator it = except.begin(); it != except.end(); ++it) + dispatch(*it, _pErrorNotification); + } + else onTimeout(); + } + catch (Exception& exc) + { + ErrorHandler::handle(exc); + } + catch (std::exception& exc) + { + ErrorHandler::handle(exc); + } + catch (...) + { + ErrorHandler::handle(); + } + } + onShutdown(); +} + + +void SocketReactor::stop() +{ + _stop = true; +} + + +void SocketReactor::wakeUp() +{ + if (_pThread) _pThread->wakeUp(); +} + + +void SocketReactor::setTimeout(const Poco::Timespan& timeout) +{ + _timeout = timeout; +} + + +const Poco::Timespan& SocketReactor::getTimeout() const +{ + return _timeout; +} + + +void SocketReactor::addEventHandler(const Socket& socket, const Poco::AbstractObserver& observer) +{ + NotifierPtr pNotifier; + { + FastMutex::ScopedLock lock(_mutex); + + EventHandlerMap::iterator it = _handlers.find(socket); + if (it == _handlers.end()) + { + pNotifier = new SocketNotifier(socket); + _handlers[socket] = pNotifier; + } + else pNotifier = it->second; + } + if (!pNotifier->hasObserver(observer)) + pNotifier->addObserver(this, observer); +} + + +bool SocketReactor::hasEventHandler(const Socket& socket, const Poco::AbstractObserver& observer) +{ + NotifierPtr pNotifier; + { + FastMutex::ScopedLock lock(_mutex); + + EventHandlerMap::iterator it = _handlers.find(socket); + if (it != _handlers.end()) + { + if (it->second->hasObserver(observer)) + return true; + } + } + + return false; +} + + +void SocketReactor::removeEventHandler(const Socket& socket, const Poco::AbstractObserver& observer) +{ + NotifierPtr pNotifier; + { + FastMutex::ScopedLock lock(_mutex); + + EventHandlerMap::iterator it = _handlers.find(socket); + if (it != _handlers.end()) + { + pNotifier = it->second; + if (pNotifier->hasObserver(observer) && pNotifier->countObservers() == 1) + { + _handlers.erase(it); + } + } + } + if (pNotifier && pNotifier->hasObserver(observer)) + { + pNotifier->removeObserver(this, observer); + } + +} + + +void SocketReactor::onTimeout() +{ + dispatch(_pTimeoutNotification); +} + + +void SocketReactor::onIdle() +{ + dispatch(_pIdleNotification); +} + + +void SocketReactor::onShutdown() +{ + dispatch(_pShutdownNotification); +} + + +void SocketReactor::onBusy() +{ +} + + +void SocketReactor::dispatch(const Socket& socket, SocketNotification* pNotification) +{ + NotifierPtr pNotifier; + { + FastMutex::ScopedLock lock(_mutex); + EventHandlerMap::iterator it = _handlers.find(socket); + if (it != _handlers.end()) + pNotifier = it->second; + else + return; + } + dispatch(pNotifier, pNotification); +} + + +void SocketReactor::dispatch(SocketNotification* pNotification) +{ + std::vector<NotifierPtr> delegates; + delegates.reserve(_handlers.size()); + { + FastMutex::ScopedLock lock(_mutex); + for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it) + delegates.push_back(it->second); + } + for (std::vector<NotifierPtr>::iterator it = delegates.begin(); it != delegates.end(); ++it) + { + dispatch(*it, pNotification); + } +} + + +void SocketReactor::dispatch(NotifierPtr& pNotifier, SocketNotification* pNotification) +{ + try + { + pNotifier->dispatch(pNotification); + } + catch (Exception& exc) + { + ErrorHandler::handle(exc); + } + catch (std::exception& exc) + { + ErrorHandler::handle(exc); + } + catch (...) + { + ErrorHandler::handle(); + } +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/SocketStream.cpp b/contrib/libs/poco/Net/src/SocketStream.cpp index 77ae8c2442..a23f4a627d 100644 --- a/contrib/libs/poco/Net/src/SocketStream.cpp +++ b/contrib/libs/poco/Net/src/SocketStream.cpp @@ -1,156 +1,156 @@ -// -// SocketStream.cpp -// -// Library: Net -// Package: Sockets -// Module: SocketStream -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/SocketStream.h" -#include "Poco/Net/StreamSocketImpl.h" -#include "Poco/Exception.h" - - -using Poco::BufferedBidirectionalStreamBuf; -using Poco::InvalidArgumentException; - - -namespace Poco { -namespace Net { - - -// -// SocketStreamBuf -// - - -SocketStreamBuf::SocketStreamBuf(const Socket& socket): - BufferedBidirectionalStreamBuf(STREAM_BUFFER_SIZE, std::ios::in | std::ios::out), - _pImpl(dynamic_cast<StreamSocketImpl*>(socket.impl())) -{ - if (_pImpl) - _pImpl->duplicate(); - else - throw InvalidArgumentException("Invalid or null SocketImpl passed to SocketStreamBuf"); -} - - -SocketStreamBuf::~SocketStreamBuf() -{ - _pImpl->release(); -} - - -int SocketStreamBuf::readFromDevice(char* buffer, std::streamsize length) -{ - return _pImpl->receiveBytes(buffer, (int) length); -} - - -int SocketStreamBuf::writeToDevice(const char* buffer, std::streamsize length) -{ - return _pImpl->sendBytes(buffer, (int) length); -} - - -// -// SocketIOS -// - - -SocketIOS::SocketIOS(const Socket& socket): - _buf(socket) -{ - poco_ios_init(&_buf); -} - - -SocketIOS::~SocketIOS() -{ - try - { - _buf.sync(); - } - catch (...) - { - } -} - - -SocketStreamBuf* SocketIOS::rdbuf() -{ - return &_buf; -} - - -void SocketIOS::close() -{ - _buf.sync(); - _buf.socketImpl()->close(); -} - - -StreamSocket SocketIOS::socket() const -{ - return StreamSocket(_buf.socketImpl()); -} - - -// -// SocketOutputStream -// - - -SocketOutputStream::SocketOutputStream(const Socket& socket): - SocketIOS(socket), - std::ostream(&_buf) -{ -} - - -SocketOutputStream::~SocketOutputStream() -{ -} - - -// -// SocketInputStream -// - - -SocketInputStream::SocketInputStream(const Socket& socket): - SocketIOS(socket), - std::istream(&_buf) -{ -} - - -SocketInputStream::~SocketInputStream() -{ -} - - -// -// SocketStream -// - - -SocketStream::SocketStream(const Socket& socket): - SocketIOS(socket), - std::iostream(&_buf) -{ -} - - -SocketStream::~SocketStream() -{ -} - - -} } // namespace Poco::Net +// +// SocketStream.cpp +// +// Library: Net +// Package: Sockets +// Module: SocketStream +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/SocketStream.h" +#include "Poco/Net/StreamSocketImpl.h" +#include "Poco/Exception.h" + + +using Poco::BufferedBidirectionalStreamBuf; +using Poco::InvalidArgumentException; + + +namespace Poco { +namespace Net { + + +// +// SocketStreamBuf +// + + +SocketStreamBuf::SocketStreamBuf(const Socket& socket): + BufferedBidirectionalStreamBuf(STREAM_BUFFER_SIZE, std::ios::in | std::ios::out), + _pImpl(dynamic_cast<StreamSocketImpl*>(socket.impl())) +{ + if (_pImpl) + _pImpl->duplicate(); + else + throw InvalidArgumentException("Invalid or null SocketImpl passed to SocketStreamBuf"); +} + + +SocketStreamBuf::~SocketStreamBuf() +{ + _pImpl->release(); +} + + +int SocketStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + return _pImpl->receiveBytes(buffer, (int) length); +} + + +int SocketStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + return _pImpl->sendBytes(buffer, (int) length); +} + + +// +// SocketIOS +// + + +SocketIOS::SocketIOS(const Socket& socket): + _buf(socket) +{ + poco_ios_init(&_buf); +} + + +SocketIOS::~SocketIOS() +{ + try + { + _buf.sync(); + } + catch (...) + { + } +} + + +SocketStreamBuf* SocketIOS::rdbuf() +{ + return &_buf; +} + + +void SocketIOS::close() +{ + _buf.sync(); + _buf.socketImpl()->close(); +} + + +StreamSocket SocketIOS::socket() const +{ + return StreamSocket(_buf.socketImpl()); +} + + +// +// SocketOutputStream +// + + +SocketOutputStream::SocketOutputStream(const Socket& socket): + SocketIOS(socket), + std::ostream(&_buf) +{ +} + + +SocketOutputStream::~SocketOutputStream() +{ +} + + +// +// SocketInputStream +// + + +SocketInputStream::SocketInputStream(const Socket& socket): + SocketIOS(socket), + std::istream(&_buf) +{ +} + + +SocketInputStream::~SocketInputStream() +{ +} + + +// +// SocketStream +// + + +SocketStream::SocketStream(const Socket& socket): + SocketIOS(socket), + std::iostream(&_buf) +{ +} + + +SocketStream::~SocketStream() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/StreamSocket.cpp b/contrib/libs/poco/Net/src/StreamSocket.cpp index 598d2991c6..6675027c6d 100644 --- a/contrib/libs/poco/Net/src/StreamSocket.cpp +++ b/contrib/libs/poco/Net/src/StreamSocket.cpp @@ -1,150 +1,150 @@ -// -// StreamSocket.cpp -// -// Library: Net -// Package: Sockets -// Module: StreamSocket -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/StreamSocket.h" -#include "Poco/Net/StreamSocketImpl.h" -#include "Poco/FIFOBuffer.h" -#include "Poco/Mutex.h" -#include "Poco/Exception.h" - - -using Poco::InvalidArgumentException; -using Poco::Mutex; -using Poco::ScopedLock; - - -namespace Poco { -namespace Net { - - -StreamSocket::StreamSocket(): Socket(new StreamSocketImpl) -{ -} - - -StreamSocket::StreamSocket(const SocketAddress& address): Socket(new StreamSocketImpl(address.family())) -{ - connect(address); -} - - -StreamSocket::StreamSocket(SocketAddress::Family family): Socket(new StreamSocketImpl(family)) -{ -} - - -StreamSocket::StreamSocket(const Socket& socket): Socket(socket) -{ - if (!dynamic_cast<StreamSocketImpl*>(impl())) - throw InvalidArgumentException("Cannot assign incompatible socket"); -} - - -StreamSocket::StreamSocket(SocketImpl* pImpl): Socket(pImpl) -{ - if (!dynamic_cast<StreamSocketImpl*>(impl())) - throw InvalidArgumentException("Cannot assign incompatible socket"); -} - - -StreamSocket::~StreamSocket() -{ -} - - -StreamSocket& StreamSocket::operator = (const Socket& socket) -{ - if (dynamic_cast<StreamSocketImpl*>(socket.impl())) - Socket::operator = (socket); - else - throw InvalidArgumentException("Cannot assign incompatible socket"); - return *this; -} - - -void StreamSocket::connect(const SocketAddress& address) -{ - impl()->connect(address); -} - - -void StreamSocket::connect(const SocketAddress& address, const Poco::Timespan& timeout) -{ - impl()->connect(address, timeout); -} - - -void StreamSocket::connectNB(const SocketAddress& address) -{ - impl()->connectNB(address); -} - - -void StreamSocket::shutdownReceive() -{ - impl()->shutdownReceive(); -} - - -void StreamSocket::shutdownSend() -{ - impl()->shutdownSend(); -} - - -void StreamSocket::shutdown() -{ - impl()->shutdown(); -} - - -int StreamSocket::sendBytes(const void* buffer, int length, int flags) -{ - return impl()->sendBytes(buffer, length, flags); -} - - -int StreamSocket::sendBytes(FIFOBuffer& fifoBuf) -{ - ScopedLock<Mutex> l(fifoBuf.mutex()); - - int ret = impl()->sendBytes(fifoBuf.begin(), (int) fifoBuf.used()); - if (ret > 0) fifoBuf.drain(ret); - return ret; -} - - -int StreamSocket::receiveBytes(void* buffer, int length, int flags) -{ - return impl()->receiveBytes(buffer, length, flags); -} - - -int StreamSocket::receiveBytes(FIFOBuffer& fifoBuf) -{ - ScopedLock<Mutex> l(fifoBuf.mutex()); - - int ret = impl()->receiveBytes(fifoBuf.next(), (int)fifoBuf.available()); - if (ret > 0) fifoBuf.advance(ret); - return ret; -} - - -void StreamSocket::sendUrgent(unsigned char data) -{ - impl()->sendUrgent(data); -} - - -} } // namespace Poco::Net +// +// StreamSocket.cpp +// +// Library: Net +// Package: Sockets +// Module: StreamSocket +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/StreamSocket.h" +#include "Poco/Net/StreamSocketImpl.h" +#include "Poco/FIFOBuffer.h" +#include "Poco/Mutex.h" +#include "Poco/Exception.h" + + +using Poco::InvalidArgumentException; +using Poco::Mutex; +using Poco::ScopedLock; + + +namespace Poco { +namespace Net { + + +StreamSocket::StreamSocket(): Socket(new StreamSocketImpl) +{ +} + + +StreamSocket::StreamSocket(const SocketAddress& address): Socket(new StreamSocketImpl(address.family())) +{ + connect(address); +} + + +StreamSocket::StreamSocket(SocketAddress::Family family): Socket(new StreamSocketImpl(family)) +{ +} + + +StreamSocket::StreamSocket(const Socket& socket): Socket(socket) +{ + if (!dynamic_cast<StreamSocketImpl*>(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +StreamSocket::StreamSocket(SocketImpl* pImpl): Socket(pImpl) +{ + if (!dynamic_cast<StreamSocketImpl*>(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +StreamSocket::~StreamSocket() +{ +} + + +StreamSocket& StreamSocket::operator = (const Socket& socket) +{ + if (dynamic_cast<StreamSocketImpl*>(socket.impl())) + Socket::operator = (socket); + else + throw InvalidArgumentException("Cannot assign incompatible socket"); + return *this; +} + + +void StreamSocket::connect(const SocketAddress& address) +{ + impl()->connect(address); +} + + +void StreamSocket::connect(const SocketAddress& address, const Poco::Timespan& timeout) +{ + impl()->connect(address, timeout); +} + + +void StreamSocket::connectNB(const SocketAddress& address) +{ + impl()->connectNB(address); +} + + +void StreamSocket::shutdownReceive() +{ + impl()->shutdownReceive(); +} + + +void StreamSocket::shutdownSend() +{ + impl()->shutdownSend(); +} + + +void StreamSocket::shutdown() +{ + impl()->shutdown(); +} + + +int StreamSocket::sendBytes(const void* buffer, int length, int flags) +{ + return impl()->sendBytes(buffer, length, flags); +} + + +int StreamSocket::sendBytes(FIFOBuffer& fifoBuf) +{ + ScopedLock<Mutex> l(fifoBuf.mutex()); + + int ret = impl()->sendBytes(fifoBuf.begin(), (int) fifoBuf.used()); + if (ret > 0) fifoBuf.drain(ret); + return ret; +} + + +int StreamSocket::receiveBytes(void* buffer, int length, int flags) +{ + return impl()->receiveBytes(buffer, length, flags); +} + + +int StreamSocket::receiveBytes(FIFOBuffer& fifoBuf) +{ + ScopedLock<Mutex> l(fifoBuf.mutex()); + + int ret = impl()->receiveBytes(fifoBuf.next(), (int)fifoBuf.available()); + if (ret > 0) fifoBuf.advance(ret); + return ret; +} + + +void StreamSocket::sendUrgent(unsigned char data) +{ + impl()->sendUrgent(data); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/StreamSocketImpl.cpp b/contrib/libs/poco/Net/src/StreamSocketImpl.cpp index 8116942db5..f1f0885f25 100644 --- a/contrib/libs/poco/Net/src/StreamSocketImpl.cpp +++ b/contrib/libs/poco/Net/src/StreamSocketImpl.cpp @@ -1,77 +1,77 @@ -// -// StreamSocketImpl.cpp -// -// Library: Net -// Package: Sockets -// Module: StreamSocketImpl -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/StreamSocketImpl.h" -#include "Poco/Exception.h" -#include "Poco/Thread.h" - - -namespace Poco { -namespace Net { - - -StreamSocketImpl::StreamSocketImpl() -{ -} - - -StreamSocketImpl::StreamSocketImpl(SocketAddress::Family family) -{ - if (family == SocketAddress::IPv4) - init(AF_INET); -#if defined(POCO_HAVE_IPv6) - else if (family == SocketAddress::IPv6) - init(AF_INET6); -#endif -#if defined(POCO_OS_FAMILY_UNIX) - else if (family == SocketAddress::UNIX_LOCAL) - init(AF_UNIX); -#endif - else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to StreamSocketImpl"); -} - - -StreamSocketImpl::StreamSocketImpl(poco_socket_t sockfd): SocketImpl(sockfd) -{ -} - - -StreamSocketImpl::~StreamSocketImpl() -{ -} - - -int StreamSocketImpl::sendBytes(const void* buffer, int length, int flags) -{ - const char* p = reinterpret_cast<const char*>(buffer); - int remaining = length; - int sent = 0; - bool blocking = getBlocking(); - while (remaining > 0) - { - int n = SocketImpl::sendBytes(p, remaining, flags); - poco_assert_dbg (n >= 0); - p += n; - sent += n; - remaining -= n; - if (blocking && remaining > 0) - Poco::Thread::yield(); - else - break; - } - return sent; -} - - -} } // namespace Poco::Net +// +// StreamSocketImpl.cpp +// +// Library: Net +// Package: Sockets +// Module: StreamSocketImpl +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/StreamSocketImpl.h" +#include "Poco/Exception.h" +#include "Poco/Thread.h" + + +namespace Poco { +namespace Net { + + +StreamSocketImpl::StreamSocketImpl() +{ +} + + +StreamSocketImpl::StreamSocketImpl(SocketAddress::Family family) +{ + if (family == SocketAddress::IPv4) + init(AF_INET); +#if defined(POCO_HAVE_IPv6) + else if (family == SocketAddress::IPv6) + init(AF_INET6); +#endif +#if defined(POCO_OS_FAMILY_UNIX) + else if (family == SocketAddress::UNIX_LOCAL) + init(AF_UNIX); +#endif + else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to StreamSocketImpl"); +} + + +StreamSocketImpl::StreamSocketImpl(poco_socket_t sockfd): SocketImpl(sockfd) +{ +} + + +StreamSocketImpl::~StreamSocketImpl() +{ +} + + +int StreamSocketImpl::sendBytes(const void* buffer, int length, int flags) +{ + const char* p = reinterpret_cast<const char*>(buffer); + int remaining = length; + int sent = 0; + bool blocking = getBlocking(); + while (remaining > 0) + { + int n = SocketImpl::sendBytes(p, remaining, flags); + poco_assert_dbg (n >= 0); + p += n; + sent += n; + remaining -= n; + if (blocking && remaining > 0) + Poco::Thread::yield(); + else + break; + } + return sent; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/StringPartSource.cpp b/contrib/libs/poco/Net/src/StringPartSource.cpp index a512449f69..d007155a6c 100644 --- a/contrib/libs/poco/Net/src/StringPartSource.cpp +++ b/contrib/libs/poco/Net/src/StringPartSource.cpp @@ -1,67 +1,67 @@ -// -// StringPartSource.cpp -// -// Library: Net -// Package: Messages -// Module: StringPartSource -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/StringPartSource.h" - - -namespace Poco { -namespace Net { - - -StringPartSource::StringPartSource(const std::string& str): - PartSource("text/plain"), - _istr(str) -{ -} - - -StringPartSource::StringPartSource(const std::string& str, const std::string& mediaType): - PartSource(mediaType), - _istr(str) -{ -} - - -StringPartSource::StringPartSource(const std::string& str, const std::string& mediaType, const std::string& filename): - PartSource(mediaType), - _istr(str), - _filename(filename) -{ -} - - -StringPartSource::~StringPartSource() -{ -} - - -std::istream& StringPartSource::stream() -{ - return _istr; -} - - -const std::string& StringPartSource::filename() const -{ - return _filename; -} - - -std::streamsize StringPartSource::getContentLength() const -{ - return _istr.str().length(); -} - - -} } // namespace Poco::Net +// +// StringPartSource.cpp +// +// Library: Net +// Package: Messages +// Module: StringPartSource +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/StringPartSource.h" + + +namespace Poco { +namespace Net { + + +StringPartSource::StringPartSource(const std::string& str): + PartSource("text/plain"), + _istr(str) +{ +} + + +StringPartSource::StringPartSource(const std::string& str, const std::string& mediaType): + PartSource(mediaType), + _istr(str) +{ +} + + +StringPartSource::StringPartSource(const std::string& str, const std::string& mediaType, const std::string& filename): + PartSource(mediaType), + _istr(str), + _filename(filename) +{ +} + + +StringPartSource::~StringPartSource() +{ +} + + +std::istream& StringPartSource::stream() +{ + return _istr; +} + + +const std::string& StringPartSource::filename() const +{ + return _filename; +} + + +std::streamsize StringPartSource::getContentLength() const +{ + return _istr.str().length(); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/TCPServer.cpp b/contrib/libs/poco/Net/src/TCPServer.cpp index 7a7282f785..99d55f5a84 100644 --- a/contrib/libs/poco/Net/src/TCPServer.cpp +++ b/contrib/libs/poco/Net/src/TCPServer.cpp @@ -1,243 +1,243 @@ -// -// TCPServer.cpp -// -// Library: Net -// Package: TCPServer -// Module: TCPServer -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/TCPServer.h" -#include "Poco/Net/TCPServerDispatcher.h" -#include "Poco/Net/TCPServerConnection.h" -#include "Poco/Net/TCPServerConnectionFactory.h" -#include "Poco/Timespan.h" -#include "Poco/Exception.h" -#include "Poco/ErrorHandler.h" - - -using Poco::ErrorHandler; - - -namespace Poco { -namespace Net { - - -// -// TCPServerConnectionFilter -// - - -TCPServerConnectionFilter::~TCPServerConnectionFilter() -{ -} - - -// -// TCPServer -// - - -TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::UInt16 portNumber, TCPServerParams::Ptr pParams): - _socket(ServerSocket(portNumber)), - _thread(threadName(_socket)), - _stopped(true) -{ - Poco::ThreadPool& pool = Poco::ThreadPool::defaultPool(); - if (pParams) - { - int toAdd = pParams->getMaxThreads() - pool.capacity(); - if (toAdd > 0) pool.addCapacity(toAdd); - } - _pDispatcher = new TCPServerDispatcher(pFactory, pool, pParams); - -} - - -TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, const ServerSocket& socket, TCPServerParams::Ptr pParams): - _socket(socket), - _thread(threadName(socket)), - _stopped(true) -{ - Poco::ThreadPool& pool = Poco::ThreadPool::defaultPool(); - if (pParams) - { - int toAdd = pParams->getMaxThreads() - pool.capacity(); - if (toAdd > 0) pool.addCapacity(toAdd); - } - _pDispatcher = new TCPServerDispatcher(pFactory, pool, pParams); -} - - -TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::ThreadPool& threadPool, const ServerSocket& socket, TCPServerParams::Ptr pParams): - _socket(socket), - _pDispatcher(new TCPServerDispatcher(pFactory, threadPool, pParams)), - _thread(threadName(socket)), - _stopped(true) -{ -} - - -TCPServer::~TCPServer() -{ - try - { - stop(); - _pDispatcher->release(); - } - catch (...) - { - poco_unexpected(); - } -} - - -const TCPServerParams& TCPServer::params() const -{ - return _pDispatcher->params(); -} - - -void TCPServer::start() -{ - poco_assert (_stopped); - - _stopped = false; - _thread.start(*this); -} - - -void TCPServer::stop() -{ - if (!_stopped) - { - _stopped = true; - _thread.join(); - _pDispatcher->stop(); - } -} - - -void TCPServer::run() -{ - while (!_stopped) - { - Poco::Timespan timeout(250000); - try - { - if (_socket.poll(timeout, Socket::SELECT_READ)) - { - try - { - StreamSocket ss = _socket.acceptConnection(); - - if (!_pConnectionFilter || _pConnectionFilter->accept(ss)) - { - // enable nodelay per default: OSX really needs that -#if defined(POCO_OS_FAMILY_UNIX) - if (ss.address().family() != AddressFamily::UNIX_LOCAL) -#endif - { - ss.setNoDelay(true); - } - _pDispatcher->enqueue(ss); - } - } - catch (Poco::Exception& exc) - { - ErrorHandler::handle(exc); - } - catch (std::exception& exc) - { - ErrorHandler::handle(exc); - } - catch (...) - { - ErrorHandler::handle(); - } - } - } - catch (Poco::Exception& exc) - { - ErrorHandler::handle(exc); - // possibly a resource issue since poll() failed; - // give some time to recover before trying again - Poco::Thread::sleep(50); - } - } -} - - -int TCPServer::currentThreads() const -{ - return _pDispatcher->currentThreads(); -} - - -int TCPServer::maxThreads() const -{ - return _pDispatcher->maxThreads(); -} - - -int TCPServer::totalConnections() const -{ - return _pDispatcher->totalConnections(); -} - - -int TCPServer::currentConnections() const -{ - return _pDispatcher->currentConnections(); -} - - -int TCPServer::maxConcurrentConnections() const -{ - return _pDispatcher->maxConcurrentConnections(); -} - - -int TCPServer::queuedConnections() const -{ - return _pDispatcher->queuedConnections(); -} - - -int TCPServer::refusedConnections() const -{ - return _pDispatcher->refusedConnections(); -} - - -void TCPServer::setConnectionFilter(const TCPServerConnectionFilter::Ptr& pConnectionFilter) -{ - poco_assert (_stopped); - - _pConnectionFilter = pConnectionFilter; -} - - -std::string TCPServer::threadName(const ServerSocket& socket) -{ -#if _WIN32_WCE == 0x0800 - // Workaround for WEC2013: only the first call to getsockname() - // succeeds. To mitigate the impact of this bug, do not call - // socket.address(), which calls getsockname(), here. - std::string name("TCPServer"); - #pragma message("Using WEC2013 getsockname() workaround in TCPServer::threadName(). Remove when no longer needed.") -#else - std::string name("TCPServer: "); - name.append(socket.address().toString()); -#endif - return name; - -} - - -} } // namespace Poco::Net +// +// TCPServer.cpp +// +// Library: Net +// Package: TCPServer +// Module: TCPServer +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/TCPServer.h" +#include "Poco/Net/TCPServerDispatcher.h" +#include "Poco/Net/TCPServerConnection.h" +#include "Poco/Net/TCPServerConnectionFactory.h" +#include "Poco/Timespan.h" +#include "Poco/Exception.h" +#include "Poco/ErrorHandler.h" + + +using Poco::ErrorHandler; + + +namespace Poco { +namespace Net { + + +// +// TCPServerConnectionFilter +// + + +TCPServerConnectionFilter::~TCPServerConnectionFilter() +{ +} + + +// +// TCPServer +// + + +TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::UInt16 portNumber, TCPServerParams::Ptr pParams): + _socket(ServerSocket(portNumber)), + _thread(threadName(_socket)), + _stopped(true) +{ + Poco::ThreadPool& pool = Poco::ThreadPool::defaultPool(); + if (pParams) + { + int toAdd = pParams->getMaxThreads() - pool.capacity(); + if (toAdd > 0) pool.addCapacity(toAdd); + } + _pDispatcher = new TCPServerDispatcher(pFactory, pool, pParams); + +} + + +TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, const ServerSocket& socket, TCPServerParams::Ptr pParams): + _socket(socket), + _thread(threadName(socket)), + _stopped(true) +{ + Poco::ThreadPool& pool = Poco::ThreadPool::defaultPool(); + if (pParams) + { + int toAdd = pParams->getMaxThreads() - pool.capacity(); + if (toAdd > 0) pool.addCapacity(toAdd); + } + _pDispatcher = new TCPServerDispatcher(pFactory, pool, pParams); +} + + +TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::ThreadPool& threadPool, const ServerSocket& socket, TCPServerParams::Ptr pParams): + _socket(socket), + _pDispatcher(new TCPServerDispatcher(pFactory, threadPool, pParams)), + _thread(threadName(socket)), + _stopped(true) +{ +} + + +TCPServer::~TCPServer() +{ + try + { + stop(); + _pDispatcher->release(); + } + catch (...) + { + poco_unexpected(); + } +} + + +const TCPServerParams& TCPServer::params() const +{ + return _pDispatcher->params(); +} + + +void TCPServer::start() +{ + poco_assert (_stopped); + + _stopped = false; + _thread.start(*this); +} + + +void TCPServer::stop() +{ + if (!_stopped) + { + _stopped = true; + _thread.join(); + _pDispatcher->stop(); + } +} + + +void TCPServer::run() +{ + while (!_stopped) + { + Poco::Timespan timeout(250000); + try + { + if (_socket.poll(timeout, Socket::SELECT_READ)) + { + try + { + StreamSocket ss = _socket.acceptConnection(); + + if (!_pConnectionFilter || _pConnectionFilter->accept(ss)) + { + // enable nodelay per default: OSX really needs that +#if defined(POCO_OS_FAMILY_UNIX) + if (ss.address().family() != AddressFamily::UNIX_LOCAL) +#endif + { + ss.setNoDelay(true); + } + _pDispatcher->enqueue(ss); + } + } + catch (Poco::Exception& exc) + { + ErrorHandler::handle(exc); + } + catch (std::exception& exc) + { + ErrorHandler::handle(exc); + } + catch (...) + { + ErrorHandler::handle(); + } + } + } + catch (Poco::Exception& exc) + { + ErrorHandler::handle(exc); + // possibly a resource issue since poll() failed; + // give some time to recover before trying again + Poco::Thread::sleep(50); + } + } +} + + +int TCPServer::currentThreads() const +{ + return _pDispatcher->currentThreads(); +} + + +int TCPServer::maxThreads() const +{ + return _pDispatcher->maxThreads(); +} + + +int TCPServer::totalConnections() const +{ + return _pDispatcher->totalConnections(); +} + + +int TCPServer::currentConnections() const +{ + return _pDispatcher->currentConnections(); +} + + +int TCPServer::maxConcurrentConnections() const +{ + return _pDispatcher->maxConcurrentConnections(); +} + + +int TCPServer::queuedConnections() const +{ + return _pDispatcher->queuedConnections(); +} + + +int TCPServer::refusedConnections() const +{ + return _pDispatcher->refusedConnections(); +} + + +void TCPServer::setConnectionFilter(const TCPServerConnectionFilter::Ptr& pConnectionFilter) +{ + poco_assert (_stopped); + + _pConnectionFilter = pConnectionFilter; +} + + +std::string TCPServer::threadName(const ServerSocket& socket) +{ +#if _WIN32_WCE == 0x0800 + // Workaround for WEC2013: only the first call to getsockname() + // succeeds. To mitigate the impact of this bug, do not call + // socket.address(), which calls getsockname(), here. + std::string name("TCPServer"); + #pragma message("Using WEC2013 getsockname() workaround in TCPServer::threadName(). Remove when no longer needed.") +#else + std::string name("TCPServer: "); + name.append(socket.address().toString()); +#endif + return name; + +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/TCPServerConnection.cpp b/contrib/libs/poco/Net/src/TCPServerConnection.cpp index 1072b182c2..4af6c8027a 100644 --- a/contrib/libs/poco/Net/src/TCPServerConnection.cpp +++ b/contrib/libs/poco/Net/src/TCPServerConnection.cpp @@ -1,60 +1,60 @@ -// -// TCPServerConnection.cpp -// -// Library: Net -// Package: TCPServer -// Module: TCPServerConnection -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/TCPServerConnection.h" -#include "Poco/Exception.h" -#include "Poco/ErrorHandler.h" - - -using Poco::Exception; -using Poco::ErrorHandler; - - -namespace Poco { -namespace Net { - - -TCPServerConnection::TCPServerConnection(const StreamSocket& socket): - _socket(socket) -{ -} - - -TCPServerConnection::~TCPServerConnection() -{ -} - - -void TCPServerConnection::start() -{ - try - { - run(); - } - catch (Exception& exc) - { - ErrorHandler::handle(exc); - } - catch (std::exception& exc) - { - ErrorHandler::handle(exc); - } - catch (...) - { - ErrorHandler::handle(); - } -} - - -} } // namespace Poco::Net +// +// TCPServerConnection.cpp +// +// Library: Net +// Package: TCPServer +// Module: TCPServerConnection +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/TCPServerConnection.h" +#include "Poco/Exception.h" +#include "Poco/ErrorHandler.h" + + +using Poco::Exception; +using Poco::ErrorHandler; + + +namespace Poco { +namespace Net { + + +TCPServerConnection::TCPServerConnection(const StreamSocket& socket): + _socket(socket) +{ +} + + +TCPServerConnection::~TCPServerConnection() +{ +} + + +void TCPServerConnection::start() +{ + try + { + run(); + } + catch (Exception& exc) + { + ErrorHandler::handle(exc); + } + catch (std::exception& exc) + { + ErrorHandler::handle(exc); + } + catch (...) + { + ErrorHandler::handle(); + } +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/TCPServerConnectionFactory.cpp b/contrib/libs/poco/Net/src/TCPServerConnectionFactory.cpp index a861e433d9..074fda5739 100644 --- a/contrib/libs/poco/Net/src/TCPServerConnectionFactory.cpp +++ b/contrib/libs/poco/Net/src/TCPServerConnectionFactory.cpp @@ -1,32 +1,32 @@ -// -// TCPServerConnectionFactory.cpp -// -// Library: Net -// Package: TCPServer -// Module: TCPServerConnectionFactory -// -// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/TCPServerConnectionFactory.h" - - -namespace Poco { -namespace Net { - - -TCPServerConnectionFactory::TCPServerConnectionFactory() -{ -} - - -TCPServerConnectionFactory::~TCPServerConnectionFactory() -{ -} - - -} } // namespace Poco::Net +// +// TCPServerConnectionFactory.cpp +// +// Library: Net +// Package: TCPServer +// Module: TCPServerConnectionFactory +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/TCPServerConnectionFactory.h" + + +namespace Poco { +namespace Net { + + +TCPServerConnectionFactory::TCPServerConnectionFactory() +{ +} + + +TCPServerConnectionFactory::~TCPServerConnectionFactory() +{ +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/TCPServerDispatcher.cpp b/contrib/libs/poco/Net/src/TCPServerDispatcher.cpp index 01474ec526..af40bb9925 100644 --- a/contrib/libs/poco/Net/src/TCPServerDispatcher.cpp +++ b/contrib/libs/poco/Net/src/TCPServerDispatcher.cpp @@ -1,256 +1,256 @@ -// -// TCPServerDispatcher.cpp -// -// Library: Net -// Package: TCPServer -// Module: TCPServerDispatcher -// -// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/TCPServerDispatcher.h" -#include "Poco/Net/TCPServerConnectionFactory.h" -#include "Poco/Notification.h" -#include "Poco/AutoPtr.h" -#include <memory> - - -using Poco::Notification; -using Poco::FastMutex; -using Poco::AutoPtr; - - -namespace Poco { -namespace Net { - - -class TCPConnectionNotification: public Notification -{ -public: - TCPConnectionNotification(const StreamSocket& socket): - _socket(socket) - { - } - - ~TCPConnectionNotification() - { - } - - const StreamSocket& socket() const - { - return _socket; - } - -private: - StreamSocket _socket; -}; - - -TCPServerDispatcher::TCPServerDispatcher(TCPServerConnectionFactory::Ptr pFactory, Poco::ThreadPool& threadPool, TCPServerParams::Ptr pParams): - _rc(1), - _pParams(pParams), - _currentThreads(0), - _totalConnections(0), - _currentConnections(0), - _maxConcurrentConnections(0), - _refusedConnections(0), - _stopped(false), - _pConnectionFactory(pFactory), - _threadPool(threadPool) -{ - poco_check_ptr (pFactory); - - if (!_pParams) - _pParams = new TCPServerParams; - - if (_pParams->getMaxThreads() == 0) - _pParams->setMaxThreads(threadPool.capacity()); -} - - -TCPServerDispatcher::~TCPServerDispatcher() -{ -} - - -void TCPServerDispatcher::duplicate() -{ - _mutex.lock(); - ++_rc; - _mutex.unlock(); -} - - -void TCPServerDispatcher::release() -{ - _mutex.lock(); - int rc = --_rc; - _mutex.unlock(); - if (rc == 0) delete this; -} - - -void TCPServerDispatcher::run() -{ - try - { - AutoPtr<TCPServerDispatcher> guard(this, true); // ensure object stays alive - - int idleTime = (int) _pParams->getThreadIdleTime().totalMilliseconds(); - - for (;;) - { - AutoPtr<Notification> pNf = _queue.waitDequeueNotification(idleTime); - if (pNf) - { - TCPConnectionNotification* pCNf = dynamic_cast<TCPConnectionNotification*>(pNf.get()); - if (pCNf) - { -#ifndef POCO_ENABLE_CPP11 - std::auto_ptr<TCPServerConnection> pConnection(_pConnectionFactory->createConnection(pCNf->socket())); -#else - std::unique_ptr<TCPServerConnection> pConnection(_pConnectionFactory->createConnection(pCNf->socket())); -#endif // POCO_ENABLE_CPP11 - poco_check_ptr(pConnection.get()); - beginConnection(); - pConnection->start(); - endConnection(); - } - } - - FastMutex::ScopedLock lock(_mutex); - if (_stopped || (_currentThreads > 1 && _queue.empty())) - { - --_currentThreads; - break; - } - } - } - catch (...) - { - FastMutex::ScopedLock lock(_mutex); - --_currentThreads; - throw; - } -} - - -namespace -{ - static const std::string threadName("TCPServerConnection"); -} - - -void TCPServerDispatcher::enqueue(const StreamSocket& socket) -{ - FastMutex::ScopedLock lock(_mutex); - - if (_queue.size() < _pParams->getMaxQueued()) - { - if (!_queue.hasIdleThreads() && _currentThreads < _pParams->getMaxThreads()) - { - try - { - _threadPool.startWithPriority(_pParams->getThreadPriority(), *this, threadName); - ++_currentThreads; - } - catch (Poco::Exception&) - { - ++_refusedConnections; - return; - } - } - _queue.enqueueNotification(new TCPConnectionNotification(socket)); - } - else - { - ++_refusedConnections; - } -} - - -void TCPServerDispatcher::stop() -{ - _stopped = true; - _queue.clear(); - _queue.wakeUpAll(); -} - - -int TCPServerDispatcher::currentThreads() const -{ - FastMutex::ScopedLock lock(_mutex); - - return _currentThreads; -} - -int TCPServerDispatcher::maxThreads() const -{ - FastMutex::ScopedLock lock(_mutex); - - return _threadPool.capacity(); -} - - -int TCPServerDispatcher::totalConnections() const -{ - FastMutex::ScopedLock lock(_mutex); - - return _totalConnections; -} - - -int TCPServerDispatcher::currentConnections() const -{ - FastMutex::ScopedLock lock(_mutex); - - return _currentConnections; -} - - -int TCPServerDispatcher::maxConcurrentConnections() const -{ - FastMutex::ScopedLock lock(_mutex); - - return _maxConcurrentConnections; -} - - -int TCPServerDispatcher::queuedConnections() const -{ - return _queue.size(); -} - - -int TCPServerDispatcher::refusedConnections() const -{ - FastMutex::ScopedLock lock(_mutex); - - return _refusedConnections; -} - - -void TCPServerDispatcher::beginConnection() -{ - FastMutex::ScopedLock lock(_mutex); - - ++_totalConnections; - ++_currentConnections; - if (_currentConnections > _maxConcurrentConnections) - _maxConcurrentConnections = _currentConnections; -} - - -void TCPServerDispatcher::endConnection() -{ - FastMutex::ScopedLock lock(_mutex); - - --_currentConnections; -} - - -} } // namespace Poco::Net +// +// TCPServerDispatcher.cpp +// +// Library: Net +// Package: TCPServer +// Module: TCPServerDispatcher +// +// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/TCPServerDispatcher.h" +#include "Poco/Net/TCPServerConnectionFactory.h" +#include "Poco/Notification.h" +#include "Poco/AutoPtr.h" +#include <memory> + + +using Poco::Notification; +using Poco::FastMutex; +using Poco::AutoPtr; + + +namespace Poco { +namespace Net { + + +class TCPConnectionNotification: public Notification +{ +public: + TCPConnectionNotification(const StreamSocket& socket): + _socket(socket) + { + } + + ~TCPConnectionNotification() + { + } + + const StreamSocket& socket() const + { + return _socket; + } + +private: + StreamSocket _socket; +}; + + +TCPServerDispatcher::TCPServerDispatcher(TCPServerConnectionFactory::Ptr pFactory, Poco::ThreadPool& threadPool, TCPServerParams::Ptr pParams): + _rc(1), + _pParams(pParams), + _currentThreads(0), + _totalConnections(0), + _currentConnections(0), + _maxConcurrentConnections(0), + _refusedConnections(0), + _stopped(false), + _pConnectionFactory(pFactory), + _threadPool(threadPool) +{ + poco_check_ptr (pFactory); + + if (!_pParams) + _pParams = new TCPServerParams; + + if (_pParams->getMaxThreads() == 0) + _pParams->setMaxThreads(threadPool.capacity()); +} + + +TCPServerDispatcher::~TCPServerDispatcher() +{ +} + + +void TCPServerDispatcher::duplicate() +{ + _mutex.lock(); + ++_rc; + _mutex.unlock(); +} + + +void TCPServerDispatcher::release() +{ + _mutex.lock(); + int rc = --_rc; + _mutex.unlock(); + if (rc == 0) delete this; +} + + +void TCPServerDispatcher::run() +{ + try + { + AutoPtr<TCPServerDispatcher> guard(this, true); // ensure object stays alive + + int idleTime = (int) _pParams->getThreadIdleTime().totalMilliseconds(); + + for (;;) + { + AutoPtr<Notification> pNf = _queue.waitDequeueNotification(idleTime); + if (pNf) + { + TCPConnectionNotification* pCNf = dynamic_cast<TCPConnectionNotification*>(pNf.get()); + if (pCNf) + { +#ifndef POCO_ENABLE_CPP11 + std::auto_ptr<TCPServerConnection> pConnection(_pConnectionFactory->createConnection(pCNf->socket())); +#else + std::unique_ptr<TCPServerConnection> pConnection(_pConnectionFactory->createConnection(pCNf->socket())); +#endif // POCO_ENABLE_CPP11 + poco_check_ptr(pConnection.get()); + beginConnection(); + pConnection->start(); + endConnection(); + } + } + + FastMutex::ScopedLock lock(_mutex); + if (_stopped || (_currentThreads > 1 && _queue.empty())) + { + --_currentThreads; + break; + } + } + } + catch (...) + { + FastMutex::ScopedLock lock(_mutex); + --_currentThreads; + throw; + } +} + + +namespace +{ + static const std::string threadName("TCPServerConnection"); +} + + +void TCPServerDispatcher::enqueue(const StreamSocket& socket) +{ + FastMutex::ScopedLock lock(_mutex); + + if (_queue.size() < _pParams->getMaxQueued()) + { + if (!_queue.hasIdleThreads() && _currentThreads < _pParams->getMaxThreads()) + { + try + { + _threadPool.startWithPriority(_pParams->getThreadPriority(), *this, threadName); + ++_currentThreads; + } + catch (Poco::Exception&) + { + ++_refusedConnections; + return; + } + } + _queue.enqueueNotification(new TCPConnectionNotification(socket)); + } + else + { + ++_refusedConnections; + } +} + + +void TCPServerDispatcher::stop() +{ + _stopped = true; + _queue.clear(); + _queue.wakeUpAll(); +} + + +int TCPServerDispatcher::currentThreads() const +{ + FastMutex::ScopedLock lock(_mutex); + + return _currentThreads; +} + +int TCPServerDispatcher::maxThreads() const +{ + FastMutex::ScopedLock lock(_mutex); + + return _threadPool.capacity(); +} + + +int TCPServerDispatcher::totalConnections() const +{ + FastMutex::ScopedLock lock(_mutex); + + return _totalConnections; +} + + +int TCPServerDispatcher::currentConnections() const +{ + FastMutex::ScopedLock lock(_mutex); + + return _currentConnections; +} + + +int TCPServerDispatcher::maxConcurrentConnections() const +{ + FastMutex::ScopedLock lock(_mutex); + + return _maxConcurrentConnections; +} + + +int TCPServerDispatcher::queuedConnections() const +{ + return _queue.size(); +} + + +int TCPServerDispatcher::refusedConnections() const +{ + FastMutex::ScopedLock lock(_mutex); + + return _refusedConnections; +} + + +void TCPServerDispatcher::beginConnection() +{ + FastMutex::ScopedLock lock(_mutex); + + ++_totalConnections; + ++_currentConnections; + if (_currentConnections > _maxConcurrentConnections) + _maxConcurrentConnections = _currentConnections; +} + + +void TCPServerDispatcher::endConnection() +{ + FastMutex::ScopedLock lock(_mutex); + + --_currentConnections; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/TCPServerParams.cpp b/contrib/libs/poco/Net/src/TCPServerParams.cpp index 6a90374abc..9c97417c97 100644 --- a/contrib/libs/poco/Net/src/TCPServerParams.cpp +++ b/contrib/libs/poco/Net/src/TCPServerParams.cpp @@ -1,64 +1,64 @@ -// -// TCPServerParams.cpp -// -// Library: Net -// Package: TCPServer -// Module: TCPServerParams -// -// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/TCPServerParams.h" - - -namespace Poco { -namespace Net { - - -TCPServerParams::TCPServerParams(): - _threadIdleTime(10000000), - _maxThreads(0), - _maxQueued(64), - _threadPriority(Poco::Thread::PRIO_NORMAL) -{ -} - - -TCPServerParams::~TCPServerParams() -{ -} - - -void TCPServerParams::setThreadIdleTime(const Poco::Timespan& milliseconds) -{ - _threadIdleTime = milliseconds; -} - - -void TCPServerParams::setMaxThreads(int count) -{ - poco_assert (count > 0); - - _maxThreads = count; -} - - -void TCPServerParams::setMaxQueued(int count) -{ - poco_assert (count >= 0); - - _maxQueued = count; -} - - -void TCPServerParams::setThreadPriority(Poco::Thread::Priority prio) -{ - _threadPriority = prio; -} - - -} } // namespace Poco::Net +// +// TCPServerParams.cpp +// +// Library: Net +// Package: TCPServer +// Module: TCPServerParams +// +// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/TCPServerParams.h" + + +namespace Poco { +namespace Net { + + +TCPServerParams::TCPServerParams(): + _threadIdleTime(10000000), + _maxThreads(0), + _maxQueued(64), + _threadPriority(Poco::Thread::PRIO_NORMAL) +{ +} + + +TCPServerParams::~TCPServerParams() +{ +} + + +void TCPServerParams::setThreadIdleTime(const Poco::Timespan& milliseconds) +{ + _threadIdleTime = milliseconds; +} + + +void TCPServerParams::setMaxThreads(int count) +{ + poco_assert (count > 0); + + _maxThreads = count; +} + + +void TCPServerParams::setMaxQueued(int count) +{ + poco_assert (count >= 0); + + _maxQueued = count; +} + + +void TCPServerParams::setThreadPriority(Poco::Thread::Priority prio) +{ + _threadPriority = prio; +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/WebSocket.cpp b/contrib/libs/poco/Net/src/WebSocket.cpp index 17816ad00a..51a63adc48 100644 --- a/contrib/libs/poco/Net/src/WebSocket.cpp +++ b/contrib/libs/poco/Net/src/WebSocket.cpp @@ -1,263 +1,263 @@ -// -// WebSocket.cpp -// -// Library: Net -// Package: WebSocket -// Module: WebSocket -// -// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/Net/WebSocket.h" -#include "Poco/Net/WebSocketImpl.h" -#include "Poco/Net/HTTPServerRequestImpl.h" -#include "Poco/Net/HTTPServerResponse.h" -#include "Poco/Net/HTTPClientSession.h" -#include "Poco/Net/HTTPServerSession.h" -#include "Poco/Net/NetException.h" -#include "Poco/MemoryStream.h" -#include "Poco/NullStream.h" -#include "Poco/BinaryWriter.h" -#include "Poco/SHA1Engine.h" -#include "Poco/Base64Encoder.h" -#include "Poco/String.h" -#include "Poco/Random.h" -#include "Poco/StreamCopier.h" -#include <sstream> - - -namespace Poco { -namespace Net { - - -const std::string WebSocket::WEBSOCKET_GUID("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); -const std::string WebSocket::WEBSOCKET_VERSION("13"); -HTTPCredentials WebSocket::_defaultCreds; - - -WebSocket::WebSocket(HTTPServerRequest& request, HTTPServerResponse& response): - StreamSocket(accept(request, response)) -{ -} - - -WebSocket::WebSocket(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response): - StreamSocket(connect(cs, request, response, _defaultCreds)) -{ -} - - -WebSocket::WebSocket(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response, HTTPCredentials& credentials): - StreamSocket(connect(cs, request, response, credentials)) -{ -} - - -WebSocket::WebSocket(const Socket& socket): - StreamSocket(socket) -{ - if (!dynamic_cast<WebSocketImpl*>(impl())) - throw InvalidArgumentException("Cannot assign incompatible socket"); -} - - -WebSocket::~WebSocket() -{ -} - - -WebSocket& WebSocket::operator = (const Socket& socket) -{ - if (dynamic_cast<WebSocketImpl*>(socket.impl())) - Socket::operator = (socket); - else - throw InvalidArgumentException("Cannot assign incompatible socket"); - return *this; -} - - -void WebSocket::shutdown() -{ - shutdown(WS_NORMAL_CLOSE); -} - - -void WebSocket::shutdown(Poco::UInt16 statusCode, const std::string& statusMessage) -{ - Poco::Buffer<char> buffer(statusMessage.size() + 2); - Poco::MemoryOutputStream ostr(buffer.begin(), buffer.size()); - Poco::BinaryWriter writer(ostr, Poco::BinaryWriter::NETWORK_BYTE_ORDER); - writer << statusCode; - writer.writeRaw(statusMessage); - sendFrame(buffer.begin(), static_cast<int>(ostr.charsWritten()), FRAME_FLAG_FIN | FRAME_OP_CLOSE); -} - - -int WebSocket::sendFrame(const void* buffer, int length, int flags) -{ - flags |= FRAME_OP_SETRAW; - return static_cast<WebSocketImpl*>(impl())->sendBytes(buffer, length, flags); -} - - -int WebSocket::receiveFrame(void* buffer, int length, int& flags) -{ - int n = static_cast<WebSocketImpl*>(impl())->receiveBytes(buffer, length, 0); - flags = static_cast<WebSocketImpl*>(impl())->frameFlags(); - return n; -} - - -int WebSocket::receiveFrame(Poco::Buffer<char>& buffer, int& flags) -{ - int n = static_cast<WebSocketImpl*>(impl())->receiveBytes(buffer, 0); - flags = static_cast<WebSocketImpl*>(impl())->frameFlags(); - return n; -} - - -WebSocket::Mode WebSocket::mode() const -{ - return static_cast<WebSocketImpl*>(impl())->mustMaskPayload() ? WS_CLIENT : WS_SERVER; -} - - -void WebSocket::setMaxPayloadSize(int maxPayloadSize) -{ - static_cast<WebSocketImpl*>(impl())->setMaxPayloadSize(maxPayloadSize); -} - - -int WebSocket::getMaxPayloadSize() const -{ - return static_cast<WebSocketImpl*>(impl())->getMaxPayloadSize(); -} - - -WebSocketImpl* WebSocket::accept(HTTPServerRequest& request, HTTPServerResponse& response) -{ - if (request.hasToken("Connection", "upgrade") && icompare(request.get("Upgrade", ""), "websocket") == 0) - { - std::string version = request.get("Sec-WebSocket-Version", ""); - if (version.empty()) throw WebSocketException("Missing Sec-WebSocket-Version in handshake request", WS_ERR_HANDSHAKE_NO_VERSION); - if (version != WEBSOCKET_VERSION) throw WebSocketException("Unsupported WebSocket version requested", version, WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION); - std::string key = request.get("Sec-WebSocket-Key", ""); - Poco::trimInPlace(key); - if (key.empty()) throw WebSocketException("Missing Sec-WebSocket-Key in handshake request", WS_ERR_HANDSHAKE_NO_KEY); - - response.setStatusAndReason(HTTPResponse::HTTP_SWITCHING_PROTOCOLS); - response.set("Upgrade", "websocket"); - response.set("Connection", "Upgrade"); - response.set("Sec-WebSocket-Accept", computeAccept(key)); - response.setContentLength(HTTPResponse::UNKNOWN_CONTENT_LENGTH); - response.send().flush(); - - HTTPServerRequestImpl& requestImpl = static_cast<HTTPServerRequestImpl&>(request); - return new WebSocketImpl(static_cast<StreamSocketImpl*>(requestImpl.detachSocket().impl()), requestImpl.session(), false); - } - else throw WebSocketException("No WebSocket handshake", WS_ERR_NO_HANDSHAKE); -} - - -WebSocketImpl* WebSocket::connect(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response, HTTPCredentials& credentials) -{ - if (!cs.getProxyHost().empty() && !cs.secure()) - { - cs.proxyTunnel(); - } - std::string key = createKey(); - request.set("Connection", "Upgrade"); - request.set("Upgrade", "websocket"); - request.set("Sec-WebSocket-Version", WEBSOCKET_VERSION); - request.set("Sec-WebSocket-Key", key); - request.setChunkedTransferEncoding(false); - cs.setKeepAlive(true); - cs.sendRequest(request); - std::istream& istr = cs.receiveResponse(response); - if (response.getStatus() == HTTPResponse::HTTP_SWITCHING_PROTOCOLS) - { - return completeHandshake(cs, response, key); - } - else if (response.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED) - { - if (!credentials.empty()) - { - Poco::NullOutputStream null; - Poco::StreamCopier::copyStream(istr, null); - credentials.authenticate(request, response); - if (!cs.getProxyHost().empty() && !cs.secure()) - { - cs.reset(); - cs.proxyTunnel(); - } - cs.sendRequest(request); - cs.receiveResponse(response); - if (response.getStatus() == HTTPResponse::HTTP_SWITCHING_PROTOCOLS) - { - return completeHandshake(cs, response, key); - } - else if (response.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED) - { - throw WebSocketException("Not authorized", WS_ERR_UNAUTHORIZED); - } - } - else throw WebSocketException("Not authorized", WS_ERR_UNAUTHORIZED); - } - if (response.getStatus() == HTTPResponse::HTTP_OK) - { - throw WebSocketException("The server does not understand the WebSocket protocol", WS_ERR_NO_HANDSHAKE); - } - else - { - throw WebSocketException("Cannot upgrade to WebSocket connection", response.getReason(), WS_ERR_NO_HANDSHAKE); - } -} - - -WebSocketImpl* WebSocket::completeHandshake(HTTPClientSession& cs, HTTPResponse& response, const std::string& key) -{ - std::string connection = response.get("Connection", ""); - if (Poco::icompare(connection, "Upgrade") != 0) - throw WebSocketException("No Connection: Upgrade header in handshake response", WS_ERR_NO_HANDSHAKE); - std::string upgrade = response.get("Upgrade", ""); - if (Poco::icompare(upgrade, "websocket") != 0) - throw WebSocketException("No Upgrade: websocket header in handshake response", WS_ERR_NO_HANDSHAKE); - std::string accept = response.get("Sec-WebSocket-Accept", ""); - if (accept != computeAccept(key)) - throw WebSocketException("Invalid or missing Sec-WebSocket-Accept header in handshake response", WS_ERR_HANDSHAKE_ACCEPT); - return new WebSocketImpl(static_cast<StreamSocketImpl*>(cs.detachSocket().impl()), cs, true); -} - - -std::string WebSocket::createKey() -{ - Poco::Random rnd; - std::ostringstream ostr; - Poco::Base64Encoder base64(ostr); - Poco::BinaryWriter writer(base64); - writer << rnd.next() << rnd.next() << rnd.next() << rnd.next(); - base64.close(); - return ostr.str(); -} - - -std::string WebSocket::computeAccept(const std::string& key) -{ - std::string accept(key); - accept += WEBSOCKET_GUID; - Poco::SHA1Engine sha1; - sha1.update(accept); - Poco::DigestEngine::Digest d = sha1.digest(); - std::ostringstream ostr; - Poco::Base64Encoder base64(ostr); - base64.write(reinterpret_cast<const char*>(&d[0]), d.size()); - base64.close(); - return ostr.str(); -} - - -} } // namespace Poco::Net +// +// WebSocket.cpp +// +// Library: Net +// Package: WebSocket +// Module: WebSocket +// +// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/WebSocket.h" +#include "Poco/Net/WebSocketImpl.h" +#include "Poco/Net/HTTPServerRequestImpl.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/HTTPClientSession.h" +#include "Poco/Net/HTTPServerSession.h" +#include "Poco/Net/NetException.h" +#include "Poco/MemoryStream.h" +#include "Poco/NullStream.h" +#include "Poco/BinaryWriter.h" +#include "Poco/SHA1Engine.h" +#include "Poco/Base64Encoder.h" +#include "Poco/String.h" +#include "Poco/Random.h" +#include "Poco/StreamCopier.h" +#include <sstream> + + +namespace Poco { +namespace Net { + + +const std::string WebSocket::WEBSOCKET_GUID("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); +const std::string WebSocket::WEBSOCKET_VERSION("13"); +HTTPCredentials WebSocket::_defaultCreds; + + +WebSocket::WebSocket(HTTPServerRequest& request, HTTPServerResponse& response): + StreamSocket(accept(request, response)) +{ +} + + +WebSocket::WebSocket(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response): + StreamSocket(connect(cs, request, response, _defaultCreds)) +{ +} + + +WebSocket::WebSocket(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response, HTTPCredentials& credentials): + StreamSocket(connect(cs, request, response, credentials)) +{ +} + + +WebSocket::WebSocket(const Socket& socket): + StreamSocket(socket) +{ + if (!dynamic_cast<WebSocketImpl*>(impl())) + throw InvalidArgumentException("Cannot assign incompatible socket"); +} + + +WebSocket::~WebSocket() +{ +} + + +WebSocket& WebSocket::operator = (const Socket& socket) +{ + if (dynamic_cast<WebSocketImpl*>(socket.impl())) + Socket::operator = (socket); + else + throw InvalidArgumentException("Cannot assign incompatible socket"); + return *this; +} + + +void WebSocket::shutdown() +{ + shutdown(WS_NORMAL_CLOSE); +} + + +void WebSocket::shutdown(Poco::UInt16 statusCode, const std::string& statusMessage) +{ + Poco::Buffer<char> buffer(statusMessage.size() + 2); + Poco::MemoryOutputStream ostr(buffer.begin(), buffer.size()); + Poco::BinaryWriter writer(ostr, Poco::BinaryWriter::NETWORK_BYTE_ORDER); + writer << statusCode; + writer.writeRaw(statusMessage); + sendFrame(buffer.begin(), static_cast<int>(ostr.charsWritten()), FRAME_FLAG_FIN | FRAME_OP_CLOSE); +} + + +int WebSocket::sendFrame(const void* buffer, int length, int flags) +{ + flags |= FRAME_OP_SETRAW; + return static_cast<WebSocketImpl*>(impl())->sendBytes(buffer, length, flags); +} + + +int WebSocket::receiveFrame(void* buffer, int length, int& flags) +{ + int n = static_cast<WebSocketImpl*>(impl())->receiveBytes(buffer, length, 0); + flags = static_cast<WebSocketImpl*>(impl())->frameFlags(); + return n; +} + + +int WebSocket::receiveFrame(Poco::Buffer<char>& buffer, int& flags) +{ + int n = static_cast<WebSocketImpl*>(impl())->receiveBytes(buffer, 0); + flags = static_cast<WebSocketImpl*>(impl())->frameFlags(); + return n; +} + + +WebSocket::Mode WebSocket::mode() const +{ + return static_cast<WebSocketImpl*>(impl())->mustMaskPayload() ? WS_CLIENT : WS_SERVER; +} + + +void WebSocket::setMaxPayloadSize(int maxPayloadSize) +{ + static_cast<WebSocketImpl*>(impl())->setMaxPayloadSize(maxPayloadSize); +} + + +int WebSocket::getMaxPayloadSize() const +{ + return static_cast<WebSocketImpl*>(impl())->getMaxPayloadSize(); +} + + +WebSocketImpl* WebSocket::accept(HTTPServerRequest& request, HTTPServerResponse& response) +{ + if (request.hasToken("Connection", "upgrade") && icompare(request.get("Upgrade", ""), "websocket") == 0) + { + std::string version = request.get("Sec-WebSocket-Version", ""); + if (version.empty()) throw WebSocketException("Missing Sec-WebSocket-Version in handshake request", WS_ERR_HANDSHAKE_NO_VERSION); + if (version != WEBSOCKET_VERSION) throw WebSocketException("Unsupported WebSocket version requested", version, WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION); + std::string key = request.get("Sec-WebSocket-Key", ""); + Poco::trimInPlace(key); + if (key.empty()) throw WebSocketException("Missing Sec-WebSocket-Key in handshake request", WS_ERR_HANDSHAKE_NO_KEY); + + response.setStatusAndReason(HTTPResponse::HTTP_SWITCHING_PROTOCOLS); + response.set("Upgrade", "websocket"); + response.set("Connection", "Upgrade"); + response.set("Sec-WebSocket-Accept", computeAccept(key)); + response.setContentLength(HTTPResponse::UNKNOWN_CONTENT_LENGTH); + response.send().flush(); + + HTTPServerRequestImpl& requestImpl = static_cast<HTTPServerRequestImpl&>(request); + return new WebSocketImpl(static_cast<StreamSocketImpl*>(requestImpl.detachSocket().impl()), requestImpl.session(), false); + } + else throw WebSocketException("No WebSocket handshake", WS_ERR_NO_HANDSHAKE); +} + + +WebSocketImpl* WebSocket::connect(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response, HTTPCredentials& credentials) +{ + if (!cs.getProxyHost().empty() && !cs.secure()) + { + cs.proxyTunnel(); + } + std::string key = createKey(); + request.set("Connection", "Upgrade"); + request.set("Upgrade", "websocket"); + request.set("Sec-WebSocket-Version", WEBSOCKET_VERSION); + request.set("Sec-WebSocket-Key", key); + request.setChunkedTransferEncoding(false); + cs.setKeepAlive(true); + cs.sendRequest(request); + std::istream& istr = cs.receiveResponse(response); + if (response.getStatus() == HTTPResponse::HTTP_SWITCHING_PROTOCOLS) + { + return completeHandshake(cs, response, key); + } + else if (response.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED) + { + if (!credentials.empty()) + { + Poco::NullOutputStream null; + Poco::StreamCopier::copyStream(istr, null); + credentials.authenticate(request, response); + if (!cs.getProxyHost().empty() && !cs.secure()) + { + cs.reset(); + cs.proxyTunnel(); + } + cs.sendRequest(request); + cs.receiveResponse(response); + if (response.getStatus() == HTTPResponse::HTTP_SWITCHING_PROTOCOLS) + { + return completeHandshake(cs, response, key); + } + else if (response.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED) + { + throw WebSocketException("Not authorized", WS_ERR_UNAUTHORIZED); + } + } + else throw WebSocketException("Not authorized", WS_ERR_UNAUTHORIZED); + } + if (response.getStatus() == HTTPResponse::HTTP_OK) + { + throw WebSocketException("The server does not understand the WebSocket protocol", WS_ERR_NO_HANDSHAKE); + } + else + { + throw WebSocketException("Cannot upgrade to WebSocket connection", response.getReason(), WS_ERR_NO_HANDSHAKE); + } +} + + +WebSocketImpl* WebSocket::completeHandshake(HTTPClientSession& cs, HTTPResponse& response, const std::string& key) +{ + std::string connection = response.get("Connection", ""); + if (Poco::icompare(connection, "Upgrade") != 0) + throw WebSocketException("No Connection: Upgrade header in handshake response", WS_ERR_NO_HANDSHAKE); + std::string upgrade = response.get("Upgrade", ""); + if (Poco::icompare(upgrade, "websocket") != 0) + throw WebSocketException("No Upgrade: websocket header in handshake response", WS_ERR_NO_HANDSHAKE); + std::string accept = response.get("Sec-WebSocket-Accept", ""); + if (accept != computeAccept(key)) + throw WebSocketException("Invalid or missing Sec-WebSocket-Accept header in handshake response", WS_ERR_HANDSHAKE_ACCEPT); + return new WebSocketImpl(static_cast<StreamSocketImpl*>(cs.detachSocket().impl()), cs, true); +} + + +std::string WebSocket::createKey() +{ + Poco::Random rnd; + std::ostringstream ostr; + Poco::Base64Encoder base64(ostr); + Poco::BinaryWriter writer(base64); + writer << rnd.next() << rnd.next() << rnd.next() << rnd.next(); + base64.close(); + return ostr.str(); +} + + +std::string WebSocket::computeAccept(const std::string& key) +{ + std::string accept(key); + accept += WEBSOCKET_GUID; + Poco::SHA1Engine sha1; + sha1.update(accept); + Poco::DigestEngine::Digest d = sha1.digest(); + std::ostringstream ostr; + Poco::Base64Encoder base64(ostr); + base64.write(reinterpret_cast<const char*>(&d[0]), d.size()); + base64.close(); + return ostr.str(); +} + + +} } // namespace Poco::Net diff --git a/contrib/libs/poco/Net/src/WebSocketImpl.cpp b/contrib/libs/poco/Net/src/WebSocketImpl.cpp index 49fcad63c2..46a0a13e6d 100644 --- a/contrib/libs/poco/Net/src/WebSocketImpl.cpp +++ b/contrib/libs/poco/Net/src/WebSocketImpl.cpp @@ -1,400 +1,400 @@ -// -// WebSocketImpl.cpp -// -// Library: Net -// Package: WebSocket -// Module: WebSocketImpl -// -// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#define NOMINMAX -#include "Poco/Net/WebSocketImpl.h" -#include "Poco/Net/NetException.h" -#include "Poco/Net/WebSocket.h" -#include "Poco/Net/HTTPSession.h" -#include "Poco/Buffer.h" -#include "Poco/BinaryWriter.h" -#include "Poco/BinaryReader.h" -#include "Poco/MemoryStream.h" -#include "Poco/Format.h" -#include <limits> -#include <cstring> - - -namespace Poco { -namespace Net { - - -WebSocketImpl::WebSocketImpl(StreamSocketImpl* pStreamSocketImpl, HTTPSession& session, bool mustMaskPayload): - StreamSocketImpl(pStreamSocketImpl->sockfd()), - _pStreamSocketImpl(pStreamSocketImpl), - _maxPayloadSize(std::numeric_limits<int>::max()), - _buffer(0), - _bufferOffset(0), - _frameFlags(0), - _mustMaskPayload(mustMaskPayload) -{ - poco_check_ptr(pStreamSocketImpl); - _pStreamSocketImpl->duplicate(); - session.drainBuffer(_buffer); -} - - -WebSocketImpl::~WebSocketImpl() -{ - try - { - _pStreamSocketImpl->release(); - reset(); - } - catch (...) - { - poco_unexpected(); - } -} - - -int WebSocketImpl::sendBytes(const void* buffer, int length, int flags) -{ - Poco::Buffer<char> frame(length + MAX_HEADER_LENGTH); - Poco::MemoryOutputStream ostr(frame.begin(), frame.size()); - Poco::BinaryWriter writer(ostr, Poco::BinaryWriter::NETWORK_BYTE_ORDER); - - if (flags == 0) flags = WebSocket::FRAME_BINARY; - flags &= 0xff; - writer << static_cast<Poco::UInt8>(flags); - Poco::UInt8 lengthByte(0); - if (_mustMaskPayload) - { - lengthByte |= FRAME_FLAG_MASK; - } - if (length < 126) - { - lengthByte |= static_cast<Poco::UInt8>(length); - writer << lengthByte; - } - else if (length < 65536) - { - lengthByte |= 126; - writer << lengthByte << static_cast<Poco::UInt16>(length); - } - else - { - lengthByte |= 127; - writer << lengthByte << static_cast<Poco::UInt64>(length); - } - if (_mustMaskPayload) - { - const Poco::UInt32 mask = _rnd.next(); - const char* m = reinterpret_cast<const char*>(&mask); - const char* b = reinterpret_cast<const char*>(buffer); - writer.writeRaw(m, 4); - char* p = frame.begin() + ostr.charsWritten(); - for (int i = 0; i < length; i++) - { - p[i] = b[i] ^ m[i % 4]; - } - } - else - { - std::memcpy(frame.begin() + ostr.charsWritten(), buffer, length); - } - _pStreamSocketImpl->sendBytes(frame.begin(), length + static_cast<int>(ostr.charsWritten())); - return length; -} - - -int WebSocketImpl::receiveHeader(char mask[4], bool& useMask) -{ - char header[MAX_HEADER_LENGTH]; - int n = receiveNBytes(header, 2); - if (n <= 0) - { - _frameFlags = 0; - return n; - } - poco_assert (n == 2); - Poco::UInt8 flags = static_cast<Poco::UInt8>(header[0]); - _frameFlags = flags; - Poco::UInt8 lengthByte = static_cast<Poco::UInt8>(header[1]); - useMask = ((lengthByte & FRAME_FLAG_MASK) != 0); - int payloadLength; - lengthByte &= 0x7f; - if (lengthByte == 127) - { - n = receiveNBytes(header + 2, 8); - if (n <= 0) - { - _frameFlags = 0; - return n; - } - Poco::MemoryInputStream istr(header + 2, 8); - Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER); - Poco::UInt64 l; - reader >> l; - if (l > _maxPayloadSize) throw WebSocketException("Payload too big", WebSocket::WS_ERR_PAYLOAD_TOO_BIG); - payloadLength = static_cast<int>(l); - } - else if (lengthByte == 126) - { - n = receiveNBytes(header + 2, 2); - if (n <= 0) - { - _frameFlags = 0; - return n; - } - Poco::MemoryInputStream istr(header + 2, 2); - Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER); - Poco::UInt16 l; - reader >> l; - if (l > _maxPayloadSize) throw WebSocketException("Payload too big", WebSocket::WS_ERR_PAYLOAD_TOO_BIG); - payloadLength = static_cast<int>(l); - } - else - { - if (lengthByte > _maxPayloadSize) throw WebSocketException("Payload too big", WebSocket::WS_ERR_PAYLOAD_TOO_BIG); - payloadLength = lengthByte; - } - - if (useMask) - { - n = receiveNBytes(mask, 4); - if (n <= 0) - { - _frameFlags = 0; - return n; - } - } - - return payloadLength; -} - - -void WebSocketImpl::setMaxPayloadSize(int maxPayloadSize) -{ - poco_assert (maxPayloadSize > 0); - - _maxPayloadSize = maxPayloadSize; -} - - -int WebSocketImpl::receivePayload(char *buffer, int payloadLength, char mask[4], bool useMask) -{ - int received = receiveNBytes(reinterpret_cast<char*>(buffer), payloadLength); - if (received <= 0) throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME); - - if (useMask) - { - for (int i = 0; i < received; i++) - { - buffer[i] ^= mask[i % 4]; - } - } - return received; -} - - -int WebSocketImpl::receiveBytes(void* buffer, int length, int) -{ - char mask[4]; - bool useMask; - int payloadLength = receiveHeader(mask, useMask); - if (payloadLength <= 0) - return payloadLength; - if (payloadLength > length) - throw WebSocketException(Poco::format("Insufficient buffer for payload size %d", payloadLength), WebSocket::WS_ERR_PAYLOAD_TOO_BIG); - return receivePayload(reinterpret_cast<char*>(buffer), payloadLength, mask, useMask); -} - - -int WebSocketImpl::receiveBytes(Poco::Buffer<char>& buffer, int) -{ - char mask[4]; - bool useMask; - int payloadLength = receiveHeader(mask, useMask); - if (payloadLength <= 0) - return payloadLength; - std::size_t oldSize = buffer.size(); - buffer.resize(oldSize + payloadLength); - return receivePayload(buffer.begin() + oldSize, payloadLength, mask, useMask); -} - - -int WebSocketImpl::receiveNBytes(void* buffer, int bytes) -{ - int received = receiveSomeBytes(reinterpret_cast<char*>(buffer), bytes); - if (received > 0) - { - while (received < bytes) - { - int n = receiveSomeBytes(reinterpret_cast<char*>(buffer) + received, bytes - received); - if (n > 0) - received += n; - else - throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME); - } - } - return received; -} - - -int WebSocketImpl::receiveSomeBytes(char* buffer, int bytes) -{ - int n = static_cast<int>(_buffer.size()) - _bufferOffset; - if (n > 0) - { - if (bytes < n) n = bytes; - std::memcpy(buffer, _buffer.begin() + _bufferOffset, n); - _bufferOffset += n; - return n; - } - else - { - return _pStreamSocketImpl->receiveBytes(buffer, bytes); - } -} - - -SocketImpl* WebSocketImpl::acceptConnection(SocketAddress& /*clientAddr*/) -{ - throw Poco::InvalidAccessException("Cannot acceptConnection() on a WebSocketImpl"); -} - - -void WebSocketImpl::connect(const SocketAddress& /*address*/) -{ - throw Poco::InvalidAccessException("Cannot connect() a WebSocketImpl"); -} - - -void WebSocketImpl::connect(const SocketAddress& /*address*/, const Poco::Timespan& /*timeout*/) -{ - throw Poco::InvalidAccessException("Cannot connect() a WebSocketImpl"); -} - - -void WebSocketImpl::connectNB(const SocketAddress& /*address*/) -{ - throw Poco::InvalidAccessException("Cannot connectNB() a WebSocketImpl"); -} - - -void WebSocketImpl::bind(const SocketAddress& /*address*/, bool /*reuseAddress*/) -{ - throw Poco::InvalidAccessException("Cannot bind() a WebSocketImpl"); -} - - -void WebSocketImpl::bind(const SocketAddress& /*address*/, bool /*reuseAddress*/, bool /*reusePort*/) -{ - throw Poco::InvalidAccessException("Cannot bind() a WebSocketImpl"); -} - - -void WebSocketImpl::bind6(const SocketAddress& /*address*/, bool /*reuseAddress*/, bool /*ipV6Only*/) -{ - throw Poco::InvalidAccessException("Cannot bind6() a WebSocketImpl"); -} - - -void WebSocketImpl::bind6(const SocketAddress& /*address*/, bool /*reuseAddress*/, bool /*reusePort*/, bool /*ipV6Only*/) -{ - throw Poco::InvalidAccessException("Cannot bind6() a WebSocketImpl"); -} - - -void WebSocketImpl::listen(int /*backlog*/) -{ - throw Poco::InvalidAccessException("Cannot listen() on a WebSocketImpl"); -} - - -void WebSocketImpl::close() -{ - _pStreamSocketImpl->close(); - reset(); -} - - -void WebSocketImpl::shutdownReceive() -{ - _pStreamSocketImpl->shutdownReceive(); -} - - -void WebSocketImpl::shutdownSend() -{ - _pStreamSocketImpl->shutdownSend(); -} - - -void WebSocketImpl::shutdown() -{ - _pStreamSocketImpl->shutdown(); -} - - -int WebSocketImpl::sendTo(const void* /*buffer*/, int /*length*/, const SocketAddress& /*address*/, int /*flags*/) -{ - throw Poco::InvalidAccessException("Cannot sendTo() on a WebSocketImpl"); -} - - -int WebSocketImpl::receiveFrom(void* /*buffer*/, int /*length*/, SocketAddress& /*address*/, int /*flags*/) -{ - throw Poco::InvalidAccessException("Cannot receiveFrom() on a WebSocketImpl"); -} - - -void WebSocketImpl::sendUrgent(unsigned char /*data*/) -{ - throw Poco::InvalidAccessException("Cannot sendUrgent() on a WebSocketImpl"); -} - - -bool WebSocketImpl::secure() const -{ - return _pStreamSocketImpl->secure(); -} - - -void WebSocketImpl::setSendTimeout(const Poco::Timespan& timeout) -{ - _pStreamSocketImpl->setSendTimeout(timeout); -} - - -Poco::Timespan WebSocketImpl::getSendTimeout() -{ - return _pStreamSocketImpl->getSendTimeout(); -} - - -void WebSocketImpl::setReceiveTimeout(const Poco::Timespan& timeout) -{ - _pStreamSocketImpl->setReceiveTimeout(timeout); -} - - -Poco::Timespan WebSocketImpl::getReceiveTimeout() -{ - return _pStreamSocketImpl->getReceiveTimeout(); -} - - -int WebSocketImpl::available() -{ - int n = static_cast<int>(_buffer.size()) - _bufferOffset; - if (n > 0) - return n + _pStreamSocketImpl->available(); - else - return _pStreamSocketImpl->available(); -} - - -} } // namespace Poco::Net +// +// WebSocketImpl.cpp +// +// Library: Net +// Package: WebSocket +// Module: WebSocketImpl +// +// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#define NOMINMAX +#include "Poco/Net/WebSocketImpl.h" +#include "Poco/Net/NetException.h" +#include "Poco/Net/WebSocket.h" +#include "Poco/Net/HTTPSession.h" +#include "Poco/Buffer.h" +#include "Poco/BinaryWriter.h" +#include "Poco/BinaryReader.h" +#include "Poco/MemoryStream.h" +#include "Poco/Format.h" +#include <limits> +#include <cstring> + + +namespace Poco { +namespace Net { + + +WebSocketImpl::WebSocketImpl(StreamSocketImpl* pStreamSocketImpl, HTTPSession& session, bool mustMaskPayload): + StreamSocketImpl(pStreamSocketImpl->sockfd()), + _pStreamSocketImpl(pStreamSocketImpl), + _maxPayloadSize(std::numeric_limits<int>::max()), + _buffer(0), + _bufferOffset(0), + _frameFlags(0), + _mustMaskPayload(mustMaskPayload) +{ + poco_check_ptr(pStreamSocketImpl); + _pStreamSocketImpl->duplicate(); + session.drainBuffer(_buffer); +} + + +WebSocketImpl::~WebSocketImpl() +{ + try + { + _pStreamSocketImpl->release(); + reset(); + } + catch (...) + { + poco_unexpected(); + } +} + + +int WebSocketImpl::sendBytes(const void* buffer, int length, int flags) +{ + Poco::Buffer<char> frame(length + MAX_HEADER_LENGTH); + Poco::MemoryOutputStream ostr(frame.begin(), frame.size()); + Poco::BinaryWriter writer(ostr, Poco::BinaryWriter::NETWORK_BYTE_ORDER); + + if (flags == 0) flags = WebSocket::FRAME_BINARY; + flags &= 0xff; + writer << static_cast<Poco::UInt8>(flags); + Poco::UInt8 lengthByte(0); + if (_mustMaskPayload) + { + lengthByte |= FRAME_FLAG_MASK; + } + if (length < 126) + { + lengthByte |= static_cast<Poco::UInt8>(length); + writer << lengthByte; + } + else if (length < 65536) + { + lengthByte |= 126; + writer << lengthByte << static_cast<Poco::UInt16>(length); + } + else + { + lengthByte |= 127; + writer << lengthByte << static_cast<Poco::UInt64>(length); + } + if (_mustMaskPayload) + { + const Poco::UInt32 mask = _rnd.next(); + const char* m = reinterpret_cast<const char*>(&mask); + const char* b = reinterpret_cast<const char*>(buffer); + writer.writeRaw(m, 4); + char* p = frame.begin() + ostr.charsWritten(); + for (int i = 0; i < length; i++) + { + p[i] = b[i] ^ m[i % 4]; + } + } + else + { + std::memcpy(frame.begin() + ostr.charsWritten(), buffer, length); + } + _pStreamSocketImpl->sendBytes(frame.begin(), length + static_cast<int>(ostr.charsWritten())); + return length; +} + + +int WebSocketImpl::receiveHeader(char mask[4], bool& useMask) +{ + char header[MAX_HEADER_LENGTH]; + int n = receiveNBytes(header, 2); + if (n <= 0) + { + _frameFlags = 0; + return n; + } + poco_assert (n == 2); + Poco::UInt8 flags = static_cast<Poco::UInt8>(header[0]); + _frameFlags = flags; + Poco::UInt8 lengthByte = static_cast<Poco::UInt8>(header[1]); + useMask = ((lengthByte & FRAME_FLAG_MASK) != 0); + int payloadLength; + lengthByte &= 0x7f; + if (lengthByte == 127) + { + n = receiveNBytes(header + 2, 8); + if (n <= 0) + { + _frameFlags = 0; + return n; + } + Poco::MemoryInputStream istr(header + 2, 8); + Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER); + Poco::UInt64 l; + reader >> l; + if (l > _maxPayloadSize) throw WebSocketException("Payload too big", WebSocket::WS_ERR_PAYLOAD_TOO_BIG); + payloadLength = static_cast<int>(l); + } + else if (lengthByte == 126) + { + n = receiveNBytes(header + 2, 2); + if (n <= 0) + { + _frameFlags = 0; + return n; + } + Poco::MemoryInputStream istr(header + 2, 2); + Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER); + Poco::UInt16 l; + reader >> l; + if (l > _maxPayloadSize) throw WebSocketException("Payload too big", WebSocket::WS_ERR_PAYLOAD_TOO_BIG); + payloadLength = static_cast<int>(l); + } + else + { + if (lengthByte > _maxPayloadSize) throw WebSocketException("Payload too big", WebSocket::WS_ERR_PAYLOAD_TOO_BIG); + payloadLength = lengthByte; + } + + if (useMask) + { + n = receiveNBytes(mask, 4); + if (n <= 0) + { + _frameFlags = 0; + return n; + } + } + + return payloadLength; +} + + +void WebSocketImpl::setMaxPayloadSize(int maxPayloadSize) +{ + poco_assert (maxPayloadSize > 0); + + _maxPayloadSize = maxPayloadSize; +} + + +int WebSocketImpl::receivePayload(char *buffer, int payloadLength, char mask[4], bool useMask) +{ + int received = receiveNBytes(reinterpret_cast<char*>(buffer), payloadLength); + if (received <= 0) throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME); + + if (useMask) + { + for (int i = 0; i < received; i++) + { + buffer[i] ^= mask[i % 4]; + } + } + return received; +} + + +int WebSocketImpl::receiveBytes(void* buffer, int length, int) +{ + char mask[4]; + bool useMask; + int payloadLength = receiveHeader(mask, useMask); + if (payloadLength <= 0) + return payloadLength; + if (payloadLength > length) + throw WebSocketException(Poco::format("Insufficient buffer for payload size %d", payloadLength), WebSocket::WS_ERR_PAYLOAD_TOO_BIG); + return receivePayload(reinterpret_cast<char*>(buffer), payloadLength, mask, useMask); +} + + +int WebSocketImpl::receiveBytes(Poco::Buffer<char>& buffer, int) +{ + char mask[4]; + bool useMask; + int payloadLength = receiveHeader(mask, useMask); + if (payloadLength <= 0) + return payloadLength; + std::size_t oldSize = buffer.size(); + buffer.resize(oldSize + payloadLength); + return receivePayload(buffer.begin() + oldSize, payloadLength, mask, useMask); +} + + +int WebSocketImpl::receiveNBytes(void* buffer, int bytes) +{ + int received = receiveSomeBytes(reinterpret_cast<char*>(buffer), bytes); + if (received > 0) + { + while (received < bytes) + { + int n = receiveSomeBytes(reinterpret_cast<char*>(buffer) + received, bytes - received); + if (n > 0) + received += n; + else + throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME); + } + } + return received; +} + + +int WebSocketImpl::receiveSomeBytes(char* buffer, int bytes) +{ + int n = static_cast<int>(_buffer.size()) - _bufferOffset; + if (n > 0) + { + if (bytes < n) n = bytes; + std::memcpy(buffer, _buffer.begin() + _bufferOffset, n); + _bufferOffset += n; + return n; + } + else + { + return _pStreamSocketImpl->receiveBytes(buffer, bytes); + } +} + + +SocketImpl* WebSocketImpl::acceptConnection(SocketAddress& /*clientAddr*/) +{ + throw Poco::InvalidAccessException("Cannot acceptConnection() on a WebSocketImpl"); +} + + +void WebSocketImpl::connect(const SocketAddress& /*address*/) +{ + throw Poco::InvalidAccessException("Cannot connect() a WebSocketImpl"); +} + + +void WebSocketImpl::connect(const SocketAddress& /*address*/, const Poco::Timespan& /*timeout*/) +{ + throw Poco::InvalidAccessException("Cannot connect() a WebSocketImpl"); +} + + +void WebSocketImpl::connectNB(const SocketAddress& /*address*/) +{ + throw Poco::InvalidAccessException("Cannot connectNB() a WebSocketImpl"); +} + + +void WebSocketImpl::bind(const SocketAddress& /*address*/, bool /*reuseAddress*/) +{ + throw Poco::InvalidAccessException("Cannot bind() a WebSocketImpl"); +} + + +void WebSocketImpl::bind(const SocketAddress& /*address*/, bool /*reuseAddress*/, bool /*reusePort*/) +{ + throw Poco::InvalidAccessException("Cannot bind() a WebSocketImpl"); +} + + +void WebSocketImpl::bind6(const SocketAddress& /*address*/, bool /*reuseAddress*/, bool /*ipV6Only*/) +{ + throw Poco::InvalidAccessException("Cannot bind6() a WebSocketImpl"); +} + + +void WebSocketImpl::bind6(const SocketAddress& /*address*/, bool /*reuseAddress*/, bool /*reusePort*/, bool /*ipV6Only*/) +{ + throw Poco::InvalidAccessException("Cannot bind6() a WebSocketImpl"); +} + + +void WebSocketImpl::listen(int /*backlog*/) +{ + throw Poco::InvalidAccessException("Cannot listen() on a WebSocketImpl"); +} + + +void WebSocketImpl::close() +{ + _pStreamSocketImpl->close(); + reset(); +} + + +void WebSocketImpl::shutdownReceive() +{ + _pStreamSocketImpl->shutdownReceive(); +} + + +void WebSocketImpl::shutdownSend() +{ + _pStreamSocketImpl->shutdownSend(); +} + + +void WebSocketImpl::shutdown() +{ + _pStreamSocketImpl->shutdown(); +} + + +int WebSocketImpl::sendTo(const void* /*buffer*/, int /*length*/, const SocketAddress& /*address*/, int /*flags*/) +{ + throw Poco::InvalidAccessException("Cannot sendTo() on a WebSocketImpl"); +} + + +int WebSocketImpl::receiveFrom(void* /*buffer*/, int /*length*/, SocketAddress& /*address*/, int /*flags*/) +{ + throw Poco::InvalidAccessException("Cannot receiveFrom() on a WebSocketImpl"); +} + + +void WebSocketImpl::sendUrgent(unsigned char /*data*/) +{ + throw Poco::InvalidAccessException("Cannot sendUrgent() on a WebSocketImpl"); +} + + +bool WebSocketImpl::secure() const +{ + return _pStreamSocketImpl->secure(); +} + + +void WebSocketImpl::setSendTimeout(const Poco::Timespan& timeout) +{ + _pStreamSocketImpl->setSendTimeout(timeout); +} + + +Poco::Timespan WebSocketImpl::getSendTimeout() +{ + return _pStreamSocketImpl->getSendTimeout(); +} + + +void WebSocketImpl::setReceiveTimeout(const Poco::Timespan& timeout) +{ + _pStreamSocketImpl->setReceiveTimeout(timeout); +} + + +Poco::Timespan WebSocketImpl::getReceiveTimeout() +{ + return _pStreamSocketImpl->getReceiveTimeout(); +} + + +int WebSocketImpl::available() +{ + int n = static_cast<int>(_buffer.size()) - _bufferOffset; + if (n > 0) + return n + _pStreamSocketImpl->available(); + else + return _pStreamSocketImpl->available(); +} + + +} } // namespace Poco::Net |