Update POCO library.

This commit is contained in:
Sandu Liviu Catalin
2023-03-23 20:19:11 +02:00
parent 8d15f4b6e9
commit 233fc103f9
2521 changed files with 257092 additions and 72789 deletions
+1 -1
View File
@@ -117,7 +117,7 @@ HostEntry DNS::hostByAddress(const IPAddress& address, unsigned
#if defined(POCO_HAVE_ADDRINFO)
SocketAddress sa(address, 0);
static char fqname[1024];
char fqname[1024];
int rc = getnameinfo(sa.addr(), sa.length(), fqname, sizeof(fqname), NULL, 0, NI_NAMEREQD);
if (rc == 0)
{
+54 -8
View File
@@ -34,15 +34,12 @@ DatagramSocket::DatagramSocket(SocketAddress::Family family): Socket(new Datagra
}
DatagramSocket::DatagramSocket(const SocketAddress& address, bool reuseAddress): Socket(new DatagramSocketImpl(address.family()))
DatagramSocket::DatagramSocket(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only):
Socket(new DatagramSocketImpl(address.family()))
{
bind(address, reuseAddress);
}
DatagramSocket::DatagramSocket(const SocketAddress& address, bool reuseAddress, bool reusePort): Socket(new DatagramSocketImpl(address.family()))
{
bind(address, reuseAddress, reusePort);
if (address.family() == SocketAddress::IPv6)
bind6(address, reuseAddress, reusePort, ipV6Only);
else bind(address, reuseAddress, reusePort);
}
@@ -53,6 +50,11 @@ DatagramSocket::DatagramSocket(const Socket& socket): Socket(socket)
}
DatagramSocket::DatagramSocket(const DatagramSocket& socket): Socket(socket)
{
}
DatagramSocket::DatagramSocket(SocketImpl* pImpl): Socket(pImpl)
{
if (!dynamic_cast<DatagramSocketImpl*>(impl()))
@@ -74,6 +76,44 @@ DatagramSocket& DatagramSocket::operator = (const Socket& socket)
return *this;
}
#if POCO_NEW_STATE_ON_MOVE
DatagramSocket::DatagramSocket(DatagramSocket&& socket): Socket(std::move(socket))
{
}
DatagramSocket::DatagramSocket(Socket&& socket): Socket(std::move(socket))
{
if (!dynamic_cast<DatagramSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
DatagramSocket& DatagramSocket::operator = (Socket&& socket)
{
if (dynamic_cast<DatagramSocketImpl*>(socket.impl()))
Socket::operator = (std::move(socket));
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
DatagramSocket& DatagramSocket::operator = (DatagramSocket&& socket)
{
Socket::operator = (std::move(socket));
return *this;
}
#endif // POCO_NEW_STATE_ON_MOVE
DatagramSocket& DatagramSocket::operator = (const DatagramSocket& socket)
{
Socket::operator = (socket);
return *this;
}
void DatagramSocket::connect(const SocketAddress& address)
{
@@ -93,6 +133,12 @@ void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress, bool
}
void DatagramSocket::bind6(const SocketAddress& address, bool reuseAddress, bool reusePort, bool ipV6Only)
{
impl()->bind6(address, reuseAddress, reusePort, ipV6Only);
}
int DatagramSocket::sendBytes(const void* buffer, int length, int flags)
{
return impl()->sendBytes(buffer, length, flags);
+10 -4
View File
@@ -28,10 +28,11 @@ namespace Poco {
namespace Net {
FTPClientSession::FTPClientSession():
FTPClientSession::FTPClientSession(Poco::UInt16 activeDataPort):
_pControlSocket(0),
_pDataStream(0),
_port(FTP_PORT),
_activeDataPort(activeDataPort),
_passiveMode(true),
_fileType(TYPE_BINARY),
_supports1738(true),
@@ -42,11 +43,14 @@ FTPClientSession::FTPClientSession():
}
FTPClientSession::FTPClientSession(const StreamSocket& socket, bool readWelcomeMessage):
FTPClientSession::FTPClientSession(const StreamSocket& socket,
bool readWelcomeMessage,
Poco::UInt16 activeDataPort):
_pControlSocket(new DialogSocket(socket)),
_pDataStream(0),
_host(socket.address().host().toString()),
_port(socket.address().port()),
_activeDataPort(activeDataPort),
_passiveMode(true),
_fileType(TYPE_BINARY),
_supports1738(true),
@@ -69,11 +73,13 @@ FTPClientSession::FTPClientSession(const StreamSocket& socket, bool readWelcomeM
FTPClientSession::FTPClientSession(const std::string& host,
Poco::UInt16 port,
const std::string& username,
const std::string& password):
const std::string& password,
Poco::UInt16 activeDataPort):
_pControlSocket(new DialogSocket(SocketAddress(host, port))),
_pDataStream(0),
_host(host),
_port(port),
_activeDataPort(activeDataPort),
_passiveMode(true),
_fileType(TYPE_BINARY),
_supports1738(true),
@@ -452,7 +458,7 @@ StreamSocket FTPClientSession::activeDataConnection(const std::string& command,
if (!isOpen())
throw FTPException("Connection is closed.");
ServerSocket server(SocketAddress(_pControlSocket->address().host(), 0));
ServerSocket server(SocketAddress(_pControlSocket->address().host(), _activeDataPort));
sendPortCommand(server.address());
std::string response;
int status = sendCommand(command, arg, response);
+13 -13
View File
@@ -41,17 +41,17 @@ public:
// make sure exceptions from underlying string propagate
_istr.exceptions(std::ios::badbit);
}
~FTPStreamBuf()
{
}
private:
int readFromDevice()
{
return _istr.get();
}
std::istream& _istr;
};
@@ -64,11 +64,11 @@ public:
{
poco_ios_init(&_buf);
}
~FTPIOS()
{
}
FTPStreamBuf* rdbuf()
{
return &_buf;
@@ -88,12 +88,12 @@ public:
_pSession(pSession)
{
}
~FTPStream()
{
delete _pSession;
}
private:
FTPClientSession* _pSession;
};
@@ -133,15 +133,15 @@ std::istream* FTPStreamFactory::open(const URI& uri)
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)
@@ -163,19 +163,19 @@ 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;
+47 -12
View File
@@ -13,6 +13,7 @@
#include "Poco/Net/HTTPChunkedStream.h"
#include "Poco/Net/HTTPStream.h"
#include "Poco/Net/HTTPSession.h"
#include "Poco/NumberFormatter.h"
#include "Poco/NumberParser.h"
@@ -32,11 +33,12 @@ namespace Net {
//
HTTPChunkedStreamBuf::HTTPChunkedStreamBuf(HTTPSession& session, openmode mode):
HTTPChunkedStreamBuf::HTTPChunkedStreamBuf(HTTPSession& session, openmode mode, MessageHeader* pTrailer):
HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode),
_session(session),
_mode(mode),
_chunk(0)
_chunk(0),
_pTrailer(pTrailer)
{
}
@@ -51,7 +53,16 @@ void HTTPChunkedStreamBuf::close()
if (_mode & std::ios::out)
{
sync();
_session.write("0\r\n\r\n", 5);
_session.write("0\r\n", 3);
if (_pTrailer && !_pTrailer->empty())
{
HTTPOutputStream hos(_session);
_pTrailer->write(hos);
}
else
{
_session.write("\r\n", 2);
}
}
}
@@ -70,9 +81,14 @@ int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length)
while (ch != eof && ch != '\n') ch = _session.get();
unsigned chunk;
if (NumberParser::tryParseHex(chunkLen, chunk))
{
_chunk = (std::streamsize) chunk;
}
else
{
_chunk = -1;
return eof;
}
}
if (_chunk > 0)
{
@@ -81,12 +97,31 @@ int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length)
if (n > 0) _chunk -= n;
return n;
}
else
else if (_chunk == 0)
{
int ch = _session.get();
while (ch != eof && ch != '\n') ch = _session.get();
int ch = _session.peek();
if (ch != eof && ch != '\r' && ch != '\n')
{
HTTPInputStream his(_session);
if (_pTrailer)
{
_pTrailer->read(his);
}
else
{
MessageHeader trailer;
trailer.read(his);
}
}
else
{
ch = _session.get();
while (ch != eof && ch != '\n') ch = _session.get();
}
_chunk = -1;
return 0;
}
else return eof;
}
@@ -107,8 +142,8 @@ int HTTPChunkedStreamBuf::writeToDevice(const char* buffer, std::streamsize leng
//
HTTPChunkedIOS::HTTPChunkedIOS(HTTPSession& session, HTTPChunkedStreamBuf::openmode mode):
_buf(session, mode)
HTTPChunkedIOS::HTTPChunkedIOS(HTTPSession& session, HTTPChunkedStreamBuf::openmode mode, MessageHeader* pTrailer):
_buf(session, mode, pTrailer)
{
poco_ios_init(&_buf);
}
@@ -140,8 +175,8 @@ HTTPChunkedStreamBuf* HTTPChunkedIOS::rdbuf()
Poco::MemoryPool HTTPChunkedInputStream::_pool(sizeof(HTTPChunkedInputStream));
HTTPChunkedInputStream::HTTPChunkedInputStream(HTTPSession& session):
HTTPChunkedIOS(session, std::ios::in),
HTTPChunkedInputStream::HTTPChunkedInputStream(HTTPSession& session, MessageHeader* pTrailer):
HTTPChunkedIOS(session, std::ios::in, pTrailer),
std::istream(&_buf)
{
}
@@ -179,8 +214,8 @@ void HTTPChunkedInputStream::operator delete(void* ptr)
Poco::MemoryPool HTTPChunkedOutputStream::_pool(sizeof(HTTPChunkedOutputStream));
HTTPChunkedOutputStream::HTTPChunkedOutputStream(HTTPSession& session):
HTTPChunkedIOS(session, std::ios::out),
HTTPChunkedOutputStream::HTTPChunkedOutputStream(HTTPSession& session, MessageHeader* pTrailer):
HTTPChunkedIOS(session, std::ios::out, pTrailer),
std::ostream(&_buf)
{
}
+70 -9
View File
@@ -40,6 +40,8 @@ HTTPClientSession::ProxyConfig HTTPClientSession::_globalProxyConfig;
HTTPClientSession::HTTPClientSession():
_port(HTTPSession::HTTP_PORT),
_sourceAddress4(IPAddress::wildcard(IPAddress::IPv4), 0),
_sourceAddress6(IPAddress::wildcard(IPAddress::IPv6), 0),
_proxyConfig(_globalProxyConfig),
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
@@ -54,6 +56,8 @@ HTTPClientSession::HTTPClientSession():
HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
HTTPSession(socket),
_port(HTTPSession::HTTP_PORT),
_sourceAddress4(IPAddress::wildcard(IPAddress::IPv4), 0),
_sourceAddress6(IPAddress::wildcard(IPAddress::IPv6), 0),
_proxyConfig(_globalProxyConfig),
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
@@ -68,6 +72,8 @@ HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
HTTPClientSession::HTTPClientSession(const SocketAddress& address):
_host(address.host().toString()),
_port(address.port()),
_sourceAddress4(IPAddress::wildcard(IPAddress::IPv4), 0),
_sourceAddress6(IPAddress::wildcard(IPAddress::IPv6), 0),
_proxyConfig(_globalProxyConfig),
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
@@ -82,6 +88,8 @@ HTTPClientSession::HTTPClientSession(const SocketAddress& address):
HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port):
_host(host),
_port(port),
_sourceAddress4(IPAddress::wildcard(IPAddress::IPv4), 0),
_sourceAddress6(IPAddress::wildcard(IPAddress::IPv6), 0),
_proxyConfig(_globalProxyConfig),
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
@@ -107,6 +115,21 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port,
}
HTTPClientSession::HTTPClientSession(const StreamSocket& socket, const ProxyConfig& proxyConfig):
HTTPSession(socket),
_port(HTTPSession::HTTP_PORT),
_sourceAddress4(IPAddress::wildcard(IPAddress::IPv4), 0),
_sourceAddress6(IPAddress::wildcard(IPAddress::IPv6), 0),
_proxyConfig(proxyConfig),
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false),
_responseReceived(false)
{
}
HTTPClientSession::~HTTPClientSession()
{
}
@@ -130,6 +153,39 @@ void HTTPClientSession::setPort(Poco::UInt16 port)
}
void HTTPClientSession::setSourceAddress(const SocketAddress& address)
{
if (!connected())
{
if (address.family() == IPAddress::IPv4)
_sourceAddress4 = address;
else
_sourceAddress6 = address;
_sourceAddress = address;
}
else
throw IllegalStateException("Cannot set the source address for an already connected session");
}
const SocketAddress& HTTPClientSession::getSourceAddress()
{
return _sourceAddress;
}
const SocketAddress& HTTPClientSession::getSourceAddress4()
{
return _sourceAddress4;
}
const SocketAddress& HTTPClientSession::getSourceAddress6()
{
return _sourceAddress6;
}
void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port)
{
if (!connected())
@@ -253,7 +309,7 @@ std::ostream& HTTPClientSession::sendRequestImpl(const HTTPRequest& request)
{
HTTPHeaderOutputStream hos(*this);
request.write(hos);
_pRequestStream = new HTTPChunkedOutputStream(*this);
_pRequestStream = new HTTPChunkedOutputStream(*this, &requestTrailer());
}
else if (request.hasContentLength())
{
@@ -293,6 +349,7 @@ void HTTPClientSession::flushRequest()
std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response)
{
flushRequest();
responseTrailer().clear();
if (!_responseReceived)
{
do
@@ -320,7 +377,7 @@ std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response)
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);
_pResponseStream = new HTTPChunkedInputStream(*this, &responseTrailer());
else if (response.hasContentLength())
#if defined(POCO_HAVE_INT64)
_pResponseStream = new HTTPFixedLengthInputStream(*this, response.getContentLength64());
@@ -400,16 +457,18 @@ int HTTPClientSession::write(const char* buffer, std::streamsize length)
void HTTPClientSession::reconnect()
{
SocketAddress addr;
if (_proxyConfig.host.empty() || bypassProxy())
{
SocketAddress addr(_host, _port);
connect(addr);
}
addr = SocketAddress(_host, _port);
else
addr = SocketAddress(_proxyConfig.host, _proxyConfig.port);
if ((!_sourceAddress4.host().isWildcard()) || (_sourceAddress4.port() != 0))
connect(addr, _sourceAddress4);
else if ((!_sourceAddress6.host().isWildcard()) || (_sourceAddress6.port() != 0))
connect(addr, _sourceAddress6);
else
{
SocketAddress addr(_proxyConfig.host, _proxyConfig.port);
connect(addr);
}
}
@@ -536,6 +595,8 @@ StreamSocket HTTPClientSession::proxyConnect()
proxyRequest.set(HTTPRequest::HOST, getHost());
proxySession.proxyAuthenticateImpl(proxyRequest, _proxyConfig);
proxySession.setKeepAlive(true);
proxySession.setSourceAddress(_sourceAddress4);
proxySession.setSourceAddress(_sourceAddress6);
proxySession.sendRequest(proxyRequest);
proxySession.receiveResponse(proxyResponse);
if (proxyResponse.getStatus() != HTTPResponse::HTTP_OK)
+118 -13
View File
@@ -18,12 +18,15 @@
#include "Poco/DateTimeFormatter.h"
#include "Poco/Exception.h"
#include "Poco/MD5Engine.h"
#include "Poco/SHA1Engine.h"
#include "Poco/SHA2Engine.h"
#include "Poco/Net/HTTPDigestCredentials.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/NumberFormatter.h"
#include "Poco/StringTokenizer.h"
#include <iostream>
namespace
{
@@ -68,7 +71,28 @@ namespace Net {
const std::string HTTPDigestCredentials::SCHEME = "Digest";
const std::string HTTPDigestCredentials::DEFAULT_ALGORITHM("MD5");
const std::vector<std::string> HTTPDigestCredentials::SUPPORTED_ALGORITHMS = {
"MD5",
"MD5-sess",
"SHA",
"SHA-sess",
"SHA-256",
"SHA-256-sess",
"SHA-512-256",
"SHA-512-256-sess",
"SHA-512",
"SHA-512-sess"
};
const std::string HTTPDigestCredentials::MD_5_ALGORITHM = "MD5";
const std::string HTTPDigestCredentials::MD_5_SESS_ALGORITHM = "MD5-sess";
const std::string HTTPDigestCredentials::SHA_ALGORITHM = "SHA";
const std::string HTTPDigestCredentials::SHA_SESS_ALGORITHM = "SHA-sess";
const std::string HTTPDigestCredentials::SHA_256_ALGORITHM = "SHA-256";
const std::string HTTPDigestCredentials::SHA_256_SESS_ALGORITHM = "SHA-256-sess";
const std::string HTTPDigestCredentials::SHA_512_256_ALGORITHM = "SHA-512-256";
const std::string HTTPDigestCredentials::SHA_512_256_SESS_ALGORITHM = "SHA-512-256-sess";
const std::string HTTPDigestCredentials::SHA_512_ALGORITHM = "SHA-512";
const std::string HTTPDigestCredentials::SHA_512_SESS_ALGORITHM = "SHA-512-sess";
const std::string HTTPDigestCredentials::DEFAULT_QOP("");
const std::string HTTPDigestCredentials::NONCE_PARAM("nonce");
const std::string HTTPDigestCredentials::REALM_PARAM("realm");
@@ -84,6 +108,44 @@ const std::string HTTPDigestCredentials::NC_PARAM("nc");
int HTTPDigestCredentials::_nonceCounter(0);
Poco::FastMutex HTTPDigestCredentials::_nonceMutex;
class HTTPDigestCredentials::DigestEngineProvider {
public:
DigestEngineProvider(std::string algorithm): _algorithm(algorithm) {
_isSessionAlgorithm = _algorithm.find("sess") != std::string::npos;
}
DigestEngine& engine() {
if (icompare(_algorithm, SHA_ALGORITHM) == 0 || icompare(_algorithm, SHA_SESS_ALGORITHM) == 0)
{
return _sha1Engine;
}
if (icompare(_algorithm, SHA_256_ALGORITHM) == 0 || icompare(_algorithm, SHA_256_SESS_ALGORITHM) == 0)
{
return _sha256Engine;
} else if (icompare(_algorithm, SHA_512_256_ALGORITHM) == 0 || icompare(_algorithm, SHA_512_256_SESS_ALGORITHM) == 0)
{
return _sha512_256Engine;
} else if (icompare(_algorithm, SHA_512_ALGORITHM) == 0 || icompare(_algorithm, SHA_512_SESS_ALGORITHM) == 0)
{
return _sha512;
}
else {
return _md5Engine;
}
}
bool isSessionAlgorithm() {
return _isSessionAlgorithm;
}
private:
std::string _algorithm;
SHA1Engine _sha1Engine;
MD5Engine _md5Engine;
SHA2Engine _sha256Engine { SHA2Engine::ALGORITHM::SHA_256 };
SHA2Engine _sha512_256Engine { SHA2Engine::ALGORITHM::SHA_512_256 };
SHA2Engine _sha512 { SHA2Engine::ALGORITHM::SHA_512 };
bool _isSessionAlgorithm;
};
HTTPDigestCredentials::HTTPDigestCredentials()
{
@@ -191,11 +253,6 @@ void HTTPDigestCredentials::createAuthParams(const HTTPRequest& request, const H
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();
@@ -208,6 +265,10 @@ void HTTPDigestCredentials::createAuthParams(const HTTPRequest& request, const H
{
_requestAuthParams.set(OPAQUE_PARAM, responseAuthParams.get(OPAQUE_PARAM));
}
if (responseAuthParams.has(ALGORITHM_PARAM))
{
_requestAuthParams.set(ALGORITHM_PARAM, responseAuthParams.get(ALGORITHM_PARAM));
}
if (qop.empty())
{
@@ -233,10 +294,8 @@ void HTTPDigestCredentials::createAuthParams(const HTTPRequest& request, const H
}
}
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);
@@ -245,6 +304,11 @@ void HTTPDigestCredentials::updateAuthParams(const HTTPRequest& request)
if (qop.empty())
{
/// Assume that https://tools.ietf.org/html/rfc7616 does not supported
/// and still using https://tools.ietf.org/html/rfc2069#section-2.4
MD5Engine engine;
const std::string ha1 = digest(engine, _username, realm, _password);
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
@@ -252,13 +316,28 @@ void HTTPDigestCredentials::updateAuthParams(const HTTPRequest& request)
}
else if (icompare(qop, AUTH_PARAM) == 0)
{
const std::string cnonce = _requestAuthParams.get(CNONCE_PARAM);
const std::string algorithm = _requestAuthParams.get(ALGORITHM_PARAM, MD_5_ALGORITHM);
const std::string ha1 = digest(engine, _username, realm, _password);
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
if (!isAlgorithmSupported(algorithm)) {
throw NotImplementedException("Unsupported digest algorithm", algorithm);
}
const std::string cnonce = _requestAuthParams.get(CNONCE_PARAM);
const std::string nc = formatNonceCounter(updateNonceCounter(nonce));
DigestEngineProvider engineProvider(algorithm);
DigestEngine &engine = engineProvider.engine();
std::string ha1 = digest(engine, _username, realm, _password);
if (engineProvider.isSessionAlgorithm()) {
ha1 = digest(engine, ha1, nonce, cnonce);
}
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
_requestAuthParams.set(NC_PARAM, nc);
_requestAuthParams.set(CNONCE_PARAM, cnonce);
_requestAuthParams.set(RESPONSE_PARAM, digest(engine, ha1, nonce, nc, cnonce, qop, ha2));
}
}
@@ -277,18 +356,34 @@ bool HTTPDigestCredentials::verifyAuthParams(const HTTPRequest& request, const H
const std::string& realm = params.getRealm();
const std::string& qop = params.get(QOP_PARAM, DEFAULT_QOP);
std::string response;
MD5Engine engine;
if (qop.empty())
{
MD5Engine engine;
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& algorithm = params.get(ALGORITHM_PARAM, MD_5_ALGORITHM);
if (!isAlgorithmSupported(algorithm)) {
throw NotImplementedException("Unsupported digest algorithm", algorithm);
}
DigestEngineProvider engineProvider(algorithm);
DigestEngine& engine = engineProvider.engine();
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);
std::string ha1 = digest(engine, _username, realm, _password);
if (engineProvider.isSessionAlgorithm()) {
ha1 = digest(engine, ha1, nonce, cnonce);
}
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
response = digest(engine, ha1, nonce, nc, cnonce, qop, ha2);
}
@@ -309,5 +404,15 @@ int HTTPDigestCredentials::updateNonceCounter(const std::string& nonce)
return iter->second;
}
bool HTTPDigestCredentials::isAlgorithmSupported(const std::string& algorithm) const
{
bool isAlgorithmSupported = std::find_if(std::begin(SUPPORTED_ALGORITHMS),
std::end(SUPPORTED_ALGORITHMS),
[&algorithm](const std::string& supportedAlgorithm) {
return icompare(algorithm, supportedAlgorithm) == 0;
}) != std::end(SUPPORTED_ALGORITHMS);
return isAlgorithmSupported;
}
} } // namespace Poco::Net
+3
View File
@@ -81,6 +81,7 @@ const std::string HTTPResponse::HTTP_REASON_MISDIRECTED_REQUEST = "M
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_TOO_EARLY = "Too Early";
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";
@@ -363,6 +364,8 @@ const std::string& HTTPResponse::getReasonForStatus(HTTPStatus status)
return HTTP_REASON_LOCKED;
case HTTP_FAILED_DEPENDENCY:
return HTTP_REASON_FAILED_DEPENDENCY;
case HTTP_TOO_EARLY:
return HTTP_REASON_TOO_EARLY;
case HTTP_UPGRADE_REQUIRED:
return HTTP_REASON_UPGRADE_REQUIRED;
case HTTP_PRECONDITION_REQUIRED:
+2
View File
@@ -76,6 +76,8 @@ void HTTPServerConnection::run()
response.set("Server", server);
try
{
session.requestTrailer().clear();
session.responseTrailer().clear();
std::unique_ptr<HTTPRequestHandler> pHandler(_pFactory->createRequestHandler(request));
if (pHandler.get())
{
+6 -6
View File
@@ -32,12 +32,12 @@ HTTPServerParams::~HTTPServerParams()
{
}
void HTTPServerParams::setServerName(const std::string& serverName)
{
_serverName = serverName;
}
void HTTPServerParams::setSoftwareVersion(const std::string& softwareVersion)
{
@@ -50,24 +50,24 @@ 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
+3 -3
View File
@@ -41,13 +41,13 @@ HTTPServerRequestImpl::HTTPServerRequestImpl(HTTPServerResponseImpl& response, H
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);
_pStream = new HTTPChunkedInputStream(session, &session.requestTrailer());
else if (hasContentLength())
#if defined(POCO_HAVE_INT64)
_pStream = new HTTPFixedLengthInputStream(session, getContentLength64());
+5 -5
View File
@@ -82,13 +82,13 @@ std::ostream& HTTPServerResponseImpl::send()
{
HTTPHeaderOutputStream hs(_session);
write(hs);
_pStream = new HTTPChunkedOutputStream(_session);
_pStream = new HTTPChunkedOutputStream(_session, &_session.responseTrailer());
}
else if (hasContentLength())
{
Poco::CountingOutputStream cs;
write(cs);
#if defined(POCO_HAVE_INT64)
#if defined(POCO_HAVE_INT64)
_pStream = new HTTPFixedLengthOutputStream(_session, getContentLength64() + cs.chars());
#else
_pStream = new HTTPFixedLengthOutputStream(_session, getContentLength() + cs.chars());
@@ -113,7 +113,7 @@ void HTTPServerResponseImpl::sendFile(const std::string& path, const std::string
Timestamp dateTime = f.getLastModified();
File::FileSize length = f.getSize();
set("Last-Modified", DateTimeFormatter::format(dateTime, DateTimeFormat::HTTP_FORMAT));
#if defined(POCO_HAVE_INT64)
#if defined(POCO_HAVE_INT64)
setContentLength64(length);
#else
setContentLength(static_cast<int>(length));
@@ -141,7 +141,7 @@ void HTTPServerResponseImpl::sendBuffer(const void* pBuffer, std::size_t length)
setContentLength(static_cast<int>(length));
setChunkedTransferEncoding(false);
_pStream = new HTTPHeaderOutputStream(_session);
write(*_pStream);
if (_pRequest && _pRequest->getMethod() != HTTPRequest::HTTP_HEAD)
@@ -169,7 +169,7 @@ void HTTPServerResponseImpl::redirect(const std::string& uri, HTTPStatus status)
void HTTPServerResponseImpl::requireAuthentication(const std::string& realm)
{
poco_assert (!_pStream);
setStatusAndReason(HTTPResponse::HTTP_UNAUTHORIZED);
std::string auth("Basic realm=\"");
auth.append(realm);
+1 -1
View File
@@ -47,7 +47,7 @@ bool HTTPServerSession::hasMoreRequests()
}
else if (_maxKeepAliveRequests != 0 && getKeepAlive())
{
if (_maxKeepAliveRequests > 0)
if (_maxKeepAliveRequests > 0)
--_maxKeepAliveRequests;
return buffered() > 0 || socket().poll(_keepAliveTimeout, Socket::SELECT_READ);
}
+10 -3
View File
@@ -111,14 +111,14 @@ 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)
@@ -130,7 +130,7 @@ int HTTPSession::peek()
return std::char_traits<char>::eof();
}
int HTTPSession::read(char* buffer, std::streamsize length)
{
if (_pCurrent < _pEnd)
@@ -203,6 +203,13 @@ void HTTPSession::connect(const SocketAddress& address)
}
void HTTPSession::connect(const SocketAddress& targetAddress, const SocketAddress& sourceAddress)
{
_socket.bind(sourceAddress, true);
connect(targetAddress);
}
void HTTPSession::abort()
{
_socket.shutdown();
+12 -12
View File
@@ -85,7 +85,7 @@ std::istream* HTTPStreamFactory::open(const URI& uri)
if (!pSession)
{
pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort());
if (proxyUri.empty())
{
if (!_proxyHost.empty())
@@ -103,28 +103,28 @@ std::istream* HTTPStreamFactory::open(const URI& uri)
}
}
}
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",
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 ||
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)
@@ -142,13 +142,13 @@ std::istream* HTTPStreamFactory::open(const URI& uri)
}
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
// 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;
delete pSession;
pSession = 0;
retry = true; // only allow useproxy once
}
+3 -3
View File
@@ -30,7 +30,7 @@ HostEntry::HostEntry(struct hostent* entry)
{
poco_check_ptr (entry);
_name = entry->h_name;
_name = entry->h_name;
char** alias = entry->h_aliases;
if (alias)
{
@@ -61,7 +61,7 @@ HostEntry::HostEntry(struct hostent* entry)
HostEntry::HostEntry(struct addrinfo* ainfo)
{
poco_check_ptr (ainfo);
for (struct addrinfo* ai = ainfo; ai; ai = ai->ai_next)
{
if (ai->ai_canonname)
@@ -123,7 +123,7 @@ HostEntry& HostEntry::operator = (const HostEntry& entry)
}
void HostEntry::swap(HostEntry& hostEntry)
void HostEntry::swap(HostEntry& hostEntry) noexcept
{
std::swap(_name, hostEntry._name);
std::swap(_aliases, hostEntry._aliases);
+12 -12
View File
@@ -31,11 +31,11 @@ namespace Net {
ICMPEventArgs::ICMPEventArgs(const SocketAddress& address, int repetitions, int dataSize, int ttl):
_address(address),
_address(address),
_sent(0),
_dataSize(dataSize),
_ttl(ttl),
_rtt(repetitions, 0),
_dataSize(dataSize),
_ttl(ttl),
_rtt(repetitions, 0),
_errors(repetitions)
{
}
@@ -52,10 +52,10 @@ std::string ICMPEventArgs::hostName() const
{
return DNS::resolve(_address.host().toString()).name();
}
catch (HostNotFoundException&)
catch (HostNotFoundException&)
{
}
catch (NoAddressFoundException&)
catch (NoAddressFoundException&)
{
}
catch (DNSException&)
@@ -101,7 +101,7 @@ int ICMPEventArgs::received() const
{
int received = 0;
for (int i = 0; i < _rtt.size(); ++i)
for (int i = 0; i < _rtt.size(); ++i)
{
if (_rtt[i]) ++received;
}
@@ -111,7 +111,7 @@ int ICMPEventArgs::received() const
void ICMPEventArgs::setError(int index, const std::string& text)
{
if (index >= _errors.size())
if (index >= _errors.size())
throw InvalidArgumentException("Supplied index exceeds vector capacity.");
_errors[index] = text;
@@ -120,7 +120,7 @@ void ICMPEventArgs::setError(int index, const std::string& text)
const std::string& ICMPEventArgs::error(int index) const
{
if (0 == _errors.size())
if (0 == _errors.size())
throw InvalidArgumentException("Supplied index exceeds vector capacity.");
if (-1 == index) index = _sent - 1;
@@ -131,7 +131,7 @@ const std::string& ICMPEventArgs::error(int index) const
void ICMPEventArgs::setReplyTime(int index, int time)
{
if (index >= _rtt.size())
if (index >= _rtt.size())
throw InvalidArgumentException("Supplied index exceeds array capacity.");
if (0 == time) time = 1;
_rtt[index] = time;
@@ -140,7 +140,7 @@ void ICMPEventArgs::setReplyTime(int index, int time)
int ICMPEventArgs::replyTime(int index) const
{
if (0 == _rtt.size())
if (0 == _rtt.size())
throw InvalidArgumentException("Supplied index exceeds array capacity.");
if (-1 == index) index = _sent - 1;
@@ -152,7 +152,7 @@ int ICMPEventArgs::replyTime(int index) const
int ICMPEventArgs::avgRTT() const
{
if (0 == _rtt.size()) return 0;
return (int) (std::accumulate(_rtt.begin(), _rtt.end(), 0) / _rtt.size());
}
+2 -2
View File
@@ -81,13 +81,13 @@ unsigned short ICMPPacketImpl::checksum(UInt16 *addr, Int32 len)
UInt16 answer;
Int32 sum = 0;
while (nleft > 1)
while (nleft > 1)
{
sum += *w++;
nleft -= sizeof(UInt16);
}
if (nleft == 1)
if (nleft == 1)
{
UInt16 u = 0;
*(UInt8*) (&u) = *(UInt8*) w;
+3 -3
View File
@@ -25,13 +25,13 @@ namespace Poco {
namespace Net {
ICMPSocket::ICMPSocket(IPAddress::Family family, int dataSize, int ttl, int timeout):
ICMPSocket::ICMPSocket(IPAddress::Family family, int dataSize, int ttl, int timeout):
Socket(new ICMPSocketImpl(family, dataSize, ttl, timeout))
{
}
ICMPSocket::ICMPSocket(const Socket& socket):
ICMPSocket::ICMPSocket(const Socket& socket):
Socket(socket)
{
if (!dynamic_cast<ICMPSocketImpl*>(impl()))
@@ -39,7 +39,7 @@ ICMPSocket::ICMPSocket(const Socket& socket):
}
ICMPSocket::ICMPSocket(SocketImpl* pImpl):
ICMPSocket::ICMPSocket(SocketImpl* pImpl):
Socket(pImpl)
{
if (!dynamic_cast<ICMPSocketImpl*>(impl()))
+8 -7
View File
@@ -66,7 +66,7 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
{
int maxPacketSize = _icmpPacket.maxPacketSize();
Poco::Buffer<unsigned char> buffer(maxPacketSize);
int expected = _icmpPacket.packetSize();
int leftover = _icmpPacket.packetSize();
int type = 0, code = 0;
try
@@ -83,8 +83,8 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
if (rc == 0) break;
if (respAddr == address)
{
expected -= rc;
if (expected <= 0)
leftover -= rc;
if (leftover <= 0)
{
if (_icmpPacket.validReplyID(buffer.begin(), maxPacketSize)) break;
std::string err = _icmpPacket.errorDescription(buffer.begin(), maxPacketSize, type, code);
@@ -95,7 +95,7 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
}
else continue;
}
while (expected > 0 && !_icmpPacket.validReplyID(buffer.begin(), maxPacketSize));
while (leftover > 0 && !_icmpPacket.validReplyID(buffer.begin(), maxPacketSize));
}
catch (ICMPException&)
{
@@ -113,10 +113,11 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
else throw;
}
if (expected > 0)
if (leftover > 0)
{
throw ICMPException(Poco::format("No response: expected %d, received: %d", _icmpPacket.packetSize(),
_icmpPacket.packetSize() - expected));
std::string err = leftover < _icmpPacket.packetSize() ? "Incomplete" : "No";
throw ICMPException(Poco::format("%s response: expected %d, received: %d", err, _icmpPacket.packetSize(),
_icmpPacket.packetSize() - leftover));
}
struct timeval then = _icmpPacket.time(buffer.begin(), maxPacketSize);
+109 -7
View File
@@ -19,6 +19,7 @@
#include "Poco/BinaryReader.h"
#include "Poco/BinaryWriter.h"
#include "Poco/String.h"
#include "Poco/Format.h"
#include "Poco/Types.h"
@@ -69,6 +70,11 @@ IPAddress::IPAddress(const IPAddress& addr)
}
IPAddress::IPAddress(IPAddress&& addr): _pImpl(std::move(addr._pImpl))
{
}
IPAddress::IPAddress(Family family)
{
if (family == IPv4)
@@ -99,7 +105,7 @@ IPAddress::IPAddress(const std::string& addr)
#if defined(POCO_HAVE_IPv6)
IPv6AddressImpl empty6 = IPv6AddressImpl();
if (addr.empty() || trim(addr) == "::")
if (addr.empty() || trimIPv6(addr) == "::")
{
newIPv6(empty6.addr());
return;
@@ -230,13 +236,20 @@ IPAddress& IPAddress::operator = (const IPAddress& addr)
else if (addr.family() == IPAddress::IPv6)
newIPv6(addr.addr(), addr.scope());
#endif
else
else
throw Poco::InvalidArgumentException("Invalid or unsupported address family");
}
return *this;
}
IPAddress& IPAddress::operator = (IPAddress&& addr)
{
_pImpl = std::move(addr._pImpl);
return *this;
}
IPAddress::Family IPAddress::family() const
{
return pImpl()->family();
@@ -248,7 +261,7 @@ Poco::UInt32 IPAddress::scope() const
return pImpl()->scope();
}
std::string IPAddress::toString() const
{
return pImpl()->toString();
@@ -278,13 +291,13 @@ bool IPAddress::isMulticast() const
return pImpl()->isMulticast();
}
bool IPAddress::isUnicast() const
{
return !isWildcard() && !isBroadcast() && !isMulticast();
}
bool IPAddress::isLinkLocal() const
{
return pImpl()->isLinkLocal();
@@ -500,7 +513,7 @@ poco_socklen_t IPAddress::length() const
return pImpl()->length();
}
const void* IPAddress::addr() const
{
return pImpl()->addr();
@@ -519,6 +532,47 @@ unsigned IPAddress::prefixLength() const
}
std::string& IPAddress::compressV6(std::string& v6addr)
{
// get rid of leading zeros at the beginning
while (v6addr.size() && v6addr[0] == '0') v6addr.erase(v6addr.begin());
// get rid of leading zeros in the middle
while (v6addr.find(":0") != std::string::npos)
Poco::replaceInPlace(v6addr, ":0", ":");
// get rid of extraneous colons
while (v6addr.find(":::") != std::string::npos)
Poco::replaceInPlace(v6addr, ":::", "::");
return v6addr;
}
std::string IPAddress::trimIPv6(const std::string v6Addr)
{
std::string v6addr(v6Addr);
std::string::size_type len = v6addr.length();
int dblColOcc = 0;
auto pos = v6addr.find("::");
while ((pos <= len-2) && (pos != std::string::npos))
{
++dblColOcc;
pos = v6addr.find("::", pos + 2);
}
if ((dblColOcc > 1) ||
(std::count(v6addr.begin(), v6addr.end(), ':') > 8) ||
(v6addr.find(":::") != std::string::npos) ||
((len >= 2) && ((v6addr[len-1] == ':') && v6addr[len-2] != ':')))
{
return v6addr;
}
return compressV6(v6addr);
}
IPAddress IPAddress::parse(const std::string& addr)
{
return IPAddress(addr);
@@ -535,7 +589,7 @@ bool IPAddress::tryParse(const std::string& addr, IPAddress& result)
}
#if defined(POCO_HAVE_IPv6)
IPv6AddressImpl impl6(IPv6AddressImpl::parse(addr));
if (impl6 != IPv6AddressImpl())
if (impl6 != IPv6AddressImpl() || trimIPv6(addr) == "::")
{
result.newIPv6(impl6.addr(), impl6.scope());
return true;
@@ -572,6 +626,54 @@ IPAddress IPAddress::broadcast()
}
IPAddress::RawIPv4 IPAddress::toV4Bytes() const
{
if (family() != IPv4)
throw Poco::InvalidAccessException(Poco::format("IPAddress::toV4Bytes(%d)", (int)family()));
RawIPv4 bytes;
std::memcpy(&bytes[0], addr(), IPv4Size);
return bytes;
}
IPAddress::RawIPv6 IPAddress::toV6Bytes() const
{
if (family() != IPv6)
throw Poco::InvalidAccessException(Poco::format("IPAddress::toV6Bytes(%d)", (int)family()));
RawIPv6 bytes;
std::memcpy(&bytes[0], addr(), IPv6Size);
return bytes;
}
std::vector<unsigned char> IPAddress::toBytes() const
{
std::size_t sz = 0;
std::vector<unsigned char> bytes;
const void* ptr = 0;
switch (family())
{
case IPv4:
sz = sizeof(in_addr);
ptr = addr();
break;
#if defined(POCO_HAVE_IPv6)
case IPv6:
sz = sizeof(in6_addr);
ptr = addr();
break;
#endif
default:
throw Poco::IllegalStateException(Poco::format("IPAddress::toBytes(%d)", (int)family()));
}
bytes.resize(sz);
std::memcpy(&bytes[0], ptr, sz);
return bytes;
}
} } // namespace Poco::Net
+14 -11
View File
@@ -40,8 +40,8 @@ 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
/// 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;
@@ -261,7 +261,7 @@ bool IPv4AddressImpl::isGlobalMC() const
IPv4AddressImpl IPv4AddressImpl::parse(const std::string& addr)
{
if (addr.empty()) return IPv4AddressImpl();
#if defined(_WIN32)
#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")
@@ -290,7 +290,7 @@ IPv4AddressImpl IPv4AddressImpl::parse(const std::string& addr)
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;
}
@@ -394,7 +394,7 @@ IPv6AddressImpl::IPv6AddressImpl(unsigned prefix):
{
unsigned i = 0;
#ifdef POCO_OS_FAMILY_WINDOWS
for (; prefix >= 16; ++i, prefix -= 16)
for (; prefix >= 16; ++i, prefix -= 16)
{
_addr.s6_addr16[i] = 0xffff;
}
@@ -407,7 +407,7 @@ IPv6AddressImpl::IPv6AddressImpl(unsigned prefix):
_addr.s6_addr16[i++] = 0;
}
#else
for (; prefix >= 32; ++i, prefix -= 32)
for (; prefix >= 32; ++i, prefix -= 32)
{
_addr.s6_addr32[i] = 0xffffffff;
}
@@ -551,7 +551,7 @@ Poco::UInt32 IPv6AddressImpl::scope() const
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 &&
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;
}
@@ -564,8 +564,11 @@ bool IPv6AddressImpl::isBroadcast() const
bool IPv6AddressImpl::isLoopback() const
{
if (isIPv4Mapped())
return (ByteOrder::fromNetwork(_addr.s6_addr[6]) & 0xFF000000) == 0x7F000000;
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
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;
}
@@ -729,9 +732,9 @@ IPv6AddressImpl IPv6AddressImpl::operator & (const IPv6AddressImpl& addr) const
IPv6AddressImpl IPv6AddressImpl::operator | (const IPv6AddressImpl& addr) const
{
if (_scope != addr._scope)
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];
@@ -756,7 +759,7 @@ 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
+27 -27
View File
@@ -52,7 +52,7 @@ namespace Net {
namespace
{
class MultiPartHandler: public PartHandler
/// This is a default part handler for multipart messages, used when there
/// 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.
{
@@ -65,14 +65,14 @@ namespace
/// 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,
/// 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.
{
@@ -97,7 +97,7 @@ namespace
std::string filename;
if (!contentDisp.empty())
filename = getParamFromHeader(contentDisp, "filename");
if (filename.empty())
if (filename.empty())
filename = getParamFromHeader(contentType, "name");
PartSource* pPS = _pMsg->createPartStore(tmp, contentType, filename);
poco_check_ptr (pPS);
@@ -108,13 +108,13 @@ namespace
{
if (!added && MailMessage::HEADER_CONTENT_DISPOSITION == it->first)
{
if (it->second == "inline")
if (it->second == "inline")
_pMsg->addContent(pPS, cte);
else
else
_pMsg->addAttachment("", pPS, cte);
added = true;
}
pPS->headers().set(it->first, it->second);
}
@@ -127,7 +127,7 @@ namespace
if (!added) delete pPS;
}
}
private:
std::string getParamFromHeader(const std::string& header, const std::string& param)
{
@@ -159,12 +159,12 @@ namespace
/// The content parameter represents the part content.
{
}
~StringPartHandler()
/// Destroys string part handler.
{
}
void handlePart(const MessageHeader& header, std::istream& stream)
/// Handles a part.
{
@@ -172,7 +172,7 @@ namespace
Poco::StreamCopier::copyToString(stream, tmp);
_str.append(tmp);
}
private:
std::string& _str;
};
@@ -198,7 +198,7 @@ const std::string MailMessage::CTE_QUOTED_PRINTABLE("quoted-printable");
const std::string MailMessage::CTE_BASE64("base64");
MailMessage::MailMessage(PartStoreFactory* pStoreFactory):
MailMessage::MailMessage(PartStoreFactory* pStoreFactory):
_encoding(),
_pStoreFactory(pStoreFactory)
{
@@ -216,7 +216,7 @@ MailMessage::~MailMessage()
}
}
void MailMessage::addRecipient(const MailRecipient& recipient)
{
_recipients.push_back(recipient);
@@ -234,7 +234,7 @@ void MailMessage::setSender(const std::string& sender)
set(HEADER_FROM, sender);
}
const std::string& MailMessage::getSender() const
{
if (has(HEADER_FROM))
@@ -243,13 +243,13 @@ const std::string& MailMessage::getSender() const
return EMPTY_HEADER;
}
void MailMessage::setSubject(const std::string& subject)
{
set(HEADER_SUBJECT, subject);
}
const std::string& MailMessage::getSubject() const
{
if (has(HEADER_SUBJECT))
@@ -272,13 +272,13 @@ 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))
@@ -293,7 +293,7 @@ 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);
@@ -301,7 +301,7 @@ Poco::Timestamp MailMessage::getDate() const
return DateTimeParser::parse(dateTime, tzd).timestamp();
}
bool MailMessage::isMultipart() const
{
MediaType mediaType = getContentType();
@@ -328,7 +328,7 @@ void MailMessage::addContent(PartSource* pSource, ContentTransferEncoding encodi
addPart("", pSource, CONTENT_INLINE, encoding);
}
void MailMessage::addAttachment(const std::string& name, PartSource* pSource, ContentTransferEncoding encoding)
{
addPart(name, pSource, CONTENT_ATTACHMENT, encoding);
@@ -388,7 +388,7 @@ void MailMessage::makeMultipart()
if (!isMultipart())
{
MediaType mediaType("multipart", "mixed");
setContentType(mediaType);
setContentType(mediaType);
}
}
@@ -408,7 +408,7 @@ void MailMessage::writeMultipart(MessageHeader& header, std::ostream& ostr) cons
header.set(HEADER_CONTENT_TYPE, mediaType.toString());
header.set(HEADER_MIME_VERSION, "1.0");
writeHeader(header, ostr);
MultipartWriter writer(ostr, _boundary);
for (const auto& part: _parts)
{
@@ -542,7 +542,7 @@ void MailMessage::setRecipientHeaders(MessageHeader& headers) const
std::string to;
std::string cc;
std::string bcc;
for (const auto& rec: _recipients)
{
switch (rec.getType())
@@ -622,7 +622,7 @@ std::string MailMessage::encodeWord(const std::string& text, const std::string&
}
}
if (!containsNonASCII) return text;
std::string encodedText;
std::string::size_type lineLength = 0;
for (auto ch: text)
@@ -680,7 +680,7 @@ std::string MailMessage::encodeWord(const std::string& text, const std::string&
if (lineLength > 0)
{
encodedText += "?=";
}
}
return encodedText;
}
+7 -7
View File
@@ -25,7 +25,7 @@ MailRecipient::MailRecipient():
{
}
MailRecipient::MailRecipient(const MailRecipient& recipient):
_address(recipient._address),
_realName(recipient._realName),
@@ -33,7 +33,7 @@ MailRecipient::MailRecipient(const MailRecipient& recipient):
{
}
MailRecipient::MailRecipient(RecipientType type, const std::string& address):
_address(address),
_type(type)
@@ -53,7 +53,7 @@ MailRecipient::~MailRecipient()
{
}
MailRecipient& MailRecipient::operator = (const MailRecipient& recipient)
{
if (this != &recipient)
@@ -65,26 +65,26 @@ MailRecipient& MailRecipient::operator = (const MailRecipient& recipient)
}
void MailRecipient::swap(MailRecipient& recipient)
void MailRecipient::swap(MailRecipient& recipient) noexcept
{
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;
+7 -7
View File
@@ -20,7 +20,7 @@ namespace Net {
MailStreamBuf::MailStreamBuf(std::istream& istr):
_pIstr(&istr),
_pIstr(&istr),
_pOstr(0),
_state(ST_CR_LF)
{
@@ -28,7 +28,7 @@ MailStreamBuf::MailStreamBuf(std::istream& istr):
MailStreamBuf::MailStreamBuf(std::ostream& ostr):
_pIstr(0),
_pIstr(0),
_pOstr(&ostr),
_state(ST_CR_LF)
{
@@ -53,7 +53,7 @@ void MailStreamBuf::close()
}
}
int MailStreamBuf::readFromDevice()
{
int c = std::char_traits<char>::eof();
@@ -194,8 +194,8 @@ MailStreamBuf* MailIOS::rdbuf()
}
MailInputStream::MailInputStream(std::istream& istr):
MailIOS(istr),
MailInputStream::MailInputStream(std::istream& istr):
MailIOS(istr),
std::istream(&_buf)
{
}
@@ -206,8 +206,8 @@ MailInputStream::~MailInputStream()
}
MailOutputStream::MailOutputStream(std::ostream& ostr):
MailIOS(ostr),
MailOutputStream::MailOutputStream(std::ostream& ostr):
MailIOS(ostr),
std::ostream(&_buf)
{
}
+1 -1
View File
@@ -89,7 +89,7 @@ MediaType& MediaType::operator = (const std::string& mediaType)
}
void MediaType::swap(MediaType& mediaType)
void MediaType::swap(MediaType& mediaType) noexcept
{
std::swap(_type, mediaType._type);
std::swap(_subType, mediaType._subType);
+53 -22
View File
@@ -28,14 +28,18 @@ namespace Net {
MessageHeader::MessageHeader():
_fieldLimit(DFL_FIELD_LIMIT)
_fieldLimit(DFL_FIELD_LIMIT),
_nameLengthLimit(DFL_NAME_LENGTH_LIMIT),
_valueLengthLimit(DFL_VALUE_LENGTH_LIMIT)
{
}
MessageHeader::MessageHeader(const MessageHeader& messageHeader):
NameValueCollection(messageHeader),
_fieldLimit(DFL_FIELD_LIMIT)
_fieldLimit(DFL_FIELD_LIMIT),
_nameLengthLimit(DFL_NAME_LENGTH_LIMIT),
_valueLengthLimit(DFL_VALUE_LENGTH_LIMIT)
{
}
@@ -80,12 +84,12 @@ void MessageHeader::read(std::istream& istr)
throw MessageException("Too many header fields");
name.clear();
value.clear();
while (ch != eof && ch != ':' && ch != '\n' && name.length() < MAX_NAME_LENGTH) { name += ch; ch = buf.sbumpc(); }
while (ch != eof && ch != ':' && ch != '\n' && name.length() < _nameLengthLimit) { name += 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 += ch; ch = buf.sbumpc(); }
while (ch != eof && ch != '\r' && ch != '\n' && value.length() < _valueLengthLimit) { value += ch; ch = buf.sbumpc(); }
if (ch == '\r') ch = buf.sbumpc();
if (ch == '\n')
ch = buf.sbumpc();
@@ -93,7 +97,7 @@ void MessageHeader::read(std::istream& istr)
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 += ch; ch = buf.sbumpc(); }
while (ch != eof && ch != '\r' && ch != '\n' && value.length() < _valueLengthLimit) { value += ch; ch = buf.sbumpc(); }
if (ch == '\r') ch = buf.sbumpc();
if (ch == '\n')
ch = buf.sbumpc();
@@ -104,7 +108,8 @@ void MessageHeader::read(std::istream& istr)
add(name, decodeWord(value));
++fields;
}
istr.putback(ch);
if (istr.good() && ch != eof)
istr.putback(ch);
}
@@ -113,15 +118,41 @@ int MessageHeader::getFieldLimit() const
return _fieldLimit;
}
void MessageHeader::setFieldLimit(int limit)
{
poco_assert (limit >= 0);
_fieldLimit = limit;
}
int MessageHeader::getNameLengthLimit() const
{
return _nameLengthLimit;
}
void MessageHeader::setNameLengthLimit(int limit)
{
poco_assert(limit >= 0);
_nameLengthLimit = limit;
}
int MessageHeader::getValueLengthLimit() const
{
return _valueLengthLimit;
}
void MessageHeader::setValueLengthLimit(int limit)
{
poco_assert(limit >= 0);
_valueLengthLimit = limit;
}
bool MessageHeader::hasToken(const std::string& fieldName, const std::string& token) const
{
std::string field = get(fieldName, "");
@@ -257,7 +288,7 @@ void MessageHeader::quote(const std::string& value, std::string& result, bool al
}
void MessageHeader::decodeRFC2047(const std::string& ins, std::string& outs, const std::string& charset_to)
void MessageHeader::decodeRFC2047(const std::string& ins, std::string& outs, const std::string& charset_to)
{
std::string tempout;
StringTokenizer tokens(ins, "?");
@@ -268,18 +299,18 @@ void MessageHeader::decodeRFC2047(const std::string& ins, std::string& outs, con
std::istringstream istr(text);
if (encoding == "B")
if (encoding == "B")
{
// Base64 encoding.
Base64Decoder decoder(istr);
for (char c; decoder.get(c); tempout += c) {}
}
else if (encoding == "Q")
else if (encoding == "Q")
{
// Quoted encoding.
for (char c; istr.get(c);)
// Quoted encoding.
for (char c; istr.get(c);)
{
if (c == '_')
if (c == '_')
{
//RFC 2047 _ is a space.
tempout += " ";
@@ -287,11 +318,11 @@ void MessageHeader::decodeRFC2047(const std::string& ins, std::string& outs, con
}
// FIXME: check that we have enought chars-
if (c == '=')
if (c == '=')
{
// The next two chars are hex representation of the complete byte.
std::string hex;
for (int i = 0; i < 2; i++)
for (int i = 0; i < 2; i++)
{
istr.get(c);
hex += c;
@@ -303,7 +334,7 @@ void MessageHeader::decodeRFC2047(const std::string& ins, std::string& outs, con
tempout += c;
}
}
else
else
{
// Wrong encoding
outs = ins;
@@ -311,22 +342,22 @@ void MessageHeader::decodeRFC2047(const std::string& ins, std::string& outs, con
}
// convert to the right charset.
if (charset != charset_to)
if (charset != charset_to)
{
try
try
{
TextEncoding& enc = TextEncoding::byName(charset);
TextEncoding& dec = TextEncoding::byName(charset_to);
TextConverter converter(enc, dec);
converter.convert(tempout, outs);
}
catch (...)
catch (...)
{
// FIXME: Unsuported encoding...
outs = tempout;
}
}
else
else
{
// Not conversion necesary.
outs = tempout;
@@ -339,7 +370,7 @@ std::string MessageHeader::decodeWord(const std::string& text, const std::string
std::string outs, tmp = text;
do {
std::string tmp2;
// find the begining of the next rfc2047 chunk
// find the begining of the next rfc2047 chunk
size_t pos = tmp.find("=?");
if (pos == std::string::npos) {
// No more found, return
+12 -13
View File
@@ -24,10 +24,10 @@
#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
// _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 ip_mreq
{
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
@@ -97,7 +97,7 @@ void MulticastSocket::setInterface(const NetworkInterface& interfc)
else throw UnsupportedFamilyException("Unknown or unsupported socket family.");
}
NetworkInterface MulticastSocket::getInterface() const
{
try
@@ -118,7 +118,7 @@ NetworkInterface MulticastSocket::getInterface() const
}
}
void MulticastSocket::setLoopback(bool flag)
{
if (address().af() == AF_INET)
@@ -135,7 +135,7 @@ void MulticastSocket::setLoopback(bool flag)
}
}
bool MulticastSocket::getLoopback() const
{
bool flag = false;
@@ -156,7 +156,7 @@ bool MulticastSocket::getLoopback() const
return flag;
}
void MulticastSocket::setTimeToLive(unsigned value)
{
if (address().af() == AF_INET)
@@ -172,7 +172,7 @@ void MulticastSocket::setTimeToLive(unsigned value)
}
}
unsigned MulticastSocket::getTimeToLive() const
{
unsigned ttl(0);
@@ -191,13 +191,13 @@ unsigned MulticastSocket::getTimeToLive() const
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)
@@ -254,14 +254,13 @@ NetworkInterface MulticastSocket::findFirstInterface(const IPAddress& groupAddre
throw NotFoundException("No multicast-eligible network interface found.");
}
void MulticastSocket::leaveGroup(const IPAddress& groupAddress)
{
NetworkInterface intf;
leaveGroup(groupAddress, intf);
leaveGroup(groupAddress, findFirstInterface(groupAddress));
}
void MulticastSocket::leaveGroup(const IPAddress& groupAddress, const NetworkInterface& interfc)
{
if (groupAddress.af() == AF_INET)
+4 -3
View File
@@ -88,7 +88,7 @@ int MultipartStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
buf.sbumpc(); // '\n'
}
return 0;
return 0;
}
else if (ch == '-' && buf.sgetc() == '-')
{
@@ -105,6 +105,7 @@ int MultipartStreamBuf::readFromDevice(char* buffer, std::streamsize length)
*buffer++ = (char) buf.sbumpc(); ++n;
ch = buf.sgetc();
}
if (ch == eof) _lastPart = true;
return n;
}
@@ -218,11 +219,11 @@ bool MultipartReader::hasNextPart()
return (!_pMPI || !_pMPI->lastPart()) && _istr.good();
}
std::istream& MultipartReader::stream() const
{
poco_check_ptr (_pMPI);
return *_pMPI;
}
+1 -1
View File
@@ -26,7 +26,7 @@ namespace Poco {
namespace Net {
NTPClient::NTPClient(IPAddress::Family family, int timeout):
NTPClient::NTPClient(IPAddress::Family family, int timeout):
_family(family), _timeout(timeout)
{
}
+2 -2
View File
@@ -46,10 +46,10 @@ std::string NTPEventArgs::hostName() const
{
return DNS::resolve(_address.host().toString()).name();
}
catch (HostNotFoundException&)
catch (HostNotFoundException&)
{
}
catch (NoAddressFoundException&)
catch (NoAddressFoundException&)
{
}
catch (DNSException&)
+5 -4
View File
@@ -27,7 +27,7 @@ namespace Net {
#else
#pragma pack(1)
#endif
struct NTPPacketData
struct NTPPacketData
{
Poco::Int8 mode:3;
Poco::Int8 vn:3;
@@ -149,9 +149,10 @@ Poco::Timestamp NTPPacket::transmitTime() const
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);
Poco::UInt64 ntpTime = Poco::ByteOrder::toLittleEndian(tm);
Poco::UInt64 secs = ((ntpTime >> 32) - seventyYears) * 1000000;
Poco::UInt64 frac = ((ntpTime & 0xFFFFFFFF) * 1000000) >> 32;
return Poco::Timestamp(secs+frac);
}
+9 -9
View File
@@ -63,12 +63,12 @@ NameValueCollection& NameValueCollection::operator = (NameValueCollection&& nvc)
}
void NameValueCollection::swap(NameValueCollection& nvc)
void NameValueCollection::swap(NameValueCollection& nvc) noexcept
{
std::swap(_map, nvc._map);
}
const std::string& NameValueCollection::operator [] (const std::string& name) const
{
ConstIterator it = _map.find(name);
@@ -78,8 +78,8 @@ const std::string& NameValueCollection::operator [] (const std::string& name) co
throw NotFoundException(name);
}
void NameValueCollection::set(const std::string& name, const std::string& value)
void NameValueCollection::set(const std::string& name, const std::string& value)
{
Iterator it = _map.find(name);
if (it != _map.end())
@@ -88,13 +88,13 @@ void NameValueCollection::set(const std::string& name, const std::string& value)
_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);
@@ -126,19 +126,19 @@ NameValueCollection::ConstIterator NameValueCollection::find(const std::string&
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();
+1 -1
View File
@@ -637,7 +637,7 @@ NetworkInterface& NetworkInterface::operator = (const NetworkInterface& interfc)
}
void NetworkInterface::swap(NetworkInterface& other)
void NetworkInterface::swap(NetworkInterface& other) noexcept
{
using std::swap;
swap(_pImpl, other._pImpl);
+15 -15
View File
@@ -128,7 +128,7 @@ void OAuth10Credentials::authenticate(HTTPRequest& request, const Poco::URI& uri
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)
@@ -165,27 +165,27 @@ bool OAuth10Credentials::verify(const HTTPRequest& request, const Poco::URI& uri
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);
@@ -205,8 +205,8 @@ bool OAuth10Credentials::verify(const HTTPRequest& request, const Poco::URI& uri
refSignature = createSignature(request, uriWithoutQuery.toString(), params, nonce, timestamp);
}
else throw NotAuthenticatedException("Unsupported OAuth signature method", method);
return refSignature == signature;
return refSignature == signature;
}
else throw NotAuthenticatedException("No OAuth credentials found in Authorization header");
}
@@ -226,7 +226,7 @@ void OAuth10Credentials::signPlaintext(Poco::Net::HTTPRequest& request) const
std::string signature(percentEncode(_consumerSecret));
signature += '&';
signature += percentEncode(_tokenSecret);
std::string authorization(SCHEME);
if (!_realm.empty())
{
@@ -322,7 +322,7 @@ std::string OAuth10Credentials::createSignature(const Poco::Net::HTTPRequest& re
{
paramsMap[percentEncode(p.first)] = percentEncode(p.second);
}
std::string paramsString;
for (auto it = paramsMap.begin(); it != paramsMap.end(); ++it)
{
@@ -331,18 +331,18 @@ std::string OAuth10Credentials::createSignature(const Poco::Net::HTTPRequest& re
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();
+1 -1
View File
@@ -75,7 +75,7 @@ void OAuth20Credentials::setScheme(const std::string& scheme)
_scheme = scheme;
}
void OAuth20Credentials::authenticate(HTTPRequest& request)
{
std::string auth(_scheme);
+8 -8
View File
@@ -39,17 +39,17 @@ public:
_socket(socket)
{
}
~DialogStreamBuf()
{
}
private:
int readFromDevice()
{
return _socket.get();
}
DialogSocket& _socket;
};
@@ -62,11 +62,11 @@ public:
{
poco_ios_init(&_buf);
}
~DialogIOS()
{
}
DialogStreamBuf* rdbuf()
{
return &_buf;
@@ -85,7 +85,7 @@ public:
std::istream(&_buf)
{
}
~DialogInputStream()
{
}
@@ -99,7 +99,7 @@ POP3ClientSession::POP3ClientSession(const StreamSocket& socket):
}
POP3ClientSession::POP3ClientSession(const std::string& host, Poco::UInt16 port):
POP3ClientSession::POP3ClientSession(const std::string& host, Poco::UInt16 port):
_socket(SocketAddress(host, port)),
_isOpen(true)
{
@@ -123,7 +123,7 @@ void POP3ClientSession::setTimeout(const Poco::Timespan& timeout)
_socket.setReceiveTimeout(timeout);
}
Poco::Timespan POP3ClientSession::getTimeout() const
{
return _socket.getReceiveTimeout();
+1 -1
View File
@@ -27,7 +27,7 @@ PartSource::PartSource():
{
}
PartSource::PartSource(const std::string& mediaType):
_mediaType(mediaType)
{
+298 -179
View File
@@ -18,23 +18,20 @@
#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>
#ifdef POCO_OS_FAMILY_WINDOWS
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/SocketAddress.h"
#include "wepoll.h"
#else
#include <sys/epoll.h>
#include <sys/eventfd.h>
#endif
#elif defined(POCO_HAVE_FD_POLL)
#ifndef _WIN32
#include <poll.h>
#endif
#ifndef _WIN32
#include <poll.h>
#include "Poco/Pipe.h"
#endif
#endif
@@ -44,19 +41,44 @@ namespace Net {
#if defined(POCO_HAVE_FD_EPOLL)
//
// Implementation using epoll (Linux) or wepoll (Windows)
//
#ifdef WEPOLL_H_
namespace {
int close(HANDLE h)
{
return epoll_close(h);
}
}
#endif // WEPOLL_H_
//
// Linux implementation using epoll
//
class PollSetImpl
{
public:
PollSetImpl():
_epollfd(-1),
_events(1024)
using Mutex = Poco::FastMutex;
using ScopedLock = Mutex::ScopedLock;
using SocketMode = std::pair<Socket, int>;
using SocketMap = std::map<void*, SocketMode>;
PollSetImpl(): _events(1024),
_port(0),
_eventfd(eventfd(_port, 0)),
_epollfd(epoll_create(1))
{
_epollfd = epoll_create(1);
if (_epollfd < 0)
int err = addFD(_eventfd, PollSet::POLL_READ, EPOLL_CTL_ADD);
#ifdef WEPOLL_H_
if ((err) || !_epollfd)
#else
if ((err) || (_epollfd < 0))
#endif
{
SocketImpl::error();
}
@@ -64,69 +86,204 @@ public:
~PollSetImpl()
{
if (_epollfd >= 0)
::close(_epollfd);
#ifdef WEPOLL_H_
if (_eventfd >= 0) eventfd(_port, _eventfd);
if (_epollfd) close(_epollfd);
#else
if (_eventfd > 0) close(_eventfd.exchange(0));
if (_epollfd >= 0) close(_epollfd);
#endif
}
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);
int newMode = getNewMode(socket.impl(), mode);
int err = addImpl(socket, newMode);
if (err)
{
if (errno == EEXIST) update(socket, mode);
if (errno == EEXIST) update(socket, newMode);
else SocketImpl::error();
}
}
if (_socketMap.find(sockImpl) == _socketMap.end())
_socketMap[sockImpl] = socket;
void update(const Socket& socket, int mode)
{
int err = updateImpl(socket, mode);
if (err) SocketImpl::error();
}
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();
ScopedLock lock(_mutex);
_socketMap.erase(socket.impl());
}
bool has(const Socket& socket) const
{
Poco::FastMutex::ScopedLock lock(_mutex);
SocketImpl* sockImpl = socket.impl();
ScopedLock lock(_mutex);
return sockImpl &&
(_socketMap.find(sockImpl) != _socketMap.end());
}
bool empty() const
{
Poco::FastMutex::ScopedLock lock(_mutex);
ScopedLock lock(_mutex);
return _socketMap.empty();
}
void update(const Socket& socket, int mode)
void clear()
{
poco_socket_t fd = socket.impl()->sockfd();
struct epoll_event ev;
{
ScopedLock lock(_mutex);
close(_epollfd);
_socketMap.clear();
_epollfd = epoll_create(1);
#ifdef WEPOLL_H_
if (!_epollfd) SocketImpl::error();
#else
if (_epollfd < 0) SocketImpl::error();
#endif
}
#ifdef WEPOLL_H_
eventfd(_port, _eventfd);
_eventfd = eventfd(_port);
#else
close(_eventfd.exchange(0));
_eventfd = eventfd(0, 0);
#endif
addFD(_eventfd, PollSet::POLL_READ, EPOLL_CTL_ADD);
}
PollSet::SocketModeMap poll(const Poco::Timespan& timeout)
{
PollSet::SocketModeMap result;
Poco::Timespan remainingTime(timeout);
int rc;
ScopedLock lock(_mutex);
do
{
Poco::Timestamp start;
rc = epoll_wait(_epollfd, &_events[0],
static_cast<int>(_events.size()), static_cast<int>(remainingTime.totalMilliseconds()));
if (rc == 0) return result;
// if we are hitting the events limit, resize it; even without resizing, the subseqent
// calls would round-robin through the remaining ready sockets, but it's better to give
// the call enough room once we start hitting the boundary
if (rc >= _events.size()) _events.resize(_events.size()*2);
else if (rc < 0)
{
// if interrupted and there's still time left, keep waiting
if (SocketImpl::lastError() == POCO_EINTR)
{
Poco::Timestamp end;
Poco::Timespan waited = end - start;
if (waited < remainingTime)
{
remainingTime -= waited;
continue;
}
}
else SocketImpl::error();
}
}
while (false);
for (int i = 0; i < rc; i++)
{
if (_events[i].data.ptr) // skip eventfd
{
SocketMap::iterator it = _socketMap.find(_events[i].data.ptr);
if (it != _socketMap.end())
{
if (_events[i].events & EPOLLIN)
result[it->second.first] |= PollSet::POLL_READ;
if (_events[i].events & EPOLLOUT)
result[it->second.first] |= PollSet::POLL_WRITE;
if (_events[i].events & EPOLLERR)
result[it->second.first] |= PollSet::POLL_ERROR;
}
}
else if (_events[i].events & EPOLLIN) // eventfd signaled
{
uint64_t val;
#ifdef WEPOLL_H_
if (_pSocket && _pSocket->available())
_pSocket->impl()->receiveBytes(&val, sizeof(val));
#else
read(_eventfd, &val, sizeof(val));
#endif
}
}
return result;
}
void wakeUp()
{
#ifdef WEPOLL_H_
StreamSocket ss(SocketAddress("127.0.0.1", _port));
#else
uint64_t val = 1;
// This is guaranteed to write into a valid fd,
// or 0 (meaning PollSet is being destroyed).
// Errors are ignored.
write(_eventfd, &val, sizeof(val));
#endif
}
int count() const
{
ScopedLock lock(_mutex);
return static_cast<int>(_socketMap.size());
}
private:
int getNewMode(SocketImpl* sockImpl, int mode)
{
ScopedLock lock(_mutex);
auto it = _socketMap.find(sockImpl);
if (it != _socketMap.end())
mode |= it->second.second;
return mode;
}
void socketMapUpdate(const Socket& socket, int mode)
{
SocketImpl* sockImpl = socket.impl();
ScopedLock lock(_mutex);
_socketMap[sockImpl] = {socket, mode};
}
int updateImpl(const Socket& socket, int mode)
{
SocketImpl* sockImpl = socket.impl();
int ret = addFD(static_cast<int>(sockImpl->sockfd()), mode, EPOLL_CTL_MOD, sockImpl);
if (ret == 0) socketMapUpdate(socket, mode);
return ret;
}
int addImpl(const Socket& socket, int mode)
{
SocketImpl* sockImpl = socket.impl();
int newMode = getNewMode(sockImpl, mode);
int ret = addFD(static_cast<int>(sockImpl->sockfd()), newMode, EPOLL_CTL_ADD, sockImpl);
if (ret == 0) socketMapUpdate(socket, newMode);
return ret;
}
int addFD(int fd, int mode, int op, void* ptr = 0)
{
struct epoll_event ev{};
ev.events = 0;
if (mode & PollSet::POLL_READ)
ev.events |= EPOLLIN;
@@ -134,79 +291,43 @@ public:
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();
}
ev.data.ptr = ptr;
return epoll_ctl(_epollfd, op, fd, &ev);
}
void clear()
#ifdef WEPOLL_H_
int eventfd(int& port, int rmFD = 0)
{
Poco::FastMutex::ScopedLock lock(_mutex);
::close(_epollfd);
_socketMap.clear();
_epollfd = epoll_create(1);
if (_epollfd < 0)
if (rmFD == 0)
{
SocketImpl::error();
_pSocket = new ServerSocket(SocketAddress("127.0.0.1", 0));
_pSocket->setBlocking(false);
port = _pSocket->address().port();
return static_cast<int>(_pSocket->impl()->sockfd());
}
else
{
delete _pSocket;
_pSocket = 0;
port = 0;
}
return 0;
}
PollSet::SocketModeMap poll(const Poco::Timespan& timeout)
{
PollSet::SocketModeMap result;
#endif // WEPOLL_H_
{
Poco::FastMutex::ScopedLock lock(_mutex);
if(_socketMap.empty()) return result;
}
Poco::Timespan remainingTime(timeout);
int rc;
do
{
Poco::Timestamp start;
rc = epoll_wait(_epollfd, &_events[0], _events.size(), remainingTime.totalMilliseconds());
if (rc < 0 && 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:
mutable Poco::FastMutex _mutex;
int _epollfd;
std::map<void*, Socket> _socketMap;
mutable Mutex _mutex;
SocketMap _socketMap;
std::vector<struct epoll_event> _events;
int _port;
std::atomic<int> _eventfd;
#ifdef WEPOLL_H_
std::atomic <HANDLE> _epollfd;
ServerSocket* _pSocket;
#else
std::atomic<int> _epollfd;
#endif
};
@@ -219,12 +340,22 @@ private:
class PollSetImpl
{
public:
PollSetImpl()
{
pollfd fd{_pipe.readHandle(), POLLIN, 0};
_pollfds.push_back(fd);
}
~PollSetImpl()
{
_pipe.close();
}
void add(const Socket& socket, int mode)
{
Poco::FastMutex::ScopedLock lock(_mutex);
poco_socket_t fd = socket.impl()->sockfd();
_addMap[fd] = mode;
_addMap[fd] |= mode;
_removeSet.erase(fd);
_socketMap[fd] = socket;
}
@@ -232,7 +363,6 @@ public:
void remove(const Socket& socket)
{
Poco::FastMutex::ScopedLock lock(_mutex);
poco_socket_t fd = socket.impl()->sockfd();
_removeSet.insert(fd);
_addMap.erase(fd);
@@ -256,7 +386,6 @@ public:
void update(const Socket& socket, int mode)
{
Poco::FastMutex::ScopedLock lock(_mutex);
poco_socket_t fd = socket.impl()->sockfd();
for (auto it = _pollfds.begin(); it != _pollfds.end(); ++it)
{
@@ -264,7 +393,7 @@ public:
{
it->events = 0;
it->revents = 0;
setMode(it->fd, it->events, mode);
setMode(it->events, mode);
}
}
}
@@ -276,7 +405,7 @@ public:
_socketMap.clear();
_addMap.clear();
_removeSet.clear();
_pollfds.clear();
_pollfds.reserve(1);
}
PollSet::SocketModeMap poll(const Poco::Timespan& timeout)
@@ -305,7 +434,7 @@ public:
pfd.fd = it->first;
pfd.events = 0;
pfd.revents = 0;
setMode(pfd.fd, pfd.events, it->second);
setMode(pfd.events, it->second);
_pollfds.push_back(pfd);
}
_addMap.clear();
@@ -318,17 +447,7 @@ public:
do
{
Poco::Timestamp start;
#ifdef _WIN32
rc = WSAPoll(&_pollfds[0], static_cast<ULONG>(_pollfds.size()), static_cast<INT>(remainingTime.totalMilliseconds()));
// see https://github.com/pocoproject/poco/issues/3248
if ((remainingTime > 0) && (rc > 0) && !hasSignaledFDs())
{
rc = -1;
WSASetLastError(WSAEINTR);
}
#else
rc = ::poll(&_pollfds[0], _pollfds.size(), remainingTime.totalMilliseconds());
#endif
if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
{
Poco::Timestamp end;
@@ -343,28 +462,26 @@ public:
if (rc < 0) SocketImpl::error();
{
if (_pollfds[0].revents & POLLIN)
{
char c;
_pipe.readBytes(&c, 1);
}
Poco::FastMutex::ScopedLock lock(_mutex);
if (!_socketMap.empty())
{
for (auto it = _pollfds.begin(); it != _pollfds.end(); ++it)
for (auto it = _pollfds.begin() + 1; 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)
#ifdef _WIN32
|| (it->revents & POLLHUP)
#endif
)
if (it->revents & POLLIN)
result[its->second] |= PollSet::POLL_READ;
if ((it->revents & POLLOUT)
#ifdef _WIN32
&& (_wantPOLLOUT.find(it->fd) != _wantPOLLOUT.end())
#endif
)
if (it->revents & POLLOUT)
result[its->second] |= PollSet::POLL_WRITE;
if (it->revents & POLLERR)
if (it->revents & POLLERR || (it->revents & POLLHUP))
result[its->second] |= PollSet::POLL_ERROR;
}
it->revents = 0;
@@ -375,38 +492,21 @@ public:
return result;
}
void wakeUp()
{
char c = 1;
_pipe.writeBytes(&c, 1);
}
int count() const
{
Poco::FastMutex::ScopedLock lock(_mutex);
return static_cast<int>(_socketMap.size());
}
private:
#ifdef _WIN32
void setMode(poco_socket_t fd, short& target, int mode)
{
if (mode & PollSet::POLL_READ)
target |= POLLIN;
if (mode & PollSet::POLL_WRITE)
_wantPOLLOUT.insert(fd);
else
_wantPOLLOUT.erase(fd);
target |= POLLOUT;
}
bool hasSignaledFDs()
{
for (const auto& pollfd : _pollfds)
{
if ((pollfd.revents | POLLOUT) &&
(_wantPOLLOUT.find(pollfd.fd) != _wantPOLLOUT.end()))
{
return true;
}
}
return false;
}
#else
void setMode(poco_socket_t fd, short& target, int mode)
void setMode(short& target, int mode)
{
if (mode & PollSet::POLL_READ)
target |= POLLIN;
@@ -415,16 +515,12 @@ private:
target |= POLLOUT;
}
#endif
mutable Poco::FastMutex _mutex;
std::map<poco_socket_t, Socket> _socketMap;
#ifdef _WIN32
std::set<poco_socket_t> _wantPOLLOUT;
#endif
std::map<poco_socket_t, int> _addMap;
std::set<poco_socket_t> _removeSet;
std::vector<pollfd> _pollfds;
Poco::Pipe _pipe;
};
@@ -562,6 +658,17 @@ public:
return result;
}
void wakeUp()
{
// TODO
}
int count() const
{
Poco::FastMutex::ScopedLock lock(_mutex);
return static_cast<int>(_map.size());
}
private:
mutable Poco::FastMutex _mutex;
PollSet::SocketModeMap _map;
@@ -625,4 +732,16 @@ PollSet::SocketModeMap PollSet::poll(const Poco::Timespan& timeout)
}
int PollSet::count() const
{
return _pImpl->count();
}
void PollSet::wakeUp()
{
_pImpl->wakeUp();
}
} } // namespace Poco::Net
+3 -3
View File
@@ -27,7 +27,7 @@ namespace Poco {
namespace Net {
QuotedPrintableDecoderBuf::QuotedPrintableDecoderBuf(std::istream& istr):
QuotedPrintableDecoderBuf::QuotedPrintableDecoderBuf(std::istream& istr):
_buf(*istr.rdbuf())
{
}
@@ -87,8 +87,8 @@ QuotedPrintableDecoderBuf* QuotedPrintableDecoderIOS::rdbuf()
}
QuotedPrintableDecoder::QuotedPrintableDecoder(std::istream& istr):
QuotedPrintableDecoderIOS(istr),
QuotedPrintableDecoder::QuotedPrintableDecoder(std::istream& istr):
QuotedPrintableDecoderIOS(istr),
std::istream(&_buf)
{
}
+3 -3
View File
@@ -24,7 +24,7 @@ namespace Poco {
namespace Net {
QuotedPrintableEncoderBuf::QuotedPrintableEncoderBuf(std::ostream& ostr):
QuotedPrintableEncoderBuf::QuotedPrintableEncoderBuf(std::ostream& ostr):
_pending(-1),
_lineLength(0),
_ostr(ostr)
@@ -135,8 +135,8 @@ QuotedPrintableEncoderBuf* QuotedPrintableEncoderIOS::rdbuf()
}
QuotedPrintableEncoder::QuotedPrintableEncoder(std::ostream& ostr):
QuotedPrintableEncoderIOS(ostr),
QuotedPrintableEncoder::QuotedPrintableEncoder(std::ostream& ostr):
QuotedPrintableEncoderIOS(ostr),
std::ostream(&_buf)
{
}
+45 -3
View File
@@ -24,19 +24,19 @@ namespace Poco {
namespace Net {
RawSocket::RawSocket():
RawSocket::RawSocket():
Socket(new RawSocketImpl)
{
}
RawSocket::RawSocket(SocketAddress::Family family, int proto):
RawSocket::RawSocket(SocketAddress::Family family, int proto):
Socket(new RawSocketImpl(family, proto))
{
}
RawSocket::RawSocket(const SocketAddress& address, bool reuseAddress):
RawSocket::RawSocket(const SocketAddress& address, bool reuseAddress):
Socket(new RawSocketImpl(address.family()))
{
bind(address, reuseAddress);
@@ -50,6 +50,18 @@ RawSocket::RawSocket(const Socket& socket): Socket(socket)
}
RawSocket::RawSocket(const RawSocket& socket): Socket(socket)
{
}
#ifdef POCO_NEW_STATE_ON_MOVE
RawSocket::RawSocket(RawSocket&& socket): Socket(std::move(socket))
{
}
#endif // POCO_NEW_STATE_ON_MOVE
RawSocket::RawSocket(SocketImpl* pImpl): Socket(pImpl)
{
if (!dynamic_cast<RawSocketImpl*>(impl()))
@@ -72,6 +84,36 @@ RawSocket& RawSocket::operator = (const Socket& socket)
}
#ifdef POCO_NEW_STATE_ON_MOVE
RawSocket& RawSocket::operator = (Socket&& socket)
{
if (dynamic_cast<RawSocketImpl*>(socket.impl()))
Socket::operator = (std::move(socket));
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
#endif // POCO_NEW_STATE_ON_MOVE
RawSocket& RawSocket::operator = (const RawSocket& socket)
{
Socket::operator = (socket);
return *this;
}
#ifdef POCO_NEW_STATE_ON_MOVE
RawSocket& RawSocket::operator = (RawSocket&& socket)
{
Socket::operator = (std::move(socket));
return *this;
}
#endif // POCO_NEW_STATE_ON_MOVE
void RawSocket::connect(const SocketAddress& address)
{
impl()->connect(address);
+2 -2
View File
@@ -41,8 +41,8 @@ RawSocketImpl::RawSocketImpl(SocketAddress::Family family, int proto)
}
RawSocketImpl::RawSocketImpl(poco_socket_t sockfd):
RawSocketImpl::RawSocketImpl(poco_socket_t sockfd):
SocketImpl(sockfd)
{
}
+63 -6
View File
@@ -49,7 +49,7 @@ RemoteSyslogChannel::RemoteSyslogChannel():
{
}
RemoteSyslogChannel::RemoteSyslogChannel(const std::string& address, const std::string& name, int facility, bool bsdFormat):
_logHost(address),
_name(name),
@@ -107,7 +107,7 @@ void RemoteSyslogChannel::open()
_open = true;
}
void RemoteSyslogChannel::close()
{
if (_open)
@@ -117,7 +117,7 @@ void RemoteSyslogChannel::close()
}
}
void RemoteSyslogChannel::log(const Message& msg)
{
Poco::FastMutex::ScopedLock lock(_mutex);
@@ -163,7 +163,7 @@ void RemoteSyslogChannel::log(const Message& msg)
_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)
@@ -180,7 +180,7 @@ void RemoteSyslogChannel::setProperty(const std::string& name, const std::string
facility = Poco::toUpper(value.substr(7));
else
facility = Poco::toUpper(value);
if (facility == "KERN")
_facility = SYSLOG_KERN;
else if (facility == "USER")
@@ -252,7 +252,7 @@ void RemoteSyslogChannel::setProperty(const std::string& name, const std::string
}
}
std::string RemoteSyslogChannel::getProperty(const std::string& name) const
{
if (name == PROP_NAME)
@@ -362,6 +362,63 @@ int RemoteSyslogChannel::getPrio(const Message& msg)
}
}
const char* RemoteSyslogChannel::facilityToString(const Facility facility)
{
switch(facility)
{
case RemoteSyslogChannel::SYSLOG_KERN:
return "KERN";
case RemoteSyslogChannel::SYSLOG_USER:
return "USER";
case RemoteSyslogChannel::SYSLOG_MAIL:
return "MAIL";
case RemoteSyslogChannel::SYSLOG_DAEMON:
return "DAEMON";
case RemoteSyslogChannel::SYSLOG_AUTH:
return "AUTH";
case RemoteSyslogChannel::SYSLOG_SYSLOG:
return "SYSLOG";
case RemoteSyslogChannel::SYSLOG_LPR:
return "LPR";
case RemoteSyslogChannel::SYSLOG_NEWS:
return "NEWS";
case RemoteSyslogChannel::SYSLOG_UUCP:
return "UUCP";
case RemoteSyslogChannel::SYSLOG_CRON:
return "CRON";
case RemoteSyslogChannel::SYSLOG_AUTHPRIV:
return "AUTHPRIV";
case RemoteSyslogChannel::SYSLOG_FTP:
return "FTP";
case RemoteSyslogChannel::SYSLOG_NTP:
return "NTP";
case RemoteSyslogChannel::SYSLOG_LOGAUDIT:
return "LOGAUDIT";
case RemoteSyslogChannel::SYSLOG_LOGALERT:
return "LOGALERT";
case RemoteSyslogChannel::SYSLOG_CLOCK:
return "CLOCK";
case RemoteSyslogChannel::SYSLOG_LOCAL0:
return "LOCAL0";
case RemoteSyslogChannel::SYSLOG_LOCAL1:
return "LOCAL1";
case RemoteSyslogChannel::SYSLOG_LOCAL2:
return "LOCAL2";
case RemoteSyslogChannel::SYSLOG_LOCAL3:
return "LOCAL3";
case RemoteSyslogChannel::SYSLOG_LOCAL4:
return "LOCAL4";
case RemoteSyslogChannel::SYSLOG_LOCAL5:
return "LOCAL5";
case RemoteSyslogChannel::SYSLOG_LOCAL6:
return "LOCAL6";
case RemoteSyslogChannel::SYSLOG_LOCAL7:
return "LOCAL7";
default:
return "";
}
}
void RemoteSyslogChannel::registerChannel()
{
+5 -2
View File
@@ -96,7 +96,7 @@ public:
private:
Poco::NotificationQueue& _queue;
DatagramSocket _socket;
bool _stopped;
std::atomic<bool> _stopped;
};
@@ -190,7 +190,7 @@ private:
private:
Poco::NotificationQueue& _queue;
bool _stopped;
std::atomic<bool> _stopped;
RemoteSyslogListener* _pListener;
};
@@ -312,6 +312,7 @@ void SyslogParser::parseNew(const std::string& line, RemoteSyslogChannel::Severi
int tzd = 0;
bool hasDate = Poco::DateTimeParser::tryParse(RemoteSyslogChannel::SYSLOG_TIMEFORMAT, timeStr, date, tzd);
Poco::Message logEntry(msgId, messageText, prio);
logEntry[RemoteSyslogListener::LOG_PROP_FACILITY] = RemoteSyslogChannel::facilityToString(fac);
logEntry[RemoteSyslogListener::LOG_PROP_HOST] = hostName;
logEntry[RemoteSyslogListener::LOG_PROP_APP] = appName;
logEntry[RemoteSyslogListener::LOG_PROP_STRUCTURED_DATA] = sd;
@@ -390,6 +391,7 @@ void SyslogParser::parseBSD(const std::string& line, RemoteSyslogChannel::Severi
pos = line.size();
Poco::Message logEntry(hostName, messageText, prio);
logEntry.setTime(date.timestamp());
logEntry[RemoteSyslogListener::LOG_PROP_FACILITY] = RemoteSyslogChannel::facilityToString(fac);
message.swap(logEntry);
}
@@ -501,6 +503,7 @@ const std::string RemoteSyslogListener::PROP_REUSE_PORT("reusePort");
const std::string RemoteSyslogListener::PROP_THREADS("threads");
const std::string RemoteSyslogListener::PROP_BUFFER("buffer");
const std::string RemoteSyslogListener::LOG_PROP_FACILITY("facility");
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");
+29 -29
View File
@@ -52,7 +52,7 @@ SMTPChannel::SMTPChannel():
{
}
SMTPChannel::SMTPChannel(const std::string& mailhost, const std::string& sender, const std::string& recipient):
_mailHost(mailhost),
_sender(sender),
@@ -82,12 +82,12 @@ void SMTPChannel::open()
{
}
void SMTPChannel::close()
{
}
void SMTPChannel::log(const Message& msg)
{
try
@@ -116,7 +116,7 @@ void SMTPChannel::log(const Message& msg)
<< "Message text: " << msg.getText() << "\r\n\r\n";
message.addContent(new StringPartSource(content.str()));
if (!_attachment.empty())
{
{
@@ -132,7 +132,7 @@ void SMTPChannel::log(const Message& msg)
fis.seekg(std::ios::beg);
fis.read(pMem, size);
message.addAttachment(_attachment,
new StringPartSource(std::string(pMem, static_cast<SST>(size)),
new StringPartSource(std::string(pMem, static_cast<SST>(size)),
_type,
_attachment));
@@ -146,54 +146,54 @@ void SMTPChannel::log(const Message& msg)
session.login();
session.sendMessage(message);
session.close();
}
catch (Exception&)
{
if (_throw) throw;
}
catch (Exception&)
{
if (_throw) throw;
}
}
void SMTPChannel::setProperty(const std::string& name, const std::string& value)
{
if (name == PROP_MAILHOST)
if (name == PROP_MAILHOST)
_mailHost = value;
else if (name == PROP_SENDER)
else if (name == PROP_SENDER)
_sender = value;
else if (name == PROP_RECIPIENT)
else if (name == PROP_RECIPIENT)
_recipient = value;
else if (name == PROP_LOCAL)
else if (name == PROP_LOCAL)
_local = isTrue(value);
else if (name == PROP_ATTACHMENT)
else if (name == PROP_ATTACHMENT)
_attachment = value;
else if (name == PROP_TYPE)
else if (name == PROP_TYPE)
_type = value;
else if (name == PROP_DELETE)
else if (name == PROP_DELETE)
_delete = isTrue(value);
else if (name == PROP_THROW)
else if (name == PROP_THROW)
_throw = isTrue(value);
else
else
Channel::setProperty(name, value);
}
std::string SMTPChannel::getProperty(const std::string& name) const
{
if (name == PROP_MAILHOST)
if (name == PROP_MAILHOST)
return _mailHost;
else if (name == PROP_SENDER)
else if (name == PROP_SENDER)
return _sender;
else if (name == PROP_RECIPIENT)
else if (name == PROP_RECIPIENT)
return _recipient;
else if (name == PROP_LOCAL)
else if (name == PROP_LOCAL)
return _local ? "true" : "false";
else if (name == PROP_ATTACHMENT)
else if (name == PROP_ATTACHMENT)
return _attachment;
else if (name == PROP_TYPE)
else if (name == PROP_TYPE)
return _type;
else if (name == PROP_DELETE)
else if (name == PROP_DELETE)
return _delete ? "true" : "false";
else if (name == PROP_THROW)
else if (name == PROP_THROW)
return _throw ? "true" : "false";
else
return Channel::getProperty(name);
@@ -202,7 +202,7 @@ std::string SMTPChannel::getProperty(const std::string& name) const
void SMTPChannel::registerChannel()
{
Poco::LoggingFactory::defaultFactory().registerChannelClass("SMTPChannel",
Poco::LoggingFactory::defaultFactory().registerChannelClass("SMTPChannel",
new Poco::Instantiator<SMTPChannel, Poco::Channel>);
}
+3 -3
View File
@@ -70,7 +70,7 @@ public:
bool available()
{
PSecPkgInfoW pSecPkgInfo;
SECURITY_STATUS status = _pSecFunTable->QuerySecurityPackageInfoW(L"NTLM", &pSecPkgInfo);
SECURITY_STATUS status = _pSecFunTable->QuerySecurityPackageInfoW(const_cast< wchar_t* >(L"NTLM"), &pSecPkgInfo);
if (status == SEC_E_OK)
{
_pSecFunTable->FreeContextBuffer(pSecPkgInfo);
@@ -82,7 +82,7 @@ public:
Poco::SharedPtr<NTLMContext> createNTLMContext(const std::string& host, const std::string& service)
{
PSecPkgInfoW pSecPkgInfo;
SECURITY_STATUS status = _pSecFunTable->QuerySecurityPackageInfoW(L"NTLM", &pSecPkgInfo);
SECURITY_STATUS status = _pSecFunTable->QuerySecurityPackageInfoW(const_cast< wchar_t* >(L"NTLM"), &pSecPkgInfo);
if (status != SEC_E_OK) throw Poco::SystemException("NTLM SSPI not available", status);
std::size_t maxTokenSize = pSecPkgInfo->cbMaxToken;
@@ -94,7 +94,7 @@ public:
TimeStamp expiry;
status = _pSecFunTable->AcquireCredentialsHandleW(
NULL,
L"NTLM",
const_cast< wchar_t* >(L"NTLM"),
SECPKG_CRED_OUTBOUND,
NULL,
NULL,
+2 -2
View File
@@ -123,7 +123,7 @@ void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool ipV6Only)
#endif // POCO_HAVE_IPv6
}
void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool reusePort, bool ipV6Only)
{
#if defined(POCO_HAVE_IPv6)
@@ -135,7 +135,7 @@ void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool reusePort, b
#endif // POCO_HAVE_IPv6
}
void ServerSocket::listen(int backlog)
{
impl()->listen(backlog);
+79 -138
View File
@@ -14,14 +14,18 @@
#include "Poco/Net/Socket.h"
#include "Poco/Net/StreamSocketImpl.h"
#include "Poco/Net/PollSet.h"
#include "Poco/Timestamp.h"
#include "Poco/Error.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>
#if defined(POCO_HAVE_FD_POLL)
#include "Poco/SharedPtr.h"
#ifndef _WIN32
#include <poll.h>
#endif
#endif
@@ -50,6 +54,30 @@ Socket::Socket(const Socket& socket):
_pImpl->duplicate();
}
#if POCO_NEW_STATE_ON_MOVE
Socket::Socket(Socket&& socket):
_pImpl(socket._pImpl)
{
poco_check_ptr (_pImpl);
socket._pImpl = nullptr;
}
Socket& Socket::operator = (Socket&& socket)
{
if (&socket != this)
{
if (_pImpl) _pImpl->release();
_pImpl = socket._pImpl;
socket._pImpl = nullptr;
}
return *this;
}
#endif // POCO_NEW_STATE_ON_MOVE
Socket& Socket::operator = (const Socket& socket)
{
@@ -62,10 +90,9 @@ Socket& Socket::operator = (const Socket& socket)
return *this;
}
Socket::~Socket()
{
_pImpl->release();
if (_pImpl) _pImpl->release();
}
@@ -73,142 +100,34 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce
{
#if defined(POCO_HAVE_FD_EPOLL)
int epollSize = readList.size() + writeList.size() + exceptList.size();
int epollSize = static_cast<int>(readList.size() + writeList.size() + exceptList.size());
if (epollSize == 0) return 0;
int epollfd = -1;
PollSet ps;
for (const auto& s : readList) ps.add(s, PollSet::POLL_READ);
for (const auto& s : writeList) ps.add(s, PollSet::POLL_WRITE);
readList.clear();
writeList.clear();
exceptList.clear();
PollSet::SocketModeMap sm = ps.poll(timeout);
for (const auto& s : sm)
{
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");
}
}
}
if (s.second & PollSet::POLL_READ) readList.push_back(s.first);
if (s.second & PollSet::POLL_WRITE) writeList.push_back(s.first);
if (s.second & PollSet::POLL_ERROR) exceptList.push_back(s.first);
}
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();
return static_cast<int>(readList.size() + writeList.size() + exceptList.size());
#elif defined(POCO_HAVE_FD_POLL)
typedef Poco::SharedPtr<pollfd, Poco::ReferenceCounter, Poco::ReleaseArrayPolicy<pollfd>> SharedPollArray;
#ifdef _WIN32
typedef ULONG nfds_t;
#endif
nfds_t nfd = static_cast<nfds_t>(readList.size() + writeList.size() + exceptList.size());
nfds_t nfd = readList.size() + writeList.size() + exceptList.size();
if (0 == nfd) return 0;
SharedPollArray pPollArr = new pollfd[nfd]();
@@ -256,7 +175,11 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce
do
{
Poco::Timestamp start;
#ifdef _WIN32
rc = WSAPoll(pPollArr, nfd, static_cast<INT>(remainingTime.totalMilliseconds()));
#else
rc = ::poll(pPollArr, nfd, remainingTime.totalMilliseconds());
#endif
if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
{
Poco::Timestamp end;
@@ -276,17 +199,17 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce
SocketList::iterator endE = exceptList.end();
for (int idx = 0; idx < nfd; ++idx)
{
SocketList::iterator slIt = std::find_if(begR, endR, Socket::FDCompare(pPollArr[idx].fd));
SocketList::iterator slIt = std::find_if(begR, endR, Socket::FDCompare(static_cast<int>(pPollArr[idx].fd)));
if (POLLIN & pPollArr[idx].revents && slIt != endR) readyReadList.push_back(*slIt);
slIt = std::find_if(begW, endW, Socket::FDCompare(pPollArr[idx].fd));
slIt = std::find_if(begW, endW, Socket::FDCompare(static_cast<int>(pPollArr[idx].fd)));
if (POLLOUT & pPollArr[idx].revents && slIt != endW) readyWriteList.push_back(*slIt);
slIt = std::find_if(begE, endE, Socket::FDCompare(pPollArr[idx].fd));
slIt = std::find_if(begE, endE, Socket::FDCompare(static_cast<int>(pPollArr[idx].fd)));
if (POLLERR & pPollArr[idx].revents && slIt != endE) readyExceptList.push_back(*slIt);
}
std::swap(readList, readyReadList);
std::swap(writeList, readyWriteList);
std::swap(exceptList, readyExceptList);
return readList.size() + writeList.size() + exceptList.size();
return static_cast<int>(readList.size() + writeList.size() + exceptList.size());
#else
@@ -464,4 +387,22 @@ SocketBufVec Socket::makeBufVec(const std::vector<std::string>& vec)
}
int Socket::lastError()
{
return SocketImpl::lastError();
}
std::string Socket::lastErrorDesc()
{
return Error::getMessage(SocketImpl::lastError());
}
void Socket::error()
{
SocketImpl::error();
}
} } // namespace Poco::Net
+13
View File
@@ -150,6 +150,12 @@ SocketAddress::SocketAddress(const SocketAddress& socketAddress)
}
SocketAddress::SocketAddress(SocketAddress&& socketAddress):
_pImpl(std::move(socketAddress._pImpl))
{
}
SocketAddress::SocketAddress(const struct sockaddr* sockAddr, poco_socklen_t length)
{
if (length == sizeof(struct sockaddr_in) && sockAddr->sa_family == AF_INET)
@@ -203,6 +209,13 @@ SocketAddress& SocketAddress::operator = (const SocketAddress& socketAddress)
}
SocketAddress& SocketAddress::operator = (SocketAddress&& socketAddress)
{
_pImpl = std::move(socketAddress._pImpl);
return *this;
}
IPAddress SocketAddress::host() const
{
return pImpl()->host();
+64 -26
View File
@@ -20,23 +20,17 @@
#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>
#ifdef POCO_OS_FAMILY_WINDOWS
#include "wepoll.h"
#else
#include <sys/epoll.h>
#include <sys/eventfd.h>
#endif
#elif defined(POCO_HAVE_FD_POLL)
#ifndef _WIN32
#include <poll.h>
#endif
#ifndef _WIN32
#include <poll.h>
#endif
#endif
@@ -63,6 +57,20 @@ using Poco::NumberFormatter;
using Poco::Timespan;
#ifdef WEPOLL_H_
namespace {
int close(HANDLE h)
{
return epoll_close(h);
}
}
#endif // WEPOLL_H_
namespace Poco {
namespace Net {
@@ -219,10 +227,8 @@ void SocketImpl::bind(const SocketAddress& address, bool reuseAddress, bool reus
{
init(address.af());
}
if (reuseAddress)
setReuseAddress(true);
if (reusePort)
setReusePort(true);
setReuseAddress(reuseAddress);
setReusePort(reusePort);
#if defined(POCO_VXWORKS)
int rc = ::bind(_sockfd, (sockaddr*) address.addr(), address.length());
#else
@@ -253,10 +259,8 @@ void SocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool reu
#else
if (ipV6Only) throw Poco::NotImplementedException("IPV6_V6ONLY not defined.");
#endif
if (reuseAddress)
setReuseAddress(true);
if (reusePort)
setReusePort(true);
setReuseAddress(reuseAddress);
setReusePort(reusePort);
int rc = ::bind(_sockfd, address.addr(), address.length());
if (rc != 0) error(address.toString());
#else
@@ -614,6 +618,13 @@ int SocketImpl::available()
{
int result = 0;
ioctl(FIONREAD, result);
#if (POCO_OS != POCO_OS_LINUX)
if (result && (type() == SOCKET_TYPE_DATAGRAM))
{
std::vector<char> buf(result);
result = recvfrom(sockfd(), &buf[0], result, MSG_PEEK, NULL, NULL);
}
#endif
return result;
}
@@ -630,9 +641,17 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode)
if (sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
#if defined(POCO_HAVE_FD_EPOLL)
#ifdef WEPOLL_H_
HANDLE epollfd = epoll_create(1);
#else
int epollfd = epoll_create(1);
#endif
#ifdef WEPOLL_H_
if (!epollfd)
#else
if (epollfd < 0)
#endif
{
error("Can't create epoll queue");
}
@@ -661,7 +680,7 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode)
memset(&evout, 0, sizeof(evout));
Poco::Timestamp start;
rc = epoll_wait(epollfd, &evout, 1, remainingTime.totalMilliseconds());
rc = epoll_wait(epollfd, &evout, 1, static_cast<int>(remainingTime.totalMilliseconds()));
if (rc < 0 && lastError() == POCO_EINTR)
{
Poco::Timestamp end;
@@ -759,6 +778,14 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode)
}
int SocketImpl::getError()
{
int result;
getOption(SOL_SOCKET, SO_ERROR, result);
return result;
}
void SocketImpl::setSendBufferSize(int size)
{
setOption(SOL_SOCKET, SO_SNDBUF, size);
@@ -1027,14 +1054,25 @@ void SocketImpl::setReuseAddress(bool flag)
{
int value = flag ? 1 : 0;
setOption(SOL_SOCKET, SO_REUSEADDR, value);
#ifdef POCO_OS_FAMILY_WINDOWS
value = flag ? 0 : 1;
setOption(SOL_SOCKET, SO_EXCLUSIVEADDRUSE, value);
#endif
}
bool SocketImpl::getReuseAddress()
{
bool ret = false;
int value(0);
getOption(SOL_SOCKET, SO_REUSEADDR, value);
return value != 0;
ret = (value != 0);
#ifdef POCO_OS_FAMILY_WINDOWS
value = 0;
getOption(SOL_SOCKET, SO_EXCLUSIVEADDRUSE, value);
ret = ret && (value == 0);
#endif
return ret;
}
+20 -8
View File
@@ -29,14 +29,14 @@ SocketNotification::~SocketNotification()
{
}
void SocketNotification::setSocket(const Socket& socket)
{
_socket = socket;
}
ReadableNotification::ReadableNotification(SocketReactor* pReactor):
ReadableNotification::ReadableNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
@@ -47,7 +47,7 @@ ReadableNotification::~ReadableNotification()
}
WritableNotification::WritableNotification(SocketReactor* pReactor):
WritableNotification::WritableNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
@@ -58,18 +58,30 @@ WritableNotification::~WritableNotification()
}
ErrorNotification::ErrorNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
ErrorNotification::ErrorNotification(SocketReactor* pReactor, int code, const std::string& description):
SocketNotification(pReactor),
_code(code),
_description(description)
{
}
ErrorNotification::ErrorNotification(SocketReactor* pReactor, const Socket& socket,
int code, const std::string& description):
SocketNotification(pReactor),
_code(code),
_description(description)
{
setSocket(socket);
}
ErrorNotification::~ErrorNotification()
{
}
TimeoutNotification::TimeoutNotification(SocketReactor* pReactor):
TimeoutNotification::TimeoutNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
@@ -80,7 +92,7 @@ TimeoutNotification::~TimeoutNotification()
}
IdleNotification::IdleNotification(SocketReactor* pReactor):
IdleNotification::IdleNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
@@ -91,7 +103,7 @@ IdleNotification::~IdleNotification()
}
ShutdownNotification::ShutdownNotification(SocketReactor* pReactor):
ShutdownNotification::ShutdownNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
+808
View File
@@ -0,0 +1,808 @@
//
// SocketProactor.cpp
//
// Library: Net
// Package: Sockets
// Module: SocketProactor
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/SocketProactor.h"
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/DatagramSocketImpl.h"
#include "Poco/Thread.h"
#include "Poco/Exception.h"
#ifdef POCO_OS_FAMILY_WINDOWS
#ifdef max
#undef max
#endif // max
#endif // POCO_OS_FAMILY_WINDOWS
#include <limits>
using Poco::Exception;
using Poco::ErrorHandler;
namespace Poco {
namespace Net {
//
// Worker
//
class Worker
/// Worker is a utility class that executes work (functions).
/// Workload can be permanent (executed on every doWork() call),
/// or "one-shot" (scheduled for a single execution at a point
/// in the future).
{
public:
using MutexType = SocketProactor::MutexType;
using ScopedLock = SocketProactor::ScopedLock;
using Work = SocketProactor::Work;
using WorkEntry = std::pair<Work, Poco::Timestamp>;
using WorkList = std::deque<WorkEntry>;
void addWork(const Work& ch, Timestamp::TimeDiff ms = SocketProactor::PERMANENT_COMPLETION_HANDLER)
{
addWork(Work(ch), ms);
}
void addWork(Work&& ch, Timestamp::TimeDiff ms, int pos = -1)
{
auto pch = SocketProactor::PERMANENT_COMPLETION_HANDLER;
Poco::Timestamp expires = (ms != pch) ? Timestamp() + (ms * 1000) : Timestamp(pch);
if (pos == -1 || (pos + 1) > _funcList.size())
{
ScopedLock lock(_mutex);
_funcList.push_back({std::move(ch), expires});
}
else
{
if (pos < 0)
throw Poco::InvalidArgumentException("SocketProactor::addWork()");
ScopedLock lock(_mutex);
_funcList.insert(_funcList.begin() + pos, {std::move(ch), expires});
}
}
void removeWork()
{
ScopedLock lock(_mutex);
_funcList.clear();
}
int scheduledWork()
{
int cnt = 0;
ScopedLock lock(_mutex);
WorkList::iterator it = _funcList.begin();
for (; it != _funcList.end(); ++it)
{
if (!isPermanent(it->second)) ++cnt;
}
return cnt;
}
int removeScheduledWork(int count)
{
auto isScheduled = [](const Timestamp &ts)
{ return !isPermanent(ts); };
return removeWork(isScheduled, count);
}
int permanentWork()
{
int cnt = 0;
ScopedLock lock(_mutex);
WorkList::iterator it = _funcList.begin();
for (; it != _funcList.end(); ++it)
{
if (isPermanent(it->second))
++cnt;
}
return cnt;
}
int removePermanentWork(int count)
{
auto perm = [](const Timestamp &ts)
{ return isPermanent(ts); };
return removeWork(perm, count);
}
static bool isPermanent(const Timestamp &entry)
{
return entry == Timestamp(SocketProactor::PERMANENT_COMPLETION_HANDLER);
}
int doWork(bool handleOne, bool expiredOnly)
{
std::unique_ptr<Work> pCH;
int handled = 0;
{
ScopedLock lock(_mutex);
WorkList::iterator it = _funcList.begin();
try
{
while (it != _funcList.end())
{
std::size_t prevSize = 0;
bool alwaysRun = isPermanent(it->second) && !expiredOnly;
bool isExpired = !alwaysRun && (Timestamp() >= it->second);
if (isExpired)
{
pCH.reset(new Work(std::move(it->first)));
it = _funcList.erase(it);
}
else if (alwaysRun)
{
pCH.reset(new Work(it->first));
++it;
}
else ++it;
prevSize = _funcList.size();
if (pCH)
{
(*pCH)();
pCH.reset();
++handled;
if (handleOne) break;
}
// handler call may add or remove handlers;
// if so, we must start from the beginning
if (prevSize != _funcList.size())
it = _funcList.begin();
}
}
catch (Exception& exc)
{
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
ErrorHandler::handle(exc);
}
catch (...)
{
ErrorHandler::handle();
}
}
return handled;
}
int runOne()
{
try
{
while (0 == doWork(true, false));
return 1;
}
catch(...) {}
return 0;
}
private:
template <typename F>
int removeWork(F isType, int count)
/// Removes `count` functions of the specified type;
/// if count is -1, removes all the functions of the
/// specified type.
{
int removed = 0;
ScopedLock lock(_mutex);
int left = count > -1 ? count : static_cast<int>(_funcList.size());
WorkList::iterator it = _funcList.begin();
while (left && it != _funcList.end())
{
if (isType(it->second))
{
++removed;
it = _funcList.erase((it));
--left;
}
else ++it;
}
return removed;
}
WorkList _funcList;
MutexType _mutex;
};
//
// SocketProactor
//
const Timestamp::TimeDiff SocketProactor::PERMANENT_COMPLETION_HANDLER =
std::numeric_limits<Timestamp::TimeDiff>::max();
SocketProactor::SocketProactor(bool worker):
_isRunning(false),
_isStopped(false),
_stop(false),
_timeout(0),
_maxTimeout(DEFAULT_MAX_TIMEOUT_MS),
_pThread(nullptr),
_ioCompletion(_maxTimeout),
_pWorker(worker ? new Worker : nullptr)
{
}
SocketProactor::SocketProactor(const Poco::Timespan& timeout, bool worker):
_isRunning(false),
_isStopped(false),
_stop(false),
_timeout(0),
_maxTimeout(static_cast<long>(timeout.totalMilliseconds())),
_pThread(nullptr),
_ioCompletion(_maxTimeout),
_pWorker(worker ? new Worker : nullptr)
{
}
SocketProactor::~SocketProactor()
{
_ioCompletion.stop();
wait();
for (auto& pS : _writeHandlers)
{
for (auto& pH : pS.second)
{
if (pH->_pBuf && pH->_owner)
delete pH->_pBuf;
}
}
}
void SocketProactor::wait()
{
_ioCompletion.wakeUp();
_ioCompletion.wait();
}
bool SocketProactor::hasHandlers(SubscriberMap& handlers, int sockfd)
{
Poco::Mutex::ScopedLock l(_writeMutex);
if (handlers.end() == handlers.find(sockfd))
return false;
return true;
}
int SocketProactor::poll(int* pHandled)
{
int handled = 0;
int worked = 0;
PollSet::SocketModeMap sm = _pollSet.poll(_timeout);
if (sm.size() > 0)
{
auto it = sm.begin();
auto end = sm.end();
for (; it != end; ++it)
{
if (it->second & PollSet::POLL_READ)
{
Socket sock = it->first;
if (hasHandlers(_readHandlers, static_cast<int>(sock.impl()->sockfd())))
handled += receive(sock);
}
if (it->second & PollSet::POLL_WRITE)
{
Socket sock = it->first;
if (hasHandlers(_writeHandlers, static_cast<int>(sock.impl()->sockfd())))
handled += send(sock);
}
if (it->second & PollSet::POLL_ERROR)
{
Socket sock = it->first;
handled += error(sock);
}
}
}
if (_pWorker)
{
if (hasSocketHandlers() && handled) worked = doWork();
else worked = doWork(false, true);
}
if (pHandled) *pHandled = handled;
return worked;
}
void SocketProactor::addReceiveFrom(Socket sock, Buffer& buf, Poco::Net::SocketAddress& addr, Callback&& onCompletion)
{
if (!sock.isDatagram())
throw Poco::InvalidArgumentException("SocketProactor::addSend(): UDP socket required");
std::unique_ptr<Handler> pHandler(new Handler);
pHandler->_pAddr = std::addressof(addr);
pHandler->_pBuf = std::addressof(buf);
pHandler->_onCompletion = std::move(onCompletion);
Poco::Mutex::ScopedLock l(_readMutex);
_readHandlers[sock.impl()->sockfd()].push_back(std::move(pHandler));
}
void SocketProactor::addSendTo(Socket sock, const Buffer& message, const SocketAddress& addr, Callback&& onCompletion)
{
if (!sock.isDatagram())
throw Poco::InvalidArgumentException("SocketProactor::addSend(): UDP socket required");
Buffer* pMessage = nullptr;
SocketAddress* pAddr = nullptr;
try
{
pMessage = new Buffer(message);
pAddr = new SocketAddress(addr);
}
catch(...)
{
delete pMessage;
delete pAddr;
throw;
}
addSend(sock, pMessage, pAddr, std::move(onCompletion), true);
}
void SocketProactor::addSendTo(Socket sock, Buffer&& message, const SocketAddress&& addr, Callback&& onCompletion)
{
if (!sock.isDatagram())
throw Poco::InvalidArgumentException("SocketProactor::addSend(): UDP socket required");
Buffer* pMessage = nullptr;
SocketAddress* pAddr = nullptr;
try
{
pMessage = new Buffer(std::move(message));
pAddr = new SocketAddress(std::move(addr));
}
catch(...)
{
delete pMessage;
delete pAddr;
throw;
}
addSend(sock, pMessage, pAddr, std::move(onCompletion), true);
}
void SocketProactor::addReceive(Socket sock, Buffer& buf, Callback&& onCompletion)
{
if (!sock.isStream())
throw Poco::InvalidArgumentException("SocketProactor::addSend(): TCP socket required");
std::unique_ptr<Handler> pHandler(new Handler);
pHandler->_pAddr = nullptr;
pHandler->_pBuf = std::addressof(buf);
pHandler->_onCompletion = std::move(onCompletion);
Poco::Mutex::ScopedLock l(_readMutex);
_readHandlers[sock.impl()->sockfd()].push_back(std::move(pHandler));
if (!has(sock)) addSocket(sock, PollSet::POLL_READ);
}
void SocketProactor::addSend(Socket sock, const Buffer& message, Callback&& onCompletion)
{
if (!sock.isStream())
throw Poco::InvalidArgumentException("SocketProactor::addSend(): TCP socket required");
Buffer* pMessage = nullptr;
try
{
pMessage = new Buffer(message);
}
catch(...)
{
delete pMessage;
throw;
}
addSend(sock, pMessage, nullptr, std::move(onCompletion), true);
}
void SocketProactor::addSend(Socket sock, Buffer&& message, Callback&& onCompletion)
{
if (!sock.isStream())
throw Poco::InvalidArgumentException("SocketProactor::addSend(): TCP socket required");
Buffer* pMessage = nullptr;
try
{
pMessage = new Buffer(std::move(message));
}
catch(...)
{
delete pMessage;
throw;
}
addSend(sock, pMessage, nullptr, std::move(onCompletion), true);
}
void SocketProactor::addSend(Socket sock, Buffer* pMessage, SocketAddress* pAddr, Callback&& onCompletion, bool own)
{
std::unique_ptr<Handler> pHandler(new Handler);
pHandler->_pAddr = pAddr;
pHandler->_pBuf = pMessage;
pHandler->_onCompletion = std::move(onCompletion);
pHandler->_owner = own;
Poco::Mutex::ScopedLock l(_writeMutex);
_writeHandlers[sock.impl()->sockfd()].push_back(std::move(pHandler));
if (!has(sock)) addSocket(sock, PollSet::POLL_WRITE);
}
int SocketProactor::error(Socket& sock)
{
int cnt = errorImpl(sock, _readHandlers, _readMutex);
cnt += errorImpl(sock, _writeHandlers, _writeMutex);
return cnt;
}
int SocketProactor::send(Socket& sock)
{
Poco::Mutex::ScopedLock l(_writeMutex);
auto hIt = _writeHandlers.find(sock.impl()->sockfd());
if (hIt == _writeHandlers.end()) return 0;
IOHandlerList& handlers = hIt->second;
int handled = static_cast<int>(handlers.size());
auto it = handlers.begin();
auto end = handlers.end();
while (it != end)
{
if (sock.isDatagram())
sendTo(*sock.impl(), it);
else if (sock.isStream())
send(*sock.impl(), it);
else
{
deleteHandler(handlers, it);
throw Poco::InvalidArgumentException("Unknown socket type.");
}
deleteHandler(handlers, it);
// end iterator is invalidated when the last member
// is removed, so make sure we don't check for it
if (handlers.empty()) break;
}
handled -= static_cast<int>(handlers.size());
if (handled) _ioCompletion.wakeUp();
return handled;
}
void SocketProactor::sendTo(SocketImpl& sock, IOHandlerIt& it)
{
Buffer* pBuf = (*it)->_pBuf;
if (pBuf && pBuf->size())
{
SocketAddress *pAddr = (*it)->_pAddr;
int n = 0, err = 0;
try
{
n = sock.sendTo(&(*pBuf)[0], static_cast<int>(pBuf->size()), *pAddr);
}
catch(std::exception&)
{
err = Socket::lastError();
}
enqueueIONotification(std::move((*it)->_onCompletion), n, err);
}
else
{
if (!pBuf)
throw Poco::NullPointerException("SocketProactor::sendTo(): null buffer");
else if (pBuf->empty())
throw Poco::InvalidArgumentException("SocketProactor::sendTo(): empty buffer");
else // we shouldn't be here
throw Poco::InvalidAccessException("SocketProactor::sendTo(): unexpected error");
}
}
void SocketProactor::send(SocketImpl& sock, IOHandlerIt& it)
{
Buffer* pBuf = (*it)->_pBuf;
if (pBuf && pBuf->size())
{
int n = 0, err = 0;
try
{
n = sock.sendBytes(&(*pBuf)[0], static_cast<int>(pBuf->size()));
}
catch(std::exception&)
{
err = Socket::lastError();
}
enqueueIONotification(std::move((*it)->_onCompletion), n, err);
}
else
{
if (!pBuf)
throw Poco::NullPointerException("SocketProactor::sendTo(): null buffer");
else if (pBuf->empty())
throw Poco::InvalidArgumentException("SocketProactor::sendTo(): empty buffer");
else // we shouldn't be here
throw Poco::InvalidAccessException("SocketProactor::sendTo(): unexpected error");
}
}
int SocketProactor::receive(Socket& sock)
{
Poco::Mutex::ScopedLock l(_readMutex);
auto hIt = _readHandlers.find(sock.impl()->sockfd());
if (hIt == _readHandlers.end()) return 0;
IOHandlerList& handlers = hIt->second;
int handled = static_cast<int>(handlers.size());
int avail = 0;
auto it = handlers.begin();
auto end = handlers.end();
for (; it != end;)
{
if ((avail = sock.available()))
{
if (sock.isDatagram())
receiveFrom(*sock.impl(), it, avail);
else if (sock.isStream())
receive(*sock.impl(), it, avail);
else
throw Poco::InvalidArgumentException("Unknown socket type.");
++it;
handlers.pop_front();
// end iterator is invalidated when the last member
// is removed, so make sure we don't check for it
if (handlers.size() == 0) break;
}
else break;
}
handled -= static_cast<int>(handlers.size());
if (handled) _ioCompletion.wakeUp();
return handled;
}
void SocketProactor::receiveFrom(SocketImpl& sock, IOHandlerIt& it, int available)
{
Buffer *pBuf = (*it)->_pBuf;
SocketAddress *pAddr = (*it)->_pAddr;
SocketAddress addr = *pAddr;
poco_check_ptr(pBuf);
if (pBuf->size() < available) pBuf->resize(available);
int n = 0, err = 0;
try
{
n = sock.receiveFrom(&(*pBuf)[0], available, *pAddr);
}
catch(std::exception&)
{
err = Socket::lastError();
}
enqueueIONotification(std::move((*it)->_onCompletion), n, err);
}
void SocketProactor::receive(SocketImpl& sock, IOHandlerIt& it, int available)
{
Buffer *pBuf = (*it)->_pBuf;
poco_check_ptr(pBuf);
if (pBuf->size() < available) pBuf->resize(available);
int n = 0, err = 0;
try
{
n = sock.receiveBytes(&(*pBuf)[0], available);
}
catch(std::exception&)
{
err = Socket::lastError();
}
enqueueIONotification(std::move((*it)->_onCompletion), n, err);
}
int SocketProactor::doWork(bool handleOne, bool expiredOnly)
{
return worker().doWork(handleOne, expiredOnly);
}
int SocketProactor::runOne()
{
return worker().runOne();
}
void SocketProactor::sleep(bool isAtWork)
{
try
{
if (isAtWork)
{
_timeout = 0;
return;
}
else
{
if (_timeout < _maxTimeout) ++_timeout;
}
if (_pThread) _pThread->trySleep(_timeout);
else Thread::sleep(_timeout);
}
catch (Exception& exc)
{
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
ErrorHandler::handle(exc);
}
catch (...)
{
ErrorHandler::handle();
}
}
void SocketProactor::run()
{
_pThread = Thread::current();
_ioCompletion.start();
int handled = 0;
if (!_isStopped) _stop = false;
_isStopped = false;
while (!_stop)
{
this->sleep(poll(&handled) || handled);
_isRunning = true;
}
_isRunning = false;
onShutdown();
}
bool SocketProactor::hasSocketHandlers() const
{
if (_readHandlers.size() || _writeHandlers.size())
return true;
return false;
}
void SocketProactor::stop()
{
// the reason for two flags is to prevent a race
// when stop() is called before run() (which sets
// stop to false before entering the polling loop
// in order to allow multiple run()/stop() cycles)
_stop = true;
_isStopped = true;
}
void SocketProactor::wakeUp()
{
if (_pThread) _pThread->wakeUp();
}
void SocketProactor::setTimeout(const Poco::Timespan& timeout)
{
_timeout = static_cast<long>(timeout.totalMilliseconds());
}
Poco::Timespan SocketProactor::getTimeout() const
{
return _maxTimeout;
}
Worker& SocketProactor::worker()
{
poco_check_ptr(_pWorker);
return *_pWorker;
}
void SocketProactor::addWork(const Work& ch, Timestamp::TimeDiff ms)
{
worker().addWork(Work(ch), ms);
}
void SocketProactor::addWork(Work&& ch, Timestamp::TimeDiff ms, int pos)
{
worker().addWork(std::move(ch), ms, pos);
}
void SocketProactor::removeWork()
{
worker().removeWork();
}
int SocketProactor::scheduledWork()
{
return worker().scheduledWork();
}
int SocketProactor::removeScheduledWork(int count)
{
return worker().removeScheduledWork(count);
}
int SocketProactor::permanentWork()
{
return worker().permanentWork();
}
int SocketProactor::removePermanentWork(int count)
{
return worker().removePermanentWork(count);
}
bool SocketProactor::has(const Socket& sock) const
{
return _pollSet.has(sock);
}
bool SocketProactor::ioCompletionInProgress() const
{
return _ioCompletion.queueSize();
}
void SocketProactor::onShutdown()
{
_pollSet.wakeUp();
_ioCompletion.stop();
_ioCompletion.wait();
}
void SocketProactor::deleteHandler(IOHandlerList& handlers, IOHandlerList::iterator& it)
{
if ((*it)->_owner)
{
if ((*it)->_pBuf)
{
delete (*it)->_pBuf;
(*it)->_pBuf = nullptr;
}
if ((*it)->_pAddr)
{
delete (*it)->_pAddr;
(*it)->_pAddr = nullptr;
}
}
++it;
handlers.pop_front();
}
} } // namespace Poco::Net
+107 -96
View File
@@ -13,10 +13,9 @@
#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/Stopwatch.h"
#include "Poco/Exception.h"
@@ -30,29 +29,38 @@ 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)
_pShutdownNotification(new ShutdownNotification(this))
{
}
SocketReactor::SocketReactor(const Poco::Timespan& timeout):
SocketReactor::SocketReactor(const Poco::Timespan& pollTimeout, int threadAffinity):
_threadAffinity(threadAffinity),
_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)
_pShutdownNotification(new ShutdownNotification(this))
{
_params.pollTimeout = pollTimeout;
}
SocketReactor::SocketReactor(const Params& params, int threadAffinity):
_params(params),
_threadAffinity(threadAffinity),
_stop(false),
_pReadableNotification(new ReadableNotification(this)),
_pWritableNotification(new WritableNotification(this)),
_pErrorNotification(new ErrorNotification(this)),
_pTimeoutNotification(new TimeoutNotification(this)),
_pShutdownNotification(new ShutdownNotification(this))
{
}
@@ -63,49 +71,79 @@ SocketReactor::~SocketReactor()
void SocketReactor::run()
{
_pThread = Thread::current();
if (_threadAffinity >= 0)
{
Poco::Thread* pThread = Thread::current();
if (pThread) pThread->setAffinity(_threadAffinity);
}
Poco::Stopwatch sw;
if (_params.throttle) sw.start();
PollSet::SocketModeMap sm;
while (!_stop)
{
try
{
if (!hasSocketHandlers())
if (hasSocketHandlers())
{
onIdle();
Thread::trySleep(static_cast<long>(_timeout.totalMilliseconds()));
}
else
{
bool readable = false;
PollSet::SocketModeMap sm = _pollSet.poll(_timeout);
if (sm.size() > 0)
sm = _pollSet.poll(_params.pollTimeout);
for (const auto& s : sm)
{
onBusy();
PollSet::SocketModeMap::iterator it = sm.begin();
PollSet::SocketModeMap::iterator end = sm.end();
for (; it != end; ++it)
try
{
if (it->second & PollSet::POLL_READ)
if (s.second & PollSet::POLL_READ)
{
dispatch(it->first, _pReadableNotification);
readable = true;
dispatch(s.first, _pReadableNotification);
}
if (it->second & PollSet::POLL_WRITE) dispatch(it->first, _pWritableNotification);
if (it->second & PollSet::POLL_ERROR) dispatch(it->first, _pErrorNotification);
if (s.second & PollSet::POLL_WRITE)
{
dispatch(s.first, _pWritableNotification);
}
if (s.second & PollSet::POLL_ERROR)
{
dispatch(s.first, _pErrorNotification);
}
}
catch (Exception& exc)
{
onError(s.first, exc.code(), exc.displayText());
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
onError(s.first, 0, exc.what());
ErrorHandler::handle(exc);
}
catch (...)
{
onError(s.first, 0, "unknown exception");
ErrorHandler::handle();
}
}
if (!readable) onTimeout();
if (0 == sm.size())
{
onTimeout();
if (_params.throttle && _params.pollTimeout == 0)
{
if ((sw.elapsed()/1000) > _params.sleepLimit) sleep();
}
}
else if (_params.throttle) sw.restart();
}
else sleep();
}
catch (Exception& exc)
{
onError(exc.code(), exc.displayText());
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
onError(0, exc.what());
ErrorHandler::handle(exc);
}
catch (...)
{
onError(0, "unknown exception");
ErrorHandler::handle();
}
}
@@ -113,6 +151,27 @@ void SocketReactor::run()
}
void SocketReactor::sleep()
{
if (_params.sleep < _params.sleepLimit) ++_params.sleep;
_event.tryWait(_params.sleep);
}
void SocketReactor::stop()
{
_stop = true;
wakeUp();
}
void SocketReactor::wakeUp()
{
_pollSet.wakeUp();
_event.set();
}
bool SocketReactor::hasSocketHandlers()
{
if (!_pollSet.empty())
@@ -130,30 +189,6 @@ bool SocketReactor::hasSocketHandlers()
}
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 = getNotifier(socket, true);
@@ -179,11 +214,14 @@ bool SocketReactor::hasEventHandler(const Socket& socket, const Poco::AbstractOb
SocketReactor::NotifierPtr SocketReactor::getNotifier(const Socket& socket, bool makeNew)
{
const SocketImpl* pImpl = socket.impl();
if (pImpl == nullptr) return 0;
poco_socket_t sockfd = pImpl->sockfd();
ScopedLock lock(_mutex);
EventHandlerMap::iterator it = _handlers.find(socket);
EventHandlerMap::iterator it = _handlers.find(sockfd);
if (it != _handlers.end()) return it->second;
else if (makeNew) return (_handlers[socket] = new SocketNotifier(socket));
else if (makeNew) return (_handlers[sockfd] = new SocketNotifier(socket));
return 0;
}
@@ -191,6 +229,8 @@ SocketReactor::NotifierPtr SocketReactor::getNotifier(const Socket& socket, bool
void SocketReactor::removeEventHandler(const Socket& socket, const Poco::AbstractObserver& observer)
{
const SocketImpl* pImpl = socket.impl();
if (pImpl == nullptr) return;
NotifierPtr pNotifier = getNotifier(socket);
if (pNotifier && pNotifier->hasObserver(observer))
{
@@ -198,44 +238,36 @@ void SocketReactor::removeEventHandler(const Socket& socket, const Poco::Abstrac
{
{
ScopedLock lock(_mutex);
_handlers.erase(socket);
_handlers.erase(pImpl->sockfd());
}
_pollSet.remove(socket);
}
pNotifier->removeObserver(this, observer);
if (pNotifier->countObservers() > 0 && socket.impl()->sockfd() > 0)
{
int mode = 0;
if (pNotifier->accepts(_pReadableNotification)) mode |= PollSet::POLL_READ;
if (pNotifier->accepts(_pWritableNotification)) mode |= PollSet::POLL_WRITE;
if (pNotifier->accepts(_pErrorNotification)) mode |= PollSet::POLL_ERROR;
_pollSet.update(socket, mode);
}
}
}
bool SocketReactor::has(const Socket& socket) const
{
return _pollSet.has(socket);
}
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 = getNotifier(socket);
@@ -260,25 +292,4 @@ void SocketReactor::dispatch(SocketNotification* 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
+2 -2
View File
@@ -30,12 +30,12 @@ namespace Net {
//
SocketStreamBuf::SocketStreamBuf(const Socket& socket):
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();
_pImpl->duplicate();
else
throw InvalidArgumentException("Invalid or null SocketImpl passed to SocketStreamBuf");
}
+50 -1
View File
@@ -51,6 +51,11 @@ StreamSocket::StreamSocket(const Socket& socket): Socket(socket)
}
StreamSocket::StreamSocket(const StreamSocket& socket): Socket(socket)
{
}
StreamSocket::StreamSocket(SocketImpl* pImpl): Socket(pImpl)
{
if (!dynamic_cast<StreamSocketImpl*>(impl()))
@@ -73,6 +78,50 @@ StreamSocket& StreamSocket::operator = (const Socket& socket)
}
StreamSocket& StreamSocket::operator = (const StreamSocket& socket)
{
Socket::operator = (socket);
return *this;
}
#if POCO_NEW_STATE_ON_MOVE
StreamSocket::StreamSocket(Socket&& socket): Socket(std::move(socket))
{
if (!dynamic_cast<StreamSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
StreamSocket::StreamSocket(StreamSocket&& socket): Socket(std::move(socket))
{
}
StreamSocket& StreamSocket::operator = (Socket&& socket)
{
Socket::operator = (std::move(socket));
return *this;
}
StreamSocket& StreamSocket::operator = (StreamSocket&& socket)
{
Socket::operator = (std::move(socket));
return *this;
}
#endif // POCO_NEW_STATE_ON_MOVE
void StreamSocket::bind(const SocketAddress& address, bool reuseAddress, bool ipV6Only)
{
if (address.family() == IPAddress::IPv4)
impl()->bind(address, reuseAddress);
else
impl()->bind6(address, reuseAddress, ipV6Only);
}
void StreamSocket::connect(const SocketAddress& address)
{
impl()->connect(address);
@@ -96,7 +145,7 @@ void StreamSocket::shutdownReceive()
impl()->shutdownReceive();
}
void StreamSocket::shutdownSend()
{
impl()->shutdownSend();
+1 -1
View File
@@ -62,7 +62,7 @@ int StreamSocketImpl::sendBytes(const void* buffer, int length, int flags)
{
int n = SocketImpl::sendBytes(p, remaining, flags);
poco_assert_dbg (n >= 0);
p += n;
p += n;
sent += n;
remaining -= n;
if (blocking && remaining > 0)
+1 -1
View File
@@ -51,7 +51,7 @@ std::istream& StringPartSource::stream()
return _istr;
}
const std::string& StringPartSource::filename() const
{
return _filename;
+7 -7
View File
@@ -47,7 +47,7 @@ TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::UInt16 port
_socket(ServerSocket(portNumber)),
_thread(threadName(_socket)),
_stopped(true)
{
{
Poco::ThreadPool& pool = Poco::ThreadPool::defaultPool();
if (pParams)
{
@@ -55,7 +55,7 @@ TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::UInt16 port
if (toAdd > 0) pool.addCapacity(toAdd);
}
_pDispatcher = new TCPServerDispatcher(pFactory, pool, pParams);
}
@@ -111,7 +111,7 @@ void TCPServer::start()
_thread.start(*this);
}
void TCPServer::stop()
{
if (!_stopped)
@@ -135,7 +135,7 @@ void TCPServer::run()
try
{
StreamSocket ss = _socket.acceptConnection();
if (!_pConnectionFilter || _pConnectionFilter->accept(ss))
{
// enable nodelay per default: OSX really needs that
@@ -167,7 +167,7 @@ void TCPServer::run()
ErrorHandler::handle(exc);
// possibly a resource issue since poll() failed;
// give some time to recover before trying again
Poco::Thread::sleep(50);
Poco::Thread::sleep(50);
}
}
}
@@ -184,7 +184,7 @@ int TCPServer::maxThreads() const
return _pDispatcher->maxThreads();
}
int TCPServer::totalConnections() const
{
return _pDispatcher->totalConnections();
@@ -202,7 +202,7 @@ int TCPServer::maxConcurrentConnections() const
return _pDispatcher->maxConcurrentConnections();
}
int TCPServer::queuedConnections() const
{
return _pDispatcher->queuedConnections();
+26 -36
View File
@@ -16,6 +16,7 @@
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Notification.h"
#include "Poco/AutoPtr.h"
#include "Poco/ErrorHandler.h"
#include <memory>
@@ -84,18 +85,13 @@ 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;
if (--_rc == 0) delete this;
}
@@ -107,26 +103,29 @@ void TCPServerDispatcher::run()
for (;;)
{
AutoPtr<Notification> pNf = _queue.waitDequeueNotification(idleTime);
if (pNf)
{
TCPConnectionNotification* pCNf = dynamic_cast<TCPConnectionNotification*>(pNf.get());
if (pCNf)
ThreadCountWatcher tcw(this);
try
{
std::unique_ptr<TCPServerConnection> pConnection(_pConnectionFactory->createConnection(pCNf->socket()));
poco_check_ptr(pConnection.get());
beginConnection();
pConnection->start();
endConnection();
AutoPtr<Notification> pNf = _queue.waitDequeueNotification(idleTime);
if (pNf)
{
TCPConnectionNotification* pCNf = dynamic_cast<TCPConnectionNotification*>(pNf.get());
if (pCNf)
{
std::unique_ptr<TCPServerConnection> pConnection(_pConnectionFactory->createConnection(pCNf->socket()));
poco_check_ptr(pConnection.get());
beginConnection();
pConnection->start();
endConnection();
}
}
}
catch (Poco::Exception &exc) { ErrorHandler::handle(exc); }
catch (std::exception &exc) { ErrorHandler::handle(exc); }
catch (...) { ErrorHandler::handle(); }
}
FastMutex::ScopedLock lock(_mutex);
if (_stopped || (_currentThreads > 1 && _queue.empty()))
{
--_currentThreads;
break;
}
if (_stopped || (_currentThreads > 1 && _queue.empty())) break;
}
}
@@ -174,14 +173,15 @@ void TCPServerDispatcher::stop()
FastMutex::ScopedLock lock(_mutex);
_stopped = true;
_queue.clear();
_queue.enqueueNotification(new StopNotification);
for (int i = 0; i < _threadPool.allocated(); i++)
{
_queue.enqueueNotification(new StopNotification);
}
}
int TCPServerDispatcher::currentThreads() const
{
FastMutex::ScopedLock lock(_mutex);
return _currentThreads;
}
@@ -195,24 +195,18 @@ int TCPServerDispatcher::maxThreads() const
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;
}
@@ -225,8 +219,6 @@ int TCPServerDispatcher::queuedConnections() const
int TCPServerDispatcher::refusedConnections() const
{
FastMutex::ScopedLock lock(_mutex);
return _refusedConnections;
}
@@ -238,14 +230,12 @@ void TCPServerDispatcher::beginConnection()
++_totalConnections;
++_currentConnections;
if (_currentConnections > _maxConcurrentConnections)
_maxConcurrentConnections = _currentConnections;
_maxConcurrentConnections.store(_currentConnections);
}
void TCPServerDispatcher::endConnection()
{
FastMutex::ScopedLock lock(_mutex);
--_currentConnections;
}
+52
View File
@@ -65,6 +65,30 @@ WebSocket::WebSocket(const Socket& socket):
}
#ifdef POCO_NEW_STATE_ON_MOVE
WebSocket::WebSocket(Socket&& socket):
StreamSocket(std::move(socket))
{
if (!dynamic_cast<WebSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
WebSocket::WebSocket(WebSocket&& socket):
StreamSocket(std::move(socket))
{
}
#endif // POCO_NEW_STATE_ON_MOVE
WebSocket::WebSocket(const WebSocket& socket):
StreamSocket(socket)
{
}
WebSocket::~WebSocket()
{
}
@@ -80,6 +104,34 @@ WebSocket& WebSocket::operator = (const Socket& socket)
}
#ifdef POCO_NEW_STATE_ON_MOVE
WebSocket& WebSocket::operator = (Socket&& socket)
{
if (dynamic_cast<WebSocketImpl*>(socket.impl()))
Socket::operator = (std::move(socket));
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
WebSocket& WebSocket::operator = (WebSocket&& socket)
{
Socket::operator = (std::move(socket));
return *this;
}
#endif // POCO_NEW_STATE_ON_MOVE
WebSocket& WebSocket::operator = (const WebSocket& socket)
{
Socket::operator = (socket);
return *this;
}
void WebSocket::shutdown()
{
shutdown(WS_NORMAL_CLOSE);
-1
View File
@@ -12,7 +12,6 @@
//
#define NOMINMAX
#include "Poco/Net/WebSocketImpl.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/WebSocket.h"
+2253
View File
File diff suppressed because it is too large Load Diff
+114
View File
@@ -0,0 +1,114 @@
/*
* wepoll - epoll for Windows
* https://github.com/piscisaureus/wepoll
*
* Copyright 2012-2020, Bert Belder <bertbelder@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WEPOLL_H_
#define WEPOLL_H_
#ifndef WEPOLL_EXPORT
#define WEPOLL_EXPORT
#endif
#include <stdint.h>
enum EPOLL_EVENTS {
EPOLLIN = (int) (1U << 0),
EPOLLPRI = (int) (1U << 1),
EPOLLOUT = (int) (1U << 2),
EPOLLERR = (int) (1U << 3),
EPOLLHUP = (int) (1U << 4),
EPOLLRDNORM = (int) (1U << 6),
EPOLLRDBAND = (int) (1U << 7),
EPOLLWRNORM = (int) (1U << 8),
EPOLLWRBAND = (int) (1U << 9),
EPOLLMSG = (int) (1U << 10), /* Never reported. */
EPOLLRDHUP = (int) (1U << 13),
EPOLLONESHOT = (int) (1U << 31)
};
#define EPOLLIN (1U << 0)
#define EPOLLPRI (1U << 1)
#define EPOLLOUT (1U << 2)
#define EPOLLERR (1U << 3)
#define EPOLLHUP (1U << 4)
#define EPOLLRDNORM (1U << 6)
#define EPOLLRDBAND (1U << 7)
#define EPOLLWRNORM (1U << 8)
#define EPOLLWRBAND (1U << 9)
#define EPOLLMSG (1U << 10)
#define EPOLLRDHUP (1U << 13)
#define EPOLLONESHOT (1U << 31)
#define EPOLL_CTL_ADD 1
#define EPOLL_CTL_MOD 2
#define EPOLL_CTL_DEL 3
typedef void* HANDLE;
typedef uintptr_t SOCKET;
typedef union epoll_data {
void* ptr;
int fd;
uint32_t u32;
uint64_t u64;
SOCKET sock; /* Windows specific */
HANDLE hnd; /* Windows specific */
} epoll_data_t;
struct epoll_event {
uint32_t events; /* Epoll events and flags */
epoll_data_t data; /* User data variable */
};
#ifdef __cplusplus
extern "C" {
#endif
WEPOLL_EXPORT HANDLE epoll_create(int size);
WEPOLL_EXPORT HANDLE epoll_create1(int flags);
WEPOLL_EXPORT int epoll_close(HANDLE ephnd);
WEPOLL_EXPORT int epoll_ctl(HANDLE ephnd,
int op,
SOCKET sock,
struct epoll_event* event);
WEPOLL_EXPORT int epoll_wait(HANDLE ephnd,
struct epoll_event* events,
int maxevents,
int timeout);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WEPOLL_H_ */