diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/poco/Net | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/poco/Net')
208 files changed, 40650 insertions, 0 deletions
diff --git a/contrib/libs/poco/Net/.yandex_meta/licenses.list.txt b/contrib/libs/poco/Net/.yandex_meta/licenses.list.txt new file mode 100644 index 0000000000..047c8d81c6 --- /dev/null +++ b/contrib/libs/poco/Net/.yandex_meta/licenses.list.txt @@ -0,0 +1,126 @@ +====================BSD-3-Clause==================== + remove advertising from BSD licensed parts + + +====================BSL-1.0==================== +- Changed license to Boost license + + +====================BSL-1.0==================== +// SPDX-License-Identifier: BSL-1.0 + + +====================BSL-1.0==================== +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +--------------------------------------------------------------------------- +Note: +Individual files contain the following tag instead of the full license text. + + SPDX-License-Identifier: BSL-1.0 + +This enables machine processing of license information based on the SPDX +License Identifiers that are here available: http://spdx.org/licenses/ + +====================COPYRIGHT==================== +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2005-2008, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2005-2012, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2007-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru). +// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2014, Applied Informatics Software Engineering GmbH. +// and Contributors. + + +====================COPYRIGHT==================== +// Copyright (c) 2016, Applied Informatics Software Engineering GmbH. +// All rights reserved. + + +====================Custom-Punycode==================== + 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. diff --git a/contrib/libs/poco/Net/include/Poco/Net/AbstractHTTPRequestHandler.h b/contrib/libs/poco/Net/include/Poco/Net/AbstractHTTPRequestHandler.h new file mode 100644 index 0000000000..7bbc174c81 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/AbstractHTTPRequestHandler.h @@ -0,0 +1,136 @@ +// +// AbstractHTTPRequestHandler.h +// +// Library: Net +// Package: HTTPServer +// Module: AbstractHTTPRequestHandler +// +// Definition of the AbstractHTTPRequestHandler class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_AbstractHTTPRequestHandler_INCLUDED +#define Net_AbstractHTTPRequestHandler_INCLUDED + + +#include "Poco/Net/HTTPRequestHandler.h" +#include "Poco/Net/HTTPResponse.h" + + +namespace Poco { +namespace Net { + + +class HTMLForm; + + +class Net_API AbstractHTTPRequestHandler: public HTTPRequestHandler + /// The abstract base class for AbstractHTTPRequestHandlers + /// created by HTTPServer. + /// + /// Derived classes must override the run() method. + + /// Contrary to a HTTPRequestHandler, an AbstractHTTPRequestHandler + /// stores request and response as member variables to avoid having + /// to pass them around as method parameters. Additionally, a + /// HTMLForm object is created for use by subclasses. + /// + /// The run() method must perform the complete handling + /// of the HTTP request connection. As soon as the run() + /// method returns, the request handler object is destroyed. + /// + /// A new AbstractHTTPRequestHandler object will be created for + /// each new HTTP request that is received by the HTTPServer. +{ +public: + AbstractHTTPRequestHandler(); + /// Creates the AbstractHTTPRequestHandler. + + virtual ~AbstractHTTPRequestHandler(); + /// Destroys the AbstractHTTPRequestHandler. + + void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response); + /// This class implements some common behavior, + /// before calling run() to actually handle the request: + /// - save request and response objects; + /// - call authorize(); + /// - if authorize() returns true call run(), + /// else send 401 (Unauthorized) response. + /// + /// If run() throws an exception and the response has not been + /// sent yet, sends a 500 (Internal Server Error) response with + /// the exception's display text. + + HTTPServerRequest& request(); + /// Returns the request. + + HTTPServerResponse& response(); + /// Returns the response. + + HTMLForm& form(); + /// Returns a HTMLForm for the given request. + /// The HTMLForm object is created when this + /// member function is executed the first time. + + void sendErrorResponse(HTTPResponse::HTTPStatus status, const std::string& message); + /// Sends a HTML error page for the given status code. + /// The given message is added to the page: + /// <HTML> + /// <HEAD> + /// <TITLE>status - reason</TITLE> + /// </HEAD> + /// <BODY> + /// <H1>status - reason</H1> + /// <P>message</P> + /// </BODY> + /// </HTML> + +protected: + virtual void run() = 0; + /// Must be overridden by subclasses. + /// + /// Handles the given request. + + virtual bool authenticate(); + /// Check authentication; returns true if okay, false if failed to authenticate. + /// The default implementation always returns true. + /// + /// Subclasses can override this member function to perform + /// some form of client or request authentication before + /// the request is actually handled. + +private: + HTTPServerRequest* _pRequest; + HTTPServerResponse* _pResponse; + HTMLForm* _pForm; +}; + + +// +// inlines +// +inline HTTPServerRequest& AbstractHTTPRequestHandler::request() +{ + poco_check_ptr (_pRequest); + + return *_pRequest; +} + + +inline HTTPServerResponse& AbstractHTTPRequestHandler::response() +{ + poco_check_ptr (_pResponse); + + return *_pResponse; +} + + +} } // namespace Poco::Net + + +#endif // Net_AbstractHTTPRequestHandler_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/DNS.h b/contrib/libs/poco/Net/include/Poco/Net/DNS.h new file mode 100644 index 0000000000..f896862d9f --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/DNS.h @@ -0,0 +1,203 @@ +// +// DNS.h +// +// Library: Net +// Package: NetCore +// Module: DNS +// +// Definition of the DNS class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_DNS_INCLUDED +#define Net_DNS_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketDefs.h" +#include "Poco/Net/IPAddress.h" +#include "Poco/Net/HostEntry.h" + +#include "Poco/Timespan.h" + + +namespace Poco { +namespace Net { + + +class Net_API DNS + /// This class provides an interface to the + /// domain name service. + /// + /// Starting with POCO C++ Libraries release 1.9.0, + /// this class also supports Internationalized Domain Names (IDNs). + /// + /// Regarding IDNs, the following rules apply: + /// + /// * An IDN passed to hostByName() must be encoded manually, by calling + /// encodeIDN() (after testing with isIDN() first). + /// * An UTF-8 IDN passed to resolve() or resolveOne() is automatically encoded. + /// * IDNs returned in HostEntry objects are never decoded. They can be + /// decoded by calling decodeIDN() (after testing for an encoded IDN by + /// calling isEncodedIDN()). +{ +public: + enum HintFlag + { + DNS_HINT_NONE = 0, +#ifdef POCO_HAVE_ADDRINFO + DNS_HINT_AI_PASSIVE = AI_PASSIVE, /// Socket address will be used in bind() call + DNS_HINT_AI_CANONNAME = AI_CANONNAME, /// Return canonical name in first ai_canonname + DNS_HINT_AI_NUMERICHOST = AI_NUMERICHOST, /// Nodename must be a numeric address string + DNS_HINT_AI_NUMERICSERV = AI_NUMERICSERV, /// Servicename must be a numeric port number + DNS_HINT_AI_ALL = AI_ALL, /// Query both IP6 and IP4 with AI_V4MAPPED + DNS_HINT_AI_ADDRCONFIG = AI_ADDRCONFIG, /// Resolution only if global address configured + DNS_HINT_AI_V4MAPPED = AI_V4MAPPED /// On v6 failure, query v4 and convert to V4MAPPED format +#endif + }; + + static const Poco::Timespan DEFAULT_DNS_TIMEOUT; + + static HostEntry hostByName(const std::string& hostname, const Poco::Timespan * timeout_ = &DEFAULT_DNS_TIMEOUT, unsigned hintFlags = +#ifdef POCO_HAVE_ADDRINFO + DNS_HINT_AI_CANONNAME | DNS_HINT_AI_ADDRCONFIG +#else + DNS_HINT_NONE +#endif + ); + /// Returns a HostEntry object containing the DNS information + /// for the host with the given name. HintFlag argument is only + /// used on platforms that have getaddrinfo(). + /// + /// Note that Internationalized Domain Names must be encoded + /// using Punycode (see encodeIDN()) before calling this method. + /// + /// Throws a HostNotFoundException if a host with the given + /// name cannot be found. + /// + /// Throws a NoAddressFoundException if no address can be + /// found for the hostname. + /// + /// Throws a DNSException in case of a general DNS error. + /// + /// Throws an IOException in case of any other error. + + static HostEntry hostByAddress(const IPAddress& address, const Poco::Timespan * timeout_ = &DEFAULT_DNS_TIMEOUT, unsigned hintFlags = +#ifdef POCO_HAVE_ADDRINFO + DNS_HINT_AI_CANONNAME | DNS_HINT_AI_ADDRCONFIG +#else + DNS_HINT_NONE +#endif + ); + /// Returns a HostEntry object containing the DNS information + /// for the host with the given IP address. HintFlag argument is only + /// used on platforms that have getaddrinfo(). + /// + /// Throws a HostNotFoundException if a host with the given + /// name cannot be found. + /// + /// Throws a DNSException in case of a general DNS error. + /// + /// Throws an IOException in case of any other error. + + static HostEntry resolve(const std::string& address); + /// Returns a HostEntry object containing the DNS information + /// for the host with the given IP address or host name. + /// + /// If address contains a UTF-8 encoded IDN (internationalized + /// domain name), the domain name will be encoded first using + /// Punycode. + /// + /// Throws a HostNotFoundException if a host with the given + /// name cannot be found. + /// + /// Throws a NoAddressFoundException if no address can be + /// found for the hostname. + /// + /// Throws a DNSException in case of a general DNS error. + /// + /// Throws an IOException in case of any other error. + + static IPAddress resolveOne(const std::string& address); + /// Convenience method that calls resolve(address) and returns + /// the first address from the HostInfo. + + static HostEntry thisHost(); + /// Returns a HostEntry object containing the DNS information + /// for this host. + /// + /// Throws a HostNotFoundException if DNS information + /// for this host cannot be found. + /// + /// Throws a NoAddressFoundException if no address can be + /// found for this host. + /// + /// Throws a DNSException in case of a general DNS error. + /// + /// Throws an IOException in case of any other error. + + static void reload(); + /// Reloads the resolver configuration. + /// + /// This method will call res_init() if the Net library + /// has been compiled with -DPOCO_HAVE_LIBRESOLV. Otherwise + /// it will do nothing. + + static std::string hostName(); + /// Returns the host name of this host. + + static bool isIDN(const std::string& hostname); + /// Returns true if the given hostname is an internationalized + /// domain name (IDN) containing non-ASCII characters, otherwise false. + /// + /// The IDN must be UTF-8 encoded. + + static bool isEncodedIDN(const std::string& hostname); + /// Returns true if the given hostname is an Punycode-encoded + /// internationalized domain name (IDN), otherwise false. + /// + /// An encoded IDN starts with the character sequence "xn--". + + static std::string encodeIDN(const std::string& idn); + /// Encodes the given IDN (internationalized domain name), which must + /// be in UTF-8 encoding. + /// + /// The resulting string will be encoded according to Punycode. + + static std::string decodeIDN(const std::string& encodedIDN); + /// Decodes the given Punycode-encoded IDN (internationalized domain name). + /// + /// The resulting string will be UTF-8 encoded. + +protected: + static int lastError(); + /// Returns the code of the last error. + + static void error(int code, const std::string& arg); + /// Throws an exception according to the error code. + + static void aierror(int code, const std::string& arg); + /// Throws an exception according to the getaddrinfo() error code. + + static std::string encodeIDNLabel(const std::string& idn); + /// Encodes the given IDN (internationalized domain name) label, which must + /// be in UTF-8 encoding. + /// + /// The resulting string will be encoded according to Punycode. + + static std::string decodeIDNLabel(const std::string& encodedIDN); + /// Decodes the given Punycode-encoded IDN (internationalized domain name) label. + /// + /// The resulting string will be UTF-8 encoded. +}; + + +} } // namespace Poco::Net + + +#endif // Net_DNS_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/DatagramSocket.h b/contrib/libs/poco/Net/include/Poco/Net/DatagramSocket.h new file mode 100644 index 0000000000..17d0253155 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/DatagramSocket.h @@ -0,0 +1,168 @@ +// +// DatagramSocket.h +// +// Library: Net +// Package: Sockets +// Module: DatagramSocket +// +// Definition of the DatagramSocket class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_DatagramSocket_INCLUDED +#define Net_DatagramSocket_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/Socket.h" + + +namespace Poco { +namespace Net { + + +class Net_API DatagramSocket: public Socket + /// This class provides an interface to an + /// UDP stream socket. +{ +public: + DatagramSocket(); + /// Creates an unconnected, unbound datagram socket. + /// + /// Before the datagram socket can be used, bind(), + /// bind6() or connect() must be called. + /// + /// Notice: The behavior of this constructor has changed + /// in release 2.0. Previously, the constructor created + /// an unbound IPv4 datagram socket. + + explicit DatagramSocket(SocketAddress::Family family); + /// Creates an unconnected datagram socket. + /// + /// The socket will be created for the + /// given address family. + + DatagramSocket(const SocketAddress& address, bool reuseAddress = false); + /// Creates a datagram socket and binds it + /// to the given address. + /// + /// Depending on the address family, the socket + /// will be either an IPv4 or an IPv6 socket. + + DatagramSocket(const Socket& socket); + /// Creates the DatagramSocket with the SocketImpl + /// from another socket. The SocketImpl must be + /// a DatagramSocketImpl, otherwise an InvalidArgumentException + /// will be thrown. + + ~DatagramSocket(); + /// Destroys the DatagramSocket. + + DatagramSocket& operator = (const Socket& socket); + /// Assignment operator. + /// + /// Releases the socket's SocketImpl and + /// attaches the SocketImpl from the other socket and + /// increments the reference count of the SocketImpl. + + void connect(const SocketAddress& address); + /// Restricts incoming and outgoing + /// packets to the specified address. + /// + /// Calls to connect() cannot come before calls to bind(). + + void bind(const SocketAddress& address, bool reuseAddress = false); + /// Bind a local address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// Calls to connect cannot() come before calls to bind(). + + void bind(const SocketAddress& address, bool reuseAddress, bool reusePort); + /// Bind a local address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + /// + /// Calls to connect cannot() come before calls to bind(). + + int sendBytes(const void* buffer, int length, int flags = 0); + /// Sends the contents of the given buffer through + /// the socket. + /// + /// Returns the number of bytes sent, which may be + /// less than the number of bytes specified. + + int receiveBytes(void* buffer, int length, int flags = 0); + /// Receives data from the socket and stores it + /// in buffer. Up to length bytes are received. + /// + /// Returns the number of bytes received. + + int sendTo(const void* buffer, int length, const SocketAddress& address, int flags = 0); + /// Sends the contents of the given buffer through + /// the socket to the given address. + /// + /// Returns the number of bytes sent, which may be + /// less than the number of bytes specified. + + int receiveFrom(void* buffer, int length, SocketAddress& address, int flags = 0); + /// Receives data from the socket and stores it + /// in buffer. Up to length bytes are received. + /// Stores the address of the sender in address. + /// + /// Returns the number of bytes received. + + void setBroadcast(bool flag); + /// Sets the value of the SO_BROADCAST socket option. + /// + /// Setting this flag allows sending datagrams to + /// the broadcast address. + + bool getBroadcast() const; + /// Returns the value of the SO_BROADCAST socket option. + +protected: + DatagramSocket(SocketImpl* pImpl); + /// Creates the Socket and attaches the given SocketImpl. + /// The socket takes ownership of the SocketImpl. + /// + /// The SocketImpl must be a StreamSocketImpl, otherwise + /// an InvalidArgumentException will be thrown. +}; + + +// +// inlines +// +inline void DatagramSocket::setBroadcast(bool flag) +{ + impl()->setBroadcast(flag); +} + + +inline bool DatagramSocket::getBroadcast() const +{ + return impl()->getBroadcast(); +} + + +} } // namespace Poco::Net + + +#endif // Net_DatagramSocket_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/DatagramSocketImpl.h b/contrib/libs/poco/Net/include/Poco/Net/DatagramSocketImpl.h new file mode 100644 index 0000000000..f9d280aa1b --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/DatagramSocketImpl.h @@ -0,0 +1,55 @@ +// +// DatagramSocketImpl.h +// +// Library: Net +// Package: Sockets +// Module: DatagramSocketImpl +// +// Definition of the DatagramSocketImpl class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_DatagramSocketImpl_INCLUDED +#define Net_DatagramSocketImpl_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketImpl.h" + + +namespace Poco { +namespace Net { + + +class Net_API DatagramSocketImpl: public SocketImpl + /// This class implements an UDP socket. +{ +public: + DatagramSocketImpl(); + /// Creates an unconnected, unbound datagram socket. + + explicit DatagramSocketImpl(SocketAddress::Family family); + /// Creates an unconnected datagram socket. + /// + /// The socket will be created for the + /// given address family. + + DatagramSocketImpl(poco_socket_t sockfd); + /// Creates a StreamSocketImpl using the given native socket. + +protected: + void init(int af); + + ~DatagramSocketImpl(); +}; + + +} } // namespace Poco::Net + + +#endif // Net_DatagramSocketImpl_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/DialogSocket.h b/contrib/libs/poco/Net/include/Poco/Net/DialogSocket.h new file mode 100644 index 0000000000..ca47b73ba6 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/DialogSocket.h @@ -0,0 +1,211 @@ +// +// DialogSocket.h +// +// Library: Net +// Package: Sockets +// Module: DialogSocket +// +// Definition of the DialogSocket class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_DialogSocket_INCLUDED +#define Net_DialogSocket_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/StreamSocket.h" +#include <cstdlib> + + +namespace Poco { +namespace Net { + + +class Net_API DialogSocket: public StreamSocket + /// DialogSocket is a subclass of StreamSocket that + /// can be used for implementing request-response + /// based client server connections. + /// + /// A request is always a single-line command terminated + /// by CR-LF. + /// + /// A response can either be a single line of text terminated + /// by CR-LF, or multiple lines of text in the format used + /// by the FTP and SMTP protocols. + /// + /// Limited support for the TELNET protocol (RFC 854) is + /// available. + /// + /// Warning: Do not call receiveBytes() on a DialogSocket. + /// Due to internal buffering in DialogSocket, receiveBytes() + /// may return an unexpected result and interfere with + /// DialogSocket's buffering. Use receiveRawBytes() instead. +{ +public: + DialogSocket(); + /// Creates an unconnected stream socket. + /// + /// Before sending or receiving data, the socket + /// must be connected with a call to connect(). + + explicit DialogSocket(const SocketAddress& address); + /// Creates a stream socket and connects it to + /// the socket specified by address. + + DialogSocket(const Socket& socket); + /// Creates the DialogSocket with the SocketImpl + /// from another socket. The SocketImpl must be + /// a StreamSocketImpl, otherwise an InvalidArgumentException + /// will be thrown. + + DialogSocket(const DialogSocket& socket); + /// Creates the DialogSocket as copy of another dialog socket. + + ~DialogSocket(); + /// Destroys the DialogSocket. + + DialogSocket& operator = (const Socket& socket); + /// Assignment operator. + /// + /// Releases the socket's SocketImpl and + /// attaches the SocketImpl from the other socket and + /// increments the reference count of the SocketImpl. + + DialogSocket& operator = (const DialogSocket& socket); + /// Assignment operator. + + void sendByte(unsigned char ch); + /// Sends a single byte over the socket connection. + + void sendString(const char* str); + /// Sends the given null-terminated string over + /// the socket connection. + + void sendString(const std::string& str); + /// Sends the given string over the socket connection. + + void sendMessage(const std::string& message); + /// Appends a CR-LF sequence to the message and sends it + /// over the socket connection. + + void sendMessage(const std::string& message, const std::string& arg); + /// Concatenates message and arg, separated by a space, appends a + /// CR-LF sequence, and sends the result over the socket connection. + + void sendMessage(const std::string& message, const std::string& arg1, const std::string& arg2); + /// Concatenates message and args, separated by a space, appends a + /// CR-LF sequence, and sends the result over the socket connection. + + bool receiveMessage(std::string& message); + /// Receives a single-line message, terminated by CR-LF, + /// from the socket connection and appends it to response. + /// + /// Returns true if a message has been read or false if + /// the connection has been closed by the peer. + + int receiveStatusMessage(std::string& message); + /// Receives a single-line or multi-line response from + /// the socket connection. The format must be according to + /// one of the response formats specified in the FTP (RFC 959) + /// or SMTP (RFC 2821) specifications. + /// + /// The first line starts with a 3-digit status code. + /// Following the status code is either a space character (' ' ) + /// (in case of a single-line response) or a minus character ('-') + /// in case of a multi-line response. The following lines can have + /// a three-digit status code followed by a minus-sign and some + /// text, or some arbitrary text only. The last line again begins + /// with a three-digit status code (which must be the same as the + /// one in the first line), followed by a space and some arbitrary + /// text. All lines must be terminated by a CR-LF sequence. + /// + /// The response contains all response lines, separated by a newline + /// character, including the status code. The status code is returned. + /// If the response line does not contain a status code, 0 is returned. + + int get(); + /// Reads one character from the connection. + /// + /// Returns -1 (EOF_CHAR) if no more characters are available. + + int peek(); + /// Returns the character that would be returned by the next call + /// to get(), without actually extracting the character from the + /// buffer. + /// + /// Returns -1 (EOF_CHAR) if no more characters are available. + + int receiveRawBytes(void* buffer, int length); + /// Read up to length bytes from the connection and place + /// them into buffer. If there are data bytes in the internal + /// buffer, these bytes are returned first. + /// + /// Use this member function instead of receiveBytes(). + /// + /// Returns the number of bytes read, which may be + /// less than requested. + + void synch(); + /// Sends a TELNET SYNCH signal over the connection. + /// + /// According to RFC 854, a TELNET_DM char is sent + /// via sendUrgent(). + + void sendTelnetCommand(unsigned char command); + /// Sends a TELNET command sequence (TELNET_IAC followed + /// by the given command) over the connection. + + void sendTelnetCommand(unsigned char command, unsigned char arg); + /// Sends a TELNET command sequence (TELNET_IAC followed + /// by the given command, followed by arg) over the connection. + + enum TelnetCodes + { + TELNET_SE = 240, + TELNET_NOP = 241, + TELNET_DM = 242, + TELNET_BRK = 243, + TELNET_IP = 244, + TELNET_AO = 245, + TELNET_AYT = 246, + TELNET_EC = 247, + TELNET_EL = 248, + TELNET_GA = 249, + TELNET_SB = 250, + TELNET_WILL = 251, + TELNET_WONT = 252, + TELNET_DO = 253, + TELNET_DONT = 254, + TELNET_IAC = 255 + }; + +protected: + void allocBuffer(); + void refill(); + bool receiveLine(std::string& line, std::size_t lineLengthLimit = 0); + int receiveStatusLine(std::string& line, std::size_t lineLengthLimit = 0); + +private: + enum + { + RECEIVE_BUFFER_SIZE = 1024, + MAX_LINE_LENGTH = 4096, + EOF_CHAR = -1 + }; + + char* _pBuffer; + char* _pNext; + char* _pEnd; +}; + + +} } // namespace Poco::Net + + +#endif // Net_DialogSocket_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/FTPClientSession.h b/contrib/libs/poco/Net/include/Poco/Net/FTPClientSession.h new file mode 100644 index 0000000000..1750cfc028 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/FTPClientSession.h @@ -0,0 +1,403 @@ +// +// FTPClientSession.h +// +// Library: Net +// Package: FTP +// Module: FTPClientSession +// +// Definition of the FTPClientSession class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_FTPClientSession_INCLUDED +#define Net_FTPClientSession_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/DialogSocket.h" +#include "Poco/Timespan.h" +#include <istream> +#include <ostream> + + +namespace Poco { +namespace Net { + + +class SocketStream; + + +class Net_API FTPClientSession + /// This class implements an File Transfer Protocol + /// (FTP, RFC 959) client. + /// + /// Most of the features of the FTP protocol, as specified + /// in RFC 959, are supported. Not supported are EBCDIC and + /// LOCAL data types and format control and structured files. + /// + /// Also supported are the EPRT and EPSV commands from + /// RFC 1738 (FTP Extensions for IPv6 and NAT). + /// The client will first attempt to use the EPRT and EPSV + /// commands. If the server does not supports these commands, + /// the client will fall back to PORT and PASV. +{ +public: + enum + { + FTP_PORT = 21 + }; + + enum FileType + { + TYPE_TEXT, // TYPE A (ASCII) + TYPE_BINARY // TYPE I (Image) + }; + + FTPClientSession(); + /// Creates an FTPClientSession. + /// + /// Passive mode will be used for data transfers. + + explicit FTPClientSession(const StreamSocket& socket); + /// Creates an FTPClientSession using the given + /// connected socket for the control connection. + /// + /// Passive mode will be used for data transfers. + + FTPClientSession(const std::string& host, + Poco::UInt16 port = FTP_PORT, + const std::string& username = "", + const std::string& password = ""); + /// Creates an FTPClientSession using a socket connected + /// to the given host and port. If username is supplied, + /// login is attempted. + /// + /// Passive mode will be used for data transfers. + + virtual ~FTPClientSession(); + /// Destroys the FTPClientSession. + + void setTimeout(const Poco::Timespan& timeout); + /// Sets the timeout for socket operations. + + Poco::Timespan getTimeout() const; + /// Returns the timeout for socket operations. + + void setPassive(bool flag, bool useRFC1738 = true); + /// Enables (default) or disables FTP passive mode for this session. + /// + /// If useRFC1738 is true (the default), the RFC 1738 + /// EPSV command is used (with a fallback to PASV if EPSV fails) + /// for switching to passive mode. The same applies to + /// EPRT and PORT for active connections. + + bool getPassive() const; + /// Returns true iff passive mode is enabled for this connection. + + void open(const std::string& host, + Poco::UInt16 port, + const std::string& username = "", + const std::string& password = ""); + /// Opens the FTP connection to the given host and port. + /// If username is supplied, login is attempted. + + void login(const std::string& username, const std::string& password); + /// Authenticates the user against the FTP server. Must be + /// called before any other commands (except QUIT) can be sent. + /// + /// Sends a USER command followed by a PASS command with the + /// respective arguments to the server. + /// + /// Throws a FTPException in case of a FTP-specific error, or a + /// NetException in case of a general network communication failure. + + void logout(); + + void close(); + /// Sends a QUIT command and closes the connection to the server. + /// + /// Throws a FTPException in case of a FTP-specific error, or a + /// NetException in case of a general network communication failure. + + std::string systemType(); + /// Returns the system type of the FTP server. + /// + /// Sends a SYST command to the server and returns the result. + + void setFileType(FileType type); + /// Sets the file type for transferring files. + /// + /// Sends a TYPE command with a corresponding argument to the + /// server. + /// + /// Throws a FTPException in case of a FTP-specific error, or a + /// NetException in case of a general network communication failure. + + FileType getFileType() const; + /// Returns the file type for transferring files. + + void setWorkingDirectory(const std::string& path); + /// Changes the current working directory on the server. + /// + /// Sends a CWD command with the given path as argument to the + /// server. + /// + /// Throws a FTPException in case of a FTP-specific error, or a + /// NetException in case of a general network communication failure. + + std::string getWorkingDirectory(); + /// Returns the current working directory on the server. + /// + /// Throws a FTPException in case of a FTP-specific error, or a + /// NetException in case of a general network communication failure. + + void cdup(); + /// Moves one directory up from the current working directory + /// on the server. + /// + /// Sends a CDUP command to the server. + /// + /// Throws a FTPException in case of a FTP-specific error, or a + /// NetException in case of a general network communication failure. + + void rename(const std::string& oldName, const std::string& newName); + /// Renames the file on the server given by oldName to newName. + /// + /// Sends a RNFR command, followed by a RNTO command to the server. + /// + /// Throws a FTPException in case of a FTP-specific error, or a + /// NetException in case of a general network communication failure. + + void remove(const std::string& path); + /// Deletes the file specified by path on the server. + /// + /// Sends a DELE command with path as argument to the server. + /// + /// Throws a FTPException in case of a FTP-specific error, or a + /// NetException in case of a general network communication failure. + + void createDirectory(const std::string& path); + /// Creates a new directory with the given path on the server. + /// + /// Sends a MKD command with path as argument to the server. + /// + /// Throws a FTPException in case of a FTP-specific error, or a + /// NetException in case of a general network communication failure. + + void removeDirectory(const std::string& path); + /// Removes the directory specified by path from the server. + /// + /// Sends a RMD command with path as argument to the server. + /// + /// Throws a FTPException in case of a FTP-specific error, or a + /// NetException in case of a general network communication failure. + + std::istream& beginDownload(const std::string& path); + /// Starts downloading the file with the given name. + /// After all data has been read from the returned stream, + /// endDownload() must be called to finish the download. + /// + /// A stream for reading the file's content is returned. + /// The stream is valid until endDownload() is called. + /// + /// Creates a data connection between the client and the + /// server. If passive mode is on, then the server waits for + /// a connection request from the client. Otherwise, the + /// client waits for a connection request from the server. + /// After establishing the data connection, a SocketStream + /// for transferring the data is created. + /// + /// If ASCII transfer mode is selected, the caller is + /// responsible for converting the received data to + /// the native text file format. + /// The InputLineEndingConverter class from the Foundation + /// library can be used for that purpose. + + void endDownload(); + /// Must be called to complete a download initiated with + /// beginDownload(). + + std::ostream& beginUpload(const std::string& path); + /// Starts uploading the file with the given name. + /// After all data has been written to the returned stream, + /// endUpload() must be called to finish the upload. + /// + /// A stream for reading the file's content is returned. + /// The stream is valid until endUpload() is called. + /// + /// Creates a data connection between the client and the + /// server. If passive mode is on, then the server waits for + /// a connection request from the client. Otherwise, the + /// client waits for a connection request from the server. + /// After establishing the data connection, a SocketStream + /// for transferring the data is created. + /// + /// If ASCII transfer mode is selected, the caller is + /// responsible for converting the data to be sent + /// into network (CR-LF line endings) format. + /// The OutputLineEndingConverter class from the Foundation + /// library can be used for that purpose. + + void endUpload(); + /// Must be called to complete an upload initiated with + /// beginUpload(). + + std::istream& beginList(const std::string& path = "", bool extended = false); + /// Starts downloading a directory listing. + /// After all data has been read from the returned stream, + /// endList() must be called to finish the download. + /// + /// A stream for reading the directory data is returned. + /// The stream is valid until endList() is called. + /// + /// Optionally, a path to a directory or file can be specified. + /// According to the FTP protocol, if a path to a filename is + /// given, only information for the specific file is returned. + /// If a path to a directory is given, a listing of that directory + /// is returned. If no path is given, a listing of the current + /// working directory is returned. + /// + /// If extended is false, only a filenames (one per line) are + /// returned. Otherwise, a full directory listing including + /// file attributes is returned. The format of this listing + /// depends on the FTP server. No attempt is made to interpret + /// this data. + /// + /// Creates a data connection between the client and the + /// server. If passive mode is on, then the server waits for + /// a connection request from the client. Otherwise, the + /// client waits for a connection request from the server. + /// After establishing the data connection, a SocketStream + /// for transferring the data is created. + + void endList(); + /// Must be called to complete a directory listing download + /// initiated with beginList(). + + void abort(); + /// Aborts the download or upload currently in progress. + /// + /// Sends a TELNET IP/SYNCH sequence, followed by an ABOR + /// command to the server. + /// + /// A separate call to endDownload() or endUpload() is + /// not necessary. + + int sendCommand(const std::string& command, std::string& response); + /// Sends the given command verbatim to the server + /// and waits for a response. + + int sendCommand(const std::string& command, const std::string& arg, std::string& response); + /// Sends the given command verbatim to the server + /// and waits for a response. + + bool isOpen() const; + /// Returns true if the connection with FTP server is opened. + + bool isLoggedIn() const; + /// Returns true if the session is logged in. + +protected: + enum StatusClass + { + FTP_POSITIVE_PRELIMINARY = 1, + FTP_POSITIVE_COMPLETION = 2, + FTP_POSITIVE_INTERMEDIATE = 3, + FTP_TRANSIENT_NEGATIVE = 4, + FTP_PERMANENT_NEGATIVE = 5 + }; + enum + { + DEFAULT_TIMEOUT = 30000000 // 30 seconds default timeout for socket operations + }; + + static bool isPositivePreliminary(int status); + static bool isPositiveCompletion(int status); + static bool isPositiveIntermediate(int status); + static bool isTransientNegative(int status); + static bool isPermanentNegative(int status); + std::string extractPath(const std::string& response); + StreamSocket establishDataConnection(const std::string& command, const std::string& arg); + StreamSocket activeDataConnection(const std::string& command, const std::string& arg); + StreamSocket passiveDataConnection(const std::string& command, const std::string& arg); + void sendPortCommand(const SocketAddress& addr); + SocketAddress sendPassiveCommand(); + bool sendEPRT(const SocketAddress& addr); + void sendPORT(const SocketAddress& addr); + bool sendEPSV(SocketAddress& addr); + void sendPASV(SocketAddress& addr); + void parseAddress(const std::string& str, SocketAddress& addr); + void parseExtAddress(const std::string& str, SocketAddress& addr); + void endTransfer(); + +private: + FTPClientSession(const FTPClientSession&); + FTPClientSession& operator = (const FTPClientSession&); + + std::string _host; + Poco::UInt16 _port; + DialogSocket* _pControlSocket; + SocketStream* _pDataStream; + bool _passiveMode; + FileType _fileType; + bool _supports1738; + bool _serverReady; + bool _isLoggedIn; + Poco::Timespan _timeout; +}; + + +// +// inlines +// +inline bool FTPClientSession::isPositivePreliminary(int status) +{ + return status/100 == FTP_POSITIVE_PRELIMINARY; +} + + +inline bool FTPClientSession::isPositiveCompletion(int status) +{ + return status/100 == FTP_POSITIVE_COMPLETION; +} + + +inline bool FTPClientSession::isPositiveIntermediate(int status) +{ + return status/100 == FTP_POSITIVE_INTERMEDIATE; +} + + +inline bool FTPClientSession::isTransientNegative(int status) +{ + return status/100 == FTP_TRANSIENT_NEGATIVE; +} + + +inline bool FTPClientSession::isPermanentNegative(int status) +{ + return status/100 == FTP_PERMANENT_NEGATIVE; +} + + +inline bool FTPClientSession::isOpen() const +{ + return _pControlSocket != 0; +} + + +inline bool FTPClientSession::isLoggedIn() const +{ + return _isLoggedIn; +} + + +} } // namespace Poco::Net + + +#endif // Net_FTPClientSession_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/FTPStreamFactory.h b/contrib/libs/poco/Net/include/Poco/Net/FTPStreamFactory.h new file mode 100644 index 0000000000..4f33f19c19 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/FTPStreamFactory.h @@ -0,0 +1,120 @@ +// +// FTPStreamFactory.h +// +// Library: Net +// Package: FTP +// Module: FTPStreamFactory +// +// Definition of the FTPStreamFactory class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_FTPStreamFactory_INCLUDED +#define Net_FTPStreamFactory_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPSession.h" +#include "Poco/URIStreamFactory.h" + + +namespace Poco { +namespace Net { + + +class Net_API FTPPasswordProvider + /// The base class for all password providers. + /// An instance of a subclass of this class can be + /// registered with the FTPStreamFactory to + /// provide a password +{ +public: + virtual std::string password(const std::string& username, const std::string& host) = 0; + /// Provide the password for the given user on the given host. + +protected: + FTPPasswordProvider(); + virtual ~FTPPasswordProvider(); +}; + + +class Net_API FTPStreamFactory: public Poco::URIStreamFactory + /// An implementation of the URIStreamFactory interface + /// that handles File Transfer Protocol (ftp) URIs. + /// + /// The URI's path may end with an optional type specification + /// in the form (;type=<typecode>), where <typecode> is + /// one of a, i or d. If type=a, the file identified by the path + /// is transferred in ASCII (text) mode. If type=i, the file + /// is transferred in Image (binary) mode. If type=d, a directory + /// listing (in NLST format) is returned. This corresponds with + /// the FTP URL format specified in RFC 1738. + /// + /// If the URI does not contain a username and password, the + /// username "anonymous" and the password " +{ +public: + FTPStreamFactory(); + /// Creates the FTPStreamFactory. + + ~FTPStreamFactory(); + /// Destroys the FTPStreamFactory. + + std::istream* open(const Poco::URI& uri); + /// Creates and opens a HTTP stream for the given URI. + /// The URI must be a ftp://... URI. + /// + /// Throws a NetException if anything goes wrong. + + static void setAnonymousPassword(const std::string& password); + /// Sets the password used for anonymous FTP. + /// + /// WARNING: Setting the anonymous password is not + /// thread-safe, so it's best to call this method + /// during application initialization, before the + /// FTPStreamFactory is used for the first time. + + static const std::string& getAnonymousPassword(); + /// Returns the password used for anonymous FTP. + + static void setPasswordProvider(FTPPasswordProvider* pProvider); + /// Sets the FTPPasswordProvider. If NULL is given, + /// no password provider is used. + /// + /// WARNING: Setting the password provider is not + /// thread-safe, so it's best to call this method + /// during application initialization, before the + /// FTPStreamFactory is used for the first time. + + static FTPPasswordProvider* getPasswordProvider(); + /// Returns the FTPPasswordProvider currently in use, + /// or NULL if no one has been set. + + static void registerFactory(); + /// Registers the FTPStreamFactory with the + /// default URIStreamOpener instance. + + static void unregisterFactory(); + /// Unregisters the FTPStreamFactory with the + /// default URIStreamOpener instance. + +protected: + static void splitUserInfo(const std::string& userInfo, std::string& username, std::string& password); + static void getUserInfo(const Poco::URI& uri, std::string& username, std::string& password); + static void getPathAndType(const Poco::URI& uri, std::string& path, char& type); + +private: + static std::string _anonymousPassword; + static FTPPasswordProvider* _pPasswordProvider; +}; + + +} } // namespace Poco::Net + + +#endif // Net_FTPStreamFactory_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/FilePartSource.h b/contrib/libs/poco/Net/include/Poco/Net/FilePartSource.h new file mode 100644 index 0000000000..056718541d --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/FilePartSource.h @@ -0,0 +1,77 @@ +// +// FilePartSource.h +// +// Library: Net +// Package: Messages +// Module: FilePartSource +// +// Definition of the FilePartSource class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_FilePartSource_INCLUDED +#define Net_FilePartSource_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/PartSource.h" +#include "Poco/FileStream.h" + + +namespace Poco { +namespace Net { + + +class Net_API FilePartSource: public PartSource + /// An implementation of PartSource for + /// plain files. +{ +public: + FilePartSource(const std::string& path); + /// Creates the FilePartSource for the given path. + /// + /// The MIME type is set to application/octet-stream. + /// + /// Throws an OpenFileException if the file cannot be opened. + + FilePartSource(const std::string& path, const std::string& mediaType); + /// Creates the FilePartSource for the given + /// path and MIME type. + /// + /// Throws an OpenFileException if the file cannot be opened. + + FilePartSource(const std::string& path, const std::string& filename, const std::string& mediaType); + /// Creates the FilePartSource for the given + /// path and MIME type. The given filename is + /// used as part filename (see filename()) only. + /// + /// Throws an OpenFileException if the file cannot be opened. + + ~FilePartSource(); + /// Destroys the FilePartSource. + + std::istream& stream(); + /// Returns a file input stream for the given file. + + const std::string& filename() const; + /// Returns the filename portion of the path. + + std::streamsize getContentLength() const; + /// Returns the file size. + +private: + std::string _path; + std::string _filename; + Poco::FileInputStream _istr; +}; + + +} } // namespace Poco::Net + + +#endif // Net_FilePartSource_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTMLForm.h b/contrib/libs/poco/Net/include/Poco/Net/HTMLForm.h new file mode 100644 index 0000000000..a4649dd2c2 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTMLForm.h @@ -0,0 +1,272 @@ +// +// HTMLForm.h +// +// Library: Net +// Package: HTML +// Module: HTMLForm +// +// Definition of the HTMLForm class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTMLForm_INCLUDED +#define Net_HTMLForm_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/NameValueCollection.h" +#include <ostream> +#include <istream> +#include <vector> + + +namespace Poco { +namespace Net { + + +class HTTPRequest; +class PartHandler; +class PartSource; + + +class Net_API HTMLForm: public NameValueCollection + /// HTMLForm is a helper class for working with HTML forms, + /// both on the client and on the server side. + /// + /// The maximum number of form fields can be restricted + /// by calling setFieldLimit(). This is useful to + /// defend against certain kinds of denial-of-service + /// attacks. The limit is only enforced when parsing + /// form data from a stream or string, not when adding + /// form fields programmatically. The default limit is 100. +{ +public: + enum Options + { + OPT_USE_CONTENT_LENGTH = 0x01 + /// Don't use Chunked Transfer-Encoding for multipart requests. + }; + + HTMLForm(); + /// Creates an empty HTMLForm and sets the + /// encoding to "application/x-www-form-urlencoded". + + explicit HTMLForm(const std::string& encoding); + /// Creates an empty HTMLForm that uses + /// the given encoding. + /// + /// Encoding must be either "application/x-www-form-urlencoded" + /// (which is the default) or "multipart/form-data". + + HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler); + /// Creates a HTMLForm from the given HTTP request. + /// + /// Uploaded files are passed to the given PartHandler. + + HTMLForm(const HTTPRequest& request, std::istream& requestBody); + /// Creates a HTMLForm from the given HTTP request. + /// + /// Uploaded files are silently discarded. + + explicit HTMLForm(const HTTPRequest& request); + /// Creates a HTMLForm from the given HTTP request. + /// + /// The request must be a GET request and the form data + /// must be in the query string (URL encoded). + /// + /// For POST requests, you must use one of the constructors + /// taking an additional input stream for the request body. + + ~HTMLForm(); + /// Destroys the HTMLForm. + + void setEncoding(const std::string& encoding); + /// Sets the encoding used for posting the form. + /// + /// Encoding must be either "application/x-www-form-urlencoded" + /// (which is the default) or "multipart/form-data". + + const std::string& getEncoding() const; + /// Returns the encoding used for posting the form. + + void addPart(const std::string& name, PartSource* pSource); + /// Adds an part/attachment (file upload) to the form. + /// + /// The form takes ownership of the PartSource and deletes it + /// when it is no longer needed. + /// + /// The part will only be sent if the encoding + /// set for the form is "multipart/form-data" + + void load(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler); + /// Reads the form data from the given HTTP request. + /// + /// Uploaded files are passed to the given PartHandler. + + void load(const HTTPRequest& request, std::istream& requestBody); + /// Reads the form data from the given HTTP request. + /// + /// Uploaded files are silently discarded. + + void load(const HTTPRequest& request); + /// Reads the form data from the given HTTP request. + /// + /// The request must be a GET request and the form data + /// must be in the query string (URL encoded). + /// + /// For POST requests, you must use one of the overloads + /// taking an additional input stream for the request body. + + void read(std::istream& istr, PartHandler& handler); + /// Reads the form data from the given input stream. + /// + /// The form data read from the stream must be + /// in the encoding specified for the form. + /// + /// Note that read() does not clear the form before + /// reading the new values. + + void read(std::istream& istr); + /// Reads the URL-encoded form data from the given input stream. + /// + /// Note that read() does not clear the form before + /// reading the new values. + + void read(const std::string& queryString); + /// Reads the form data from the given HTTP query string. + /// + /// Note that read() does not clear the form before + /// reading the new values. + + void prepareSubmit(HTTPRequest& request, int options = 0); + /// Fills out the request object for submitting the form. + /// + /// If the request method is GET, the encoded form is appended to the + /// request URI as query string. Otherwise (the method is + /// POST), the form's content type is set to the form's encoding. + /// The form's parameters must be written to the + /// request body separately, with a call to write. + /// If the request's HTTP version is HTTP/1.0: + /// - persistent connections are disabled + /// - the content transfer encoding is set to identity encoding + /// Otherwise, if the request's HTTP version is HTTP/1.1: + /// - the request's persistent connection state is left unchanged + /// - the content transfer encoding is set to chunked, unless + /// the OPT_USE_CONTENT_LENGTH is given in options + /// + /// Note: Not using chunked transfer encoding for multipart forms + /// degrades performance, as the request content must be generated + /// twice, first to determine its size, then to actually send it. + + std::streamsize calculateContentLength(); + /// Calculate the content length for the form. + /// May be UNKNOWN_CONTENT_LENGTH if not possible + /// to calculate + + void write(std::ostream& ostr, const std::string& boundary); + /// Writes the form data to the given output stream, + /// using the specified encoding. + + void write(std::ostream& ostr); + /// Writes the form data to the given output stream, + /// using the specified encoding. + + const std::string& boundary() const; + /// Returns the MIME boundary used for writing + /// multipart form data. + + int getFieldLimit() const; + /// Returns the maximum number of header fields + /// allowed. + /// + /// See setFieldLimit() for more information. + + void setFieldLimit(int limit); + /// Sets the maximum number of header fields + /// allowed. This limit is used to defend certain + /// kinds of denial-of-service attacks. + /// Specify 0 for unlimited (not recommended). + /// + /// The default limit is 100. + + void setValueLengthLimit(int limit); + /// Sets the maximum size for form field values + /// stored as strings. + + int getValueLengthLimit() const; + /// Returns the maximum size for form field values + /// stored as strings. + + static const std::string ENCODING_URL; /// "application/x-www-form-urlencoded" + static const std::string ENCODING_MULTIPART; /// "multipart/form-data" + static const int UNKNOWN_CONTENT_LENGTH; + +protected: + void readUrl(std::istream& istr); + void readMultipart(std::istream& istr, PartHandler& handler); + void writeUrl(std::ostream& ostr); + void writeMultipart(std::ostream& ostr); + +private: + HTMLForm(const HTMLForm&); + HTMLForm& operator = (const HTMLForm&); + + enum Limits + { + DFL_FIELD_LIMIT = 100, + MAX_NAME_LENGTH = 1024, + DFL_MAX_VALUE_LENGTH = 256*1024 + }; + + struct Part + { + std::string name; + PartSource* pSource; + }; + + typedef std::vector<Part> PartVec; + + int _fieldLimit; + int _valueLengthLimit; + std::string _encoding; + std::string _boundary; + PartVec _parts; +}; + + +// +// inlines +// +inline const std::string& HTMLForm::getEncoding() const +{ + return _encoding; +} + + +inline const std::string& HTMLForm::boundary() const +{ + return _boundary; +} + + +inline int HTMLForm::getFieldLimit() const +{ + return _fieldLimit; +} + + +inline int HTMLForm::getValueLengthLimit() const +{ + return _valueLengthLimit; +} + + +} } // namespace Poco::Net + + +#endif // Net_HTMLForm_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPAuthenticationParams.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPAuthenticationParams.h new file mode 100644 index 0000000000..492e2c45d4 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPAuthenticationParams.h @@ -0,0 +1,103 @@ +// +// HTTPAuthenticationParams.h +// +// Library: Net +// Package: HTTP +// Module: HTTPAuthenticationParams +// +// Definition of the HTTPAuthenticationParams class. +// +// 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 +// + + +#ifndef Net_HTTPAuthenticationParams_INCLUDED +#define Net_HTTPAuthenticationParams_INCLUDED + + +#include "Poco/Net/NameValueCollection.h" + + +namespace Poco { +namespace Net { + + +class HTTPRequest; +class HTTPResponse; + + +class Net_API HTTPAuthenticationParams: public NameValueCollection + /// Collection of name-value pairs of HTTP authentication header (i.e. + /// "realm", "qop", "nonce" in case of digest authentication header). +{ +public: + HTTPAuthenticationParams(); + /// Creates an empty authentication parameters collection. + + explicit HTTPAuthenticationParams(const std::string& authInfo); + /// See fromAuthInfo() documentation. + + explicit HTTPAuthenticationParams(const HTTPRequest& request); + /// See fromRequest() documentation. + + HTTPAuthenticationParams(const HTTPResponse& response, const std::string& header = WWW_AUTHENTICATE); + /// See fromResponse() documentation. + + virtual ~HTTPAuthenticationParams(); + /// Destroys the HTTPAuthenticationParams. + + HTTPAuthenticationParams& operator = (const HTTPAuthenticationParams& authParams); + /// Assigns the content of another HTTPAuthenticationParams. + + void fromAuthInfo(const std::string& authInfo); + /// Creates an HTTPAuthenticationParams by parsing authentication + /// information. + + void fromRequest(const HTTPRequest& request); + /// Extracts authentication information from the request and creates + /// HTTPAuthenticationParams by parsing it. + /// + /// Throws a NotAuthenticatedException if no authentication + /// information is contained in request. + /// Throws a InvalidArgumentException if authentication scheme is + /// unknown or invalid. + + void fromResponse(const HTTPResponse& response, const std::string& header = WWW_AUTHENTICATE); + /// Extracts authentication information from the response and creates + /// HTTPAuthenticationParams by parsing it. + /// + /// Throws a NotAuthenticatedException if no authentication + /// information is contained in response. + /// Throws a InvalidArgumentException if authentication scheme is + /// unknown or invalid. + + void setRealm(const std::string& realm); + /// Sets the "realm" parameter to the provided string. + + const std::string& getRealm() const; + /// Returns value of the "realm" parameter. + /// + /// Throws NotFoundException is there is no "realm" set in the + /// HTTPAuthenticationParams. + + std::string toString() const; + /// Formats the HTTPAuthenticationParams for inclusion in HTTP + /// request or response authentication header. + + static const std::string REALM; + static const std::string WWW_AUTHENTICATE; + static const std::string PROXY_AUTHENTICATE; + +private: + void parse(std::string::const_iterator first, std::string::const_iterator last); +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPAuthenticationParams_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPBasicCredentials.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPBasicCredentials.h new file mode 100644 index 0000000000..56894db8ca --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPBasicCredentials.h @@ -0,0 +1,123 @@ +// +// HTTPBasicCredentials.h +// +// Library: Net +// Package: HTTP +// Module: HTTPBasicCredentials +// +// Definition of the HTTPBasicCredentials class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPBasicCredentials_INCLUDED +#define Net_HTTPBasicCredentials_INCLUDED + + +#include "Poco/Net/Net.h" + + +namespace Poco { +namespace Net { + + +class HTTPRequest; + + +class Net_API HTTPBasicCredentials + /// This is a utility class for working with + /// HTTP Basic Authentication in HTTPRequest + /// objects. +{ +public: + HTTPBasicCredentials(); + /// Creates an empty HTTPBasicCredentials object. + + HTTPBasicCredentials(const std::string& username, const std::string& password); + /// Creates a HTTPBasicCredentials object with the given username and password. + + explicit HTTPBasicCredentials(const HTTPRequest& request); + /// Creates a HTTPBasicCredentials object with the authentication information + /// from the given request. + /// + /// Throws a NotAuthenticatedException if the request does + /// not contain basic authentication information. + + explicit HTTPBasicCredentials(const std::string& authInfo); + /// Creates a HTTPBasicCredentials object with the authentication information + /// in the given string. The authentication information can be extracted + /// from a HTTPRequest object by calling HTTPRequest::getCredentials(). + + ~HTTPBasicCredentials(); + /// Destroys the HTTPBasicCredentials. + + void clear(); + /// Clears both username and password. + + void setUsername(const std::string& username); + /// Sets the username. + + const std::string& getUsername() const; + /// Returns the username. + + void setPassword(const std::string& password); + /// Sets the password. + + const std::string& getPassword() const; + /// Returns the password. + + bool empty() const; + /// Returns true if both username and password are empty, otherwise false. + + void authenticate(HTTPRequest& request) const; + /// Adds authentication information to the given HTTPRequest. + + void proxyAuthenticate(HTTPRequest& request) const; + /// Adds proxy authentication information to the given HTTPRequest. + + static const std::string SCHEME; + +protected: + void parseAuthInfo(const std::string& authInfo); + /// Extracts username and password from Basic authentication info + /// by base64-decoding authInfo and splitting the resulting + /// string at the ':' delimiter. + +private: + HTTPBasicCredentials(const HTTPBasicCredentials&); + HTTPBasicCredentials& operator = (const HTTPBasicCredentials&); + + std::string _username; + std::string _password; +}; + + +// +// inlines +// +inline const std::string& HTTPBasicCredentials::getUsername() const +{ + return _username; +} + + +inline const std::string& HTTPBasicCredentials::getPassword() const +{ + return _password; +} + + +inline bool HTTPBasicCredentials::empty() const +{ + return _username.empty() && _password.empty(); +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPBasicCredentials_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPBasicStreamBuf.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPBasicStreamBuf.h new file mode 100644 index 0000000000..0edbec3298 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPBasicStreamBuf.h @@ -0,0 +1,36 @@ +// +// HTTPBasicStreamBuf.h +// +// Library: Net +// Package: HTTP +// Module: HTTPBasicStreamBuf +// +// Definition of the HTTPBasicStreamBuf class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPBasicStreamBuf_INCLUDED +#define Net_HTTPBasicStreamBuf_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/BufferedStreamBuf.h" +#include "Poco/Net/HTTPBufferAllocator.h" + + +namespace Poco { +namespace Net { + + +typedef Poco::BasicBufferedStreamBuf<char, std::char_traits<char>, HTTPBufferAllocator> HTTPBasicStreamBuf; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPBasicStreamBuf_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPBufferAllocator.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPBufferAllocator.h new file mode 100644 index 0000000000..ce2039aeaa --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPBufferAllocator.h @@ -0,0 +1,50 @@ +// +// HTTPBufferAllocator.h +// +// Library: Net +// Package: HTTP +// Module: HTTPBufferAllocator +// +// Definition of the HTTPBufferAllocator class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPBufferAllocator_INCLUDED +#define Net_HTTPBufferAllocator_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/MemoryPool.h" +#include <ios> + + +namespace Poco { +namespace Net { + + +class Net_API HTTPBufferAllocator + /// A BufferAllocator for HTTP streams. +{ +public: + static char* allocate(std::streamsize size); + static void deallocate(char* ptr, std::streamsize size); + + enum + { + BUFFER_SIZE = 4096 + }; + +private: + static Poco::MemoryPool _pool; +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPBufferAllocator_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPChunkedStream.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPChunkedStream.h new file mode 100644 index 0000000000..7e140ed586 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPChunkedStream.h @@ -0,0 +1,105 @@ +// +// HTTPChunkedStream.h +// +// Library: Net +// Package: HTTP +// Module: HTTPChunkedStream +// +// Definition of the HTTPChunkedStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPChunkedStream_INCLUDED +#define Net_HTTPChunkedStream_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPBasicStreamBuf.h" +#include "Poco/MemoryPool.h" +#include <cstddef> +#include <istream> +#include <ostream> + + +namespace Poco { +namespace Net { + + +class HTTPSession; + + +class Net_API HTTPChunkedStreamBuf: public HTTPBasicStreamBuf + /// This is the streambuf class used for reading and writing + /// HTTP message bodies in chunked transfer coding. +{ +public: + typedef HTTPBasicStreamBuf::openmode openmode; + + HTTPChunkedStreamBuf(HTTPSession& session, openmode mode); + ~HTTPChunkedStreamBuf(); + void close(); + +protected: + int readFromDevice(char* buffer, std::streamsize length); + int writeToDevice(const char* buffer, std::streamsize length); + +private: + HTTPSession& _session; + openmode _mode; + std::streamsize _chunk; + std::string _chunkBuffer; +}; + + +class Net_API HTTPChunkedIOS: public virtual std::ios + /// The base class for HTTPInputStream. +{ +public: + HTTPChunkedIOS(HTTPSession& session, HTTPChunkedStreamBuf::openmode mode); + ~HTTPChunkedIOS(); + HTTPChunkedStreamBuf* rdbuf(); + +protected: + HTTPChunkedStreamBuf _buf; +}; + + +class Net_API HTTPChunkedInputStream: public HTTPChunkedIOS, public std::istream + /// This class is for internal use by HTTPSession only. +{ +public: + HTTPChunkedInputStream(HTTPSession& session); + ~HTTPChunkedInputStream(); + + void* operator new(std::size_t size); + void operator delete(void* ptr); + +private: + static Poco::MemoryPool _pool; +}; + + +class Net_API HTTPChunkedOutputStream: public HTTPChunkedIOS, public std::ostream + /// This class is for internal use by HTTPSession only. +{ +public: + HTTPChunkedOutputStream(HTTPSession& session); + ~HTTPChunkedOutputStream(); + + void* operator new(std::size_t size); + void operator delete(void* ptr); + +private: + static Poco::MemoryPool _pool; +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPChunkedStream_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPClientSession.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPClientSession.h new file mode 100644 index 0000000000..2f2e21c599 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPClientSession.h @@ -0,0 +1,391 @@ +// +// HTTPClientSession.h +// +// Library: Net +// Package: HTTPClient +// Module: HTTPClientSession +// +// Definition of the HTTPClientSession class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPClientSession_INCLUDED +#define Net_HTTPClientSession_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPSession.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/SharedPtr.h" +#include <istream> +#include <ostream> + + +namespace Poco { +namespace Net { + + +class HTTPRequest; +class HTTPResponse; + + +class Net_API HTTPClientSession: public HTTPSession + /// This class implements the client-side of + /// a HTTP session. + /// + /// To send a HTTP request to a HTTP server, first + /// instantiate a HTTPClientSession object and + /// specify the server's host name and port number. + /// + /// Then create a HTTPRequest object, fill it accordingly, + /// and pass it as argument to the sendRequest() method. + /// + /// sendRequest() will return an output stream that can + /// be used to send the request body, if there is any. + /// + /// After you are done sending the request body, create + /// a HTTPResponse object and pass it to receiveResponse(). + /// + /// This will return an input stream that can be used to + /// read the response body. + /// + /// See RFC 2616 <http://www.faqs.org/rfcs/rfc2616.html> for more + /// information about the HTTP protocol. + /// + /// Proxies and proxy authorization (only HTTP Basic Authorization) + /// is supported. Use setProxy() and setProxyCredentials() to + /// set up a session through a proxy. +{ +public: + struct ProxyConfig + /// HTTP proxy server configuration. + { + ProxyConfig(): + port(HTTP_PORT) + { + } + + std::string host; + /// Proxy server host name or IP address. + Poco::UInt16 port; + /// Proxy server TCP port. + std::string username; + /// Proxy server username. + std::string password; + /// Proxy server password. + std::string nonProxyHosts; + /// A regular expression defining hosts for which the proxy should be bypassed, + /// e.g. "localhost|127\.0\.0\.1|192\.168\.0\.\d+". Can also be an empty + /// string to disable proxy bypassing. + }; + + HTTPClientSession(); + /// Creates an unconnected HTTPClientSession. + + explicit HTTPClientSession(const StreamSocket& socket); + /// Creates a HTTPClientSession using the given socket. + /// The socket must not be connected. The session + /// takes ownership of the socket. + + explicit HTTPClientSession(const SocketAddress& address); + /// Creates a HTTPClientSession using the given address. + + HTTPClientSession(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT); + /// Creates a HTTPClientSession using the given host and port. + + HTTPClientSession(const std::string& host, Poco::UInt16 port, const ProxyConfig& proxyConfig); + /// Creates a HTTPClientSession using the given host, port and proxy configuration. + + virtual ~HTTPClientSession(); + /// Destroys the HTTPClientSession and closes + /// the underlying socket. + + void setHost(const std::string& host); + /// Sets the host name of the target HTTP server. + /// + /// The host must not be changed once there is an + /// open connection to the server. + + const std::string& getHost() const; + /// Returns the host name of the target HTTP server. + + void setPort(Poco::UInt16 port); + /// Sets the port number of the target HTTP server. + /// + /// The port number must not be changed once there is an + /// open connection to the server. + + Poco::UInt16 getPort() const; + /// Returns the port number of the target HTTP server. + + void setProxy(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT); + /// Sets the proxy host name and port number. + + void setProxyHost(const std::string& host); + /// Sets the host name of the proxy server. + + void setProxyPort(Poco::UInt16 port); + /// Sets the port number of the proxy server. + + const std::string& getProxyHost() const; + /// Returns the proxy host name. + + Poco::UInt16 getProxyPort() const; + /// Returns the proxy port number. + + void setProxyCredentials(const std::string& username, const std::string& password); + /// Sets the username and password for proxy authentication. + /// Only Basic authentication is supported. + + void setProxyUsername(const std::string& username); + /// Sets the username for proxy authentication. + /// Only Basic authentication is supported. + + const std::string& getProxyUsername() const; + /// Returns the username for proxy authentication. + + void setProxyPassword(const std::string& password); + /// Sets the password for proxy authentication. + /// Only Basic authentication is supported. + + const std::string& getProxyPassword() const; + /// Returns the password for proxy authentication. + + void setProxyConfig(const ProxyConfig& config); + /// Sets the proxy configuration. + + const ProxyConfig& getProxyConfig() const; + /// Returns the proxy configuration. + + static void setGlobalProxyConfig(const ProxyConfig& config); + /// Sets the global proxy configuration. + /// + /// The global proxy configuration is used by all HTTPClientSession + /// instances, unless a different proxy configuration is explicitly set. + /// + /// Warning: Setting the global proxy configuration is not thread safe. + /// The global proxy configuration should be set at start up, before + /// the first HTTPClientSession instance is created. + + static const ProxyConfig& getGlobalProxyConfig(); + /// Returns the global proxy configuration. + + void setKeepAliveTimeout(const Poco::Timespan& timeout); + /// Sets the connection timeout for HTTP connections. + + const Poco::Timespan& getKeepAliveTimeout() const; + /// Returns the connection timeout for HTTP connections. + + virtual std::ostream& sendRequest(HTTPRequest& request); + /// Sends the header for the given HTTP request to + /// the server. + /// + /// The HTTPClientSession will set the request's + /// Host and Keep-Alive headers accordingly. + /// + /// The returned output stream can be used to write + /// the request body. The stream is valid until + /// receiveResponse() is called or the session + /// is destroyed. + /// + /// In case a network or server failure happens + /// while writing the request body to the returned stream, + /// the stream state will change to bad or fail. In this + /// case, reset() should be called if the session will + /// be reused and persistent connections are enabled + /// to ensure a new connection will be set up + /// for the next request. + + virtual std::istream& receiveResponse(HTTPResponse& response); + /// Receives the header for the response to the previous + /// HTTP request. + /// + /// The returned input stream can be used to read + /// the response body. The stream is valid until + /// sendRequest() is called or the session is + /// destroyed. + /// + /// It must be ensured that the response stream + /// is fully consumed before sending a new request + /// and persistent connections are enabled. Otherwise, + /// the unread part of the response body may be treated as + /// part of the next request's response header, resulting + /// in a Poco::Net::MessageException being thrown. + /// + /// In case a network or server failure happens + /// while reading the response body from the returned stream, + /// the stream state will change to bad or fail. In this + /// case, reset() should be called if the session will + /// be reused and persistent connections are enabled + /// to ensure a new connection will be set up + /// for the next request. + + virtual bool peekResponse(HTTPResponse& response); + /// If the request contains a "Expect: 100-continue" header, + /// (see HTTPRequest::setExpectContinue()) this method can be + /// used to check whether the server has sent a 100 Continue response + /// before continuing with the request, i.e. sending the request body, + /// after calling sendRequest(). + /// + /// Returns true if the server has responded with 100 Continue, + /// otherwise false. The HTTPResponse object contains the + /// response sent by the server. + /// + /// In any case, receiveResponse() must be called afterwards as well in + /// order to complete the request. The same HTTPResponse object + /// passed to peekResponse() must also be passed to receiveResponse(). + /// + /// This method should only be called if the request contains + /// a "Expect: 100-continue" header. + + void flushRequest(); + /// Flushes the request stream. + /// + /// Normally this method does not need to be called. + /// It can be used to ensure the request has been + /// fully sent if receiveResponse() is not called, e.g., + /// because the underlying socket will be detached. + + void reset(); + /// Resets the session and closes the socket. + /// + /// The next request will initiate a new connection, + /// even if persistent connections are enabled. + /// + /// This should be called whenever something went + /// wrong when sending a request (e.g., sendRequest() + /// or receiveResponse() throws an exception, or + /// the request or response stream changes into + /// fail or bad state, but not eof state). + + virtual bool secure() const; + /// Return true iff the session uses SSL or TLS, + /// or false otherwise. + + bool bypassProxy() const; + /// Returns true if the proxy should be bypassed + /// for the current host. + +protected: + enum + { + DEFAULT_KEEP_ALIVE_TIMEOUT = 8 + }; + + void reconnect(); + /// Connects the underlying socket to the HTTP server. + + int write(const char* buffer, std::streamsize length); + /// Tries to re-connect if keep-alive is on. + + virtual std::string proxyRequestPrefix() const; + /// Returns the prefix prepended to the URI for proxy requests + /// (e.g., "http://myhost.com"). + + virtual bool mustReconnect() const; + /// Checks if we can reuse a persistent connection. + + virtual void proxyAuthenticate(HTTPRequest& request); + /// Sets the proxy credentials (Proxy-Authorization header), if + /// proxy username and password have been set. + + void proxyAuthenticateImpl(HTTPRequest& request); + /// Sets the proxy credentials (Proxy-Authorization header), if + /// proxy username and password have been set. + + StreamSocket proxyConnect(); + /// Sends a CONNECT request to the proxy server and returns + /// a StreamSocket for the resulting connection. + + void proxyTunnel(); + /// Calls proxyConnect() and attaches the resulting StreamSocket + /// to the HTTPClientSession. + +private: + std::string _host; + Poco::UInt16 _port; + ProxyConfig _proxyConfig; + Poco::Timespan _keepAliveTimeout; + Poco::Timestamp _lastRequest; + bool _reconnect; + bool _mustReconnect; + bool _expectResponseBody; + bool _responseReceived; + Poco::SharedPtr<std::ostream> _pRequestStream; + Poco::SharedPtr<std::istream> _pResponseStream; + + static ProxyConfig _globalProxyConfig; + + HTTPClientSession(const HTTPClientSession&); + HTTPClientSession& operator = (const HTTPClientSession&); + + friend class WebSocket; +}; + + +// +// inlines +// +inline const std::string& HTTPClientSession::getHost() const +{ + return _host; +} + + +inline Poco::UInt16 HTTPClientSession::getPort() const +{ + return _port; +} + + +inline const std::string& HTTPClientSession::getProxyHost() const +{ + return _proxyConfig.host; +} + + +inline Poco::UInt16 HTTPClientSession::getProxyPort() const +{ + return _proxyConfig.port; +} + + +inline const std::string& HTTPClientSession::getProxyUsername() const +{ + return _proxyConfig.username; +} + + +inline const std::string& HTTPClientSession::getProxyPassword() const +{ + return _proxyConfig.password; +} + + +inline const HTTPClientSession::ProxyConfig& HTTPClientSession::getProxyConfig() const +{ + return _proxyConfig; +} + + +inline const HTTPClientSession::ProxyConfig& HTTPClientSession::getGlobalProxyConfig() +{ + return _globalProxyConfig; +} + + +inline const Poco::Timespan& HTTPClientSession::getKeepAliveTimeout() const +{ + return _keepAliveTimeout; +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPClientSession_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPCookie.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPCookie.h new file mode 100644 index 0000000000..c7c47b2e0a --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPCookie.h @@ -0,0 +1,272 @@ +// +// HTTPCookie.h +// +// Library: Net +// Package: HTTP +// Module: HTTPCookie +// +// Definition of the HTTPCookie class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPCookie_INCLUDED +#define Net_HTTPCookie_INCLUDED + + +#include "Poco/Net/Net.h" + + +namespace Poco { +namespace Net { + + +class NameValueCollection; + + +class Net_API HTTPCookie + /// This class represents a HTTP Cookie. + /// + /// A cookie is a small amount of information sent by a Web + /// server to a Web browser, saved by the browser, and later sent back + /// to the server. A cookie's value can uniquely identify a client, so + /// cookies are commonly used for session management. + /// + /// A cookie has a name, a single value, and optional attributes such + /// as a comment, path and domain qualifiers, a maximum age, and a + /// version number. + /// + /// This class supports both the Version 0 (by Netscape) and Version 1 + /// (by RFC 2109) cookie specifications. By default, cookies are created + /// using Version 0 to ensure the best interoperability. +{ +public: + HTTPCookie(); + /// Creates an empty HTTPCookie. + + explicit HTTPCookie(const std::string& name); + /// Creates a cookie with the given name. + /// The cookie never expires. + + explicit HTTPCookie(const NameValueCollection& nvc); + /// Creates a cookie from the given NameValueCollection. + + HTTPCookie(const std::string& name, const std::string& value); + /// Creates a cookie with the given name and value. + /// The cookie never expires. + /// + /// Note: If value contains whitespace or non-alphanumeric + /// characters, the value should be escaped by calling escape() + /// before passing it to the constructor. + + HTTPCookie(const HTTPCookie& cookie); + /// Creates the HTTPCookie by copying another one. + + ~HTTPCookie(); + /// Destroys the HTTPCookie. + + HTTPCookie& operator = (const HTTPCookie& cookie); + /// Assigns a cookie. + + void setVersion(int version); + /// Sets the version of the cookie. + /// + /// Version must be either 0 (denoting a Netscape cookie) + /// or 1 (denoting a RFC 2109 cookie). + + int getVersion() const; + /// Returns the version of the cookie, which is + /// either 0 or 1. + + void setName(const std::string& name); + /// Sets the name of the cookie. + + const std::string& getName() const; + /// Returns the name of the cookie. + + void setValue(const std::string& value); + /// Sets the value of the cookie. + /// + /// According to the cookie specification, the + /// size of the value should not exceed 4 Kbytes. + /// + /// Note: If value contains whitespace or non-alphanumeric + /// characters, the value should be escaped by calling escape() + /// prior to passing it to setName(). + + const std::string& getValue() const; + /// Returns the value of the cookie. + + void setComment(const std::string& comment); + /// Sets the comment for the cookie. + /// + /// Comments are only supported for version 1 cookies. + + const std::string& getComment() const; + /// Returns the comment for the cookie. + + void setDomain(const std::string& domain); + /// Sets the domain for the cookie. + + const std::string& getDomain() const; + /// Returns the domain for the cookie. + + void setPath(const std::string& path); + /// Sets the path for the cookie. + + void setPriority(const std::string& priority); + /// Sets the priority for the cookie. + + const std::string& getPath() const; + /// Returns the path for the cookie. + + const std::string& getPriority() const; + /// Returns the priority for the cookie. + + void setSecure(bool secure); + /// Sets the value of the secure flag for + /// the cookie. + + bool getSecure() const; + /// Returns the value of the secure flag + /// for the cookie. + + void setMaxAge(int maxAge); + /// Sets the maximum age in seconds for + /// the cookie. + /// + /// A value of -1 (default) causes the cookie + /// to become a session cookie, which will + /// be deleted when the browser window + /// is closed. + /// + /// A value of 0 deletes the cookie on + /// the client. + + int getMaxAge() const; + /// Returns the maximum age in seconds for + /// the cookie. + + void setHttpOnly(bool flag = true); + /// Sets the HttpOnly flag for the cookie. + + bool getHttpOnly() const; + /// Returns true iff the cookie's HttpOnly flag is set. + + std::string toString() const; + /// Returns a string representation of the cookie, + /// suitable for use in a Set-Cookie header. + + static std::string escape(const std::string& str); + /// Escapes the given string by replacing all + /// non-alphanumeric characters with escape + /// sequences in the form %xx, where xx is the + /// hexadecimal character code. + /// + /// The following characters will be replaced + /// with escape sequences: + /// - percent sign % + /// - less-than and greater-than < and > + /// - curly brackets { and } + /// - square brackets [ and ] + /// - parenthesis ( and ) + /// - solidus / + /// - vertical line | + /// - reverse solidus (backslash /) + /// - quotation mark " + /// - apostrophe ' + /// - circumflex accent ^ + /// - grave accent ` + /// - comma and semicolon , and ; + /// - whitespace and control characters + + static std::string unescape(const std::string& str); + /// Unescapes the given string by replacing all + /// escape sequences in the form %xx with the + /// respective characters. + +private: + int _version; + std::string _name; + std::string _value; + std::string _comment; + std::string _domain; + std::string _path; + std::string _priority; + bool _secure; + int _maxAge; + bool _httpOnly; +}; + + +// +// inlines +// +inline int HTTPCookie::getVersion() const +{ + return _version; +} + + +inline const std::string& HTTPCookie::getName() const +{ + return _name; +} + + +inline const std::string& HTTPCookie::getValue() const +{ + return _value; +} + + +inline const std::string& HTTPCookie::getComment() const +{ + return _comment; +} + + +inline const std::string& HTTPCookie::getDomain() const +{ + return _domain; +} + + +inline const std::string& HTTPCookie::getPath() const +{ + return _path; +} + + +inline const std::string& HTTPCookie::getPriority() const +{ + return _priority; +} + + +inline bool HTTPCookie::getSecure() const +{ + return _secure; +} + + +inline int HTTPCookie::getMaxAge() const +{ + return _maxAge; +} + + +inline bool HTTPCookie::getHttpOnly() const +{ + return _httpOnly; +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPCookie_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPCredentials.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPCredentials.h new file mode 100644 index 0000000000..e62b8c2467 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPCredentials.h @@ -0,0 +1,206 @@ +// +// HTTPCredentials.h +// +// Library: Net +// Package: HTTP +// Module: HTTPCredentials +// +// Definition of the HTTPCredentials class. +// +// 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 +// + + +#ifndef Net_HTTPCredentials_INCLUDED +#define Net_HTTPCredentials_INCLUDED + + +#include "Poco/Net/HTTPDigestCredentials.h" + + +namespace Poco { + + +class URI; + + +namespace Net { + + +class HTTPRequest; +class HTTPResponse; + + +class Net_API HTTPCredentials + /// This is a utility class for working with HTTP + /// authentication (Basic or Digest) in HTTPRequest objects. + /// + /// Usage is as follows: + /// First, create a HTTPCredentials object containing + /// the username and password. + /// Poco::Net::HTTPCredentials creds("user", "s3cr3t"); + /// + /// Second, send the HTTP request with Poco::Net::HTTPClientSession. + /// Poco::Net::HTTPClientSession session("pocoproject.org"); + /// Poco::Net::HTTPRequest request(HTTPRequest::HTTP_GET, "/index.html", HTTPMessage::HTTP_1_1); + /// session.sendRequest(request); + /// Poco::Net::HTTPResponse; + /// std::istream& istr = session.receiveResponse(response); + /// + /// If the server responds with a 401 status, authenticate the + /// request and resend it: + /// if (response.getStatus() == Poco::Net::HTTPResponse::HTTP_UNAUTHORIZED) + /// { + /// creds.authenticate(request, response); + /// session.sendRequest(request); + /// ... + /// } + /// + /// To perform multiple authenticated requests, call updateAuthInfo() + /// instead of authenticate() on subsequent requests. + /// creds.updateAuthInfo(request); + /// session.sendRequest(request); + /// ... + /// + /// Note: Do not forget to read the entire response stream from the 401 response + /// before sending the authenticated request, otherwise there may be + /// problems if a persistent connection is used. +{ +public: + HTTPCredentials(); + /// Creates an empty HTTPCredentials object. + + HTTPCredentials(const std::string& username, const std::string& password); + /// Creates an HTTPCredentials object with the given username and password. + + ~HTTPCredentials(); + /// Destroys the HTTPCredentials. + + void fromUserInfo(const std::string& userInfo); + /// Parses username:password string and sets username and password of + /// the credentials object. + /// Throws SyntaxException on invalid user information. + + void fromURI(const URI& uri); + /// Extracts username and password from the given URI and sets username + /// and password of the credentials object. + /// Does nothing if URI has no user info part. + + void clear(); + /// Clears username, password and host. + + void setUsername(const std::string& username); + /// Sets the username. + + const std::string& getUsername() const; + /// Returns the username. + + void setPassword(const std::string& password); + /// Sets the password. + + const std::string& getPassword() const; + /// Returns the password. + + bool empty() const; + /// Returns true if both username and password are empty, otherwise false. + + void authenticate(HTTPRequest& request, const HTTPResponse& response); + /// Inspects WWW-Authenticate header of the response, initializes + /// the internal state (in case of digest authentication) and + /// adds required information to the given HTTPRequest. + /// + /// Does nothing if there is no WWW-Authenticate header in the + /// HTTPResponse. + + void updateAuthInfo(HTTPRequest& request); + /// Updates internal state (in case of digest authentication) and + /// replaces authentication information in the request accordingly. + + void proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response); + /// Inspects Proxy-Authenticate header of the response, initializes + /// the internal state (in case of digest authentication) and + /// adds required information to the given HTTPRequest. + /// + /// Does nothing if there is no Proxy-Authenticate header in the + /// HTTPResponse. + + void updateProxyAuthInfo(HTTPRequest& request); + /// Updates internal state (in case of digest authentication) and + /// replaces proxy authentication information in the request accordingly. + + static bool isBasicCredentials(const std::string& header); + /// Returns true if authentication header is for Basic authentication. + + static bool isDigestCredentials(const std::string& header); + /// Returns true if authentication header is for Digest authentication. + + static bool hasBasicCredentials(const HTTPRequest& request); + /// Returns true if an Authorization header with Basic credentials is present in the request. + + static bool hasDigestCredentials(const HTTPRequest& request); + /// Returns true if an Authorization header with Digest credentials is present in the request. + + static bool hasNTLMCredentials(const HTTPRequest& request); + /// Returns true if an Authorization header with NTLM credentials is present in the request. + + static bool hasProxyBasicCredentials(const HTTPRequest& request); + /// Returns true if a Proxy-Authorization header with Basic credentials is present in the request. + + static bool hasProxyDigestCredentials(const HTTPRequest& request); + /// Returns true if a Proxy-Authorization header with Digest credentials is present in the request. + + static void extractCredentials(const std::string& userInfo, std::string& username, std::string& password); + /// Extracts username and password from user:password information string. + + static void extractCredentials(const Poco::URI& uri, std::string& username, std::string& password); + /// Extracts username and password from the given URI (e.g.: "http://user:pass@sample.com/secret"). + +private: + HTTPCredentials(const HTTPCredentials&); + HTTPCredentials& operator = (const HTTPCredentials&); + + HTTPDigestCredentials _digest; +}; + + +// +// inlines +// +inline void HTTPCredentials::setUsername(const std::string& username) +{ + _digest.setUsername(username); +} + + +inline const std::string& HTTPCredentials::getUsername() const +{ + return _digest.getUsername(); +} + + +inline void HTTPCredentials::setPassword(const std::string& password) +{ + _digest.setPassword(password); +} + + +inline const std::string& HTTPCredentials::getPassword() const +{ + return _digest.getPassword(); +} + + +inline bool HTTPCredentials::empty() const +{ + return _digest.empty(); +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPCredentials_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPDigestCredentials.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPDigestCredentials.h new file mode 100644 index 0000000000..c321c9fc87 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPDigestCredentials.h @@ -0,0 +1,186 @@ +// +// HTTPDigestCredentials.h +// +// Library: Net +// Package: HTTP +// Module: HTTPDigestCredentials +// +// Definition of the HTTPDigestCredentials class. +// +// 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 +// + + +#ifndef Net_HTTPDigestCredentials_INCLUDED +#define Net_HTTPDigestCredentials_INCLUDED + + +#include "Poco/Net/HTTPAuthenticationParams.h" +#include "Poco/Mutex.h" +#include <map> + + +namespace Poco { +namespace Net { + + +class HTTPRequest; +class HTTPResponse; + + +class Net_API HTTPDigestCredentials + /// This is a utility class for working with + /// HTTP Digest Authentication in HTTPRequest + /// objects. + /// + /// Note: currently, no qop or qop=auth is + /// supported only. +{ +public: + HTTPDigestCredentials(); + /// Creates an empty HTTPDigestCredentials object. + + HTTPDigestCredentials(const std::string& username, const std::string& password); + /// Creates a HTTPDigestCredentials object with the given username and password. + + ~HTTPDigestCredentials(); + /// Destroys the HTTPDigestCredentials. + + void reset(); + /// Resets the HTTPDigestCredentials object to a clean state. + /// Does not clear username and password. + + void clear(); + /// Clears both username and password. + + void setUsername(const std::string& username); + /// Sets the username. + + const std::string& getUsername() const; + /// Returns the username. + + void setPassword(const std::string& password); + /// Sets the password. + + const std::string& getPassword() const; + /// Returns the password. + + bool empty() const; + /// Returns true if both username and password are empty, otherwise false. + + void authenticate(HTTPRequest& request, const HTTPResponse& response); + /// Parses WWW-Authenticate header of the HTTPResponse, initializes + /// internal state, and adds authentication information to the given HTTPRequest. + + void authenticate(HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams); + /// Initializes internal state according to information from the + /// HTTPAuthenticationParams of the response, and adds authentication + /// information to the given HTTPRequest. + /// + /// Throws InvalidArgumentException if HTTPAuthenticationParams is + /// invalid or some required parameter is missing. + /// Throws NotImplementedException in case of unsupported digest + /// algorithm or quality of protection method. + + void updateAuthInfo(HTTPRequest& request); + /// Updates internal state and adds authentication information to + /// the given HTTPRequest. + + void proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response); + /// Parses Proxy-Authenticate header of the HTTPResponse, initializes + /// internal state, and adds proxy authentication information to the given HTTPRequest. + + void proxyAuthenticate(HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams); + /// Initializes internal state according to information from the + /// HTTPAuthenticationParams of the response, and adds proxy authentication + /// information to the given HTTPRequest. + /// + /// Throws InvalidArgumentException if HTTPAuthenticationParams is + /// invalid or some required parameter is missing. + /// Throws NotImplementedException in case of unsupported digest + /// algorithm or quality of protection method. + + void updateProxyAuthInfo(HTTPRequest& request); + /// Updates internal state and adds proxy authentication information to + /// the given HTTPRequest. + + bool verifyAuthInfo(const HTTPRequest& request) const; + /// Verifies the digest authentication information in the given HTTPRequest + /// by recomputing the response and comparing it with what's in the request. + /// + /// Note: This method creates a HTTPAuthenticationParams object from the request + /// and calls verifyAuthParams() with request and params. + + bool verifyAuthParams(const HTTPRequest& request, const HTTPAuthenticationParams& params) const; + /// Verifies the digest authentication information in the given HTTPRequest + /// and HTTPAuthenticationParams by recomputing the response and comparing + /// it with what's in the request. + + static std::string createNonce(); + /// Creates a random nonce string. + + static const std::string SCHEME; + +private: + HTTPDigestCredentials(const HTTPDigestCredentials&); + HTTPDigestCredentials& operator = (const HTTPDigestCredentials&); + + void createAuthParams(const HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams); + void updateAuthParams(const HTTPRequest& request); + int updateNonceCounter(const std::string& nonce); + + static const std::string DEFAULT_ALGORITHM; + static const std::string DEFAULT_QOP; + static const std::string NONCE_PARAM; + static const std::string REALM_PARAM; + static const std::string QOP_PARAM; + static const std::string ALGORITHM_PARAM; + static const std::string USERNAME_PARAM; + static const std::string OPAQUE_PARAM; + static const std::string URI_PARAM; + static const std::string RESPONSE_PARAM; + static const std::string AUTH_PARAM; + static const std::string CNONCE_PARAM; + static const std::string NC_PARAM; + + typedef std::map<std::string, int> NonceCounterMap; + + std::string _username; + std::string _password; + HTTPAuthenticationParams _requestAuthParams; + NonceCounterMap _nc; + + static int _nonceCounter; + static Poco::FastMutex _nonceMutex; +}; + + +// +// inlines +// +inline const std::string& HTTPDigestCredentials::getUsername() const +{ + return _username; +} + + +inline const std::string& HTTPDigestCredentials::getPassword() const +{ + return _password; +} + + +inline bool HTTPDigestCredentials::empty() const +{ + return _username.empty() && _password.empty(); +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPDigestCredentials_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPFixedLengthStream.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPFixedLengthStream.h new file mode 100644 index 0000000000..ad781e4e00 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPFixedLengthStream.h @@ -0,0 +1,110 @@ +// +// HTTPFixedLengthStream.h +// +// Library: Net +// Package: HTTP +// Module: HTTPFixedLengthStream +// +// Definition of the HTTPFixedLengthStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPFixedLengthStream_INCLUDED +#define Net_HTTPFixedLengthStream_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPBasicStreamBuf.h" +#include <cstddef> +#include <istream> +#include <ostream> + + +namespace Poco { +namespace Net { + + +class HTTPSession; + + +class Net_API HTTPFixedLengthStreamBuf: public HTTPBasicStreamBuf + /// This is the streambuf class used for reading and writing fixed-size + /// HTTP message bodies. + /// + /// At most a given number of bytes are read or written. +{ +public: + typedef HTTPBasicStreamBuf::openmode openmode; + +#if defined(POCO_HAVE_INT64) + typedef Poco::Int64 ContentLength; +#else + typedef std::streamsize ContentLength; +#endif + + HTTPFixedLengthStreamBuf(HTTPSession& session, ContentLength length, openmode mode); + ~HTTPFixedLengthStreamBuf(); + +protected: + int readFromDevice(char* buffer, std::streamsize length); + int writeToDevice(const char* buffer, std::streamsize length); + +private: + HTTPSession& _session; + ContentLength _length; + ContentLength _count; +}; + + +class Net_API HTTPFixedLengthIOS: public virtual std::ios + /// The base class for HTTPFixedLengthInputStream. +{ +public: + HTTPFixedLengthIOS(HTTPSession& session, HTTPFixedLengthStreamBuf::ContentLength length, HTTPFixedLengthStreamBuf::openmode mode); + ~HTTPFixedLengthIOS(); + HTTPFixedLengthStreamBuf* rdbuf(); + +protected: + HTTPFixedLengthStreamBuf _buf; +}; + + +class Net_API HTTPFixedLengthInputStream: public HTTPFixedLengthIOS, public std::istream + /// This class is for internal use by HTTPSession only. +{ +public: + HTTPFixedLengthInputStream(HTTPSession& session, HTTPFixedLengthStreamBuf::ContentLength length); + ~HTTPFixedLengthInputStream(); + + void* operator new(std::size_t size); + void operator delete(void* ptr); + +private: + static Poco::MemoryPool _pool; +}; + + +class Net_API HTTPFixedLengthOutputStream: public HTTPFixedLengthIOS, public std::ostream + /// This class is for internal use by HTTPSession only. +{ +public: + HTTPFixedLengthOutputStream(HTTPSession& session, HTTPFixedLengthStreamBuf::ContentLength length); + ~HTTPFixedLengthOutputStream(); + + void* operator new(std::size_t size); + void operator delete(void* ptr); + +private: + static Poco::MemoryPool _pool; +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPFixedLengthStream_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPHeaderStream.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPHeaderStream.h new file mode 100644 index 0000000000..f3f4c891b6 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPHeaderStream.h @@ -0,0 +1,103 @@ +// +// HTTPHeaderStream.h +// +// Library: Net +// Package: HTTP +// Module: HTTPHeaderStream +// +// Definition of the HTTPHeaderStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPHeaderStream_INCLUDED +#define Net_HTTPHeaderStream_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPBasicStreamBuf.h" +#include "Poco/MemoryPool.h" +#include <cstddef> +#include <istream> +#include <ostream> + + +namespace Poco { +namespace Net { + + +class HTTPSession; + + +class Net_API HTTPHeaderStreamBuf: public HTTPBasicStreamBuf + /// This is the streambuf class used for reading from a HTTP header + /// in a HTTPSession. +{ +public: + typedef HTTPBasicStreamBuf::openmode openmode; + + HTTPHeaderStreamBuf(HTTPSession& session, openmode mode); + ~HTTPHeaderStreamBuf(); + +protected: + int readFromDevice(char* buffer, std::streamsize length); + int writeToDevice(const char* buffer, std::streamsize length); + +private: + HTTPSession& _session; + bool _end; + bool _line_ended; +}; + + +class Net_API HTTPHeaderIOS: public virtual std::ios + /// The base class for HTTPHeaderInputStream. +{ +public: + HTTPHeaderIOS(HTTPSession& session, HTTPHeaderStreamBuf::openmode mode); + ~HTTPHeaderIOS(); + HTTPHeaderStreamBuf* rdbuf(); + +protected: + HTTPHeaderStreamBuf _buf; +}; + + +class Net_API HTTPHeaderInputStream: public HTTPHeaderIOS, public std::istream + /// This class is for internal use by HTTPSession only. +{ +public: + HTTPHeaderInputStream(HTTPSession& session); + ~HTTPHeaderInputStream(); + + void* operator new(std::size_t size); + void operator delete(void* ptr); + +private: + static Poco::MemoryPool _pool; +}; + + +class Net_API HTTPHeaderOutputStream: public HTTPHeaderIOS, public std::ostream + /// This class is for internal use by HTTPSession only. +{ +public: + HTTPHeaderOutputStream(HTTPSession& session); + ~HTTPHeaderOutputStream(); + + void* operator new(std::size_t size); + void operator delete(void* ptr); + +private: + static Poco::MemoryPool _pool; +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPHeaderStream_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPIOStream.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPIOStream.h new file mode 100644 index 0000000000..2c45812ae1 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPIOStream.h @@ -0,0 +1,88 @@ +// +// HTTPIOStream.h +// +// Library: Net +// Package: HTTP +// Module: HTTPIOStream +// +// Definition of the HTTPIOStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPIOStream_INCLUDED +#define Net_HTTPIOStream_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPResponse.h" +#include "Poco/UnbufferedStreamBuf.h" + + +namespace Poco { +namespace Net { + + +class HTTPClientSession; + + +class Net_API HTTPResponseStreamBuf: public Poco::UnbufferedStreamBuf +{ +public: + HTTPResponseStreamBuf(std::istream& istr); + + ~HTTPResponseStreamBuf(); + +private: + int readFromDevice(); + + std::istream& _istr; +}; + + +inline int HTTPResponseStreamBuf::readFromDevice() +{ + return _istr.get(); +} + + +class Net_API HTTPResponseIOS: public virtual std::ios +{ +public: + HTTPResponseIOS(std::istream& istr); + + ~HTTPResponseIOS(); + + HTTPResponseStreamBuf* rdbuf(); + +protected: + HTTPResponseStreamBuf _buf; +}; + + +inline HTTPResponseStreamBuf* HTTPResponseIOS::rdbuf() +{ + return &_buf; +} + + +class Net_API HTTPResponseStream: public HTTPResponseIOS, public std::istream +{ +public: + HTTPResponseStream(std::istream& istr, HTTPClientSession* pSession); + + ~HTTPResponseStream(); + +private: + HTTPClientSession* _pSession; +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPIOStream_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPMessage.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPMessage.h new file mode 100644 index 0000000000..345543d5a1 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPMessage.h @@ -0,0 +1,185 @@ +// +// HTTPMessage.h +// +// Library: Net +// Package: HTTP +// Module: HTTPMessage +// +// Definition of the HTTPMessage class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPMessage_INCLUDED +#define Net_HTTPMessage_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/MessageHeader.h" + + +namespace Poco { +namespace Net { + + +class MediaType; + + +class Net_API HTTPMessage: public MessageHeader + /// The base class for HTTPRequest and HTTPResponse. + /// + /// Defines the common properties of all HTTP messages. + /// These are version, content length, content type + /// and transfer encoding. +{ +public: + void setVersion(const std::string& version); + /// Sets the HTTP version for this message. + + const std::string& getVersion() const; + /// Returns the HTTP version for this message. + + void setContentLength(std::streamsize length); + /// Sets the Content-Length header. + /// + /// If length is UNKNOWN_CONTENT_LENGTH, removes + /// the Content-Length header. + + std::streamsize getContentLength() const; + /// Returns the content length for this message, + /// which may be UNKNOWN_CONTENT_LENGTH if + /// no Content-Length header is present. + +#if defined(POCO_HAVE_INT64) + void setContentLength64(Poco::Int64 length); + /// Sets the Content-Length header. + /// + /// If length is UNKNOWN_CONTENT_LENGTH, removes + /// the Content-Length header. + /// + /// In contrast to setContentLength(), this method takes + /// a 64-bit integer as content length. + + Poco::Int64 getContentLength64() const; + /// Returns the content length for this message, + /// which may be UNKNOWN_CONTENT_LENGTH if + /// no Content-Length header is present. + /// + /// In contrast to getContentLength(), this method + /// always returns a 64-bit integer for content length. +#endif // defined(POCO_HAVE_INT64) + + bool hasContentLength() const; + /// Returns true iff a Content-Length header is present. + + void setTransferEncoding(const std::string& transferEncoding); + /// Sets the transfer encoding for this message. + /// + /// The value should be either IDENTITY_TRANSFER_CODING + /// or CHUNKED_TRANSFER_CODING. + + const std::string& getTransferEncoding() const; + /// Returns the transfer encoding used for this + /// message. + /// + /// Normally, this is the value of the Transfer-Encoding + /// header field. If no such field is present, + /// returns IDENTITY_TRANSFER_CODING. + + void setChunkedTransferEncoding(bool flag); + /// If flag is true, sets the Transfer-Encoding header to + /// chunked. Otherwise, removes the Transfer-Encoding + /// header. + + bool getChunkedTransferEncoding() const; + /// Returns true if the Transfer-Encoding header is set + /// and its value is chunked. + + void setContentType(const std::string& mediaType); + /// Sets the content type for this message. + /// + /// Specify NO_CONTENT_TYPE to remove the + /// Content-Type header. + + void setContentType(const MediaType& mediaType); + /// Sets the content type for this message. + + const std::string& getContentType() const; + /// Returns the content type for this message. + /// + /// If no Content-Type header is present, + /// returns UNKNOWN_CONTENT_TYPE. + + void setKeepAlive(bool keepAlive); + /// Sets the value of the Connection header field. + /// + /// The value is set to "Keep-Alive" if keepAlive is + /// true, or to "Close" otherwise. + + bool getKeepAlive() const; + /// Returns true if + /// * the message has a Connection header field and its value is "Keep-Alive" + /// * the message is a HTTP/1.1 message and not Connection header is set + /// Returns false otherwise. + + static const std::string HTTP_1_0; + static const std::string HTTP_1_1; + + static const std::string IDENTITY_TRANSFER_ENCODING; + static const std::string CHUNKED_TRANSFER_ENCODING; + + static const int UNKNOWN_CONTENT_LENGTH; + static const std::string UNKNOWN_CONTENT_TYPE; + + static const std::string CONTENT_LENGTH; + static const std::string CONTENT_TYPE; + static const std::string TRANSFER_ENCODING; + static const std::string CONNECTION; + + static const std::string CONNECTION_KEEP_ALIVE; + static const std::string CONNECTION_CLOSE; + + static const std::string EMPTY; + +protected: + HTTPMessage(); + /// Creates the HTTPMessage with version HTTP/1.0. + + HTTPMessage(const std::string& version); + /// Creates the HTTPMessage and sets + /// the version. + + virtual ~HTTPMessage(); + /// Destroys the HTTPMessage. + +private: + HTTPMessage(const HTTPMessage&); + HTTPMessage& operator = (const HTTPMessage&); + + std::string _version; +}; + + +// +// inlines +// +inline const std::string& HTTPMessage::getVersion() const +{ + return _version; +} + + +inline bool HTTPMessage::hasContentLength() const +{ + return has(CONTENT_LENGTH); +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPMessage_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPRequest.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPRequest.h new file mode 100644 index 0000000000..817a74dc46 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPRequest.h @@ -0,0 +1,200 @@ +// +// HTTPRequest.h +// +// Library: Net +// Package: HTTP +// Module: HTTPRequest +// +// Definition of the HTTPRequest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPRequest_INCLUDED +#define Net_HTTPRequest_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPMessage.h" + + +namespace Poco { +namespace Net { + + +class Net_API HTTPRequest: public HTTPMessage + /// This class encapsulates an HTTP request + /// message. + /// + /// In addition to the properties common to + /// all HTTP messages, a HTTP request has + /// a method (e.g. GET, HEAD, POST, etc.) and + /// a request URI. +{ +public: + HTTPRequest(); + /// Creates a GET / HTTP/1.0 HTTP request. + + HTTPRequest(const std::string& version); + /// Creates a GET / HTTP/1.x request with + /// the given version (HTTP/1.0 or HTTP/1.1). + + HTTPRequest(const std::string& method, const std::string& uri); + /// Creates a HTTP/1.0 request with the given method and URI. + + HTTPRequest(const std::string& method, const std::string& uri, const std::string& version); + /// Creates a HTTP request with the given method, URI and version. + + virtual ~HTTPRequest(); + /// Destroys the HTTPRequest. + + void setMethod(const std::string& method); + /// Sets the method. + + const std::string& getMethod() const; + /// Returns the method. + + void setURI(const std::string& uri); + /// Sets the request URI. + + const std::string& getURI() const; + /// Returns the request URI. + + void setHost(const std::string& host); + /// Sets the value of the Host header field. + + void setHost(const std::string& host, Poco::UInt16 port); + /// Sets the value of the Host header field. + /// + /// If the given port number is a non-standard + /// port number (other than 80 or 443), it is + /// included in the Host header field. + + const std::string& getHost() const; + /// Returns the value of the Host header field. + /// + /// Throws a NotFoundException if the request + /// does not have a Host header field. + + void setCookies(const NameValueCollection& cookies); + /// Adds a Cookie header with the names and + /// values from cookies. + + void getCookies(NameValueCollection& cookies) const; + /// Fills cookies with the cookies extracted + /// from the Cookie headers in the request. + + bool hasCredentials() const; + /// Returns true iff the request contains authentication + /// information in the form of an Authorization header. + + void getCredentials(std::string& scheme, std::string& authInfo) const; + /// Returns the authentication scheme and additional authentication + /// information contained in this request. + /// + /// Throws a NotAuthenticatedException if no authentication information + /// is contained in the request. + + void setCredentials(const std::string& scheme, const std::string& authInfo); + /// Sets the authentication scheme and information for + /// this request. + + bool getExpectContinue() const; + /// Returns true if the request contains an + /// "Expect: 100-continue" header. + + void setExpectContinue(bool expectContinue); + /// Adds a "Expect: 100-continue" header to the request if + /// expectContinue is true, otherwise removes the Expect header. + + bool hasProxyCredentials() const; + /// Returns true iff the request contains proxy authentication + /// information in the form of an Proxy-Authorization header. + + void getProxyCredentials(std::string& scheme, std::string& authInfo) const; + /// Returns the proxy authentication scheme and additional proxy authentication + /// information contained in this request. + /// + /// Throws a NotAuthenticatedException if no proxy authentication information + /// is contained in the request. + + void setProxyCredentials(const std::string& scheme, const std::string& authInfo); + /// Sets the proxy authentication scheme and information for + /// this request. + + void write(std::ostream& ostr) const; + /// Writes the HTTP request to the given + /// output stream. + + void read(std::istream& istr); + /// Reads the HTTP request from the + /// given input stream. + + static const std::string HTTP_GET; + static const std::string HTTP_HEAD; + static const std::string HTTP_PUT; + static const std::string HTTP_POST; + static const std::string HTTP_OPTIONS; + static const std::string HTTP_DELETE; + static const std::string HTTP_TRACE; + static const std::string HTTP_CONNECT; + static const std::string HTTP_PATCH; + + static const std::string HOST; + static const std::string COOKIE; + static const std::string AUTHORIZATION; + static const std::string PROXY_AUTHORIZATION; + static const std::string UPGRADE; + static const std::string EXPECT; + +protected: + void getCredentials(const std::string& header, std::string& scheme, std::string& authInfo) const; + /// Returns the authentication scheme and additional authentication + /// information contained in the given header of request. + /// + /// Throws a NotAuthenticatedException if no authentication information + /// is contained in the request. + + void setCredentials(const std::string& header, const std::string& scheme, const std::string& authInfo); + /// Writes the authentication scheme and information for + /// this request to the given header. + +private: + enum Limits + { + MAX_METHOD_LENGTH = 32, + MAX_URI_LENGTH = 16384, + MAX_VERSION_LENGTH = 8 + }; + + std::string _method; + std::string _uri; + + HTTPRequest(const HTTPRequest&); + HTTPRequest& operator = (const HTTPRequest&); +}; + + +// +// inlines +// +inline const std::string& HTTPRequest::getMethod() const +{ + return _method; +} + + +inline const std::string& HTTPRequest::getURI() const +{ + return _uri; +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPRequest_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPRequestHandler.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPRequestHandler.h new file mode 100644 index 0000000000..8a6271204c --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPRequestHandler.h @@ -0,0 +1,67 @@ +// +// HTTPRequestHandler.h +// +// Library: Net +// Package: HTTPServer +// Module: HTTPRequestHandler +// +// Definition of the HTTPRequestHandler class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPRequestHandler_INCLUDED +#define Net_HTTPRequestHandler_INCLUDED + + +#include "Poco/Net/Net.h" + + +namespace Poco { +namespace Net { + + +class HTTPServerRequest; +class HTTPServerResponse; + + +class Net_API HTTPRequestHandler + /// The abstract base class for HTTPRequestHandlers + /// created by HTTPServer. + /// + /// Derived classes must override the handleRequest() method. + /// Furthermore, a HTTPRequestHandlerFactory must be provided. + /// + /// The handleRequest() method must perform the complete handling + /// of the HTTP request connection. As soon as the handleRequest() + /// method returns, the request handler object is destroyed. + /// + /// A new HTTPRequestHandler object will be created for + /// each new HTTP request that is received by the HTTPServer. +{ +public: + HTTPRequestHandler(); + /// Creates the HTTPRequestHandler. + + virtual ~HTTPRequestHandler(); + /// Destroys the HTTPRequestHandler. + + virtual void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) = 0; + /// Must be overridden by subclasses. + /// + /// Handles the given request. + +private: + HTTPRequestHandler(const HTTPRequestHandler&); + HTTPRequestHandler& operator = (const HTTPRequestHandler&); +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPRequestHandler_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPRequestHandlerFactory.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPRequestHandlerFactory.h new file mode 100644 index 0000000000..421c465018 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPRequestHandlerFactory.h @@ -0,0 +1,78 @@ +// +// HTTPRequestHandlerFactory.h +// +// Library: Net +// Package: HTTPServer +// Module: HTTPRequestHandlerFactory +// +// Definition of the HTTPRequestHandlerFactory class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPRequestHandlerFactory_INCLUDED +#define Net_HTTPRequestHandlerFactory_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/SharedPtr.h" +#include "Poco/BasicEvent.h" + + +namespace Poco { +namespace Net { + + +class HTTPServerRequest; +class HTTPServerResponse; +class HTTPRequestHandler; + + +class Net_API HTTPRequestHandlerFactory + /// A factory for HTTPRequestHandler objects. + /// Subclasses must override the createRequestHandler() + /// method. +{ +public: + typedef Poco::SharedPtr<HTTPRequestHandlerFactory> Ptr; + + HTTPRequestHandlerFactory(); + /// Creates the HTTPRequestHandlerFactory. + + virtual ~HTTPRequestHandlerFactory(); + /// Destroys the HTTPRequestHandlerFactory. + + virtual HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request) = 0; + /// Must be overridden by subclasses. + /// + /// Creates a new request handler for the given HTTP request. + /// + /// The method should inspect the given HTTPServerRequest object (e.g., method + /// and URI) and create an appropriate HTTPRequestHandler object to handle the + /// request. + /// + /// If the request contains a "Expect: 100-continue" header, it's possible + /// to prevent the server from sending the default 100 Continue response + /// by setting the status of the response object that can be obtained through + /// the request object (request.response()) to something other than 200 OK. + +protected: + Poco::BasicEvent<const bool> serverStopped; + +private: + HTTPRequestHandlerFactory(const HTTPRequestHandlerFactory&); + HTTPRequestHandlerFactory& operator = (const HTTPRequestHandlerFactory&); + + friend class HTTPServer; + friend class HTTPServerConnection; +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPRequestHandlerFactory_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPResponse.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPResponse.h new file mode 100644 index 0000000000..0c795f8f29 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPResponse.h @@ -0,0 +1,299 @@ +// +// HTTPResponse.h +// +// Library: Net +// Package: HTTP +// Module: HTTPResponse +// +// Definition of the HTTPResponse class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPResponse_INCLUDED +#define Net_HTTPResponse_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPMessage.h" +#include "Poco/Net/HTTPCookie.h" +#include "Poco/Timestamp.h" +#include <vector> + + +namespace Poco { +namespace Net { + + +class HTTPCookie; + + +class Net_API HTTPResponse: public HTTPMessage + /// This class encapsulates an HTTP response + /// message. + /// + /// In addition to the properties common to + /// all HTTP messages, a HTTP response has + /// status code and a reason phrase. +{ +public: + enum HTTPStatus + { + HTTP_CONTINUE = 100, + HTTP_SWITCHING_PROTOCOLS = 101, + HTTP_PROCESSING = 102, + HTTP_OK = 200, + HTTP_CREATED = 201, + HTTP_ACCEPTED = 202, + HTTP_NONAUTHORITATIVE = 203, + HTTP_NO_CONTENT = 204, + HTTP_RESET_CONTENT = 205, + HTTP_PARTIAL_CONTENT = 206, + HTTP_MULTI_STATUS = 207, + HTTP_ALREADY_REPORTED = 208, + HTTP_IM_USED = 226, + HTTP_MULTIPLE_CHOICES = 300, + HTTP_MOVED_PERMANENTLY = 301, + HTTP_FOUND = 302, + HTTP_SEE_OTHER = 303, + HTTP_NOT_MODIFIED = 304, + HTTP_USE_PROXY = 305, + HTTP_USEPROXY = 305, /// @deprecated + // UNUSED: 306 + HTTP_TEMPORARY_REDIRECT = 307, + HTTP_PERMANENT_REDIRECT = 308, + HTTP_BAD_REQUEST = 400, + HTTP_UNAUTHORIZED = 401, + HTTP_PAYMENT_REQUIRED = 402, + HTTP_FORBIDDEN = 403, + HTTP_NOT_FOUND = 404, + HTTP_METHOD_NOT_ALLOWED = 405, + HTTP_NOT_ACCEPTABLE = 406, + HTTP_PROXY_AUTHENTICATION_REQUIRED = 407, + HTTP_REQUEST_TIMEOUT = 408, + HTTP_CONFLICT = 409, + HTTP_GONE = 410, + HTTP_LENGTH_REQUIRED = 411, + HTTP_PRECONDITION_FAILED = 412, + HTTP_REQUEST_ENTITY_TOO_LARGE = 413, + HTTP_REQUESTENTITYTOOLARGE = 413, /// @deprecated + HTTP_REQUEST_URI_TOO_LONG = 414, + HTTP_REQUESTURITOOLONG = 414, /// @deprecated + HTTP_UNSUPPORTED_MEDIA_TYPE = 415, + HTTP_UNSUPPORTEDMEDIATYPE = 415, /// @deprecated + HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416, + HTTP_EXPECTATION_FAILED = 417, + HTTP_IM_A_TEAPOT = 418, + HTTP_ENCHANCE_YOUR_CALM = 420, + HTTP_MISDIRECTED_REQUEST = 421, + HTTP_UNPROCESSABLE_ENTITY = 422, + HTTP_LOCKED = 423, + HTTP_FAILED_DEPENDENCY = 424, + HTTP_UPGRADE_REQUIRED = 426, + HTTP_PRECONDITION_REQUIRED = 428, + HTTP_TOO_MANY_REQUESTS = 429, + HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431, + HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451, + HTTP_INTERNAL_SERVER_ERROR = 500, + HTTP_NOT_IMPLEMENTED = 501, + HTTP_BAD_GATEWAY = 502, + HTTP_SERVICE_UNAVAILABLE = 503, + HTTP_GATEWAY_TIMEOUT = 504, + HTTP_VERSION_NOT_SUPPORTED = 505, + HTTP_VARIANT_ALSO_NEGOTIATES = 506, + HTTP_INSUFFICIENT_STORAGE = 507, + HTTP_LOOP_DETECTED = 508, + HTTP_NOT_EXTENDED = 510, + HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511 + }; + + HTTPResponse(); + /// Creates the HTTPResponse with OK status. + + HTTPResponse(HTTPStatus status, const std::string& reason); + /// Creates the HTTPResponse with the given status + /// and reason phrase. + + HTTPResponse(const std::string& version, HTTPStatus status, const std::string& reason); + /// Creates the HTTPResponse with the given version, status + /// and reason phrase. + + HTTPResponse(HTTPStatus status); + /// Creates the HTTPResponse with the given status + /// an an appropriate reason phrase. + + HTTPResponse(const std::string& version, HTTPStatus status); + /// Creates the HTTPResponse with the given version, status + /// an an appropriate reason phrase. + + virtual ~HTTPResponse(); + /// Destroys the HTTPResponse. + + void setStatus(HTTPStatus status); + /// Sets the HTTP status code. + /// + /// Does not change the reason phrase. + + HTTPStatus getStatus() const; + /// Returns the HTTP status code. + + void setStatus(const std::string& status); + /// Sets the HTTP status code. + /// + /// The string must contain a valid + /// HTTP numerical status code. + + void setReason(const std::string& reason); + /// Sets the HTTP reason phrase. + + const std::string& getReason() const; + /// Returns the HTTP reason phrase. + + void setStatusAndReason(HTTPStatus status, const std::string& reason); + /// Sets the HTTP status code and reason phrase. + + void setStatusAndReason(HTTPStatus status); + /// Sets the HTTP status code and reason phrase. + /// + /// The reason phrase is set according to the status code. + + void setDate(const Poco::Timestamp& dateTime); + /// Sets the Date header to the given date/time value. + + Poco::Timestamp getDate() const; + /// Returns the value of the Date header. + + void addCookie(const HTTPCookie& cookie); + /// Adds the cookie to the response by + /// adding a Set-Cookie header. + + void getCookies(std::vector<HTTPCookie>& cookies) const; + /// Returns a vector with all the cookies + /// set in the response header. + /// + /// May throw an exception in case of a malformed + /// Set-Cookie header. + + void write(std::ostream& ostr) const; + /// Writes the HTTP response to the given + /// output stream. + + void beginWrite(std::ostream& ostr) const; + /// Writes the HTTP response to the given + /// output stream, but do not finish with \r\n delimiter. + + void read(std::istream& istr); + /// Reads the HTTP response from the + /// given input stream. + /// + /// 100 Continue responses are ignored. + + static const std::string& getReasonForStatus(HTTPStatus status); + /// Returns an appropriate reason phrase + /// for the given status code. + + static const std::string HTTP_REASON_CONTINUE; + static const std::string HTTP_REASON_SWITCHING_PROTOCOLS; + static const std::string HTTP_REASON_PROCESSING; + static const std::string HTTP_REASON_OK; + static const std::string HTTP_REASON_CREATED; + static const std::string HTTP_REASON_ACCEPTED; + static const std::string HTTP_REASON_NONAUTHORITATIVE; + static const std::string HTTP_REASON_NO_CONTENT; + static const std::string HTTP_REASON_RESET_CONTENT; + static const std::string HTTP_REASON_PARTIAL_CONTENT; + static const std::string HTTP_REASON_MULTI_STATUS; + static const std::string HTTP_REASON_ALREADY_REPORTED; + static const std::string HTTP_REASON_IM_USED; + static const std::string HTTP_REASON_MULTIPLE_CHOICES; + static const std::string HTTP_REASON_MOVED_PERMANENTLY; + static const std::string HTTP_REASON_FOUND; + static const std::string HTTP_REASON_SEE_OTHER; + static const std::string HTTP_REASON_NOT_MODIFIED; + static const std::string HTTP_REASON_USE_PROXY; + static const std::string HTTP_REASON_TEMPORARY_REDIRECT; + static const std::string HTTP_REASON_PERMANENT_REDIRECT; + static const std::string HTTP_REASON_BAD_REQUEST; + static const std::string HTTP_REASON_UNAUTHORIZED; + static const std::string HTTP_REASON_PAYMENT_REQUIRED; + static const std::string HTTP_REASON_FORBIDDEN; + static const std::string HTTP_REASON_NOT_FOUND; + static const std::string HTTP_REASON_METHOD_NOT_ALLOWED; + static const std::string HTTP_REASON_NOT_ACCEPTABLE; + static const std::string HTTP_REASON_PROXY_AUTHENTICATION_REQUIRED; + static const std::string HTTP_REASON_REQUEST_TIMEOUT; + static const std::string HTTP_REASON_CONFLICT; + static const std::string HTTP_REASON_GONE; + static const std::string HTTP_REASON_LENGTH_REQUIRED; + static const std::string HTTP_REASON_PRECONDITION_FAILED; + static const std::string HTTP_REASON_REQUEST_ENTITY_TOO_LARGE; + static const std::string HTTP_REASON_REQUEST_URI_TOO_LONG; + static const std::string HTTP_REASON_UNSUPPORTED_MEDIA_TYPE; + static const std::string HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE; + static const std::string HTTP_REASON_EXPECTATION_FAILED; + static const std::string HTTP_REASON_IM_A_TEAPOT; + static const std::string HTTP_REASON_ENCHANCE_YOUR_CALM; + static const std::string HTTP_REASON_MISDIRECTED_REQUEST; + static const std::string HTTP_REASON_UNPROCESSABLE_ENTITY; + static const std::string HTTP_REASON_LOCKED; + static const std::string HTTP_REASON_FAILED_DEPENDENCY; + static const std::string HTTP_REASON_UPGRADE_REQUIRED; + static const std::string HTTP_REASON_PRECONDITION_REQUIRED; + static const std::string HTTP_REASON_TOO_MANY_REQUESTS; + static const std::string HTTP_REASON_REQUEST_HEADER_FIELDS_TOO_LARGE; + static const std::string HTTP_REASON_UNAVAILABLE_FOR_LEGAL_REASONS; + static const std::string HTTP_REASON_INTERNAL_SERVER_ERROR; + static const std::string HTTP_REASON_NOT_IMPLEMENTED; + static const std::string HTTP_REASON_BAD_GATEWAY; + static const std::string HTTP_REASON_SERVICE_UNAVAILABLE; + static const std::string HTTP_REASON_GATEWAY_TIMEOUT; + static const std::string HTTP_REASON_VERSION_NOT_SUPPORTED; + static const std::string HTTP_REASON_VARIANT_ALSO_NEGOTIATES; + static const std::string HTTP_REASON_INSUFFICIENT_STORAGE; + static const std::string HTTP_REASON_LOOP_DETECTED; + static const std::string HTTP_REASON_NOT_EXTENDED; + static const std::string HTTP_REASON_NETWORK_AUTHENTICATION_REQUIRED; + static const std::string HTTP_REASON_UNKNOWN; + + static const std::string DATE; + static const std::string SET_COOKIE; + +private: + enum Limits + { + MAX_VERSION_LENGTH = 8, + MAX_STATUS_LENGTH = 3, + MAX_REASON_LENGTH = 512 + }; + + HTTPStatus _status; + std::string _reason; + + HTTPResponse(const HTTPResponse&); + HTTPResponse& operator = (const HTTPResponse&); +}; + + +// +// inlines +// +inline HTTPResponse::HTTPStatus HTTPResponse::getStatus() const +{ + return _status; +} + + +inline const std::string& HTTPResponse::getReason() const +{ + return _reason; +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPResponse_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPServer.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPServer.h new file mode 100644 index 0000000000..69f092a673 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPServer.h @@ -0,0 +1,103 @@ +// +// HTTPServer.h +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServer +// +// Definition of the HTTPServer class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPServer_INCLUDED +#define Net_HTTPServer_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/TCPServer.h" +#include "Poco/Net/HTTPRequestHandlerFactory.h" +#include "Poco/Net/HTTPServerParams.h" + + +namespace Poco { +namespace Net { + + +class Net_API HTTPServer: public TCPServer + /// A subclass of TCPServer that implements a + /// full-featured multithreaded HTTP server. + /// + /// A HTTPRequestHandlerFactory must be supplied. + /// The ServerSocket must be bound and in listening state. + /// + /// To configure various aspects of the server, a HTTPServerParams + /// object can be passed to the constructor. + /// + /// The server supports: + /// - HTTP/1.0 and HTTP/1.1 + /// - automatic handling of persistent connections. + /// - automatic decoding/encoding of request/response message bodies + /// using chunked transfer encoding. + /// + /// Please see the TCPServer class for information about + /// connection and thread handling. + /// + /// See RFC 2616 <http://www.faqs.org/rfcs/rfc2616.html> for more + /// information about the HTTP protocol. +{ +public: + HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, Poco::UInt16 portNumber = 80, HTTPServerParams::Ptr pParams = new HTTPServerParams); + /// Creates HTTPServer listening on the given port (default 80). + /// + /// The server takes ownership of the HTTPRequstHandlerFactory + /// and deletes it when it's no longer needed. + /// + /// New threads are taken from the default thread pool. + + HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, const ServerSocket& socket, HTTPServerParams::Ptr pParams); + /// Creates the HTTPServer, using the given ServerSocket. + /// + /// The server takes ownership of the HTTPRequstHandlerFactory + /// and deletes it when it's no longer needed. + /// + /// The server also takes ownership of the HTTPServerParams object. + /// + /// New threads are taken from the default thread pool. + + HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, Poco::ThreadPool& threadPool, const ServerSocket& socket, HTTPServerParams::Ptr pParams); + /// Creates the HTTPServer, using the given ServerSocket. + /// + /// The server takes ownership of the HTTPRequstHandlerFactory + /// and deletes it when it's no longer needed. + /// + /// The server also takes ownership of the HTTPServerParams object. + /// + /// New threads are taken from the given thread pool. + + ~HTTPServer(); + /// Destroys the HTTPServer and its HTTPRequestHandlerFactory. + + void stopAll(bool abortCurrent = false); + /// Stops the server. In contrast to TCPServer::stop(), which also + /// stops the server, but allows all client connections to finish at + /// their pace, this allows finer control over client connections. + /// + /// If abortCurrent is false, all current requests are allowed to + /// complete. If abortCurrent is true, the underlying sockets of + /// all client connections are shut down, causing all requests + /// to abort. + +private: + HTTPRequestHandlerFactory::Ptr _pFactory; +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPServer_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPServerConnection.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerConnection.h new file mode 100644 index 0000000000..536889c04a --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerConnection.h @@ -0,0 +1,65 @@ +// +// HTTPServerConnection.h +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerConnection +// +// Definition of the HTTPServerConnection class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPServerConnection_INCLUDED +#define Net_HTTPServerConnection_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/TCPServerConnection.h" +#include "Poco/Net/HTTPResponse.h" +#include "Poco/Net/HTTPRequestHandlerFactory.h" +#include "Poco/Net/HTTPServerParams.h" +#include "Poco/Mutex.h" + + +namespace Poco { +namespace Net { + + +class HTTPServerSession; + + +class Net_API HTTPServerConnection: public TCPServerConnection + /// This subclass of TCPServerConnection handles HTTP + /// connections. +{ +public: + HTTPServerConnection(const StreamSocket& socket, HTTPServerParams::Ptr pParams, HTTPRequestHandlerFactory::Ptr pFactory); + /// Creates the HTTPServerConnection. + + virtual ~HTTPServerConnection(); + /// Destroys the HTTPServerConnection. + + void run(); + /// Handles all HTTP requests coming in. + +protected: + void sendErrorResponse(HTTPServerSession& session, HTTPResponse::HTTPStatus status); + void onServerStopped(const bool& abortCurrent); + +private: + HTTPServerParams::Ptr _pParams; + HTTPRequestHandlerFactory::Ptr _pFactory; + bool _stopped; + Poco::FastMutex _mutex; +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPServerConnection_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPServerConnectionFactory.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerConnectionFactory.h new file mode 100644 index 0000000000..fc44f912c5 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerConnectionFactory.h @@ -0,0 +1,55 @@ +// +// HTTPServerConnectionFactory.h +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerConnectionFactory +// +// Definition of the HTTPServerConnectionFactory class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPServerConnectionFactory_INCLUDED +#define Net_HTTPServerConnectionFactory_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/TCPServerConnectionFactory.h" +#include "Poco/Net/HTTPRequestHandlerFactory.h" +#include "Poco/Net/HTTPServerParams.h" + + +namespace Poco { +namespace Net { + + +class Net_API HTTPServerConnectionFactory: public TCPServerConnectionFactory + /// This implementation of a TCPServerConnectionFactory + /// is used by HTTPServer to create HTTPServerConnection objects. +{ +public: + HTTPServerConnectionFactory(HTTPServerParams::Ptr pParams, HTTPRequestHandlerFactory::Ptr pFactory); + /// Creates the HTTPServerConnectionFactory. + + ~HTTPServerConnectionFactory(); + /// Destroys the HTTPServerConnectionFactory. + + TCPServerConnection* createConnection(const StreamSocket& socket); + /// Creates an instance of HTTPServerConnection + /// using the given StreamSocket. + +private: + HTTPServerParams::Ptr _pParams; + HTTPRequestHandlerFactory::Ptr _pFactory; +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPServerConnectionFactory_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPServerParams.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerParams.h new file mode 100644 index 0000000000..0fb86aaca1 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerParams.h @@ -0,0 +1,154 @@ +// +// HTTPServerParams.h +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerParams +// +// Definition of the HTTPServerParams class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPServerParams_INCLUDED +#define Net_HTTPServerParams_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/TCPServerParams.h" + + +namespace Poco { +namespace Net { + + +class Net_API HTTPServerParams: public TCPServerParams + /// This class is used to specify parameters to both the + /// HTTPServer, as well as to HTTPRequestHandler objects. + /// + /// Subclasses may add new parameters to the class. +{ +public: + typedef Poco::AutoPtr<HTTPServerParams> Ptr; + + HTTPServerParams(); + /// Creates the HTTPServerParams. + /// + /// Sets the following default values: + /// - timeout: 60 seconds + /// - keepAlive: true + /// - maxKeepAliveRequests: 0 + /// - keepAliveTimeout: 10 seconds + + void setServerName(const std::string& serverName); + /// Sets the name and port (name:port) that the server uses to identify itself. + /// + /// If this is not set to valid DNS name for your host, server-generated + /// redirections will not work. + + const std::string& getServerName() const; + /// Returns the name and port (name:port) that the server uses to identify itself. + + void setSoftwareVersion(const std::string& softwareVersion); + /// Sets the server software name and version that the server uses to identify + /// itself. If this is set to a non-empty string, the server will + /// automatically include a Server header field with the value given + /// here in every response it sends. + /// + /// The format of the softwareVersion string should be name/version + /// (e.g. MyHTTPServer/1.0). + + const std::string& getSoftwareVersion() const; + /// Returns the server software name and version that the server uses to + /// identify itself. + + void setTimeout(const Poco::Timespan& timeout); + /// Sets the connection timeout for HTTP connections. + + const Poco::Timespan& getTimeout() const; + /// Returns the connection timeout for HTTP connections. + + void setKeepAlive(bool keepAlive); + /// Enables (keepAlive == true) or disables (keepAlive == false) + /// persistent connections. + + bool getKeepAlive() const; + /// Returns true iff persistent connections are enabled. + + void setKeepAliveTimeout(const Poco::Timespan& timeout); + /// Sets the connection timeout for HTTP connections. + + const Poco::Timespan& getKeepAliveTimeout() const; + /// Returns the connection timeout for HTTP connections. + + void setMaxKeepAliveRequests(int maxKeepAliveRequests); + /// Specifies the maximum number of requests allowed + /// during a persistent connection. 0 means unlimited + /// connections. + + int getMaxKeepAliveRequests() const; + /// Returns the maximum number of requests allowed + /// during a persistent connection, or 0 if + /// unlimited connections are allowed. + +protected: + virtual ~HTTPServerParams(); + /// Destroys the HTTPServerParams. + +private: + std::string _serverName; + std::string _softwareVersion; + Poco::Timespan _timeout; + bool _keepAlive; + int _maxKeepAliveRequests; + Poco::Timespan _keepAliveTimeout; +}; + + +// +// inlines +// +inline const std::string& HTTPServerParams::getServerName() const +{ + return _serverName; +} + + +inline const std::string& HTTPServerParams::getSoftwareVersion() const +{ + return _softwareVersion; +} + + +inline const Poco::Timespan& HTTPServerParams::getTimeout() const +{ + return _timeout; +} + + +inline bool HTTPServerParams::getKeepAlive() const +{ + return _keepAlive; +} + + +inline int HTTPServerParams::getMaxKeepAliveRequests() const +{ + return _maxKeepAliveRequests; +} + + +inline const Poco::Timespan& HTTPServerParams::getKeepAliveTimeout() const +{ + return _keepAliveTimeout; +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPServerParams_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPServerRequest.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerRequest.h new file mode 100644 index 0000000000..69ffeaec08 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerRequest.h @@ -0,0 +1,80 @@ +// +// HTTPServerRequest.h +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerRequest +// +// Definition of the HTTPServerRequest class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPServerRequest_INCLUDED +#define Net_HTTPServerRequest_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/SocketAddress.h" +#include <istream> + + +namespace Poco { +namespace Net { + + +class HTTPServerSession; +class HTTPServerResponse; +class HTTPServerParams; + + +class Net_API HTTPServerRequest: public HTTPRequest + /// This abstract subclass of HTTPRequest is used for + /// representing server-side HTTP requests. + /// + /// A HTTPServerRequest is passed to the + /// handleRequest() method of HTTPRequestHandler. +{ +public: + HTTPServerRequest(); + /// Creates the HTTPServerRequest + + ~HTTPServerRequest(); + /// Destroys the HTTPServerRequest. + + virtual std::istream& stream() = 0; + /// Returns the input stream for reading + /// the request body. + /// + /// The stream must be valid until the HTTPServerRequest + /// object is destroyed. + + virtual const SocketAddress& clientAddress() const = 0; + /// Returns the client's address. + + virtual const SocketAddress& serverAddress() const = 0; + /// Returns the server's address. + + virtual const HTTPServerParams& serverParams() const = 0; + /// Returns a reference to the server parameters. + + virtual HTTPServerResponse& response() const = 0; + /// Returns a reference to the associated response. + + virtual bool secure() const = 0; + /// Returns true if the request is using a secure + /// connection. Returns false if no secure connection + /// is used, or if it is not known whether a secure + /// connection is used. +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPServerRequest_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPServerRequestImpl.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerRequestImpl.h new file mode 100644 index 0000000000..419adbb5e4 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerRequestImpl.h @@ -0,0 +1,142 @@ +// +// HTTPServerRequestImpl.h +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerRequestImpl +// +// Definition of the HTTPServerRequestImpl class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPServerRequestImpl_INCLUDED +#define Net_HTTPServerRequestImpl_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponseImpl.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/AutoPtr.h" +#include <istream> + + +namespace Poco { +namespace Net { + + +class HTTPServerSession; +class HTTPServerParams; +class StreamSocket; + + +class Net_API HTTPServerRequestImpl: public HTTPServerRequest + /// This subclass of HTTPServerRequest is used for + /// representing server-side HTTP requests. + /// + /// A HTTPServerRequest is passed to the + /// handleRequest() method of HTTPRequestHandler. +{ +public: + HTTPServerRequestImpl(HTTPServerResponseImpl& response, HTTPServerSession& session, HTTPServerParams* pParams); + /// Creates the HTTPServerRequestImpl, using the + /// given HTTPServerSession. + + ~HTTPServerRequestImpl(); + /// Destroys the HTTPServerRequestImpl. + + std::istream& stream(); + /// Returns the input stream for reading + /// the request body. + /// + /// The stream is valid until the HTTPServerRequestImpl + /// object is destroyed. + + const SocketAddress& clientAddress() const; + /// Returns the client's address. + + const SocketAddress& serverAddress() const; + /// Returns the server's address. + + const HTTPServerParams& serverParams() const; + /// Returns a reference to the server parameters. + + HTTPServerResponse& response() const; + /// Returns a reference to the associated response. + + bool secure() const; + /// Returns true if the request is using a secure + /// connection. Returns false if no secure connection + /// is used, or if it is not known whether a secure + /// connection is used. + + StreamSocket& socket(); + /// Returns a reference to the underlying socket. + + StreamSocket detachSocket(); + /// Returns the underlying socket after detaching + /// it from the server session. + + HTTPServerSession& session(); + /// Returns the underlying HTTPServerSession. + +private: + HTTPServerResponseImpl& _response; + HTTPServerSession& _session; + std::istream* _pStream; + Poco::AutoPtr<HTTPServerParams> _pParams; + SocketAddress _clientAddress; + SocketAddress _serverAddress; +}; + + +// +// inlines +// +inline std::istream& HTTPServerRequestImpl::stream() +{ + poco_check_ptr (_pStream); + + return *_pStream; +} + + +inline const SocketAddress& HTTPServerRequestImpl::clientAddress() const +{ + return _clientAddress; +} + + +inline const SocketAddress& HTTPServerRequestImpl::serverAddress() const +{ + return _serverAddress; +} + + +inline const HTTPServerParams& HTTPServerRequestImpl::serverParams() const +{ + return *_pParams; +} + + +inline HTTPServerResponse& HTTPServerRequestImpl::response() const +{ + return _response; +} + + +inline HTTPServerSession& HTTPServerRequestImpl::session() +{ + return _session; +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPServerRequestImpl_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPServerResponse.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerResponse.h new file mode 100644 index 0000000000..7d89ffbb7e --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerResponse.h @@ -0,0 +1,127 @@ +// +// HTTPServerResponse.h +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerResponse +// +// Definition of the HTTPServerResponse class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPServerResponse_INCLUDED +#define Net_HTTPServerResponse_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPResponse.h" +#include <cstddef> +#include <ostream> + + +namespace Poco { +namespace Net { + + +class HTTPServerSession; +class HTTPCookie; + + +class Net_API HTTPServerResponse: public HTTPResponse + /// This subclass of HTTPResponse is used for + /// representing server-side HTTP responses. + /// + /// A HTTPServerResponse is passed to the + /// handleRequest() method of HTTPRequestHandler. + /// + /// handleRequest() must set a status code + /// and optional reason phrase, set headers + /// as necessary, and provide a message body. +{ +public: + HTTPServerResponse(); + /// Creates the HTTPServerResponse. + + ~HTTPServerResponse(); + /// Destroys the HTTPServerResponse. + + virtual void sendContinue() = 0; + /// Sends a 100 Continue response to the + /// client. + + virtual std::ostream& send() = 0; + /// Sends the response header to the client and + /// returns an output stream for sending the + /// response body. + /// + /// The returned stream is valid until the response + /// object is destroyed. + /// + /// Must not be called after beginSend(), sendFile(), sendBuffer() + /// or redirect() has been called. + + virtual std::pair<std::ostream *, std::ostream *> beginSend() = 0; + /// Sends the response headers to the client + /// but do not finish headers with \r\n, + /// allowing to continue sending additional header fields. + /// + /// Returns an output streams for sending the remaining headers + /// and response body. + /// + /// Must not be called after send(), sendFile(), sendBuffer() + /// or redirect() has been called. + + virtual void sendFile(const std::string& path, const std::string& mediaType) = 0; + /// Sends the response header to the client, followed + /// by the content of the given file. + /// + /// Must not be called after send(), sendBuffer() + /// or redirect() has been called. + /// + /// Throws a FileNotFoundException if the file + /// cannot be found, or an OpenFileException if + /// the file cannot be opened. + + virtual void sendBuffer(const void* pBuffer, std::size_t length) = 0; + /// Sends the response header to the client, followed + /// by the contents of the given buffer. + /// + /// The Content-Length header of the response is set + /// to length and chunked transfer encoding is disabled. + /// + /// If both the HTTP message header and body (from the + /// given buffer) fit into one single network packet, the + /// complete response can be sent in one network packet. + /// + /// Must not be called after send(), sendFile() + /// or redirect() has been called. + + virtual void redirect(const std::string& uri, HTTPStatus status = HTTP_FOUND) = 0; + /// Sets the status code, which must be one of + /// HTTP_MOVED_PERMANENTLY (301), HTTP_FOUND (302), + /// or HTTP_SEE_OTHER (303), + /// and sets the "Location" header field + /// to the given URI, which according to + /// the HTTP specification, must be absolute. + /// + /// Must not be called after send() has been called. + + virtual void requireAuthentication(const std::string& realm) = 0; + /// Sets the status code to 401 (Unauthorized) + /// and sets the "WWW-Authenticate" header field + /// according to the given realm. + + virtual bool sent() const = 0; + /// Returns true if the response (header) has been sent. +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPServerResponse_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPServerResponseImpl.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerResponseImpl.h new file mode 100644 index 0000000000..0210cb830f --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerResponseImpl.h @@ -0,0 +1,151 @@ +// +// HTTPServerResponseImpl.h +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerResponseImpl +// +// Definition of the HTTPServerResponseImpl class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPServerResponseImpl_INCLUDED +#define Net_HTTPServerResponseImpl_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPServerResponse.h" + + +namespace Poco { +namespace Net { + + +class HTTPServerSession; +class HTTPServerRequestImpl; + + +class Net_API HTTPServerResponseImpl: public HTTPServerResponse + /// This subclass of HTTPServerResponse is used for + /// representing server-side HTTP responses. + /// + /// A HTTPServerResponse is passed to the + /// handleRequest() method of HTTPRequestHandler. + /// + /// handleRequest() must set a status code + /// and optional reason phrase, set headers + /// as necessary, and provide a message body. +{ +public: + HTTPServerResponseImpl(HTTPServerSession& session); + /// Creates the HTTPServerResponseImpl. + + ~HTTPServerResponseImpl(); + /// Destroys the HTTPServerResponseImpl. + + void sendContinue(); + /// Sends a 100 Continue response to the + /// client. + + std::ostream& send(); + /// Sends the response header to the client and + /// returns an output stream for sending the + /// response body. + /// + /// The returned stream is valid until the response + /// object is destroyed. + /// + /// Must not be called after beginSend(), sendFile(), sendBuffer() + /// or redirect() has been called. + + std::pair<std::ostream *, std::ostream *> beginSend(); + /// Sends the response headers to the client + /// but do not finish headers with \r\n, + /// allowing to continue sending additional header fields. + /// + /// Returns an output streams for sending the remaining headers + /// and response body. + /// + /// Must not be called after send(), sendFile(), sendBuffer() + /// or redirect() has been called. + + void sendFile(const std::string& path, const std::string& mediaType); + /// Sends the response header to the client, followed + /// by the content of the given file. + /// + /// Must not be called after send(), sendBuffer() + /// or redirect() has been called. + /// + /// Throws a FileNotFoundException if the file + /// cannot be found, or an OpenFileException if + /// the file cannot be opened. + + void sendBuffer(const void* pBuffer, std::size_t length); + /// Sends the response header to the client, followed + /// by the contents of the given buffer. + /// + /// The Content-Length header of the response is set + /// to length and chunked transfer encoding is disabled. + /// + /// If both the HTTP message header and body (from the + /// given buffer) fit into one single network packet, the + /// complete response can be sent in one network packet. + /// + /// Must not be called after send(), sendFile() + /// or redirect() has been called. + + void redirect(const std::string& uri, HTTPStatus status = HTTP_FOUND); + /// Sets the status code, which must be one of + /// HTTP_MOVED_PERMANENTLY (301), HTTP_FOUND (302), + /// or HTTP_SEE_OTHER (303), + /// and sets the "Location" header field + /// to the given URI, which according to + /// the HTTP specification, must be absolute. + /// + /// Must not be called after send() has been called. + + void requireAuthentication(const std::string& realm); + /// Sets the status code to 401 (Unauthorized) + /// and sets the "WWW-Authenticate" header field + /// according to the given realm. + + bool sent() const; + /// Returns true if the response (header) has been sent. + +protected: + void attachRequest(HTTPServerRequestImpl* pRequest); + +private: + HTTPServerSession& _session; + HTTPServerRequestImpl* _pRequest; + std::ostream* _pStream; + std::ostream* _pHeaderStream; + + friend class HTTPServerRequestImpl; +}; + + +// +// inlines +// +inline bool HTTPServerResponseImpl::sent() const +{ + return _pStream != 0; +} + + +inline void HTTPServerResponseImpl::attachRequest(HTTPServerRequestImpl* pRequest) +{ + _pRequest = pRequest; +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPServerResponseImpl_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPServerSession.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerSession.h new file mode 100644 index 0000000000..8b169bf556 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPServerSession.h @@ -0,0 +1,76 @@ +// +// HTTPServerSession.h +// +// Library: Net +// Package: HTTPServer +// Module: HTTPServerSession +// +// Definition of the HTTPServerSession class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPServerSession_INCLUDED +#define Net_HTTPServerSession_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPSession.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/Net/HTTPServerSession.h" +#include "Poco/Net/HTTPServerParams.h" +#include "Poco/Timespan.h" + + +namespace Poco { +namespace Net { + + +class Net_API HTTPServerSession: public HTTPSession + /// This class handles the server side of a + /// HTTP session. It is used internally by + /// HTTPServer. +{ +public: + HTTPServerSession(const StreamSocket& socket, HTTPServerParams::Ptr pParams); + /// Creates the HTTPServerSession. + + virtual ~HTTPServerSession(); + /// Destroys the HTTPServerSession. + + bool hasMoreRequests(); + /// Returns true if there are requests available. + + bool canKeepAlive() const; + /// Returns true if the session can be kept alive. + + SocketAddress clientAddress(); + /// Returns the client's address. + + SocketAddress serverAddress(); + /// Returns the server's address. + +private: + bool _firstRequest; + Poco::Timespan _keepAliveTimeout; + int _maxKeepAliveRequests; +}; + + +// +// inlines +// +inline bool HTTPServerSession::canKeepAlive() const +{ + return _maxKeepAliveRequests != 0; +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPServerSession_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPSession.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPSession.h new file mode 100644 index 0000000000..666f6f6267 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPSession.h @@ -0,0 +1,251 @@ +// +// HTTPSession.h +// +// Library: Net +// Package: HTTP +// Module: HTTPSession +// +// Definition of the HTTPSession class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPSession_INCLUDED +#define Net_HTTPSession_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/StreamSocket.h" +#include "Poco/Timespan.h" +#include "Poco/Exception.h" +#include "Poco/Any.h" +#include "Poco/Buffer.h" +#include <ios> + + +namespace Poco { +namespace Net { + + +class Net_API HTTPSession + /// HTTPSession implements basic HTTP session management + /// for both HTTP clients and HTTP servers. + /// + /// HTTPSession implements buffering for HTTP connections, as well + /// as specific support for the various HTTP stream classes. + /// + /// This class can not be instantiated. HTTPClientSession or + /// HTTPServerSession must be used instead. +{ +public: + void setKeepAlive(bool keepAlive); + /// Sets the keep-alive flag for this session. + /// + /// If the keep-alive flag is enabled, persistent + /// HTTP/1.1 connections are supported. + + bool getKeepAlive() const; + /// Returns the value of the keep-alive flag for + /// this session. + + void setTimeout(const Poco::Timespan& timeout); + /// Sets the timeout for the HTTP session. + + void setTimeout(const Poco::Timespan& connectionTimeout, const Poco::Timespan& sendTimeout, const Poco::Timespan& receiveTimeout); + /// Sets different timeouts for the HTTP session. + + Poco::Timespan getTimeout() const; + /// Returns the timeout for the HTTP session. + + bool connected() const; + /// Returns true if the underlying socket is connected. + + virtual void abort(); + /// Aborts a session in progress by shutting down + /// and closing the underlying socket. + + const Poco::Exception* networkException() const; + /// If sending or receiving data over the underlying + /// socket connection resulted in an exception, a + /// pointer to this exception is returned. + /// + /// Otherwise, NULL is returned. + + void attachSessionData(const Poco::Any& data); + /// Allows to attach an application-specific data + /// item to the session. + /// + /// On the server side, this can be used to manage + /// data that must be maintained over the entire + /// lifetime of a persistent connection (that is, + /// multiple requests sent over the same connection). + + const Poco::Any& sessionData() const; + /// Returns the data attached with attachSessionData(), + /// or an empty Poco::Any if no user data has been + /// attached. + + enum + { + HTTP_PORT = 80 + }; + + StreamSocket detachSocket(); + /// Detaches the socket from the session. + /// + /// The socket is returned, and a new, uninitialized socket is + /// attached to the session. + + StreamSocket& socket(); + /// Returns a reference to the underlying socket. + + void drainBuffer(Poco::Buffer<char>& buffer); + /// Copies all bytes remaining in the internal buffer to the + /// given Poco::Buffer, resizing it as necessary. + /// + /// This is usually used together with detachSocket() to + /// obtain any data already read from the socket, but not + /// yet processed. + +protected: + HTTPSession(); + /// Creates a HTTP session using an + /// unconnected stream socket. + + HTTPSession(const StreamSocket& socket); + /// Creates a HTTP session using the + /// given socket. The session takes ownership + /// of the socket and closes it when it's no + /// longer used. + + HTTPSession(const StreamSocket& socket, bool keepAlive); + /// Creates a HTTP session using the + /// given socket. The session takes ownership + /// of the socket and closes it when it's no + /// longer used. + + virtual ~HTTPSession(); + /// Destroys the HTTPSession and closes the + /// underlying socket. + + int get(); + /// Returns the next byte in the buffer. + /// Reads more data from the socket if there are + /// no bytes left in the buffer. + + int peek(); + /// Peeks at the next character in the buffer. + /// Reads more data from the socket if there are + /// no bytes left in the buffer. + + virtual int read(char* buffer, std::streamsize length); + /// Reads up to length bytes. + /// + /// If there is data in the buffer, this data + /// is returned. Otherwise, data is read from + /// the socket to avoid unnecessary buffering. + + virtual int write(const char* buffer, std::streamsize length); + /// Writes data to the socket. + + int receive(char* buffer, int length); + /// Reads up to length bytes. + + int buffered() const; + /// Returns the number of bytes in the buffer. + + void refill(); + /// Refills the internal buffer. + + virtual void connect(const SocketAddress& address); + /// Connects the underlying socket to the given address + /// and sets the socket's receive timeout. + + void attachSocket(const StreamSocket& socket); + /// Attaches a socket to the session, replacing the + /// previously attached socket. + + void close(); + /// Closes the underlying socket. + + void setException(const Poco::Exception& exc); + /// Stores a clone of the exception. + + void clearException(); + /// Clears the stored exception. + +private: + enum + { + HTTP_DEFAULT_TIMEOUT = 60000000, + HTTP_DEFAULT_CONNECTION_TIMEOUT = 30000000 + }; + + HTTPSession(const HTTPSession&); + HTTPSession& operator = (const HTTPSession&); + + StreamSocket _socket; + char* _pBuffer; + char* _pCurrent; + char* _pEnd; + bool _keepAlive; + Poco::Timespan _connectionTimeout; + Poco::Timespan _receiveTimeout; + Poco::Timespan _sendTimeout; + Poco::Exception* _pException; + Poco::Any _data; + + friend class HTTPStreamBuf; + friend class HTTPHeaderStreamBuf; + friend class HTTPFixedLengthStreamBuf; + friend class HTTPChunkedStreamBuf; +}; + + +// +// inlines +// +inline bool HTTPSession::getKeepAlive() const +{ + return _keepAlive; +} + + +inline Poco::Timespan HTTPSession::getTimeout() const +{ + return _receiveTimeout; +} + + +inline StreamSocket& HTTPSession::socket() +{ + return _socket; +} + + +inline const Poco::Exception* HTTPSession::networkException() const +{ + return _pException; +} + + +inline int HTTPSession::buffered() const +{ + return static_cast<int>(_pEnd - _pCurrent); +} + + +inline const Poco::Any& HTTPSession::sessionData() const +{ + return _data; +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPSession_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPSessionFactory.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPSessionFactory.h new file mode 100644 index 0000000000..3bc7d15d2c --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPSessionFactory.h @@ -0,0 +1,155 @@ +// +// HTTPSessionFactory.h +// +// Library: Net +// Package: HTTPClient +// Module: HTTPSessionFactory +// +// Definition of the HTTPSessionFactory class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPSessionFactoryMgr_INCLUDED +#define Net_HTTPSessionFactoryMgr_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Mutex.h" +#include "Poco/URI.h" +#include "Poco/SingletonHolder.h" +#include "Poco/SharedPtr.h" +#include <map> + + +namespace Poco { +namespace Net { + + +class HTTPSessionInstantiator; +class HTTPClientSession; + + +class Net_API HTTPSessionFactory + /// A factory for HTTPClientSession objects. + /// + /// Given a URI, this class creates a HTTPClientSession + /// (for http) or a HTTPSClientSession (for https) for + /// accessing the URI. + /// + /// The actual work of creating the session is done by + /// HTTPSessionInstantiator objects that must be registered + /// with a HTTPSessionFactory. +{ +public: + HTTPSessionFactory(); + /// Creates the HTTPSessionFactory. + + HTTPSessionFactory(const std::string& proxyHost, Poco::UInt16 proxyPort); + /// Creates the HTTPSessionFactory and sets the proxy host and port. + + ~HTTPSessionFactory(); + /// Destroys the HTTPSessionFactory. + + void registerProtocol(const std::string& protocol, HTTPSessionInstantiator* pSessionInstantiator); + /// Registers the session instantiator for the given protocol. + /// The factory takes ownership of the SessionInstantiator. + /// + /// A protocol can be registered more than once. However, only the instantiator + /// that has been registered first is used. Also, for each call to + /// registerProtocol(), a corresponding call to unregisterProtocol() must + /// be made. + + void unregisterProtocol(const std::string& protocol); + /// Removes the registration of a protocol. + /// + /// Throws a NotFoundException if no instantiator has been registered + /// for the given protocol. + + bool supportsProtocol(const std::string& protocol); + /// Returns true if a session instantiator for the given protocol has been registered. + + HTTPClientSession* createClientSession(const Poco::URI& uri); + /// Creates a client session for the given uri scheme. Throws exception if no factory is registered for the given scheme + + const std::string& proxyHost() const; + /// Returns the proxy host, if one has been set, or an empty string otherwise. + + Poco::UInt16 proxyPort() const; + /// Returns the proxy port number, if one has been set, or zero otherwise. + + void setProxy(const std::string& proxyHost, Poco::UInt16 proxyPort); + /// Sets the proxy host and port number. + + void setProxyCredentials(const std::string& username, const std::string& password); + /// Sets the username and password for proxy authorization (Basic auth only). + + const std::string& proxyUsername() const; + /// Returns the username for proxy authorization. + + const std::string& proxyPassword() const; + /// Returns the password for proxy authorization. + + static HTTPSessionFactory& defaultFactory(); + /// Returns the default HTTPSessionFactory. + +private: + struct InstantiatorInfo + { + HTTPSessionInstantiator* pIn; + int cnt; + InstantiatorInfo(HTTPSessionInstantiator* pInst); + // no destructor!!! this is by purpose, don't add one! + }; + + + HTTPSessionFactory(const HTTPSessionFactory&); + HTTPSessionFactory& operator = (const HTTPSessionFactory&); + + typedef std::map<std::string, InstantiatorInfo> Instantiators; + + Instantiators _instantiators; + std::string _proxyHost; + Poco::UInt16 _proxyPort; + std::string _proxyUsername; + std::string _proxyPassword; + + mutable Poco::FastMutex _mutex; +}; + + +// +// inlines +// +inline const std::string& HTTPSessionFactory::proxyHost() const +{ + return _proxyHost; +} + + +inline Poco::UInt16 HTTPSessionFactory::proxyPort() const +{ + return _proxyPort; +} + + +inline const std::string& HTTPSessionFactory::proxyUsername() const +{ + return _proxyUsername; +} + + +inline const std::string& HTTPSessionFactory::proxyPassword() const +{ + return _proxyPassword; +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPSessionFactoryMgr_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPSessionInstantiator.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPSessionInstantiator.h new file mode 100644 index 0000000000..cbb6ee82f2 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPSessionInstantiator.h @@ -0,0 +1,117 @@ +// +// HTTPSessionInstantiator.h +// +// Library: Net +// Package: HTTPClient +// Module: HTTPSessionInstantiator +// +// Definition of the HTTPSessionInstantiator class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPSessionInstantiator_INCLUDED +#define Net_HTTPSessionInstantiator_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPSession.h" +#include "Poco/URI.h" + + +namespace Poco { +namespace Net { + + +class HTTPClientSession; + + +class Net_API HTTPSessionInstantiator + /// A factory for HTTPClientSession objects. + /// + /// Creates a HTTP session for a given URI. + /// A HTTPSessionInstantiator is not used directly. + /// Instances are registered with a HTTPSessionFactory, + /// and used through it. +{ +public: + HTTPSessionInstantiator(); + /// Creates the HTTPSessionInstantiator. + + virtual ~HTTPSessionInstantiator(); + /// Destroys the HTTPSessionInstantiator. + + virtual HTTPClientSession* createClientSession(const Poco::URI& uri); + /// Creates a HTTPClientSession for the given URI. + + static void registerInstantiator(); + /// Registers the instantiator with the global HTTPSessionFactory. + + static void unregisterInstantiator(); + /// Unregisters the factory with the global HTTPSessionFactory. + +protected: + void setProxy(const std::string& host, Poco::UInt16 port); + /// Sets the proxy host and port. + /// Called by HTTPSessionFactory. + + const std::string& proxyHost() const; + /// Returns the proxy post. + + Poco::UInt16 proxyPort() const; + /// Returns the proxy port. + + void setProxyCredentials(const std::string& username, const std::string& password); + /// Sets the username and password for proxy authorization (Basic auth only). + + const std::string& proxyUsername() const; + /// Returns the username for proxy authorization. + + const std::string& proxyPassword() const; + /// Returns the password for proxy authorization. + +private: + std::string _proxyHost; + Poco::UInt16 _proxyPort; + std::string _proxyUsername; + std::string _proxyPassword; + + friend class HTTPSessionFactory; +}; + + +// +// inlines +// +inline const std::string& HTTPSessionInstantiator::proxyHost() const +{ + return _proxyHost; +} + + +inline Poco::UInt16 HTTPSessionInstantiator::proxyPort() const +{ + return _proxyPort; +} + + +inline const std::string& HTTPSessionInstantiator::proxyUsername() const +{ + return _proxyUsername; +} + + +inline const std::string& HTTPSessionInstantiator::proxyPassword() const +{ + return _proxyPassword; +} + + +} } // namespace Poco::Net + + +#endif // Net_HTTPSessionInstantiator_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPStream.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPStream.h new file mode 100644 index 0000000000..94d52095c5 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPStream.h @@ -0,0 +1,103 @@ +// +// HTTPStream.h +// +// Library: Net +// Package: HTTP +// Module: HTTPStream +// +// Definition of the HTTPStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPStream_INCLUDED +#define Net_HTTPStream_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPBasicStreamBuf.h" +#include "Poco/MemoryPool.h" +#include <cstddef> +#include <istream> +#include <ostream> + + +namespace Poco { +namespace Net { + + +class HTTPSession; + + +class Net_API HTTPStreamBuf: public HTTPBasicStreamBuf + /// This is the streambuf class used for reading and writing + /// HTTP message bodies. +{ +public: + typedef HTTPBasicStreamBuf::openmode openmode; + + HTTPStreamBuf(HTTPSession& session, openmode mode); + ~HTTPStreamBuf(); + void close(); + +protected: + int readFromDevice(char* buffer, std::streamsize length); + int writeToDevice(const char* buffer, std::streamsize length); + +private: + HTTPSession& _session; + openmode _mode; +}; + + +class Net_API HTTPIOS: public virtual std::ios + /// The base class for HTTPInputStream. +{ +public: + HTTPIOS(HTTPSession& session, HTTPStreamBuf::openmode mode); + ~HTTPIOS(); + HTTPStreamBuf* rdbuf(); + +protected: + HTTPStreamBuf _buf; +}; + + +class Net_API HTTPInputStream: public HTTPIOS, public std::istream + /// This class is for internal use by HTTPSession only. +{ +public: + HTTPInputStream(HTTPSession& session); + ~HTTPInputStream(); + + void* operator new(std::size_t size); + void operator delete(void* ptr); + +private: + static Poco::MemoryPool _pool; +}; + + +class Net_API HTTPOutputStream: public HTTPIOS, public std::ostream + /// This class is for internal use by HTTPSession only. +{ +public: + HTTPOutputStream(HTTPSession& session); + ~HTTPOutputStream(); + + void* operator new(std::size_t size); + void operator delete(void* ptr); + +private: + static Poco::MemoryPool _pool; +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPStream_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HTTPStreamFactory.h b/contrib/libs/poco/Net/include/Poco/Net/HTTPStreamFactory.h new file mode 100644 index 0000000000..df4a5f3336 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HTTPStreamFactory.h @@ -0,0 +1,92 @@ +// +// HTTPStreamFactory.h +// +// Library: Net +// Package: HTTP +// Module: HTTPStreamFactory +// +// Definition of the HTTPStreamFactory class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HTTPStreamFactory_INCLUDED +#define Net_HTTPStreamFactory_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPSession.h" +#include "Poco/URIStreamFactory.h" + + +namespace Poco { +namespace Net { + + +class Net_API HTTPStreamFactory: public Poco::URIStreamFactory + /// An implementation of the URIStreamFactory interface + /// that handles Hyper-Text Transfer Protocol (http) URIs. +{ +public: + HTTPStreamFactory(); + /// Creates the HTTPStreamFactory. + + HTTPStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort = HTTPSession::HTTP_PORT); + /// Creates the HTTPStreamFactory. + /// + /// HTTP connections will use the given proxy. + + HTTPStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort, const std::string& proxyUsername, const std::string& proxyPassword); + /// Creates the HTTPStreamFactory. + /// + /// HTTP connections will use the given proxy and + /// will be authorized against the proxy using Basic authentication + /// with the given proxyUsername and proxyPassword. + + virtual ~HTTPStreamFactory(); + /// Destroys the HTTPStreamFactory. + + virtual std::istream* open(const Poco::URI& uri); + /// Creates and opens a HTTP stream for the given URI. + /// The URI must be a http://... URI. + /// + /// Throws a NetException if anything goes wrong. + /// + /// Redirect responses are handled and the redirect + /// location is automatically resolved, as long + /// as the redirect location is still accessible + /// via the HTTP protocol. If a redirection to + /// a non http://... URI is received, a + /// UnsupportedRedirectException exception is thrown. + /// The offending URI can then be obtained via the message() + /// method of UnsupportedRedirectException. + + static void registerFactory(); + /// Registers the HTTPStreamFactory with the + /// default URIStreamOpener instance. + + static void unregisterFactory(); + /// Unregisters the HTTPStreamFactory with the + /// default URIStreamOpener instance. + +private: + enum + { + MAX_REDIRECTS = 10 + }; + + std::string _proxyHost; + Poco::UInt16 _proxyPort; + std::string _proxyUsername; + std::string _proxyPassword; +}; + + +} } // namespace Poco::Net + + +#endif // Net_HTTPStreamFactory_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/HostEntry.h b/contrib/libs/poco/Net/include/Poco/Net/HostEntry.h new file mode 100644 index 0000000000..23cccdffb5 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/HostEntry.h @@ -0,0 +1,115 @@ +// +// HostEntry.h +// +// Library: Net +// Package: NetCore +// Module: HostEntry +// +// Definition of the HostEntry class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_HostEntry_INCLUDED +#define Net_HostEntry_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketDefs.h" +#include "Poco/Net/IPAddress.h" +#include <vector> + + +namespace Poco { +namespace Net { + + +class Net_API HostEntry + /// This class stores information about a host + /// such as host name, alias names and a list + /// of IP addresses. +{ +public: + typedef std::vector<std::string> AliasList; + typedef std::vector<IPAddress> AddressList; + + HostEntry(); + /// Creates an empty HostEntry. + + HostEntry(struct hostent* entry); + /// Creates the HostEntry from the data in a hostent structure. + +#if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO) + HostEntry(struct addrinfo* info); + /// Creates the HostEntry from the data in an addrinfo structure. +#endif + +#if defined(POCO_VXWORKS) + HostEntry(const std::string& name, const IPAddress& addr); +#endif + + HostEntry(const HostEntry& entry); + /// Creates the HostEntry by copying another one. + + HostEntry& operator = (const HostEntry& entry); + /// Assigns another HostEntry. + + void swap(HostEntry& hostEntry); + /// Swaps the HostEntry with another one. + + ~HostEntry(); + /// Destroys the HostEntry. + + const std::string& name() const; + /// Returns the canonical host name. + + const AliasList& aliases() const; + /// Returns a vector containing alias names for + /// the host name. + + const AddressList& addresses() const; + /// Returns a vector containing the IPAddresses + /// for the host. + +private: + std::string _name; + AliasList _aliases; + AddressList _addresses; +}; + + +// +// inlines +// +inline const std::string& HostEntry::name() const +{ + return _name; +} + + +inline const HostEntry::AliasList& HostEntry::aliases() const +{ + return _aliases; +} + + +inline const HostEntry::AddressList& HostEntry::addresses() const +{ + return _addresses; +} + + +inline void swap(HostEntry& h1, HostEntry& h2) +{ + h1.swap(h2); +} + + +} } // namespace Poco::Net + + +#endif // Net_HostEntry_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/ICMPClient.h b/contrib/libs/poco/Net/include/Poco/Net/ICMPClient.h new file mode 100644 index 0000000000..31fb5202af --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/ICMPClient.h @@ -0,0 +1,97 @@ +// +// ICMPClient.h +// +// Library: Net +// Package: ICMP +// Module: ICMPClient +// +// Definition of the ICMPClient class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_ICMPClient_INCLUDED +#define Net_ICMPClient_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/ICMPSocket.h" +#include "Poco/Net/ICMPEventArgs.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/BasicEvent.h" + + +namespace Poco { +namespace Net { + + +class Net_API ICMPClient + /// This class provides ICMP Ping functionality. + /// + /// The events are available when class is instantiated + /// and non-static member functions are called. + /// + /// A "lightweight" alternative is direct (without instantiation) + /// use of static member functions. +{ +public: + mutable Poco::BasicEvent<ICMPEventArgs> pingBegin; + mutable Poco::BasicEvent<ICMPEventArgs> pingReply; + mutable Poco::BasicEvent<ICMPEventArgs> pingError; + mutable Poco::BasicEvent<ICMPEventArgs> pingEnd; + + explicit ICMPClient(SocketAddress::Family family, int dataSize = 48, int ttl = 128, int timeout = 50000); + /// Creates an ICMP client. + + ~ICMPClient(); + /// Destroys the ICMP client. + + int ping(SocketAddress& address, int repeat = 1) const; + /// Pings the specified address [repeat] times. + /// Notifications are posted for events. + /// + /// Returns the number of valid replies. + + int ping(const std::string& address, int repeat = 1) const; + /// Calls ICMPClient::ping(SocketAddress&, int) and + /// returns the result. + /// + /// Returns the number of valid replies. + + static int ping(SocketAddress& address, + SocketAddress::Family family, + int repeat = 1, + int dataSize = 48, + int ttl = 128, + int timeout = 50000); + /// Pings the specified address [repeat] times. + /// Notifications are not posted for events. + /// + /// Returns the number of valid replies. + + static int pingIPv4(const std::string& address, + int repeat = 1, + int dataSize = 48, + int ttl = 128, + int timeout = 50000); + /// Calls ICMPClient::ping(SocketAddress&, int) and + /// returns the result. + /// + /// Returns the number of valid replies. + +private: + mutable SocketAddress::Family _family; + int _dataSize; + int _ttl; + int _timeout; +}; + + +} } // namespace Poco::Net + + +#endif // Net_ICMPClient_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/ICMPEventArgs.h b/contrib/libs/poco/Net/include/Poco/Net/ICMPEventArgs.h new file mode 100644 index 0000000000..2a663eb32f --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/ICMPEventArgs.h @@ -0,0 +1,163 @@ +// +// ICMPEventArgs.h +// +// Library: Net +// Package: ICMP +// Module: ICMPEventArgs +// +// Definition of ICMPEventArgs. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_ICMPEventArgs_INCLUDED +#define Net_ICMPEventArgs_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketAddress.h" +#include <vector> +#include <algorithm> + + +namespace Poco { +namespace Net { + + +class Net_API ICMPEventArgs + /// The purpose of the ICMPEventArgs class is to be used as template parameter + /// to instantiate event members in ICMPClient class. + /// When clients register for an event notification, the reference to the class is + /// passed to the handler function to provide information about the event. +{ +public: + ICMPEventArgs(const SocketAddress& address, int repetitions, int dataSize, int ttl); + /// Creates ICMPEventArgs. + + virtual ~ICMPEventArgs(); + /// Destroys ICMPEventArgs. + + std::string hostName() const; + /// Tries to resolve the target IP address into host name. + /// If unsuccessful, all exceptions are silently ignored and + /// the IP address is returned. + + std::string hostAddress() const; + /// Returns the target IP address. + + int repetitions() const; + /// Returns the number of repetitions for the ping operation. + + int dataSize() const; + /// Returns the packet data size in bytes. + + int ttl() const; + /// Returns time to live. + + int sent() const; + /// Returns the number of packets sent. + + int received() const; + /// Returns the number of packets received. + + int replyTime(int index = -1) const; + /// Returns the reply time for the request specified with index. + /// If index == -1 (default), returns the most recent reply time. + + const std::string& error(int index = -1) const; + /// Returns the error string for the request specified with index. + /// If index == -1 (default), returns the most recent error string. + + int minRTT() const; + /// Returns the minimum round trip time for a sequence of requests. + + int maxRTT() const; + /// Returns the maximum round trip time for a sequence of requests. + + int avgRTT() const; + /// Returns the average round trip time for a sequence of requests. + + float percent() const; + /// Returns the success percentage for a sequence of requests. + +private: + ICMPEventArgs(); + + void setRepetitions(int repetitions); + void setDataSize(int sz); + void setTTL(int timeToLive); + void setReplyTime(int index, int time); + void setError(int index, const std::string& text); + ICMPEventArgs& operator ++ (); + ICMPEventArgs operator ++ (int); + + SocketAddress _address; + int _sent; + int _dataSize; + int _ttl; + std::vector<int> _rtt; + std::vector<std::string> _errors; + + friend class ICMPClient; +}; + + +// +// inlines +// +inline int ICMPEventArgs::repetitions() const +{ + return (int) _rtt.size(); +} + + +inline void ICMPEventArgs::setDataSize(int sz) +{ + _dataSize = sz; +} + + +inline int ICMPEventArgs::dataSize() const +{ + return _dataSize; +} + + +inline void ICMPEventArgs::setTTL(int timeToLive) +{ + _ttl = timeToLive; +} + + +inline int ICMPEventArgs::ttl() const +{ + return _ttl; +} + + +inline int ICMPEventArgs::sent() const +{ + return _sent; +} + + +inline int ICMPEventArgs::minRTT() const +{ + return *std::min_element(_rtt.begin(), _rtt.end()); +} + + +inline int ICMPEventArgs::maxRTT() const +{ + return *std::max_element(_rtt.begin(), _rtt.end()); +} + + +} } // namespace Poco::Net + + +#endif diff --git a/contrib/libs/poco/Net/include/Poco/Net/ICMPPacket.h b/contrib/libs/poco/Net/include/Poco/Net/ICMPPacket.h new file mode 100644 index 0000000000..52d0e87f87 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/ICMPPacket.h @@ -0,0 +1,89 @@ +// +// ICMPPacket.h +// +// Library: Net +// Package: ICMP +// Module: ICMPPacket +// +// Definition of the ICMPPacket class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_ICMPPacket_INCLUDED +#define Net_ICMPPacket_INCLUDED + + +#include "Poco/Foundation.h" +#include "Poco/Net/Socket.h" +#include "Poco/Net/ICMPPacketImpl.h" + + +namespace Poco { +namespace Net { + + +class Net_API ICMPPacket + /// This class is the ICMP packet abstraction. +{ +public: + ICMPPacket(SocketAddress::Family family, int dataSize = 48); + /// Creates an ICMPPacket of specified family. + + ~ICMPPacket(); + /// Destroys the ICMPPacket. + + const Poco::UInt8* packet(); + /// Returns raw ICMP packet. ICMP header and data are included in the returned packet. + + int packetSize() const; + /// Returns the total length of packet (header + data); + + Poco::UInt16 sequence() const; + /// Returns the most recent sequence number generated. + + void setDataSize(int dataSize); + /// Sets data size. + + int getDataSize() const; + /// Returns data size. + + int maxPacketSize() const; + /// Returns the total length of packet (header + data); + + struct timeval time(Poco::UInt8* buffer = 0, int length = 0) const; + /// Returns current epoch time if either buffer or length are equal to zero. + /// Otherwise, it extracts the time value from the supplied buffer and + /// returns the extracted value. + /// + /// Supplied buffer includes IP header, ICMP header and data. + + bool validReplyID(Poco::UInt8* buffer, int length) const; + /// Returns true if the extracted id is recognized + /// (equals the process id). + /// + /// Supplied buffer includes IP header, ICMP header and data. + + std::string errorDescription(Poco::UInt8* buffer, int length); + /// Returns error description string. + /// If supplied buffer contains an ICMP echo reply packet, an + /// empty string is returned indicating the absence of error. + /// + /// Supplied buffer includes IP header, ICMP header and data. + + std::string typeDescription(int typeId); + /// Returns the description of the packet type. + +private: + ICMPPacketImpl* _pImpl; +}; + + +} } // namespace Poco::Net + + +#endif // Net_ICMPPacket_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/ICMPPacketImpl.h b/contrib/libs/poco/Net/include/Poco/Net/ICMPPacketImpl.h new file mode 100644 index 0000000000..da6bf46484 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/ICMPPacketImpl.h @@ -0,0 +1,141 @@ +// +// ICMPPacketImpl.h +// +// Library: Net +// Package: ICMP +// Module: ICMPPacketImpl +// +// Definition of the ICMPPacketImpl class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_ICMPPacketImpl_INCLUDED +#define Net_ICMPPacketImpl_INCLUDED + + +#include "Poco/Foundation.h" +#include "Poco/Net/Socket.h" + + +namespace Poco { +namespace Net { + + +class Net_API ICMPPacketImpl + /// This is the abstract class for ICMP packet implementations. +{ +public: + ICMPPacketImpl(int dataSize = 48); + /// Constructor. Creates an ICMPPacketImpl. + + virtual ~ICMPPacketImpl(); + /// Destructor. + + const Poco::UInt8* packet(bool init = true); + /// Returns raw ICMP packet. + /// ICMP header and data are included in the packet. + /// If init is true, initPacket() is called. + + virtual int packetSize() const = 0; + /// Returns the total size of packet (ICMP header + data) in number of octets. + /// Must be overriden. + + virtual int maxPacketSize() const; + /// Returns the maximum permitted size of packet in number of octets. + + Poco::UInt16 sequence() const; + /// Returns the most recent sequence number generated. + + void setDataSize(int dataSize); + /// Sets data size. + + int getDataSize() const; + /// Returns data size. + + virtual struct timeval time(Poco::UInt8* buffer = 0, int length = 0) const = 0; + /// Returns current epoch time if either argument is equal to zero. + /// Otherwise, it extracts the time value from the supplied buffer. + /// + /// Supplied buffer includes IP header, ICMP header and data. + /// Must be overriden. + + virtual bool validReplyID(unsigned char* buffer, int length) const = 0; + /// Returns true if the extracted id is recognized + /// (i.e. equals the process id). + /// + /// Supplied buffer includes IP header, ICMP header and data. + /// Must be overriden. + + virtual std::string errorDescription(Poco::UInt8* buffer, int length) = 0; + /// Returns error description string. + /// If supplied buffer contains an ICMP echo reply packet, an + /// empty string is returned indicating the absence of error. + /// + /// Supplied buffer includes IP header, ICMP header and data. + /// Must be overriden. + + virtual std::string typeDescription(int typeId) = 0; + /// Returns the description of the packet type. + /// Must be overriden. + + static const Poco::UInt16 MAX_PACKET_SIZE; + static const Poco::UInt16 MAX_SEQ_VALUE; + +protected: + Poco::UInt16 nextSequence(); + /// Increments sequence number and returns the new value. + + void resetSequence(); + /// Resets the sequence to zero. + + virtual void initPacket() = 0; + /// (Re)assembles the packet. + /// Must be overriden. + + Poco::UInt16 checksum(Poco::UInt16 *addr, Poco::Int32 len); + /// Calculates the checksum for supplied buffer. + +private: + Poco::UInt16 _seq; + Poco::UInt8* _pPacket; + int _dataSize; + +}; + + +// +// inlines +// +inline Poco::UInt16 ICMPPacketImpl::sequence() const +{ + return _seq; +} + + +inline Poco::UInt16 ICMPPacketImpl::nextSequence() +{ + return ++_seq; +} + + +inline void ICMPPacketImpl::resetSequence() +{ + _seq = 0; +} + + +inline int ICMPPacketImpl::maxPacketSize() const +{ + return MAX_PACKET_SIZE; +} + + +} } // namespace Poco::Net + + +#endif // Net_ICMPPacketImpl_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/ICMPSocket.h b/contrib/libs/poco/Net/include/Poco/Net/ICMPSocket.h new file mode 100644 index 0000000000..75e049b382 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/ICMPSocket.h @@ -0,0 +1,91 @@ +// +// ICMPSocket.h +// +// Library: Net +// Package: ICMP +// Module: ICMPSocket +// +// Definition of the ICMPSocket class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_ICMPSocket_INCLUDED +#define Net_ICMPSocket_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/Socket.h" + + +namespace Poco { +namespace Net { + + +class Net_API ICMPSocket: public Socket + /// This class provides an interface to an + /// ICMP client socket. +{ +public: + ICMPSocket(SocketAddress::Family family, int dataSize = 48, int ttl = 128, int timeout = 5000000); + /// Creates an unconnected ICMP socket. + /// + /// The socket will be created for the + /// given address family. + + ICMPSocket(const Socket& socket); + /// Creates the ICMPSocket with the SocketImpl + /// from another socket. The SocketImpl must be + /// a ICMPSocketImpl, otherwise an InvalidArgumentException + /// will be thrown. + + ~ICMPSocket(); + /// Destroys the ICMPSocket. + + ICMPSocket& operator = (const Socket& socket); + /// Assignment operator. + /// + /// Releases the socket's SocketImpl and + /// attaches the SocketImpl from the other socket and + /// increments the reference count of the SocketImpl. + + int sendTo(const SocketAddress& address, int flags = 0); + /// Sends an ICMP request through + /// the socket to the given address. + /// + /// Returns the number of bytes sent. + + int receiveFrom(SocketAddress& address, int flags = 0); + /// Receives data from the socket. + /// Stores the address of the sender in address. + /// + /// Returns the time elapsed since the originating + /// request was sent. + + int dataSize() const; + /// Returns the data size in bytes. + + int ttl() const; + /// Returns the Time-To-Live value. + + int timeout() const; + /// Returns the socket timeout value. + +protected: + ICMPSocket(SocketImpl* pImpl); + /// Creates the Socket and attaches the given SocketImpl. + /// The socket takes ownership of the SocketImpl. + /// + /// The SocketImpl must be a ICMPSocketImpl, otherwise + /// an InvalidArgumentException will be thrown. +}; + + +} } // namespace Poco::Net + + +#endif // Net_ICMPSocket_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/ICMPSocketImpl.h b/contrib/libs/poco/Net/include/Poco/Net/ICMPSocketImpl.h new file mode 100644 index 0000000000..98ba9a2259 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/ICMPSocketImpl.h @@ -0,0 +1,94 @@ +// +// ICMPSocketImpl.h +// +// Library: Net +// Package: ICMP +// Module: ICMPSocketImpl +// +// Definition of the ICMPSocketImpl class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_ICMPSocketImpl_INCLUDED +#define Net_ICMPSocketImpl_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/RawSocketImpl.h" +#include "Poco/Net/ICMPPacket.h" +#include "Poco/Timestamp.h" + + +namespace Poco { +namespace Net { + + +class Net_API ICMPSocketImpl: public RawSocketImpl + /// This class implements an ICMP socket. +{ +public: + ICMPSocketImpl(SocketAddress::Family family, int dataSize, int ttl, int timeout); + /// Creates an unconnected ICMP socket. + /// + /// The socket will be created for the given address family. + + int sendTo(const void*, int, const SocketAddress& address, int flags = 0); + /// Sends an ICMP request through the socket to the given address. + /// + /// Returns the number of bytes sent. + + int receiveFrom(void*, int, SocketAddress& address, int flags = 0); + /// Receives data from the socket. + /// Stores the address of the sender in address. + /// + /// Returns the time elapsed since the originating request was sent. + + int dataSize() const; + /// Returns the data size in bytes. + + int ttl() const; + /// Returns the Time-To-Live value. + + int timeout() const; + /// Returns the socket timeout value. + +protected: + ~ICMPSocketImpl(); + +private: + ICMPPacket _icmpPacket; + int _ttl; + int _timeout; +}; + + +// +// inlines +// +inline int ICMPSocketImpl::dataSize() const +{ + return _icmpPacket.getDataSize(); +} + + +inline int ICMPSocketImpl::ttl() const +{ + return _ttl; +} + + +inline int ICMPSocketImpl::timeout() const +{ + return _timeout; +} + + +} } // namespace Poco::Net + + +#endif // Net_ICMPSocketImpl_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/ICMPv4PacketImpl.h b/contrib/libs/poco/Net/include/Poco/Net/ICMPv4PacketImpl.h new file mode 100644 index 0000000000..116f8c7617 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/ICMPv4PacketImpl.h @@ -0,0 +1,173 @@ +// +// ICMPv4PacketImpl.h +// +// Library: Net +// Package: ICMP +// Module: ICMPv4PacketImpl +// +// Definition of the ICMPv4PacketImpl class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_ICMPv4PacketImpl_INCLUDED +#define Net_ICMPv4PacketImpl_INCLUDED + + +#include "Poco/Foundation.h" +#include "Poco/Net/Socket.h" +#include "Poco/Net/ICMPPacketImpl.h" +#include <cstddef> + + +namespace Poco { +namespace Net { + + +class Net_API ICMPv4PacketImpl : public ICMPPacketImpl + /// This class implements the ICMPv4 packet. + /// Parts are based on original ICMP code by + /// Mike Muuss + /// U. S. Army Ballistic Research Laboratory + /// December, 1983 +{ +public: + // ICMPv4 header + struct Header + { + Poco::UInt8 type; // ICMP packet type + Poco::UInt8 code; // Type sub code + Poco::UInt16 checksum; + Poco::UInt16 id; + Poco::UInt16 seq; + }; + + // compile-time shield against misalignment +#if POCO_OS != POCO_OS_ANDROID + poco_static_assert (offsetof(Header, code) == 0x01); + poco_static_assert (offsetof(Header, checksum) == 0x02); + poco_static_assert (offsetof(Header, id) == 0x04); + poco_static_assert (offsetof(Header, seq) == 0x06); +#endif + + enum MessageType + { + ECHO_REPLY, + ICMP_1, + ICMP_2, + DESTINATION_UNREACHABLE, + SOURCE_QUENCH, + REDIRECT, + ICMP_6, + ICMP_7, + ECHO_REQUEST, + ICMP_9, + ICMP_10, + TIME_EXCEEDED, + PARAMETER_PROBLEM, + TIMESTAMP_REQUEST, + TIMESTAMP_REPLY, + INFORMATION_REQUEST, + INFORMATION_REPLY, + MESSAGE_TYPE_UNKNOWN, // non-standard default, must remain last but one + MESSAGE_TYPE_LENGTH // length indicator, must remain last + }; + + enum DestinationUnreachableCode + { + NET_UNREACHABLE, + HOST_UNREACHABLE, + PROTOCOL_UNREACHABLE, + PORT_UNREACHABLE, + FRAGMENTATION_NEEDED_AND_DF_SET, + SOURCE_ROUTE_FAILED, + DESTINATION_UNREACHABLE_UNKNOWN, // non-standard default, must remain last but one + DESTINATION_UNREACHABLE_LENGTH // length indicator, must remain last + }; + + enum RedirectMessageCode + { + REDIRECT_NETWORK, + REDIRECT_HOST, + REDIRECT_SERVICE_NETWORK, + REDIRECT_SERVICE_HOST, + REDIRECT_MESSAGE_UNKNOWN, // non-standard default, must remain last but one + REDIRECT_MESSAGE_LENGTH // length indicator, must remain last + }; + + enum TimeExceededCode + { + TIME_TO_LIVE, + FRAGMENT_REASSEMBLY, + TIME_EXCEEDED_UNKNOWN, // non-standard default, must remain last but one + TIME_EXCEEDED_LENGTH // length indicator, must remain last + }; + + enum ParameterProblemCode + { + POINTER_INDICATES_THE_ERROR, + PARAMETER_PROBLEM_UNKNOWN, // non-standard default, must remain last but one + PARAMETER_PROBLEM_LENGTH // length indicator, must remain last + }; + + ICMPv4PacketImpl(int dataSize = 48); + /// Constructor. Creates an ICMPv4PacketImpl. + + ~ICMPv4PacketImpl(); + /// Destructor. + + int packetSize() const; + /// Returns the total length of packet (header + data); + + struct timeval time(Poco::UInt8* buffer = 0, int length = 0) const; + /// Returns current epoch time if either buffer or length are equal to zero. + /// Otherwise, it extracts the time value from the supplied buffer. + /// + /// Buffer includes IP header, ICMP header and data. + + bool validReplyID(Poco::UInt8* buffer, int length) const; + /// Returns true if the extracted id is recognized + /// (i.e. equals the process id). + /// + /// Buffer includes IP header, ICMP header and data. + + virtual std::string errorDescription(Poco::UInt8* buffer, int length); + /// Returns error description string. + /// If supplied buffer contains ICMPv4 echo reply packet, an + /// empty string is returned indicating the absence of error. + /// + /// Buffer includes IP header, ICMP header and data. + + virtual std::string typeDescription(int typeId); + /// Returns the description of the packet type. + + static const Poco::UInt16 MAX_PACKET_SIZE; + static const std::string MESSAGE_TYPE[MESSAGE_TYPE_LENGTH]; + static const Poco::UInt8 DESTINATION_UNREACHABLE_TYPE; // 3 + static const Poco::UInt8 SOURCE_QUENCH_TYPE; // 4 + static const Poco::UInt8 REDIRECT_MESSAGE_TYPE; // 5 + static const Poco::UInt8 TIME_EXCEEDED_TYPE; // 11 + static const Poco::UInt8 PARAMETER_PROBLEM_TYPE; // 12 + +private: + void initPacket(); + Header* header(Poco::UInt8* buffer, int length) const; + Poco::UInt8* data(Poco::UInt8* buffer, int length) const; + + static const std::string DESTINATION_UNREACHABLE_CODE[DESTINATION_UNREACHABLE_LENGTH]; + static const std::string REDIRECT_MESSAGE_CODE[REDIRECT_MESSAGE_LENGTH]; + static const std::string TIME_EXCEEDED_CODE[TIME_EXCEEDED_LENGTH]; + static const std::string PARAMETER_PROBLEM_CODE[PARAMETER_PROBLEM_LENGTH]; + + Poco::UInt16 _seq; +}; + + +} } // namespace Poco::Net + + +#endif // Net_ICMPv4PacketImpl_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/IPAddress.h b/contrib/libs/poco/Net/include/Poco/Net/IPAddress.h new file mode 100644 index 0000000000..7d9cb6fa83 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/IPAddress.h @@ -0,0 +1,450 @@ +// +// IPAddress.h +// +// Library: Net +// Package: NetCore +// Module: IPAddress +// +// Definition of the IPAddress class. +// +// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_IPAddress_INCLUDED +#define Net_IPAddress_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketDefs.h" +#include "Poco/Net/IPAddressImpl.h" +#include "Poco/AutoPtr.h" +#include "Poco/Exception.h" +#include <vector> +#include <ostream> + + +namespace Poco { + +class BinaryReader; +class BinaryWriter; + +namespace Net { + + +class Net_API IPAddress + /// This class represents an internet (IP) host + /// address. The address can belong either to the + /// IPv4 or the IPv6 address family. + /// + /// Relational operators (==, !=, <, <=, >, >=) are + /// supported. However, you must not interpret any + /// special meaning into the result of these + /// operations, other than that the results are + /// consistent. + /// + /// Especially, an IPv4 address is never equal to + /// an IPv6 address, even if the IPv6 address is + /// IPv4 compatible and the addresses are the same. + /// + /// IPv6 addresses are supported only if the target platform + /// supports IPv6. +{ +public: + typedef std::vector<IPAddress> List; + + // The following declarations keep the Family type + // backwards compatible with the previously used + // enum declaration. + typedef AddressFamily::Family Family; + static const Family IPv4 = AddressFamily::IPv4; +#if defined(POCO_HAVE_IPv6) + static const Family IPv6 = AddressFamily::IPv6; +#endif + + IPAddress(); + /// Creates a wildcard (zero) IPv4 IPAddress. + + IPAddress(const IPAddress& addr); + /// Creates an IPAddress by copying another one. + + explicit IPAddress(Family family); + /// Creates a wildcard (zero) IPAddress for the + /// given address family. + + explicit IPAddress(const std::string& addr); + /// Creates an IPAddress from the string containing + /// an IP address in presentation format (dotted decimal + /// for IPv4, hex string for IPv6). + /// + /// Depending on the format of addr, either an IPv4 or + /// an IPv6 address is created. + /// + /// See toString() for details on the supported formats. + /// + /// Throws an InvalidAddressException if the address cannot be parsed. + + IPAddress(const std::string& addr, Family family); + /// Creates an IPAddress from the string containing + /// an IP address in presentation format (dotted decimal + /// for IPv4, hex string for IPv6). + + IPAddress(const void* addr, poco_socklen_t length); + /// Creates an IPAddress from a native internet address. + /// A pointer to a in_addr or a in6_addr structure may be + /// passed. + + IPAddress(const void* addr, poco_socklen_t length, Poco::UInt32 scope); + /// Creates an IPAddress from a native internet address. + /// A pointer to a in_addr or a in6_addr structure may be + /// passed. Additionally, for an IPv6 address, a scope ID + /// may be specified. The scope ID will be ignored if an IPv4 + /// address is specified. + + IPAddress(unsigned prefix, Family family); + /// Creates an IPAddress mask with the given length of prefix. + +#if defined(_WIN32) + IPAddress(const SOCKET_ADDRESS& socket_address); + /// Creates an IPAddress from Windows SOCKET_ADDRESS structure. +#endif + + IPAddress(const struct sockaddr& sockaddr); + /// Same for struct sock_addr on POSIX. + + + ~IPAddress(); + /// Destroys the IPAddress. + + IPAddress& operator = (const IPAddress& addr); + /// Assigns an IPAddress. + + Family family() const; + /// Returns the address family (IPv4 or IPv6) of the address. + + Poco::UInt32 scope() const; + /// Returns the IPv6 scope identifier of the address. Returns 0 if + /// the address is an IPv4 address, or the address is an + /// IPv6 address but does not have a scope identifier. + + std::string toString() const; + /// Returns a string containing a representation of the address + /// in presentation format. + /// + /// For IPv4 addresses the result will be in dotted-decimal + /// (d.d.d.d) notation. + /// + /// Textual representation of IPv6 address is one of the following forms: + /// + /// The preferred form is x:x:x:x:x:x:x:x, where the 'x's are the hexadecimal + /// values of the eight 16-bit pieces of the address. This is the full form. + /// Example: 1080:0:0:0:8:600:200A:425C + /// + /// It is not necessary to write the leading zeros in an individual field. + /// However, there must be at least one numeral in every field, except as described below. + /// + /// It is common for IPv6 addresses to contain long strings of zero bits. + /// In order to make writing addresses containing zero bits easier, a special syntax is + /// available to compress the zeros. The use of "::" indicates multiple groups of 16-bits of zeros. + /// The "::" can only appear once in an address. The "::" can also be used to compress the leading + /// and/or trailing zeros in an address. Example: 1080::8:600:200A:425C + /// + /// For dealing with IPv4 compatible addresses in a mixed environment, + /// a special syntax is available: x:x:x:x:x:x:d.d.d.d, where the 'x's are the + /// hexadecimal values of the six high-order 16-bit pieces of the address, + /// and the 'd's are the decimal values of the four low-order 8-bit pieces of the + /// standard IPv4 representation address. Example: ::FFFF:192.168.1.120 + /// + /// If an IPv6 address contains a non-zero scope identifier, it is added + /// to the string, delimited by a percent character. On Windows platforms, + /// the numeric value (which specifies an interface index) is directly + /// appended. On Unix platforms, the name of the interface corresponding + /// to the index (interpretation of the scope identifier) is added. + + bool isWildcard() const; + /// Returns true iff the address is a wildcard (all zero) + /// address. + + bool isBroadcast() const; + /// Returns true iff the address is a broadcast address. + /// + /// Only IPv4 addresses can be broadcast addresses. In a broadcast + /// address, all bits are one. + /// + /// For an IPv6 address, returns always false. + + bool isLoopback() const; + /// Returns true iff the address is a loopback address. + /// + /// For IPv4, the loopback address is 127.0.0.1. + /// + /// For IPv6, the loopback address is ::1. + + bool isMulticast() const; + /// Returns true iff the address is a multicast address. + /// + /// IPv4 multicast addresses are in the + /// 224.0.0.0 to 239.255.255.255 range + /// (the first four bits have the value 1110). + /// + /// IPv6 multicast addresses are in the + /// FFxx:x:x:x:x:x:x:x range. + + bool isUnicast() const; + /// Returns true iff the address is a unicast address. + /// + /// An address is unicast if it is neither a wildcard, + /// broadcast or multicast address. + + bool isLinkLocal() const; + /// Returns true iff the address is a link local unicast address. + /// + /// IPv4 link local addresses are in the 169.254.0.0/16 range, + /// according to RFC 3927. + /// + /// IPv6 link local addresses have 1111 1110 10 as the first + /// 10 bits, followed by 54 zeros. + + bool isSiteLocal() const; + /// Returns true iff the address is a site local unicast address. + /// + /// IPv4 site local addresses are in on of the 10.0.0.0/24, + /// 192.168.0.0/16 or 172.16.0.0 to 172.31.255.255 ranges. + /// + /// Originally, IPv6 site-local addresses had FEC0/10 (1111 1110 11) + /// prefix (RFC 4291), followed by 38 zeros. Interfaces using + /// this mask are supported, but obsolete; RFC 4193 prescribes + /// fc00::/7 (1111 110) as local unicast prefix. + + bool isIPv4Compatible() const; + /// Returns true iff the address is IPv4 compatible. + /// + /// For IPv4 addresses, this is always true. + /// + /// For IPv6, the address must be in the ::x:x range (the + /// first 96 bits are zero). + + bool isIPv4Mapped() const; + /// Returns true iff the address is an IPv4 mapped IPv6 address. + /// + /// For IPv4 addresses, this is always true. + /// + /// For IPv6, the address must be in the ::FFFF:x:x range. + + bool isWellKnownMC() const; + /// Returns true iff the address is a well-known multicast address. + /// + /// For IPv4, well-known multicast addresses are in the + /// 224.0.0.0/8 range. + /// + /// For IPv6, well-known multicast addresses are in the + /// FF0x:x:x:x:x:x:x:x range. + + bool isNodeLocalMC() const; + /// Returns true iff the address is a node-local multicast address. + /// + /// IPv4 does not support node-local addresses, thus the result is + /// always false for an IPv4 address. + /// + /// For IPv6, node-local multicast addresses are in the + /// FFx1:x:x:x:x:x:x:x range. + + bool isLinkLocalMC() const; + /// Returns true iff the address is a link-local multicast address. + /// + /// For IPv4, link-local multicast addresses are in the + /// 224.0.0.0/24 range. Note that this overlaps with the range for well-known + /// multicast addresses. + /// + /// For IPv6, link-local multicast addresses are in the + /// FFx2:x:x:x:x:x:x:x range. + + bool isSiteLocalMC() const; + /// Returns true iff the address is a site-local multicast address. + /// + /// For IPv4, site local multicast addresses are in the + /// 239.255.0.0/16 range. + /// + /// For IPv6, site-local multicast addresses are in the + /// FFx5:x:x:x:x:x:x:x range. + + bool isOrgLocalMC() const; + /// Returns true iff the address is a organization-local multicast address. + /// + /// For IPv4, organization-local multicast addresses are in the + /// 239.192.0.0/16 range. + /// + /// For IPv6, organization-local multicast addresses are in the + /// FFx8:x:x:x:x:x:x:x range. + + bool isGlobalMC() const; + /// Returns true iff the address is a global multicast address. + /// + /// For IPv4, global multicast addresses are in the + /// 224.0.1.0 to 238.255.255.255 range. + /// + /// For IPv6, global multicast addresses are in the + /// FFxF:x:x:x:x:x:x:x range. + + bool operator == (const IPAddress& addr) const; + bool operator != (const IPAddress& addr) const; + bool operator < (const IPAddress& addr) const; + bool operator <= (const IPAddress& addr) const; + bool operator > (const IPAddress& addr) const; + bool operator >= (const IPAddress& addr) const; + IPAddress operator & (const IPAddress& addr) const; + IPAddress operator | (const IPAddress& addr) const; + IPAddress operator ^ (const IPAddress& addr) const; + IPAddress operator ~ () const; + + poco_socklen_t length() const; + /// Returns the length in bytes of the internal socket address structure. + + const void* addr() const; + /// Returns the internal address structure. + + int af() const; + /// Returns the address family (AF_INET or AF_INET6) of the address. + + unsigned prefixLength() const; + /// Returns the prefix length. + + void mask(const IPAddress& mask); + /// Masks the IP address using the given netmask, which is usually + /// a IPv4 subnet mask. Only supported for IPv4 addresses. + /// + /// The new address is (address & mask). + + void mask(const IPAddress& mask, const IPAddress& set); + /// Masks the IP address using the given netmask, which is usually + /// a IPv4 subnet mask. Only supported for IPv4 addresses. + /// + /// The new address is (address & mask) | (set & ~mask). + + static IPAddress parse(const std::string& addr); + /// Creates an IPAddress from the string containing + /// an IP address in presentation format (dotted decimal + /// for IPv4, hex string for IPv6). + /// + /// Depending on the format of addr, either an IPv4 or + /// an IPv6 address is created. + /// + /// See toString() for details on the supported formats. + /// + /// Throws an InvalidAddressException if the address cannot be parsed. + + static bool tryParse(const std::string& addr, IPAddress& result); + /// Tries to interpret the given address string as an + /// IP address in presentation format (dotted decimal + /// for IPv4, hex string for IPv6). + /// + /// Returns true and stores the IPAddress in result if the + /// string contains a valid address. + /// + /// Returns false and leaves result unchanged otherwise. + + static IPAddress wildcard(Family family = IPv4); + /// Returns a wildcard IPv4 or IPv6 address (0.0.0.0). + + static IPAddress broadcast(); + /// Returns a broadcast IPv4 address (255.255.255.255). + + enum + { + MAX_ADDRESS_LENGTH = +#if defined(POCO_HAVE_IPv6) + sizeof(struct in6_addr) +#else + sizeof(struct in_addr) +#endif + /// Maximum length in bytes of a socket address. + }; + +private: + typedef Poco::Net::Impl::IPAddressImpl Impl; + typedef Poco::AutoPtr<Impl> Ptr; + + Ptr pImpl() const; + void newIPv4(); + void newIPv4(const void* hostAddr); + void newIPv4(unsigned prefix); +#if defined(POCO_HAVE_IPv6) + void newIPv6(); + void newIPv6(const void* hostAddr); + void newIPv6(const void* hostAddr, Poco::UInt32 scope); + void newIPv6(unsigned prefix); +#endif + Ptr _pImpl; +}; + + +// +// inlines +// +inline IPAddress::Ptr IPAddress::pImpl() const +{ + if (_pImpl) return _pImpl; + throw NullPointerException("IPaddress implementation pointer is NULL."); +} + + +inline void IPAddress::newIPv4() +{ + _pImpl = new Poco::Net::Impl::IPv4AddressImpl; +} + + +inline void IPAddress::newIPv4(const void* hostAddr) +{ + _pImpl = new Poco::Net::Impl::IPv4AddressImpl(hostAddr); +} + + +inline void IPAddress::newIPv4(unsigned prefix) +{ + _pImpl = new Poco::Net::Impl::IPv4AddressImpl(prefix); +} + + +#if defined(POCO_HAVE_IPv6) + + +inline void IPAddress::newIPv6() +{ + _pImpl = new Poco::Net::Impl::IPv6AddressImpl; +} + + +inline void IPAddress::newIPv6(const void* hostAddr) +{ + _pImpl = new Poco::Net::Impl::IPv6AddressImpl(hostAddr); +} + + +inline void IPAddress::newIPv6(const void* hostAddr, Poco::UInt32 scope) +{ + _pImpl = new Poco::Net::Impl::IPv6AddressImpl(hostAddr, scope); +} + + +inline void IPAddress::newIPv6(unsigned prefix) +{ + _pImpl = new Poco::Net::Impl::IPv6AddressImpl(prefix); +} + + +#endif // POCO_HAVE_IPv6 + + +} } // namespace Poco::Net + + +Net_API Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::IPAddress& value); +Net_API Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::IPAddress& value); +Net_API std::ostream& operator << (std::ostream& ostr, const Poco::Net::IPAddress& addr); + + +#endif // Net_IPAddress_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/IPAddressImpl.h b/contrib/libs/poco/Net/include/Poco/Net/IPAddressImpl.h new file mode 100644 index 0000000000..e43d685509 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/IPAddressImpl.h @@ -0,0 +1,179 @@ +// +// IPAddressImpl.h +// +// Library: Net +// Package: NetCore +// Module: IPAddressImpl +// +// Definition of the IPAddressImpl class. +// +// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_IPAddressImpl_INCLUDED +#define Net_IPAddressImpl_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketDefs.h" +#include "Poco/RefCountedObject.h" +#include <vector> + + +namespace Poco { +namespace Net { +namespace Impl { + + +class IPAddressImpl : public Poco::RefCountedObject +{ +public: + typedef AddressFamily::Family Family; + + virtual ~IPAddressImpl(); + + virtual IPAddressImpl* clone() const = 0; + virtual std::string toString() const = 0; + virtual poco_socklen_t length() const = 0; + virtual const void* addr() const = 0; + virtual Family family() const = 0; + virtual int af() const = 0; + virtual Poco::UInt32 scope() const = 0; + virtual bool isWildcard() const = 0; + virtual bool isBroadcast() const = 0; + virtual bool isLoopback() const = 0; + virtual bool isMulticast() const = 0; + virtual bool isLinkLocal() const = 0; + virtual bool isSiteLocal() const = 0; + virtual bool isIPv4Mapped() const = 0; + virtual bool isIPv4Compatible() const = 0; + virtual bool isWellKnownMC() const = 0; + virtual bool isNodeLocalMC() const = 0; + virtual bool isLinkLocalMC() const = 0; + virtual bool isSiteLocalMC() const = 0; + virtual bool isOrgLocalMC() const = 0; + virtual bool isGlobalMC() const = 0; + virtual void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) = 0; + virtual unsigned prefixLength() const = 0; + +protected: + IPAddressImpl(); + +private: + IPAddressImpl(const IPAddressImpl&); + IPAddressImpl& operator = (const IPAddressImpl&); +}; + + +// +// IPv4AddressImpl +// + +class IPv4AddressImpl: public IPAddressImpl +{ +public: + IPv4AddressImpl(); + IPv4AddressImpl(const void* addr); + IPv4AddressImpl(unsigned prefix); + IPv4AddressImpl(const IPv4AddressImpl& addr); + IPv4AddressImpl& operator = (const IPv4AddressImpl&); + std::string toString() const; + poco_socklen_t length() const; + const void* addr() const; + Family family() const; + int af() const; + unsigned prefixLength() const; + Poco::UInt32 scope() const; + bool isWildcard() const; + bool isBroadcast() const; + bool isLoopback() const; + bool isMulticast() const; + bool isLinkLocal() const; + bool isSiteLocal() const; + bool isIPv4Compatible() const; + bool isIPv4Mapped() const; + bool isWellKnownMC() const; + bool isNodeLocalMC() const; + bool isLinkLocalMC() const; + bool isSiteLocalMC() const; + bool isOrgLocalMC() const; + bool isGlobalMC() const; + static IPv4AddressImpl parse(const std::string& addr); + void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet); + IPAddressImpl* clone() const; + IPv4AddressImpl operator & (const IPv4AddressImpl& addr) const; + IPv4AddressImpl operator | (const IPv4AddressImpl& addr) const; + IPv4AddressImpl operator ^ (const IPv4AddressImpl& addr) const; + IPv4AddressImpl operator ~ () const; + bool operator == (const IPv4AddressImpl& addr) const; + bool operator != (const IPv4AddressImpl& addr) const; + +private: + struct in_addr _addr; +}; + + +#if defined(POCO_HAVE_IPv6) + + +// +// IPv6AddressImpl +// + +class IPv6AddressImpl: public IPAddressImpl +{ +public: + IPv6AddressImpl(); + IPv6AddressImpl(const void* addr); + IPv6AddressImpl(const void* addr, Poco::UInt32 scope); + IPv6AddressImpl(unsigned prefix); + std::string toString() const; + poco_socklen_t length() const; + const void* addr() const; + Family family() const; + int af() const; + unsigned prefixLength() const; + Poco::UInt32 scope() const; + bool isWildcard() const; + bool isBroadcast() const; + bool isLoopback() const; + bool isMulticast() const; + bool isLinkLocal() const; + bool isSiteLocal() const; + bool isIPv4Compatible() const; + bool isIPv4Mapped() const; + bool isWellKnownMC() const; + bool isNodeLocalMC() const; + bool isLinkLocalMC() const; + bool isSiteLocalMC() const; + bool isOrgLocalMC() const; + bool isGlobalMC() const; + static IPv6AddressImpl parse(const std::string& addr); + void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet); + IPAddressImpl* clone() const; + IPv6AddressImpl operator & (const IPv6AddressImpl& addr) const; + IPv6AddressImpl operator | (const IPv6AddressImpl& addr) const; + IPv6AddressImpl operator ^ (const IPv6AddressImpl& addr) const; + IPv6AddressImpl operator ~ () const; + bool operator == (const IPv6AddressImpl& addr) const; + bool operator != (const IPv6AddressImpl& addr) const; + IPv6AddressImpl(const IPv6AddressImpl& addr); + IPv6AddressImpl& operator = (const IPv6AddressImpl&); + +private: + struct in6_addr _addr; + unsigned int _scope; +}; + + +#endif // POCO_HAVE_IPv6 + + +} } } // namespace Poco::Net::Impl + + +#endif // Net_IPAddressImpl_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/MailMessage.h b/contrib/libs/poco/Net/include/Poco/Net/MailMessage.h new file mode 100644 index 0000000000..474186036e --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/MailMessage.h @@ -0,0 +1,314 @@ +// +// MailMessage.h +// +// Library: Net +// Package: Mail +// Module: MailMessage +// +// Definition of the MailMessage class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_MailMessage_INCLUDED +#define Net_MailMessage_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/MessageHeader.h" +#include "Poco/Net/MailRecipient.h" +#include "Poco/Net/PartStore.h" +#include "Poco/Timestamp.h" +#include <vector> + + +namespace Poco { +namespace Net { + + +class MediaType; +class PartSource; +class PartHandler; +class MultipartWriter; + + +class Net_API MailMessage: public MessageHeader + /// This class represents an e-mail message for + /// use with the SMTPClientSession and POPClientSession + /// classes. + /// + /// MailMessage supports both old-style plain text messages, + /// as well as MIME multipart mail messages with attachments. + /// + /// For multi-part messages, the following content transfer + /// encodings are supported: 7bit, 8bit, quoted-printable + /// and base64. +{ +public: + typedef std::vector<MailRecipient> Recipients; + + enum ContentDisposition + { + CONTENT_INLINE, + CONTENT_ATTACHMENT + }; + + enum ContentTransferEncoding + { + ENCODING_7BIT, + ENCODING_8BIT, + ENCODING_QUOTED_PRINTABLE, + ENCODING_BASE64 + }; + + struct Part + { + std::string name; + PartSource* pSource; + ContentDisposition disposition; + ContentTransferEncoding encoding; + }; + + typedef std::vector<Part> PartVec; + + MailMessage(PartStoreFactory* pStoreFactory = 0); + /// Creates an empty MailMessage. + /// + /// If pStoreFactory is not null, message attachments will be + /// handled by the object created by the factory. Most + /// common reason is to temporarily save attachments to + /// the file system in order to avoid potential memory + /// exhaustion when attachment files are very large. + + virtual ~MailMessage(); + /// Destroys the MailMessage. + + void addRecipient(const MailRecipient& recipient); + /// Adds a recipient for the message. + + void setRecipients(const Recipients& recipient); + /// Clears existing and sets new recipient list for the message. + + const Recipients& recipients() const; + /// Returns the recipients of the message. + + void setSubject(const std::string& subject); + /// Sets the subject of the message. + /// + /// The subject must not contain any non-ASCII + /// characters. To include non-ASCII characters + /// in the subject, use RFC 2047 word encoding + /// (see encodeWord()). + + const std::string& getSubject() const; + /// Returns the subject of the message. + + void setSender(const std::string& sender); + /// Sets the sender of the message (which + /// ends up in the From header field). + /// + /// The sender must either be a valid email + /// address, or a real name followed by + /// an email address enclosed in < and >. + /// + /// The sender must not contain any non-ASCII + /// characters. To include non-ASCII characters + /// in the sender, use RFC 2047 word encoding + /// (see encodeWord()). + + const std::string& getSender() const; + /// Returns the sender of the message (taken + /// from the From header field). + + void setContent(const std::string& content, ContentTransferEncoding encoding = ENCODING_QUOTED_PRINTABLE); + /// Sets the content of the mail message. + /// + /// If the content transfer encoding is ENCODING_7BIT or + /// ENCODING_8BIT, the content string must be formatted + /// according to the rules of an internet email message. + /// + /// The message will be sent as a single-part + /// message. + /// + /// Note that single CR or LF characters as line delimiters must + /// not be used. Content lines always should be terminated with a + /// proper CRLF sequence. + + const std::string& getContent() const; + /// Returns the content of the mail message. + /// + /// A content will only be returned for single-part + /// messages. The content of multi-part mail messages + /// will be reported through the registered PartHandler. + + void setContentType(const std::string& mediaType); + /// Sets the content type for the message. + + void setContentType(const MediaType& mediaType); + /// Sets the content type for the message. + + const std::string& getContentType() const; + /// Returns the content type for the message. + + void setDate(const Poco::Timestamp& dateTime); + /// Sets the Date header to the given date/time value. + + Poco::Timestamp getDate() const; + /// Returns the value of the Date header. + + bool isMultipart() const; + /// Returns true iff the message is a multipart message. + + void addPart(const std::string& name, + PartSource* pSource, + ContentDisposition disposition, + ContentTransferEncoding encoding); + /// Adds a part/attachment to the mail message. + /// + /// The MailMessage takes ownership of the PartSource and deletes it + /// when it is no longer needed. + /// + /// The MailMessage will be converted to a multipart message + /// if it is not already one. + /// + /// The part name, and the filename specified in the part source + /// must not contain any non-ASCII characters. + /// To include non-ASCII characters in the part name or filename, + /// use RFC 2047 word encoding (see encodeWord()). + + void addContent(PartSource* pSource, + ContentTransferEncoding encoding = ENCODING_QUOTED_PRINTABLE); + /// Adds a part to the mail message by calling + /// addPart("", pSource, CONTENT_INLINE, encoding); + /// + /// The part name, and the filename specified in the part source + /// must not contain any non-ASCII characters. + /// To include non-ASCII characters in the part name or filename, + /// use RFC 2047 word encoding (see encodeWord()). + + void addAttachment(const std::string& name, + PartSource* pSource, + ContentTransferEncoding encoding = ENCODING_BASE64); + /// Adds an attachment to the mail message by calling + /// addPart(name, pSource, CONTENT_ATTACHMENT, encoding); + /// + /// The part name, and the filename specified in the part source + /// must not contain any non-ASCII characters. + /// To include non-ASCII characters in the part name or filename, + /// use RFC 2047 word encoding (see encodeWord()). + + PartSource* createPartStore(const std::string& content, + const std::string& mediaType, + const std::string& filename = ""); + /// Returns either default StringPartSource part store or, + /// if the part store factory was provided during construction, + /// the one created by PartStoreFactory. + /// Returned part store is allocated on the heap; it is caller's + /// responsibility to delete it after use. Typical use is handler + /// passing it back to MailMessage, which takes care of the cleanup. + + const PartVec& parts() const; + /// Returns const reference to the vector containing part stores. + + void read(std::istream& istr, PartHandler& handler); + /// Reads the MailMessage from the given input stream. + /// + /// If the message has multiple parts, the parts + /// are reported to the PartHandler. If the message + /// is not a multi-part message, the content is stored + /// in a string available by calling getContent(). + + void read(std::istream& istr); + /// Reads the MailMessage from the given input stream. + /// + /// The raw message (including all MIME parts) is stored + /// in a string and available by calling getContent(). + + void write(std::ostream& ostr) const; + /// Writes the mail message to the given output stream. + + static std::string encodeWord(const std::string& text, const std::string& charset = "UTF-8"); + /// If the given string contains non-ASCII characters, + /// encodes the given string using RFC 2047 "Q" word encoding. + /// + /// The given text must already be encoded in the character set + /// given in charset (default is UTF-8). + /// + /// Returns the encoded string, or the original string if it + /// consists only of ASCII characters. + + static const std::string HEADER_SUBJECT; + static const std::string HEADER_FROM; + static const std::string HEADER_TO; + static const std::string HEADER_CC; + static const std::string HEADER_BCC; + static const std::string HEADER_DATE; + static const std::string HEADER_CONTENT_TYPE; + static const std::string HEADER_CONTENT_TRANSFER_ENCODING; + static const std::string HEADER_CONTENT_DISPOSITION; + static const std::string HEADER_CONTENT_ID; + static const std::string HEADER_MIME_VERSION; + static const std::string EMPTY_HEADER; + static const std::string TEXT_PLAIN; + static const std::string CTE_7BIT; + static const std::string CTE_8BIT; + static const std::string CTE_QUOTED_PRINTABLE; + static const std::string CTE_BASE64; + +protected: + void makeMultipart(); + void writeHeader(const MessageHeader& header, std::ostream& ostr) const; + void writeMultipart(MessageHeader& header, std::ostream& ostr) const; + void writePart(MultipartWriter& writer, const Part& part) const; + void writeEncoded(std::istream& istr, std::ostream& ostr, ContentTransferEncoding encoding) const; + void setRecipientHeaders(MessageHeader& headers) const; + void readHeader(std::istream& istr); + void readMultipart(std::istream& istr, PartHandler& handler); + void readPart(std::istream& istr, const MessageHeader& header, PartHandler& handler); + void handlePart(std::istream& istr, const MessageHeader& header, PartHandler& handler); + static const std::string& contentTransferEncodingToString(ContentTransferEncoding encoding); + static int lineLength(const std::string& str); + static void appendRecipient(const MailRecipient& recipient, std::string& str); + +private: + MailMessage(const MailMessage&); + MailMessage& operator = (const MailMessage&); + + Recipients _recipients; + PartVec _parts; + std::string _content; + ContentTransferEncoding _encoding; + mutable std::string _boundary; + PartStoreFactory* _pStoreFactory; +}; + + +// +// inlines +// +inline const MailMessage::Recipients& MailMessage::recipients() const +{ + return _recipients; +} + + +inline const std::string& MailMessage::getContent() const +{ + return _content; +} + + +inline const MailMessage::PartVec& MailMessage::parts() const +{ + return _parts; +} + + +} } // namespace Poco::Net + + +#endif // Net_MailMessage_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/MailRecipient.h b/contrib/libs/poco/Net/include/Poco/Net/MailRecipient.h new file mode 100644 index 0000000000..7b146141af --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/MailRecipient.h @@ -0,0 +1,120 @@ +// +// MailRecipient.h +// +// Library: Net +// Package: Mail +// Module: MailRecipient +// +// Definition of the MailRecipient class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_MailRecipient_INCLUDED +#define Net_MailRecipient_INCLUDED + + +#include "Poco/Net/Net.h" + + +namespace Poco { +namespace Net { + + +class Net_API MailRecipient + /// The recipient of an e-mail message. + /// + /// A recipient has a type (primary recipient, + /// carbon-copy recipient, blind-carbon-copy + /// recipient), an e-mail address and an optional + /// real name. +{ +public: + enum RecipientType + { + PRIMARY_RECIPIENT, + CC_RECIPIENT, + BCC_RECIPIENT + }; + + MailRecipient(); + /// Creates an empty MailRecipient. + + MailRecipient(const MailRecipient& recipient); + /// Creates a MailRecipient by copying another one. + + MailRecipient(RecipientType type, const std::string& address); + /// Creates a MailRecipient of the given type. + + MailRecipient(RecipientType type, const std::string& address, const std::string& realName); + /// Creates a MailRecipient of the given type. + + ~MailRecipient(); + /// Destroys the MailRecipient. + + MailRecipient& operator = (const MailRecipient& recipient); + /// Assigns another recipient. + + void swap(MailRecipient& recipient); + /// Exchanges the content of two recipients. + + RecipientType getType() const; + /// Returns the type of the recipient. + + void setType(RecipientType type); + /// Sets the type of the recipient. + + const std::string& getAddress() const; + /// Returns the address of the recipient. + + void setAddress(const std::string& address); + /// Sets the address of the recipient. + + const std::string& getRealName() const; + /// Returns the real name of the recipient. + + void setRealName(const std::string& realName); + /// Sets the real name of the recipient. + +private: + std::string _address; + std::string _realName; + RecipientType _type; +}; + + +// +// inlines +// +inline MailRecipient::RecipientType MailRecipient::getType() const +{ + return _type; +} + + +inline const std::string& MailRecipient::getAddress() const +{ + return _address; +} + + +inline const std::string& MailRecipient::getRealName() const +{ + return _realName; +} + + +inline void swap(MailRecipient& r1, MailRecipient& r2) +{ + r1.swap(r2); +} + + +} } // namespace Poco::Net + + +#endif // Net_MailRecipient_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/MailStream.h b/contrib/libs/poco/Net/include/Poco/Net/MailStream.h new file mode 100644 index 0000000000..bc674b014d --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/MailStream.h @@ -0,0 +1,146 @@ +// +// MailStream.h +// +// Library: Net +// Package: Mail +// Module: MailStream +// +// Definition of the MailStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_MailStream_INCLUDED +#define Net_MailStream_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/UnbufferedStreamBuf.h" +#include <istream> +#include <ostream> + + +namespace Poco { +namespace Net { + + +class Net_API MailStreamBuf: public Poco::UnbufferedStreamBuf + /// The sole purpose of this stream buffer is to replace + /// a "\r\n.\r\n" character sequence with a "\r\n..\r\n" sequence for + /// output streams and vice-versa for input streams. + /// + /// This is used when sending mail messages to SMTP servers, or + /// receiving mail messages from POP servers. + /// + /// See RFC 2181 (Simple Mail Transfer Protocol) and RFC 1939 + /// (Post Office Protocol - Version 3) for more information. +{ +public: + MailStreamBuf(std::istream& istr); + /// Creates the MailStreamBuf and connects it + /// to the given input stream. + + MailStreamBuf(std::ostream& ostr); + /// Creates the MailStreamBuf and connects it + /// to the given output stream. + + ~MailStreamBuf(); + /// Destroys the MailStreamBuf. + + void close(); + /// Writes the terminating period, followed by + /// CR-LF. + +protected: + int readFromDevice(); + int writeToDevice(char c); + int readOne(); + +private: + enum State + { + ST_DATA, + ST_CR, + ST_CR_LF, + ST_CR_LF_DOT, + ST_CR_LF_DOT_DOT, + ST_CR_LF_DOT_CR, + ST_CR_LF_DOT_CR_LF + }; + + std::istream* _pIstr; + std::ostream* _pOstr; + std::string _buffer; + State _state; +}; + + +class Net_API MailIOS: public virtual std::ios + /// The base class for MailInputStream and MailOutputStream. + /// + /// This class provides common methods and is also needed to ensure + /// the correct initialization order of the stream buffer and base classes. +{ +public: + MailIOS(std::istream& istr); + /// Creates the MailIOS and connects it + /// to the given input stream. + + MailIOS(std::ostream& ostr); + /// Creates the MailIOS and connects it + /// to the given output stream. + + ~MailIOS(); + /// Destroys the stream. + + void close(); + /// Writes the terminating period, followed by + /// CR-LF. + + MailStreamBuf* rdbuf(); + /// Returns a pointer to the underlying streambuf. + +protected: + MailStreamBuf _buf; +}; + + +class Net_API MailInputStream: public MailIOS, public std::istream + /// This class is used for reading E-Mail messages from a + /// POP3 server. All occurrences of "\r\n..\r\n" are replaced with + /// "\r\n.\r\n". The first occurrence of "\r\n.\r\n" denotes the end + /// of the stream. +{ +public: + MailInputStream(std::istream& istr); + /// Creates the MailInputStream and connects it + /// to the given input stream. + + ~MailInputStream(); + /// Destroys the MailInputStream. +}; + + +class Net_API MailOutputStream: public MailIOS, public std::ostream + /// This class is used for writing E-Mail messages to a + /// SMTP server. All occurrences of "\r\n.\r\n" are replaced with + /// "\r\n..\r\n". +{ +public: + MailOutputStream(std::ostream& ostr); + /// Creates the MailOutputStream and connects it + /// to the given input stream. + + ~MailOutputStream(); + /// Destroys the MailOutputStream. +}; + + +} } // namespace Poco::Net + + +#endif // Net_MailStream_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/MediaType.h b/contrib/libs/poco/Net/include/Poco/Net/MediaType.h new file mode 100644 index 0000000000..8440cb6245 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/MediaType.h @@ -0,0 +1,169 @@ +// +// MediaType.h +// +// Library: Net +// Package: Messages +// Module: MediaType +// +// Definition of the MediaType class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_MediaType_INCLUDED +#define Net_MediaType_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/NameValueCollection.h" + + +namespace Poco { +namespace Net { + + +class Net_API MediaType + /// This class represents a MIME media type, consisting of + /// a top-level type, a subtype and an optional set of + /// parameters. + /// + /// The implementation conforms with RFC 2045 and RFC 2046. +{ +public: + MediaType(const std::string& mediaType); + /// Creates the MediaType from the given string, which + /// must have the format <type>/<subtype>{;<parameter>=<value>}. + + MediaType(const std::string& type, const std::string& subType); + /// Creates the MediaType, using the given type and subtype. + + MediaType(const MediaType& mediaType); + /// Creates a MediaType from another one. + + ~MediaType(); + /// Destroys the MediaType. + + MediaType& operator = (const MediaType& mediaType); + /// Assigns another media type. + + MediaType& operator = (const std::string& mediaType); + /// Assigns another media type. + + void swap(MediaType& mediaType); + /// Swaps the MediaType with another one. + + void setType(const std::string& type); + /// Sets the top-level type. + + const std::string& getType() const; + /// Returns the top-level type. + + void setSubType(const std::string& subType); + /// Sets the sub type. + + const std::string& getSubType() const; + /// Returns the sub type. + + void setParameter(const std::string& name, const std::string& value); + /// Sets the parameter with the given name. + + const std::string& getParameter(const std::string& name) const; + /// Returns the parameter with the given name. + /// + /// Throws a NotFoundException if the parameter does not exist. + + bool hasParameter(const std::string& name) const; + /// Returns true iff a parameter with the given name exists. + + void removeParameter(const std::string& name); + /// Removes the parameter with the given name. + + const NameValueCollection& parameters() const; + /// Returns the parameters. + + std::string toString() const; + /// Returns the string representation of the media type + /// which is <type>/<subtype>{;<parameter>=<value>} + + bool matches(const MediaType& mediaType) const; + /// Returns true iff the type and subtype match + /// the type and subtype of the given media type. + /// Matching is case insensitive. + + bool matches(const std::string& type, const std::string& subType) const; + /// Returns true iff the type and subtype match + /// the given type and subtype. + /// Matching is case insensitive. + + bool matches(const std::string& type) const; + /// Returns true iff the type matches the given type. + /// Matching is case insensitive. + + bool matchesRange(const MediaType& mediaType) const; + /// Returns true if the type and subtype match + /// the type and subtype of the given media type. + /// If the MIME type is a range of types it matches + /// any media type within the range (e.g. "image/*" matches + /// any image media type, "*/*" matches anything). + /// Matching is case insensitive. + + bool matchesRange(const std::string& type, const std::string& subType) const; + /// Returns true if the type and subtype match + /// the given type and subtype. + /// If the MIME type is a range of types it matches + /// any media type within the range (e.g. "image/*" matches + /// any image media type, "*/*" matches anything). + /// Matching is case insensitive. + + bool matchesRange(const std::string& type) const; + /// Returns true if the type matches the given type or + /// the type is a range of types denoted by "*". + /// Matching is case insensitive. + +protected: + void parse(const std::string& mediaType); + +private: + MediaType(); + + std::string _type; + std::string _subType; + NameValueCollection _parameters; +}; + + +// +// inlines +// +inline const std::string& MediaType::getType() const +{ + return _type; +} + + +inline const std::string& MediaType::getSubType() const +{ + return _subType; +} + + +inline const NameValueCollection& MediaType::parameters() const +{ + return _parameters; +} + + +inline void swap(MediaType& m1, MediaType& m2) +{ + m1.swap(m2); +} + + +} } // namespace Poco::Net + + +#endif // Net_MediaType_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/MessageHeader.h b/contrib/libs/poco/Net/include/Poco/Net/MessageHeader.h new file mode 100644 index 0000000000..9b05ccb279 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/MessageHeader.h @@ -0,0 +1,169 @@ +// +// MessageHeader.h +// +// Library: Net +// Package: Messages +// Module: MessageHeader +// +// Definition of the MessageHeader class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_MessageHeader_INCLUDED +#define Net_MessageHeader_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/NameValueCollection.h" +#include <ostream> +#include <istream> +#include <vector> + + +namespace Poco { +namespace Net { + + +class Net_API MessageHeader: public NameValueCollection + /// A collection of name-value pairs that are used in + /// various internet protocols like HTTP and SMTP. + /// + /// The name is case-insensitive. + /// + /// There can be more than one name-value pair with the + /// same name. + /// + /// MessageHeader supports writing and reading the + /// header data in RFC 2822 format. + /// + /// The maximum number of fields can be restricted + /// by calling setFieldLimit(). This is useful to + /// defend against certain kinds of denial-of-service + /// attacks. The limit is only enforced when parsing + /// header fields from a stream, not when programmatically + /// adding them. The default limit is 100. +{ +public: + MessageHeader(); + /// Creates the MessageHeader. + + MessageHeader(const MessageHeader& messageHeader); + /// Creates the MessageHeader by copying + /// another one. + + virtual ~MessageHeader(); + /// Destroys the MessageHeader. + + MessageHeader& operator = (const MessageHeader& messageHeader); + /// Assigns the content of another MessageHeader. + + virtual void write(std::ostream& ostr) const; + /// Writes the message header to the given output stream. + /// + /// The format is one name-value pair per line, with + /// name and value separated by a colon and lines + /// delimited by a carriage return and a linefeed + /// character. See RFC 2822 for details. + + virtual void read(std::istream& istr); + /// Reads the message header from the given input stream. + /// + /// See write() for the expected format. + /// Also supported is folding of field content, according + /// to section 2.2.3 of RFC 2822. + /// + /// Reading stops at the first empty line (a line only + /// containing \r\n or \n), as well as at the end of + /// the stream. + /// + /// Some basic sanity checking of the input stream is + /// performed. + /// + /// Throws a MessageException if the input stream is + /// malformed. + + int getFieldLimit() const; + /// Returns the maximum number of header fields + /// allowed. + /// + /// See setFieldLimit() for more information. + + void setFieldLimit(int limit); + /// Sets the maximum number of header fields + /// allowed. This limit is used to defend certain + /// kinds of denial-of-service attacks. + /// Specify 0 for unlimited (not recommended). + /// + /// The default limit is 100. + + bool hasToken(const std::string& fieldName, const std::string& token) const; + /// Returns true iff the field with the given fieldName contains + /// the given token. Tokens in a header field are expected to be + /// comma-separated and are case insensitive. + + static void splitElements(const std::string& s, std::vector<std::string>& elements, bool ignoreEmpty = true); + /// Splits the given string into separate elements. Elements are expected + /// to be separated by commas. + /// + /// For example, the string + /// text/plain; q=0.5, text/html, text/x-dvi; q=0.8 + /// is split into the elements + /// text/plain; q=0.5 + /// text/html + /// text/x-dvi; q=0.8 + /// + /// Commas enclosed in double quotes do not split elements. + /// + /// If ignoreEmpty is true, empty elements are not returned. + + static void splitParameters(const std::string& s, std::string& value, NameValueCollection& parameters); + /// Splits the given string into a value and a collection of parameters. + /// Parameters are expected to be separated by semicolons. + /// + /// Enclosing quotes of parameter values are removed. + /// + /// For example, the string + /// multipart/mixed; boundary="MIME_boundary_01234567" + /// is split into the value + /// multipart/mixed + /// and the parameter + /// boundary -> MIME_boundary_01234567 + + static void splitParameters(const std::string::const_iterator& begin, const std::string::const_iterator& end, NameValueCollection& parameters); + /// Splits the given string into a collection of parameters. + /// Parameters are expected to be separated by semicolons. + /// + /// Enclosing quotes of parameter values are removed. + + static void quote(const std::string& value, std::string& result, bool allowSpace = false); + /// Checks if the value must be quoted. If so, the value is + /// appended to result, enclosed in double-quotes. + /// Otherwise, the value is appended to result as-is. + + static void decodeRFC2047(const std::string& ins, std::string& outs, const std::string& charset = "UTF-8"); + static std::string decodeWord(const std::string& text, const std::string& charset = "UTF-8"); + /// Decode RFC2047 string. + + +private: + enum Limits + /// Limits for basic sanity checks when reading a header + { + MAX_NAME_LENGTH = 256, + MAX_VALUE_LENGTH = 16384, + DFL_FIELD_LIMIT = 100 + }; + + int _fieldLimit; +}; + + +} } // namespace Poco::Net + + +#endif // Net_MessageHeader_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/MulticastSocket.h b/contrib/libs/poco/Net/include/Poco/Net/MulticastSocket.h new file mode 100644 index 0000000000..6ae465775f --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/MulticastSocket.h @@ -0,0 +1,135 @@ +// +// MulticastSocket.h +// +// Library: Net +// Package: Sockets +// Module: MulticastSocket +// +// Definition of the MulticastSocket class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_MulticastSocket_INCLUDED +#define Net_MulticastSocket_INCLUDED + + +#include "Poco/Net/Net.h" + + +#ifdef POCO_NET_HAS_INTERFACE + + +#include "Poco/Net/DatagramSocket.h" +#include "Poco/Net/NetworkInterface.h" + + +namespace Poco { +namespace Net { + + +class Net_API MulticastSocket: public DatagramSocket + /// A MulticastSocket is a special DatagramSocket + /// that can be used to send packets to and receive + /// packets from multicast groups. +{ +public: + MulticastSocket(); + /// Creates an unconnected, unbound multicast socket. + /// + /// Before the multicast socket can be used, bind(), + /// bind6() or connect() must be called. + /// + /// Notice: The behavior of this constructor has changed + /// in release 2.0. Previously, the constructor created + /// an unbound IPv4 multicast socket. + + explicit MulticastSocket(SocketAddress::Family family); + /// Creates an unconnected datagram socket. + /// + /// The socket will be created for the + /// given address family. + + MulticastSocket(const SocketAddress& address, bool reuseAddress = false); + /// Creates a datagram socket and binds it + /// to the given address. + /// + /// Depending on the address family, the socket + /// will be either an IPv4 or an IPv6 socket. + + MulticastSocket(const Socket& socket); + /// Creates the DatagramSocket with the SocketImpl + /// from another socket. The SocketImpl must be + /// a DatagramSocketImpl, otherwise an InvalidArgumentException + /// will be thrown. + + ~MulticastSocket(); + /// Destroys the DatagramSocket. + + MulticastSocket& operator = (const Socket& socket); + /// Assignment operator. + /// + /// Releases the socket's SocketImpl and + /// attaches the SocketImpl from the other socket and + /// increments the reference count of the SocketImpl. + + void setInterface(const NetworkInterface& interfc); + /// Sets the interface used for sending multicast packets. + /// + /// To select the default interface, specify an empty + /// interface. + /// + /// This is done by setting the IP_MULTICAST_IF/IPV6_MULTICAST_IF + /// socket option. + + NetworkInterface getInterface() const; + /// Returns the interface used for sending multicast packets. + + void setLoopback(bool flag); + /// Enable or disable loopback for multicast packets. + /// + /// Sets the value of the IP_MULTICAST_LOOP/IPV6_MULTICAST_LOOP + /// socket option. + + bool getLoopback() const; + /// Returns true iff loopback for multicast packets is enabled, + /// false otherwise. + + void setTimeToLive(unsigned value); + /// Specifies the TTL/hop limit for outgoing packets. + /// + /// Sets the value of the IP_MULTICAST_TTL/IPV6_MULTICAST_HOPS + /// socket option. + + unsigned getTimeToLive() const; + /// Returns the TTL/hop limit for outgoing packets. + + void joinGroup(const IPAddress& groupAddress); + /// Joins the specified multicast group at the default interface. + + void joinGroup(const IPAddress& groupAddress, const NetworkInterface& interfc); + /// Joins the specified multicast group at the given interface. + + void leaveGroup(const IPAddress& groupAddress); + /// Leaves the specified multicast group at the default interface. + + void leaveGroup(const IPAddress& groupAddress, const NetworkInterface& interfc); + /// Leaves the specified multicast group at the given interface. + +private: + static NetworkInterface findFirstInterface(const IPAddress& groupAddress); + /// Returns first multicast-eligible network interface. +}; + + +} } // namespace Poco::Net + + +#endif // POCO_NET_HAS_INTERFACE + + +#endif // Net_MulticastSocket_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/MultipartReader.h b/contrib/libs/poco/Net/include/Poco/Net/MultipartReader.h new file mode 100644 index 0000000000..5f972dcba2 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/MultipartReader.h @@ -0,0 +1,160 @@ +// +// MultipartReader.h +// +// Library: Net +// Package: Messages +// Module: MultipartReader +// +// Definition of the MultipartReader class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_MultipartReader_INCLUDED +#define Net_MultipartReader_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/BufferedStreamBuf.h" +#include <istream> + + +namespace Poco { +namespace Net { + + +class MessageHeader; + + +class Net_API MultipartStreamBuf: public Poco::BufferedStreamBuf + /// This is the streambuf class used for reading from a multipart message stream. +{ +public: + MultipartStreamBuf(std::istream& istr, const std::string& boundary); + ~MultipartStreamBuf(); + bool lastPart() const; + +protected: + int readFromDevice(char* buffer, std::streamsize length); + +private: + enum + { + STREAM_BUFFER_SIZE = 1024 + }; + + std::istream& _istr; + std::string _boundary; + bool _lastPart; +}; + + +class Net_API MultipartIOS: public virtual std::ios + /// The base class for MultipartInputStream. +{ +public: + MultipartIOS(std::istream& istr, const std::string& boundary); + ~MultipartIOS(); + MultipartStreamBuf* rdbuf(); + bool lastPart() const; + +protected: + MultipartStreamBuf _buf; +}; + + +class Net_API MultipartInputStream: public MultipartIOS, public std::istream + /// This class is for internal use by MultipartReader only. +{ +public: + MultipartInputStream(std::istream& istr, const std::string& boundary); + ~MultipartInputStream(); +}; + + + +class Net_API MultipartReader + /// This class is used to split a MIME multipart + /// message into its single parts. + /// + /// The format of multipart messages is described + /// in section 5.1 of RFC 2046. + /// + /// To split a multipart message into its parts, + /// do the following: + /// - Create a MultipartReader object, passing it + /// an input stream and optionally a boundary string. + /// - while hasNextPart() returns true, call nextPart() + /// and read the part from stream(). + /// + /// Always ensure that you read all data from the part + /// stream, otherwise the MultipartReader will fail to + /// find the next part. +{ +public: + explicit MultipartReader(std::istream& istr); + /// Creates the MultipartReader and attaches it to the + /// given input stream. + /// + /// The boundary string is determined from the input + /// stream. The message must not contain a preamble + /// preceding the first encapsulation boundary. + + MultipartReader(std::istream& istr, const std::string& boundary); + /// Creates the MultipartReader and attaches it to the + /// given input stream. The given boundary string is + /// used to find message boundaries. + + ~MultipartReader(); + /// Destroys the MultipartReader. + + void nextPart(MessageHeader& messageHeader); + /// Moves to the next part in the message and stores the + /// part's header fields in messageHeader. + /// + /// Throws an MultipartException if there are no more parts + /// available, or if no boundary line can be found in + /// the input stream. + + bool hasNextPart(); + /// Returns true iff more parts are available. + /// + /// Before the first call to nextPart(), returns + /// always true. + + std::istream& stream() const; + /// Returns a reference to the reader's stream that + /// can be used to read the current part. + /// + /// The returned reference will be valid until + /// nextPart() is called or the MultipartReader + /// object is destroyed. + + const std::string& boundary() const; + /// Returns the multipart boundary used by this reader. + +protected: + void findFirstBoundary(); + void guessBoundary(); + void parseHeader(MessageHeader& messageHeader); + bool readLine(std::string& line, std::string::size_type n); + +private: + MultipartReader(); + MultipartReader(const MultipartReader&); + MultipartReader& operator = (const MultipartReader&); + + std::istream& _istr; + std::string _boundary; + MultipartInputStream* _pMPI; +}; + + +} } // namespace Poco::Net + + +#endif // Net_MultipartReader_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/MultipartWriter.h b/contrib/libs/poco/Net/include/Poco/Net/MultipartWriter.h new file mode 100644 index 0000000000..97b3fd2356 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/MultipartWriter.h @@ -0,0 +1,109 @@ +// +// MultipartWriter.h +// +// Library: Net +// Package: Messages +// Module: MultipartWriter +// +// Definition of the MultipartWriter class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_MultipartWriter_INCLUDED +#define Net_MultipartWriter_INCLUDED + + +#include "Poco/Net/Net.h" +#include <ostream> + + +namespace Poco { +namespace Net { + + +class MessageHeader; + + +class Net_API MultipartWriter + /// This class is used to write MIME multipart + /// messages to an output stream. + /// + /// The format of multipart messages is described + /// in section 5.1 of RFC 2046. + /// + /// To create a multipart message, first create + /// a MultipartWriter object. + /// Then, for each part, call nextPart() and + /// write the content to the output stream. + /// Repeat for all parts. + /// After the last part has been written, + /// call close() to finish the multipart message. +{ +public: + explicit MultipartWriter(std::ostream& ostr); + /// Creates the MultipartWriter, using the + /// given output stream. + /// + /// Creates a random boundary string. + + MultipartWriter(std::ostream& ostr, const std::string& boundary); + /// Creates the MultipartWriter, using the + /// given output stream and boundary string. + + ~MultipartWriter(); + /// Destroys the MultipartWriter. + + void nextPart(const MessageHeader& header); + /// Opens a new message part and writes + /// the message boundary string, followed + /// by the message header to the stream. + + void close(); + /// Closes the multipart message and writes + /// the terminating boundary string. + /// + /// Does not close the underlying stream. + + std::ostream& stream(); + /// Returns the writer's stream. + + const std::string& boundary() const; + /// Returns the multipart boundary used by this writer. + + static std::string createBoundary(); + /// Creates a random boundary string. + /// + /// The string always has the form + /// MIME_boundary_XXXXXXXXXXXX, where + /// XXXXXXXXXXXX is a random hexadecimal + /// number. + +private: + MultipartWriter(); + MultipartWriter(const MultipartWriter&); + MultipartWriter& operator = (const MultipartWriter&); + + std::ostream& _ostr; + std::string _boundary; + bool _firstPart; +}; + + +// +// inlines +// +inline std::ostream& MultipartWriter::stream() +{ + return _ostr; +} + + +} } // namespace Poco::Net + + +#endif // Net_MultipartWriter_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/NTPClient.h b/contrib/libs/poco/Net/include/Poco/Net/NTPClient.h new file mode 100644 index 0000000000..044a486a73 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/NTPClient.h @@ -0,0 +1,64 @@ +// +// NTPClient.h +// +// Library: Net +// Package: NTP +// Module: NTPClient +// +// Definition of the NTPClient class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_NTPClient_INCLUDED +#define Net_NTPClient_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/NTPEventArgs.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/BasicEvent.h" + + +namespace Poco { +namespace Net { + + +class Net_API NTPClient + /// This class provides NTP (Network Time Protocol) client functionality. +{ +public: + mutable Poco::BasicEvent<NTPEventArgs> response; + + explicit NTPClient(SocketAddress::Family family, int timeout = 3000000); + /// Creates an NTP client. + + ~NTPClient(); + /// Destroys the NTP client. + + int request(SocketAddress& address) const; + /// Request the time from the server at address. + /// Notifications are posted for events. + /// + /// Returns the number of valid replies. + + int request(const std::string& address) const; + /// Request the time from the server at address. + /// Notifications are posted for events. + /// + /// Returns the number of valid replies. + +private: + mutable SocketAddress::Family _family; + int _timeout; +}; + + +} } // namespace Poco::Net + + +#endif // Net_NTPClient_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/NTPEventArgs.h b/contrib/libs/poco/Net/include/Poco/Net/NTPEventArgs.h new file mode 100644 index 0000000000..89c12751c3 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/NTPEventArgs.h @@ -0,0 +1,84 @@ +// +// NTPEventArgs.h +// +// Library: Net +// Package: NTP +// Module: NTPEventArgs +// +// Definition of NTPEventArgs. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_NTPEventArgs_INCLUDED +#define Net_NTPEventArgs_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/Net/NTPPacket.h" + + +namespace Poco { +namespace Net { + + +class Net_API NTPEventArgs + /// The purpose of the NTPEventArgs class is to be used as template parameter + /// to instantiate event members in NTPClient class. + /// When clients register for an event notification, the reference to the class is + /// passed to the handler function to provide information about the event. +{ +public: + NTPEventArgs(const SocketAddress& address); + /// Creates NTPEventArgs. + + virtual ~NTPEventArgs(); + /// Destroys NTPEventArgs. + + std::string hostName() const; + /// Tries to resolve the target IP address into host name. + /// If unsuccessful, all exceptions are silently ignored and + /// the IP address is returned. + + std::string hostAddress() const; + /// Returns the target IP address. + + const NTPPacket &packet(); + /// Returns the NTP packet. + +private: + NTPEventArgs(); + + void setPacket(NTPPacket &packet); + + SocketAddress _address; + NTPPacket _packet; + + friend class NTPClient; +}; + + +// +// inlines +// +inline const NTPPacket &NTPEventArgs::packet() +{ + return _packet; +} + + +inline void NTPEventArgs::setPacket(NTPPacket &packet) +{ + _packet = packet; +} + + +} } // namespace Poco::Net + + +#endif diff --git a/contrib/libs/poco/Net/include/Poco/Net/NTPPacket.h b/contrib/libs/poco/Net/include/Poco/Net/NTPPacket.h new file mode 100644 index 0000000000..4dae347888 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/NTPPacket.h @@ -0,0 +1,207 @@ +// +// NTPPacket.h +// +// Library: Net +// Package: NTP +// Module: NTPPacket +// +// Definition of the NTPPacket class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_NTPPacket_INCLUDED +#define Net_NTPPacket_INCLUDED + + +#include "Poco/Foundation.h" +#include "Poco/Net/Net.h" +#include "Poco/Timestamp.h" + +namespace Poco { +namespace Net { + + +class Net_API NTPPacket + /// This class is the NTP packet abstraction. +{ +public: + NTPPacket(); + /// Creates an NTPPacket. + + NTPPacket(Poco::UInt8 *packet); + /// Creates an NTPPacket. + /// + /// Assumed to have at least 48 bytes. + + ~NTPPacket(); + /// Destroys the NTPPacket. + + void packet(Poco::UInt8 *packet) const; + /// Returns the NTP packet. + /// + /// Assumed to have at least 48 bytes. + + void setPacket(Poco::UInt8 *packet); + /// Returns the NTP packet. + /// + /// Assumed to have exactly 48 bytes. + + Poco::Int8 leapIndicator() const; + /// Returns the leap indicator. + + Poco::Int8 version() const; + /// Returns the version. + + Poco::Int8 mode() const; + /// Returns the mode. + + Poco::Int8 stratum() const; + /// Returns the stratum. + + Poco::Int8 pool() const; + /// Returns the pool. + + Poco::Int8 precision() const; + /// Returns the precision + + Poco::Int32 rootDelay() const; + /// Returns the root delay + + Poco::Int32 rootDispersion() const; + /// Returns the root dispersion + + Poco::Int32 referenceId() const; + /// Returns the reference id + + Poco::Int64 referenceTimestamp() const; + /// Returns the reference timestamp + + Poco::Int64 originateTimestamp() const; + /// Returns the originate timestamp + + Poco::Int64 receiveTimestamp() const; + /// Returns the receive timestamp + + Poco::Int64 transmitTimestamp() const; + /// Returns the transmit timestamp + + Poco::Timestamp referenceTime() const; + /// Returns the reference time + + Poco::Timestamp originateTime() const; + /// Returns the originate time + + Poco::Timestamp receiveTime() const; + /// Returns the receive time + + Poco::Timestamp transmitTime() const; + /// Returns the transmit time +private: + Poco::Timestamp convertTime(Poco::Int64 tm) const; + + Poco::Int8 _leapIndicator; + Poco::Int8 _version; + Poco::Int8 _mode; + Poco::Int8 _stratum; + Poco::Int8 _pool; + Poco::Int8 _precision; + Poco::Int32 _rootDelay; + Poco::Int32 _rootDispersion; + Poco::Int32 _referenceId; + Poco::Int64 _referenceTimestamp; + Poco::Int64 _originateTimestamp; + Poco::Int64 _receiveTimestamp; + Poco::Int64 _transmitTimestamp; +}; + + +// +// inlines +// +inline Poco::Int8 NTPPacket::leapIndicator() const +{ + return _leapIndicator; +} + + +inline Poco::Int8 NTPPacket::version() const +{ + return _version; +} + + +inline Poco::Int8 NTPPacket::mode() const +{ + return _mode; +} + + +inline Poco::Int8 NTPPacket::stratum() const +{ + return _stratum; +} + + +inline Poco::Int8 NTPPacket::pool() const +{ + return _pool; +} + + +inline Poco::Int8 NTPPacket::precision() const +{ + return _precision; +} + + +inline Poco::Int32 NTPPacket::rootDelay() const +{ + return _rootDelay; +} + + +inline Poco::Int32 NTPPacket::rootDispersion() const +{ + return _rootDispersion; +} + + +inline Poco::Int32 NTPPacket::referenceId() const +{ + return _referenceId; +} + + +inline Poco::Int64 NTPPacket::referenceTimestamp() const +{ + return _referenceTimestamp; +} + + +inline Poco::Int64 NTPPacket::originateTimestamp() const +{ + return _originateTimestamp; +} + + +inline Poco::Int64 NTPPacket::receiveTimestamp() const +{ + return _receiveTimestamp; +} + + +inline Poco::Int64 NTPPacket::transmitTimestamp() const +{ + return _transmitTimestamp; +} + + +} } // namespace Poco::Net + + +#endif // Net_NTPPacket_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/NameValueCollection.h b/contrib/libs/poco/Net/include/Poco/Net/NameValueCollection.h new file mode 100644 index 0000000000..e2edce3408 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/NameValueCollection.h @@ -0,0 +1,126 @@ +// +// NameValueCollection.h +// +// Library: Net +// Package: Messages +// Module: NameValueCollection +// +// Definition of the NameValueCollection class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_NameValueCollection_INCLUDED +#define Net_NameValueCollection_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/String.h" +#include "Poco/ListMap.h" +#include <cstddef> + + +namespace Poco { +namespace Net { + + +class Net_API NameValueCollection + /// A collection of name-value pairs that are used in + /// various internet protocols like HTTP and SMTP. + /// + /// The name is case-insensitive. + /// + /// There can be more than one name-value pair with the + /// same name. +{ +public: + typedef Poco::ListMap<std::string, std::string> HeaderMap; + typedef HeaderMap::Iterator Iterator; + typedef HeaderMap::ConstIterator ConstIterator; + + NameValueCollection(); + /// Creates an empty NameValueCollection. + + NameValueCollection(const NameValueCollection& nvc); + /// Creates a NameValueCollection by copying another one. + + virtual ~NameValueCollection(); + /// Destroys the NameValueCollection. + + NameValueCollection& operator = (const NameValueCollection& nvc); + /// Assigns the name-value pairs of another NameValueCollection to this one. + + void swap(NameValueCollection& nvc); + /// Swaps the NameValueCollection with another one. + + const std::string& operator [] (const std::string& name) const; + /// Returns the value of the (first) name-value pair with the given name. + /// + /// Throws a NotFoundException if the name-value pair does not exist. + + void set(const std::string& name, const std::string& value); + /// Sets the value of the (first) name-value pair with the given name. + + void add(const std::string& name, const std::string& value); + /// Adds a new name-value pair with the given name and value. + + const std::string& get(const std::string& name) const; + /// Returns the value of the first name-value pair with the given name. + /// + /// Throws a NotFoundException if the name-value pair does not exist. + + const std::string& get(const std::string& name, const std::string& defaultValue) const; + /// Returns the value of the first name-value pair with the given name. + /// If no value with the given name has been found, the defaultValue is returned. + + bool has(const std::string& name) const; + /// Returns true if there is at least one name-value pair + /// with the given name. + + ConstIterator find(const std::string& name) const; + /// Returns an iterator pointing to the first name-value pair + /// with the given name. + + ConstIterator begin() const; + /// Returns an iterator pointing to the begin of + /// the name-value pair collection. + + ConstIterator end() const; + /// Returns an iterator pointing to the end of + /// the name-value pair collection. + + bool empty() const; + /// Returns true iff the header does not have any content. + + std::size_t size() const; + /// Returns the number of name-value pairs in the + /// collection. + + void erase(const std::string& name); + /// Removes all name-value pairs with the given name. + + void clear(); + /// Removes all name-value pairs and their values. + +private: + HeaderMap _map; +}; + + +// +// inlines +// +inline void swap(NameValueCollection& nvc1, NameValueCollection& nvc2) +{ + nvc1.swap(nvc2); +} + + +} } // namespace Poco::Net + + +#endif // Net_NameValueCollection_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/Net.h b/contrib/libs/poco/Net/include/Poco/Net/Net.h new file mode 100644 index 0000000000..4ec0203515 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/Net.h @@ -0,0 +1,122 @@ +// +// Net.h +// +// Library: Net +// Package: NetCore +// Module: Net +// +// Basic definitions for the Poco Net library. +// This file must be the first file included by every other Net +// header file. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_Net_INCLUDED +#define Net_Net_INCLUDED + + +#include "Poco/Foundation.h" + + +// +// The following block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the Net_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// Net_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. +// +#if defined(_WIN32) && defined(POCO_DLL) + #if defined(Net_EXPORTS) + #define Net_API __declspec(dllexport) + #else + #define Net_API __declspec(dllimport) + #endif +#endif + + +#if !defined(Net_API) + #if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4) + #define Net_API __attribute__ ((visibility ("default"))) + #else + #define Net_API + #endif +#endif + + +// +// Automatically link Net library. +// +#if defined(_MSC_VER) + #if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(Net_EXPORTS) + #pragma comment(lib, "PocoNet" POCO_LIB_SUFFIX) + #endif +#endif + + +// Default to enabled IPv6 support if not explicitly disabled +#if !defined(POCO_NET_NO_IPv6) && !defined (POCO_HAVE_IPv6) + #define POCO_HAVE_IPv6 +#elif defined(POCO_NET_NO_IPv6) && defined (POCO_HAVE_IPv6) + #undef POCO_HAVE_IPv6 +#endif // POCO_NET_NO_IPv6, POCO_HAVE_IPv6 + + +namespace Poco { +namespace Net { + + +void Net_API initializeNetwork(); + /// Initialize the network subsystem. + /// (Windows only, no-op elsewhere) + + +void Net_API uninitializeNetwork(); + /// Uninitialize the network subsystem. + /// (Windows only, no-op elsewhere) + + +}} // namespace Poco::Net + + +// +// Automate network initialization (only relevant on Windows). +// + +#if defined(POCO_OS_FAMILY_WINDOWS) && !defined(POCO_NO_AUTOMATIC_LIB_INIT) && !defined(__GNUC__) + +extern "C" const struct Net_API NetworkInitializer pocoNetworkInitializer; + +#if defined(Net_EXPORTS) + #if defined(_WIN64) || defined(_WIN32_WCE) + #define POCO_NET_FORCE_SYMBOL(s) __pragma(comment (linker, "/export:"#s)) + #elif defined(_WIN32) + #define POCO_NET_FORCE_SYMBOL(s) __pragma(comment (linker, "/export:_"#s)) + #endif +#else // !Net_EXPORTS + #if defined(_WIN64) || defined(_WIN32_WCE) + #define POCO_NET_FORCE_SYMBOL(s) __pragma(comment (linker, "/include:"#s)) + #elif defined(_WIN32) + #define POCO_NET_FORCE_SYMBOL(s) __pragma(comment (linker, "/include:_"#s)) + #endif +#endif // Net_EXPORTS + +POCO_NET_FORCE_SYMBOL(pocoNetworkInitializer) + +#endif // POCO_OS_FAMILY_WINDOWS + + +// +// Define POCO_NET_HAS_INTERFACE for platforms that have network interface detection implemented. +// +#if defined(POCO_OS_FAMILY_WINDOWS) || (POCO_OS == POCO_OS_LINUX) || (POCO_OS == POCO_OS_ANDROID) || defined(POCO_OS_FAMILY_BSD) || (POCO_OS == POCO_OS_SOLARIS) || (POCO_OS == POCO_OS_QNX) + #define POCO_NET_HAS_INTERFACE +#endif + + +#endif // Net_Net_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/NetException.h b/contrib/libs/poco/Net/include/Poco/Net/NetException.h new file mode 100644 index 0000000000..92bb3ed912 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/NetException.h @@ -0,0 +1,60 @@ +// +// NetException.h +// +// Library: Net +// Package: NetCore +// Module: NetException +// +// Definition of the NetException class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_NetException_INCLUDED +#define Net_NetException_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Exception.h" + + +namespace Poco { +namespace Net { + + +POCO_DECLARE_EXCEPTION(Net_API, NetException, Poco::IOException) +POCO_DECLARE_EXCEPTION(Net_API, InvalidAddressException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, InvalidSocketException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, ServiceNotFoundException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, ConnectionAbortedException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, ConnectionResetException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, ConnectionRefusedException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, DNSException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, HostNotFoundException, DNSException) +POCO_DECLARE_EXCEPTION(Net_API, NoAddressFoundException, DNSException) +POCO_DECLARE_EXCEPTION(Net_API, InterfaceNotFoundException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, NoMessageException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, MessageException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, MultipartException, MessageException) +POCO_DECLARE_EXCEPTION(Net_API, HTTPException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, NotAuthenticatedException, HTTPException) +POCO_DECLARE_EXCEPTION(Net_API, UnsupportedRedirectException, HTTPException) +POCO_DECLARE_EXCEPTION(Net_API, FTPException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, SMTPException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, POP3Exception, NetException) +POCO_DECLARE_EXCEPTION(Net_API, ICMPException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, NTPException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, HTMLFormException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, WebSocketException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, UnsupportedFamilyException, NetException) +POCO_DECLARE_EXCEPTION(Net_API, AddressFamilyMismatchException, NetException) + + +} } // namespace Poco::Net + + +#endif // Net_NetException_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/NetworkInterface.h b/contrib/libs/poco/Net/include/Poco/Net/NetworkInterface.h new file mode 100644 index 0000000000..17e10fdf6c --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/NetworkInterface.h @@ -0,0 +1,352 @@ +// +// NetworkInterface.h +// +// Library: Net +// Package: Sockets +// Module: NetworkInterface +// +// Definition of the NetworkInterface class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_NetworkInterface_INCLUDED +#define Net_NetworkInterface_INCLUDED + + +#include "Poco/Net/Net.h" + + +#ifdef POCO_NET_HAS_INTERFACE + + +#include "Poco/Net/IPAddress.h" +#include "Poco/Mutex.h" +#include "Poco/Tuple.h" +#include <map> +#include <ostream> + + +namespace Poco { +namespace Net { + + +class NetworkInterfaceImpl; + + +class Net_API NetworkInterface + /// This class represents a network interface. + /// + /// NetworkInterface is used with MulticastSocket to specify + /// multicast interfaces for sending and receiving multicast + /// messages. + /// + /// The class also provides static member functions for + /// enumerating or searching network interfaces and their + /// respective configuration values. + /// + /// On Windows, detection capabilities vary depending on the + /// OS version/service pack. Although the best effort is made + /// not to attempt access to non-existent features through a + /// combination of compile/runtime checks, when running binaries + /// compiled on a newer version of the OS on an older one + /// problems may occur; if possible, it is best to run + /// binaries on the OS version where they were compiled. + /// This particularly applies to OS versions older than Vista + /// and XP. +{ +public: + typedef std::vector<NetworkInterface> List; + typedef List NetworkInterfaceList;//@deprecated + typedef std::map<unsigned, NetworkInterface> Map; + typedef Poco::Tuple<IPAddress, IPAddress, IPAddress> AddressTuple; + typedef std::vector<AddressTuple> AddressList; + typedef AddressList::iterator AddressIterator; + typedef AddressList::const_iterator ConstAddressIterator; + typedef std::vector<unsigned char> MACAddress; + + enum AddressType + { + IP_ADDRESS, + SUBNET_MASK, + BROADCAST_ADDRESS + }; + + enum Type + { + NI_TYPE_ETHERNET_CSMACD, + NI_TYPE_ISO88025_TOKENRING, + NI_TYPE_FRAMERELAY, + NI_TYPE_PPP, + NI_TYPE_SOFTWARE_LOOPBACK, + NI_TYPE_ATM, + NI_TYPE_IEEE80211, + NI_TYPE_TUNNEL, + NI_TYPE_IEEE1394, + NI_TYPE_OTHER + }; + + enum IPVersion + { + IPv4_ONLY, /// Return interfaces with IPv4 address only + IPv6_ONLY, /// Return interfaces with IPv6 address only + IPv4_OR_IPv6 /// Return interfaces with IPv4 or IPv6 address + }; + + static const unsigned NO_INDEX = ~0; +#if defined(POCO_OS_FAMILY_WINDOWS) + static const char MAC_SEPARATOR = '-'; +#else + static const char MAC_SEPARATOR = ':'; +#endif + + NetworkInterface(unsigned index = NO_INDEX); + /// Creates a NetworkInterface representing the + /// default interface. + /// + /// The name is empty, the IP address is the wildcard + /// address and the index is max value of unsigned integer. + + NetworkInterface(const NetworkInterface& interfc); + /// Creates the NetworkInterface by copying another one. + + ~NetworkInterface(); + /// Destroys the NetworkInterface. + + NetworkInterface& operator = (const NetworkInterface& interfc); + /// Assigns another NetworkInterface. + + bool operator < (const NetworkInterface& other) const; + /// Operator less-than. + + bool operator == (const NetworkInterface& other) const; + /// Operator equal. Compares interface indices. + + void swap(NetworkInterface& other); + /// Swaps the NetworkInterface with another one. + + unsigned index() const; + /// Returns the interface OS index. + + const std::string& name() const; + /// Returns the interface name. + + const std::string& displayName() const; + /// Returns the interface display name. + /// + /// On Windows platforms, this is currently the network adapter + /// name. This may change to the "friendly name" of the network + /// connection in a future version, however. + /// + /// On other platforms this is the same as name(). + + const std::string& adapterName() const; + /// Returns the interface adapter name. + /// + /// On Windows platforms, this is the network adapter LUID. + /// The adapter name is used by some Windows Net APIs like DHCP. + /// + /// On other platforms this is the same as name(). + + const IPAddress& firstAddress(IPAddress::Family family) const; + /// Returns the first IP address bound to the interface. + /// Throws NotFoundException if the address family is not + /// configured on the interface. + + void firstAddress(IPAddress& addr, IPAddress::Family family = IPAddress::IPv4) const; + /// Returns the first IP address bound to the interface. + /// If the address family is not configured on the interface, + /// the address returned in addr will be unspecified (wildcard). + + const IPAddress& address(unsigned index = 0) const; + /// Returns the IP address bound to the interface at index position. + + void addAddress(const IPAddress& address); + /// Adds address to the interface. + + void addAddress(const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress); + /// Adds address to the interface. + + const AddressList& addressList() const; + /// Returns the list of IP addresses bound to the interface. + + const IPAddress& subnetMask(unsigned index = 0) const; + /// Returns the subnet mask for this network interface. + + const IPAddress& broadcastAddress(unsigned index = 0) const; + /// Returns the broadcast address for this network interface. + + const IPAddress& destAddress(unsigned index = 0) const; + /// Returns the IPv4 point-to-point destination address for this network interface. + + const MACAddress& macAddress() const; + /// Returns MAC (Media Access Control) address for the interface. + + unsigned mtu() const; + /// Returns the MTU for this interface. + + NetworkInterface::Type type() const; + /// returns the MIB IfType of the interface. + + bool supportsIP() const; + /// Returns true if the interface supports IP. + + bool supportsIPv4() const; + /// Returns true if the interface supports IPv4. + + bool supportsIPv6() const; + /// Returns true if the interface supports IPv6. + + bool supportsBroadcast() const; + /// Returns true if the interface supports broadcast. + + bool supportsMulticast() const; + /// Returns true if the interface supports multicast. + + bool isLoopback() const; + /// Returns true if the interface is loopback. + + bool isPointToPoint() const; + /// Returns true if the interface is point-to-point. + + bool isRunning() const; + /// Returns true if the interface is running. + + bool isUp() const; + /// Returns true if the interface is up. + + static NetworkInterface forName(const std::string& name, bool requireIPv6 = false); + /// Returns the NetworkInterface for the given name. + /// + /// If requireIPv6 is false, an IPv4 interface is returned. + /// Otherwise, an IPv6 interface is returned. + /// + /// Throws an InterfaceNotFoundException if an interface + /// with the give name does not exist. + + static NetworkInterface forName(const std::string& name, IPVersion ipVersion); + /// Returns the NetworkInterface for the given name. + /// + /// The ipVersion argument can be used to specify whether + /// an IPv4 (IPv4_ONLY) or IPv6 (IPv6_ONLY) interface is required, + /// or whether the caller does not care (IPv4_OR_IPv6). + /// + /// Throws an InterfaceNotFoundException if an interface + /// with the give name does not exist. + + static NetworkInterface forAddress(const IPAddress& address); + /// Returns the NetworkInterface for the given IP address. + /// + /// Throws an InterfaceNotFoundException if an interface + /// with the give address does not exist. + + static NetworkInterface forIndex(unsigned index); + /// Returns the NetworkInterface for the given interface index. + /// + /// Throws an InterfaceNotFoundException if an interface + /// with the given index does not exist. + + static List list(bool ipOnly = true, bool upOnly = true); + /// Returns a list with all network interfaces + /// on the system. + /// + /// If ipOnly is true, only interfaces supporting IP + /// are returned. Otherwise, all system network interfaces + /// are returned. + /// + /// If upOnly is true, only interfaces being up are returned. + /// Otherwise, both interfaces being up and down are returned. + /// + /// If there are multiple addresses bound to one interface, + /// multiple NetworkInterface entries are listed for + /// the same interface. + + static Map map(bool ipOnly = true, bool upOnly = true); + /// Returns a map containing system network interfaces + /// Map is keyed by interface system indices. + /// + /// If ipOnly is true, only interfaces supporting IP + /// are returned. Otherwise, all system network interfaces + /// are returned. + /// + /// If upOnly is true, only interfaces being up are returned. + /// Otherwise, both interfaces being up and down are returned. + /// + /// If there are multiple addresses bound to one interface, + /// they are contained within the NetworkInterface (second) + /// member of the pair. + +protected: + NetworkInterface(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, MACAddress* pMACAddress = 0); + /// Creates the NetworkInterface. + + NetworkInterface(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index, MACAddress* pMACAddress = 0); + /// Creates the NetworkInterface. + + NetworkInterface(const std::string& name, const IPAddress& address, unsigned index, MACAddress* pMACAddress = 0); + /// Creates the 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 = 0); + /// Creates the NetworkInterface. + + NetworkInterface(const std::string& name, + const IPAddress& address, + const IPAddress& subnetMask, + const IPAddress& broadcastAddress, + unsigned index, + MACAddress* pMACAddress = 0); + /// Creates the NetworkInterface. + + IPAddress interfaceNameToAddress(const std::string& interfaceName) const; + /// Determines the IPAddress bound to the interface with the given name. + + unsigned interfaceNameToIndex(const std::string& interfaceName) const; + /// Determines the interface index of the interface with the given name. + + NetworkInterfaceImpl& impl() { return *_pImpl; }; + +private: + NetworkInterfaceImpl* _pImpl; + + static Poco::FastMutex _mutex; +}; + + +/// +/// inlines +/// + + +inline bool NetworkInterface::operator < (const NetworkInterface& other) const +{ + return this->index() < other.index(); +} + + +inline bool NetworkInterface::operator == (const NetworkInterface& other) const +{ + return this->index() == other.index(); +} + + +} } // namespace Poco::Net + + +Net_API std::ostream& operator << (std::ostream& ostr, const Poco::Net::NetworkInterface::MACAddress& addr); + + +#endif // POCO_NET_HAS_INTERFACE + + +#endif // Net_NetworkInterface_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/NullPartHandler.h b/contrib/libs/poco/Net/include/Poco/Net/NullPartHandler.h new file mode 100644 index 0000000000..21c45c6805 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/NullPartHandler.h @@ -0,0 +1,47 @@ +// +// NullPartHandler.h +// +// Library: Net +// Package: Messages +// Module: NullPartHandler +// +// Definition of the NullPartHandler class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_NullPartHandler_INCLUDED +#define Net_NullPartHandler_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/PartHandler.h" + + +namespace Poco { +namespace Net { + + +class Net_API NullPartHandler: public PartHandler + /// A very special PartHandler that simply discards all data. +{ +public: + NullPartHandler(); + /// Creates the NullPartHandler. + + ~NullPartHandler(); + /// Destroys the NullPartHandler. + + void handlePart(const MessageHeader& header, std::istream& stream); + /// Reads and discards all data from the stream. +}; + + +} } // namespace Poco::Net + + +#endif // Net_NullPartHandler_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/OAuth10Credentials.h b/contrib/libs/poco/Net/include/Poco/Net/OAuth10Credentials.h new file mode 100644 index 0000000000..1402d40d5b --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/OAuth10Credentials.h @@ -0,0 +1,274 @@ +// +// OAuth10Credentials.h +// +// Library: Net +// Package: OAuth +// Module: OAuth10Credentials +// +// Definition of the OAuth10Credentials class. +// +// Copyright (c) 2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_OAuth10Credentials_INCLUDED +#define Net_OAuth10Credentials_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/URI.h" + + +namespace Poco { +namespace Net { + + +class HTTPRequest; +class HTMLForm; + + +class Net_API OAuth10Credentials + /// This class implements OAuth 1.0A authentication for HTTP requests, + /// according to RFC 5849. + /// + /// Only PLAINTEXT and HMAC-SHA1 signature methods are + /// supported. The RSA-SHA1 signature method is not supported. + /// + /// The OAuth10Credentials can be used to sign a client request, as + /// well as to verify the signature of a request on the server. + /// + /// To sign a client request, using a known consumer (client) key, consumer (client) secret, + /// OAuth token and token secret: + /// + /// 1. Create an OAuth10Credentials object using all four credentials, either using + /// the four argument constructor, or by using the default constructor and setting + /// the credentials using the setter methods. + /// 2. Create a URI containing the full request URI. + /// 3. Create an appropriate HTTPRequest object. + /// 4. Optionally, create a HTMLForm object containing additional parameters to sign. + /// 5. Sign the request by calling authenticate(). This will add an OAuth + /// Authorization header to the request. + /// 6. Send the request using a HTTPClientSession. + /// + /// To request the OAuth request token from a server, using only the consumer (client) key + /// and consumer (client) secret: + /// + /// 1. Create an OAuth10Credentials object using the two consumer credentials, either using + /// the two argument constructor, or by using the default constructor and setting + /// the credentials using the setter methods. + /// 2. Specify the callback URI using setCallback(). + /// 3. Create a URI containing the full request URI to obtain the token. + /// 4. Create an appropriate HTTPRequest object. + /// 5. Sign the request by calling authenticate(). This will add an OAuth + /// Authorization header to the request. + /// 6. Send the request using a HTTPClientSession. + /// 7. The response will contain the request token and request token secret. + /// These can be extracted from the response body using a HTMLForm object. + /// + /// Requesting the access token and secret (temporary credentials) from the server + /// is analogous to signing a client request using consumer key, consumer secret, + /// request token and request token secret. + /// The server response will contain the access token and access token secret, + /// which can again be extracted from the response body using a HTMLForm object. + /// + /// To verify a request on the server: + /// + /// 1. Create an OAuth10Credentials object using the constructor taking a + /// HTTPRequest object. This will extract the consumer key and token (if + /// provided). + /// 2. Provide the consumer secret and token secret (if required) matching the + /// consumer key and token to the OAuth10Credentials object using the + /// setter methods. + /// 3. Create an URI object containing the full request URI. + /// 4. Call verify() to verify the signature. + /// 5. If verification was successful, and the request was a request for + /// a request (temporary) token, call getCallback() to + /// obtain the callback URI provided by the client. +{ +public: + enum SignatureMethod + /// OAuth 1.0A Signature Method. + { + SIGN_PLAINTEXT, /// OAuth 1.0A PLAINTEXT signature method + SIGN_HMAC_SHA1 /// OAuth 1.0A HMAC-SHA1 signature method + }; + + OAuth10Credentials(); + /// Creates an empty OAuth10Credentials object. + + OAuth10Credentials(const std::string& consumerKey, const std::string& consumerSecret); + /// Creates an OAuth10Credentials object with the given consumer key and consumer secret. + /// + /// The token and tokenSecret will be left empty. + + OAuth10Credentials(const std::string& consumerKey, const std::string& consumerSecret, const std::string& token, const std::string& tokenSecret); + /// Creates an OAuth10Credentials object with the given consumer key and + /// consumer secret, as well as token and token secret. + + explicit OAuth10Credentials(const HTTPRequest& request); + /// Creates an OAuth10Credentials object from a HTTPRequest object. + /// + /// Extracts consumer key and token (if available) from the Authorization header. + /// + /// Throws a NotAuthenticatedException if the request does + /// not contain OAuth 1.0 credentials. + + ~OAuth10Credentials(); + /// Destroys the OAuth10Credentials. + + void setConsumerKey(const std::string& consumerKey); + /// Sets the consumer key. + + const std::string& getConsumerKey() const; + /// Returns the consumer key. + + void setConsumerSecret(const std::string& consumerSecret); + /// Sets the consumer secret. + + const std::string& getConsumerSecret() const; + /// Returns the consumer secret. + + void setToken(const std::string& token); + /// Sets the token. + + const std::string& getToken() const; + /// Returns the token. + + void setTokenSecret(const std::string& tokenSecret); + /// Sets the token. + + const std::string& getTokenSecret() const; + /// Returns the token secret. + + void setRealm(const std::string& realm); + /// Sets the optional realm to be included in the Authorization header. + + const std::string& getRealm() const; + /// Returns the optional realm to be included in the Authorization header. + + void setCallback(const std::string& uri); + /// Sets the callback URI. + + const std::string& getCallback() const; + /// Returns the callback URI. + + void authenticate(HTTPRequest& request, const Poco::URI& uri, SignatureMethod method = SIGN_HMAC_SHA1); + /// Adds an OAuth 1.0A Authentication header to the given request, using + /// the given signature method. + + void authenticate(HTTPRequest& request, const Poco::URI& uri, const Poco::Net::HTMLForm& params, SignatureMethod method = SIGN_HMAC_SHA1); + /// Adds an OAuth 1.0A Authentication header to the given request, using + /// the given signature method. + + bool verify(const HTTPRequest& request, const Poco::URI& uri); + /// Verifies the signature of the given request. + /// + /// The consumer key, consumer secret, token and token secret must have been set. + /// + /// Returns true if the signature is valid, otherwise false. + /// + /// Throws a NotAuthenticatedException if the request does not contain OAuth + /// credentials, or in case of an unsupported OAuth version or signature method. + + bool verify(const HTTPRequest& request, const Poco::URI& uri, const Poco::Net::HTMLForm& params); + /// Verifies the signature of the given request. + /// + /// The consumer key, consumer secret, token and token secret must have been set. + /// + /// Returns true if the signature is valid, otherwise false. + /// + /// Throws a NotAuthenticatedException if the request does not contain OAuth + /// credentials, or in case of an unsupported OAuth version or signature method. + + void nonceAndTimestampForTesting(const std::string& nonce, const std::string& timestamp); + /// Sets the nonce and timestamp to a wellknown value. + /// + /// For use by testsuite only, to test the signature + /// algorithm with wellknown inputs. + /// + /// In normal operation, the nonce is a random value + /// computed by createNonce() and the timestamp is taken + /// from the system time. + + static const std::string SCHEME; + +protected: + void signPlaintext(Poco::Net::HTTPRequest& request) const; + /// Signs the given HTTP request according to OAuth 1.0A PLAINTEXT signature method. + + void signHMACSHA1(Poco::Net::HTTPRequest& request, const std::string& uri, const Poco::Net::HTMLForm& params) const; + /// Signs the given HTTP request according to OAuth 1.0A HMAC-SHA1 signature method. + + std::string createNonce() const; + /// Creates a nonce, which is basically a Base64-encoded 32 character random + /// string, with non-alphanumeric characters removed. + + std::string createSignature(const Poco::Net::HTTPRequest& request, const std::string& uri, const Poco::Net::HTMLForm& params, const std::string& nonce, const std::string& timestamp) const; + /// Creates a OAuth signature for the given request and its parameters, according + /// to <https://dev.twitter.com/docs/auth/creating-signature>. + + static std::string percentEncode(const std::string& str); + /// Percent-encodes the given string according to Twitter API's rules, + /// given in <https://dev.twitter.com/docs/auth/percent-encoding-parameters>. + +private: + OAuth10Credentials(const OAuth10Credentials&); + OAuth10Credentials& operator = (const OAuth10Credentials&); + + std::string _consumerKey; + std::string _consumerSecret; + std::string _token; + std::string _tokenSecret; + std::string _callback; + std::string _realm; + std::string _nonce; + std::string _timestamp; +}; + + +// +// inlines +// +inline const std::string& OAuth10Credentials::getConsumerKey() const +{ + return _consumerKey; +} + + +inline const std::string& OAuth10Credentials::getConsumerSecret() const +{ + return _consumerSecret; +} + + +inline const std::string& OAuth10Credentials::getToken() const +{ + return _token; +} + + +inline const std::string& OAuth10Credentials::getTokenSecret() const +{ + return _tokenSecret; +} + + +inline const std::string& OAuth10Credentials::getRealm() const +{ + return _realm; +} + + +inline const std::string& OAuth10Credentials::getCallback() const +{ + return _callback; +} + + +} } // namespace Poco::Net + + +#endif // Net_OAuth10Credentials_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/OAuth20Credentials.h b/contrib/libs/poco/Net/include/Poco/Net/OAuth20Credentials.h new file mode 100644 index 0000000000..6935f2dfa6 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/OAuth20Credentials.h @@ -0,0 +1,132 @@ +// +// OAuth20Credentials.h +// +// Library: Net +// Package: OAuth +// Module: OAuth20Credentials +// +// Definition of the OAuth20Credentials class. +// +// Copyright (c) 2014, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_OAuth20Credentials_INCLUDED +#define Net_OAuth20Credentials_INCLUDED + + +#include "Poco/Net/Net.h" + + +namespace Poco { +namespace Net { + + +class HTTPRequest; + + +class Net_API OAuth20Credentials + /// This class implements OAuth 2.0 authentication for HTTP requests, + /// via Bearer tokens in the Authorization header, + /// according to RFC 6749 and RFC 6750. + /// + /// To add an Authorization header containing a bearer token + /// to a HTTPRequest object, create an OAuth20Credentials object + /// with the bearer token and call authenticate(). + /// + /// The bearer token can also be extracted from a HTTPRequest + /// by creating the OAuth20Credentials object with a HTTPRequest + /// object containing a "Bearer" Authorization header and + /// calling getBearerToken(). + /// + /// The authorization header scheme can be changed from + /// "Bearer" to a custom value. For example, GitHub uses + /// the "token" scheme. +{ +public: + OAuth20Credentials(); + /// Creates an empty OAuth20Credentials object. + + explicit OAuth20Credentials(const std::string& bearerToken); + /// Creates an OAuth20Credentials object with the given bearer token. + + OAuth20Credentials(const std::string& bearerToken, const std::string& scheme); + /// Creates an OAuth20Credentials object with the given bearer token + /// and authorization scheme, which overrides the default scheme ("Bearer"). + /// + /// This is useful for services like GitHub, which use "token" as scheme. + + explicit OAuth20Credentials(const HTTPRequest& request); + /// Creates an OAuth20Credentials object from a HTTPRequest object. + /// + /// Extracts bearer token from the Authorization header, which + /// must use the "Bearer" authorization scheme. + /// + /// Throws a NotAuthenticatedException if the request does + /// not contain a bearer token in the Authorization header. + + OAuth20Credentials(const HTTPRequest& request, const std::string& scheme); + /// Creates an OAuth20Credentials object from a HTTPRequest object. + /// + /// Extracts bearer token from the Authorization header, which must + /// use the given authorization scheme. + /// + /// Throws a NotAuthenticatedException if the request does + /// not contain a bearer token in the Authorization header. + + ~OAuth20Credentials(); + /// Destroys the HTTPCredentials. + + void setBearerToken(const std::string& bearerToken); + /// Sets the bearer token. + + const std::string& getBearerToken() const; + /// Returns the bearer token. + + void setScheme(const std::string& scheme); + /// Sets the Authorization header scheme. + + const std::string& getScheme() const; + /// Returns the Authorization header scheme. + + void authenticate(HTTPRequest& request); + /// Adds an Authorization header containing the bearer token to + /// the HTTPRequest. + + static const std::string SCHEME; + +protected: + void extractBearerToken(const HTTPRequest& request); + /// Extracts the bearer token from the HTTPRequest. + +private: + OAuth20Credentials(const OAuth20Credentials&); + OAuth20Credentials& operator = (const OAuth20Credentials&); + + std::string _bearerToken; + std::string _scheme; +}; + + +// +// inlines +// +inline const std::string& OAuth20Credentials::getBearerToken() const +{ + return _bearerToken; +} + + +inline const std::string& OAuth20Credentials::getScheme() const +{ + return _scheme; +} + + +} } // namespace Poco::Net + + +#endif // Net_OAuth20Credentials_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/POP3ClientSession.h b/contrib/libs/poco/Net/include/Poco/Net/POP3ClientSession.h new file mode 100644 index 0000000000..a4b12ce1ed --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/POP3ClientSession.h @@ -0,0 +1,185 @@ +// +// POP3ClientSession.h +// +// Library: Net +// Package: Mail +// Module: POP3ClientSession +// +// Definition of the POP3ClientSession class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_POP3ClientSession_INCLUDED +#define Net_POP3ClientSession_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/DialogSocket.h" +#include "Poco/Timespan.h" +#include <ostream> +#include <vector> + + +namespace Poco { +namespace Net { + + +class MessageHeader; +class MailMessage; +class PartHandler; + + +class Net_API POP3ClientSession + /// This class implements an Post Office Protocol + /// Version 3 (POP3, RFC 1939) + /// client for receiving e-mail messages. +{ +public: + enum + { + POP3_PORT = 110 + }; + + struct MessageInfo + /// Information returned by listMessages(). + { + int id; + int size; + }; + + typedef std::vector<MessageInfo> MessageInfoVec; + + explicit POP3ClientSession(const StreamSocket& socket); + /// Creates the POP3ClientSession using + /// the given socket, which must be connected + /// to a POP3 server. + + POP3ClientSession(const std::string& host, Poco::UInt16 port = POP3_PORT); + /// Creates the POP3ClientSession using a socket connected + /// to the given host and port. + + virtual ~POP3ClientSession(); + /// Destroys the SMTPClientSession. + + void setTimeout(const Poco::Timespan& timeout); + /// Sets the timeout for socket read operations. + + Poco::Timespan getTimeout() const; + /// Returns the timeout for socket read operations. + + void login(const std::string& username, const std::string& password); + /// Logs in to the POP3 server by sending a USER command + /// followed by a PASS command. + /// + /// Throws a POP3Exception in case of a POP3-specific error, or a + /// NetException in case of a general network communication failure. + + void close(); + /// Sends a QUIT command and closes the connection to the server. + /// + /// Throws a POP3Exception in case of a POP3-specific error, or a + /// NetException in case of a general network communication failure. + + int messageCount(); + /// Sends a STAT command to determine the number of messages + /// available on the server and returns that number. + /// + /// Throws a POP3Exception in case of a POP3-specific error, or a + /// NetException in case of a general network communication failure. + + void listMessages(MessageInfoVec& messages); + /// Fills the given vector with the ids and sizes of all + /// messages available on the server. + /// + /// Throws a POP3Exception in case of a POP3-specific error, or a + /// NetException in case of a general network communication failure. + + void retrieveMessage(int id, MailMessage& message); + /// Retrieves the message with the given id from the server and + /// stores the raw message content in the message's + /// content string, available with message.getContent(). + /// + /// Throws a POP3Exception in case of a POP3-specific error, or a + /// NetException in case of a general network communication failure. + + void retrieveMessage(int id, MailMessage& message, PartHandler& handler); + /// Retrieves the message with the given id from the server and + /// stores it in message. + /// + /// If the message has multiple parts, the parts + /// are reported to the PartHandler. If the message + /// is not a multi-part message, the content is stored + /// in a string available by calling message.getContent(). + /// + /// Throws a POP3Exception in case of a POP3-specific error, or a + /// NetException in case of a general network communication failure. + + void retrieveMessage(int id, std::ostream& ostr); + /// Retrieves the raw message with the given id from the + /// server and copies it to the given output stream. + /// + /// Throws a POP3Exception in case of a POP3-specific error, or a + /// NetException in case of a general network communication failure. + + void retrieveHeader(int id, MessageHeader& header); + /// Retrieves the message header of the message with the + /// given id and stores it in header. + /// + /// For this to work, the server must support the TOP command. + /// + /// Throws a POP3Exception in case of a POP3-specific error, or a + /// NetException in case of a general network communication failure. + + void deleteMessage(int id); + /// Marks the message with the given ID for deletion. The message + /// will be deleted when the connection to the server is + /// closed by calling close(). + /// + /// Throws a POP3Exception in case of a POP3-specific error, or a + /// NetException in case of a general network communication failure. + + bool sendCommand(const std::string& command, std::string& response); + /// Sends the given command verbatim to the server + /// and waits for a response. + /// + /// Returns true if the response is positive, false otherwise. + /// + /// Throws a POP3Exception in case of a POP3-specific error, or a + /// NetException in case of a general network communication failure. + + bool sendCommand(const std::string& command, const std::string& arg, std::string& response); + /// Sends the given command verbatim to the server + /// and waits for a response. + /// + /// Returns true if the response is positive, false otherwise. + /// + /// Throws a POP3Exception in case of a POP3-specific error, or a + /// NetException in case of a general network communication failure. + + bool sendCommand(const std::string& command, const std::string& arg1, const std::string& arg2, std::string& response); + /// Sends the given command verbatim to the server + /// and waits for a response. + /// + /// Returns true if the response is positive, false otherwise. + /// + /// Throws a POP3Exception in case of a POP3-specific error, or a + /// NetException in case of a general network communication failure. + +protected: + static bool isPositive(const std::string& response); + +private: + DialogSocket _socket; + bool _isOpen; +}; + + +} } // namespace Poco::Net + + +#endif // Net_POP3ClientSession_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/ParallelSocketAcceptor.h b/contrib/libs/poco/Net/include/Poco/Net/ParallelSocketAcceptor.h new file mode 100644 index 0000000000..514bcfbfa1 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/ParallelSocketAcceptor.h @@ -0,0 +1,233 @@ +// +// ParallelSocketAcceptor.h +// +// Library: Net +// Package: Reactor +// Module: ParallelSocketAcceptor +// +// Definition of the ParallelSocketAcceptor class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_ParallelSocketAcceptor_INCLUDED +#define Net_ParallelSocketAcceptor_INCLUDED + + +#include "Poco/Net/ParallelSocketReactor.h" +#include "Poco/Net/StreamSocket.h" +#include "Poco/Net/ServerSocket.h" +#include "Poco/Environment.h" +#include "Poco/NObserver.h" +#include "Poco/SharedPtr.h" +#include <vector> + + +using Poco::Net::Socket; +using Poco::Net::SocketReactor; +using Poco::Net::ServerSocket; +using Poco::Net::StreamSocket; +using Poco::NObserver; +using Poco::AutoPtr; + + +namespace Poco { +namespace Net { + + +template <class ServiceHandler, class SR> +class ParallelSocketAcceptor + /// This class implements the Acceptor part of the Acceptor-Connector design pattern. + /// Only the difference from single-threaded version is documented here, For full + /// description see Poco::Net::SocketAcceptor documentation. + /// + /// This is a multi-threaded version of SocketAcceptor, it differs from the + /// single-threaded version in number of reactors (defaulting to number of processors) + /// that can be specified at construction time and is rotated in a round-robin fashion + /// by event handler. See ParallelSocketAcceptor::onAccept and + /// ParallelSocketAcceptor::createServiceHandler documentation and implementation for + /// details. +{ +public: + typedef Poco::Net::ParallelSocketReactor<SR> ParallelReactor; + + explicit ParallelSocketAcceptor(ServerSocket& socket, + unsigned threads = Poco::Environment::processorCount()): + _socket(socket), + _pReactor(0), + _threads(threads), + _next(0) + /// Creates a ParallelSocketAcceptor using the given ServerSocket, + /// sets number of threads and populates the reactors vector. + { + init(); + } + + ParallelSocketAcceptor(ServerSocket& socket, + SocketReactor& reactor, + unsigned threads = Poco::Environment::processorCount()): + _socket(socket), + _pReactor(&reactor), + _threads(threads), + _next(0) + /// Creates a ParallelSocketAcceptor using the given ServerSocket, sets the + /// number of threads, populates the reactors vector and registers itself + /// with the given SocketReactor. + { + init(); + _pReactor->addEventHandler(_socket, + Poco::Observer<ParallelSocketAcceptor, + ReadableNotification>(*this, &ParallelSocketAcceptor::onAccept)); + } + + virtual ~ParallelSocketAcceptor() + /// Destroys the ParallelSocketAcceptor. + { + try + { + if (_pReactor) + { + _pReactor->removeEventHandler(_socket, + Poco::Observer<ParallelSocketAcceptor, + ReadableNotification>(*this, &ParallelSocketAcceptor::onAccept)); + } + } + catch (...) + { + poco_unexpected(); + } + } + + void setReactor(SocketReactor& reactor) + /// Sets the reactor for this acceptor. + { + _pReactor = &reactor; + if (!_pReactor->hasEventHandler(_socket, + Poco::Observer<ParallelSocketAcceptor, + ReadableNotification>(*this, &ParallelSocketAcceptor::onAccept))) + { + registerAcceptor(reactor); + } + } + + virtual void registerAcceptor(SocketReactor& reactor) + /// Registers the ParallelSocketAcceptor with a SocketReactor. + /// + /// A subclass can override this function to e.g. + /// register an event handler for timeout event. + /// + /// The overriding method must either call the base class + /// implementation or register the accept handler on its own. + { + if (_pReactor) + throw Poco::InvalidAccessException("Acceptor already registered."); + + _pReactor = &reactor; + _pReactor->addEventHandler(_socket, + Poco::Observer<ParallelSocketAcceptor, + ReadableNotification>(*this, &ParallelSocketAcceptor::onAccept)); + } + + virtual void unregisterAcceptor() + /// Unregisters the ParallelSocketAcceptor. + /// + /// A subclass can override this function to e.g. + /// unregister its event handler for a timeout event. + /// + /// The overriding method must either call the base class + /// implementation or unregister the accept handler on its own. + { + if (_pReactor) + { + _pReactor->removeEventHandler(_socket, + Poco::Observer<ParallelSocketAcceptor, + ReadableNotification>(*this, &ParallelSocketAcceptor::onAccept)); + } + } + + void onAccept(ReadableNotification* pNotification) + /// Accepts connection and creates event handler. + { + pNotification->release(); + StreamSocket sock = _socket.acceptConnection(); + _pReactor->wakeUp(); + createServiceHandler(sock); + } + +protected: + virtual ServiceHandler* createServiceHandler(StreamSocket& socket) + /// Create and initialize a new ServiceHandler instance. + /// + /// Subclasses can override this method. + { + std::size_t next = _next++; + if (_next == _reactors.size()) _next = 0; + _reactors[next]->wakeUp(); + return new ServiceHandler(socket, *_reactors[next]); + } + + SocketReactor* reactor() + /// Returns a pointer to the SocketReactor where + /// this SocketAcceptor is registered. + /// + /// The pointer may be null. + { + return _pReactor; + } + + Socket& socket() + /// Returns a reference to the SocketAcceptor's socket. + { + return _socket; + } + + void init() + /// Populates the reactors vector. + { + poco_assert (_threads > 0); + + for (unsigned i = 0; i < _threads; ++i) + _reactors.push_back(new ParallelReactor); + } + + typedef std::vector<typename ParallelReactor::Ptr> ReactorVec; + + ReactorVec& reactors() + /// Returns reference to vector of reactors. + { + return _reactors; + } + + SocketReactor* reactor(std::size_t idx) + /// Returns reference to the reactor at position idx. + { + return _reactors.at(idx).get(); + } + + std::size_t& next() + /// Returns reference to the next reactor index. + { + return _next; + } + +private: + ParallelSocketAcceptor(); + ParallelSocketAcceptor(const ParallelSocketAcceptor&); + ParallelSocketAcceptor& operator = (const ParallelSocketAcceptor&); + + ServerSocket _socket; + SocketReactor* _pReactor; + unsigned _threads; + ReactorVec _reactors; + std::size_t _next; +}; + + +} } // namespace Poco::Net + + +#endif // Net_ParallelSocketAcceptor_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/ParallelSocketReactor.h b/contrib/libs/poco/Net/include/Poco/Net/ParallelSocketReactor.h new file mode 100644 index 0000000000..a7631ce1d9 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/ParallelSocketReactor.h @@ -0,0 +1,90 @@ +// +// ParallelSocketReactor.h +// +// Library: Net +// Package: Reactor +// Module: ParallelSocketReactor +// +// Definition of the ParallelSocketReactor class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_ParallelSocketReactor_INCLUDED +#define Net_ParallelSocketReactor_INCLUDED + + +#include "Poco/Net/SocketReactor.h" +#include "Poco/Net/SocketNotification.h" +#include "Poco/Net/StreamSocket.h" +#include "Poco/Net/ServerSocket.h" +#include "Poco/NObserver.h" +#include "Poco/Thread.h" +#include "Poco/SharedPtr.h" + + +using Poco::Net::Socket; +using Poco::Net::SocketReactor; +using Poco::Net::ReadableNotification; +using Poco::Net::ShutdownNotification; +using Poco::Net::ServerSocket; +using Poco::Net::StreamSocket; +using Poco::NObserver; +using Poco::AutoPtr; +using Poco::Thread; + + +namespace Poco { +namespace Net { + + +template <class SR> +class ParallelSocketReactor: public SR +{ +public: + typedef Poco::SharedPtr<ParallelSocketReactor> Ptr; + + ParallelSocketReactor() + { + _thread.start(*this); + } + + ParallelSocketReactor(const Poco::Timespan& timeout): + SR(timeout) + { + _thread.start(*this); + } + + ~ParallelSocketReactor() + { + try + { + this->stop(); + _thread.join(); + } + catch (...) + { + poco_unexpected(); + } + } + +protected: + void onIdle() + { + SR::onIdle(); + Poco::Thread::yield(); + } + +private: + Poco::Thread _thread; +}; + + +} } // namespace Poco::Net + + +#endif // Net_ParallelSocketReactor_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/PartHandler.h b/contrib/libs/poco/Net/include/Poco/Net/PartHandler.h new file mode 100644 index 0000000000..941dd0305c --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/PartHandler.h @@ -0,0 +1,68 @@ +// +// PartHandler.h +// +// Library: Net +// Package: Messages +// Module: PartHandler +// +// Definition of the PartHandler class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_PartHandler_INCLUDED +#define Net_PartHandler_INCLUDED + + +#include "Poco/Net/Net.h" +#include <istream> + + +namespace Poco { +namespace Net { + + +class MessageHeader; + + +class Net_API PartHandler + /// The base class for all part or attachment handlers. + /// + /// Part handlers are used for handling email parts and + /// attachments in MIME multipart messages, as well as file + /// uploads via HTML forms. + /// + /// Subclasses must override handlePart(). +{ +public: + virtual void handlePart(const MessageHeader& header, std::istream& stream) = 0; + /// Called for every part encountered during the processing + /// of an email message or an uploaded HTML form. + /// + /// Information about the part can be extracted from + /// the given message header. What information can be obtained + /// from header depends on the kind of part. + /// + /// The content of the part can be read from stream. + +protected: + PartHandler(); + /// Creates the PartHandler. + + virtual ~PartHandler(); + /// Destroys the PartHandler. + +private: + PartHandler(const PartHandler&); + PartHandler& operator = (const PartHandler&); +}; + + +} } // namespace Poco::Net + + +#endif // Net_PartHandler_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/PartSource.h b/contrib/libs/poco/Net/include/Poco/Net/PartSource.h new file mode 100644 index 0000000000..06978d74cd --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/PartSource.h @@ -0,0 +1,110 @@ +// +// PartSource.h +// +// Library: Net +// Package: Messages +// Module: PartSource +// +// Definition of the PartSource class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_PartSource_INCLUDED +#define Net_PartSource_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/MessageHeader.h" +#include <istream> + + +namespace Poco { +namespace Net { + + +class Net_API PartSource + /// This abstract class is used for adding parts or attachments + /// to mail messages, as well as for uploading files as part of a HTML form. +{ +public: + virtual std::istream& stream() = 0; + /// Returns an input stream for reading the + /// part data. + /// + /// Subclasses must override this method. + + virtual const std::string& filename() const; + /// Returns the filename for the part or attachment. + /// + /// May be overridded by subclasses. The default + /// implementation returns an empty string. + + const std::string& mediaType() const; + /// Returns the MIME media type for this part or attachment. + + MessageHeader& headers(); + /// Returns a MessageHeader containing additional header + /// fields for the part. + + const MessageHeader& headers() const; + /// Returns a MessageHeader containing additional header + /// fields for the part. + + virtual std::streamsize getContentLength() const; + /// Returns the content length for this part + /// which may be UNKNOWN_CONTENT_LENGTH if + /// not available. + + virtual ~PartSource(); + /// Destroys the PartSource. + + static const int UNKNOWN_CONTENT_LENGTH; + +protected: + PartSource(); + /// Creates the PartSource, using + /// the application/octet-stream MIME type. + + PartSource(const std::string& mediaType); + /// Creates the PartSource, using the + /// given MIME type. + +private: + PartSource(const PartSource&); + PartSource& operator = (const PartSource&); + + std::string _mediaType; + MessageHeader _headers; +}; + + +// +// inlines +// +inline const std::string& PartSource::mediaType() const +{ + return _mediaType; +} + + +inline MessageHeader& PartSource::headers() +{ + return _headers; +} + + +inline const MessageHeader& PartSource::headers() const +{ + return _headers; +} + + +} } // namespace Poco::Net + + +#endif // Net_PartSource_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/PartStore.h b/contrib/libs/poco/Net/include/Poco/Net/PartStore.h new file mode 100644 index 0000000000..a7be187c80 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/PartStore.h @@ -0,0 +1,106 @@ +// +// PartStore.h +// +// Library: Net +// Package: Messages +// Module: PartStore +// +// Definition of the PartStore class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_PartStore_INCLUDED +#define Net_PartStore_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/PartSource.h" +#include "Poco/FileStream.h" + + +namespace Poco { +namespace Net { + + +class Net_API PartStore: public PartSource + /// A parent class for part stores storing message parts. +{ +public: + PartStore(const std::string& mediaType); + /// Creates the PartStore for the given MIME type. + + ~PartStore(); + /// Destroys the PartFileStore. + +private: + PartStore(); +}; + + +class Net_API FilePartStore: public PartStore + /// An implementation of PartSource for persisting + /// parts (usually email attachment files) to the file system. +{ +public: + FilePartStore(const std::string& content, const std::string& mediaType, const std::string& filename = ""); + /// Creates the FilePartStore for the given MIME type. + /// For security purposes, attachment filename is NOT used to save file to the file system. + /// A unique temporary file name is used to persist the file. + /// The given filename parameter is the message part (attachment) filename (see filename()) only. + /// + /// Throws an exception if the file cannot be opened. + + ~FilePartStore(); + /// Destroys the FilePartStore. + + std::istream& stream(); + /// Returns a file input stream for the given file. + + const std::string& filename() const; + /// Returns the filename portion of the path. + /// This is the name under which the file is known + /// to the user of this class (typically, MailMessage + /// class). The real name of the file as saved + /// to the filesystem can be obtained by calling + /// path() member function. + + const std::string& path() const; + /// Returns the full path to the file as saved + /// to the file system. For security reasons, + /// file is not saved under the real file name + /// (as specified by the user). + +private: + std::string _filename; + std::string _path; + Poco::FileStream _fstr; +}; + + +class PartStoreFactory + /// Parent factory class for part stores creation. +{ +public: + virtual PartSource* createPartStore(const std::string& content, const std::string& mediaType, const std::string& filename = "") = 0; +}; + + +class FilePartStoreFactory: public PartStoreFactory +{ +public: + PartSource* createPartStore(const std::string& content, const std::string& mediaType, const std::string& filename = "") + { + return new FilePartStore(content, mediaType, filename); + } +}; + + +} } // namespace Poco::Net + + +#endif // Net_PartStore_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/PollSet.h b/contrib/libs/poco/Net/include/Poco/Net/PollSet.h new file mode 100644 index 0000000000..9b24e13591 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/PollSet.h @@ -0,0 +1,86 @@ +// +// PollSet.h +// +// Library: Net +// Package: Sockets +// Module: PollSet +// +// Definition of the PollSet class. +// +// Copyright (c) 2016, Applied Informatics Software Engineering GmbH. +// All rights reserved. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_PollSet_INCLUDED +#define Net_PollSet_INCLUDED + + +#include "Poco/Net/Socket.h" +#include <map> + + +namespace Poco { +namespace Net { + + +class PollSetImpl; + + +class Net_API PollSet + /// A set of sockets that can be efficiently polled as a whole. + /// + /// If supported, PollSet is implemented using epoll (Linux) or + /// poll (BSD) APIs. A fallback implementation using select() + /// is also provided. +{ +public: + enum Mode + { + POLL_READ = 0x01, + POLL_WRITE = 0x02, + POLL_ERROR = 0x04 + }; + + typedef std::map<Poco::Net::Socket, int> SocketModeMap; + + PollSet(); + /// Creates an empty PollSet. + + ~PollSet(); + /// Destroys the PollSet. + + void add(const Poco::Net::Socket& socket, int mode); + /// Adds the given socket to the set, for polling with + /// the given mode, which can be an OR'd combination of + /// POLL_READ, POLL_WRITE and POLL_ERROR. + + void remove(const Poco::Net::Socket& socket); + /// Removes the given socket from the set. + + void update(const Poco::Net::Socket& socket, int mode); + /// Updates the mode of the given socket. + + void clear(); + /// Removes all sockets from the PollSet. + + SocketModeMap poll(const Poco::Timespan& timeout); + /// Waits until the state of at least one of the PollSet's sockets + /// changes accordingly to its mode, or the timeout expires. + /// Returns a PollMap containing the sockets that have had + /// their state changed. + +private: + PollSetImpl* _pImpl; + + PollSet(const PollSet&); + PollSet& operator = (const PollSet&); +}; + + +} } // namespace Poco::Net + + +#endif // Net_PollSet_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/QuotedPrintableDecoder.h b/contrib/libs/poco/Net/include/Poco/Net/QuotedPrintableDecoder.h new file mode 100644 index 0000000000..b456660f6e --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/QuotedPrintableDecoder.h @@ -0,0 +1,86 @@ +// +// QuotedPrintableDecoder.h +// +// Library: Net +// Package: Messages +// Module: QuotedPrintableDecoder +// +// Definition of the QuotedPrintableDecoder class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_QuotedPrintableDecoder_INCLUDED +#define Net_QuotedPrintableDecoder_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/UnbufferedStreamBuf.h" +#include <istream> + + +namespace Poco { +namespace Net { + + +class Net_API QuotedPrintableDecoderBuf: public Poco::UnbufferedStreamBuf + /// This streambuf decodes all quoted-printable (see RFC 2045) + /// encoded data read from the istream connected to it. + /// + /// Note: For performance reasons, the characters + /// are read directly from the given istream's + /// underlying streambuf, so the state + /// of the istream will not reflect that of + /// its streambuf. +{ +public: + QuotedPrintableDecoderBuf(std::istream& istr); + ~QuotedPrintableDecoderBuf(); + +private: + int readFromDevice(); + + std::streambuf& _buf; +}; + + +class Net_API QuotedPrintableDecoderIOS: public virtual std::ios + /// The base class for QuotedPrintableDecoder. + /// + /// This class is needed to ensure the correct initialization + /// order of the stream buffer and base classes. +{ +public: + QuotedPrintableDecoderIOS(std::istream& istr); + ~QuotedPrintableDecoderIOS(); + QuotedPrintableDecoderBuf* rdbuf(); + +protected: + QuotedPrintableDecoderBuf _buf; +}; + + +class Net_API QuotedPrintableDecoder: public QuotedPrintableDecoderIOS, public std::istream + /// This istream decodes all quoted-printable (see RFC 2045) + /// encoded data read from the istream connected to it. + /// + /// Note: For performance reasons, the characters + /// are read directly from the given istream's + /// underlying streambuf, so the state + /// of the istream will not reflect that of + /// its streambuf. +{ +public: + QuotedPrintableDecoder(std::istream& istr); + ~QuotedPrintableDecoder(); +}; + + +} } // namespace Poco::Net + + +#endif // Net_QuotedPrintableDecoder_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/QuotedPrintableEncoder.h b/contrib/libs/poco/Net/include/Poco/Net/QuotedPrintableEncoder.h new file mode 100644 index 0000000000..d0e7d74549 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/QuotedPrintableEncoder.h @@ -0,0 +1,85 @@ +// +// QuotedPrintableEncoder.h +// +// Library: Net +// Package: Messages +// Module: QuotedPrintableEncoder +// +// Definition of the QuotedPrintableEncoder class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_QuotedPrintableEncoder_INCLUDED +#define Net_QuotedPrintableEncoder_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/UnbufferedStreamBuf.h" +#include <ostream> + + +namespace Poco { +namespace Net { + + +class Net_API QuotedPrintableEncoderBuf: public Poco::UnbufferedStreamBuf + /// This streambuf encodes all data written + /// to it in quoted-printable encoding (see RFC 2045) + /// and forwards it to a connected ostream. +{ +public: + QuotedPrintableEncoderBuf(std::ostream& ostr); + ~QuotedPrintableEncoderBuf(); + int close(); + +private: + int writeToDevice(char c); + void writeEncoded(char c); + void writeRaw(char c); + + int _pending; + int _lineLength; + std::ostream& _ostr; +}; + + +class Net_API QuotedPrintableEncoderIOS: public virtual std::ios + /// The base class for QuotedPrintableEncoder. + /// + /// This class is needed to ensure the correct initialization + /// order of the stream buffer and base classes. +{ +public: + QuotedPrintableEncoderIOS(std::ostream& ostr); + ~QuotedPrintableEncoderIOS(); + int close(); + QuotedPrintableEncoderBuf* rdbuf(); + +protected: + QuotedPrintableEncoderBuf _buf; +}; + + +class Net_API QuotedPrintableEncoder: public QuotedPrintableEncoderIOS, public std::ostream + /// This ostream encodes all data + /// written to it in quoted-printable encoding + /// (see RFC 2045) and forwards it to a connected ostream. + /// Always call close() when done + /// writing data, to ensure proper + /// completion of the encoding operation. +{ +public: + QuotedPrintableEncoder(std::ostream& ostr); + ~QuotedPrintableEncoder(); +}; + + +} } // namespace Poco::Net + + +#endif // Net_QuotedPrintableEncoder_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/RawSocket.h b/contrib/libs/poco/Net/include/Poco/Net/RawSocket.h new file mode 100644 index 0000000000..3638b20e45 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/RawSocket.h @@ -0,0 +1,161 @@ +// +// RawSocket.h +// +// Library: Net +// Package: Sockets +// Module: RawSocket +// +// Definition of the RawSocket class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_RawSocket_INCLUDED +#define Net_RawSocket_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/Socket.h" + + +namespace Poco { +namespace Net { + + +class Net_API RawSocket: public Socket + /// This class provides an interface to a + /// raw IP socket. +{ +public: + RawSocket(); + /// Creates an unconnected IPv4 raw socket. + + RawSocket(SocketAddress::Family family, int proto = IPPROTO_RAW); + /// Creates an unconnected raw socket. + /// + /// The socket will be created for the + /// given address family. + + RawSocket(const SocketAddress& address, bool reuseAddress = false); + /// Creates a raw socket and binds it + /// to the given address. + /// + /// Depending on the address family, the socket + /// will be either an IPv4 or an IPv6 socket. + + RawSocket(const Socket& socket); + /// Creates the RawSocket with the SocketImpl + /// from another socket. The SocketImpl must be + /// a RawSocketImpl, otherwise an InvalidArgumentException + /// will be thrown. + + ~RawSocket(); + /// Destroys the RawSocket. + + RawSocket& operator = (const Socket& socket); + /// Assignment operator. + /// + /// Releases the socket's SocketImpl and + /// attaches the SocketImpl from the other socket and + /// increments the reference count of the SocketImpl. + + void connect(const SocketAddress& address); + /// Restricts incoming and outgoing + /// packets to the specified address. + /// + /// Calls to connect() cannot come before calls to bind(). + + void bind(const SocketAddress& address, bool reuseAddress = false); + /// Bind a local address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// Calls to connect() cannot come before calls to bind(). + + void bind(const SocketAddress& address, bool reuseAddress, bool reusePort); + /// Bind a local address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + /// + /// Calls to connect() cannot come before calls to bind(). + + int sendBytes(const void* buffer, int length, int flags = 0); + /// Sends the contents of the given buffer through + /// the socket. + /// + /// Returns the number of bytes sent, which may be + /// less than the number of bytes specified. + + int receiveBytes(void* buffer, int length, int flags = 0); + /// Receives data from the socket and stores it + /// in buffer. Up to length bytes are received. + /// + /// Returns the number of bytes received. + + int sendTo(const void* buffer, int length, const SocketAddress& address, int flags = 0); + /// Sends the contents of the given buffer through + /// the socket to the given address. + /// + /// Returns the number of bytes sent, which may be + /// less than the number of bytes specified. + + int receiveFrom(void* buffer, int length, SocketAddress& address, int flags = 0); + /// Receives data from the socket and stores it + /// in buffer. Up to length bytes are received. + /// Stores the address of the sender in address. + /// + /// Returns the number of bytes received. + + void setBroadcast(bool flag); + /// Sets the value of the SO_BROADCAST socket option. + /// + /// Setting this flag allows sending datagrams to + /// the broadcast address. + + bool getBroadcast() const; + /// Returns the value of the SO_BROADCAST socket option. + +protected: + RawSocket(SocketImpl* pImpl); + /// Creates the Socket and attaches the given SocketImpl. + /// The socket takes ownership of the SocketImpl. + /// + /// The SocketImpl must be a StreamSocketImpl, otherwise + /// an InvalidArgumentException will be thrown. +}; + + +// +// inlines +// +inline void RawSocket::setBroadcast(bool flag) +{ + impl()->setBroadcast(flag); +} + + +inline bool RawSocket::getBroadcast() const +{ + return impl()->getBroadcast(); +} + + +} } // namespace Poco::Net + + +#endif // Net_RawSocket_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/RawSocketImpl.h b/contrib/libs/poco/Net/include/Poco/Net/RawSocketImpl.h new file mode 100644 index 0000000000..df10b64587 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/RawSocketImpl.h @@ -0,0 +1,56 @@ +// +// RawSocketImpl.h +// +// Library: Net +// Package: Sockets +// Module: RawSocketImpl +// +// Definition of the RawSocketImpl class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_RawSocketImpl_INCLUDED +#define Net_RawSocketImpl_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketImpl.h" + + +namespace Poco { +namespace Net { + + +class Net_API RawSocketImpl: public SocketImpl + /// This class implements a raw socket. +{ +public: + RawSocketImpl(); + /// Creates an unconnected IPv4 raw socket with IPPROTO_RAW. + + RawSocketImpl(SocketAddress::Family family, int proto = IPPROTO_RAW); + /// Creates an unconnected raw socket. + /// + /// The socket will be created for the + /// given address family. + + RawSocketImpl(poco_socket_t sockfd); + /// Creates a RawSocketImpl using the given native socket. + +protected: + void init(int af); + void init2(int af, int proto); + + ~RawSocketImpl(); +}; + + +} } // namespace Poco::Net + + +#endif // Net_RawSocketImpl_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/RemoteSyslogChannel.h b/contrib/libs/poco/Net/include/Poco/Net/RemoteSyslogChannel.h new file mode 100644 index 0000000000..848b1634fb --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/RemoteSyslogChannel.h @@ -0,0 +1,158 @@ +// +// RemoteSyslogChannel.h +// +// Library: Net +// Package: Logging +// Module: RemoteSyslogChannel +// +// Definition of the RemoteSyslogChannel class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_RemoteSyslogChannel_INCLUDED +#define Net_RemoteSyslogChannel_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Channel.h" +#include "Poco/Mutex.h" +#include "Poco/Net/DatagramSocket.h" +#include "Poco/Net/SocketAddress.h" + + +namespace Poco { +namespace Net { + + +class Net_API RemoteSyslogChannel: public Poco::Channel + /// This Channel implements remote syslog logging over UDP according + /// to RFC 5424 "The Syslog Protocol" + /// and RFC 5426 "Transmission of syslog messages over UDP". + /// + /// In addition, RemoteSyslogListener also supports the "old" BSD syslog + /// protocol, as described in RFC 3164. + /// + /// RFC 5425 structured data can be passed via the "structured-data" + /// property of the log Message. The content of the "structured-data" + /// property must be correct according to RFC 5425. + /// + /// Example: + /// msg.set("structured-data", "[exampleSDID@32473 iut=\"3\" eventSource=\"Application\" eventID=\"1011\"]"); +{ +public: + static const std::string BSD_TIMEFORMAT; + static const std::string SYSLOG_TIMEFORMAT; + + enum Severity + { + SYSLOG_EMERGENCY = 0, /// Emergency: system is unusable + SYSLOG_ALERT = 1, /// Alert: action must be taken immediately + SYSLOG_CRITICAL = 2, /// Critical: critical conditions + SYSLOG_ERROR = 3, /// Error: error conditions + SYSLOG_WARNING = 4, /// Warning: warning conditions + SYSLOG_NOTICE = 5, /// Notice: normal but significant condition + SYSLOG_INFORMATIONAL = 6, /// Informational: informational messages + SYSLOG_DEBUG = 7 /// Debug: debug-level messages + }; + + enum Facility + { + SYSLOG_KERN = ( 0<<3), /// kernel messages + SYSLOG_USER = ( 1<<3), /// random user-level messages + SYSLOG_MAIL = ( 2<<3), /// mail system + SYSLOG_DAEMON = ( 3<<3), /// system daemons + SYSLOG_AUTH = ( 4<<3), /// security/authorization messages + SYSLOG_SYSLOG = ( 5<<3), /// messages generated internally by syslogd + SYSLOG_LPR = ( 6<<3), /// line printer subsystem + SYSLOG_NEWS = ( 7<<3), /// network news subsystem + SYSLOG_UUCP = ( 8<<3), /// UUCP subsystem + SYSLOG_CRON = ( 9<<3), /// clock daemon + SYSLOG_AUTHPRIV = (10<<3), /// security/authorization messages (private) + SYSLOG_FTP = (11<<3), /// ftp daemon + SYSLOG_NTP = (12<<3), /// ntp subsystem + SYSLOG_LOGAUDIT = (13<<3), /// log audit + SYSLOG_LOGALERT = (14<<3), /// log alert + SYSLOG_CLOCK = (15<<3), /// clock daemon + SYSLOG_LOCAL0 = (16<<3), /// reserved for local use + SYSLOG_LOCAL1 = (17<<3), /// reserved for local use + SYSLOG_LOCAL2 = (18<<3), /// reserved for local use + SYSLOG_LOCAL3 = (19<<3), /// reserved for local use + SYSLOG_LOCAL4 = (20<<3), /// reserved for local use + SYSLOG_LOCAL5 = (21<<3), /// reserved for local use + SYSLOG_LOCAL6 = (22<<3), /// reserved for local use + SYSLOG_LOCAL7 = (23<<3) /// reserved for local use + }; + + enum + { + SYSLOG_PORT = 514 + }; + + RemoteSyslogChannel(); + /// Creates a RemoteSyslogChannel. + + RemoteSyslogChannel(const std::string& address, const std::string& name, int facility = SYSLOG_USER, bool bsdFormat = false); + /// Creates a RemoteSyslogChannel with the given target address, name, and facility. + /// If bsdFormat is true, messages are formatted according to RFC 3164. + + void open(); + /// Opens the RemoteSyslogChannel. + + void close(); + /// Closes the RemoteSyslogChannel. + + void log(const Message& msg); + /// Sends the message's text to the syslog service. + + void setProperty(const std::string& name, const std::string& value); + /// Sets the property with the given value. + /// + /// The following properties are supported: + /// * name: The name used to identify the source of log messages. + /// * facility: The facility added to each log message. See the Facility enumeration for a list of supported values. + /// The LOG_ prefix can be omitted and values are case insensitive (e.g. a facility value "mail" is recognized as SYSLOG_MAIL) + /// * format: "bsd"/"rfc3164" (RFC 3164 format) or "new"/"rfc5424" (default) + /// * loghost: The target IP address or host name where log messages are sent. Optionally, a port number (separated + /// by a colon) can also be specified. + /// * host: (optional) Host name included in syslog messages. If not specified, the host's real domain name or + /// IP address will be used. + + std::string getProperty(const std::string& name) const; + /// Returns the value of the property with the given name. + + static void registerChannel(); + /// Registers the channel with the global LoggingFactory. + + static const std::string PROP_NAME; + static const std::string PROP_FACILITY; + static const std::string PROP_FORMAT; + static const std::string PROP_LOGHOST; + static const std::string PROP_HOST; + static const std::string STRUCTURED_DATA; + +protected: + ~RemoteSyslogChannel(); + static int getPrio(const Message& msg); + +private: + std::string _logHost; + std::string _name; + std::string _host; + int _facility; + bool _bsdFormat; + DatagramSocket _socket; + SocketAddress _socketAddress; + bool _open; + mutable Poco::FastMutex _mutex; +}; + + +} } // namespace Poco::Net + + +#endif // Net_RemoteSyslogChannel_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/RemoteSyslogListener.h b/contrib/libs/poco/Net/include/Poco/Net/RemoteSyslogListener.h new file mode 100644 index 0000000000..93895244c2 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/RemoteSyslogListener.h @@ -0,0 +1,121 @@ +// +// RemoteSyslogListener.h +// +// Library: Net +// Package: Logging +// Module: RemoteSyslogListener +// +// Definition of the RemoteSyslogListener class. +// +// Copyright (c) 2007-2011, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_RemoteSyslogListener_INCLUDED +#define Net_RemoteSyslogListener_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/ThreadPool.h" +#include "Poco/SplitterChannel.h" +#include "Poco/NotificationQueue.h" + + +namespace Poco { +namespace Net { + + +class RemoteUDPListener; +class SyslogParser; + + +class Net_API RemoteSyslogListener: public Poco::SplitterChannel + /// RemoteSyslogListener implements listening for syslog messages + /// sent over UDP, according to RFC 5424 "The Syslog Protocol" + /// and RFC 5426 "Transmission of syslog messages over UDP". + /// + /// In addition, RemoteSyslogListener also supports the "old" BSD syslog + /// protocol, as described in RFC 3164. + /// + /// The RemoteSyslogListener is a subclass of Poco::SplitterChannel. + /// Every received log message is sent to the channels registered + /// with addChannel() or the "channel" property. + /// + /// Poco::Message objects created by RemoteSyslogListener will have + /// the following named parameters: + /// - addr: IP address of the host/interface sending the message. + /// - host: host name; only for "new" syslog messages. + /// - app: application name; only for "new" syslog messages. + /// - structured-data: RFC 5424 structured data, or empty if not present. +{ +public: + RemoteSyslogListener(); + /// Creates the RemoteSyslogListener. + + RemoteSyslogListener(Poco::UInt16 port); + /// Creates the RemoteSyslogListener, listening on the given port number. + + RemoteSyslogListener(Poco::UInt16 port, int threads); + /// Creates the RemoteSyslogListener, listening on the given port number + /// and using the number of threads for message processing. + + void setProperty(const std::string& name, const std::string& value); + /// Sets the property with the given value. + /// + /// The following properties are supported: + /// * port: The UDP port number where to listen for UDP packets + /// containing syslog messages. If 0 is specified, does not + /// listen for UDP messages. + /// * threads: The number of parser threads processing + /// received syslog messages. Defaults to 1. A maximum + /// of 16 threads is supported. + + std::string getProperty(const std::string& name) const; + /// Returns the value of the property with the given name. + + void open(); + /// Starts the listener. + + void close(); + /// Stops the listener. + + void processMessage(const std::string& messageText); + /// Parses a single line of text containing a syslog message + /// and sends it down the filter chain. + + void enqueueMessage(const std::string& messageText, const Poco::Net::SocketAddress& senderAddress); + /// Enqueues a single line of text containing a syslog message + /// for asynchronous processing by a parser thread. + + static void registerChannel(); + /// Registers the channel with the global LoggingFactory. + + static const std::string PROP_PORT; + static const std::string PROP_THREADS; + + static const std::string LOG_PROP_APP; + static const std::string LOG_PROP_HOST; + static const std::string LOG_PROP_STRUCTURED_DATA; + +protected: + ~RemoteSyslogListener(); + /// Destroys the RemoteSyslogListener. + +private: + RemoteUDPListener* _pListener; + SyslogParser* _pParser; + Poco::ThreadPool _threadPool; + Poco::NotificationQueue _queue; + Poco::UInt16 _port; + int _threads; +}; + + +} } // namespace Poco::Net + + +#endif // Net_RemoteSyslogListener_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/SMTPChannel.h b/contrib/libs/poco/Net/include/Poco/Net/SMTPChannel.h new file mode 100644 index 0000000000..373d93ded4 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/SMTPChannel.h @@ -0,0 +1,108 @@ +// +// SMTPChannel.h +// +// Library: Net +// Package: Logging +// Module: SMTPChannel +// +// Definition of the SMTPChannel class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_SMTPChannel_INCLUDED +#define Net_SMTPChannel_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Channel.h" +#include "Poco/String.h" + + +namespace Poco { +namespace Net { + + +class Net_API SMTPChannel: public Poco::Channel + /// This Channel implements SMTP (email) logging. +{ +public: + SMTPChannel(); + /// Creates a SMTPChannel. + + SMTPChannel(const std::string& mailhost, const std::string& sender, const std::string& recipient); + /// Creates a SMTPChannel with the given target mailhost, sender, and recipient. + + void open(); + /// Opens the SMTPChannel. + + void close(); + /// Closes the SMTPChannel. + + void log(const Message& msg); + /// Sends the message's text to the recipient. + + void setProperty(const std::string& name, const std::string& value); + /// Sets the property with the given value. + /// + /// The following properties are supported: + /// * mailhost: The SMTP server. Default is "localhost". + /// * sender: The sender address. + /// * recipient: The recipient address. + /// * local: If true, local time is used. Default is true. + /// * attachment: Filename of the file to attach. + /// * type: Content type of the file to attach. + /// * delete: Boolean value indicating whether to delete + /// the attachment file after sending. + /// * throw: Boolean value indicating whether to throw + /// exception upon failure. + + std::string getProperty(const std::string& name) const; + /// Returns the value of the property with the given name. + + static void registerChannel(); + /// Registers the channel with the global LoggingFactory. + + static const std::string PROP_MAILHOST; + static const std::string PROP_SENDER; + static const std::string PROP_RECIPIENT; + static const std::string PROP_LOCAL; + static const std::string PROP_ATTACHMENT; + static const std::string PROP_TYPE; + static const std::string PROP_DELETE; + static const std::string PROP_THROW; + +protected: + ~SMTPChannel(); + +private: + bool isTrue(const std::string& value) const; + + std::string _mailHost; + std::string _sender; + std::string _recipient; + bool _local; + std::string _attachment; + std::string _type; + bool _delete; + bool _throw; +}; + + +inline bool SMTPChannel::isTrue(const std::string& value) const +{ + return ((0 == icompare(value, "true")) || + (0 == icompare(value, "t")) || + (0 == icompare(value, "yes")) || + (0 == icompare(value, "y"))); +} + + +} } // namespace Poco::Net + + +#endif // Net_SMTPChannel_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/SMTPClientSession.h b/contrib/libs/poco/Net/include/Poco/Net/SMTPClientSession.h new file mode 100644 index 0000000000..5edf999598 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/SMTPClientSession.h @@ -0,0 +1,234 @@ +// +// SMTPClientSession.h +// +// Library: Net +// Package: Mail +// Module: SMTPClientSession +// +// Definition of the SMTPClientSession class. +// +// Copyright (c) 2005-2008, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_SMTPClientSession_INCLUDED +#define Net_SMTPClientSession_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/DialogSocket.h" +#include "Poco/DigestEngine.h" +#include "Poco/Timespan.h" + + +namespace Poco { +namespace Net { + + +class MailMessage; + + +class Net_API SMTPClientSession + /// This class implements an Simple Mail + /// Transfer Protocol (SMTP, RFC 2821) + /// client for sending e-mail messages. +{ +public: + typedef std::vector<std::string> Recipients; + + enum + { + SMTP_PORT = 25 + }; + + enum LoginMethod + { + AUTH_NONE, + AUTH_CRAM_MD5, + AUTH_CRAM_SHA1, + AUTH_LOGIN, + AUTH_PLAIN, + AUTH_XOAUTH2 + }; + + explicit SMTPClientSession(const StreamSocket& socket); + /// Creates the SMTPClientSession using + /// the given socket, which must be connected + /// to a SMTP server. + + SMTPClientSession(const std::string& host, Poco::UInt16 port = SMTP_PORT); + /// Creates the SMTPClientSession using a socket connected + /// to the given host and port. + + virtual ~SMTPClientSession(); + /// Destroys the SMTPClientSession. + + void setTimeout(const Poco::Timespan& timeout); + /// Sets the timeout for socket read operations. + + Poco::Timespan getTimeout() const; + /// Returns the timeout for socket read operations. + + void login(const std::string& hostname); + /// Greets the SMTP server by sending a EHLO command + /// with the given hostname as argument. + /// + /// If the server does not understand the EHLO command, + /// a HELO command is sent instead. + /// + /// Throws a SMTPException in case of a SMTP-specific error, or a + /// NetException in case of a general network communication failure. + + void login(); + /// Calls login(hostname) with the current host name. + + void login(const std::string& hostname, LoginMethod loginMethod, const std::string& username, const std::string& password); + /// Logs in to the SMTP server using the given authentication method and the given + /// credentials. + + void login(LoginMethod loginMethod, const std::string& username, const std::string& password); + /// Logs in to the SMTP server using the given authentication method and the given + /// credentials. + + void open(); + /// Reads the initial response from the SMTP server. + /// + /// Usually called implicitly through login(), but can + /// also be called explicitly to implement different forms + /// of SMTP authentication. + /// + /// Does nothing if called more than once. + + void close(); + /// Sends a QUIT command and closes the connection to the server. + /// + /// Throws a SMTPException in case of a SMTP-specific error, or a + /// NetException in case of a general network communication failure. + + void sendMessage(const MailMessage& message); + /// Sends the given mail message by sending a MAIL FROM command, + /// a RCPT TO command for every recipient, and a DATA command with + /// the message headers and content. Using this function results in + /// RCPT TO commands list generated from the recipient list supplied + /// with the message itself. + /// + /// Throws a SMTPException in case of a SMTP-specific error, or a + /// NetException in case of a general network communication failure. + + void sendMessage(const MailMessage& message, const Recipients& recipients); + /// Sends the given mail message by sending a MAIL FROM command, + /// a RCPT TO command for every recipient, and a DATA command with + /// the message headers and content. Using this function results in + /// message header being generated from the supplied recipients list. + /// + /// Throws a SMTPException in case of a SMTP-specific error, or a + /// NetException in case of a general network communication failure. + + void sendMessage(std::istream& istr); + /// Sends the mail message from the supplied stream. Content of the stream + /// is copied without any checking. Only the completion status is checked and, + /// if not valid, SMTPExcpetion is thrown. + + int sendCommand(const std::string& command, std::string& response); + /// Sends the given command verbatim to the server + /// and waits for a response. + /// + /// Throws a SMTPException in case of a SMTP-specific error, or a + /// NetException in case of a general network communication failure. + + int sendCommand(const std::string& command, const std::string& arg, std::string& response); + /// Sends the given command verbatim to the server + /// and waits for a response. + /// + /// Throws a SMTPException in case of a SMTP-specific error, or a + /// NetException in case of a general network communication failure. + + void sendAddresses(const std::string& from, const Recipients& recipients); + /// Sends the message preamble by sending a MAIL FROM command, + /// and a RCPT TO command for every recipient. + /// + /// Throws a SMTPException in case of a SMTP-specific error, or a + /// NetException in case of a general network communication failure. + + void sendData(); + /// Sends the message preamble by sending a DATA command. + /// + /// Throws a SMTPException in case of a SMTP-specific error, or a + /// NetException in case of a general network communication failure. + +protected: + enum StatusClass + { + SMTP_POSITIVE_COMPLETION = 2, + SMTP_POSITIVE_INTERMEDIATE = 3, + SMTP_TRANSIENT_NEGATIVE = 4, + SMTP_PERMANENT_NEGATIVE = 5 + }; + enum + { + DEFAULT_TIMEOUT = 30000000 // 30 seconds default timeout for socket operations + }; + + static bool isPositiveCompletion(int status); + static bool isPositiveIntermediate(int status); + static bool isTransientNegative(int status); + static bool isPermanentNegative(int status); + + void login(const std::string& hostname, std::string& response); + void loginUsingCRAMMD5(const std::string& username, const std::string& password); + void loginUsingCRAMSHA1(const std::string& username, const std::string& password); + void loginUsingCRAM(const std::string& username, const std::string& method, Poco::DigestEngine& hmac); + void loginUsingLogin(const std::string& username, const std::string& password); + void loginUsingPlain(const std::string& username, const std::string& password); + void loginUsingXOAUTH2(const std::string& username, const std::string& password); + DialogSocket& socket(); + +private: + void sendCommands(const MailMessage& message, const Recipients* pRecipients = 0); + void transportMessage(const MailMessage& message); + + DialogSocket _socket; + bool _isOpen; +}; + + +// +// inlines +// +inline bool SMTPClientSession::isPositiveCompletion(int status) +{ + return status/100 == SMTP_POSITIVE_COMPLETION; +} + + +inline bool SMTPClientSession::isPositiveIntermediate(int status) +{ + return status/100 == SMTP_POSITIVE_INTERMEDIATE; +} + + +inline bool SMTPClientSession::isTransientNegative(int status) +{ + return status/100 == SMTP_TRANSIENT_NEGATIVE; +} + + +inline bool SMTPClientSession::isPermanentNegative(int status) +{ + return status/100 == SMTP_PERMANENT_NEGATIVE; +} + + +inline DialogSocket& SMTPClientSession::socket() +{ + return _socket; +} + + +} } // namespace Poco::Net + + +#endif // Net_SMTPClientSession_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/ServerSocket.h b/contrib/libs/poco/Net/include/Poco/Net/ServerSocket.h new file mode 100644 index 0000000000..d8aca6790a --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/ServerSocket.h @@ -0,0 +1,230 @@ +// +// ServerSocket.h +// +// Library: Net +// Package: Sockets +// Module: ServerSocket +// +// Definition of the ServerSocket class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_ServerSocket_INCLUDED +#define Net_ServerSocket_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/Socket.h" +#include "Poco/Net/StreamSocket.h" + + +namespace Poco { +namespace Net { + + +class Net_API ServerSocket: public Socket + /// This class provides an interface to a + /// TCP server socket. +{ +public: + ServerSocket(); + /// Creates a server socket. + /// + /// The server socket must be bound to + /// an address and put into listening state. + + ServerSocket(const Socket& socket); + /// Creates the ServerSocket with the SocketImpl + /// from another socket. The SocketImpl must be + /// a ServerSocketImpl, otherwise an InvalidArgumentException + /// will be thrown. + + ServerSocket(const SocketAddress& address, int backlog = 64); + /// Creates a server socket, binds it + /// to the given address and puts it in listening + /// state. + /// + /// After successful construction, the server socket + /// is ready to accept connections. + + ServerSocket(Poco::UInt16 port, int backlog = 64); + /// Creates a server socket, binds it + /// to the given port and puts it in listening + /// state. + /// + /// After successful construction, the server socket + /// is ready to accept connections. + + virtual ~ServerSocket(); + /// Destroys the StreamSocket. + + ServerSocket& operator = (const Socket& socket); + /// Assignment operator. + /// + /// Releases the socket's SocketImpl and + /// attaches the SocketImpl from the other socket and + /// increments the reference count of the SocketImpl. + + virtual void bind(const SocketAddress& address, bool reuseAddress = false); + /// Binds a local address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. TCP clients should not bind a socket to a + /// specific address. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + + virtual void bind(const SocketAddress& address, bool reuseAddress, bool reusePort); + /// Binds a local address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. TCP clients should not bind a socket to a + /// specific address. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reuseAddress is true, sets the SO_REUSEPORT + /// socket option. + + virtual void bind(Poco::UInt16 port, bool reuseAddress = false); + /// Binds a local port to the socket. + /// + /// This is usually only done when establishing a server + /// socket. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + + virtual void bind(Poco::UInt16 port, bool reuseAddress, bool reusePort); + /// Binds a local port to the socket. + /// + /// This is usually only done when establishing a server + /// socket. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + + virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false); + /// Binds a local IPv6 address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. TCP clients should not bind a socket to a + /// specific address. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// The given address must be an IPv6 address. The + /// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket + /// according to the ipV6Only parameter. + /// + /// If the library has not been built with IPv6 support, + /// a Poco::NotImplementedException will be thrown. + + virtual void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only); + /// Binds a local IPv6 address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. TCP clients should not bind a socket to a + /// specific address. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + /// + /// The given address must be an IPv6 address. The + /// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket + /// according to the ipV6Only parameter. + /// + /// If the library has not been built with IPv6 support, + /// a Poco::NotImplementedException will be thrown. + + virtual void bind6(Poco::UInt16 port, bool reuseAddress = false, bool ipV6Only = false); + /// Binds a local IPv6 port to the socket. + /// + /// This is usually only done when establishing a server + /// socket. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// The given address must be an IPv6 address. The + /// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket + /// according to the ipV6Only parameter. + /// + /// If the library has not been built with IPv6 support, + /// a Poco::NotImplementedException will be thrown. + + virtual void bind6(Poco::UInt16 port, bool reuseAddress, bool reusePort, bool ipV6Only); + /// Binds a local IPv6 port to the socket. + /// + /// This is usually only done when establishing a server + /// socket. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + /// The given address must be an IPv6 address. The + /// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket + /// according to the ipV6Only parameter. + /// + /// If the library has not been built with IPv6 support, + /// a Poco::NotImplementedException will be thrown. + + virtual void listen(int backlog = 64); + /// Puts the socket into listening state. + /// + /// The socket becomes a passive socket that + /// can accept incoming connection requests. + /// + /// The backlog argument specifies the maximum + /// number of connections that can be queued + /// for this socket. + + virtual StreamSocket acceptConnection(SocketAddress& clientAddr); + /// Gets the next completed connection from the + /// socket's completed connection queue. + /// + /// If the queue is empty, waits until a connection + /// request completes. + /// + /// Returns a new TCP socket for the connection + /// with the client. + /// + /// The client socket's address is returned in clientAddr. + + virtual StreamSocket acceptConnection(); + /// Gets the next completed connection from the + /// socket's completed connection queue. + /// + /// If the queue is empty, waits until a connection + /// request completes. + /// + /// Returns a new TCP socket for the connection + /// with the client. + +protected: + ServerSocket(SocketImpl* pImpl, bool); + /// The bool argument is to resolve an ambiguity with + /// another constructor (Microsoft Visual C++ 2005) +}; + + +} } // namespace Poco::Net + + +#endif // Net_ServerSocket_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/ServerSocketImpl.h b/contrib/libs/poco/Net/include/Poco/Net/ServerSocketImpl.h new file mode 100644 index 0000000000..aaa5c7cc20 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/ServerSocketImpl.h @@ -0,0 +1,45 @@ +// +// ServerSocketImpl.h +// +// Library: Net +// Package: Sockets +// Module: ServerSocketImpl +// +// Definition of the ServerSocketImpl class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_ServerSocketImpl_INCLUDED +#define Net_ServerSocketImpl_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketImpl.h" + + +namespace Poco { +namespace Net { + + +class Net_API ServerSocketImpl: public SocketImpl + /// This class implements a TCP server socket. +{ +public: + ServerSocketImpl(); + /// Creates the ServerSocketImpl. + +protected: + virtual ~ServerSocketImpl(); + /// Destroys the ServerSocketImpl. +}; + + +} } // namespace Poco::Net + + +#endif // Net_ServerSocketImpl_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/Socket.h b/contrib/libs/poco/Net/include/Poco/Net/Socket.h new file mode 100644 index 0000000000..c509187d8d --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/Socket.h @@ -0,0 +1,631 @@ +// +// Socket.h +// +// Library: Net +// Package: Sockets +// Module: Socket +// +// Definition of the Socket class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_Socket_INCLUDED +#define Net_Socket_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketImpl.h" +#include <vector> + + +namespace Poco { +namespace Net { + + +class Net_API Socket + /// Socket is the common base class for + /// StreamSocket, ServerSocket, DatagramSocket and other + /// socket classes. + /// + /// It provides operations common to all socket types. +{ +public: + enum SelectMode + /// The mode argument to poll() and select(). + { + SELECT_READ = 1, + SELECT_WRITE = 2, + SELECT_ERROR = 4 + }; + + typedef std::vector<Socket> SocketList; + + Socket(); + /// Creates an uninitialized socket. + + Socket(const Socket& socket); + /// Copy constructor. + /// + /// Attaches the SocketImpl from the other socket and + /// increments the reference count of the SocketImpl. + + Socket& operator = (const Socket& socket); + /// Assignment operator. + /// + /// Releases the socket's SocketImpl and + /// attaches the SocketImpl from the other socket and + /// increments the reference count of the SocketImpl. + + virtual ~Socket(); + /// Destroys the Socket and releases the + /// SocketImpl. + + bool operator == (const Socket& socket) const; + /// Returns true if both sockets share the same + /// SocketImpl, false otherwise. + + bool operator != (const Socket& socket) const; + /// Returns false if both sockets share the same + /// SocketImpl, true otherwise. + + bool operator < (const Socket& socket) const; + /// Compares the SocketImpl pointers. + + bool operator <= (const Socket& socket) const; + /// Compares the SocketImpl pointers. + + bool operator > (const Socket& socket) const; + /// Compares the SocketImpl pointers. + + bool operator >= (const Socket& socket) const; + /// Compares the SocketImpl pointers. + + void close(); + /// Closes the socket. + + static int select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Poco::Timespan& timeout); + /// Determines the status of one or more sockets, + /// using a call to select(). + /// + /// ReadList contains the list of sockets which should be + /// checked for readability. + /// + /// WriteList contains the list of sockets which should be + /// checked for writeability. + /// + /// ExceptList contains a list of sockets which should be + /// checked for a pending error. + /// + /// Returns the number of sockets ready. + /// + /// After return, + /// * readList contains those sockets ready for reading, + /// * writeList contains those sockets ready for writing, + /// * exceptList contains those sockets with a pending error. + /// + /// If the total number of sockets passed in readList, writeList and + /// exceptList is zero, select() will return immediately and the + /// return value will be 0. + /// + /// If one of the sockets passed to select() is closed while + /// select() runs, select will return immediately. However, + /// the closed socket will not be included in any list. + /// In this case, the return value may be greater than the sum + /// of all sockets in all list. + + bool poll(const Poco::Timespan& timeout, int mode) const; + /// Determines the status of the socket, using a + /// call to poll() or select(). + /// + /// The mode argument is constructed by combining the values + /// of the SelectMode enumeration. + /// + /// Returns true if the next operation corresponding to + /// mode will not block, false otherwise. + + int available() const; + /// Returns the number of bytes available that can be read + /// without causing the socket to block. + + void setSendBufferSize(int size); + /// Sets the size of the send buffer. + + int getSendBufferSize() const; + /// Returns the size of the send buffer. + /// + /// The returned value may be different than the + /// value previously set with setSendBufferSize(), + /// as the system is free to adjust the value. + + void setReceiveBufferSize(int size); + /// Sets the size of the receive buffer. + + int getReceiveBufferSize() const; + /// Returns the size of the receive buffer. + /// + /// The returned value may be different than the + /// value previously set with setReceiveBufferSize(), + /// as the system is free to adjust the value. + + void setSendTimeout(const Poco::Timespan& timeout); + /// Sets the send timeout for the socket. + + Poco::Timespan getSendTimeout() const; + /// Returns the send timeout for the socket. + /// + /// The returned timeout may be different than the + /// timeout previously set with setSendTimeout(), + /// as the system is free to adjust the value. + + void setReceiveTimeout(const Poco::Timespan& timeout); + /// Sets the send timeout for the socket. + /// + /// On systems that do not support SO_RCVTIMEO, a + /// workaround using poll() is provided. + + Poco::Timespan getReceiveTimeout() const; + /// Returns the receive timeout for the socket. + /// + /// The returned timeout may be different than the + /// timeout previously set with getReceiveTimeout(), + /// as the system is free to adjust the value. + + void setOption(int level, int option, int value); + /// Sets the socket option specified by level and option + /// to the given integer value. + + void setOption(int level, int option, unsigned value); + /// Sets the socket option specified by level and option + /// to the given integer value. + + void setOption(int level, int option, unsigned char value); + /// Sets the socket option specified by level and option + /// to the given integer value. + + void setOption(int level, int option, const Poco::Timespan& value); + /// Sets the socket option specified by level and option + /// to the given time value. + + void setOption(int level, int option, const IPAddress& value); + /// Sets the socket option specified by level and option + /// to the given time value. + + void getOption(int level, int option, int& value) const; + /// Returns the value of the socket option + /// specified by level and option. + + void getOption(int level, int option, unsigned& value) const; + /// Returns the value of the socket option + /// specified by level and option. + + void getOption(int level, int option, unsigned char& value) const; + /// Returns the value of the socket option + /// specified by level and option. + + void getOption(int level, int option, Poco::Timespan& value) const; + /// Returns the value of the socket option + /// specified by level and option. + + void getOption(int level, int option, IPAddress& value) const; + /// Returns the value of the socket option + /// specified by level and option. + + void setLinger(bool on, int seconds); + /// Sets the value of the SO_LINGER socket option. + + void getLinger(bool& on, int& seconds) const; + /// Returns the value of the SO_LINGER socket option. + + void setNoDelay(bool flag); + /// Sets the value of the TCP_NODELAY socket option. + + bool getNoDelay() const; + /// Returns the value of the TCP_NODELAY socket option. + + void setKeepAlive(bool flag); + /// Sets the value of the SO_KEEPALIVE socket option. + + bool getKeepAlive() const; + /// Returns the value of the SO_KEEPALIVE socket option. + + void setReuseAddress(bool flag); + /// Sets the value of the SO_REUSEADDR socket option. + + bool getReuseAddress() const; + /// Returns the value of the SO_REUSEADDR socket option. + + void setReusePort(bool flag); + /// Sets the value of the SO_REUSEPORT socket option. + /// Does nothing if the socket implementation does not + /// support SO_REUSEPORT. + + bool getReusePort() const; + /// Returns the value of the SO_REUSEPORT socket option. + /// + /// Returns false if the socket implementation does not + /// support SO_REUSEPORT. + + void setOOBInline(bool flag); + /// Sets the value of the SO_OOBINLINE socket option. + + bool getOOBInline() const; + /// Returns the value of the SO_OOBINLINE socket option. + + void setBlocking(bool flag); + /// Sets the socket in blocking mode if flag is true, + /// disables blocking mode if flag is false. + + bool getBlocking() const; + /// Returns the blocking mode of the socket. + /// This method will only work if the blocking modes of + /// the socket are changed via the setBlocking method! + + SocketAddress address() const; + /// Returns the IP address and port number of the socket. + + SocketAddress peerAddress() const; + /// Returns the IP address and port number of the peer socket. + + SocketImpl* impl() const; + /// Returns the SocketImpl for this socket. + + bool secure() const; + /// Returns true iff the socket's connection is secure + /// (using SSL or TLS). + + static bool supportsIPv4(); + /// Returns true if the system supports IPv4. + + static bool supportsIPv6(); + /// Returns true if the system supports IPv6. + + void init(int af); + /// Creates the underlying system socket for the given + /// address family. + /// + /// Normally, this method should not be called directly, as + /// socket creation will be handled automatically. There are + /// a few situations where calling this method after creation + /// of the Socket object makes sense. One example is setting + /// a socket option before calling bind() on a ServerSocket. + +protected: + Socket(SocketImpl* pImpl); + /// Creates the Socket and attaches the given SocketImpl. + /// The socket takes ownership of the SocketImpl. + + poco_socket_t sockfd() const; + /// Returns the socket descriptor for this socket. + +private: + +#if defined(POCO_HAVE_FD_POLL) +class FDCompare + /// Utility functor used to compare socket file descriptors. + /// Used in poll() member function. +{ +public: + FDCompare(int fd): _fd(fd) { } + inline bool operator()(const Socket& socket) const + { return socket.sockfd() == _fd; } + +private: + FDCompare(); + int _fd; +}; +#endif + + SocketImpl* _pImpl; +}; + + +// +// inlines +// +inline bool Socket::operator == (const Socket& socket) const +{ + return _pImpl == socket._pImpl; +} + + +inline bool Socket::operator != (const Socket& socket) const +{ + return _pImpl != socket._pImpl; +} + + +inline bool Socket::operator < (const Socket& socket) const +{ + return _pImpl < socket._pImpl; +} + + +inline bool Socket::operator <= (const Socket& socket) const +{ + return _pImpl <= socket._pImpl; +} + + +inline bool Socket::operator > (const Socket& socket) const +{ + return _pImpl > socket._pImpl; +} + + +inline bool Socket::operator >= (const Socket& socket) const +{ + return _pImpl >= socket._pImpl; +} + + +inline void Socket::close() +{ + _pImpl->close(); +} + + +inline bool Socket::poll(const Poco::Timespan& timeout, int mode) const +{ + return _pImpl->poll(timeout, mode); +} + + +inline int Socket::available() const +{ + return _pImpl->available(); +} + + +inline void Socket::setSendBufferSize(int size) +{ + _pImpl->setSendBufferSize(size); +} + + +inline int Socket::getSendBufferSize() const +{ + return _pImpl->getSendBufferSize(); +} + + +inline void Socket::setReceiveBufferSize(int size) +{ + _pImpl->setReceiveBufferSize(size); +} + + +inline int Socket::getReceiveBufferSize() const +{ + return _pImpl->getReceiveBufferSize(); +} + + +inline void Socket::setSendTimeout(const Poco::Timespan& timeout) +{ + _pImpl->setSendTimeout(timeout); +} + + +inline Poco::Timespan Socket::getSendTimeout() const +{ + return _pImpl->getSendTimeout(); +} + + +inline void Socket::setReceiveTimeout(const Poco::Timespan& timeout) +{ + _pImpl->setReceiveTimeout(timeout); +} + + +inline Poco::Timespan Socket::getReceiveTimeout() const +{ + return _pImpl->getReceiveTimeout(); +} + + +inline void Socket::setOption(int level, int option, int value) +{ + _pImpl->setOption(level, option, value); +} + + +inline void Socket::setOption(int level, int option, unsigned value) +{ + _pImpl->setOption(level, option, value); +} + + +inline void Socket::setOption(int level, int option, unsigned char value) +{ + _pImpl->setOption(level, option, value); +} + + +inline void Socket::setOption(int level, int option, const Poco::Timespan& value) +{ + _pImpl->setOption(level, option, value); +} + + +inline void Socket::setOption(int level, int option, const IPAddress& value) +{ + _pImpl->setOption(level, option, value); +} + + +inline void Socket::getOption(int level, int option, int& value) const +{ + _pImpl->getOption(level, option, value); +} + + +inline void Socket::getOption(int level, int option, unsigned& value) const +{ + _pImpl->getOption(level, option, value); +} + + +inline void Socket::getOption(int level, int option, unsigned char& value) const +{ + _pImpl->getOption(level, option, value); +} + + +inline void Socket::getOption(int level, int option, Poco::Timespan& value) const +{ + _pImpl->getOption(level, option, value); +} + + +inline void Socket::getOption(int level, int option, IPAddress& value) const +{ + _pImpl->getOption(level, option, value); +} + + +inline void Socket::setLinger(bool on, int seconds) +{ + _pImpl->setLinger(on, seconds); +} + + +inline void Socket::getLinger(bool& on, int& seconds) const +{ + _pImpl->getLinger(on, seconds); +} + + +inline void Socket::setNoDelay(bool flag) +{ + _pImpl->setNoDelay(flag); +} + + +inline bool Socket::getNoDelay() const +{ + return _pImpl->getNoDelay(); +} + + +inline void Socket::setKeepAlive(bool flag) +{ + _pImpl->setKeepAlive(flag); +} + + +inline bool Socket::getKeepAlive() const +{ + return _pImpl->getKeepAlive(); +} + + +inline void Socket::setReuseAddress(bool flag) +{ + _pImpl->setReuseAddress(flag); +} + + +inline bool Socket::getReuseAddress() const +{ + return _pImpl->getReuseAddress(); +} + + +inline void Socket::setReusePort(bool flag) +{ + _pImpl->setReusePort(flag); +} + + +inline bool Socket::getReusePort() const +{ + return _pImpl->getReusePort(); +} + + +inline void Socket::setOOBInline(bool flag) +{ + _pImpl->setOOBInline(flag); +} + + +inline bool Socket::getOOBInline() const +{ + return _pImpl->getOOBInline(); +} + + +inline void Socket::setBlocking(bool flag) +{ + _pImpl->setBlocking(flag); +} + + +inline bool Socket::getBlocking() const +{ + return _pImpl->getBlocking(); +} + + +inline SocketImpl* Socket::impl() const +{ + return _pImpl; +} + + +inline poco_socket_t Socket::sockfd() const +{ + return _pImpl->sockfd(); +} + + +inline SocketAddress Socket::address() const +{ + return _pImpl->address(); +} + + +inline SocketAddress Socket::peerAddress() const +{ + return _pImpl->peerAddress(); +} + + +inline bool Socket::secure() const +{ + return _pImpl->secure(); +} + + +inline bool Socket::supportsIPv4() +{ + return true; +} + + +inline bool Socket::supportsIPv6() +{ +#if defined(POCO_HAVE_IPv6) + return true; +#else + return false; +#endif +} + + +inline void Socket::init(int af) +{ + _pImpl->init(af); +} + + +} } // namespace Poco::Net + + +#endif // Net_Socket_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/SocketAcceptor.h b/contrib/libs/poco/Net/include/Poco/Net/SocketAcceptor.h new file mode 100644 index 0000000000..c9021ecd0b --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/SocketAcceptor.h @@ -0,0 +1,196 @@ +// +// SocketAcceptor.h +// +// Library: Net +// Package: Reactor +// Module: SocketAcceptor +// +// Definition of the SocketAcceptor class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_SocketAcceptor_INCLUDED +#define Net_SocketAcceptor_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketNotification.h" +#include "Poco/Net/SocketReactor.h" +#include "Poco/Net/ServerSocket.h" +#include "Poco/Net/StreamSocket.h" +#include "Poco/Observer.h" + + +namespace Poco { +namespace Net { + + +template <class ServiceHandler> +class SocketAcceptor + /// This class implements the Acceptor part of the + /// Acceptor-Connector design pattern. + /// + /// The Acceptor-Connector pattern has been described in the book + /// "Pattern Languages of Program Design 3", edited by Robert Martin, + /// Frank Buschmann and Dirk Riehle (Addison Wesley, 1997). + /// + /// The Acceptor-Connector design pattern decouples connection + /// establishment and service initialization in a distributed system + /// from the processing performed once a service is initialized. + /// This decoupling is achieved with three components: Acceptors, + /// Connectors and Service Handlers. + /// The SocketAcceptor passively waits for connection requests (usually + /// from a remote Connector) and establishes a connection upon + /// arrival of a connection requests. Also, a Service Handler is + /// initialized to process the data arriving via the connection in + /// an application-specific way. + /// + /// The SocketAcceptor sets up a ServerSocket and registers itself + /// for a ReadableNotification, denoting an incoming connection request. + /// + /// When the ServerSocket becomes readable the SocketAcceptor accepts + /// the connection request and creates a ServiceHandler to + /// service the connection. + /// + /// The ServiceHandler class must provide a constructor that + /// takes a StreamSocket and a SocketReactor as arguments, + /// e.g.: + /// MyServiceHandler(const StreamSocket& socket, ServiceReactor& reactor) + /// + /// When the ServiceHandler is done, it must destroy itself. + /// + /// Subclasses can override the createServiceHandler() factory method + /// if special steps are necessary to create a ServiceHandler object. +{ +public: + explicit SocketAcceptor(ServerSocket& socket): + _socket(socket), + _pReactor(0) + /// Creates a SocketAcceptor, using the given ServerSocket. + { + } + + SocketAcceptor(ServerSocket& socket, SocketReactor& reactor): + _socket(socket), + _pReactor(&reactor) + /// Creates a SocketAcceptor, using the given ServerSocket. + /// The SocketAcceptor registers itself with the given SocketReactor. + { + _pReactor->addEventHandler(_socket, Poco::Observer<SocketAcceptor, + ReadableNotification>(*this, &SocketAcceptor::onAccept)); + } + + virtual ~SocketAcceptor() + /// Destroys the SocketAcceptor. + { + try + { + if (_pReactor) + { + _pReactor->removeEventHandler(_socket, Poco::Observer<SocketAcceptor, + ReadableNotification>(*this, &SocketAcceptor::onAccept)); + } + } + catch (...) + { + poco_unexpected(); + } + } + + void setReactor(SocketReactor& reactor) + /// Sets the reactor for this acceptor. + { + _pReactor = &reactor; + if (!_pReactor->hasEventHandler(_socket, Poco::Observer<SocketAcceptor, + ReadableNotification>(*this, &SocketAcceptor::onAccept))) + { + registerAcceptor(reactor); + } + } + + virtual void registerAcceptor(SocketReactor& reactor) + /// Registers the SocketAcceptor with a SocketReactor. + /// + /// A subclass can override this function to e.g. + /// register an event handler for timeout event. + /// + /// If acceptor was constructed without providing reactor to it, + /// the override of this method must either call the base class + /// implementation or directly register the accept handler with + /// the reactor. + { + if (_pReactor) + throw Poco::InvalidAccessException("Acceptor already registered."); + + _pReactor = &reactor; + _pReactor->addEventHandler(_socket, Poco::Observer<SocketAcceptor, ReadableNotification>(*this, &SocketAcceptor::onAccept)); + } + + virtual void unregisterAcceptor() + /// Unregisters the SocketAcceptor. + /// + /// A subclass can override this function to e.g. + /// unregister its event handler for a timeout event. + /// + /// If the accept handler was registered with the reactor, + /// the overriding method must either call the base class + /// implementation or directly unregister the accept handler. + { + if (_pReactor) + { + _pReactor->removeEventHandler(_socket, Poco::Observer<SocketAcceptor, ReadableNotification>(*this, &SocketAcceptor::onAccept)); + } + } + + void onAccept(ReadableNotification* pNotification) + /// Accepts connection and creates event handler. + { + pNotification->release(); + StreamSocket sock = _socket.acceptConnection(); + _pReactor->wakeUp(); + createServiceHandler(sock); + } + +protected: + virtual ServiceHandler* createServiceHandler(StreamSocket& socket) + /// Create and initialize a new ServiceHandler instance. + /// + /// Subclasses can override this method. + { + return new ServiceHandler(socket, *_pReactor); + } + + SocketReactor* reactor() + /// Returns a pointer to the SocketReactor where + /// this SocketAcceptor is registered. + /// + /// The pointer may be null. + { + return _pReactor; + } + + Socket& socket() + /// Returns a reference to the SocketAcceptor's socket. + { + return _socket; + } + +private: + SocketAcceptor(); + SocketAcceptor(const SocketAcceptor&); + SocketAcceptor& operator = (const SocketAcceptor&); + + ServerSocket _socket; + SocketReactor* _pReactor; +}; + + +} } // namespace Poco::Net + + +#endif // Net_SocketAcceptor_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/SocketAddress.h b/contrib/libs/poco/Net/include/Poco/Net/SocketAddress.h new file mode 100644 index 0000000000..61c5581789 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/SocketAddress.h @@ -0,0 +1,301 @@ +// +// SocketAddress.h +// +// Library: Net +// Package: NetCore +// Module: SocketAddress +// +// Definition of the SocketAddress class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_SocketAddress_INCLUDED +#define Net_SocketAddress_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketAddressImpl.h" +#include <ostream> + + +namespace Poco { + +class BinaryReader; +class BinaryWriter; + +namespace Net { + + +class IPAddress; + + +class Net_API SocketAddress + /// This class represents an internet (IP) endpoint/socket + /// address. The address can belong either to the + /// IPv4 or the IPv6 address family and consists of a + /// host address and a port number. +{ +public: + // The following declarations keep the Family type + // backwards compatible with the previously used + // enum declaration. + typedef AddressFamily::Family Family; + static const Family IPv4 = AddressFamily::IPv4; +#if defined(POCO_HAVE_IPv6) + static const Family IPv6 = AddressFamily::IPv6; +#endif +#if defined(POCO_OS_FAMILY_UNIX) + static const Family UNIX_LOCAL = AddressFamily::UNIX_LOCAL; +#endif + + SocketAddress(); + /// Creates a wildcard (all zero) IPv4 SocketAddress. + + explicit SocketAddress(Family family); + /// Creates a SocketAddress with unspecified (wildcard) IP address + /// of the given family. + + SocketAddress(const IPAddress& hostAddress, Poco::UInt16 portNumber); + /// Creates a SocketAddress from an IP address and given port number. + + explicit SocketAddress(Poco::UInt16 port); + /// Creates a SocketAddress with unspecified (wildcard) IP address + /// and given port number. + + SocketAddress(Family family, Poco::UInt16 port); + /// Creates a SocketAddress with unspecified (wildcard) IP address + /// of the given family, and given port number. + + SocketAddress(const std::string& hostAddress, Poco::UInt16 portNumber); + /// Creates a SocketAddress from an IP address and given port number. + /// + /// The IP address must either be a domain name, or it must + /// be in dotted decimal (IPv4) or hex string (IPv6) format. + + SocketAddress(Family family, const std::string& hostAddress, Poco::UInt16 portNumber); + /// Creates a SocketAddress from an IP address and given port number. + /// + /// The IP address must either be a domain name, or it must + /// be in dotted decimal (IPv4) or hex string (IPv6) format. + /// + /// If a domain name is given in hostAddress, it is resolved and the address + /// matching the given family is used. If no address matching the given family + /// is found, or the IP address given in hostAddress does not match the given + /// family, an AddressFamilyMismatchException is thrown. + + SocketAddress(const std::string& hostAddress, const std::string& portNumber); + /// Creates a SocketAddress from an IP address and the + /// service name or port number. + /// + /// The IP address must either be a domain name, or it must + /// be in dotted decimal (IPv4) or hex string (IPv6) format. + /// + /// The given port must either be a decimal port number, or + /// a service name. + + SocketAddress(Family family, const std::string& hostAddress, const std::string& portNumber); + /// Creates a SocketAddress from an IP address and the + /// service name or port number. + /// + /// The IP address must either be a domain name, or it must + /// be in dotted decimal (IPv4) or hex string (IPv6) format. + /// + /// The given port must either be a decimal port number, or + /// a service name. + /// + /// If a domain name is given in hostAddress, it is resolved and the address + /// matching the given family is used. If no address matching the given family + /// is found, or the IP address given in hostAddress does not match the given + /// family, an AddressFamilyMismatchException is thrown. + + explicit SocketAddress(const std::string& hostAndPort); + /// Creates a SocketAddress from an IP address or host name and the + /// port number/service name. Host name/address and port number must + /// be separated by a colon. In case of an IPv6 address, + /// the address part must be enclosed in brackets. + /// + /// Examples: + /// 192.168.1.10:80 + /// [::ffff:192.168.1.120]:2040 + /// www.appinf.com:8080 + /// + /// On POSIX platforms supporting UNIX_LOCAL sockets, hostAndPort + /// can also be the absolute path of a local socket, starting with a + /// slash, e.g. "/tmp/local.socket". + + SocketAddress(Family family, const std::string& addr); + /// Creates a SocketAddress of the given family from a + /// string representation of the address, which is + /// either an IP address and port number, separated by + /// a colon for IPv4 or IPv6 addresses, or a path for + /// UNIX_LOCAL sockets. + + SocketAddress(const SocketAddress& addr); + /// Creates a SocketAddress by copying another one. + + SocketAddress(const struct sockaddr* addr, poco_socklen_t length); + /// Creates a SocketAddress from a native socket address. + + ~SocketAddress(); + /// Destroys the SocketAddress. + + SocketAddress& operator = (const SocketAddress& socketAddress); + /// Assigns another SocketAddress. + + IPAddress host() const; + /// Returns the host IP address. + + Poco::UInt16 port() const; + /// Returns the port number. + + poco_socklen_t length() const; + /// Returns the length of the internal native socket address. + + const struct sockaddr* addr() const; + /// Returns a pointer to the internal native socket address. + + int af() const; + /// Returns the address family (AF_INET or AF_INET6) of the address. + + std::string toString() const; + /// Returns a string representation of the address. + + Family family() const; + /// Returns the address family of the host's address. + + bool operator < (const SocketAddress& socketAddress) const; + bool operator == (const SocketAddress& socketAddress) const; + bool operator != (const SocketAddress& socketAddress) const; + + enum + { + MAX_ADDRESS_LENGTH = +#if defined(POCO_OS_FAMILY_UNIX) + sizeof(struct sockaddr_un) +#elif defined(POCO_HAVE_IPv6) + sizeof(struct sockaddr_in6) +#else + sizeof(struct sockaddr_in) +#endif + /// Maximum length in bytes of a socket address. + }; + +protected: + void init(const IPAddress& hostAddress, Poco::UInt16 portNumber); + void init(const std::string& hostAddress, Poco::UInt16 portNumber); + void init(Family family, const std::string& hostAddress, Poco::UInt16 portNumber); + void init(Family family, const std::string& address); + void init(const std::string& hostAndPort); + Poco::UInt16 resolveService(const std::string& service); + +private: + typedef Poco::Net::Impl::SocketAddressImpl Impl; + typedef Poco::AutoPtr<Impl> Ptr; + + Ptr pImpl() const; + + void newIPv4(); + void newIPv4(const sockaddr_in*); + void newIPv4(const IPAddress& hostAddress, Poco::UInt16 portNumber); + +#if defined(POCO_HAVE_IPv6) + void newIPv6(const sockaddr_in6*); + void newIPv6(const IPAddress& hostAddress, Poco::UInt16 portNumber); +#endif + +#if defined(POCO_OS_FAMILY_UNIX) + void newLocal(const sockaddr_un* sockAddr); + void newLocal(const std::string& path); +#endif + + Ptr _pImpl; +}; + + +// +// inlines +// +inline SocketAddress::Ptr SocketAddress::pImpl() const +{ + if (_pImpl) return _pImpl; + throw Poco::NullPointerException("Pointer to SocketAddress implementation is NULL."); +} + + +inline void SocketAddress::newIPv4() +{ + _pImpl = new Poco::Net::Impl::IPv4SocketAddressImpl; +} + + +inline void SocketAddress::newIPv4(const sockaddr_in* sockAddr) +{ + _pImpl = new Poco::Net::Impl::IPv4SocketAddressImpl(sockAddr); +} + + +inline void SocketAddress::newIPv4(const IPAddress& hostAddress, Poco::UInt16 portNumber) +{ + _pImpl = new Poco::Net::Impl::IPv4SocketAddressImpl(hostAddress.addr(), htons(portNumber)); +} + + +#if defined(POCO_HAVE_IPv6) +inline void SocketAddress::newIPv6(const sockaddr_in6* sockAddr) +{ + _pImpl = new Poco::Net::Impl::IPv6SocketAddressImpl(sockAddr); +} + + +inline void SocketAddress::newIPv6(const IPAddress& hostAddress, Poco::UInt16 portNumber) +{ + _pImpl = new Poco::Net::Impl::IPv6SocketAddressImpl(hostAddress.addr(), htons(portNumber), hostAddress.scope()); +} +#endif // POCO_HAVE_IPv6 + + +#if defined(POCO_OS_FAMILY_UNIX) +inline void SocketAddress::newLocal(const sockaddr_un* sockAddr) +{ + _pImpl = new Poco::Net::Impl::LocalSocketAddressImpl(sockAddr); +} + + +inline void SocketAddress::newLocal(const std::string& path) +{ + _pImpl = new Poco::Net::Impl::LocalSocketAddressImpl(path.c_str(), path.size()); +} +#endif // POCO_OS_FAMILY_UNIX + + +inline bool SocketAddress::operator == (const SocketAddress& socketAddress) const +{ +#if defined(POCO_OS_FAMILY_UNIX) + if (family() == UNIX_LOCAL) + return toString() == socketAddress.toString(); + else +#endif + return host() == socketAddress.host() && port() == socketAddress.port(); +} + + +inline bool SocketAddress::operator != (const SocketAddress& socketAddress) const +{ + return !(operator == (socketAddress)); +} + + +} } // namespace Poco::Net + + +Net_API Poco::BinaryWriter& operator << (Poco::BinaryWriter& writer, const Poco::Net::SocketAddress& value); +Net_API Poco::BinaryReader& operator >> (Poco::BinaryReader& reader, Poco::Net::SocketAddress& value); +Net_API std::ostream& operator << (std::ostream& ostr, const Poco::Net::SocketAddress& address); + + +#endif // Net_SocketAddress_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/SocketAddressImpl.h b/contrib/libs/poco/Net/include/Poco/Net/SocketAddressImpl.h new file mode 100644 index 0000000000..079bece510 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/SocketAddressImpl.h @@ -0,0 +1,258 @@ +// +// SocketAddressImpl.h +// +// Library: Net +// Package: NetCore +// Module: SocketAddressImpl +// +// Definition of the SocketAddressImpl class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_SocketAddressImpl_INCLUDED +#define Net_SocketAddressImpl_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketDefs.h" +#include "Poco/Net/IPAddress.h" +#include "Poco/RefCountedObject.h" + + +namespace Poco { +namespace Net { +namespace Impl { + + +class Net_API SocketAddressImpl : public Poco::RefCountedObject +{ +public: + typedef AddressFamily::Family Family; + + virtual ~SocketAddressImpl(); + + virtual IPAddress host() const = 0; + virtual UInt16 port() const = 0; + virtual poco_socklen_t length() const = 0; + virtual const struct sockaddr* addr() const = 0; + virtual int af() const = 0; + virtual Family family() const = 0; + virtual std::string toString() const = 0; + +protected: + SocketAddressImpl(); + +private: + SocketAddressImpl(const SocketAddressImpl&); + SocketAddressImpl& operator = (const SocketAddressImpl&); +}; + + +class Net_API IPv4SocketAddressImpl: public SocketAddressImpl +{ +public: + IPv4SocketAddressImpl(); + IPv4SocketAddressImpl(const struct sockaddr_in* addr); + IPv4SocketAddressImpl(const void* addr, UInt16 port); + IPAddress host() const; + UInt16 port() const; + poco_socklen_t length() const; + const struct sockaddr* addr() const; + int af() const; + Family family() const; + std::string toString() const; + +private: + struct sockaddr_in _addr; +}; + + +// +// inlines +// + +inline IPAddress IPv4SocketAddressImpl::host() const +{ + return IPAddress(&_addr.sin_addr, sizeof(_addr.sin_addr)); +} + + +inline UInt16 IPv4SocketAddressImpl::port() const +{ + return _addr.sin_port; +} + + +inline poco_socklen_t IPv4SocketAddressImpl::length() const +{ + return sizeof(_addr); +} + + +inline const struct sockaddr* IPv4SocketAddressImpl::addr() const +{ + return reinterpret_cast<const struct sockaddr*>(&_addr); +} + + +inline int IPv4SocketAddressImpl::af() const +{ + return _addr.sin_family; +} + + +inline SocketAddressImpl::Family IPv4SocketAddressImpl::family() const +{ + return AddressFamily::IPv4; +} + + +#if defined(POCO_HAVE_IPv6) + + +class Net_API IPv6SocketAddressImpl: public SocketAddressImpl +{ +public: + IPv6SocketAddressImpl(const struct sockaddr_in6* addr); + IPv6SocketAddressImpl(const void* addr, UInt16 port); + IPv6SocketAddressImpl(const void* addr, UInt16 port, UInt32 scope); + IPAddress host() const; + UInt16 port() const; + poco_socklen_t length() const; + const struct sockaddr* addr() const; + int af() const; + Family family() const; + std::string toString() const; + +private: + struct sockaddr_in6 _addr; +}; + + +// +// inlines +// + +inline IPAddress IPv6SocketAddressImpl::host() const +{ + return IPAddress(&_addr.sin6_addr, sizeof(_addr.sin6_addr), _addr.sin6_scope_id); +} + + +inline UInt16 IPv6SocketAddressImpl::port() const +{ + return _addr.sin6_port; +} + + +inline poco_socklen_t IPv6SocketAddressImpl::length() const +{ + return sizeof(_addr); +} + + +inline const struct sockaddr* IPv6SocketAddressImpl::addr() const +{ + return reinterpret_cast<const struct sockaddr*>(&_addr); +} + + +inline int IPv6SocketAddressImpl::af() const +{ + return _addr.sin6_family; +} + + +inline SocketAddressImpl::Family IPv6SocketAddressImpl::family() const +{ + return AddressFamily::IPv6; +} + + +#endif // POCO_HAVE_IPv6 + + +#if defined(POCO_OS_FAMILY_UNIX) + + +class Net_API LocalSocketAddressImpl: public SocketAddressImpl +{ +public: + LocalSocketAddressImpl(const struct sockaddr_un* addr); + LocalSocketAddressImpl(const char* path); + LocalSocketAddressImpl(const char* path, std::size_t length); + ~LocalSocketAddressImpl(); + IPAddress host() const; + UInt16 port() const; + poco_socklen_t length() const; + const struct sockaddr* addr() const; + int af() const; + Family family() const; + const char* path() const; + std::string toString() const; + +private: + struct sockaddr_un* _pAddr; + // Note: We allocate struct sockaddr_un on the heap, otherwise we would + // waste a lot of memory due to small object optimization in SocketAddress. +}; + + +// +// inlines +// + +inline IPAddress LocalSocketAddressImpl::host() const +{ + throw Poco::InvalidAccessException("local socket address does not have host IP address"); +} + + +inline UInt16 LocalSocketAddressImpl::port() const +{ + throw Poco::InvalidAccessException("local socket address does not have port number"); +} + + +inline poco_socklen_t LocalSocketAddressImpl::length() const +{ + return sizeof(struct sockaddr_un); +} + + +inline const struct sockaddr* LocalSocketAddressImpl::addr() const +{ + return reinterpret_cast<const struct sockaddr*>(_pAddr); +} + + +inline int LocalSocketAddressImpl::af() const +{ + return _pAddr->sun_family; +} + + +inline SocketAddressImpl::Family LocalSocketAddressImpl::family() const +{ + return AddressFamily::UNIX_LOCAL; +} + + +inline const char* LocalSocketAddressImpl::path() const +{ + return _pAddr->sun_path; +} + + +#endif // POCO_OS_FAMILY_UNIX + + +} } } // namespace Poco::Net::Impl + + +#endif // Net_SocketAddressImpl_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/SocketConnector.h b/contrib/libs/poco/Net/include/Poco/Net/SocketConnector.h new file mode 100644 index 0000000000..d3196c9f62 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/SocketConnector.h @@ -0,0 +1,212 @@ +// +// SocketConnector.h +// +// Library: Net +// Package: Reactor +// Module: SocketConnector +// +// Definition of the SocketConnector class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_SocketConnector_INCLUDED +#define Net_SocketConnector_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketNotification.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/Net/StreamSocket.h" +#include "Poco/Observer.h" + + +namespace Poco { +namespace Net { + + +template <class ServiceHandler> +class SocketConnector + /// This class implements the Connector part of the + /// Acceptor-Connector design pattern. + /// + /// The Acceptor-Connector pattern has been described in the book + /// "Pattern Languages of Program Design 3", edited by Robert Martin, + /// Frank Buschmann and Dirk Riehle (Addison Wesley, 1997). + /// + /// The Acceptor-Connector design pattern decouples connection + /// establishment and service initialization in a distributed system + /// from the processing performed once a service is initialized. + /// This decoupling is achieved with three components: Acceptors, + /// Connectors and Service Handlers. + /// The Connector actively establishes a connection with a remote + /// server socket (usually managed by an Acceptor) and initializes + /// a Service Handler to manage the connection. + /// + /// The SocketConnector sets up a StreamSocket, initiates a non-blocking + /// connect operation and registers itself for ReadableNotification, WritableNotification + /// and ErrorNotification. ReadableNotification or WritableNotification denote the successful + /// establishment of the connection. + /// + /// When the StreamSocket becomes readable or writeable, the SocketConnector + /// creates a ServiceHandler to service the connection and unregisters + /// itself. + /// + /// In case of an error (ErrorNotification), the SocketConnector unregisters itself + /// and calls the onError() method, which can be overridden by subclasses + /// to perform custom error handling. + /// + /// The ServiceHandler class must provide a constructor that + /// takes a StreamSocket and a SocketReactor as arguments, + /// e.g.: + /// MyServiceHandler(const StreamSocket& socket, ServiceReactor& reactor) + /// + /// When the ServiceHandler is done, it must destroy itself. + /// + /// Subclasses can override the createServiceHandler() factory method + /// if special steps are necessary to create a ServiceHandler object. +{ +public: + explicit SocketConnector(SocketAddress& address): + _pReactor(0) + /// Creates a SocketConnector, using the given Socket. + { + _socket.connectNB(address); + } + + SocketConnector(SocketAddress& address, SocketReactor& reactor): + _pReactor(0) + /// Creates an acceptor, using the given ServerSocket. + /// The SocketConnector registers itself with the given SocketReactor. + { + _socket.connectNB(address); + registerConnector(reactor); + } + + virtual ~SocketConnector() + /// Destroys the SocketConnector. + { + try + { + unregisterConnector(); + } + catch (...) + { + poco_unexpected(); + } + } + + virtual void registerConnector(SocketReactor& reactor) + /// Registers the SocketConnector with a SocketReactor. + /// + /// A subclass can override this and, for example, also register + /// an event handler for a timeout event. + /// + /// The overriding method must call the baseclass implementation first. + { + _pReactor = &reactor; + _pReactor->addEventHandler(_socket, Poco::Observer<SocketConnector, ReadableNotification>(*this, &SocketConnector::onReadable)); + _pReactor->addEventHandler(_socket, Poco::Observer<SocketConnector, WritableNotification>(*this, &SocketConnector::onWritable)); + _pReactor->addEventHandler(_socket, Poco::Observer<SocketConnector, ErrorNotification>(*this, &SocketConnector::onError)); + } + + virtual void unregisterConnector() + /// Unregisters the SocketConnector. + /// + /// A subclass can override this and, for example, also unregister + /// its event handler for a timeout event. + /// + /// The overriding method must call the baseclass implementation first. + { + if (_pReactor) + { + _pReactor->removeEventHandler(_socket, Poco::Observer<SocketConnector, ReadableNotification>(*this, &SocketConnector::onReadable)); + _pReactor->removeEventHandler(_socket, Poco::Observer<SocketConnector, WritableNotification>(*this, &SocketConnector::onWritable)); + _pReactor->removeEventHandler(_socket, Poco::Observer<SocketConnector, ErrorNotification>(*this, &SocketConnector::onError)); + } + } + + void onReadable(ReadableNotification* pNotification) + { + pNotification->release(); + int err = _socket.impl()->socketError(); + if (err) + { + onError(err); + unregisterConnector(); + } + else + { + onConnect(); + } + } + + void onWritable(WritableNotification* pNotification) + { + pNotification->release(); + onConnect(); + } + + void onConnect() + { + _socket.setBlocking(true); + createServiceHandler(); + unregisterConnector(); + } + + void onError(ErrorNotification* pNotification) + { + pNotification->release(); + onError(_socket.impl()->socketError()); + unregisterConnector(); + } + +protected: + virtual ServiceHandler* createServiceHandler() + /// Create and initialize a new ServiceHandler instance. + /// + /// Subclasses can override this method. + { + return new ServiceHandler(_socket, *_pReactor); + } + + virtual void onError(int errorCode) + /// Called when the socket cannot be connected. + /// + /// Subclasses can override this method. + { + } + + SocketReactor* reactor() + /// Returns a pointer to the SocketReactor where + /// this SocketConnector is registered. + /// + /// The pointer may be null. + { + return _pReactor; + } + + StreamSocket& socket() + /// Returns a reference to the SocketConnector's socket. + { + return _socket; + } + +private: + SocketConnector(); + SocketConnector(const SocketConnector&); + SocketConnector& operator = (const SocketConnector&); + + StreamSocket _socket; + SocketReactor* _pReactor; +}; + + +} } // namespace Poco::Net + + +#endif // Net_SocketConnector_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/SocketDefs.h b/contrib/libs/poco/Net/include/Poco/Net/SocketDefs.h new file mode 100644 index 0000000000..ef62155389 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/SocketDefs.h @@ -0,0 +1,385 @@ +// +// SocketDefs.h +// +// Library: Net +// Package: NetCore +// Module: SocketDefs +// +// Include platform-specific header files for sockets. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_SocketDefs_INCLUDED +#define Net_SocketDefs_INCLUDED + + +#define POCO_ENOERR 0 + + +#if defined(POCO_OS_FAMILY_WINDOWS) + #include "Poco/UnWindows.h" + #include <winsock2.h> + #include <ws2tcpip.h> + #define POCO_INVALID_SOCKET INVALID_SOCKET + #define poco_socket_t SOCKET + #define poco_socklen_t int + #define poco_ioctl_request_t int + #define poco_closesocket(s) closesocket(s) + #define POCO_EINTR WSAEINTR + #define POCO_EACCES WSAEACCES + #define POCO_EFAULT WSAEFAULT + #define POCO_EINVAL WSAEINVAL + #define POCO_EMFILE WSAEMFILE + #define POCO_EAGAIN WSAEWOULDBLOCK + #define POCO_EWOULDBLOCK WSAEWOULDBLOCK + #define POCO_EINPROGRESS WSAEINPROGRESS + #define POCO_EALREADY WSAEALREADY + #define POCO_ENOTSOCK WSAENOTSOCK + #define POCO_EDESTADDRREQ WSAEDESTADDRREQ + #define POCO_EMSGSIZE WSAEMSGSIZE + #define POCO_EPROTOTYPE WSAEPROTOTYPE + #define POCO_ENOPROTOOPT WSAENOPROTOOPT + #define POCO_EPROTONOSUPPORT WSAEPROTONOSUPPORT + #define POCO_ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT + #define POCO_ENOTSUP WSAEOPNOTSUPP + #define POCO_EPFNOSUPPORT WSAEPFNOSUPPORT + #define POCO_EAFNOSUPPORT WSAEAFNOSUPPORT + #define POCO_EADDRINUSE WSAEADDRINUSE + #define POCO_EADDRNOTAVAIL WSAEADDRNOTAVAIL + #define POCO_ENETDOWN WSAENETDOWN + #define POCO_ENETUNREACH WSAENETUNREACH + #define POCO_ENETRESET WSAENETRESET + #define POCO_ECONNABORTED WSAECONNABORTED + #define POCO_ECONNRESET WSAECONNRESET + #define POCO_ENOBUFS WSAENOBUFS + #define POCO_EISCONN WSAEISCONN + #define POCO_ENOTCONN WSAENOTCONN + #define POCO_ESHUTDOWN WSAESHUTDOWN + #define POCO_ETIMEDOUT WSAETIMEDOUT + #define POCO_ECONNREFUSED WSAECONNREFUSED + #define POCO_EHOSTDOWN WSAEHOSTDOWN + #define POCO_EHOSTUNREACH WSAEHOSTUNREACH + #define POCO_ESYSNOTREADY WSASYSNOTREADY + #define POCO_ENOTINIT WSANOTINITIALISED + #define POCO_HOST_NOT_FOUND WSAHOST_NOT_FOUND + #define POCO_TRY_AGAIN WSATRY_AGAIN + #define POCO_NO_RECOVERY WSANO_RECOVERY + #define POCO_NO_DATA WSANO_DATA + #ifndef ADDRESS_FAMILY + #define ADDRESS_FAMILY USHORT + #endif +#elif defined(POCO_VXWORKS) + #include <hostLib.h> + #error #include <ifLib.h> + #error #include <inetLib.h> + #include <ioLib.h> + #include <resolvLib.h> + #include <types.h> + #include <socket.h> + #include <netinet/tcp.h> + #define POCO_INVALID_SOCKET -1 + #define poco_socket_t int + #define poco_socklen_t int + #define poco_ioctl_request_t int + #define poco_closesocket(s) ::close(s) + #define POCO_EINTR EINTR + #define POCO_EACCES EACCES + #define POCO_EFAULT EFAULT + #define POCO_EINVAL EINVAL + #define POCO_EMFILE EMFILE + #define POCO_EAGAIN EAGAIN + #define POCO_EWOULDBLOCK EWOULDBLOCK + #define POCO_EINPROGRESS EINPROGRESS + #define POCO_EALREADY EALREADY + #define POCO_ENOTSOCK ENOTSOCK + #define POCO_EDESTADDRREQ EDESTADDRREQ + #define POCO_EMSGSIZE EMSGSIZE + #define POCO_EPROTOTYPE EPROTOTYPE + #define POCO_ENOPROTOOPT ENOPROTOOPT + #define POCO_EPROTONOSUPPORT EPROTONOSUPPORT + #define POCO_ESOCKTNOSUPPORT ESOCKTNOSUPPORT + #define POCO_ENOTSUP ENOTSUP + #define POCO_EPFNOSUPPORT EPFNOSUPPORT + #define POCO_EAFNOSUPPORT EAFNOSUPPORT + #define POCO_EADDRINUSE EADDRINUSE + #define POCO_EADDRNOTAVAIL EADDRNOTAVAIL + #define POCO_ENETDOWN ENETDOWN + #define POCO_ENETUNREACH ENETUNREACH + #define POCO_ENETRESET ENETRESET + #define POCO_ECONNABORTED ECONNABORTED + #define POCO_ECONNRESET ECONNRESET + #define POCO_ENOBUFS ENOBUFS + #define POCO_EISCONN EISCONN + #define POCO_ENOTCONN ENOTCONN + #define POCO_ESHUTDOWN ESHUTDOWN + #define POCO_ETIMEDOUT ETIMEDOUT + #define POCO_ECONNREFUSED ECONNREFUSED + #define POCO_EHOSTDOWN EHOSTDOWN + #define POCO_EHOSTUNREACH EHOSTUNREACH + #define POCO_ESYSNOTREADY -4 + #define POCO_ENOTINIT -5 + #define POCO_HOST_NOT_FOUND HOST_NOT_FOUND + #define POCO_TRY_AGAIN TRY_AGAIN + #define POCO_NO_RECOVERY NO_RECOVERY + #define POCO_NO_DATA NO_DATA +#elif defined(POCO_OS_FAMILY_UNIX) + #include <unistd.h> + #include <errno.h> + #include <sys/types.h> + #include <sys/socket.h> + #include <sys/un.h> + #include <fcntl.h> + #if POCO_OS != POCO_OS_HPUX + #include <sys/select.h> + #endif + #include <sys/ioctl.h> + #include <arpa/inet.h> + #include <netinet/in.h> + #include <netinet/tcp.h> + #include <netdb.h> + #if defined(POCO_OS_FAMILY_UNIX) + #if (POCO_OS == POCO_OS_LINUX) || (POCO_OS == POCO_OS_ANDROID) + // Net/src/NetworkInterface.cpp changed #include <linux/if.h> to #include <net/if.h> + // no more conflict, can use #include <net/if.h> here + #include <net/if.h> + #elif (POCO_OS == POCO_OS_HPUX) + extern "C" + { + #include <net/if.h> + } + #else + #include <net/if.h> + #endif + #endif + #if (POCO_OS == POCO_OS_SOLARIS) || (POCO_OS == POCO_OS_MAC_OS_X) + #include <sys/sockio.h> + #include <sys/filio.h> + #endif + #define POCO_INVALID_SOCKET -1 + #define poco_socket_t int + #define poco_socklen_t socklen_t + #define poco_fcntl_request_t int + #if defined(POCO_OS_FAMILY_BSD) + #define poco_ioctl_request_t unsigned long + #else + #define poco_ioctl_request_t int + #endif + #define poco_closesocket(s) ::close(s) + #define POCO_EINTR EINTR + #define POCO_EACCES EACCES + #define POCO_EFAULT EFAULT + #define POCO_EINVAL EINVAL + #define POCO_EMFILE EMFILE + #define POCO_EAGAIN EAGAIN + #define POCO_EWOULDBLOCK EWOULDBLOCK + #define POCO_EINPROGRESS EINPROGRESS + #define POCO_EALREADY EALREADY + #define POCO_ENOTSOCK ENOTSOCK + #define POCO_EDESTADDRREQ EDESTADDRREQ + #define POCO_EMSGSIZE EMSGSIZE + #define POCO_EPROTOTYPE EPROTOTYPE + #define POCO_ENOPROTOOPT ENOPROTOOPT + #define POCO_EPROTONOSUPPORT EPROTONOSUPPORT + #if defined(ESOCKTNOSUPPORT) + #define POCO_ESOCKTNOSUPPORT ESOCKTNOSUPPORT + #else + #define POCO_ESOCKTNOSUPPORT -1 + #endif + #define POCO_ENOTSUP ENOTSUP + #define POCO_EPFNOSUPPORT EPFNOSUPPORT + #define POCO_EAFNOSUPPORT EAFNOSUPPORT + #define POCO_EADDRINUSE EADDRINUSE + #define POCO_EADDRNOTAVAIL EADDRNOTAVAIL + #define POCO_ENETDOWN ENETDOWN + #define POCO_ENETUNREACH ENETUNREACH + #define POCO_ENETRESET ENETRESET + #define POCO_ECONNABORTED ECONNABORTED + #define POCO_ECONNRESET ECONNRESET + #define POCO_ENOBUFS ENOBUFS + #define POCO_EISCONN EISCONN + #define POCO_ENOTCONN ENOTCONN + #if defined(ESHUTDOWN) + #define POCO_ESHUTDOWN ESHUTDOWN + #else + #define POCO_ESHUTDOWN -2 + #endif + #define POCO_ETIMEDOUT ETIMEDOUT + #define POCO_ECONNREFUSED ECONNREFUSED + #if defined(EHOSTDOWN) + #define POCO_EHOSTDOWN EHOSTDOWN + #else + #define POCO_EHOSTDOWN -3 + #endif + #define POCO_EHOSTUNREACH EHOSTUNREACH + #define POCO_ESYSNOTREADY -4 + #define POCO_ENOTINIT -5 + #define POCO_HOST_NOT_FOUND HOST_NOT_FOUND + #define POCO_TRY_AGAIN TRY_AGAIN + #define POCO_NO_RECOVERY NO_RECOVERY + #define POCO_NO_DATA NO_DATA +#endif + + +#if defined(POCO_OS_FAMILY_BSD) || (POCO_OS == POCO_OS_TRU64) || (POCO_OS == POCO_OS_AIX) || (POCO_OS == POCO_OS_IRIX) || (POCO_OS == POCO_OS_QNX) || (POCO_OS == POCO_OS_VXWORKS) + #define POCO_HAVE_SALEN 1 +#endif + + +#if POCO_OS != POCO_OS_VXWORKS && !defined(POCO_NET_NO_ADDRINFO) + #define POCO_HAVE_ADDRINFO 1 +#endif + + +#if POCO_OS == POCO_OS_LINUX + #define POCO_HAVE_ADDRINFO_A 1 +#endif + + +/// Without this option, Poco library will restart recv after EINTR, +/// but it doesn't update socket receive timeout that leads to infinite wait +/// when query profiler is activated. The issue persisted in delayed_replica_failover +/// integration test after we enabled query profiler by default. +#define POCO_BROKEN_TIMEOUTS 1 + + +#if defined(POCO_HAVE_ADDRINFO) + #ifndef AI_PASSIVE + #define AI_PASSIVE 0 + #endif + #ifndef AI_CANONNAME + #define AI_CANONNAME 0 + #endif + #ifndef AI_NUMERICHOST + #define AI_NUMERICHOST 0 + #endif + #ifndef AI_NUMERICSERV + #define AI_NUMERICSERV 0 + #endif + #ifndef AI_ALL + #define AI_ALL 0 + #endif + #ifndef AI_ADDRCONFIG + #define AI_ADDRCONFIG 0 + #endif + #ifndef AI_V4MAPPED + #define AI_V4MAPPED 0 + #endif +#endif + + +#if defined(POCO_HAVE_SALEN) + #define poco_set_sa_len(pSA, len) (pSA)->sa_len = (len) + #define poco_set_sin_len(pSA) (pSA)->sin_len = sizeof(struct sockaddr_in) + #if defined(POCO_HAVE_IPv6) + #define poco_set_sin6_len(pSA) (pSA)->sin6_len = sizeof(struct sockaddr_in6) + #endif + #if defined(POCO_OS_FAMILY_UNIX) + #define poco_set_sun_len(pSA, len) (pSA)->sun_len = (len) + #endif +#else + #define poco_set_sa_len(pSA, len) (void) 0 + #define poco_set_sin_len(pSA) (void) 0 + #define poco_set_sin6_len(pSA) (void) 0 + #define poco_set_sun_len(pSA, len) (void) 0 +#endif + + +#ifndef INADDR_NONE + #define INADDR_NONE 0xffffffff +#endif + +#ifndef INADDR_ANY + #define INADDR_ANY 0x00000000 +#endif + +#ifndef INADDR_BROADCAST + #define INADDR_BROADCAST 0xffffffff +#endif + +#ifndef INADDR_LOOPBACK + #define INADDR_LOOPBACK 0x7f000001 +#endif + +#ifndef INADDR_UNSPEC_GROUP + #define INADDR_UNSPEC_GROUP 0xe0000000 +#endif + +#ifndef INADDR_ALLHOSTS_GROUP + #define INADDR_ALLHOSTS_GROUP 0xe0000001 +#endif + +#ifndef INADDR_ALLRTRS_GROUP + #define INADDR_ALLRTRS_GROUP 0xe0000002 +#endif + +#ifndef INADDR_MAX_LOCAL_GROUP + #define INADDR_MAX_LOCAL_GROUP 0xe00000ff +#endif + +#if defined(POCO_ARCH_BIG_ENDIAN) + #define poco_ntoh_16(x) (x) + #define poco_ntoh_32(x) (x) +#else + #define poco_ntoh_16(x) \ + ((((x) >> 8) & 0x00ff) | (((x) << 8) & 0xff00)) + #define poco_ntoh_32(x) \ + ((((x) >> 24) & 0x000000ff) | (((x) >> 8) & 0x0000ff00) | (((x) << 8) & 0x00ff0000) | (((x) << 24) & 0xff000000)) +#endif +#define poco_hton_16(x) poco_ntoh_16(x) +#define poco_hton_32(x) poco_ntoh_32(x) + + +#if !defined(s6_addr16) + #if defined(POCO_OS_FAMILY_WINDOWS) + #define s6_addr16 u.Word + #else + #define s6_addr16 __u6_addr.__u6_addr16 + #endif +#endif + + +#if !defined(s6_addr32) + #if defined(POCO_OS_FAMILY_UNIX) + #if (POCO_OS == POCO_OS_SOLARIS) + #define s6_addr32 _S6_un._S6_u32 + #else + #define s6_addr32 __u6_addr.__u6_addr32 + #endif + #endif +#endif + + +namespace Poco { +namespace Net { + + +struct AddressFamily + /// AddressFamily::Family replaces the previously used IPAddress::Family + /// enumeration and is now used for IPAddress::Family and SocketAddress::Family. +{ + enum Family + /// Possible address families for socket addresses. + { + IPv4, + /// IPv4 address family. + #if defined(POCO_HAVE_IPv6) + IPv6, + /// IPv6 address family. + #endif + #if defined(POCO_OS_FAMILY_UNIX) + UNIX_LOCAL + /// UNIX domain socket address family. Available on UNIX/POSIX platforms only. + #endif + }; +}; + + +} } // namespace Poco::Net + + +#endif // Net_SocketDefs_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/SocketImpl.h b/contrib/libs/poco/Net/include/Poco/Net/SocketImpl.h new file mode 100644 index 0000000000..d1fec1de7d --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/SocketImpl.h @@ -0,0 +1,503 @@ +// +// SocketImpl.h +// +// Library: Net +// Package: Sockets +// Module: SocketImpl +// +// Definition of the SocketImpl class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_SocketImpl_INCLUDED +#define Net_SocketImpl_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketDefs.h" +#include "Poco/Net/SocketAddress.h" +#include "Poco/RefCountedObject.h" +#include "Poco/Timespan.h" + + +namespace Poco { +namespace Net { + + +class Net_API SocketImpl: public Poco::RefCountedObject + /// This class encapsulates the Berkeley sockets API. + /// + /// Subclasses implement specific socket types like + /// stream or datagram sockets. + /// + /// You should not create any instances of this class. +{ +public: + enum SelectMode + { + SELECT_READ = 1, + SELECT_WRITE = 2, + SELECT_ERROR = 4 + }; + + virtual SocketImpl* acceptConnection(SocketAddress& clientAddr); + /// Get the next completed connection from the + /// socket's completed connection queue. + /// + /// If the queue is empty, waits until a connection + /// request completes. + /// + /// Returns a new TCP socket for the connection + /// with the client. + /// + /// The client socket's address is returned in clientAddr. + + virtual void connect(const SocketAddress& address); + /// Initializes the socket and establishes a connection to + /// the TCP server at the given address. + /// + /// Can also be used for UDP sockets. In this case, no + /// connection is established. Instead, incoming and outgoing + /// packets are restricted to the specified address. + + virtual void connect(const SocketAddress& address, const Poco::Timespan& timeout); + /// Initializes the socket, sets the socket timeout and + /// establishes a connection to the TCP server at the given address. + + virtual void connectNB(const SocketAddress& address); + /// Initializes the socket and establishes a connection to + /// the TCP server at the given address. Prior to opening the + /// connection the socket is set to nonblocking mode. + + virtual void bind(const SocketAddress& address, bool reuseAddress = false); + /// Bind a local address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. TCP clients should not bind a socket to a + /// specific address. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + + virtual void bind(const SocketAddress& address, bool reuseAddress, bool reusePort ); + /// Bind a local address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. TCP clients should not bind a socket to a + /// specific address. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + + virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false); + /// Bind a local IPv6 address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. TCP clients should not bind a socket to a + /// specific address. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// The given address must be an IPv6 address. The + /// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket + /// according to the ipV6Only parameter. + /// + /// If the library has not been built with IPv6 support, + /// a Poco::NotImplementedException will be thrown. + + virtual void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only); + /// Bind a local IPv6 address to the socket. + /// + /// This is usually only done when establishing a server + /// socket. TCP clients should not bind a socket to a + /// specific address. + /// + /// If reuseAddress is true, sets the SO_REUSEADDR + /// socket option. + /// + /// If reusePort is true, sets the SO_REUSEPORT + /// socket option. + /// + /// The given address must be an IPv6 address. The + /// IPPROTO_IPV6/IPV6_V6ONLY option is set on the socket + /// according to the ipV6Only parameter. + /// + /// If the library has not been built with IPv6 support, + /// a Poco::NotImplementedException will be thrown. + + virtual void listen(int backlog = 64); + /// Puts the socket into listening state. + /// + /// The socket becomes a passive socket that + /// can accept incoming connection requests. + /// + /// The backlog argument specifies the maximum + /// number of connections that can be queued + /// for this socket. + + virtual void close(); + /// Close the socket. + + virtual void shutdownReceive(); + /// Shuts down the receiving part of the socket connection. + + virtual void shutdownSend(); + /// Shuts down the sending part of the socket connection. + + virtual void shutdown(); + /// Shuts down both the receiving and the sending part + /// of the socket connection. + + virtual int sendBytes(const void* buffer, int length, int flags = 0); + /// Sends the contents of the given buffer through + /// the socket. + /// + /// Returns the number of bytes sent, which may be + /// less than the number of bytes specified. + /// + /// Certain socket implementations may also return a negative + /// value denoting a certain condition. + + virtual int receiveBytes(void* buffer, int length, int flags = 0); + /// Receives data from the socket and stores it + /// in buffer. Up to length bytes are received. + /// + /// Returns the number of bytes received. + /// + /// Certain socket implementations may also return a negative + /// value denoting a certain condition. + + virtual int sendTo(const void* buffer, int length, const SocketAddress& address, int flags = 0); + /// Sends the contents of the given buffer through + /// the socket to the given address. + /// + /// Returns the number of bytes sent, which may be + /// less than the number of bytes specified. + + virtual int receiveFrom(void* buffer, int length, SocketAddress& address, int flags = 0); + /// Receives data from the socket and stores it + /// in buffer. Up to length bytes are received. + /// Stores the address of the sender in address. + /// + /// Returns the number of bytes received. + + virtual void sendUrgent(unsigned char data); + /// Sends one byte of urgent data through + /// the socket. + /// + /// The data is sent with the MSG_OOB flag. + /// + /// The preferred way for a socket to receive urgent data + /// is by enabling the SO_OOBINLINE option. + + virtual int available(); + /// Returns the number of bytes available that can be read + /// without causing the socket to block. + + virtual bool poll(const Poco::Timespan& timeout, int mode); + /// Determines the status of the socket, using a + /// call to select(). + /// + /// The mode argument is constructed by combining the values + /// of the SelectMode enumeration. + /// + /// Returns true if the next operation corresponding to + /// mode will not block, false otherwise. + + bool pollImpl(Poco::Timespan& timeout, int mode); + /// Modifies `timeout` + + virtual void setSendBufferSize(int size); + /// Sets the size of the send buffer. + + virtual int getSendBufferSize(); + /// Returns the size of the send buffer. + /// + /// The returned value may be different than the + /// value previously set with setSendBufferSize(), + /// as the system is free to adjust the value. + + virtual void setReceiveBufferSize(int size); + /// Sets the size of the receive buffer. + + virtual int getReceiveBufferSize(); + /// Returns the size of the receive buffer. + /// + /// The returned value may be different than the + /// value previously set with setReceiveBufferSize(), + /// as the system is free to adjust the value. + + virtual void setSendTimeout(const Poco::Timespan& timeout); + /// Sets the send timeout for the socket. + + virtual Poco::Timespan getSendTimeout(); + /// Returns the send timeout for the socket. + /// + /// The returned timeout may be different than the + /// timeout previously set with setSendTimeout(), + /// as the system is free to adjust the value. + + virtual void setReceiveTimeout(const Poco::Timespan& timeout); + /// Sets the send timeout for the socket. + /// + /// On systems that do not support SO_RCVTIMEO, a + /// workaround using poll() is provided. + + virtual Poco::Timespan getReceiveTimeout(); + /// Returns the receive timeout for the socket. + /// + /// The returned timeout may be different than the + /// timeout previously set with setReceiveTimeout(), + /// as the system is free to adjust the value. + + virtual SocketAddress address(); + /// Returns the IP address and port number of the socket. + + virtual SocketAddress peerAddress(); + /// Returns the IP address and port number of the peer socket. + + void setOption(int level, int option, int value); + /// Sets the socket option specified by level and option + /// to the given integer value. + + void setOption(int level, int option, unsigned value); + /// Sets the socket option specified by level and option + /// to the given integer value. + + void setOption(int level, int option, unsigned char value); + /// Sets the socket option specified by level and option + /// to the given integer value. + + void setOption(int level, int option, const Poco::Timespan& value); + /// Sets the socket option specified by level and option + /// to the given time value. + + void setOption(int level, int option, const IPAddress& value); + /// Sets the socket option specified by level and option + /// to the given time value. + + virtual void setRawOption(int level, int option, const void* value, poco_socklen_t length); + /// Sets the socket option specified by level and option + /// to the given time value. + + void getOption(int level, int option, int& value); + /// Returns the value of the socket option + /// specified by level and option. + + void getOption(int level, int option, unsigned& value); + /// Returns the value of the socket option + /// specified by level and option. + + void getOption(int level, int option, unsigned char& value); + /// Returns the value of the socket option + /// specified by level and option. + + void getOption(int level, int option, Poco::Timespan& value); + /// Returns the value of the socket option + /// specified by level and option. + + void getOption(int level, int option, IPAddress& value); + /// Returns the value of the socket option + /// specified by level and option. + + virtual void getRawOption(int level, int option, void* value, poco_socklen_t& length); + /// Returns the value of the socket option + /// specified by level and option. + + void setLinger(bool on, int seconds); + /// Sets the value of the SO_LINGER socket option. + + void getLinger(bool& on, int& seconds); + /// Returns the value of the SO_LINGER socket option. + + void setNoDelay(bool flag); + /// Sets the value of the TCP_NODELAY socket option. + + bool getNoDelay(); + /// Returns the value of the TCP_NODELAY socket option. + + void setKeepAlive(bool flag); + /// Sets the value of the SO_KEEPALIVE socket option. + + bool getKeepAlive(); + /// Returns the value of the SO_KEEPALIVE socket option. + + void setReuseAddress(bool flag); + /// Sets the value of the SO_REUSEADDR socket option. + + bool getReuseAddress(); + /// Returns the value of the SO_REUSEADDR socket option. + + void setReusePort(bool flag); + /// Sets the value of the SO_REUSEPORT socket option. + /// Does nothing if the socket implementation does not + /// support SO_REUSEPORT. + + bool getReusePort(); + /// Returns the value of the SO_REUSEPORT socket option. + /// + /// Returns false if the socket implementation does not + /// support SO_REUSEPORT. + + void setOOBInline(bool flag); + /// Sets the value of the SO_OOBINLINE socket option. + + bool getOOBInline(); + /// Returns the value of the SO_OOBINLINE socket option. + + void setBroadcast(bool flag); + /// Sets the value of the SO_BROADCAST socket option. + + bool getBroadcast(); + /// Returns the value of the SO_BROADCAST socket option. + + virtual void setBlocking(bool flag); + /// Sets the socket in blocking mode if flag is true, + /// disables blocking mode if flag is false. + + virtual bool getBlocking() const; + /// Returns the blocking mode of the socket. + /// This method will only work if the blocking modes of + /// the socket are changed via the setBlocking method! + + virtual bool secure() const; + /// Returns true iff the socket's connection is secure + /// (using SSL or TLS). + + int socketError(); + /// Returns the value of the SO_ERROR socket option. + + poco_socket_t sockfd() const; + /// Returns the socket descriptor for the + /// underlying native socket. + + void ioctl(poco_ioctl_request_t request, int& arg); + /// A wrapper for the ioctl system call. + + void ioctl(poco_ioctl_request_t request, void* arg); + /// A wrapper for the ioctl system call. + +#if defined(POCO_OS_FAMILY_UNIX) + int fcntl(poco_fcntl_request_t request); + /// A wrapper for the fcntl system call. + + int fcntl(poco_fcntl_request_t request, long arg); + /// A wrapper for the fcntl system call. +#endif + + bool initialized() const; + /// Returns true iff the underlying socket is initialized. + +protected: + SocketImpl(); + /// Creates a SocketImpl. + + SocketImpl(poco_socket_t sockfd); + /// Creates a SocketImpl using the given native socket. + + virtual ~SocketImpl(); + /// Destroys the SocketImpl. + /// Closes the socket if it is still open. + + virtual void init(int af); + /// Creates the underlying native socket. + /// + /// Subclasses must implement this method so + /// that it calls initSocket() with the + /// appropriate arguments. + /// + /// The default implementation creates a + /// stream socket. + + void initSocket(int af, int type, int proto = 0); + /// Creates the underlying native socket. + /// + /// The first argument, af, specifies the address family + /// used by the socket, which should be either AF_INET or + /// AF_INET6. + /// + /// The second argument, type, specifies the type of the + /// socket, which can be one of SOCK_STREAM, SOCK_DGRAM + /// or SOCK_RAW. + /// + /// The third argument, proto, is normally set to 0, + /// except for raw sockets. + + void reset(poco_socket_t fd = POCO_INVALID_SOCKET); + /// Allows subclasses to set the socket manually, iff no valid socket is set yet. + + static int lastError(); + /// Returns the last error code. + + static void error(); + /// Throws an appropriate exception for the last error. + + static void error(const std::string& arg); + /// Throws an appropriate exception for the last error. + + static void error(int code); + /// Throws an appropriate exception for the given error code. + + static void error(int code, const std::string& arg); + /// Throws an appropriate exception for the given error code. + +protected: + SocketImpl(const SocketImpl&); + SocketImpl& operator = (const SocketImpl&); + + poco_socket_t _sockfd; + Poco::Timespan _recvTimeout; + Poco::Timespan _sndTimeout; + bool _blocking; + bool _isBrokenTimeout; + + friend class Socket; + friend class SecureSocketImpl; + friend class PollSetImpl; +}; + + +// +// inlines +// +inline poco_socket_t SocketImpl::sockfd() const +{ + return _sockfd; +} + + +inline bool SocketImpl::initialized() const +{ + return _sockfd != POCO_INVALID_SOCKET; +} + + +inline int SocketImpl::lastError() +{ +#if defined(_WIN32) + return WSAGetLastError(); +#else + return errno; +#endif +} + + +inline bool SocketImpl::getBlocking() const +{ + return _blocking; +} + + +} } // namespace Poco::Net + + +#endif // Net_SocketImpl_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/SocketNotification.h b/contrib/libs/poco/Net/include/Poco/Net/SocketNotification.h new file mode 100644 index 0000000000..7b857ecfe8 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/SocketNotification.h @@ -0,0 +1,153 @@ +// +// SocketNotification.h +// +// Library: Net +// Package: Reactor +// Module: SocketNotification +// +// Definition of the SocketNotification class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_SocketNotification_INCLUDED +#define Net_SocketNotification_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/Socket.h" +#include "Poco/Notification.h" + + +namespace Poco { +namespace Net { + + +class SocketReactor; + + +class Net_API SocketNotification: public Poco::Notification + /// The base class for all notifications generated by + /// the SocketReactor. +{ +public: + explicit SocketNotification(SocketReactor* pReactor); + /// Creates the SocketNotification for the given SocketReactor. + + virtual ~SocketNotification(); + /// Destroys the SocketNotification. + + SocketReactor& source() const; + /// Returns the SocketReactor that generated the notification. + + Socket socket() const; + /// Returns the socket that caused the notification. + +private: + void setSocket(const Socket& socket); + + SocketReactor* _pReactor; + Socket _socket; + + friend class SocketNotifier; +}; + + +class Net_API ReadableNotification: public SocketNotification + /// This notification is sent if a socket has become readable. +{ +public: + ReadableNotification(SocketReactor* pReactor); + /// Creates the ReadableNotification for the given SocketReactor. + + ~ReadableNotification(); + /// Destroys the ReadableNotification. +}; + + +class Net_API WritableNotification: public SocketNotification + /// This notification is sent if a socket has become writable. +{ +public: + WritableNotification(SocketReactor* pReactor); + /// Creates the WritableNotification for the given SocketReactor. + + ~WritableNotification(); + /// Destroys the WritableNotification. +}; + + +class Net_API ErrorNotification: public SocketNotification + /// This notification is sent if a socket has signalled an error. +{ +public: + ErrorNotification(SocketReactor* pReactor); + /// Creates the ErrorNotification for the given SocketReactor. + + ~ErrorNotification(); + /// Destroys the ErrorNotification. +}; + + +class Net_API TimeoutNotification: public SocketNotification + /// This notification is sent if no other event has occurred + /// for a specified time. +{ +public: + TimeoutNotification(SocketReactor* pReactor); + /// Creates the TimeoutNotification for the given SocketReactor. + + ~TimeoutNotification(); + /// Destroys the TimeoutNotification. +}; + + +class Net_API IdleNotification: public SocketNotification + /// This notification is sent when the SocketReactor does + /// not have any sockets to react to. +{ +public: + IdleNotification(SocketReactor* pReactor); + /// Creates the IdleNotification for the given SocketReactor. + + ~IdleNotification(); + /// Destroys the IdleNotification. +}; + + +class Net_API ShutdownNotification: public SocketNotification + /// This notification is sent when the SocketReactor is + /// about to shut down. +{ +public: + ShutdownNotification(SocketReactor* pReactor); + /// Creates the ShutdownNotification for the given SocketReactor. + + ~ShutdownNotification(); + /// Destroys the ShutdownNotification. +}; + + +// +// inlines +// +inline SocketReactor& SocketNotification::source() const +{ + return *_pReactor; +} + + +inline Socket SocketNotification::socket() const +{ + return _socket; +} + + +} } // namespace Poco::Net + + +#endif // Net_SocketNotification_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/SocketNotifier.h b/contrib/libs/poco/Net/include/Poco/Net/SocketNotifier.h new file mode 100644 index 0000000000..a98e407a3d --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/SocketNotifier.h @@ -0,0 +1,110 @@ +// +// SocketNotifier.h +// +// Library: Net +// Package: Reactor +// Module: SocketNotifier +// +// Definition of the SocketNotifier class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_SocketNotifier_INCLUDED +#define Net_SocketNotifier_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/Socket.h" +#include "Poco/RefCountedObject.h" +#include "Poco/NotificationCenter.h" +#include "Poco/Observer.h" +#include <set> + + +namespace Poco { +namespace Net { + + +class Socket; +class SocketReactor; +class SocketNotification; + + +class Net_API SocketNotifier: public Poco::RefCountedObject + /// This class is used internally by SocketReactor + /// to notify registered event handlers of socket events. +{ +public: + explicit SocketNotifier(const Socket& socket); + /// Creates the SocketNotifier for the given socket. + + void addObserver(SocketReactor* pReactor, const Poco::AbstractObserver& observer); + /// Adds the given observer. + + void removeObserver(SocketReactor* pReactor, const Poco::AbstractObserver& observer); + /// Removes the given observer. + + bool hasObserver(const Poco::AbstractObserver& observer) const; + /// Returns true if the given observer is registered. + + bool accepts(SocketNotification* pNotification); + /// Returns true if there is at least one observer for the given notification. + + void dispatch(SocketNotification* pNotification); + /// Dispatches the notification to all observers. + + bool hasObservers() const; + /// Returns true if there are subscribers. + + std::size_t countObservers() const; + /// Returns the number of subscribers; + +protected: + ~SocketNotifier(); + /// Destroys the SocketNotifier. + +private: + typedef std::multiset<SocketNotification*> EventSet; + + EventSet _events; + Poco::NotificationCenter _nc; + Socket _socket; +}; + + +// +// inlines +// +inline bool SocketNotifier::accepts(SocketNotification* pNotification) +{ + return _events.find(pNotification) != _events.end(); +} + + +inline bool SocketNotifier::hasObserver(const Poco::AbstractObserver& observer) const +{ + return _nc.hasObserver(observer); +} + + +inline bool SocketNotifier::hasObservers() const +{ + return _nc.hasObservers(); +} + + +inline std::size_t SocketNotifier::countObservers() const +{ + return _nc.countObservers(); +} + + +} } // namespace Poco::Net + + +#endif // Net_SocketNotifier_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/SocketReactor.h b/contrib/libs/poco/Net/include/Poco/Net/SocketReactor.h new file mode 100644 index 0000000000..06c40bbd6a --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/SocketReactor.h @@ -0,0 +1,235 @@ +// +// SocketReactor.h +// +// Library: Net +// Package: Reactor +// Module: SocketReactor +// +// Definition of the SocketReactor class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_SocketReactor_INCLUDED +#define Net_SocketReactor_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/Socket.h" +#include "Poco/Runnable.h" +#include "Poco/Timespan.h" +#include "Poco/Observer.h" +#include "Poco/AutoPtr.h" +#include <map> + + +namespace Poco { + + +class Thread; + + +namespace Net { + + +class Socket; +class SocketNotification; +class SocketNotifier; + + +class Net_API SocketReactor: public Poco::Runnable + /// This class, which is part of the Reactor pattern, + /// implements the "Initiation Dispatcher". + /// + /// The Reactor pattern has been described in the book + /// "Pattern Languages of Program Design" by Jim Coplien + /// and Douglas C. Schmidt (Addison Wesley, 1995). + /// + /// The Reactor design pattern handles service requests that + /// are delivered concurrently to an application by one or more + /// clients. Each service in an application may consist of several + /// methods and is represented by a separate event handler. The event + /// handler is responsible for servicing service-specific requests. + /// The SocketReactor dispatches the event handlers. + /// + /// Event handlers (any class can be an event handler - there + /// is no base class for event handlers) can be registered + /// with the addEventHandler() method and deregistered with + /// the removeEventHandler() method. + /// + /// An event handler is always registered for a certain socket, + /// which is given in the call to addEventHandler(). Any method + /// of the event handler class can be registered to handle the + /// event - the only requirement is that the method takes + /// a pointer to an instance of SocketNotification (or a subclass of it) + /// as argument. + /// + /// Once started, the SocketReactor waits for events + /// on the registered sockets, using Socket::select(). + /// If an event is detected, the corresponding event handler + /// is invoked. There are five event types (and corresponding + /// notification classes) defined: ReadableNotification, WritableNotification, + /// ErrorNotification, TimeoutNotification, IdleNotification and + /// ShutdownNotification. + /// + /// The ReadableNotification will be dispatched if a socket becomes + /// readable. The WritableNotification will be dispatched if a socket + /// becomes writable. The ErrorNotification will be dispatched if + /// there is an error condition on a socket. + /// + /// If the timeout expires and no event has occurred, a + /// TimeoutNotification will be dispatched to all event handlers + /// registered for it. This is done in the onTimeout() method + /// which can be overridden by subclasses to perform custom + /// timeout processing. + /// + /// If there are no sockets for the SocketReactor to pass to + /// Socket::select(), an IdleNotification will be dispatched to + /// all event handlers registered for it. This is done in the + /// onIdle() method which can be overridden by subclasses + /// to perform custom idle processing. Since onIdle() will be + /// called repeatedly in a loop, it is recommended to do a + /// short sleep or yield in the event handler. + /// + /// Finally, when the SocketReactor is about to shut down (as a result + /// of stop() being called), it dispatches a ShutdownNotification + /// to all event handlers. This is done in the onShutdown() method + /// which can be overridded by subclasses to perform custom + /// shutdown processing. + /// + /// The SocketReactor is implemented so that it can + /// run in its own thread. It is also possible to run + /// multiple SocketReactors in parallel, as long as + /// they work on different sockets. + /// + /// It is safe to call addEventHandler() and removeEventHandler() + /// from another thread while the SocketReactor is running. Also, + /// it is safe to call addEventHandler() and removeEventHandler() + /// from event handlers. +{ +public: + SocketReactor(); + /// Creates the SocketReactor. + + explicit SocketReactor(const Poco::Timespan& timeout); + /// Creates the SocketReactor, using the given timeout. + + virtual ~SocketReactor(); + /// Destroys the SocketReactor. + + void run(); + /// Runs the SocketReactor. The reactor will run + /// until stop() is called (in a separate thread). + + void stop(); + /// Stops the SocketReactor. + /// + /// The reactor will be stopped when the next event + /// (including a timeout event) occurs. + + void wakeUp(); + /// Wakes up idle reactor. + + void setTimeout(const Poco::Timespan& timeout); + /// Sets the timeout. + /// + /// If no other event occurs for the given timeout + /// interval, a timeout event is sent to all event listeners. + /// + /// The default timeout is 250 milliseconds; + /// + /// The timeout is passed to the Socket::select() + /// method. + + const Poco::Timespan& getTimeout() const; + /// Returns the timeout. + + void addEventHandler(const Socket& socket, const Poco::AbstractObserver& observer); + /// Registers an event handler with the SocketReactor. + /// + /// Usage: + /// Poco::Observer<MyEventHandler, SocketNotification> obs(*this, &MyEventHandler::handleMyEvent); + /// reactor.addEventHandler(obs); + + bool hasEventHandler(const Socket& socket, const Poco::AbstractObserver& observer); + /// Returns true if the observer is registered with SocketReactor for the given socket. + + void removeEventHandler(const Socket& socket, const Poco::AbstractObserver& observer); + /// Unregisters an event handler with the SocketReactor. + /// + /// Usage: + /// Poco::Observer<MyEventHandler, SocketNotification> obs(*this, &MyEventHandler::handleMyEvent); + /// reactor.removeEventHandler(obs); + +protected: + virtual void onTimeout(); + /// Called if the timeout expires and no other events are available. + /// + /// Can be overridden by subclasses. The default implementation + /// dispatches the TimeoutNotification and thus should be called by overriding + /// implementations. + + virtual void onIdle(); + /// Called if no sockets are available to call select() on. + /// + /// Can be overridden by subclasses. The default implementation + /// dispatches the IdleNotification and thus should be called by overriding + /// implementations. + + virtual void onShutdown(); + /// Called when the SocketReactor is about to terminate. + /// + /// Can be overridden by subclasses. The default implementation + /// dispatches the ShutdownNotification and thus should be called by overriding + /// implementations. + + virtual void onBusy(); + /// Called when the SocketReactor is busy and at least one notification + /// has been dispatched. + /// + /// Can be overridden by subclasses to perform additional + /// periodic tasks. The default implementation does nothing. + + void dispatch(const Socket& socket, SocketNotification* pNotification); + /// Dispatches the given notification to all observers + /// registered for the given socket. + + void dispatch(SocketNotification* pNotification); + /// Dispatches the given notification to all observers. + +private: + typedef Poco::AutoPtr<SocketNotifier> NotifierPtr; + typedef Poco::AutoPtr<SocketNotification> NotificationPtr; + typedef std::map<Socket, NotifierPtr> EventHandlerMap; + + void dispatch(NotifierPtr& pNotifier, SocketNotification* pNotification); + + enum + { + DEFAULT_TIMEOUT = 250000 + }; + + bool _stop; + Poco::Timespan _timeout; + EventHandlerMap _handlers; + NotificationPtr _pReadableNotification; + NotificationPtr _pWritableNotification; + NotificationPtr _pErrorNotification; + NotificationPtr _pTimeoutNotification; + NotificationPtr _pIdleNotification; + NotificationPtr _pShutdownNotification; + Poco::FastMutex _mutex; + Poco::Thread* _pThread; + + friend class SocketNotifier; +}; + + +} } // namespace Poco::Net + + +#endif // Net_SocketReactor_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/SocketStream.h b/contrib/libs/poco/Net/include/Poco/Net/SocketStream.h new file mode 100644 index 0000000000..5a9a62c0ef --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/SocketStream.h @@ -0,0 +1,177 @@ +// +// SocketStream.h +// +// Library: Net +// Package: Sockets +// Module: SocketStream +// +// Definition of the SocketStream class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_SocketStream_INCLUDED +#define Net_SocketStream_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/StreamSocket.h" +#include "Poco/BufferedBidirectionalStreamBuf.h" +#include <istream> +#include <ostream> + + +namespace Poco { +namespace Net { + + +class StreamSocketImpl; + + +class Net_API SocketStreamBuf: public Poco::BufferedBidirectionalStreamBuf + /// This is the streambuf class used for reading from and writing to a socket. +{ +public: + SocketStreamBuf(const Socket& socket); + /// Creates a SocketStreamBuf with the given socket. + /// + /// The socket's SocketImpl must be a StreamSocketImpl, + /// otherwise an InvalidArgumentException is thrown. + + ~SocketStreamBuf(); + /// Destroys the SocketStreamBuf. + + StreamSocketImpl* socketImpl() const; + /// Returns the internal SocketImpl. + +protected: + int readFromDevice(char* buffer, std::streamsize length); + int writeToDevice(const char* buffer, std::streamsize length); + +private: + enum + { + STREAM_BUFFER_SIZE = 1024 + }; + + StreamSocketImpl* _pImpl; +}; + + +class Net_API SocketIOS: public virtual std::ios + /// The base class for SocketStream, SocketInputStream and + /// SocketOutputStream. + /// + /// This class is needed to ensure the correct initialization + /// order of the stream buffer and base classes. +{ +public: + SocketIOS(const Socket& socket); + /// Creates the SocketIOS with the given socket. + /// + /// The socket's SocketImpl must be a StreamSocketImpl, + /// otherwise an InvalidArgumentException is thrown. + + ~SocketIOS(); + /// Destroys the SocketIOS. + /// + /// Flushes the buffer, but does not close the socket. + + SocketStreamBuf* rdbuf(); + /// Returns a pointer to the internal SocketStreamBuf. + + void close(); + /// Flushes the stream and closes the socket. + + StreamSocket socket() const; + /// Returns the underlying socket. + +protected: + SocketStreamBuf _buf; +}; + + +class Net_API SocketOutputStream: public SocketIOS, public std::ostream + /// An output stream for writing to a socket. +{ +public: + explicit SocketOutputStream(const Socket& socket); + /// Creates the SocketOutputStream with the given socket. + /// + /// The socket's SocketImpl must be a StreamSocketImpl, + /// otherwise an InvalidArgumentException is thrown. + + ~SocketOutputStream(); + /// Destroys the SocketOutputStream. + /// + /// Flushes the buffer, but does not close the socket. +}; + + +class Net_API SocketInputStream: public SocketIOS, public std::istream + /// An input stream for reading from a socket. + /// + /// When using formatted input from a SocketInputStream, + /// always ensure that a receive timeout is set for the + /// socket. Otherwise your program might unexpectedly + /// hang. + /// + /// However, using formatted input from a SocketInputStream + /// is not recommended, due to the read-ahead behavior of + /// istream with formatted reads. +{ +public: + explicit SocketInputStream(const Socket& socket); + /// Creates the SocketInputStream with the given socket. + /// + /// The socket's SocketImpl must be a StreamSocketImpl, + /// otherwise an InvalidArgumentException is thrown. + + ~SocketInputStream(); + /// Destroys the SocketInputStream. +}; + + +class Net_API SocketStream: public SocketIOS, public std::iostream + /// An bidirectional stream for reading from and writing to a socket. + /// + /// When using formatted input from a SocketStream, + /// always ensure that a receive timeout is set for the + /// socket. Otherwise your program might unexpectedly + /// hang. + /// + /// However, using formatted input from a SocketStream + /// is not recommended, due to the read-ahead behavior of + /// istream with formatted reads. +{ +public: + explicit SocketStream(const Socket& socket); + /// Creates the SocketStream with the given socket. + /// + /// The socket's SocketImpl must be a StreamSocketImpl, + /// otherwise an InvalidArgumentException is thrown. + + ~SocketStream(); + /// Destroys the SocketStream. + /// + /// Flushes the buffer, but does not close the socket. +}; + + +// +// inlines +// +inline StreamSocketImpl* SocketStreamBuf::socketImpl() const +{ + return _pImpl; +} + + +} } // namespace Poco::Net + + +#endif // Net_SocketStream_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/StreamSocket.h b/contrib/libs/poco/Net/include/Poco/Net/StreamSocket.h new file mode 100644 index 0000000000..46374d85dc --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/StreamSocket.h @@ -0,0 +1,180 @@ +// +// StreamSocket.h +// +// Library: Net +// Package: Sockets +// Module: StreamSocket +// +// Definition of the StreamSocket class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_StreamSocket_INCLUDED +#define Net_StreamSocket_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/Socket.h" +#include "Poco/FIFOBuffer.h" + + +namespace Poco { +namespace Net { + + +class StreamSocketImpl; + + +class Net_API StreamSocket: public Socket + /// This class provides an interface to a + /// TCP stream socket. +{ +public: + StreamSocket(); + /// Creates an unconnected stream socket. + /// + /// Before sending or receiving data, the socket + /// must be connected with a call to connect(). + + explicit StreamSocket(const SocketAddress& address); + /// Creates a stream socket and connects it to + /// the socket specified by address. + + explicit StreamSocket(SocketAddress::Family family); + /// Creates an unconnected stream socket + /// for the given address family. + /// + /// This is useful if certain socket options + /// (like send and receive buffer) sizes, that must + /// be set before connecting the socket, will be + /// set later on. + + StreamSocket(const Socket& socket); + /// Creates the StreamSocket with the SocketImpl + /// from another socket. The SocketImpl must be + /// a StreamSocketImpl, otherwise an InvalidArgumentException + /// will be thrown. + + virtual ~StreamSocket(); + /// Destroys the StreamSocket. + + StreamSocket& operator = (const Socket& socket); + /// Assignment operator. + /// + /// Releases the socket's SocketImpl and + /// attaches the SocketImpl from the other socket and + /// increments the reference count of the SocketImpl. + + void connect(const SocketAddress& address); + /// Initializes the socket and establishes a connection to + /// the TCP server at the given address. + /// + /// Can also be used for UDP sockets. In this case, no + /// connection is established. Instead, incoming and outgoing + /// packets are restricted to the specified address. + + void connect(const SocketAddress& address, const Poco::Timespan& timeout); + /// Initializes the socket, sets the socket timeout and + /// establishes a connection to the TCP server at the given address. + + void connectNB(const SocketAddress& address); + /// Initializes the socket and establishes a connection to + /// the TCP server at the given address. Prior to opening the + /// connection the socket is set to nonblocking mode. + + void shutdownReceive(); + /// Shuts down the receiving part of the socket connection. + + void shutdownSend(); + /// Shuts down the sending part of the socket connection. + + void shutdown(); + /// Shuts down both the receiving and the sending part + /// of the socket connection. + + int sendBytes(const void* buffer, int length, int flags = 0); + /// Sends the contents of the given buffer through + /// the socket. + /// + /// Returns the number of bytes sent, which may be + /// less than the number of bytes specified. + /// + /// Certain socket implementations may also return a negative + /// value denoting a certain condition. + + int sendBytes(Poco::FIFOBuffer& buffer); + /// Sends the contents of the given buffer through + /// the socket. FIFOBuffer has writable/readable transition + /// notifications which may be enabled to notify the caller when + /// the buffer transitions between empty, partially full and + /// full states. + /// + /// Returns the number of bytes sent, which may be + /// less than the number of bytes specified. + /// + /// Certain socket implementations may also return a negative + /// value denoting a certain condition. + + int receiveBytes(void* buffer, int length, int flags = 0); + /// Receives data from the socket and stores it + /// in buffer. Up to length bytes are received. + /// + /// Returns the number of bytes received. + /// A return value of 0 means a graceful shutdown + /// of the connection from the peer. + /// + /// Throws a TimeoutException if a receive timeout has + /// been set and nothing is received within that interval. + /// Throws a NetException (or a subclass) in case of other errors. + + int receiveBytes(Poco::FIFOBuffer& buffer); + /// Receives data from the socket and stores it + /// in buffer. Up to length bytes are received. FIFOBuffer has + /// writable/readable transition notifications which may be enabled + /// to notify the caller when the buffer transitions between empty, + /// partially full and full states. + /// + /// Returns the number of bytes received. + /// A return value of 0 means a graceful shutdown + /// of the connection from the peer. + /// + /// Throws a TimeoutException if a receive timeout has + /// been set and nothing is received within that interval. + /// Throws a NetException (or a subclass) in case of other errors. + + void sendUrgent(unsigned char data); + /// Sends one byte of urgent data through + /// the socket. + /// + /// The data is sent with the MSG_OOB flag. + /// + /// The preferred way for a socket to receive urgent data + /// is by enabling the SO_OOBINLINE option. + + StreamSocket(SocketImpl* pImpl); + /// Creates the Socket and attaches the given SocketImpl. + /// The socket takes ownership of the SocketImpl. + /// + /// The SocketImpl must be a StreamSocketImpl, otherwise + /// an InvalidArgumentException will be thrown. + +private: + enum + { + BUFFER_SIZE = 1024 + }; + + friend class ServerSocket; + friend class SocketIOS; +}; + + +} } // namespace Poco::Net + + +#endif // Net_StreamSocket_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/StreamSocketImpl.h b/contrib/libs/poco/Net/include/Poco/Net/StreamSocketImpl.h new file mode 100644 index 0000000000..eb4196983c --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/StreamSocketImpl.h @@ -0,0 +1,59 @@ +// +// StreamSocketImpl.h +// +// Library: Net +// Package: Sockets +// Module: StreamSocketImpl +// +// Definition of the StreamSocketImpl class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_StreamSocketImpl_INCLUDED +#define Net_StreamSocketImpl_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/SocketImpl.h" + + +namespace Poco { +namespace Net { + + +class Net_API StreamSocketImpl: public SocketImpl + /// This class implements a TCP socket. +{ +public: + StreamSocketImpl(); + /// Creates a StreamSocketImpl. + + explicit StreamSocketImpl(SocketAddress::Family addressFamily); + /// Creates a SocketImpl, with the underlying + /// socket initialized for the given address family. + + StreamSocketImpl(poco_socket_t sockfd); + /// Creates a StreamSocketImpl using the given native socket. + + virtual int sendBytes(const void* buffer, int length, int flags = 0); + /// Ensures that all data in buffer is sent if the socket + /// is blocking. In case of a non-blocking socket, sends as + /// many bytes as possible. + /// + /// Returns the number of bytes sent. The return value may also be + /// negative to denote some special condition. + +protected: + virtual ~StreamSocketImpl(); +}; + + +} } // namespace Poco::Net + + +#endif // Net_StreamSocketImpl_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/StringPartSource.h b/contrib/libs/poco/Net/include/Poco/Net/StringPartSource.h new file mode 100644 index 0000000000..8f2b478dc2 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/StringPartSource.h @@ -0,0 +1,71 @@ +// +// StringPartSource.h +// +// Library: Net +// Package: Messages +// Module: StringPartSource +// +// Definition of the StringPartSource class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_StringPartSource_INCLUDED +#define Net_StringPartSource_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/PartSource.h" +#include <sstream> + + +namespace Poco { +namespace Net { + + +class Net_API StringPartSource: public PartSource + /// An implementation of PartSource for strings. +{ +public: + StringPartSource(const std::string& str); + /// Creates the StringPartSource for the given string. + /// + /// The MIME type is set to text/plain. + + StringPartSource(const std::string& str, const std::string& mediaType); + /// Creates the StringPartSource for the given + /// string and MIME type. + + StringPartSource(const std::string& str, const std::string& mediaType, const std::string& filename); + /// Creates the StringPartSource for the given + /// string, MIME type and filename. + + ~StringPartSource(); + /// Destroys the StringPartSource. + + std::istream& stream(); + /// Returns a string input stream for the string. + + const std::string& filename() const; + /// Returns the filename portion of the path. + + std::streamsize getContentLength() const; + /// Returns the string size. + +private: + std::istringstream _istr; + std::string _filename; + + StringPartSource(const StringPartSource&); + StringPartSource& operator = (const StringPartSource&); +}; + + +} } // namespace Poco::Net + + +#endif // Net_StringPartSource_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/TCPServer.h b/contrib/libs/poco/Net/include/Poco/Net/TCPServer.h new file mode 100644 index 0000000000..1277475a11 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/TCPServer.h @@ -0,0 +1,260 @@ +// +// TCPServer.h +// +// Library: Net +// Package: TCPServer +// Module: TCPServer +// +// Definition of the TCPServer class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_TCPServer_INCLUDED +#define Net_TCPServer_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/ServerSocket.h" +#include "Poco/Net/TCPServerConnectionFactory.h" +#include "Poco/Net/TCPServerParams.h" +#include "Poco/RefCountedObject.h" +#include "Poco/AutoPtr.h" +#include "Poco/Runnable.h" +#include "Poco/Thread.h" +#include "Poco/ThreadPool.h" + +#include <atomic> + + +namespace Poco { +namespace Net { + + +class TCPServerDispatcher; +class StreamSocket; + + +class Net_API TCPServerConnectionFilter: public Poco::RefCountedObject + /// A TCPServerConnectionFilter can be used to reject incoming connections + /// before passing them on to the TCPServerDispatcher and + /// starting a thread to handle them. + /// + /// An example use case is white-list or black-list IP address filtering. + /// + /// Subclasses must override the accept() method. +{ +public: + typedef Poco::AutoPtr<TCPServerConnectionFilter> Ptr; + + virtual bool accept(const StreamSocket& socket) = 0; + /// Returns true if the given StreamSocket connection should + /// be handled, and passed on to the TCPServerDispatcher. + /// + /// Returns false if the socket should be closed immediately. + /// + /// The socket can be prevented from being closed immediately + /// if false is returned by creating a copy of the socket. + /// This can be used to handle certain socket connections in + /// a special way, outside the TCPServer framework. + +protected: + virtual ~TCPServerConnectionFilter(); +}; + + +class Net_API TCPServer: public Poco::Runnable + /// This class implements a multithreaded TCP server. + /// + /// The server uses a ServerSocket to listen for incoming + /// connections. The ServerSocket must have been bound to + /// an address before it is passed to the TCPServer constructor. + /// Additionally, the ServerSocket must be put into listening + /// state before the TCPServer is started by calling the start() + /// method. + /// + /// The server uses a thread pool to assign threads to incoming + /// connections. Before incoming connections are assigned to + /// a connection thread, they are put into a queue. + /// Connection threads fetch new connections from the queue as soon + /// as they become free. Thus, a connection thread may serve more + /// than one connection. + /// + /// As soon as a connection thread fetches the next connection from + /// the queue, it creates a TCPServerConnection object for it + /// (using the TCPServerConnectionFactory passed to the constructor) + /// and calls the TCPServerConnection's start() method. When the + /// start() method returns, the connection object is deleted. + /// + /// The number of connection threads is adjusted dynamically, depending + /// on the number of connections waiting to be served. + /// + /// It is possible to specify a maximum number of queued connections. + /// This prevents the connection queue from overflowing in the + /// case of an extreme server load. In such a case, connections that + /// cannot be queued are silently and immediately closed. + /// + /// TCPServer uses a separate thread to accept incoming connections. + /// Thus, the call to start() returns immediately, and the server + /// continues to run in the background. + /// + /// To stop the server from accepting new connections, call stop(). + /// + /// After calling stop(), no new connections will be accepted and + /// all queued connections will be discarded. + /// Already served connections, however, will continue being served. +{ +public: + TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::UInt16 portNumber = 0, TCPServerParams::Ptr pParams = 0); + /// Creates the TCPServer, with ServerSocket listening on the given port. + /// Default port is zero, allowing any available port. The port number + /// can be queried through TCPServer::port() member. + /// + /// The server takes ownership of the TCPServerConnectionFactory + /// and deletes it when it's no longer needed. + /// + /// The server also takes ownership of the TCPServerParams object. + /// If no TCPServerParams object is given, the server's TCPServerDispatcher + /// creates its own one. + /// + /// New threads are taken from the default thread pool. + + TCPServer(TCPServerConnectionFactory::Ptr pFactory, const ServerSocket& socket, TCPServerParams::Ptr pParams = 0); + /// Creates the TCPServer, using the given ServerSocket. + /// + /// The server takes ownership of the TCPServerConnectionFactory + /// and deletes it when it's no longer needed. + /// + /// The server also takes ownership of the TCPServerParams object. + /// If no TCPServerParams object is given, the server's TCPServerDispatcher + /// creates its own one. + /// + /// New threads are taken from the default thread pool. + + TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::ThreadPool& threadPool, const ServerSocket& socket, TCPServerParams::Ptr pParams = 0); + /// Creates the TCPServer, using the given ServerSocket. + /// + /// The server takes ownership of the TCPServerConnectionFactory + /// and deletes it when it's no longer needed. + /// + /// The server also takes ownership of the TCPServerParams object. + /// If no TCPServerParams object is given, the server's TCPServerDispatcher + /// creates its own one. + /// + /// New threads are taken from the given thread pool. + + virtual ~TCPServer(); + /// Destroys the TCPServer and its TCPServerConnectionFactory. + + const TCPServerParams& params() const; + /// Returns a const reference to the TCPServerParam object + /// used by the server's TCPServerDispatcher. + + void start(); + /// Starts the server. A new thread will be + /// created that waits for and accepts incoming + /// connections. + /// + /// Before start() is called, the ServerSocket passed to + /// TCPServer must have been bound and put into listening state. + + void stop(); + /// Stops the server. + /// + /// No new connections will be accepted. + /// Already handled connections will continue to be served. + /// + /// Once the server has been stopped, it cannot be restarted. + + int currentThreads() const; + /// Returns the number of currently used connection threads. + + int maxThreads() const; + /// Returns the maximum number of threads available. + + int totalConnections() const; + /// Returns the total number of handled connections. + + int currentConnections() const; + /// Returns the number of currently handled connections. + + int maxConcurrentConnections() const; + /// Returns the maximum number of concurrently handled connections. + + int queuedConnections() const; + /// Returns the number of queued connections. + + int refusedConnections() const; + /// Returns the number of refused connections. + + const ServerSocket& socket() const; + /// Returns the underlying server socket. + + Poco::UInt16 port() const; + /// Returns the port the server socket listens on. + + void setConnectionFilter(const TCPServerConnectionFilter::Ptr& pFilter); + /// Sets a TCPServerConnectionFilter. Can also be used to remove + /// a filter by passing a null pointer. + /// + /// To avoid a potential race condition, the filter must + /// be set before the TCPServer is started. Trying to set + /// the filter after start() has been called will trigger + /// an assertion. + + TCPServerConnectionFilter::Ptr getConnectionFilter() const; + /// Returns the TCPServerConnectionFilter set with setConnectionFilter(), + /// or null pointer if no filter has been set. + +protected: + void run(); + /// Runs the server. The server will run until + /// the stop() method is called, or the server + /// object is destroyed, which implicitly calls + /// the stop() method. + + static std::string threadName(const ServerSocket& socket); + /// Returns a thread name for the server thread. + +private: + TCPServer(); + TCPServer(const TCPServer&); + TCPServer& operator = (const TCPServer&); + + ServerSocket _socket; + TCPServerDispatcher* _pDispatcher; + TCPServerConnectionFilter::Ptr _pConnectionFilter; + Poco::Thread _thread; + std::atomic<bool> _stopped; +}; + + +// +// inlines +// +inline const ServerSocket& TCPServer::socket() const +{ + return _socket; +} + + +inline Poco::UInt16 TCPServer::port() const +{ + return _socket.address().port(); +} + + +inline TCPServerConnectionFilter::Ptr TCPServer::getConnectionFilter() const +{ + return _pConnectionFilter; +} + + +} } // namespace Poco::Net + + +#endif // Net_TCPServer_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/TCPServerConnection.h b/contrib/libs/poco/Net/include/Poco/Net/TCPServerConnection.h new file mode 100644 index 0000000000..380edcc169 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/TCPServerConnection.h @@ -0,0 +1,86 @@ +// +// TCPServerConnection.h +// +// Library: Net +// Package: TCPServer +// Module: TCPServerConnection +// +// Definition of the TCPServerConnection class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_TCPServerConnection_INCLUDED +#define Net_TCPServerConnection_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/StreamSocket.h" +#include "Poco/Runnable.h" + + +namespace Poco { +namespace Net { + + +class Net_API TCPServerConnection: public Poco::Runnable + /// The abstract base class for TCP server connections + /// created by TCPServer. + /// + /// Derived classes must override the run() method + /// (inherited from Runnable). Furthermore, a + /// TCPServerConnectionFactory must be provided for the subclass. + /// + /// The run() method must perform the complete handling + /// of the client connection. As soon as the run() method + /// returns, the server connection object is destroyed and + /// the connection is automatically closed. + /// + /// A new TCPServerConnection object will be created for + /// each new client connection that is accepted by + /// TCPServer. +{ +public: + TCPServerConnection(const StreamSocket& socket); + /// Creates the TCPServerConnection using the given + /// stream socket. + + virtual ~TCPServerConnection(); + /// Destroys the TCPServerConnection. + +protected: + StreamSocket& socket(); + /// Returns a reference to the underlying socket. + + void start(); + /// Calls run() and catches any exceptions that + /// might be thrown by run(). + +private: + TCPServerConnection(); + TCPServerConnection(const TCPServerConnection&); + TCPServerConnection& operator = (const TCPServerConnection&); + + StreamSocket _socket; + + friend class TCPServerDispatcher; +}; + + +// +// inlines +// +inline StreamSocket& TCPServerConnection::socket() +{ + return _socket; +} + + +} } // namespace Poco::Net + + +#endif // Net_TCPServerConnection_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/TCPServerConnectionFactory.h b/contrib/libs/poco/Net/include/Poco/Net/TCPServerConnectionFactory.h new file mode 100644 index 0000000000..8fc4d6b4d0 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/TCPServerConnectionFactory.h @@ -0,0 +1,89 @@ +// +// TCPServerConnectionFactory.h +// +// Library: Net +// Package: TCPServer +// Module: TCPServerConnectionFactory +// +// Definition of the TCPServerConnectionFactory class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_TCPServerConnectionFactory_INCLUDED +#define Net_TCPServerConnectionFactory_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/TCPServerConnection.h" +#include "Poco/SharedPtr.h" + + +namespace Poco { +namespace Net { + + +class Net_API TCPServerConnectionFactory + /// A factory for TCPServerConnection objects. + /// + /// The TCPServer class uses a TCPServerConnectionFactory + /// to create a connection object for each new connection + /// it accepts. + /// + /// Subclasses must override the createConnection() + /// method. + /// + /// The TCPServerConnectionFactoryImpl template class + /// can be used to automatically instantiate a + /// TCPServerConnectionFactory for a given subclass + /// of TCPServerConnection. +{ +public: + typedef Poco::SharedPtr<TCPServerConnectionFactory> Ptr; + + virtual ~TCPServerConnectionFactory(); + /// Destroys the TCPServerConnectionFactory. + + virtual TCPServerConnection* createConnection(const StreamSocket& socket) = 0; + /// Creates an instance of a subclass of TCPServerConnection, + /// using the given StreamSocket. + +protected: + TCPServerConnectionFactory(); + /// Creates the TCPServerConnectionFactory. + +private: + TCPServerConnectionFactory(const TCPServerConnectionFactory&); + TCPServerConnectionFactory& operator = (const TCPServerConnectionFactory&); +}; + + +template <class S> +class TCPServerConnectionFactoryImpl: public TCPServerConnectionFactory + /// This template provides a basic implementation of + /// TCPServerConnectionFactory. +{ +public: + TCPServerConnectionFactoryImpl() + { + } + + ~TCPServerConnectionFactoryImpl() + { + } + + TCPServerConnection* createConnection(const StreamSocket& socket) + { + return new S(socket); + } +}; + + +} } // namespace Poco::Net + + +#endif // Net_TCPServerConnectionFactory_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/TCPServerDispatcher.h b/contrib/libs/poco/Net/include/Poco/Net/TCPServerDispatcher.h new file mode 100644 index 0000000000..3c46d0f268 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/TCPServerDispatcher.h @@ -0,0 +1,130 @@ +// +// TCPServerDispatcher.h +// +// Library: Net +// Package: TCPServer +// Module: TCPServerDispatcher +// +// Definition of the TCPServerDispatcher class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_TCPServerDispatcher_INCLUDED +#define Net_TCPServerDispatcher_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/StreamSocket.h" +#include "Poco/Net/TCPServerConnectionFactory.h" +#include "Poco/Net/TCPServerParams.h" +#include "Poco/Runnable.h" +#include "Poco/NotificationQueue.h" +#include "Poco/ThreadPool.h" +#include "Poco/Mutex.h" + + +namespace Poco { +namespace Net { + + +class Net_API TCPServerDispatcher: public Poco::Runnable + /// A helper class for TCPServer that dispatches + /// connections to server connection threads. +{ +public: + TCPServerDispatcher(TCPServerConnectionFactory::Ptr pFactory, Poco::ThreadPool& threadPool, TCPServerParams::Ptr pParams); + /// Creates the TCPServerDispatcher. + /// + /// The dispatcher takes ownership of the TCPServerParams object. + /// If no TCPServerParams object is supplied, the TCPServerDispatcher + /// creates one. + + void duplicate(); + /// Increments the object's reference count. + + void release(); + /// Decrements the object's reference count + /// and deletes the object if the count + /// reaches zero. + + void run(); + /// Runs the dispatcher. + + void enqueue(const StreamSocket& socket); + /// Queues the given socket connection. + + void stop(); + /// Stops the dispatcher. + + int currentThreads() const; + /// Returns the number of currently used threads. + + int maxThreads() const; + /// Returns the maximum number of threads available. + + int totalConnections() const; + /// Returns the total number of handled connections. + + int currentConnections() const; + /// Returns the number of currently handled connections. + + int maxConcurrentConnections() const; + /// Returns the maximum number of concurrently handled connections. + + int queuedConnections() const; + /// Returns the number of queued connections. + + int refusedConnections() const; + /// Returns the number of refused connections. + + const TCPServerParams& params() const; + /// Returns a const reference to the TCPServerParam object. + +protected: + ~TCPServerDispatcher(); + /// Destroys the TCPServerDispatcher. + + void beginConnection(); + /// Updates the performance counters. + + void endConnection(); + /// Updates the performance counters. + +private: + TCPServerDispatcher(); + TCPServerDispatcher(const TCPServerDispatcher&); + TCPServerDispatcher& operator = (const TCPServerDispatcher&); + + int _rc; + TCPServerParams::Ptr _pParams; + int _currentThreads; + int _totalConnections; + int _currentConnections; + int _maxConcurrentConnections; + int _refusedConnections; + bool _stopped; + Poco::NotificationQueue _queue; + TCPServerConnectionFactory::Ptr _pConnectionFactory; + Poco::ThreadPool& _threadPool; + mutable Poco::FastMutex _mutex; +}; + + +// +// inlines +// +inline const TCPServerParams& TCPServerDispatcher::params() const +{ + return *_pParams; +} + + +} } // namespace Poco::Net + + +#endif // Net_TCPServerDispatcher_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/TCPServerParams.h b/contrib/libs/poco/Net/include/Poco/Net/TCPServerParams.h new file mode 100644 index 0000000000..1c2057e5ec --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/TCPServerParams.h @@ -0,0 +1,137 @@ +// +// TCPServerParams.h +// +// Library: Net +// Package: TCPServer +// Module: TCPServerParams +// +// Definition of the TCPServerParams class. +// +// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_TCPServerParams_INCLUDED +#define Net_TCPServerParams_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/RefCountedObject.h" +#include "Poco/Timespan.h" +#include "Poco/Thread.h" +#include "Poco/AutoPtr.h" + + +namespace Poco { +namespace Net { + + +class Net_API TCPServerParams: public Poco::RefCountedObject + /// This class is used to specify parameters to both the + /// TCPServer, as well as to TCPServerDispatcher objects. + /// + /// Subclasses may add new parameters to the class. +{ +public: + typedef Poco::AutoPtr<TCPServerParams> Ptr; + + TCPServerParams(); + /// Creates the TCPServerParams. + /// + /// Sets the following default values: + /// - threadIdleTime: 10 seconds + /// - maxThreads: 0 + /// - maxQueued: 64 + + void setThreadIdleTime(const Poco::Timespan& idleTime); + /// Sets the maximum idle time for a thread before + /// it is terminated. + /// + /// The default idle time is 10 seconds; + + const Poco::Timespan& getThreadIdleTime() const; + /// Returns the maximum thread idle time. + + void setMaxQueued(int count); + /// Sets the maximum number of queued connections. + /// Must be greater than 0. + /// + /// If there are already the maximum number of connections + /// in the queue, new connections will be silently discarded. + /// + /// The default number is 64. + + int getMaxQueued() const; + /// Returns the maximum number of queued connections. + + void setMaxThreads(int count); + /// Sets the maximum number of simultaneous threads + /// available for this TCPServerDispatcher. + /// + /// Must be greater than or equal to 0. + /// If 0 is specified, the TCPServerDispatcher will + /// set this parameter to the number of available threads + /// in its thread pool. + /// + /// The thread pool used by the TCPServerDispatcher + /// must at least have the capacity for the given + /// number of threads. + + int getMaxThreads() const; + /// Returns the maximum number of simultaneous threads + /// available for this TCPServerDispatcher. + + void setThreadPriority(Poco::Thread::Priority prio); + /// Sets the priority of TCP server threads + /// created by TCPServer. + + Poco::Thread::Priority getThreadPriority() const; + /// Returns the priority of TCP server threads + /// created by TCPServer. + +protected: + virtual ~TCPServerParams(); + /// Destroys the TCPServerParams. + +private: + Poco::Timespan _threadIdleTime; + int _maxThreads; + int _maxQueued; + Poco::Thread::Priority _threadPriority; +}; + + +// +// inlines +// +inline const Poco::Timespan& TCPServerParams::getThreadIdleTime() const +{ + return _threadIdleTime; +} + + +inline int TCPServerParams::getMaxThreads() const +{ + return _maxThreads; +} + + +inline int TCPServerParams::getMaxQueued() const +{ + return _maxQueued; +} + + +inline Poco::Thread::Priority TCPServerParams::getThreadPriority() const +{ + return _threadPriority; +} + + +} } // namespace Poco::Net + + +#endif // Net_TCPServerParams_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/WebSocket.h b/contrib/libs/poco/Net/include/Poco/Net/WebSocket.h new file mode 100644 index 0000000000..5d3f05d12d --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/WebSocket.h @@ -0,0 +1,297 @@ +// +// WebSocket.h +// +// Library: Net +// Package: WebSocket +// Module: WebSocket +// +// Definition of the WebSocket class. +// +// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_WebSocket_INCLUDED +#define Net_WebSocket_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/StreamSocket.h" +#include "Poco/Net/HTTPCredentials.h" +#include "Poco/Buffer.h" + + +namespace Poco { +namespace Net { + + +class WebSocketImpl; +class HTTPServerRequest; +class HTTPServerResponse; +class HTTPClientSession; + + +class Net_API WebSocket: public StreamSocket + /// This class implements a WebSocket according + /// to the WebSocket protocol specification in RFC 6455. + /// + /// Both client-side and server-side WebSockets + /// are supported. + /// + /// Server-side WebSockets are usually created from within + /// a HTTPRequestHandler. + /// + /// Client-side WebSockets are created using a HTTPClientSession. + /// + /// Note that special frames like PING must be handled at + /// application level. In the case of a PING, a PONG message + /// must be returned. +{ +public: + enum Mode + { + WS_SERVER, /// Server-side WebSocket. + WS_CLIENT /// Client-side WebSocket. + }; + + enum FrameFlags + /// Frame header flags. + { + FRAME_FLAG_FIN = 0x80, /// FIN bit: final fragment of a multi-fragment message. + FRAME_FLAG_RSV1 = 0x40, /// Reserved for future use. Must be zero. + FRAME_FLAG_RSV2 = 0x20, /// Reserved for future use. Must be zero. + FRAME_FLAG_RSV3 = 0x10 /// Reserved for future use. Must be zero. + }; + + enum FrameOpcodes + /// Frame header opcodes. + { + FRAME_OP_CONT = 0x00, /// Continuation frame. + FRAME_OP_TEXT = 0x01, /// Text frame. + FRAME_OP_BINARY = 0x02, /// Binary frame. + FRAME_OP_CLOSE = 0x08, /// Close connection. + FRAME_OP_PING = 0x09, /// Ping frame. + FRAME_OP_PONG = 0x0a, /// Pong frame. + FRAME_OP_BITMASK = 0x0f, /// Bit mask for opcodes. + FRAME_OP_SETRAW = 0x100 /// Set raw flags (for use with sendBytes() and FRAME_OP_CONT). + }; + + enum SendFlags + /// Combined header flags and opcodes for use with sendFrame(). + { + FRAME_TEXT = FRAME_FLAG_FIN | FRAME_OP_TEXT, + /// Use this for sending a single text (UTF-8) payload frame. + FRAME_BINARY = FRAME_FLAG_FIN | FRAME_OP_BINARY + /// Use this for sending a single binary payload frame. + }; + + enum StatusCodes + /// StatusCodes for CLOSE frames sent with shutdown(). + { + WS_NORMAL_CLOSE = 1000, + WS_ENDPOINT_GOING_AWAY = 1001, + WS_PROTOCOL_ERROR = 1002, + WS_PAYLOAD_NOT_ACCEPTABLE = 1003, + WS_RESERVED = 1004, + WS_RESERVED_NO_STATUS_CODE = 1005, + WS_RESERVED_ABNORMAL_CLOSE = 1006, + WS_MALFORMED_PAYLOAD = 1007, + WS_POLICY_VIOLATION = 1008, + WS_PAYLOAD_TOO_BIG = 1009, + WS_EXTENSION_REQUIRED = 1010, + WS_UNEXPECTED_CONDITION = 1011, + WS_RESERVED_TLS_FAILURE = 1015 + }; + + enum ErrorCodes + /// These error codes can be obtained from a WebSocketException + /// to determine the exact cause of the error. + { + WS_ERR_NO_HANDSHAKE = 1, + /// No Connection: Upgrade or Upgrade: websocket header in handshake request. + WS_ERR_HANDSHAKE_NO_VERSION = 2, + /// No Sec-WebSocket-Version header in handshake request. + WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION = 3, + /// Unsupported WebSocket version requested by client. + WS_ERR_HANDSHAKE_NO_KEY = 4, + /// No Sec-WebSocket-Key header in handshake request. + WS_ERR_HANDSHAKE_ACCEPT = 5, + /// No Sec-WebSocket-Accept header or wrong value. + WS_ERR_UNAUTHORIZED = 6, + /// The server rejected the username or password for authentication. + WS_ERR_PAYLOAD_TOO_BIG = 10, + /// Payload too big for supplied buffer. + WS_ERR_INCOMPLETE_FRAME = 11 + /// Incomplete frame received. + }; + + WebSocket(HTTPServerRequest& request, HTTPServerResponse& response); + /// Creates a server-side WebSocket from within a + /// HTTPRequestHandler. + /// + /// First verifies that the request is a valid WebSocket upgrade + /// request. If so, completes the handshake by sending + /// a proper 101 response. + /// + /// Throws an exception if the request is not a proper WebSocket + /// upgrade request. + + WebSocket(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response); + /// Creates a client-side WebSocket, using the given + /// HTTPClientSession and HTTPRequest for the initial handshake + /// (HTTP Upgrade request). + /// + /// Additional HTTP headers for the initial handshake request + /// (such as Origin or Sec-WebSocket-Protocol) can be given + /// in the request object. + /// + /// The result of the handshake can be obtained from the response + /// object. + + WebSocket(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response, HTTPCredentials& credentials); + /// Creates a client-side WebSocket, using the given + /// HTTPClientSession and HTTPRequest for the initial handshake + /// (HTTP Upgrade request). + /// + /// The given credentials are used for authentication + /// if requested by the server. + /// + /// Additional HTTP headers for the initial handshake request + /// (such as Origin or Sec-WebSocket-Protocol) can be given + /// in the request object. + /// + /// The result of the handshake can be obtained from the response + /// object. + + WebSocket(const Socket& socket); + /// Creates a WebSocket from another Socket, which must be a WebSocket, + /// otherwise a Poco::InvalidArgumentException will be thrown. + + virtual ~WebSocket(); + /// Destroys the StreamSocket. + + WebSocket& operator = (const Socket& socket); + /// Assignment operator. + /// + /// The other socket must be a WebSocket, otherwise a Poco::InvalidArgumentException + /// will be thrown. + + void shutdown(); + /// Sends a Close control frame to the server end of + /// the connection to initiate an orderly shutdown + /// of the connection. + + void shutdown(Poco::UInt16 statusCode, const std::string& statusMessage = ""); + /// Sends a Close control frame to the server end of + /// the connection to initiate an orderly shutdown + /// of the connection. + + int sendFrame(const void* buffer, int length, int flags = FRAME_TEXT); + /// Sends the contents of the given buffer through + /// the socket as a single frame. + /// + /// Values from the FrameFlags, FrameOpcodes and SendFlags enumerations + /// can be specified in flags. + /// + /// Returns the number of bytes sent, which may be + /// less than the number of bytes specified. + /// + /// Certain socket implementations may also return a negative + /// value denoting a certain condition. + + int receiveFrame(void* buffer, int length, int& flags); + /// Receives a frame from the socket and stores it + /// in buffer. Up to length bytes are received. If + /// the frame's payload is larger, a WebSocketException + /// is thrown and the WebSocket connection must be + /// terminated. + /// + /// The frame's payload size must not exceed the + /// maximum payload size set with setMaxPayloadSize(). + /// If it does, a WebSocketException (WS_ERR_PAYLOAD_TOO_BIG) + /// is thrown and the WebSocket connection must be + /// terminated. + /// + /// A WebSocketException will also be thrown if a malformed + /// or incomplete frame is received. + /// + /// Returns the number of bytes received. + /// A return value of 0 means that the peer has + /// shut down or closed the connection. + /// + /// Throws a TimeoutException if a receive timeout has + /// been set and nothing is received within that interval. + /// Throws a NetException (or a subclass) in case of other errors. + /// + /// The frame flags and opcode (FrameFlags and FrameOpcodes) + /// is stored in flags. + + int receiveFrame(Poco::Buffer<char>& buffer, int& flags); + /// Receives a frame from the socket and stores it + /// after any previous content in buffer. + /// The buffer will be grown as necessary. + /// + /// The frame's payload size must not exceed the + /// maximum payload size set with setMaxPayloadSize(). + /// If it does, a WebSocketException (WS_ERR_PAYLOAD_TOO_BIG) + /// is thrown and the WebSocket connection must be + /// terminated. + /// + /// A WebSocketException will also be thrown if a malformed + /// or incomplete frame is received. + /// + /// If this method is used, a reasonable maximum payload size should + /// be set with setMaxPayloadSize() to prevent a potential + /// DoS attack (memory exhaustion) by sending a WebSocket frame + /// header with a huge payload size. + /// + /// Returns the number of bytes received. + /// A return value of 0 means that the peer has + /// shut down or closed the connection. + /// + /// Throws a TimeoutException if a receive timeout has + /// been set and nothing is received within that interval. + /// Throws a NetException (or a subclass) in case of other errors. + /// + /// The frame flags and opcode (FrameFlags and FrameOpcodes) + /// is stored in flags. + + Mode mode() const; + /// Returns WS_SERVER if the WebSocket is a server-side + /// WebSocket, or WS_CLIENT otherwise. + + void setMaxPayloadSize(int maxPayloadSize); + /// Sets the maximum payload size for receiveFrame(). + /// + /// The default is std::numeric_limits<int>::max(). + + int getMaxPayloadSize() const; + /// Returns the maximum payload size for receiveFrame(). + /// + /// The default is std::numeric_limits<int>::max(). + + static const std::string WEBSOCKET_VERSION; + /// The WebSocket protocol version supported (13). + +protected: + static WebSocketImpl* accept(HTTPServerRequest& request, HTTPServerResponse& response); + static WebSocketImpl* connect(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response, HTTPCredentials& credentials); + static WebSocketImpl* completeHandshake(HTTPClientSession& cs, HTTPResponse& response, const std::string& key); + static std::string computeAccept(const std::string& key); + static std::string createKey(); + +private: + WebSocket(); + + static const std::string WEBSOCKET_GUID; + static HTTPCredentials _defaultCreds; +}; + + +} } // namespace Poco::Net + + +#endif // Net_WebSocket_INCLUDED diff --git a/contrib/libs/poco/Net/include/Poco/Net/WebSocketImpl.h b/contrib/libs/poco/Net/include/Poco/Net/WebSocketImpl.h new file mode 100644 index 0000000000..a2471c3694 --- /dev/null +++ b/contrib/libs/poco/Net/include/Poco/Net/WebSocketImpl.h @@ -0,0 +1,142 @@ +// +// WebSocketImpl.h +// +// Library: Net +// Package: WebSocket +// Module: WebSocketImpl +// +// Definition of the StreamSocketImpl class. +// +// Copyright (c) 2012, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_WebSocketImpl_INCLUDED +#define Net_WebSocketImpl_INCLUDED + + +#include "Poco/Net/StreamSocketImpl.h" +#include "Poco/Buffer.h" +#include "Poco/Random.h" +#include "Poco/Buffer.h" + + +namespace Poco { +namespace Net { + + +class HTTPSession; + + +class Net_API WebSocketImpl: public StreamSocketImpl + /// This class implements a WebSocket, according + /// to the WebSocket protocol described in RFC 6455. +{ +public: + WebSocketImpl(StreamSocketImpl* pStreamSocketImpl, HTTPSession& session, bool mustMaskPayload); + /// Creates a WebSocketImpl. + + // StreamSocketImpl + virtual int sendBytes(const void* buffer, int length, int flags); + /// Sends a WebSocket protocol frame. + + virtual int receiveBytes(void* buffer, int length, int flags); + /// Receives a WebSocket protocol frame. + + virtual int receiveBytes(Poco::Buffer<char>& buffer, int flags); + /// Receives a WebSocket protocol frame. + + virtual SocketImpl* acceptConnection(SocketAddress& clientAddr); + virtual void connect(const SocketAddress& address); + virtual void connect(const SocketAddress& address, const Poco::Timespan& timeout); + virtual void connectNB(const SocketAddress& address); + virtual void bind(const SocketAddress& address, bool reuseAddress = false); + virtual void bind(const SocketAddress& address, bool reuseAddress, bool reusePort); + virtual void bind6(const SocketAddress& address, bool reuseAddress = false, bool ipV6Only = false); + virtual void bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only); + virtual void listen(int backlog = 64); + virtual void close(); + virtual void shutdownReceive(); + virtual void shutdownSend(); + virtual void shutdown(); + virtual int sendTo(const void* buffer, int length, const SocketAddress& address, int flags = 0); + virtual int receiveFrom(void* buffer, int length, SocketAddress& address, int flags = 0); + virtual void sendUrgent(unsigned char data); + virtual int available(); + virtual bool secure() const; + virtual void setSendTimeout(const Poco::Timespan& timeout); + virtual Poco::Timespan getSendTimeout(); + virtual void setReceiveTimeout(const Poco::Timespan& timeout); + virtual Poco::Timespan getReceiveTimeout(); + + // Internal + int frameFlags() const; + /// Returns the frame flags of the most recently received frame. + + bool mustMaskPayload() const; + /// Returns true if the payload must be masked. + + void setMaxPayloadSize(int maxPayloadSize); + /// Sets the maximum payload size for receiveFrame(). + /// + /// The default is std::numeric_limits<int>::max(). + + int getMaxPayloadSize() const; + /// Returns the maximum payload size for receiveFrame(). + /// + /// The default is std::numeric_limits<int>::max(). + +protected: + enum + { + FRAME_FLAG_MASK = 0x80, + MAX_HEADER_LENGTH = 14 + }; + + int receiveHeader(char mask[4], bool& useMask); + int receivePayload(char *buffer, int payloadLength, char mask[4], bool useMask); + int receiveNBytes(void* buffer, int bytes); + int receiveSomeBytes(char* buffer, int bytes); + virtual ~WebSocketImpl(); + +private: + WebSocketImpl(); + + StreamSocketImpl* _pStreamSocketImpl; + int _maxPayloadSize; + Poco::Buffer<char> _buffer; + int _bufferOffset; + int _frameFlags; + bool _mustMaskPayload; + Poco::Random _rnd; +}; + + +// +// inlines +// +inline int WebSocketImpl::frameFlags() const +{ + return _frameFlags; +} + + +inline bool WebSocketImpl::mustMaskPayload() const +{ + return _mustMaskPayload; +} + + +inline int WebSocketImpl::getMaxPayloadSize() const +{ + return _maxPayloadSize; +} + + +} } // namespace Poco::Net + + +#endif // Net_WebSocketImpl_INCLUDED diff --git a/contrib/libs/poco/Net/src/AbstractHTTPRequestHandler.cpp b/contrib/libs/poco/Net/src/AbstractHTTPRequestHandler.cpp new file mode 100644 index 0000000000..ed39617e2b --- /dev/null +++ b/contrib/libs/poco/Net/src/AbstractHTTPRequestHandler.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/DNS.cpp b/contrib/libs/poco/Net/src/DNS.cpp new file mode 100644 index 0000000000..6ef8810aa1 --- /dev/null +++ b/contrib/libs/poco/Net/src/DNS.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/DatagramSocket.cpp b/contrib/libs/poco/Net/src/DatagramSocket.cpp new file mode 100644 index 0000000000..8d7cc92e3e --- /dev/null +++ b/contrib/libs/poco/Net/src/DatagramSocket.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/DatagramSocketImpl.cpp b/contrib/libs/poco/Net/src/DatagramSocketImpl.cpp new file mode 100644 index 0000000000..9b86ebe611 --- /dev/null +++ b/contrib/libs/poco/Net/src/DatagramSocketImpl.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/DialogSocket.cpp b/contrib/libs/poco/Net/src/DialogSocket.cpp new file mode 100644 index 0000000000..030280c6c3 --- /dev/null +++ b/contrib/libs/poco/Net/src/DialogSocket.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/FTPClientSession.cpp b/contrib/libs/poco/Net/src/FTPClientSession.cpp new file mode 100644 index 0000000000..e0bf448983 --- /dev/null +++ b/contrib/libs/poco/Net/src/FTPClientSession.cpp @@ -0,0 +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); + 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 new file mode 100644 index 0000000000..b557e2f751 --- /dev/null +++ b/contrib/libs/poco/Net/src/FTPStreamFactory.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/FilePartSource.cpp b/contrib/libs/poco/Net/src/FilePartSource.cpp new file mode 100644 index 0000000000..afd3a01db7 --- /dev/null +++ b/contrib/libs/poco/Net/src/FilePartSource.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTMLForm.cpp b/contrib/libs/poco/Net/src/HTMLForm.cpp new file mode 100644 index 0000000000..0518bdddd6 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTMLForm.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPAuthenticationParams.cpp b/contrib/libs/poco/Net/src/HTTPAuthenticationParams.cpp new file mode 100644 index 0000000000..1c01ac268f --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPAuthenticationParams.cpp @@ -0,0 +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); + + 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 new file mode 100644 index 0000000000..5b5e89897e --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPBasicCredentials.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPBufferAllocator.cpp b/contrib/libs/poco/Net/src/HTTPBufferAllocator.cpp new file mode 100644 index 0000000000..2944e2a612 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPBufferAllocator.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPChunkedStream.cpp b/contrib/libs/poco/Net/src/HTTPChunkedStream.cpp new file mode 100644 index 0000000000..5e8da38b9e --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPChunkedStream.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPClientSession.cpp b/contrib/libs/poco/Net/src/HTTPClientSession.cpp new file mode 100644 index 0000000000..c2b8170343 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPClientSession.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPCookie.cpp b/contrib/libs/poco/Net/src/HTTPCookie.cpp new file mode 100644 index 0000000000..9cbae4ad8a --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPCookie.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPCredentials.cpp b/contrib/libs/poco/Net/src/HTTPCredentials.cpp new file mode 100644 index 0000000000..ae1d6ea0b6 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPCredentials.cpp @@ -0,0 +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; + } + 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); + } + 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; + } + 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); + } + 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 diff --git a/contrib/libs/poco/Net/src/HTTPDigestCredentials.cpp b/contrib/libs/poco/Net/src/HTTPDigestCredentials.cpp new file mode 100644 index 0000000000..0d3deb5146 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPDigestCredentials.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPFixedLengthStream.cpp b/contrib/libs/poco/Net/src/HTTPFixedLengthStream.cpp new file mode 100644 index 0000000000..3273fe6c00 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPFixedLengthStream.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPHeaderStream.cpp b/contrib/libs/poco/Net/src/HTTPHeaderStream.cpp new file mode 100644 index 0000000000..7d8279bc80 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPHeaderStream.cpp @@ -0,0 +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), + _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; + 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 diff --git a/contrib/libs/poco/Net/src/HTTPIOStream.cpp b/contrib/libs/poco/Net/src/HTTPIOStream.cpp new file mode 100644 index 0000000000..c6492aed8f --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPIOStream.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPMessage.cpp b/contrib/libs/poco/Net/src/HTTPMessage.cpp new file mode 100644 index 0000000000..debda04c3b --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPMessage.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPRequest.cpp b/contrib/libs/poco/Net/src/HTTPRequest.cpp new file mode 100644 index 0000000000..52b3cf2f71 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPRequest.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPRequestHandler.cpp b/contrib/libs/poco/Net/src/HTTPRequestHandler.cpp new file mode 100644 index 0000000000..1d73ff8227 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPRequestHandler.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPRequestHandlerFactory.cpp b/contrib/libs/poco/Net/src/HTTPRequestHandlerFactory.cpp new file mode 100644 index 0000000000..d6f44f070b --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPRequestHandlerFactory.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPResponse.cpp b/contrib/libs/poco/Net/src/HTTPResponse.cpp new file mode 100644 index 0000000000..70093ac07e --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPResponse.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPServer.cpp b/contrib/libs/poco/Net/src/HTTPServer.cpp new file mode 100644 index 0000000000..31aa83d1be --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPServer.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPServerConnection.cpp b/contrib/libs/poco/Net/src/HTTPServerConnection.cpp new file mode 100644 index 0000000000..a6c27ce8c9 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPServerConnection.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPServerConnectionFactory.cpp b/contrib/libs/poco/Net/src/HTTPServerConnectionFactory.cpp new file mode 100644 index 0000000000..8e17288f3b --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPServerConnectionFactory.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPServerParams.cpp b/contrib/libs/poco/Net/src/HTTPServerParams.cpp new file mode 100644 index 0000000000..cc87161111 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPServerParams.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPServerRequest.cpp b/contrib/libs/poco/Net/src/HTTPServerRequest.cpp new file mode 100644 index 0000000000..de3d46481a --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPServerRequest.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPServerRequestImpl.cpp b/contrib/libs/poco/Net/src/HTTPServerRequestImpl.cpp new file mode 100644 index 0000000000..d8ea7398c9 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPServerRequestImpl.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPServerResponse.cpp b/contrib/libs/poco/Net/src/HTTPServerResponse.cpp new file mode 100644 index 0000000000..e5550a3222 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPServerResponse.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPServerResponseImpl.cpp b/contrib/libs/poco/Net/src/HTTPServerResponseImpl.cpp new file mode 100644 index 0000000000..fb6783c633 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPServerResponseImpl.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPServerSession.cpp b/contrib/libs/poco/Net/src/HTTPServerSession.cpp new file mode 100644 index 0000000000..f6d3c4e5b9 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPServerSession.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPSession.cpp b/contrib/libs/poco/Net/src/HTTPSession.cpp new file mode 100644 index 0000000000..cb6fdc25e9 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPSession.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPSessionFactory.cpp b/contrib/libs/poco/Net/src/HTTPSessionFactory.cpp new file mode 100644 index 0000000000..e4a62da68b --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPSessionFactory.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPSessionInstantiator.cpp b/contrib/libs/poco/Net/src/HTTPSessionInstantiator.cpp new file mode 100644 index 0000000000..d2f291f6b5 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPSessionInstantiator.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPStream.cpp b/contrib/libs/poco/Net/src/HTTPStream.cpp new file mode 100644 index 0000000000..2faeb422b0 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPStream.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HTTPStreamFactory.cpp b/contrib/libs/poco/Net/src/HTTPStreamFactory.cpp new file mode 100644 index 0000000000..ee77d98ec4 --- /dev/null +++ b/contrib/libs/poco/Net/src/HTTPStreamFactory.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/HostEntry.cpp b/contrib/libs/poco/Net/src/HostEntry.cpp new file mode 100644 index 0000000000..3257c70311 --- /dev/null +++ b/contrib/libs/poco/Net/src/HostEntry.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/ICMPClient.cpp b/contrib/libs/poco/Net/src/ICMPClient.cpp new file mode 100644 index 0000000000..4639d6a5fa --- /dev/null +++ b/contrib/libs/poco/Net/src/ICMPClient.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/ICMPEventArgs.cpp b/contrib/libs/poco/Net/src/ICMPEventArgs.cpp new file mode 100644 index 0000000000..3a219f9d74 --- /dev/null +++ b/contrib/libs/poco/Net/src/ICMPEventArgs.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/ICMPPacket.cpp b/contrib/libs/poco/Net/src/ICMPPacket.cpp new file mode 100644 index 0000000000..a05f7260f4 --- /dev/null +++ b/contrib/libs/poco/Net/src/ICMPPacket.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/ICMPPacketImpl.cpp b/contrib/libs/poco/Net/src/ICMPPacketImpl.cpp new file mode 100644 index 0000000000..48092c0094 --- /dev/null +++ b/contrib/libs/poco/Net/src/ICMPPacketImpl.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/ICMPSocket.cpp b/contrib/libs/poco/Net/src/ICMPSocket.cpp new file mode 100644 index 0000000000..4e66c237ae --- /dev/null +++ b/contrib/libs/poco/Net/src/ICMPSocket.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/ICMPSocketImpl.cpp b/contrib/libs/poco/Net/src/ICMPSocketImpl.cpp new file mode 100644 index 0000000000..8c68d53030 --- /dev/null +++ b/contrib/libs/poco/Net/src/ICMPSocketImpl.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/ICMPv4PacketImpl.cpp b/contrib/libs/poco/Net/src/ICMPv4PacketImpl.cpp new file mode 100644 index 0000000000..7df987a6fd --- /dev/null +++ b/contrib/libs/poco/Net/src/ICMPv4PacketImpl.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/IPAddress.cpp b/contrib/libs/poco/Net/src/IPAddress.cpp new file mode 100644 index 0000000000..e34a02181b --- /dev/null +++ b/contrib/libs/poco/Net/src/IPAddress.cpp @@ -0,0 +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 + 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 new file mode 100644 index 0000000000..316bba33f3 --- /dev/null +++ b/contrib/libs/poco/Net/src/IPAddressImpl.cpp @@ -0,0 +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(); +#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 +{ + 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 diff --git a/contrib/libs/poco/Net/src/MailMessage.cpp b/contrib/libs/poco/Net/src/MailMessage.cpp new file mode 100644 index 0000000000..6246f9e90b --- /dev/null +++ b/contrib/libs/poco/Net/src/MailMessage.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/MailRecipient.cpp b/contrib/libs/poco/Net/src/MailRecipient.cpp new file mode 100644 index 0000000000..1f6672810b --- /dev/null +++ b/contrib/libs/poco/Net/src/MailRecipient.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/MailStream.cpp b/contrib/libs/poco/Net/src/MailStream.cpp new file mode 100644 index 0000000000..8cd8fa44d8 --- /dev/null +++ b/contrib/libs/poco/Net/src/MailStream.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/MediaType.cpp b/contrib/libs/poco/Net/src/MediaType.cpp new file mode 100644 index 0000000000..d8a23c9ef2 --- /dev/null +++ b/contrib/libs/poco/Net/src/MediaType.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/MessageHeader.cpp b/contrib/libs/poco/Net/src/MessageHeader.cpp new file mode 100644 index 0000000000..a684b3cf5d --- /dev/null +++ b/contrib/libs/poco/Net/src/MessageHeader.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/MulticastSocket.cpp b/contrib/libs/poco/Net/src/MulticastSocket.cpp new file mode 100644 index 0000000000..e302f6a818 --- /dev/null +++ b/contrib/libs/poco/Net/src/MulticastSocket.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/MultipartReader.cpp b/contrib/libs/poco/Net/src/MultipartReader.cpp new file mode 100644 index 0000000000..a41b2d61c5 --- /dev/null +++ b/contrib/libs/poco/Net/src/MultipartReader.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/MultipartWriter.cpp b/contrib/libs/poco/Net/src/MultipartWriter.cpp new file mode 100644 index 0000000000..831fae1071 --- /dev/null +++ b/contrib/libs/poco/Net/src/MultipartWriter.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/NTPClient.cpp b/contrib/libs/poco/Net/src/NTPClient.cpp new file mode 100644 index 0000000000..b370388767 --- /dev/null +++ b/contrib/libs/poco/Net/src/NTPClient.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/NTPEventArgs.cpp b/contrib/libs/poco/Net/src/NTPEventArgs.cpp new file mode 100644 index 0000000000..21c57b8779 --- /dev/null +++ b/contrib/libs/poco/Net/src/NTPEventArgs.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/NTPPacket.cpp b/contrib/libs/poco/Net/src/NTPPacket.cpp new file mode 100644 index 0000000000..2f7aec830c --- /dev/null +++ b/contrib/libs/poco/Net/src/NTPPacket.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/NameValueCollection.cpp b/contrib/libs/poco/Net/src/NameValueCollection.cpp new file mode 100644 index 0000000000..def4814a16 --- /dev/null +++ b/contrib/libs/poco/Net/src/NameValueCollection.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/Net.cpp b/contrib/libs/poco/Net/src/Net.cpp new file mode 100644 index 0000000000..e81b4b5459 --- /dev/null +++ b/contrib/libs/poco/Net/src/Net.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/NetException.cpp b/contrib/libs/poco/Net/src/NetException.cpp new file mode 100644 index 0000000000..a167642b2a --- /dev/null +++ b/contrib/libs/poco/Net/src/NetException.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/NetworkInterface.cpp b/contrib/libs/poco/Net/src/NetworkInterface.cpp new file mode 100644 index 0000000000..e3b1c24f7b --- /dev/null +++ b/contrib/libs/poco/Net/src/NetworkInterface.cpp @@ -0,0 +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); + 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; + } + 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; + + } +} + + +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 diff --git a/contrib/libs/poco/Net/src/NullPartHandler.cpp b/contrib/libs/poco/Net/src/NullPartHandler.cpp new file mode 100644 index 0000000000..0a8cbf9794 --- /dev/null +++ b/contrib/libs/poco/Net/src/NullPartHandler.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/OAuth10Credentials.cpp b/contrib/libs/poco/Net/src/OAuth10Credentials.cpp new file mode 100644 index 0000000000..71ec0f736b --- /dev/null +++ b/contrib/libs/poco/Net/src/OAuth10Credentials.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/OAuth20Credentials.cpp b/contrib/libs/poco/Net/src/OAuth20Credentials.cpp new file mode 100644 index 0000000000..392115ad5f --- /dev/null +++ b/contrib/libs/poco/Net/src/OAuth20Credentials.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/POP3ClientSession.cpp b/contrib/libs/poco/Net/src/POP3ClientSession.cpp new file mode 100644 index 0000000000..159f2108c5 --- /dev/null +++ b/contrib/libs/poco/Net/src/POP3ClientSession.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/PartHandler.cpp b/contrib/libs/poco/Net/src/PartHandler.cpp new file mode 100644 index 0000000000..945cf318b5 --- /dev/null +++ b/contrib/libs/poco/Net/src/PartHandler.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/PartSource.cpp b/contrib/libs/poco/Net/src/PartSource.cpp new file mode 100644 index 0000000000..22f6c66828 --- /dev/null +++ b/contrib/libs/poco/Net/src/PartSource.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/PartStore.cpp b/contrib/libs/poco/Net/src/PartStore.cpp new file mode 100644 index 0000000000..3b0b0251d0 --- /dev/null +++ b/contrib/libs/poco/Net/src/PartStore.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/PollSet.cpp b/contrib/libs/poco/Net/src/PollSet.cpp new file mode 100644 index 0000000000..57d481d23e --- /dev/null +++ b/contrib/libs/poco/Net/src/PollSet.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/QuotedPrintableDecoder.cpp b/contrib/libs/poco/Net/src/QuotedPrintableDecoder.cpp new file mode 100644 index 0000000000..4f8b3c6726 --- /dev/null +++ b/contrib/libs/poco/Net/src/QuotedPrintableDecoder.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/QuotedPrintableEncoder.cpp b/contrib/libs/poco/Net/src/QuotedPrintableEncoder.cpp new file mode 100644 index 0000000000..a71eb154f5 --- /dev/null +++ b/contrib/libs/poco/Net/src/QuotedPrintableEncoder.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/RawSocket.cpp b/contrib/libs/poco/Net/src/RawSocket.cpp new file mode 100644 index 0000000000..7605dcac39 --- /dev/null +++ b/contrib/libs/poco/Net/src/RawSocket.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/RawSocketImpl.cpp b/contrib/libs/poco/Net/src/RawSocketImpl.cpp new file mode 100644 index 0000000000..c7fb248ef7 --- /dev/null +++ b/contrib/libs/poco/Net/src/RawSocketImpl.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/RemoteSyslogChannel.cpp b/contrib/libs/poco/Net/src/RemoteSyslogChannel.cpp new file mode 100644 index 0000000000..8ad6d5b2d0 --- /dev/null +++ b/contrib/libs/poco/Net/src/RemoteSyslogChannel.cpp @@ -0,0 +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()) + { + 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 diff --git a/contrib/libs/poco/Net/src/RemoteSyslogListener.cpp b/contrib/libs/poco/Net/src/RemoteSyslogListener.cpp new file mode 100644 index 0000000000..c33a4e49da --- /dev/null +++ b/contrib/libs/poco/Net/src/RemoteSyslogListener.cpp @@ -0,0 +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); + } + 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 new file mode 100644 index 0000000000..a498179a44 --- /dev/null +++ b/contrib/libs/poco/Net/src/SMTPChannel.cpp @@ -0,0 +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(); + } + 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 + 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 new file mode 100644 index 0000000000..35612381ee --- /dev/null +++ b/contrib/libs/poco/Net/src/SMTPClientSession.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/ServerSocket.cpp b/contrib/libs/poco/Net/src/ServerSocket.cpp new file mode 100644 index 0000000000..c44a52b5b5 --- /dev/null +++ b/contrib/libs/poco/Net/src/ServerSocket.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/ServerSocketImpl.cpp b/contrib/libs/poco/Net/src/ServerSocketImpl.cpp new file mode 100644 index 0000000000..7f6cd41bbf --- /dev/null +++ b/contrib/libs/poco/Net/src/ServerSocketImpl.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/Socket.cpp b/contrib/libs/poco/Net/src/Socket.cpp new file mode 100644 index 0000000000..72a8bd9e2f --- /dev/null +++ b/contrib/libs/poco/Net/src/Socket.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/SocketAddress.cpp b/contrib/libs/poco/Net/src/SocketAddress.cpp new file mode 100644 index 0000000000..0782ca3eea --- /dev/null +++ b/contrib/libs/poco/Net/src/SocketAddress.cpp @@ -0,0 +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; +} diff --git a/contrib/libs/poco/Net/src/SocketAddressImpl.cpp b/contrib/libs/poco/Net/src/SocketAddressImpl.cpp new file mode 100644 index 0000000000..57690170f2 --- /dev/null +++ b/contrib/libs/poco/Net/src/SocketAddressImpl.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/SocketImpl.cpp b/contrib/libs/poco/Net/src/SocketImpl.cpp new file mode 100644 index 0000000000..92c664ec82 --- /dev/null +++ b/contrib/libs/poco/Net/src/SocketImpl.cpp @@ -0,0 +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), + _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); + 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); + 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 +} + +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) +{ +#if defined(_WIN32) + int value = (int) timeout.totalMilliseconds(); + setOption(SOL_SOCKET, SO_SNDTIMEO, value); +#else + 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 + _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); + 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 diff --git a/contrib/libs/poco/Net/src/SocketNotification.cpp b/contrib/libs/poco/Net/src/SocketNotification.cpp new file mode 100644 index 0000000000..da3c922da5 --- /dev/null +++ b/contrib/libs/poco/Net/src/SocketNotification.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/SocketNotifier.cpp b/contrib/libs/poco/Net/src/SocketNotifier.cpp new file mode 100644 index 0000000000..9bbf6ca826 --- /dev/null +++ b/contrib/libs/poco/Net/src/SocketNotifier.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/SocketReactor.cpp b/contrib/libs/poco/Net/src/SocketReactor.cpp new file mode 100644 index 0000000000..79150e2842 --- /dev/null +++ b/contrib/libs/poco/Net/src/SocketReactor.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/SocketStream.cpp b/contrib/libs/poco/Net/src/SocketStream.cpp new file mode 100644 index 0000000000..77ae8c2442 --- /dev/null +++ b/contrib/libs/poco/Net/src/SocketStream.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/StreamSocket.cpp b/contrib/libs/poco/Net/src/StreamSocket.cpp new file mode 100644 index 0000000000..598d2991c6 --- /dev/null +++ b/contrib/libs/poco/Net/src/StreamSocket.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/StreamSocketImpl.cpp b/contrib/libs/poco/Net/src/StreamSocketImpl.cpp new file mode 100644 index 0000000000..8116942db5 --- /dev/null +++ b/contrib/libs/poco/Net/src/StreamSocketImpl.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/StringPartSource.cpp b/contrib/libs/poco/Net/src/StringPartSource.cpp new file mode 100644 index 0000000000..a512449f69 --- /dev/null +++ b/contrib/libs/poco/Net/src/StringPartSource.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/TCPServer.cpp b/contrib/libs/poco/Net/src/TCPServer.cpp new file mode 100644 index 0000000000..7a7282f785 --- /dev/null +++ b/contrib/libs/poco/Net/src/TCPServer.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/TCPServerConnection.cpp b/contrib/libs/poco/Net/src/TCPServerConnection.cpp new file mode 100644 index 0000000000..1072b182c2 --- /dev/null +++ b/contrib/libs/poco/Net/src/TCPServerConnection.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/TCPServerConnectionFactory.cpp b/contrib/libs/poco/Net/src/TCPServerConnectionFactory.cpp new file mode 100644 index 0000000000..a861e433d9 --- /dev/null +++ b/contrib/libs/poco/Net/src/TCPServerConnectionFactory.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/TCPServerDispatcher.cpp b/contrib/libs/poco/Net/src/TCPServerDispatcher.cpp new file mode 100644 index 0000000000..01474ec526 --- /dev/null +++ b/contrib/libs/poco/Net/src/TCPServerDispatcher.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/TCPServerParams.cpp b/contrib/libs/poco/Net/src/TCPServerParams.cpp new file mode 100644 index 0000000000..6a90374abc --- /dev/null +++ b/contrib/libs/poco/Net/src/TCPServerParams.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/WebSocket.cpp b/contrib/libs/poco/Net/src/WebSocket.cpp new file mode 100644 index 0000000000..17816ad00a --- /dev/null +++ b/contrib/libs/poco/Net/src/WebSocket.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/src/WebSocketImpl.cpp b/contrib/libs/poco/Net/src/WebSocketImpl.cpp new file mode 100644 index 0000000000..49fcad63c2 --- /dev/null +++ b/contrib/libs/poco/Net/src/WebSocketImpl.cpp @@ -0,0 +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 diff --git a/contrib/libs/poco/Net/ya.make b/contrib/libs/poco/Net/ya.make new file mode 100644 index 0000000000..9feadc7027 --- /dev/null +++ b/contrib/libs/poco/Net/ya.make @@ -0,0 +1,145 @@ +# Generated by devtools/yamaker. + +LIBRARY() + +OWNER( + orivej + g:cpp-contrib +) + +LICENSE( + BSD-3-Clause AND + BSL-1.0 AND + Custom-Punycode +) + +LICENSE_TEXTS(.yandex_meta/licenses.list.txt) + +PEERDIR( + contrib/libs/poco/Foundation +) + +ADDINCL( + GLOBAL contrib/libs/poco/Net/include + contrib/libs/poco/Foundation/include + contrib/libs/poco/Net/src +) + +NO_COMPILER_WARNINGS() + +NO_UTIL() + +CFLAGS( + -DPOCO_SOCKETADDRESS_DONT_PREFER_IPV4 +) + +IF (OS_LINUX) + CFLAGS( + -DPOCO_HAVE_FD_EPOLL + ) +ENDIF() + +SRCS( + src/AbstractHTTPRequestHandler.cpp + src/DNS.cpp + src/DatagramSocket.cpp + src/DatagramSocketImpl.cpp + src/DialogSocket.cpp + src/FTPClientSession.cpp + src/FTPStreamFactory.cpp + src/FilePartSource.cpp + src/HTMLForm.cpp + src/HTTPAuthenticationParams.cpp + src/HTTPBasicCredentials.cpp + src/HTTPBufferAllocator.cpp + src/HTTPChunkedStream.cpp + src/HTTPClientSession.cpp + src/HTTPCookie.cpp + src/HTTPCredentials.cpp + src/HTTPDigestCredentials.cpp + src/HTTPFixedLengthStream.cpp + src/HTTPHeaderStream.cpp + src/HTTPIOStream.cpp + src/HTTPMessage.cpp + src/HTTPRequest.cpp + src/HTTPRequestHandler.cpp + src/HTTPRequestHandlerFactory.cpp + src/HTTPResponse.cpp + src/HTTPServer.cpp + src/HTTPServerConnection.cpp + src/HTTPServerConnectionFactory.cpp + src/HTTPServerParams.cpp + src/HTTPServerRequest.cpp + src/HTTPServerRequestImpl.cpp + src/HTTPServerResponse.cpp + src/HTTPServerResponseImpl.cpp + src/HTTPServerSession.cpp + src/HTTPSession.cpp + src/HTTPSessionFactory.cpp + src/HTTPSessionInstantiator.cpp + src/HTTPStream.cpp + src/HTTPStreamFactory.cpp + src/HostEntry.cpp + src/ICMPClient.cpp + src/ICMPEventArgs.cpp + src/ICMPPacket.cpp + src/ICMPPacketImpl.cpp + src/ICMPSocket.cpp + src/ICMPSocketImpl.cpp + src/ICMPv4PacketImpl.cpp + src/IPAddress.cpp + src/IPAddressImpl.cpp + src/MailMessage.cpp + src/MailRecipient.cpp + src/MailStream.cpp + src/MediaType.cpp + src/MessageHeader.cpp + src/MulticastSocket.cpp + src/MultipartReader.cpp + src/MultipartWriter.cpp + src/NTPClient.cpp + src/NTPEventArgs.cpp + src/NTPPacket.cpp + src/NameValueCollection.cpp + src/Net.cpp + src/NetException.cpp + src/NetworkInterface.cpp + src/NullPartHandler.cpp + src/OAuth10Credentials.cpp + src/OAuth20Credentials.cpp + src/POP3ClientSession.cpp + src/PartHandler.cpp + src/PartSource.cpp + src/PartStore.cpp + src/PollSet.cpp + src/QuotedPrintableDecoder.cpp + src/QuotedPrintableEncoder.cpp + src/RawSocket.cpp + src/RawSocketImpl.cpp + src/RemoteSyslogChannel.cpp + src/RemoteSyslogListener.cpp + src/SMTPChannel.cpp + src/SMTPClientSession.cpp + src/ServerSocket.cpp + src/ServerSocketImpl.cpp + src/Socket.cpp + src/SocketAddress.cpp + src/SocketAddressImpl.cpp + src/SocketImpl.cpp + src/SocketNotification.cpp + src/SocketNotifier.cpp + src/SocketReactor.cpp + src/SocketStream.cpp + src/StreamSocket.cpp + src/StreamSocketImpl.cpp + src/StringPartSource.cpp + src/TCPServer.cpp + src/TCPServerConnection.cpp + src/TCPServerConnectionFactory.cpp + src/TCPServerDispatcher.cpp + src/TCPServerParams.cpp + src/WebSocket.cpp + src/WebSocketImpl.cpp +) + +END() |