initial import

This commit is contained in:
Guenter Obiltschnig
2006-07-11 16:33:40 +00:00
commit f476bd6b32
1463 changed files with 242402 additions and 0 deletions

226
Net/src/DNS.cpp Normal file
View File

@@ -0,0 +1,226 @@
//
// DNS.cpp
//
// $Id: //poco/1.1.0/Net/src/DNS.cpp#2 $
//
// Library: Net
// Package: NetCore
// Module: DNS
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/DNS.h"
#include "Net/NetException.h"
#include "Net/SocketAddress.h"
#include "Foundation/Environment.h"
#include "Foundation/NumberFormatter.h"
using Foundation::FastMutex;
using Foundation::Environment;
using Foundation::NumberFormatter;
using Foundation::IOException;
//
// Automatic initialization of Windows networking
//
#if defined(_WIN32)
namespace
{
class NetworkInitializer
{
public:
NetworkInitializer()
{
WORD version = MAKEWORD(2, 2);
WSADATA data;
WSAStartup(version, &data);
}
~NetworkInitializer()
{
WSACleanup();
}
};
static NetworkInitializer networkInitializer;
}
#endif // _WIN32
Net_BEGIN
DNS::DNSCache DNS::_cache;
Foundation::FastMutex DNS::_mutex;
const HostEntry& DNS::hostByName(const std::string& hostname)
{
FastMutex::ScopedLock lock(_mutex);
DNSCache::const_iterator it = _cache.find(hostname);
if (it != _cache.end())
{
return it->second;
}
else
{
#if defined(_WIN32) && defined(POCO_HAVE_IPv6)
struct addrinfo* pAI;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
if (getaddrinfo(hostname.c_str(), NULL, &hints, &pAI) == 0)
{
std::pair<DNSCache::iterator, bool> res = _cache.insert(std::pair<std::string, HostEntry>(hostname, HostEntry(pAI)));
freeaddrinfo(pAI);
return res.first->second;
}
#else
struct hostent* he = gethostbyname(hostname.c_str());
if (he)
{
std::pair<DNSCache::iterator, bool> res = _cache.insert(std::pair<std::string, HostEntry>(hostname, HostEntry(he)));
return res.first->second;
}
#endif
}
error(lastError(), hostname); // will throw an appropriate exception
throw NetException(); // to silence compiler
}
const HostEntry& DNS::hostByAddress(const IPAddress& address)
{
FastMutex::ScopedLock lock(_mutex);
#if defined(_WIN32) && defined(POCO_HAVE_IPv6)
SocketAddress sa(address, 0);
static char fqname[1024];
if (getnameinfo(sa.addr(), sa.length(), fqname, sizeof(fqname), NULL, 0, 0) == 0)
{
DNSCache::const_iterator it = _cache.find(std::string(fqname));
if (it != _cache.end())
{
return it->second;
}
else
{
struct addrinfo* pAI;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
if (getaddrinfo(fqname, NULL, &hints, &pAI) == 0)
{
std::pair<DNSCache::iterator, bool> res = _cache.insert(std::pair<std::string, HostEntry>(std::string(fqname), HostEntry(pAI)));
freeaddrinfo(pAI);
return res.first->second;
}
}
}
#else
struct hostent* he = gethostbyaddr(reinterpret_cast<const char*>(address.addr()), address.length(), address.af());
if (he)
{
std::pair<DNSCache::iterator, bool> res = _cache.insert(std::pair<std::string, HostEntry>(std::string(he->h_name), HostEntry(he)));
return res.first->second;
}
#endif
error(lastError(), address.toString()); // will throw an appropriate exception
throw NetException(); // to silence compiler
}
const HostEntry& DNS::resolve(const std::string& address)
{
IPAddress ip;
if (IPAddress::tryParse(address, ip))
return hostByAddress(ip);
else
return hostByName(address);
}
IPAddress DNS::resolveOne(const std::string& address)
{
const HostEntry& entry = resolve(address);
if (!entry.addresses().empty())
return entry.addresses()[0];
else
throw NoAddressFoundException(address);
}
const HostEntry& DNS::thisHost()
{
return hostByName(Environment::nodeName());
}
void DNS::flushCache()
{
FastMutex::ScopedLock lock(_mutex);
_cache.clear();
}
int DNS::lastError()
{
#if defined(_WIN32)
return GetLastError();
#else
return h_errno;
#endif
}
void DNS::error(int code, const std::string& arg)
{
switch (code)
{
case POCO_ESYSNOTREADY:
throw NetException("Net subsystem not ready");
case POCO_ENOTINIT:
throw NetException("Net subsystem not initialized");
case POCO_HOST_NOT_FOUND:
throw HostNotFoundException(arg);
case POCO_TRY_AGAIN:
throw DNSException("Temporary DNS error while resolving", arg);
case POCO_NO_RECOVERY:
throw DNSException("Non recoverable DNS error while resolving", arg);
case POCO_NO_DATA:
throw NoAddressFoundException(arg);
default:
throw IOException(NumberFormatter::format(code));
}
}
Net_END

129
Net/src/DatagramSocket.cpp Normal file
View File

@@ -0,0 +1,129 @@
//
// DatagramSocket.cpp
//
// $Id: //poco/1.1.0/Net/src/DatagramSocket.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: DatagramSocket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/DatagramSocket.h"
#include "Net/DatagramSocketImpl.h"
#include "Foundation/Exception.h"
using Foundation::InvalidArgumentException;
Net_BEGIN
DatagramSocket::DatagramSocket(): Socket(new DatagramSocketImpl)
{
}
DatagramSocket::DatagramSocket(IPAddress::Family family): Socket(new DatagramSocketImpl(family))
{
}
DatagramSocket::DatagramSocket(const SocketAddress& address, bool reuseAddress): Socket(new DatagramSocketImpl)
{
bind(address, reuseAddress);
}
DatagramSocket::DatagramSocket(const Socket& socket): Socket(socket)
{
if (!dynamic_cast<DatagramSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
DatagramSocket::DatagramSocket(SocketImpl* pImpl): Socket(pImpl)
{
if (!dynamic_cast<DatagramSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
DatagramSocket::~DatagramSocket()
{
}
DatagramSocket& DatagramSocket::operator = (const Socket& socket)
{
if (dynamic_cast<DatagramSocketImpl*>(socket.impl()))
Socket::operator = (socket);
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
void DatagramSocket::connect(const SocketAddress& address)
{
impl()->connect(address);
}
void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress)
{
impl()->bind(address, reuseAddress);
}
int DatagramSocket::sendBytes(const void* buffer, int length, int flags)
{
return impl()->sendBytes(buffer, length, flags);
}
int DatagramSocket::receiveBytes(void* buffer, int length, int flags)
{
return impl()->receiveBytes(buffer, length, flags);
}
int DatagramSocket::sendTo(const void* buffer, int length, const SocketAddress& address, int flags)
{
return impl()->sendTo(buffer, length, address, flags);
}
int DatagramSocket::receiveFrom(void* buffer, int length, SocketAddress& address, int flags)
{
return impl()->receiveFrom(buffer, length, address, flags);
}
Net_END

View File

@@ -0,0 +1,82 @@
//
// DatagramSocketImpl.cpp
//
// $Id: //poco/1.1.0/Net/src/DatagramSocketImpl.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: DatagramSocketImpl
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/DatagramSocketImpl.h"
#include "Net/NetException.h"
using Foundation::InvalidArgumentException;
Net_BEGIN
DatagramSocketImpl::DatagramSocketImpl()
{
init(AF_INET);
}
DatagramSocketImpl::DatagramSocketImpl(IPAddress::Family family)
{
if (family == IPAddress::IPv4)
init(AF_INET);
#if POCO_HAVE_IPv6
else if (family == IPAddress::IPv6)
init(AF_INET6);
#endif
else throw InvalidArgumentException("Invalid or unsupported address family passed to DatagramSocketImpl");
}
DatagramSocketImpl::DatagramSocketImpl(poco_socket_t sockfd): SocketImpl(sockfd)
{
}
DatagramSocketImpl::~DatagramSocketImpl()
{
}
void DatagramSocketImpl::init(int af)
{
initSocket(af, SOCK_DGRAM);
}
Net_END

277
Net/src/DialogSocket.cpp Normal file
View File

@@ -0,0 +1,277 @@
//
// DialogSocket.cpp
//
// $Id: //poco/1.1.0/Net/src/DialogSocket.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: DialogSocket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/DialogSocket.h"
#include <string.h>
#include <ctype.h>
Net_BEGIN
DialogSocket::DialogSocket():
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
}
DialogSocket::DialogSocket(const SocketAddress& address):
StreamSocket(address),
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
}
DialogSocket::DialogSocket(const Socket& socket):
StreamSocket(socket),
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
}
DialogSocket::~DialogSocket()
{
delete [] _pBuffer;
}
DialogSocket& DialogSocket::operator = (const Socket& socket)
{
StreamSocket::operator = (socket);
return *this;
}
void DialogSocket::sendByte(unsigned char ch)
{
sendBytes(&ch, 1);
}
void DialogSocket::sendString(const char* str)
{
sendBytes(str, (int) strlen(str));
}
void DialogSocket::sendString(const std::string& str)
{
sendBytes(str.data(), (int) str.length());
}
void DialogSocket::sendMessage(const std::string& message)
{
std::string line;
line.reserve(message.length() + 2);
line.append(message);
line.append("\r\n");
sendString(line);
}
void DialogSocket::sendMessage(const std::string& message, const std::string& arg)
{
std::string line;
line.reserve(message.length() + arg.length() + 3);
line.append(message);
if (!arg.empty())
{
line.append(" ");
line.append(arg);
}
line.append("\r\n");
sendString(line);
}
void DialogSocket::sendMessage(const std::string& message, const std::string& arg1, const std::string& arg2)
{
std::string line;
line.reserve(message.length() + arg1.length() +arg2.length() + 4);
line.append(message);
line.append(" ");
line.append(arg1);
if (!arg2.empty())
{
line.append(" ");
line.append(arg2);
}
line.append("\r\n");
sendString(line);
}
bool DialogSocket::receiveMessage(std::string& message)
{
message.clear();
return receiveLine(message);
}
int DialogSocket::receiveStatusMessage(std::string& message)
{
message.clear();
int status = receiveStatusLine(message);
if (status < 0)
{
while (status <= 0)
{
message += '\n';
status = receiveStatusLine(message);
}
}
return status;
}
int DialogSocket::get()
{
refill();
if (_pNext != _pEnd)
return *_pNext++;
else
return EOF_CHAR;
}
int DialogSocket::peek()
{
refill();
if (_pNext != _pEnd)
return *_pNext;
else
return EOF_CHAR;
}
void DialogSocket::synch()
{
sendUrgent(TELNET_DM);
}
void DialogSocket::sendTelnetCommand(unsigned char command)
{
unsigned char buffer[2];
buffer[0] = TELNET_IAC;
buffer[1] = command;
sendBytes(buffer, 2);
}
void DialogSocket::sendTelnetCommand(unsigned char command, unsigned char arg)
{
unsigned char buffer[3];
buffer[0] = TELNET_IAC;
buffer[1] = command;
buffer[2] = arg;
sendBytes(buffer, 3);
}
void DialogSocket::refill()
{
if (_pNext == _pEnd)
{
int n = receiveBytes(_pBuffer, RECEIVE_BUFFER_SIZE);
_pNext = _pBuffer;
_pEnd = _pBuffer + n;
}
}
void DialogSocket::allocBuffer()
{
_pBuffer = new char [RECEIVE_BUFFER_SIZE];
_pNext = _pBuffer;
_pEnd = _pBuffer;
}
bool DialogSocket::receiveLine(std::string& line)
{
// An old wisdom goes: be strict in what you emit
// and generous in what you accept.
int ch = get();
while (ch != EOF_CHAR && ch != '\r' && ch != '\n')
{
line += (char) ch;
ch = get();
}
if (ch == '\r' && peek() == '\n')
get();
else if (ch == EOF_CHAR)
return false;
return true;
}
int DialogSocket::receiveStatusLine(std::string& line)
{
int status = 0;
int ch = get();
if (ch != EOF_CHAR) line += (char) ch;
int n = 0;
while (isdigit(ch) && n < 3)
{
status *= 10;
status += ch - '0';
++n;
ch = get();
if (ch != EOF_CHAR) line += (char) ch;
}
if (n == 3)
{
if (ch == '-')
status = -status;
}
else status = 0;
if (ch != EOF_CHAR) receiveLine(line);
return status;
}
Net_END

View File

@@ -0,0 +1,507 @@
//
// FTPClientSession.cpp
//
// $Id: //poco/1.1.0/Net/src/FTPClientSession.cpp#2 $
//
// Library: Net
// Package: FTP
// Module: FTPClientSession
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/FTPClientSession.h"
#include "Net/SocketAddress.h"
#include "Net/SocketStream.h"
#include "Net/ServerSocket.h"
#include "Net/NetException.h"
#include "Foundation/NumberFormatter.h"
#include <ctype.h>
using Foundation::NumberFormatter;
Net_BEGIN
FTPClientSession::FTPClientSession(const StreamSocket& socket):
_controlSocket(socket),
_pDataStream(0),
_passiveMode(true),
_fileType(TYPE_BINARY),
_supports1738(true),
_isOpen(true),
_timeout(DEFAULT_TIMEOUT)
{
_controlSocket.setReceiveTimeout(_timeout);
}
FTPClientSession::FTPClientSession(const std::string& host, Foundation::UInt16 port):
_controlSocket(SocketAddress(host, port)),
_pDataStream(0),
_passiveMode(true),
_fileType(TYPE_BINARY),
_supports1738(true),
_isOpen(true),
_timeout(DEFAULT_TIMEOUT)
{
_controlSocket.setReceiveTimeout(_timeout);
}
FTPClientSession::~FTPClientSession()
{
try
{
close();
}
catch (...)
{
}
}
void FTPClientSession::setTimeout(const Foundation::Timespan& timeout)
{
_timeout = timeout;
_controlSocket.setReceiveTimeout(timeout);
}
Foundation::Timespan FTPClientSession::getTimeout() const
{
return _timeout;
}
void FTPClientSession::setPassive(bool flag)
{
_passiveMode = flag;
}
bool FTPClientSession::getPassive() const
{
return _passiveMode;
}
void FTPClientSession::login(const std::string& username, const std::string& password)
{
std::string response;
int status = _controlSocket.receiveStatusMessage(response);
if (!isPositiveCompletion(status)) throw FTPException("Cannot login to server", response);
status = sendCommand("USER", username, response);
if (isPositiveIntermediate(status))
status = sendCommand("PASS", password, response);
if (!isPositiveCompletion(status)) throw FTPException("Login denied", response);
setFileType(_fileType);
}
void FTPClientSession::close()
{
if (_isOpen)
{
try
{
endTransfer();
}
catch (...)
{
}
std::string response;
sendCommand("QUIT", response);
_controlSocket.close();
_isOpen = false;
}
}
void FTPClientSession::setFileType(FTPClientSession::FileType type)
{
std::string response;
int status = sendCommand("TYPE", (type == TYPE_TEXT ? "A" : "I"), response);
if (!isPositiveCompletion(status)) throw FTPException("Cannot set file type", response);
_fileType = type;
}
FTPClientSession::FileType FTPClientSession::getFileType() const
{
return _fileType;
}
std::string FTPClientSession::systemType()
{
std::string response;
int status = sendCommand("SYST", response);
if (isPositiveCompletion(status))
return response.substr(4);
else
throw FTPException("Cannot get remote system type", response);
}
void FTPClientSession::setWorkingDirectory(const std::string& path)
{
std::string response;
int status = sendCommand("CWD", path, response);
if (!isPositiveCompletion(status)) throw FTPException("Cannot change directory", response);
}
std::string FTPClientSession::getWorkingDirectory()
{
std::string response;
int status = sendCommand("PWD", response);
if (isPositiveCompletion(status))
return extractPath(response);
else
throw FTPException("Cannot get current working directory", response);
}
void FTPClientSession::cdup()
{
std::string response;
int status = sendCommand("CDUP", response);
if (!isPositiveCompletion(status)) throw FTPException("Cannot change directory", response);
}
void FTPClientSession::rename(const std::string& oldName, const std::string& newName)
{
std::string response;
int status = sendCommand("RNFR", oldName, response);
if (!isPositiveIntermediate(status)) throw FTPException(std::string("Cannot rename ") + oldName, response);
status = sendCommand("RNTO", newName, response);
if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot rename to ") + newName, response);
}
void FTPClientSession::remove(const std::string& path)
{
std::string response;
int status = sendCommand("DELE", path, response);
if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot remove " + path), response);
}
void FTPClientSession::createDirectory(const std::string& path)
{
std::string response;
int status = sendCommand("MKD", path, response);
if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot create directory ") + path, response);
}
void FTPClientSession::removeDirectory(const std::string& path)
{
std::string response;
int status = sendCommand("RMD", path, response);
if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot remove directory ") + path, response);
}
std::istream& FTPClientSession::beginDownload(const std::string& path)
{
delete _pDataStream;
_pDataStream = 0;
_pDataStream = new SocketStream(establishDataConnection("RETR", path));
return *_pDataStream;
}
void FTPClientSession::endDownload()
{
endTransfer();
}
std::ostream& FTPClientSession::beginUpload(const std::string& path)
{
delete _pDataStream;
_pDataStream = 0;
_pDataStream = new SocketStream(establishDataConnection("STOR", path));
return *_pDataStream;
}
void FTPClientSession::endUpload()
{
endTransfer();
}
std::istream& FTPClientSession::beginList(const std::string& path, bool extended)
{
delete _pDataStream;
_pDataStream = 0;
_pDataStream = new SocketStream(establishDataConnection(extended ? "LIST" : "NLST", path));
return *_pDataStream;
}
void FTPClientSession::endList()
{
endTransfer();
}
void FTPClientSession::abort()
{
_controlSocket.sendByte(DialogSocket::TELNET_IP);
_controlSocket.synch();
std::string response;
int status = sendCommand("ABOR", response);
if (status == 426)
status = _controlSocket.receiveStatusMessage(response);
if (status != 226) throw FTPException("Cannot abort transfer", response);
}
int FTPClientSession::sendCommand(const std::string& command, std::string& response)
{
_controlSocket.sendMessage(command);
return _controlSocket.receiveStatusMessage(response);
}
int FTPClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response)
{
_controlSocket.sendMessage(command, arg);
return _controlSocket.receiveStatusMessage(response);
}
std::string FTPClientSession::extractPath(const std::string& response)
{
std::string path;
std::string::const_iterator it = response.begin();
std::string::const_iterator end = response.end();
while (it != end && *it != '"') ++it;
if (it != end)
{
++it;
while (it != end)
{
if (*it == '"')
{
++it;
if (it != end && *it != '"') break;
}
path += *it++;
}
}
return path;
}
StreamSocket FTPClientSession::establishDataConnection(const std::string& command, const std::string& arg)
{
if (_passiveMode)
return passiveDataConnection(command, arg);
else
return activeDataConnection(command, arg);
}
StreamSocket FTPClientSession::activeDataConnection(const std::string& command, const std::string& arg)
{
ServerSocket server(SocketAddress(_controlSocket.address().host(), 0));
sendPortCommand(server.address());
std::string response;
int status = sendCommand(command, arg, response);
if (!isPositivePreliminary(status)) throw FTPException(command + " command failed", response);
if (server.poll(_timeout, Socket::SELECT_READ))
return server.acceptConnection();
else
throw FTPException("The server has not initiated a data connection");
}
StreamSocket FTPClientSession::passiveDataConnection(const std::string& command, const std::string& arg)
{
SocketAddress sa(sendPassiveCommand());
StreamSocket sock(sa);
std::string response;
int status = sendCommand(command, arg, response);
if (!isPositivePreliminary(status)) throw FTPException(command + " command failed", response);
return sock;
}
void FTPClientSession::sendPortCommand(const SocketAddress& addr)
{
if (_supports1738)
{
if (sendEPRT(addr))
return;
else
_supports1738 = false;
}
sendPORT(addr);
}
SocketAddress FTPClientSession::sendPassiveCommand()
{
SocketAddress addr;
if (_supports1738)
{
if (sendEPSV(addr))
return addr;
else
_supports1738 = false;
}
sendPASV(addr);
return addr;
}
bool FTPClientSession::sendEPRT(const SocketAddress& addr)
{
std::string arg("|");
arg += addr.af() == AF_INET ? '1' : '2';
arg += '|';
arg += addr.host().toString();
arg += '|';
arg += NumberFormatter::format(addr.port());
arg += '|';
std::string response;
int status = sendCommand("EPRT", arg, response);
if (isPositiveCompletion(status))
return true;
else if (isPermanentNegative(status))
return false;
else
throw FTPException("EPRT command failed", response);
}
void FTPClientSession::sendPORT(const SocketAddress& addr)
{
std::string arg(addr.host().toString());
for (std::string::iterator it = arg.begin(); it != arg.end(); ++it)
{
if (*it == '.') *it = ',';
}
arg += ',';
Foundation::UInt16 port = addr.port();
arg += NumberFormatter::format(port/256);
arg += ',';
arg += NumberFormatter::format(port % 256);
std::string response;
int status = sendCommand("PORT", arg, response);
if (!isPositiveCompletion(status)) throw FTPException("PORT command failed", response);
}
bool FTPClientSession::sendEPSV(SocketAddress& addr)
{
std::string response;
int status = sendCommand("EPSV", response);
if (isPositiveCompletion(status))
{
parseExtAddress(response, addr);
return true;
}
else if (isPermanentNegative(status))
{
return false;
}
else throw FTPException("EPSV command failed", response);
}
void FTPClientSession::sendPASV(SocketAddress& addr)
{
std::string response;
int status = sendCommand("PASV", response);
if (!isPositiveCompletion(status)) throw FTPException("PASV command failed", response);
parseAddress(response, addr);
}
void FTPClientSession::parseAddress(const std::string& str, SocketAddress& addr)
{
std::string::const_iterator it = str.begin();
std::string::const_iterator end = str.end();
while (it != end && *it != '(') ++it;
if (it != end) ++it;
std::string host;
while (it != end && isdigit(*it)) host += *it++;
if (it != end && *it == ',') { host += '.'; ++it; }
while (it != end && isdigit(*it)) host += *it++;
if (it != end && *it == ',') { host += '.'; ++it; }
while (it != end && isdigit(*it)) host += *it++;
if (it != end && *it == ',') { host += '.'; ++it; }
while (it != end && isdigit(*it)) host += *it++;
if (it != end && *it == ',') ++it;
Foundation::UInt16 portHi = 0;
while (it != end && isdigit(*it)) { portHi *= 10; portHi += *it++ - '0'; }
if (it != end && *it == ',') ++it;
Foundation::UInt16 portLo = 0;
while (it != end && isdigit(*it)) { portLo *= 10; portLo += *it++ - '0'; }
addr = SocketAddress(host, portHi*256 + portLo);
}
void FTPClientSession::parseExtAddress(const std::string& str, SocketAddress& addr)
{
std::string::const_iterator it = str.begin();
std::string::const_iterator end = str.end();
while (it != end && *it != '(') ++it;
if (it != end) ++it;
char delim = '|';
if (it != end) delim = *it++;
if (it != end && *it == delim) ++it;
if (it != end && *it == delim) ++it;
Foundation::UInt16 port = 0;
while (it != end && isdigit(*it)) { port *= 10; port += *it++ - '0'; }
addr = SocketAddress(_controlSocket.peerAddress().host(), port);
}
void FTPClientSession::endTransfer()
{
if (_pDataStream)
{
delete _pDataStream;
_pDataStream = 0;
std::string response;
int status = _controlSocket.receiveStatusMessage(response);
if (!isPositiveCompletion(status)) throw FTPException("Data transfer failed", response);
}
}
Net_END

View File

@@ -0,0 +1,256 @@
//
// FTPStreamFactory.cpp
//
// $Id: //poco/1.1.0/Net/src/FTPStreamFactory.cpp#2 $
//
// Library: Net
// Package: FTP
// Module: FTPStreamFactory
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/FTPStreamFactory.h"
#include "Net/FTPClientSession.h"
#include "Net/NetException.h"
#include "Foundation/URI.h"
#include "Foundation/URIStreamOpener.h"
#include "Foundation/UnbufferedStreamBuf.h"
#include "Foundation/Path.h"
using Foundation::URIStreamFactory;
using Foundation::URI;
using Foundation::URIStreamOpener;
using Foundation::UnbufferedStreamBuf;
using Foundation::Path;
Net_BEGIN
class FTPStreamBuf: public UnbufferedStreamBuf
{
public:
FTPStreamBuf(std::istream& istr):
_istr(istr)
{
}
~FTPStreamBuf()
{
}
private:
int readFromDevice()
{
return _istr.get();
}
std::istream& _istr;
};
class FTPIOS: public virtual std::ios
{
public:
FTPIOS(std::istream& istr):
_buf(istr)
{
poco_ios_init(&_buf);
}
~FTPIOS()
{
}
FTPStreamBuf* rdbuf()
{
return &_buf;
}
protected:
FTPStreamBuf _buf;
};
class FTPStream: public FTPIOS, public std::istream
{
public:
FTPStream(std::istream& istr, FTPClientSession* pSession):
FTPIOS(istr),
std::istream(&_buf),
_pSession(pSession)
{
}
~FTPStream()
{
delete _pSession;
}
private:
FTPClientSession* _pSession;
};
FTPPasswordProvider::FTPPasswordProvider()
{
}
FTPPasswordProvider::~FTPPasswordProvider()
{
}
std::string FTPStreamFactory::_anonymousPassword("poco@localhost");
FTPPasswordProvider* FTPStreamFactory::_pPasswordProvider(0);
FTPStreamFactory::FTPStreamFactory()
{
}
FTPStreamFactory::~FTPStreamFactory()
{
}
std::istream* FTPStreamFactory::open(const URI& uri)
{
poco_assert (uri.getScheme() == "ftp");
FTPClientSession* pSession = new FTPClientSession(uri.getHost(), uri.getPort());
try
{
std::string username;
std::string password;
getUserInfo(uri, username, password);
std::string path;
char type;
getPathAndType(uri, path, type);
pSession->login(username, password);
if (type == 'a')
pSession->setFileType(FTPClientSession::TYPE_TEXT);
Path p(path, Path::PATH_UNIX);
p.makeFile();
for (int i = 0; i < p.depth(); ++i)
pSession->setWorkingDirectory(p[i]);
std::string file(p.getFileName());
std::istream& istr = (type == 'd' ? pSession->beginList(file) : pSession->beginDownload(file));
return new FTPStream(istr, pSession);
}
catch (...)
{
delete pSession;
throw;
}
}
void FTPStreamFactory::setAnonymousPassword(const std::string& password)
{
_anonymousPassword = password;
}
const std::string& FTPStreamFactory::getAnonymousPassword()
{
return _anonymousPassword;
}
void FTPStreamFactory::setPasswordProvider(FTPPasswordProvider* pProvider)
{
_pPasswordProvider = pProvider;
}
FTPPasswordProvider* FTPStreamFactory::getPasswordProvider()
{
return _pPasswordProvider;
}
void FTPStreamFactory::splitUserInfo(const std::string& userInfo, std::string& username, std::string& password)
{
std::string::size_type pos = userInfo.find(':');
if (pos != std::string::npos)
{
username.assign(userInfo, 0, pos++);
password.assign(userInfo, pos, userInfo.size() - pos);
}
else username = userInfo;
}
void FTPStreamFactory::getUserInfo(const URI& uri, std::string& username, std::string& password)
{
splitUserInfo(uri.getUserInfo(), username, password);
if (username.empty())
{
username = "anonymous";
password = _anonymousPassword;
}
else if (password.empty())
{
if (_pPasswordProvider)
password = _pPasswordProvider->password(username, uri.getHost());
else
throw FTPException(std::string("Password required for ") + username + "@" + uri.getHost());
}
}
void FTPStreamFactory::getPathAndType(const Foundation::URI& uri, std::string& path, char& type)
{
path = uri.getPath();
type = 'i';
std::string::size_type pos = path.rfind(';');
if (pos != std::string::npos)
{
if (path.length() == pos + 7 && path.compare(pos + 1, 5, "type=") == 0)
{
type = path[pos + 6];
path.resize(pos);
}
}
}
void FTPStreamFactory::registerFactory()
{
URIStreamOpener::defaultOpener().registerStreamFactory("ftp", new FTPStreamFactory);
}
Net_END

View File

@@ -0,0 +1,87 @@
//
// FilePartSource.cpp
//
// $Id: //poco/1.1.0/Net/src/FilePartSource.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: FilePartSource
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/FilePartSource.h"
#include "Foundation/Path.h"
#include "Foundation/Exception.h"
using Foundation::Path;
using Foundation::OpenFileException;
Net_BEGIN
FilePartSource::FilePartSource(const std::string& path):
_istr(path.c_str(), std::ios::in | std::ios::binary)
{
Path p(path);
_filename = p.getFileName();
if (!_istr.good())
throw OpenFileException(path);
}
FilePartSource::FilePartSource(const std::string& path, const std::string& mediaType):
PartSource(mediaType),
_istr(path.c_str(), std::ios::in | std::ios::binary)
{
Path p(path);
_filename = p.getFileName();
if (!_istr.good())
throw OpenFileException(path);
}
FilePartSource::~FilePartSource()
{
}
std::istream& FilePartSource::stream()
{
return _istr;
}
const std::string& FilePartSource::filename()
{
return _filename;
}
Net_END

358
Net/src/HTMLForm.cpp Normal file
View File

@@ -0,0 +1,358 @@
//
// HTMLForm.cpp
//
// $Id: //poco/1.1.0/Net/src/HTMLForm.cpp#2 $
//
// Library: Net
// Package: HTML
// Module: HTMLForm
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTMLForm.h"
#include "Net/HTTPRequest.h"
#include "Net/PartSource.h"
#include "Net/PartHandler.h"
#include "Net/MultipartWriter.h"
#include "Net/MultipartReader.h"
#include "Net/NullPartHandler.h"
#include "Foundation/NullStream.h"
#include "Foundation/StreamCopier.h"
#include "Foundation/Exception.h"
#include "Foundation/URI.h"
#include "Foundation/String.h"
#include <sstream>
#include <ctype.h>
using Foundation::NullInputStream;
using Foundation::StreamCopier;
using Foundation::SyntaxException;
using Foundation::URI;
using Foundation::icompare;
Net_BEGIN
const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded";
const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data";
HTMLForm::HTMLForm():
_encoding(ENCODING_URL)
{
}
HTMLForm::HTMLForm(const std::string& encoding):
_encoding(encoding)
{
}
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& istr, PartHandler& handler)
{
load(request, istr, handler);
}
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& istr)
{
load(request, istr);
}
HTMLForm::HTMLForm(const HTTPRequest& request)
{
load(request);
}
HTMLForm::~HTMLForm()
{
for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it)
{
delete it->pSource;
}
}
void HTMLForm::setEncoding(const std::string& encoding)
{
_encoding = encoding;
}
void HTMLForm::addPart(const std::string& name, PartSource* pSource)
{
poco_check_ptr (pSource);
Part part;
part.name = name;
part.pSource = pSource;
_parts.push_back(part);
}
void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler)
{
if (request.getMethod() == HTTPRequest::HTTP_GET)
{
URI uri(request.getURI());
std::istringstream istr(uri.getRawQuery());
readUrl(istr);
}
else
{
std::string mediaType;
NameValueCollection params;
MessageHeader::splitParameters(request.getContentType(), mediaType, params);
_encoding = mediaType;
if (_encoding == ENCODING_MULTIPART)
{
_boundary = params["boundary"];
readMultipart(requestBody, handler);
}
else
{
readUrl(requestBody);
}
}
}
void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody)
{
NullPartHandler nah;
load(request, requestBody, nah);
}
void HTMLForm::load(const HTTPRequest& request)
{
NullPartHandler nah;
NullInputStream nis;
load(request, nis, nah);
}
void HTMLForm::read(std::istream& istr, PartHandler& handler)
{
if (_encoding == ENCODING_URL)
readUrl(istr);
else
readMultipart(istr, handler);
}
void HTMLForm::prepareSubmit(HTTPRequest& request)
{
if (request.getMethod() == HTTPRequest::HTTP_GET)
{
std::string uri = request.getURI();
std::ostringstream ostr;
write(ostr);
uri.append("?");
uri.append(ostr.str());
request.setURI(uri);
}
else if (request.getMethod() == HTTPRequest::HTTP_POST)
{
if (_encoding == ENCODING_URL)
{
request.setContentType(_encoding);
}
else
{
_boundary = MultipartWriter::createBoundary();
std::string ct(_encoding);
ct.append("; boundary=\"");
ct.append(_boundary);
ct.append("\"");
request.setContentType(ct);
}
if (request.getVersion() == HTTPMessage::HTTP_1_0)
{
request.setKeepAlive(false);
request.setChunkedTransferEncoding(false);
}
else
{
request.setChunkedTransferEncoding(true);
}
}
}
void HTMLForm::write(std::ostream& ostr, const std::string& boundary)
{
if (_encoding == ENCODING_URL)
{
writeUrl(ostr);
}
else
{
_boundary = boundary;
writeMultipart(ostr);
}
}
void HTMLForm::write(std::ostream& ostr)
{
if (_encoding == ENCODING_URL)
writeUrl(ostr);
else
writeMultipart(ostr);
}
void HTMLForm::readUrl(std::istream& istr)
{
static const int eof = std::char_traits<char>::eof();
int ch = istr.get();
while (ch != eof)
{
std::string name;
std::string value;
while (ch != eof && ch != '=' && ch != '&')
{
if (ch == '+') ch = ' ';
name += (char) ch;
ch = istr.get();
}
if (ch == '=')
{
ch = istr.get();
while (ch != eof && ch != '&')
{
if (ch == '+') ch = ' ';
value += (char) ch;
ch = istr.get();
}
}
std::string decodedName;
std::string decodedValue;
URI::decode(name, decodedName);
URI::decode(value, decodedValue);
set(decodedName, decodedValue);
if (ch == '&') ch = istr.get();
}
}
void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler)
{
static const int eof = std::char_traits<char>::eof();
MultipartReader reader(istr, _boundary);
while (reader.hasNextPart())
{
MessageHeader header;
reader.nextPart(header);
std::string disp;
NameValueCollection params;
if (header.has("Content-Disposition"))
{
std::string cd = header.get("Content-Disposition");
MessageHeader::splitParameters(cd, disp, params);
}
if (icompare(disp, "file") == 0)
{
handler.handlePart(header, reader.stream());
}
else
{
std::string name = params["name"];
std::string value;
std::istream& istr = reader.stream();
int ch = istr.get();
while (ch != eof)
{
value += (char) ch;
ch = istr.get();
}
set(name, value);
}
}
}
void HTMLForm::writeUrl(std::ostream& ostr)
{
for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it)
{
if (it != begin()) ostr << "&";
std::string name;
URI::encode(it->first, "=&", name);
std::string value;
URI::encode(it->second, "=&", value);
ostr << name << "=" << value;
}
}
void HTMLForm::writeMultipart(std::ostream& ostr)
{
MultipartWriter writer(ostr, _boundary);
for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it)
{
MessageHeader header;
std::string disp("form-data; name=\"");
disp.append(it->first);
disp.append("\"");
header.set("Content-Disposition", disp);
writer.nextPart(header);
ostr << it->second;
}
for (PartVec::iterator ita = _parts.begin(); ita != _parts.end(); ++ita)
{
MessageHeader header;
std::string disp("file; name=\"");
disp.append(ita->name);
disp.append("\"");
std::string filename = ita->pSource->filename();
if (!filename.empty())
{
disp.append("; filename=\"");
disp.append(filename);
disp.append("\"");
}
header.set("Content-Disposition", disp);
header.set("Content-Type", ita->pSource->mediaType());
writer.nextPart(header);
StreamCopier::copyStream(ita->pSource->stream(), ostr);
}
writer.close();
_boundary = writer.boundary();
}
Net_END

View File

@@ -0,0 +1,124 @@
//
// HTTPBasicCredentials.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPBasicCredentials.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPBasicCredentials
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPBasicCredentials.h"
#include "Net/HTTPRequest.h"
#include "Net/NetException.h"
#include "Foundation/Base64Encoder.h"
#include "Foundation/Base64Decoder.h"
#include "Foundation/String.h"
#include <sstream>
using Foundation::Base64Decoder;
using Foundation::Base64Encoder;
using Foundation::icompare;
Net_BEGIN
const std::string HTTPBasicCredentials::SCHEME = "Basic";
HTTPBasicCredentials::HTTPBasicCredentials()
{
}
HTTPBasicCredentials::HTTPBasicCredentials(const std::string& username, const std::string& password):
_username(username),
_password(password)
{
}
HTTPBasicCredentials::HTTPBasicCredentials(const HTTPRequest& request)
{
static const int eof = std::char_traits<char>::eof();
std::string scheme;
std::string info;
request.getCredentials(scheme, info);
if (icompare(scheme, SCHEME) == 0)
{
std::istringstream istr(info);
Base64Decoder decoder(istr);
int ch = decoder.get();
while (ch != eof && ch != ':')
{
_username += (char) ch;
ch = decoder.get();
}
if (ch == ':') ch = decoder.get();
while (ch != eof)
{
_password += (char) ch;
ch = decoder.get();
}
}
else throw NotAuthenticatedException("Basic authentication expected");
}
HTTPBasicCredentials::~HTTPBasicCredentials()
{
}
void HTTPBasicCredentials::setUsername(const std::string& username)
{
_username = username;
}
void HTTPBasicCredentials::setPassword(const std::string& password)
{
_password = password;
}
void HTTPBasicCredentials::authenticate(HTTPRequest& request)
{
std::ostringstream ostr;
Base64Encoder encoder(ostr);
encoder << _username << ":" << _password;
encoder.close();
request.setCredentials(SCHEME, ostr.str());
}
Net_END

View File

@@ -0,0 +1,65 @@
//
// HTTPBufferAllocator.cpp
//
// $Id: //poco/Main/template/class.cpp#4 $
//
// Library: Net
// Package: HTTP
// Module: HTTPBufferAllocator
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPBufferAllocator.h"
using Foundation::MemoryPool;
Net_BEGIN
MemoryPool HTTPBufferAllocator::_pool(HTTPBufferAllocator::BUFFER_SIZE, 16);
char* HTTPBufferAllocator::allocate(std::streamsize size)
{
poco_assert_dbg (size == BUFFER_SIZE);
return reinterpret_cast<char*>(_pool.get());
}
void HTTPBufferAllocator::deallocate(char* ptr, std::streamsize size)
{
poco_assert_dbg (size == BUFFER_SIZE);
_pool.release(ptr);
}
Net_END

View File

@@ -0,0 +1,213 @@
//
// HTTPChunkedStream.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPChunkedStream.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPChunkedStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPChunkedStream.h"
#include "Net/HTTPSession.h"
#include "Foundation/NumberFormatter.h"
#include "Foundation/NumberParser.h"
#include <ctype.h>
using Foundation::NumberFormatter;
using Foundation::NumberParser;
Net_BEGIN
//
// HTTPChunkedStreamBuf
//
HTTPChunkedStreamBuf::HTTPChunkedStreamBuf(HTTPSession& session, openmode mode):
HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode),
_session(session),
_mode(mode),
_chunk(0)
{
}
HTTPChunkedStreamBuf::~HTTPChunkedStreamBuf()
{
}
void HTTPChunkedStreamBuf::close()
{
if (_mode & std::ios::out)
{
sync();
_session.write("0\r\n", 3);
}
}
int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
static const int eof = std::char_traits<char>::eof();
if (_chunk == 0)
{
int ch = _session.get();
while (isspace(ch)) ch = _session.get();
std::string chunkLen;
while (isxdigit(ch)) { chunkLen += (char) ch; ch = _session.get(); }
while (ch != eof && ch != '\n') ch = _session.get();
unsigned chunk;
if (NumberParser::tryParseHex(chunkLen, chunk))
_chunk = (std::streamsize) chunk;
else
return eof;
}
if (_chunk > 0)
{
if (length > _chunk) length = _chunk;
int n = _session.read(buffer, length);
if (n > 0) _chunk -= n;
return n;
}
else return 0;
}
int HTTPChunkedStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
std::string chunkSize(NumberFormatter::formatHex(length));
chunkSize.append("\r\n");
_session.write(chunkSize.data(), (std::streamsize) chunkSize.length());
_session.write(buffer, length);
_session.write("\r\n", 2);
return length;
}
//
// HTTPChunkedIOS
//
HTTPChunkedIOS::HTTPChunkedIOS(HTTPSession& session, HTTPChunkedStreamBuf::openmode mode):
_buf(session, mode)
{
poco_ios_init(&_buf);
}
HTTPChunkedIOS::~HTTPChunkedIOS()
{
try
{
_buf.close();
}
catch (...)
{
}
}
HTTPChunkedStreamBuf* HTTPChunkedIOS::rdbuf()
{
return &_buf;
}
//
// HTTPChunkedInputStream
//
Foundation::MemoryPool HTTPChunkedInputStream::_pool(sizeof(HTTPChunkedInputStream));
HTTPChunkedInputStream::HTTPChunkedInputStream(HTTPSession& session):
HTTPChunkedIOS(session, std::ios::in),
std::istream(&_buf)
{
}
HTTPChunkedInputStream::~HTTPChunkedInputStream()
{
}
void* HTTPChunkedInputStream::operator new(size_t size)
{
return _pool.get();
}
void HTTPChunkedInputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
//
// HTTPChunkedOutputStream
//
Foundation::MemoryPool HTTPChunkedOutputStream::_pool(sizeof(HTTPChunkedOutputStream));
HTTPChunkedOutputStream::HTTPChunkedOutputStream(HTTPSession& session):
HTTPChunkedIOS(session, std::ios::out),
std::ostream(&_buf)
{
}
HTTPChunkedOutputStream::~HTTPChunkedOutputStream()
{
}
void* HTTPChunkedOutputStream::operator new(size_t size)
{
return _pool.get();
}
void HTTPChunkedOutputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
Net_END

View File

@@ -0,0 +1,269 @@
//
// HTTPClientSession.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPClientSession.cpp#2 $
//
// Library: Net
// Package: HTTPClient
// Module: HTTPClientSession
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPClientSession.h"
#include "Net/HTTPRequest.h"
#include "Net/HTTPResponse.h"
#include "Net/HTTPHeaderStream.h"
#include "Net/HTTPStream.h"
#include "Net/HTTPFixedLengthStream.h"
#include "Net/HTTPChunkedStream.h"
#include "Net/NetException.h"
#include "Foundation/NumberFormatter.h"
using Foundation::NumberFormatter;
using Foundation::IllegalStateException;
Net_BEGIN
HTTPClientSession::HTTPClientSession():
_port(HTTPSession::HTTP_PORT),
_proxyPort(HTTPSession::HTTP_PORT),
_reconnect(false),
_expectResponseBody(false),
_pRequestStream(0),
_pResponseStream(0)
{
}
HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
HTTPSession(socket),
_port(HTTPSession::HTTP_PORT),
_proxyPort(HTTPSession::HTTP_PORT),
_reconnect(false),
_expectResponseBody(false),
_pRequestStream(0),
_pResponseStream(0)
{
}
HTTPClientSession::HTTPClientSession(const std::string& host, Foundation::UInt16 port):
_host(host),
_port(port),
_proxyPort(HTTPSession::HTTP_PORT),
_reconnect(false),
_expectResponseBody(false),
_pRequestStream(0),
_pResponseStream(0)
{
}
HTTPClientSession::~HTTPClientSession()
{
delete _pRequestStream;
delete _pResponseStream;
}
void HTTPClientSession::setHost(const std::string& host)
{
if (!connected())
_host = host;
else
throw IllegalStateException("Cannot set the host for an already connected session");
}
void HTTPClientSession::setPort(Foundation::UInt16 port)
{
if (!connected())
_port = port;
else
throw IllegalStateException("Cannot set the port number for an already connected session");
}
void HTTPClientSession::setProxy(const std::string& host, Foundation::UInt16 port)
{
if (!connected())
{
_proxyHost = host;
_proxyPort = port;
}
else throw IllegalStateException("Cannot set the proxy host and port for an already connected session");
}
void HTTPClientSession::setProxyHost(const std::string& host)
{
if (!connected())
_proxyHost = host;
else
throw IllegalStateException("Cannot set the proxy host for an already connected session");
}
void HTTPClientSession::setProxyPort(Foundation::UInt16 port)
{
if (!connected())
_proxyPort = port;
else
throw IllegalStateException("Cannot set the proxy port number for an already connected session");
}
std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request)
{
delete _pResponseStream;
_pResponseStream = 0;
bool keepAlive = getKeepAlive();
if (connected() && !keepAlive)
close();
if (!connected())
reconnect();
request.setKeepAlive(keepAlive);
request.setHost(_host, _port);
if (!_proxyHost.empty())
request.setURI(getHostInfo() + request.getURI());
HTTPHeaderOutputStream hos(*this);
_reconnect = keepAlive;
request.write(hos);
_reconnect = false;
_expectResponseBody = request.getMethod() != HTTPRequest::HTTP_HEAD;
if (request.getChunkedTransferEncoding())
_pRequestStream = new HTTPChunkedOutputStream(*this);
else if (request.getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
_pRequestStream = new HTTPFixedLengthOutputStream(*this, request.getContentLength());
else if (request.getMethod() == HTTPRequest::HTTP_GET || request.getMethod() == HTTPRequest::HTTP_HEAD)
_pRequestStream = new HTTPFixedLengthOutputStream(*this, 0);
else
_pRequestStream = new HTTPOutputStream(*this);
return *_pRequestStream;
}
std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response)
{
delete _pRequestStream;
_pRequestStream = 0;
response.clear();
HTTPHeaderInputStream his(*this);
response.read(his);
if (!_expectResponseBody)
_pResponseStream = new HTTPFixedLengthInputStream(*this, 0);
else if (response.getChunkedTransferEncoding())
_pResponseStream = new HTTPChunkedInputStream(*this);
else if (response.getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
_pResponseStream = new HTTPFixedLengthInputStream(*this, response.getContentLength());
else
_pResponseStream = new HTTPInputStream(*this);
return *_pResponseStream;
}
int HTTPClientSession::write(const char* buffer, std::streamsize length)
{
try
{
return HTTPSession::write(buffer, length);
}
catch (NetException&)
{
if (_reconnect)
{
close();
reconnect();
return HTTPSession::write(buffer, length);
}
else throw;
}
}
void HTTPClientSession::reconnect()
{
if (_proxyHost.empty())
{
SocketAddress addr(_host, _port);
connect(addr);
}
else
{
SocketAddress addr(_proxyHost, _proxyPort);
connect(addr);
}
}
std::string HTTPClientSession::getHostInfo() const
{
std::string result("http://");
result.append(_host);
result.append(":");
result.append(NumberFormatter::format(_port));
return result;
}
void HTTPClientSession::deleteResponseStream()
{
delete _pResponseStream;
_pResponseStream = 0;
}
void HTTPClientSession::deleteRequestStream()
{
delete _pRequestStream;
_pRequestStream = 0;
}
void HTTPClientSession::setResponseStream(std::istream* pRespStream)
{
poco_assert( !_pResponseStream);
_pResponseStream = pRespStream;
}
void HTTPClientSession::setRequestStream(std::ostream* pRequestStream)
{
poco_assert (!_pRequestStream);
_pRequestStream = pRequestStream;
}
Net_END

291
Net/src/HTTPCookie.cpp Normal file
View File

@@ -0,0 +1,291 @@
//
// HTTPCookie.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPCookie.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPCookie
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPCookie.h"
#include "Net/NameValueCollection.h"
#include "Foundation/Timestamp.h"
#include "Foundation/DateTime.h"
#include "Foundation/DateTimeFormatter.h"
#include "Foundation/DateTimeFormat.h"
#include "Foundation/DateTimeParser.h"
#include "Foundation/NumberFormatter.h"
#include "Foundation/NumberParser.h"
#include "Foundation/String.h"
using Foundation::Timestamp;
using Foundation::DateTime;
using Foundation::DateTimeFormatter;
using Foundation::DateTimeFormat;
using Foundation::DateTimeParser;
using Foundation::NumberFormatter;
using Foundation::NumberParser;
using Foundation::icompare;
Net_BEGIN
HTTPCookie::HTTPCookie():
_version(0),
_secure(false),
_maxAge(-1)
{
}
HTTPCookie::HTTPCookie(const std::string& name):
_version(0),
_name(name),
_secure(false),
_maxAge(-1)
{
}
HTTPCookie::HTTPCookie(const NameValueCollection& nvc):
_version(0),
_secure(false),
_maxAge(-1)
{
for (NameValueCollection::ConstIterator it = nvc.begin(); it != nvc.end(); ++it)
{
const std::string& name = it->first;
const std::string& value = it->second;
if (icompare(name, "comment") == 0)
{
setComment(value);
}
else if (icompare(name, "domain") == 0)
{
setDomain(value);
}
else if (icompare(name, "path") == 0)
{
setPath(value);
}
else if (icompare(name, "max-age") == 0)
{
setMaxAge(NumberParser::parse(value));
}
else if (icompare(name, "secure") == 0)
{
setSecure(true);
}
else if (icompare(name, "expires") == 0)
{
int tzd;
DateTime exp = DateTimeParser::parse(value, tzd);
Timestamp now;
setMaxAge((int) ((exp.timestamp() - now)/1000000));
}
else if (icompare(name, "version") == 0)
{
setVersion(NumberParser::parse(value));
}
else
{
setName(name);
setValue(value);
}
}
}
HTTPCookie::HTTPCookie(const std::string& name, const std::string& value):
_version(0),
_name(name),
_value(value),
_secure(false),
_maxAge(-1)
{
}
HTTPCookie::HTTPCookie(const HTTPCookie& cookie):
_version(cookie._version),
_name(cookie._name),
_value(cookie._value),
_comment(cookie._comment),
_domain(cookie._domain),
_path(cookie._path),
_secure(cookie._secure),
_maxAge(cookie._maxAge)
{
}
HTTPCookie::~HTTPCookie()
{
}
HTTPCookie& HTTPCookie::operator = (const HTTPCookie& cookie)
{
if (&cookie != this)
{
_version = cookie._version;
_name = cookie._name;
_value = cookie._value;
_comment = cookie._comment;
_domain = cookie._domain;
_path = cookie._path;
_secure = cookie._secure;
_maxAge = cookie._maxAge;
}
return *this;
}
void HTTPCookie::setVersion(int version)
{
_version = version;
}
void HTTPCookie::setName(const std::string& name)
{
_name = name;
}
void HTTPCookie::setValue(const std::string& value)
{
_value = value;
}
void HTTPCookie::setComment(const std::string& comment)
{
_comment = comment;
}
void HTTPCookie::setDomain(const std::string& domain)
{
_domain = domain;
}
void HTTPCookie::setPath(const std::string& path)
{
_path = path;
}
void HTTPCookie::setSecure(bool secure)
{
_secure = secure;
}
void HTTPCookie::setMaxAge(int maxAge)
{
_maxAge = maxAge;
}
std::string HTTPCookie::toString() const
{
std::string result(_name);
result.append("=");
if (_version == 0)
{
// Netscape cookie
result.append(_value);
if (!_domain.empty())
{
result.append("; domain=");
result.append(_domain);
}
if (!_path.empty())
{
result.append("; path=");
result.append(_path);
}
if (_maxAge >= 0)
{
Timestamp ts;
ts += _maxAge*1000000;
result.append("; expires=");
result.append(DateTimeFormatter::format(ts, DateTimeFormat::RFC850_FORMAT));
}
if (_secure)
{
result.append("; secure");
}
}
else
{
// RFC 2109 cookie
result.append("\"");
result.append(_value);
result.append("\"");
if (!_comment.empty())
{
result.append("; Comment=\"");
result.append(_comment);
result.append("\"");
}
if (!_domain.empty())
{
result.append("; Domain=\"");
result.append(_domain);
result.append("\"");
}
if (!_path.empty())
{
result.append("; Path=\"");
result.append(_path);
result.append("\"");
}
if (_maxAge >= 0)
{
result.append("; Max-Age=\"");
result.append(NumberFormatter::format(_maxAge));
result.append("\"");
}
if (_secure)
{
result.append("; secure");
}
result.append("; Version=\"1\"");
}
return result;
}
Net_END

View File

@@ -0,0 +1,188 @@
//
// HTTPFixedLengthStream.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPFixedLengthStream.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPFixedLengthStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPFixedLengthStream.h"
#include "Net/HTTPSession.h"
using Foundation::BufferedStreamBuf;
Net_BEGIN
//
// HTTPFixedLengthStreamBuf
//
HTTPFixedLengthStreamBuf::HTTPFixedLengthStreamBuf(HTTPSession& session, std::streamsize length, openmode mode):
HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode),
_session(session),
_length(length),
_count(0)
{
}
HTTPFixedLengthStreamBuf::~HTTPFixedLengthStreamBuf()
{
}
int HTTPFixedLengthStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
int n = 0;
if (_count < _length)
{
if (_count + length > _length)
length = _length - _count;
n = _session.read(buffer, length);
if (n > 0) _count += n;
}
return n;
}
int HTTPFixedLengthStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
int n = 0;
if (_count < _length)
{
if (_count + length > _length)
length = _length - _count;
n = _session.write(buffer, length);
if (n > 0) _count += n;
}
return n;
}
//
// HTTPFixedLengthIOS
//
HTTPFixedLengthIOS::HTTPFixedLengthIOS(HTTPSession& session, std::streamsize length, HTTPFixedLengthStreamBuf::openmode mode):
_buf(session, length, mode)
{
poco_ios_init(&_buf);
}
HTTPFixedLengthIOS::~HTTPFixedLengthIOS()
{
try
{
_buf.sync();
}
catch (...)
{
}
}
HTTPFixedLengthStreamBuf* HTTPFixedLengthIOS::rdbuf()
{
return &_buf;
}
//
// HTTPFixedLengthInputStream
//
Foundation::MemoryPool HTTPFixedLengthInputStream::_pool(sizeof(HTTPFixedLengthInputStream));
HTTPFixedLengthInputStream::HTTPFixedLengthInputStream(HTTPSession& session, std::streamsize length):
HTTPFixedLengthIOS(session, length, std::ios::in),
std::istream(&_buf)
{
}
HTTPFixedLengthInputStream::~HTTPFixedLengthInputStream()
{
}
void* HTTPFixedLengthInputStream::operator new(size_t size)
{
return _pool.get();
}
void HTTPFixedLengthInputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
//
// HTTPFixedLengthOutputStream
//
Foundation::MemoryPool HTTPFixedLengthOutputStream::_pool(sizeof(HTTPFixedLengthOutputStream));
HTTPFixedLengthOutputStream::HTTPFixedLengthOutputStream(HTTPSession& session, std::streamsize length):
HTTPFixedLengthIOS(session, length, std::ios::out),
std::ostream(&_buf)
{
}
HTTPFixedLengthOutputStream::~HTTPFixedLengthOutputStream()
{
}
void* HTTPFixedLengthOutputStream::operator new(size_t size)
{
return _pool.get();
}
void HTTPFixedLengthOutputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
Net_END

View File

@@ -0,0 +1,185 @@
//
// HTTPHeaderStream.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPHeaderStream.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPHeaderStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPHeaderStream.h"
#include "Net/HTTPSession.h"
Net_BEGIN
//
// HTTPHeaderStreamBuf
//
HTTPHeaderStreamBuf::HTTPHeaderStreamBuf(HTTPSession& session, openmode mode):
HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode),
_session(session),
_end(false)
{
}
HTTPHeaderStreamBuf::~HTTPHeaderStreamBuf()
{
}
int HTTPHeaderStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
// read line-by-line; an empty line denotes the end of the headers.
static const int eof = std::char_traits<char>::eof();
if (_end) return 0;
int n = 0;
int ch = _session.get();
while (ch != eof && ch != '\n' && n < length - 1)
{
*buffer++ = (char) ch; ++n;
ch = _session.get();
}
if (ch != eof)
{
*buffer++ = (char) ch; ++n;
if (n == 2) _end = true;
}
return n;
}
int HTTPHeaderStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
return _session.write(buffer, length);
}
//
// HTTPHeaderIOS
//
HTTPHeaderIOS::HTTPHeaderIOS(HTTPSession& session, HTTPHeaderStreamBuf::openmode mode):
_buf(session, mode)
{
poco_ios_init(&_buf);
}
HTTPHeaderIOS::~HTTPHeaderIOS()
{
try
{
_buf.sync();
}
catch (...)
{
}
}
HTTPHeaderStreamBuf* HTTPHeaderIOS::rdbuf()
{
return &_buf;
}
//
// HTTPHeaderInputStream
//
Foundation::MemoryPool HTTPHeaderInputStream::_pool(sizeof(HTTPHeaderInputStream));
HTTPHeaderInputStream::HTTPHeaderInputStream(HTTPSession& session):
HTTPHeaderIOS(session, std::ios::in),
std::istream(&_buf)
{
}
HTTPHeaderInputStream::~HTTPHeaderInputStream()
{
}
void* HTTPHeaderInputStream::operator new(size_t size)
{
return _pool.get();
}
void HTTPHeaderInputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
//
// HTTPHeaderOutputStream
//
Foundation::MemoryPool HTTPHeaderOutputStream::_pool(sizeof(HTTPHeaderOutputStream));
HTTPHeaderOutputStream::HTTPHeaderOutputStream(HTTPSession& session):
HTTPHeaderIOS(session, std::ios::out),
std::ostream(&_buf)
{
}
HTTPHeaderOutputStream::~HTTPHeaderOutputStream()
{
}
void* HTTPHeaderOutputStream::operator new(size_t size)
{
return _pool.get();
}
void HTTPHeaderOutputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
Net_END

84
Net/src/HTTPIOStream.cpp Normal file
View File

@@ -0,0 +1,84 @@
//
// HTTPIOStream.cpp
//
// $Id: //poco/Main/template/class.cpp#5 $
//
// Library: Net
// Package: HTTP
// Module: HTTPIOStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPIOStream.h"
#include "Net/HTTPClientSession.h"
using Foundation::UnbufferedStreamBuf;
Net_BEGIN
HTTPResponseStreamBuf::HTTPResponseStreamBuf(std::istream& istr):
_istr(istr)
{
}
HTTPResponseStreamBuf::~HTTPResponseStreamBuf()
{
}
HTTPResponseIOS::HTTPResponseIOS(std::istream& istr):
_buf(istr)
{
poco_ios_init(&_buf);
}
HTTPResponseIOS::~HTTPResponseIOS()
{
}
HTTPResponseStream::HTTPResponseStream(std::istream& istr, HTTPClientSession* pSession):
HTTPResponseIOS(istr),
std::istream(&_buf),
_pSession(pSession)
{
}
HTTPResponseStream::~HTTPResponseStream()
{
delete _pSession;
}
Net_END

182
Net/src/HTTPMessage.cpp Normal file
View File

@@ -0,0 +1,182 @@
//
// HTTPMessage.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPMessage.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPMessage
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPMessage.h"
#include "Net/MediaType.h"
#include "Foundation/NumberFormatter.h"
#include "Foundation/NumberParser.h"
#include "Foundation/String.h"
using Foundation::NumberFormatter;
using Foundation::NumberParser;
using Foundation::icompare;
Net_BEGIN
const std::string HTTPMessage::HTTP_1_0 = "HTTP/1.0";
const std::string HTTPMessage::HTTP_1_1 = "HTTP/1.1";
const std::string HTTPMessage::IDENTITY_TRANSFER_ENCODING = "identity";
const std::string HTTPMessage::CHUNKED_TRANSFER_ENCODING = "chunked";
const int HTTPMessage::UNKNOWN_CONTENT_LENGTH = -1;
const std::string HTTPMessage::UNKNOWN_CONTENT_TYPE;
const std::string HTTPMessage::CONTENT_LENGTH = "Content-Length";
const std::string HTTPMessage::CONTENT_TYPE = "Content-Type";
const std::string HTTPMessage::TRANSFER_ENCODING = "Transfer-Encoding";
const std::string HTTPMessage::CONNECTION = "Connection";
const std::string HTTPMessage::CONNECTION_KEEP_ALIVE = "Keep-Alive";
const std::string HTTPMessage::CONNECTION_CLOSE = "Close";
HTTPMessage::HTTPMessage():
_version(HTTP_1_0)
{
}
HTTPMessage::HTTPMessage(const std::string& version):
_version(version)
{
}
HTTPMessage::~HTTPMessage()
{
}
void HTTPMessage::setVersion(const std::string& version)
{
_version = version;
}
void HTTPMessage::setContentLength(int length)
{
if (length != UNKNOWN_CONTENT_LENGTH)
set(CONTENT_LENGTH, NumberFormatter::format(length));
else
erase(CONTENT_LENGTH);
}
int HTTPMessage::getContentLength() const
{
if (has(CONTENT_LENGTH))
return NumberParser::parse(get(CONTENT_LENGTH));
else
return UNKNOWN_CONTENT_LENGTH;
}
void HTTPMessage::setTransferEncoding(const std::string& transferEncoding)
{
if (icompare(transferEncoding, IDENTITY_TRANSFER_ENCODING) == 0)
erase(TRANSFER_ENCODING);
else
set(TRANSFER_ENCODING, transferEncoding);
}
const std::string& HTTPMessage::getTransferEncoding() const
{
if (has(TRANSFER_ENCODING))
return get(TRANSFER_ENCODING);
else
return IDENTITY_TRANSFER_ENCODING;
}
void HTTPMessage::setChunkedTransferEncoding(bool flag)
{
if (flag)
setTransferEncoding(CHUNKED_TRANSFER_ENCODING);
else
setTransferEncoding(IDENTITY_TRANSFER_ENCODING);
}
bool HTTPMessage::getChunkedTransferEncoding() const
{
return icompare(getTransferEncoding(), CHUNKED_TRANSFER_ENCODING) == 0;
}
void HTTPMessage::setContentType(const std::string& mediaType)
{
if (mediaType.empty())
erase(CONTENT_TYPE);
else
set(CONTENT_TYPE, mediaType);
}
void HTTPMessage::setContentType(const MediaType& mediaType)
{
setContentType(mediaType.toString());
}
const std::string& HTTPMessage::getContentType() const
{
if (has(CONTENT_TYPE))
return get(CONTENT_TYPE);
else
return UNKNOWN_CONTENT_TYPE;
}
void HTTPMessage::setKeepAlive(bool keepAlive)
{
if (keepAlive)
set(CONNECTION, CONNECTION_KEEP_ALIVE);
else
set(CONNECTION, CONNECTION_CLOSE);
}
bool HTTPMessage::getKeepAlive() const
{
if (has(CONNECTION))
return icompare(get(CONNECTION), CONNECTION_KEEP_ALIVE) == 0;
else
return getVersion() == HTTP_1_1;
}
Net_END

229
Net/src/HTTPRequest.cpp Normal file
View File

@@ -0,0 +1,229 @@
//
// HTTPRequest.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPRequest.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPRequest
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPRequest.h"
#include "Net/HTTPSession.h"
#include "Net/NetException.h"
#include "Net/NameValueCollection.h"
#include "Foundation/NumberFormatter.h"
#include <ctype.h>
using Foundation::NumberFormatter;
Net_BEGIN
const std::string HTTPRequest::HTTP_GET = "GET";
const std::string HTTPRequest::HTTP_HEAD = "HEAD";
const std::string HTTPRequest::HTTP_PUT = "PUT";
const std::string HTTPRequest::HTTP_POST = "POST";
const std::string HTTPRequest::HTTP_OPTIONS = "OPTIONS";
const std::string HTTPRequest::HTTP_DELETE = "DELETE";
const std::string HTTPRequest::HTTP_TRACE = "TRACE";
const std::string HTTPRequest::HTTP_CONNECT = "CONNECT";
const std::string HTTPRequest::HOST = "Host";
const std::string HTTPRequest::COOKIE = "Cookie";
const std::string HTTPRequest::AUTHORIZATION = "Authorization";
HTTPRequest::HTTPRequest():
_method(HTTP_GET),
_uri("/")
{
}
HTTPRequest::HTTPRequest(const std::string& version):
HTTPMessage(version),
_method(HTTP_GET),
_uri("/")
{
}
HTTPRequest::HTTPRequest(const std::string& method, const std::string& uri):
_method(method),
_uri(uri)
{
}
HTTPRequest::HTTPRequest(const std::string& method, const std::string& uri, const std::string& version):
HTTPMessage(version),
_method(method),
_uri(uri)
{
}
HTTPRequest::~HTTPRequest()
{
}
void HTTPRequest::setMethod(const std::string& method)
{
_method = method;
}
void HTTPRequest::setURI(const std::string& uri)
{
_uri = uri;
}
void HTTPRequest::setHost(const std::string& host)
{
set(HOST, host);
}
void HTTPRequest::setHost(const std::string& host, Foundation::UInt16 port)
{
std::string value(host);
if (port != HTTPSession::HTTP_PORT)
{
value.append(":");
value.append(NumberFormatter::format(port));
}
setHost(value);
}
const std::string& HTTPRequest::getHost() const
{
return get(HOST);
}
void HTTPRequest::setCookies(const NameValueCollection& cookies)
{
std::string cookie;
for (NameValueCollection::ConstIterator it = cookies.begin(); it != cookies.end(); ++it)
{
if (it != cookies.begin())
cookie.append("; ");
cookie.append(it->first);
cookie.append("=");
cookie.append(it->second);
}
add(COOKIE, cookie);
}
void HTTPRequest::getCookies(NameValueCollection& cookies) const
{
NameValueCollection::ConstIterator it = find(COOKIE);
while (it != end() && it->first == COOKIE)
{
splitParameters(it->second.begin(), it->second.end(), cookies);
++it;
}
}
bool HTTPRequest::hasCredentials() const
{
return has(AUTHORIZATION);
}
void HTTPRequest::getCredentials(std::string& scheme, std::string& authInfo) const
{
scheme.clear();
authInfo.clear();
if (has(AUTHORIZATION))
{
const std::string& auth = get(AUTHORIZATION);
std::string::const_iterator it = auth.begin();
std::string::const_iterator end = auth.end();
while (it != end && isspace(*it)) ++it;
while (it != end && !isspace(*it)) scheme += *it++;
while (it != end && isspace(*it)) ++it;
while (it != end) authInfo += *it++;
}
else throw NotAuthenticatedException();
}
void HTTPRequest::setCredentials(const std::string& scheme, const std::string& authInfo)
{
std::string auth(scheme);
auth.append(" ");
auth.append(authInfo);
set(AUTHORIZATION, auth);
}
void HTTPRequest::write(std::ostream& ostr) const
{
ostr << _method << " " << _uri << " " << getVersion() << "\r\n";
HTTPMessage::write(ostr);
ostr << "\r\n";
}
void HTTPRequest::read(std::istream& istr)
{
static const int eof = std::char_traits<char>::eof();
std::string method;
std::string uri;
std::string version;
int ch = istr.get();
while (isspace(ch)) ch = istr.get();
while (!isspace(ch) && ch != eof && method.length() < MAX_METHOD_LENGTH) { method += (char) ch; ch = istr.get(); }
if (!isspace(ch)) throw MessageException("HTTP request method too long");
while (isspace(ch)) ch = istr.get();
while (!isspace(ch) && ch != eof && uri.length() < MAX_URI_LENGTH) { uri += (char) ch; ch = istr.get(); }
if (!isspace(ch)) throw MessageException("HTTP request URI too long");
while (isspace(ch)) ch = istr.get();
while (!isspace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); }
if (!isspace(ch)) throw MessageException("Invalid HTTP version string");
while (ch != '\n' && ch != eof) { ch = istr.get(); }
HTTPMessage::read(istr);
ch = istr.get();
while (ch != '\n' && ch != eof) { ch = istr.get(); }
setMethod(method);
setURI(uri);
setVersion(version);
}
Net_END

View File

@@ -0,0 +1,53 @@
//
// HTTPRequestHandler.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPRequestHandler.cpp#2 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPRequestHandler
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPRequestHandler.h"
Net_BEGIN
HTTPRequestHandler::HTTPRequestHandler()
{
}
HTTPRequestHandler::~HTTPRequestHandler()
{
}
Net_END

View File

@@ -0,0 +1,53 @@
//
// HTTPRequestHandlerFactory.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPRequestHandlerFactory.cpp#2 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPRequestHandlerFactory
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPRequestHandlerFactory.h"
Net_BEGIN
HTTPRequestHandlerFactory::HTTPRequestHandlerFactory()
{
}
HTTPRequestHandlerFactory::~HTTPRequestHandlerFactory()
{
}
Net_END

345
Net/src/HTTPResponse.cpp Normal file
View File

@@ -0,0 +1,345 @@
//
// HTTPResponse.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPResponse.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPResponse
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPResponse.h"
#include "Net/NetException.h"
#include "Foundation/NumberFormatter.h"
#include "Foundation/NumberParser.h"
#include "Foundation/DateTime.h"
#include "Foundation/DateTimeFormatter.h"
#include "Foundation/DateTimeFormat.h"
#include "Foundation/DateTimeParser.h"
#include <ctype.h>
using Foundation::DateTime;
using Foundation::NumberFormatter;
using Foundation::NumberParser;
using Foundation::DateTimeFormatter;
using Foundation::DateTimeFormat;
using Foundation::DateTimeParser;
Net_BEGIN
const std::string HTTPResponse::HTTP_REASON_CONTINUE = "Continue";
const std::string HTTPResponse::HTTP_REASON_SWITCHING_PROTOCOLS = "Switching Protocols";
const std::string HTTPResponse::HTTP_REASON_OK = "OK";
const std::string HTTPResponse::HTTP_REASON_CREATED = "Created";
const std::string HTTPResponse::HTTP_REASON_ACCEPTED = "Accepted";
const std::string HTTPResponse::HTTP_REASON_NONAUTHORITATIVE = "Non-Authoritative Information";
const std::string HTTPResponse::HTTP_REASON_NO_CONTENT = "No Content";
const std::string HTTPResponse::HTTP_REASON_RESET_CONTENT = "Reset Content";
const std::string HTTPResponse::HTTP_REASON_PARTIAL_CONTENT = "Partial Content";
const std::string HTTPResponse::HTTP_REASON_MULTIPLE_CHOICES = "Multiple Choices";
const std::string HTTPResponse::HTTP_REASON_MOVED_PERMANENTLY = "Moved Permanently";
const std::string HTTPResponse::HTTP_REASON_FOUND = "Found";
const std::string HTTPResponse::HTTP_REASON_SEE_OTHER = "See Other";
const std::string HTTPResponse::HTTP_REASON_NOT_MODIFIED = "Not Modified";
const std::string HTTPResponse::HTTP_REASON_USEPROXY = "Use Proxy";
const std::string HTTPResponse::HTTP_REASON_TEMPORARY_REDIRECT = "Temporary Redirect";
const std::string HTTPResponse::HTTP_REASON_BAD_REQUEST = "Bad Request";
const std::string HTTPResponse::HTTP_REASON_UNAUTHORIZED = "Unauthorized";
const std::string HTTPResponse::HTTP_REASON_PAYMENT_REQUIRED = "Payment Required";
const std::string HTTPResponse::HTTP_REASON_FORBIDDEN = "Forbidden";
const std::string HTTPResponse::HTTP_REASON_NOT_FOUND = "Not Found";
const std::string HTTPResponse::HTTP_REASON_METHOD_NOT_ALLOWED = "Method Not Allowed";
const std::string HTTPResponse::HTTP_REASON_NOT_ACCEPTABLE = "Not Acceptable";
const std::string HTTPResponse::HTTP_REASON_PROXY_AUTHENTICATION_REQUIRED = "Proxy Authentication Required";
const std::string HTTPResponse::HTTP_REASON_REQUEST_TIMEOUT = "Request Time-out";
const std::string HTTPResponse::HTTP_REASON_CONFLICT = "Conflict";
const std::string HTTPResponse::HTTP_REASON_GONE = "Gone";
const std::string HTTPResponse::HTTP_REASON_LENGTH_REQUIRED = "Length Required";
const std::string HTTPResponse::HTTP_REASON_PRECONDITION_FAILED = "Precondition Failed";
const std::string HTTPResponse::HTTP_REASON_REQUESTENTITYTOOLARGE = "Request Entity Too Large";
const std::string HTTPResponse::HTTP_REASON_REQUESTURITOOLONG = "Request-URI Too Large";
const std::string HTTPResponse::HTTP_REASON_UNSUPPORTEDMEDIATYPE = "Unsupported Media Type";
const std::string HTTPResponse::HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE = "Requested Range Not Satisfiable";
const std::string HTTPResponse::HTTP_REASON_EXPECTATION_FAILED = "Expectation Failed";
const std::string HTTPResponse::HTTP_REASON_INTERNAL_SERVER_ERROR = "Internal Server Error";
const std::string HTTPResponse::HTTP_REASON_NOT_IMPLEMENTED = "Not Implemented";
const std::string HTTPResponse::HTTP_REASON_BAD_GATEWAY = "Bad Gateway";
const std::string HTTPResponse::HTTP_REASON_SERVICE_UNAVAILABLE = "Service Unavailable";
const std::string HTTPResponse::HTTP_REASON_GATEWAY_TIMEOUT = "Gateway Time-out";
const std::string HTTPResponse::HTTP_REASON_VERSION_NOT_SUPPORTED = "HTTP Version not supported";
const std::string HTTPResponse::HTTP_REASON_UNKNOWN = "???";
const std::string HTTPResponse::DATE = "Date";
const std::string HTTPResponse::SET_COOKIE = "Set-Cookie";
HTTPResponse::HTTPResponse():
_status(HTTP_OK),
_reason(getReasonForStatus(HTTP_OK))
{
}
HTTPResponse::HTTPResponse(HTTPStatus status, const std::string& reason):
_status(status),
_reason(reason)
{
}
HTTPResponse::HTTPResponse(const std::string& version, HTTPStatus status, const std::string& reason):
HTTPMessage(version),
_status(status),
_reason(reason)
{
}
HTTPResponse::HTTPResponse(HTTPStatus status):
_status(status),
_reason(getReasonForStatus(status))
{
}
HTTPResponse::HTTPResponse(const std::string& version, HTTPStatus status):
HTTPMessage(version),
_status(status),
_reason(getReasonForStatus(status))
{
}
HTTPResponse::~HTTPResponse()
{
}
void HTTPResponse::setStatus(HTTPStatus status)
{
_status = status;
}
void HTTPResponse::setStatus(const std::string& status)
{
setStatus((HTTPStatus) NumberParser::parse(status));
}
void HTTPResponse::setReason(const std::string& reason)
{
_reason = reason;
}
void HTTPResponse::setStatusAndReason(HTTPStatus status, const std::string& reason)
{
_status = status;
_reason = reason;
}
void HTTPResponse::setStatusAndReason(HTTPStatus status)
{
setStatusAndReason(status, getReasonForStatus(status));
}
void HTTPResponse::setDate(const Foundation::Timestamp& dateTime)
{
set(DATE, DateTimeFormatter::format(dateTime, DateTimeFormat::HTTP_FORMAT));
}
Foundation::Timestamp HTTPResponse::getDate() const
{
const std::string& dateTime = get(DATE);
int tzd;
return DateTimeParser::parse(dateTime, tzd).timestamp();
}
void HTTPResponse::addCookie(const HTTPCookie& cookie)
{
add(SET_COOKIE, cookie.toString());
}
void HTTPResponse::getCookies(std::vector<HTTPCookie>& cookies) const
{
cookies.clear();
NameValueCollection::ConstIterator it = find(SET_COOKIE);
while (it != end() && it->first == SET_COOKIE)
{
NameValueCollection nvc;
splitParameters(it->second.begin(), it->second.end(), nvc);
cookies.push_back(HTTPCookie(nvc));
++it;
}
}
void HTTPResponse::write(std::ostream& ostr) const
{
ostr << getVersion() << " " << NumberFormatter::format((int) _status) << " " << _reason << "\r\n";
HTTPMessage::write(ostr);
ostr << "\r\n";
}
void HTTPResponse::read(std::istream& istr)
{
static const int eof = std::char_traits<char>::eof();
std::string version;
std::string status;
std::string reason;
int ch = 0;
do
{
version.clear();
status.clear();
reason.clear();
ch = istr.get();
while (isspace(ch)) ch = istr.get();
while (!isspace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); }
if (!isspace(ch)) throw MessageException("Invalid HTTP version string");
while (isspace(ch)) ch = istr.get();
while (!isspace(ch) && ch != eof && status.length() < MAX_STATUS_LENGTH) { status += (char) ch; ch = istr.get(); }
if (!isspace(ch)) throw MessageException("Invalid HTTP status code");
while (isspace(ch)) ch = istr.get();
while (ch != '\r' && ch != '\n' && ch != eof && reason.length() < MAX_REASON_LENGTH) { reason += (char) ch; ch = istr.get(); }
if (!isspace(ch)) throw MessageException("HTTP reason string too long");
if (ch == '\r') ch = istr.get();
}
while (ch != eof && status == "100");
HTTPMessage::read(istr);
ch = istr.get();
while (ch != '\n' && ch != eof) { ch = istr.get(); }
setVersion(version);
setStatus(status);
setReason(reason);
}
const std::string& HTTPResponse::getReasonForStatus(HTTPStatus status)
{
switch (status)
{
case HTTP_CONTINUE:
return HTTP_REASON_CONTINUE;
case HTTP_SWITCHING_PROTOCOLS:
return HTTP_REASON_SWITCHING_PROTOCOLS;
case HTTP_OK:
return HTTP_REASON_OK;
case HTTP_CREATED:
return HTTP_REASON_CREATED;
case HTTP_ACCEPTED:
return HTTP_REASON_ACCEPTED;
case HTTP_NONAUTHORITATIVE:
return HTTP_REASON_NONAUTHORITATIVE;
case HTTP_NO_CONTENT:
return HTTP_REASON_NO_CONTENT;
case HTTP_RESET_CONTENT:
return HTTP_REASON_RESET_CONTENT;
case HTTP_PARTIAL_CONTENT:
return HTTP_REASON_PARTIAL_CONTENT;
case HTTP_MULTIPLE_CHOICES:
return HTTP_REASON_MULTIPLE_CHOICES;
case HTTP_MOVED_PERMANENTLY:
return HTTP_REASON_MOVED_PERMANENTLY;
case HTTP_FOUND:
return HTTP_REASON_FOUND;
case HTTP_SEE_OTHER:
return HTTP_REASON_SEE_OTHER;
case HTTP_NOT_MODIFIED:
return HTTP_REASON_NOT_MODIFIED;
case HTTP_USEPROXY:
return HTTP_REASON_USEPROXY;
case HTTP_TEMPORARY_REDIRECT:
return HTTP_REASON_TEMPORARY_REDIRECT;
case HTTP_BAD_REQUEST:
return HTTP_REASON_BAD_REQUEST;
case HTTP_UNAUTHORIZED:
return HTTP_REASON_UNAUTHORIZED;
case HTTP_PAYMENT_REQUIRED:
return HTTP_REASON_PAYMENT_REQUIRED;
case HTTP_FORBIDDEN:
return HTTP_REASON_FORBIDDEN;
case HTTP_NOT_FOUND:
return HTTP_REASON_NOT_FOUND;
case HTTP_METHOD_NOT_ALLOWED:
return HTTP_REASON_METHOD_NOT_ALLOWED;
case HTTP_NOT_ACCEPTABLE:
return HTTP_REASON_NOT_ACCEPTABLE;
case HTTP_PROXY_AUTHENTICATION_REQUIRED:
return HTTP_REASON_PROXY_AUTHENTICATION_REQUIRED;
case HTTP_REQUEST_TIMEOUT:
return HTTP_REASON_REQUEST_TIMEOUT;
case HTTP_CONFLICT:
return HTTP_REASON_CONFLICT;
case HTTP_GONE:
return HTTP_REASON_GONE;
case HTTP_LENGTH_REQUIRED:
return HTTP_REASON_LENGTH_REQUIRED;
case HTTP_PRECONDITION_FAILED:
return HTTP_REASON_PRECONDITION_FAILED;
case HTTP_REQUESTENTITYTOOLARGE:
return HTTP_REASON_REQUESTENTITYTOOLARGE;
case HTTP_REQUESTURITOOLONG:
return HTTP_REASON_REQUESTURITOOLONG;
case HTTP_UNSUPPORTEDMEDIATYPE:
return HTTP_REASON_UNSUPPORTEDMEDIATYPE;
case HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
return HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE;
case HTTP_EXPECTATION_FAILED:
return HTTP_REASON_EXPECTATION_FAILED;
case HTTP_INTERNAL_SERVER_ERROR:
return HTTP_REASON_INTERNAL_SERVER_ERROR;
case HTTP_NOT_IMPLEMENTED:
return HTTP_REASON_NOT_IMPLEMENTED;
case HTTP_BAD_GATEWAY:
return HTTP_REASON_BAD_GATEWAY;
case HTTP_SERVICE_UNAVAILABLE:
return HTTP_REASON_SERVICE_UNAVAILABLE;
case HTTP_GATEWAY_TIMEOUT:
return HTTP_REASON_GATEWAY_TIMEOUT;
case HTTP_VERSION_NOT_SUPPORTED:
return HTTP_REASON_VERSION_NOT_SUPPORTED;
default:
return HTTP_REASON_UNKNOWN;
}
}
Net_END

62
Net/src/HTTPServer.cpp Normal file
View File

@@ -0,0 +1,62 @@
//
// HTTPServer.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPServer.cpp#2 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServer
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPServer.h"
#include "Net/HTTPServerParams.h"
#include "Net/HTTPServerConnectionFactory.h"
Net_BEGIN
HTTPServer::HTTPServer(HTTPRequestHandlerFactory* pFactory, const ServerSocket& socket, HTTPServerParams* pParams):
TCPServer(new HTTPServerConnectionFactory(pParams, pFactory), socket, pParams)
{
}
HTTPServer::HTTPServer(HTTPRequestHandlerFactory* pFactory, Foundation::ThreadPool& threadPool, const ServerSocket& socket, HTTPServerParams* pParams):
TCPServer(new HTTPServerConnectionFactory(pParams, pFactory), threadPool, socket, pParams)
{
}
HTTPServer::~HTTPServer()
{
}
Net_END

View File

@@ -0,0 +1,102 @@
//
// HTTPServerConnection.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPServerConnection.cpp#2 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerConnection
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPServerConnection.h"
#include "Net/HTTPServerSession.h"
#include "Net/HTTPServerRequest.h"
#include "Net/HTTPServerResponse.h"
#include "Net/HTTPRequestHandler.h"
#include "Net/HTTPRequestHandlerFactory.h"
#include "Net/HTTPServerParams.h"
#include "Net/NetException.h"
#include "Foundation/NumberFormatter.h"
#include <memory>
Net_BEGIN
HTTPServerConnection::HTTPServerConnection(const StreamSocket& socket, HTTPServerParams* pParams, HTTPRequestHandlerFactory* pFactory):
TCPServerConnection(socket),
_pParams(pParams),
_pFactory(pFactory)
{
poco_check_ptr (pFactory);
poco_check_ptr (pParams);
_pParams->duplicate();
}
HTTPServerConnection::~HTTPServerConnection()
{
_pParams->release();
}
void HTTPServerConnection::run()
{
std::string server = _pParams->getSoftwareVersion();
HTTPServerSession session(socket(), _pParams);
while (session.hasMoreRequests())
{
HTTPServerRequest request(session, _pParams);
HTTPServerResponse response(session);
response.setVersion(request.getVersion());
response.setKeepAlive(_pParams->getKeepAlive() && request.getKeepAlive());
if (!server.empty())
response.set("Server", server);
std::auto_ptr<HTTPRequestHandler> pHandler(_pFactory->createRequestHandler(request));
if (pHandler.get())
{
if (request.expectContinue())
response.sendContinue();
pHandler->handleRequest(request, response);
session.setKeepAlive(_pParams->getKeepAlive() && response.getKeepAlive());
}
else
{
response.setStatusAndReason(HTTPResponse::HTTP_NOT_IMPLEMENTED);
response.setKeepAlive(false);
response.send();
session.setKeepAlive(false);
}
}
}
Net_END

View File

@@ -0,0 +1,70 @@
//
// HTTPServerConnectionFactory.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPServerConnectionFactory.cpp#2 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerConnectionFactory
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPServerConnectionFactory.h"
#include "Net/HTTPServerConnection.h"
#include "Net/HTTPServerParams.h"
#include "Net/HTTPRequestHandlerFactory.h"
Net_BEGIN
HTTPServerConnectionFactory::HTTPServerConnectionFactory(HTTPServerParams* pParams, HTTPRequestHandlerFactory* pFactory):
_pParams(pParams),
_pFactory(pFactory)
{
poco_check_ptr (pParams);
poco_check_ptr (pFactory);
_pParams->duplicate();
}
HTTPServerConnectionFactory::~HTTPServerConnectionFactory()
{
_pParams->release();
delete _pFactory;
}
TCPServerConnection* HTTPServerConnectionFactory::createConnection(const StreamSocket& socket)
{
return new HTTPServerConnection(socket, _pParams, _pFactory);
}
Net_END

View File

@@ -0,0 +1,94 @@
//
// HTTPServerParams.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPServerParams.cpp#2 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerParams
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPServerParams.h"
Net_BEGIN
HTTPServerParams::HTTPServerParams():
_timeout(60000000),
_keepAlive(true),
_maxKeepAliveRequests(0),
_keepAliveTimeout(15000000)
{
}
HTTPServerParams::~HTTPServerParams()
{
}
void HTTPServerParams::setServerName(const std::string& serverName)
{
_serverName = serverName;
}
void HTTPServerParams::setSoftwareVersion(const std::string& softwareVersion)
{
_softwareVersion = softwareVersion;
}
void HTTPServerParams::setTimeout(const Foundation::Timespan& timeout)
{
_timeout = timeout;
}
void HTTPServerParams::setKeepAlive(bool keepAlive)
{
_keepAlive = keepAlive;
}
void HTTPServerParams::setKeepAliveTimeout(const Foundation::Timespan& timeout)
{
_keepAliveTimeout = timeout;
}
void HTTPServerParams::setMaxKeepAliveRequests(int maxKeepAliveRequests)
{
poco_assert (maxKeepAliveRequests >= 0);
_maxKeepAliveRequests = maxKeepAliveRequests;
}
Net_END

View File

@@ -0,0 +1,90 @@
//
// HTTPServerRequest.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPServerRequest.cpp#2 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerRequest
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPServerRequest.h"
#include "Net/HTTPServerSession.h"
#include "Net/HTTPHeaderStream.h"
#include "Net/HTTPStream.h"
#include "Net/HTTPFixedLengthStream.h"
#include "Net/HTTPChunkedStream.h"
#include "Net/HTTPServerParams.h"
#include "Foundation/String.h"
using Foundation::icompare;
Net_BEGIN
HTTPServerRequest::HTTPServerRequest(HTTPServerSession& session, HTTPServerParams* pParams):
_pStream(0),
_pParams(pParams),
_clientAddress(session.clientAddress()),
_serverAddress(session.serverAddress())
{
poco_check_ptr (_pParams);
_pParams->duplicate();
HTTPHeaderInputStream hs(session);
read(hs);
if (getChunkedTransferEncoding())
_pStream = new HTTPChunkedInputStream(session);
else if (getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
_pStream = new HTTPFixedLengthInputStream(session, getContentLength());
else if (getMethod() == HTTPRequest::HTTP_GET || getMethod() == HTTPRequest::HTTP_HEAD)
_pStream = new HTTPFixedLengthInputStream(session, 0);
else
_pStream = new HTTPInputStream(session);
}
HTTPServerRequest::~HTTPServerRequest()
{
_pParams->release();
delete _pStream;
}
bool HTTPServerRequest::expectContinue() const
{
return has("Expect") && icompare(get("Expect"), "100-continue") == 0;
}
Net_END

View File

@@ -0,0 +1,150 @@
//
// HTTPServerResponse.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPServerResponse.cpp#2 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerResponse
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPServerResponse.h"
#include "Net/HTTPServerSession.h"
#include "Net/HTTPHeaderStream.h"
#include "Net/HTTPStream.h"
#include "Net/HTTPFixedLengthStream.h"
#include "Net/HTTPChunkedStream.h"
#include "Foundation/File.h"
#include "Foundation/Timestamp.h"
#include "Foundation/NumberFormatter.h"
#include "Foundation/StreamCopier.h"
#include "Foundation/Exception.h"
#include <fstream>
using Foundation::File;
using Foundation::Timestamp;
using Foundation::NumberFormatter;
using Foundation::StreamCopier;
using Foundation::OpenFileException;
Net_BEGIN
HTTPServerResponse::HTTPServerResponse(HTTPServerSession& session):
_session(session),
_pStream(0)
{
}
HTTPServerResponse::~HTTPServerResponse()
{
delete _pStream;
}
void HTTPServerResponse::sendContinue()
{
HTTPHeaderOutputStream hs(_session);
hs << getVersion() << " 100 Continue\r\n";
}
std::ostream& HTTPServerResponse::send()
{
poco_assert (!_pStream);
if (getChunkedTransferEncoding())
{
_pStream = new HTTPChunkedOutputStream(_session);
}
else if (getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
{
_pStream = new HTTPFixedLengthOutputStream(_session, getContentLength());
}
else
{
_pStream = new HTTPOutputStream(_session);
setKeepAlive(false);
}
HTTPHeaderOutputStream hs(_session);
write(hs);
return *_pStream;
}
void HTTPServerResponse::sendFile(const std::string& path, const std::string& mediaType)
{
poco_assert (!_pStream);
File f(path);
Timestamp dateTime = f.getLastModified();
File::FileSize length = f.getSize();
setDate(dateTime);
setContentLength((int) length);
setContentType(mediaType);
std::ifstream istr(path.c_str(), std::ios::binary | std::ios::in);
if (istr.good())
{
send();
StreamCopier::copyStream(istr, *_pStream);
}
else throw OpenFileException(path);
}
void HTTPServerResponse::redirect(const std::string& uri)
{
poco_assert (!_pStream);
setStatusAndReason(HTTPResponse::HTTP_FOUND);
set("Location", uri);
HTTPHeaderOutputStream hs(_session);
write(hs);
}
void HTTPServerResponse::requireAuthentication(const std::string& realm)
{
poco_assert (!_pStream);
setStatusAndReason(HTTPResponse::HTTP_UNAUTHORIZED);
std::string auth("Basic realm=\"");
auth.append(realm);
auth.append("\"");
set("WWW-Authenticate", auth);
}
Net_END

View File

@@ -0,0 +1,87 @@
//
// HTTPServerSession.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPServerSession.cpp#2 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerSession
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPServerSession.h"
#include "Net/HTTPServerParams.h"
Net_BEGIN
HTTPServerSession::HTTPServerSession(const StreamSocket& socket, HTTPServerParams* pParams):
HTTPSession(socket, pParams->getKeepAlive()),
_firstRequest(true),
_keepAliveTimeout(pParams->getKeepAliveTimeout()),
_maxKeepAliveRequests(pParams->getMaxKeepAliveRequests())
{
}
HTTPServerSession::~HTTPServerSession()
{
}
bool HTTPServerSession::hasMoreRequests()
{
if (_firstRequest)
{
_firstRequest = false;
--_maxKeepAliveRequests;
return socket().poll(getTimeout(), Socket::SELECT_READ);
}
else if (_maxKeepAliveRequests > 0 && getKeepAlive())
{
--_maxKeepAliveRequests;
return socket().poll(_keepAliveTimeout, Socket::SELECT_READ);
}
else return false;
}
SocketAddress HTTPServerSession::clientAddress()
{
return socket().peerAddress();
}
SocketAddress HTTPServerSession::serverAddress()
{
return socket().address();
}
Net_END

190
Net/src/HTTPSession.cpp Normal file
View File

@@ -0,0 +1,190 @@
//
// HTTPSession.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPSession.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPSession
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPSession.h"
#include "Net/HTTPBufferAllocator.h"
#include "Net/NetException.h"
#include <string.h>
using Foundation::TimeoutException;
Net_BEGIN
HTTPSession::HTTPSession():
_pBuffer(0),
_pCurrent(0),
_pEnd(0),
_keepAlive(false),
_timeout(HTTP_DEFAULT_TIMEOUT)
{
}
HTTPSession::HTTPSession(const StreamSocket& socket):
_socket(socket),
_pBuffer(0),
_pCurrent(0),
_pEnd(0),
_keepAlive(false),
_timeout(HTTP_DEFAULT_TIMEOUT)
{
}
HTTPSession::HTTPSession(const StreamSocket& socket, bool keepAlive):
_socket(socket),
_pBuffer(0),
_pCurrent(0),
_pEnd(0),
_keepAlive(keepAlive),
_timeout(HTTP_DEFAULT_TIMEOUT)
{
}
HTTPSession::~HTTPSession()
{
if (_pBuffer) HTTPBufferAllocator::deallocate(_pBuffer, HTTPBufferAllocator::BUFFER_SIZE);
close();
}
void HTTPSession::setKeepAlive(bool keepAlive)
{
_keepAlive = keepAlive;
}
void HTTPSession::setTimeout(const Foundation::Timespan& timeout)
{
_timeout = timeout;
}
int HTTPSession::get()
{
if (_pCurrent == _pEnd)
refill();
if (_pCurrent < _pEnd)
return *_pCurrent++;
else
return std::char_traits<char>::eof();
}
int HTTPSession::peek()
{
if (_pCurrent == _pEnd)
refill();
if (_pCurrent < _pEnd)
return *_pCurrent;
else
return std::char_traits<char>::eof();
}
int HTTPSession::read(char* buffer, std::streamsize length)
{
if (_pCurrent < _pEnd)
{
int n = (int) (_pEnd - _pCurrent);
if (n > length) n = (int) length;
memcpy(buffer, _pCurrent, n);
_pCurrent += n;
return n;
}
else return receive(buffer, (int) length);
}
int HTTPSession::write(const char* buffer, std::streamsize length)
{
return _socket.sendBytes(buffer, (int) length);
}
int HTTPSession::receive(char* buffer, int length)
{
if (_socket.poll(_timeout, Socket::SELECT_READ))
return _socket.receiveBytes(buffer, length);
else
throw TimeoutException();
}
void HTTPSession::refill()
{
if (!_pBuffer)
{
_pBuffer = HTTPBufferAllocator::allocate(HTTPBufferAllocator::BUFFER_SIZE);
}
_pCurrent = _pEnd = _pBuffer;
int n = receive(_pBuffer, HTTPBufferAllocator::BUFFER_SIZE);
_pEnd += n;
}
bool HTTPSession::connected() const
{
return _socket.impl()->initialized();
}
void HTTPSession::connect(const SocketAddress& address)
{
_socket.connect(address, _timeout);
}
void HTTPSession::abort()
{
_socket.shutdown();
close();
}
void HTTPSession::close()
{
_socket.close();
}
Net_END

179
Net/src/HTTPStream.cpp Normal file
View File

@@ -0,0 +1,179 @@
//
// HTTPStream.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPStream.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPStream.h"
#include "Net/HTTPSession.h"
Net_BEGIN
//
// HTTPStreamBuf
//
HTTPStreamBuf::HTTPStreamBuf(HTTPSession& session, openmode mode):
HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode),
_session(session),
_mode(mode)
{
}
HTTPStreamBuf::~HTTPStreamBuf()
{
}
void HTTPStreamBuf::close()
{
if (_mode & std::ios::out)
{
sync();
_session.socket().shutdownSend();
}
}
int HTTPStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
return _session.read(buffer, length);
}
int HTTPStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
return _session.write(buffer, length);
}
//
// HTTPIOS
//
HTTPIOS::HTTPIOS(HTTPSession& session, HTTPStreamBuf::openmode mode):
_buf(session, mode)
{
poco_ios_init(&_buf);
}
HTTPIOS::~HTTPIOS()
{
try
{
_buf.close();
}
catch (...)
{
}
}
HTTPStreamBuf* HTTPIOS::rdbuf()
{
return &_buf;
}
//
// HTTPInputStream
//
Foundation::MemoryPool HTTPInputStream::_pool(sizeof(HTTPInputStream));
HTTPInputStream::HTTPInputStream(HTTPSession& session):
HTTPIOS(session, std::ios::in),
std::istream(&_buf)
{
}
HTTPInputStream::~HTTPInputStream()
{
}
void* HTTPInputStream::operator new(size_t size)
{
return _pool.get();
}
void HTTPInputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
//
// HTTPOutputStream
//
Foundation::MemoryPool HTTPOutputStream::_pool(sizeof(HTTPOutputStream));
HTTPOutputStream::HTTPOutputStream(HTTPSession& session):
HTTPIOS(session, std::ios::out),
std::ostream(&_buf)
{
}
HTTPOutputStream::~HTTPOutputStream()
{
}
void* HTTPOutputStream::operator new(size_t size)
{
return _pool.get();
}
void HTTPOutputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
Net_END

View File

@@ -0,0 +1,126 @@
//
// HTTPStreamFactory.cpp
//
// $Id: //poco/1.1.0/Net/src/HTTPStreamFactory.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPStreamFactory
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HTTPStreamFactory.h"
#include "Net/HTTPClientSession.h"
#include "Net/HTTPIOStream.h"
#include "Net/HTTPRequest.h"
#include "Net/HTTPResponse.h"
#include "Net/NetException.h"
#include "Foundation/URI.h"
#include "Foundation/URIStreamOpener.h"
#include "Foundation/UnbufferedStreamBuf.h"
using Foundation::URIStreamFactory;
using Foundation::URI;
using Foundation::URIStreamOpener;
using Foundation::UnbufferedStreamBuf;
Net_BEGIN
HTTPStreamFactory::HTTPStreamFactory():
_proxyPort(HTTPSession::HTTP_PORT)
{
}
HTTPStreamFactory::HTTPStreamFactory(const std::string& proxyHost, Foundation::UInt16 proxyPort):
_proxyHost(proxyHost),
_proxyPort(proxyPort)
{
}
HTTPStreamFactory::~HTTPStreamFactory()
{
}
std::istream* HTTPStreamFactory::open(const URI& uri)
{
poco_assert (uri.getScheme() == "http");
URI resolvedURI(uri);
HTTPClientSession* pSession = 0;
try
{
int redirects = 0;
do
{
pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort());
pSession->setProxy(_proxyHost, _proxyPort);
std::string path = resolvedURI.getPathAndQuery();
if (path.empty()) path = "/";
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
pSession->sendRequest(req);
HTTPResponse res;
std::istream& rs = pSession->receiveResponse(res);
bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY ||
res.getStatus() == HTTPResponse::HTTP_FOUND ||
res.getStatus() == HTTPResponse::HTTP_SEE_OTHER);
if (moved)
{
resolvedURI.resolve(res.get("Location"));
delete pSession;
++redirects;
}
else if (res.getStatus() == HTTPResponse::HTTP_OK)
{
return new HTTPResponseStream(rs, pSession);
}
else throw HTTPException(res.getReason(), uri.toString());
}
while (redirects < MAX_REDIRECTS);
throw HTTPException("Too many redirects", uri.toString());
}
catch (...)
{
delete pSession;
throw;
}
}
void HTTPStreamFactory::registerFactory()
{
URIStreamOpener::defaultOpener().registerStreamFactory("http", new HTTPStreamFactory);
}
Net_END

129
Net/src/HostEntry.cpp Normal file
View File

@@ -0,0 +1,129 @@
//
// HostEntry.cpp
//
// $Id: //poco/1.1.0/Net/src/HostEntry.cpp#2 $
//
// Library: Net
// Package: NetCore
// Module: HostEntry
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/HostEntry.h"
#include "Foundation/Exception.h"
#include <algorithm>
Net_BEGIN
HostEntry::HostEntry()
{
}
HostEntry::HostEntry(struct hostent* entry)
{
poco_check_ptr (entry);
_name = entry->h_name;
char** alias = entry->h_aliases;
if (alias)
{
while (*alias)
{
_aliases.push_back(std::string(*alias));
++alias;
}
}
char** address = entry->h_addr_list;
if (address)
{
while (*address)
{
_addresses.push_back(IPAddress(*address, entry->h_length));
++address;
}
}
}
#if defined(_WIN32) && defined(POCO_HAVE_IPv6)
HostEntry::HostEntry(struct addrinfo* ainfo)
{
poco_check_ptr (ainfo);
for (struct addrinfo* ai = ainfo; ai; ai = ai->ai_next)
{
if (ai->ai_canonname)
_name.assign(ai->ai_canonname);
else if (ai->ai_addrlen && ai->ai_addr)
_addresses.push_back(IPAddress(ai->ai_addr, (poco_socklen_t) ai->ai_addrlen));
}
}
#endif
HostEntry::HostEntry(const HostEntry& entry):
_name(entry._name),
_aliases(entry._aliases),
_addresses(entry._addresses)
{
}
HostEntry& HostEntry::operator = (const HostEntry& entry)
{
if (&entry != this)
{
_name = entry._name;
_aliases = entry._aliases;
_addresses = entry._addresses;
}
return *this;
}
void HostEntry::swap(HostEntry& hostEntry)
{
std::swap(_name, hostEntry._name);
std::swap(_aliases, hostEntry._aliases);
std::swap(_addresses, hostEntry._addresses);
}
HostEntry::~HostEntry()
{
}
Net_END

744
Net/src/IPAddress.cpp Normal file
View File

@@ -0,0 +1,744 @@
//
// IPAddress.cpp
//
// $Id: //poco/1.1.0/Net/src/IPAddress.cpp#2 $
//
// Library: Net
// Package: NetCore
// Module: IPAddress
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/IPAddress.h"
#include "Net/NetException.h"
#include "Foundation/RefCountedObject.h"
#include "Foundation/NumberFormatter.h"
#include "Foundation/Types.h"
#include <algorithm>
#include <string.h>
using Foundation::RefCountedObject;
using Foundation::NumberFormatter;
using Foundation::UInt8;
using Foundation::UInt16;
using Foundation::UInt32;
Net_BEGIN
//
// IPAddressImpl
//
class IPAddressImpl: public RefCountedObject
{
public:
virtual std::string toString() const = 0;
virtual poco_socklen_t length() const = 0;
virtual const void* addr() const = 0;
virtual IPAddress::Family family() const = 0;
virtual int af() const = 0;
virtual bool isWildcard() const = 0;
virtual bool isBroadcast() const = 0;
virtual bool isLoopback() const = 0;
virtual bool isMulticast() const = 0;
virtual bool isLinkLocal() const = 0;
virtual bool isSiteLocal() const = 0;
virtual bool isIPv4Mapped() const = 0;
virtual bool isIPv4Compatible() const = 0;
virtual bool isWellKnownMC() const = 0;
virtual bool isNodeLocalMC() const = 0;
virtual bool isLinkLocalMC() const = 0;
virtual bool isSiteLocalMC() const = 0;
virtual bool isOrgLocalMC() const = 0;
virtual bool isGlobalMC() const = 0;
protected:
IPAddressImpl()
{
}
virtual ~IPAddressImpl()
{
}
private:
IPAddressImpl(const IPAddressImpl&);
IPAddressImpl& operator = (const IPAddressImpl&);
};
class IPv4AddressImpl: public IPAddressImpl
{
public:
IPv4AddressImpl()
{
memset(&_addr, 0, sizeof(_addr));
}
IPv4AddressImpl(const void* addr)
{
memcpy(&_addr, addr, sizeof(_addr));
}
std::string toString() const
{
const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr);
std::string result;
result.reserve(16);
result.append(NumberFormatter::format(bytes[0]));
result.append(".");
result.append(NumberFormatter::format(bytes[1]));
result.append(".");
result.append(NumberFormatter::format(bytes[2]));
result.append(".");
result.append(NumberFormatter::format(bytes[3]));
return result;
}
poco_socklen_t length() const
{
return sizeof(_addr);
}
const void* addr() const
{
return &_addr;
}
IPAddress::Family family() const
{
return IPAddress::IPv4;
}
int af() const
{
return AF_INET;
}
bool isWildcard() const
{
return _addr.s_addr == INADDR_ANY;
}
bool isBroadcast() const
{
return _addr.s_addr == INADDR_NONE;
}
bool isLoopback() const
{
return ntohl(_addr.s_addr) == 0x7F000001; // 127.0.0.1
}
bool isMulticast() const
{
return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/24 to 239.0.0.0/24
}
bool isLinkLocal() const
{
return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16
}
bool isSiteLocal() const
{
UInt32 addr = ntohl(_addr.s_addr);
return (addr & 0xFF000000) == 0x0A000000 || // 10.0.0.0/24
(addr & 0xFFFF0000) == 0xC0A80000 || // 192.68.0.0/16
addr >= 0xAC100000 && addr <= 0xAC1FFFFF; // 172.16.0.0 to 172.31.255.255
}
bool isIPv4Compatible() const
{
return true;
}
bool isIPv4Mapped() const
{
return true;
}
bool isWellKnownMC() const
{
return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8
}
bool isNodeLocalMC() const
{
return false;
}
bool isLinkLocalMC() const
{
return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24
}
bool isSiteLocalMC() const
{
return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16
}
bool isOrgLocalMC() const
{
return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16
}
bool isGlobalMC() const
{
UInt32 addr = ntohl(_addr.s_addr);
return addr >= 0xE0000100 && addr <= 0xEE000000; // 224.0.1.0 to 238.255.255.255
}
static IPv4AddressImpl* parse(const std::string& addr)
{
#if defined(_WIN32)
struct in_addr ia;
ia.s_addr = inet_addr(addr.c_str());
if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255")
return 0;
else
return new IPv4AddressImpl(&ia);
#else
struct in_addr ia;
if (inet_aton(addr.c_str(), &ia))
return new IPv4AddressImpl(&ia);
else
return 0;
#endif
}
private:
struct in_addr _addr;
};
#if defined(POCO_HAVE_IPv6)
class IPv6AddressImpl: public IPAddressImpl
{
public:
IPv6AddressImpl()
{
memset(&_addr, 0, sizeof(_addr));
}
IPv6AddressImpl(const void* addr)
{
memcpy(&_addr, addr, sizeof(_addr));
}
std::string toString() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
if (isIPv4Compatible() || isIPv4Mapped())
{
std::string result;
result.reserve(24);
if (words[5] == 0)
result.append("::");
else
result.append("::FFFF:");
const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr);
result.append(NumberFormatter::format(bytes[12]));
result.append(".");
result.append(NumberFormatter::format(bytes[13]));
result.append(".");
result.append(NumberFormatter::format(bytes[14]));
result.append(".");
result.append(NumberFormatter::format(bytes[15]));
return result;
}
else
{
std::string result;
result.reserve(46);
bool zeroSequence = false;
int i = 0;
while (i < 8)
{
if (!zeroSequence && words[i] == 0)
{
int zi = i;
while (zi < 8 && words[zi] == 0) ++zi;
if (zi > i + 1)
{
i = zi;
result.append(":");
zeroSequence = true;
}
}
if (i > 0) result.append(":");
if (i < 8) result.append(NumberFormatter::formatHex(words[i++]));
}
return result;
}
}
poco_socklen_t length() const
{
return sizeof(_addr);
}
const void* addr() const
{
return &_addr;
}
IPAddress::Family family() const
{
return IPAddress::IPv6;
}
int af() const
{
return AF_INET6;
}
bool isWildcard() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0;
}
bool isBroadcast() const
{
return false;
}
bool isLoopback() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 1;
}
bool isMulticast() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (words[0] & 0xFFE0) == 0xFF00;
}
bool isLinkLocal() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (words[0] & 0xFFE0) == 0xFE80;
}
bool isSiteLocal() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (words[0] & 0xFFE0) == 0xFEC0;
}
bool isIPv4Compatible() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0;
}
bool isIPv4Mapped() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0xFFFF;
}
bool isWellKnownMC() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (words[0] & 0xFFF0) == 0xFF00;
}
bool isNodeLocalMC() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (words[0] & 0xFFEF) == 0xFF01;
}
bool isLinkLocalMC() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (words[0] & 0xFFEF) == 0xFF02;
}
bool isSiteLocalMC() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (words[0] & 0xFFEF) == 0xFF05;
}
bool isOrgLocalMC() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (words[0] & 0xFFEF) == 0xFF08;
}
bool isGlobalMC() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (words[0] & 0xFFEF) == 0xFF0F;
}
static IPv6AddressImpl* parse(const std::string& addr)
{
#if defined(_WIN32)
struct addrinfo* pAI;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
int rc = getaddrinfo(addr.c_str(), NULL, &hints, &pAI);
if (rc == 0)
{
IPv6AddressImpl* pResult = new IPv6AddressImpl(&reinterpret_cast<struct sockaddr_in6*>(pAI->ai_addr)->sin6_addr);
freeaddrinfo(pAI);
return pResult;
}
else return 0;
#else
struct in6_addr ia;
if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1)
return new IPv6AddressImpl(&ia);
else
return 0;
#endif
}
private:
struct in6_addr _addr;
};
#endif // POCO_HAVE_IPv6
//
// IPAddress
//
IPAddress::IPAddress(): _pImpl(new IPv4AddressImpl)
{
}
IPAddress::IPAddress(const IPAddress& addr): _pImpl(addr._pImpl)
{
_pImpl->duplicate();
}
IPAddress::IPAddress(Family family): _pImpl(0)
{
if (family == IPv4)
_pImpl = new IPv4AddressImpl();
#if defined(POCO_HAVE_IPv6)
else if (family == IPv6)
_pImpl = new IPv6AddressImpl();
#endif
else Foundation::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
}
IPAddress::IPAddress(const std::string& addr)
{
_pImpl = IPv4AddressImpl::parse(addr);
#if defined(POCO_HAVE_IPv6)
if (!_pImpl)
_pImpl = IPv6AddressImpl::parse(addr);
#endif
if (!_pImpl) throw InvalidAddressException(addr);
}
IPAddress::IPAddress(const std::string& addr, Family family): _pImpl(0)
{
if (family == IPv4)
_pImpl = IPv4AddressImpl::parse(addr);
#if defined(POCO_HAVE_IPv6)
else if (family == IPv6)
_pImpl = IPv6AddressImpl::parse(addr);
#endif
else throw Foundation::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
}
IPAddress::IPAddress(const void* addr, poco_socklen_t length)
{
if (length == sizeof(struct in_addr))
_pImpl = new IPv4AddressImpl(addr);
#if defined(POCO_HAVE_IPv6)
else if (length == sizeof(struct in6_addr))
_pImpl = new IPv6AddressImpl(addr);
#endif
else throw Foundation::InvalidArgumentException("Invalid address length passed to IPAddress()");
}
IPAddress::~IPAddress()
{
_pImpl->release();
}
IPAddress& IPAddress::operator = (const IPAddress& addr)
{
if (&addr != this)
{
_pImpl->release();
_pImpl = addr._pImpl;
_pImpl->duplicate();
}
return *this;
}
void IPAddress::swap(IPAddress& address)
{
std::swap(_pImpl, address._pImpl);
}
IPAddress::Family IPAddress::family() const
{
return _pImpl->family();
}
std::string IPAddress::toString() const
{
return _pImpl->toString();
}
bool IPAddress::isWildcard() const
{
return _pImpl->isWildcard();
}
bool IPAddress::isBroadcast() const
{
return _pImpl->isBroadcast();
}
bool IPAddress::isLoopback() const
{
return _pImpl->isLoopback();
}
bool IPAddress::isMulticast() const
{
return _pImpl->isMulticast();
}
bool IPAddress::isUnicast() const
{
return !isWildcard() && !isBroadcast() && !isMulticast();
}
bool IPAddress::isLinkLocal() const
{
return _pImpl->isLinkLocal();
}
bool IPAddress::isSiteLocal() const
{
return _pImpl->isSiteLocal();
}
bool IPAddress::isIPv4Compatible() const
{
return _pImpl->isIPv4Compatible();
}
bool IPAddress::isIPv4Mapped() const
{
return _pImpl->isIPv4Mapped();
}
bool IPAddress::isWellKnownMC() const
{
return _pImpl->isWellKnownMC();
}
bool IPAddress::isNodeLocalMC() const
{
return _pImpl->isNodeLocalMC();
}
bool IPAddress::isLinkLocalMC() const
{
return _pImpl->isLinkLocalMC();
}
bool IPAddress::isSiteLocalMC() const
{
return _pImpl->isSiteLocalMC();
}
bool IPAddress::isOrgLocalMC() const
{
return _pImpl->isOrgLocalMC();
}
bool IPAddress::isGlobalMC() const
{
return _pImpl->isGlobalMC();
}
bool IPAddress::operator == (const IPAddress& a) const
{
poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length();
if (l1 == l2)
return memcmp(addr(), a.addr(), l1) == 0;
else
return false;
}
bool IPAddress::operator != (const IPAddress& a) const
{
poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length();
if (l1 == l2)
return memcmp(addr(), a.addr(), l1) != 0;
else
return true;
}
bool IPAddress::operator < (const IPAddress& a) const
{
poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length();
if (l1 == l2)
return memcmp(addr(), a.addr(), l1) < 0;
else
return l1 < l2;
}
bool IPAddress::operator <= (const IPAddress& a) const
{
poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length();
if (l1 == l2)
return memcmp(addr(), a.addr(), l1) <= 0;
else
return l1 < l2;
}
bool IPAddress::operator > (const IPAddress& a) const
{
poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length();
if (l1 == l2)
return memcmp(addr(), a.addr(), l1) > 0;
else
return l1 > l2;
}
bool IPAddress::operator >= (const IPAddress& a) const
{
poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length();
if (l1 == l2)
return memcmp(addr(), a.addr(), l1) >= 0;
else
return l1 > l2;
}
poco_socklen_t IPAddress::length() const
{
return _pImpl->length();
}
const void* IPAddress::addr() const
{
return _pImpl->addr();
}
int IPAddress::af() const
{
return _pImpl->af();
}
void IPAddress::init(IPAddressImpl* pImpl)
{
_pImpl->release();
_pImpl = pImpl;
}
IPAddress IPAddress::parse(const std::string& addr)
{
return IPAddress(addr);
}
bool IPAddress::tryParse(const std::string& addr, IPAddress& result)
{
IPAddressImpl* pImpl = IPv4AddressImpl::parse(addr);
#if defined(POCO_HAVE_IPv6)
if (!pImpl) pImpl = IPv6AddressImpl::parse(addr);
#endif
if (pImpl)
{
result.init(pImpl);
return true;
}
else return false;
}
Net_END

492
Net/src/MailMessage.cpp Normal file
View File

@@ -0,0 +1,492 @@
//
// MailMessage.cpp
//
// $Id: //poco/1.1.0/Net/src/MailMessage.cpp#2 $
//
// Library: Net
// Package: Mail
// Module: MailMessage
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/MailMessage.h"
#include "Net/MediaType.h"
#include "Net/MultipartReader.h"
#include "Net/MultipartWriter.h"
#include "Net/PartSource.h"
#include "Net/PartHandler.h"
#include "Net/QuotedPrintableEncoder.h"
#include "Net/QuotedPrintableDecoder.h"
#include "Foundation/Base64Encoder.h"
#include "Foundation/Base64Decoder.h"
#include "Foundation/StreamCopier.h"
#include "Foundation/DateTimeFormat.h"
#include "Foundation/DateTimeFormatter.h"
#include "Foundation/DateTimeParser.h"
#include "Foundation/String.h"
#include <sstream>
#include <ctype.h>
using Foundation::Base64Encoder;
using Foundation::Base64Decoder;
using Foundation::StreamCopier;
using Foundation::DateTimeFormat;
using Foundation::DateTimeFormatter;
using Foundation::DateTimeParser;
using Foundation::icompare;
Net_BEGIN
namespace
{
class StringPartHandler: public PartHandler
{
public:
StringPartHandler(std::string& content):
_str(content)
{
}
~StringPartHandler()
{
}
void handlePart(const MessageHeader& header, std::istream& stream)
{
int ch = stream.get();
while (ch >= 0)
{
_str += (char) ch;
ch = stream.get();
}
}
private:
std::string& _str;
};
}
const std::string MailMessage::HEADER_SUBJECT("Subject");
const std::string MailMessage::HEADER_FROM("From");
const std::string MailMessage::HEADER_TO("To");
const std::string MailMessage::HEADER_CC("CC");
const std::string MailMessage::HEADER_BCC("BCC");
const std::string MailMessage::HEADER_DATE("Date");
const std::string MailMessage::HEADER_CONTENT_TYPE("Content-Type");
const std::string MailMessage::HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding");
const std::string MailMessage::HEADER_CONTENT_DISPOSITION("Content-Disposition");
const std::string MailMessage::HEADER_MIME_VERSION("Mime-Version");
const std::string MailMessage::EMPTY_HEADER;
const std::string MailMessage::TEXT_PLAIN("text/plain");
const std::string MailMessage::CTE_7BIT("7bit");
const std::string MailMessage::CTE_8BIT("8bit");
const std::string MailMessage::CTE_QUOTED_PRINTABLE("quoted-printable");
const std::string MailMessage::CTE_BASE64("base64");
MailMessage::MailMessage()
{
Foundation::Timestamp now;
setDate(now);
setContentType("text/plain");
}
MailMessage::~MailMessage()
{
for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it)
{
delete it->pSource;
}
}
void MailMessage::addRecipient(const MailRecipient& recipient)
{
_recipients.push_back(recipient);
}
void MailMessage::setSender(const std::string& sender)
{
set(HEADER_FROM, sender);
}
const std::string& MailMessage::getSender() const
{
if (has(HEADER_FROM))
return get(HEADER_FROM);
else
return EMPTY_HEADER;
}
void MailMessage::setSubject(const std::string& subject)
{
set(HEADER_SUBJECT, subject);
}
const std::string& MailMessage::getSubject() const
{
if (has(HEADER_SUBJECT))
return get(HEADER_SUBJECT);
else
return EMPTY_HEADER;
}
void MailMessage::setContent(const std::string& content, ContentTransferEncoding encoding)
{
_content = content;
_encoding = encoding;
set(HEADER_CONTENT_TRANSFER_ENCODING, contentTransferEncodingToString(encoding));
}
void MailMessage::setContentType(const std::string& mediaType)
{
set(HEADER_CONTENT_TYPE, mediaType);
}
void MailMessage::setContentType(const MediaType& mediaType)
{
setContentType(mediaType.toString());
}
const std::string& MailMessage::getContentType() const
{
if (has(HEADER_CONTENT_TYPE))
return get(HEADER_CONTENT_TYPE);
else
return TEXT_PLAIN;
}
void MailMessage::setDate(const Foundation::Timestamp& dateTime)
{
set(HEADER_DATE, DateTimeFormatter::format(dateTime, DateTimeFormat::RFC1123_FORMAT));
}
Foundation::Timestamp MailMessage::getDate() const
{
const std::string& dateTime = get(HEADER_DATE);
int tzd;
return DateTimeParser::parse(dateTime, tzd).timestamp();
}
bool MailMessage::isMultipart() const
{
MediaType mediaType = getContentType();
return mediaType.matches("multipart");
}
void MailMessage::addPart(const std::string& name, PartSource* pSource, ContentDisposition disposition, ContentTransferEncoding encoding)
{
poco_check_ptr (pSource);
makeMultipart();
Part part;
part.name = name;
part.pSource = pSource;
part.disposition = disposition;
part.encoding = encoding;
_parts.push_back(part);
}
void MailMessage::addContent(PartSource* pSource, ContentTransferEncoding encoding)
{
addPart("", pSource, CONTENT_INLINE, encoding);
}
void MailMessage::addAttachment(const std::string& name, PartSource* pSource, ContentTransferEncoding encoding)
{
addPart(name, pSource, CONTENT_ATTACHMENT, encoding);
}
void MailMessage::read(std::istream& istr, PartHandler& handler)
{
readHeader(istr);
if (isMultipart())
{
readMultipart(istr, handler);
}
else
{
StringPartHandler handler(_content);
readPart(istr, *this, handler);
}
}
void MailMessage::read(std::istream& istr)
{
readHeader(istr);
StringPartHandler handler(_content);
readPart(istr, *this, handler);
}
void MailMessage::write(std::ostream& ostr) const
{
MessageHeader header(*this);
setRecipientHeaders(header);
if (isMultipart())
{
writeMultipart(header, ostr);
}
else
{
writeHeader(header, ostr);
std::istringstream istr(_content);
writeEncoded(istr, ostr, _encoding);
}
}
void MailMessage::makeMultipart()
{
if (!isMultipart())
{
MediaType mediaType("multipart", "mixed");
setContentType(mediaType);
}
}
void MailMessage::writeHeader(const MessageHeader& header, std::ostream& ostr) const
{
header.write(ostr);
ostr << "\r\n";
}
void MailMessage::writeMultipart(MessageHeader& header, std::ostream& ostr) const
{
std::string boundary(MultipartWriter::createBoundary());
MediaType mediaType(getContentType());
mediaType.setParameter("boundary", boundary);
header.set(HEADER_CONTENT_TYPE, mediaType.toString());
header.set(HEADER_MIME_VERSION, "1.0");
writeHeader(header, ostr);
MultipartWriter writer(ostr, boundary);
for (PartVec::const_iterator it = _parts.begin(); it != _parts.end(); ++it)
{
writePart(writer, *it);
}
writer.close();
}
void MailMessage::writePart(MultipartWriter& writer, const Part& part) const
{
MessageHeader partHeader;
MediaType mediaType(part.pSource->mediaType());
if (!part.name.empty())
mediaType.setParameter("name", part.name);
partHeader.set(HEADER_CONTENT_TYPE, mediaType.toString());
partHeader.set(HEADER_CONTENT_TRANSFER_ENCODING, contentTransferEncodingToString(part.encoding));
std::string disposition;
if (part.disposition == CONTENT_ATTACHMENT)
{
disposition = "attachment";
const std::string& filename = part.pSource->filename();
if (!filename.empty())
{
disposition.append("; filename=");
quote(filename, disposition);
}
}
else disposition = "inline";
partHeader.set(HEADER_CONTENT_DISPOSITION, disposition);
writer.nextPart(partHeader);
writeEncoded(part.pSource->stream(), writer.stream(), part.encoding);
}
void MailMessage::writeEncoded(std::istream& istr, std::ostream& ostr, ContentTransferEncoding encoding) const
{
switch (encoding)
{
case ENCODING_7BIT:
case ENCODING_8BIT:
StreamCopier::copyStream(istr, ostr);
break;
case ENCODING_QUOTED_PRINTABLE:
{
QuotedPrintableEncoder encoder(ostr);
StreamCopier::copyStream(istr, encoder);
}
break;
case ENCODING_BASE64:
{
Base64Encoder encoder(ostr);
StreamCopier::copyStream(istr, encoder);
}
break;
}
}
void MailMessage::readHeader(std::istream& istr)
{
clear();
MessageHeader::read(istr);
istr.get(); // \r
istr.get(); // \n
}
void MailMessage::readMultipart(std::istream& istr, PartHandler& handler)
{
MediaType contentType(getContentType());
std::string boundary = contentType.getParameter("boundary");
MultipartReader reader(istr, boundary);
while (reader.hasNextPart())
{
MessageHeader partHeader;
reader.nextPart(partHeader);
readPart(reader.stream(), partHeader, handler);
}
}
void MailMessage::readPart(std::istream& istr, const MessageHeader& header, PartHandler& handler)
{
std::string encoding;
if (header.has(HEADER_CONTENT_TRANSFER_ENCODING))
{
encoding = header.get(HEADER_CONTENT_TRANSFER_ENCODING);
// get rid of a parameter if one is set
std::string::size_type pos = encoding.find(';');
if (pos != std::string::npos)
encoding.resize(pos);
}
if (icompare(encoding, CTE_QUOTED_PRINTABLE) == 0)
{
QuotedPrintableDecoder decoder(istr);
handler.handlePart(header, decoder);
}
else if (icompare(encoding, CTE_BASE64) == 0)
{
Base64Decoder decoder(istr);
handler.handlePart(header, decoder);
}
else
{
handler.handlePart(header, istr);
}
}
void MailMessage::setRecipientHeaders(MessageHeader& headers) const
{
std::string to;
std::string cc;
std::string bcc;
for (Recipients::const_iterator it = _recipients.begin(); it != _recipients.end(); ++it)
{
switch (it->getType())
{
case MailRecipient::PRIMARY_RECIPIENT:
appendRecipient(*it, to);
break;
case MailRecipient::CC_RECIPIENT:
appendRecipient(*it, cc);
break;
}
}
if (!to.empty()) headers.set(HEADER_TO, to);
if (!cc.empty()) headers.set(HEADER_CC, cc);
}
const std::string& MailMessage::contentTransferEncodingToString(ContentTransferEncoding encoding)
{
switch (encoding)
{
case ENCODING_7BIT:
return CTE_8BIT;
case ENCODING_8BIT:
return CTE_8BIT;
case ENCODING_QUOTED_PRINTABLE:
return CTE_QUOTED_PRINTABLE;
case ENCODING_BASE64:
return CTE_BASE64;
default:
poco_bugcheck();
}
return CTE_7BIT;
}
int MailMessage::lineLength(const std::string& str)
{
int n = 0;
std::string::const_reverse_iterator it = str.rbegin();
std::string::const_reverse_iterator end = str.rend();
while (it != end && *it != '\n') { ++n; ++it; }
return n;
}
void MailMessage::appendRecipient(const MailRecipient& recipient, std::string& str)
{
if (!str.empty()) str.append(", ");
const std::string& realName = recipient.getRealName();
const std::string& address = recipient.getAddress();
std::string rec;
if (!realName.empty())
{
quote(realName, rec, true);
rec.append(" ");
}
rec.append("<");
rec.append(address);
rec.append(">");
if (lineLength(str) + rec.length() > 70) str.append("\r\n\t");
str.append(rec);
}
Net_END

115
Net/src/MailRecipient.cpp Normal file
View File

@@ -0,0 +1,115 @@
//
// MailRecipient.cpp
//
// $Id: //poco/1.1.0/Net/src/MailRecipient.cpp#2 $
//
// Library: Net
// Package: Mail
// Module: MailRecipient
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/MailRecipient.h"
#include <algorithm>
Net_BEGIN
MailRecipient::MailRecipient():
_type(PRIMARY_RECIPIENT)
{
}
MailRecipient::MailRecipient(const MailRecipient& recipient):
_type(recipient._type),
_address(recipient._address),
_realName(recipient._realName)
{
}
MailRecipient::MailRecipient(RecipientType type, const std::string& address):
_type(type),
_address(address)
{
}
MailRecipient::MailRecipient(RecipientType type, const std::string& address, const std::string& realName):
_type(type),
_address(address),
_realName(realName)
{
}
MailRecipient::~MailRecipient()
{
}
MailRecipient& MailRecipient::operator = (const MailRecipient& recipient)
{
if (this != &recipient)
{
MailRecipient tmp(recipient);
swap(tmp);
}
return *this;
}
void MailRecipient::swap(MailRecipient& recipient)
{
std::swap(_type, recipient._type);
std::swap(_address, recipient._address);
std::swap(_realName, recipient._realName);
}
void MailRecipient::setType(RecipientType type)
{
_type = type;
}
void MailRecipient::setAddress(const std::string& address)
{
_address = address;
}
void MailRecipient::setRealName(const std::string& realName)
{
_realName = realName;
}
Net_END

240
Net/src/MailStream.cpp Normal file
View File

@@ -0,0 +1,240 @@
//
// MailStream.cpp
//
// $Id: //poco/1.1.0/Net/src/MailStream.cpp#2 $
//
// Library: Net
// Package: Mail
// Module: MailStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/MailStream.h"
Net_BEGIN
MailStreamBuf::MailStreamBuf(std::istream& istr):
_pIstr(&istr),
_pOstr(0),
_state(ST_CR_LF)
{
}
MailStreamBuf::MailStreamBuf(std::ostream& ostr):
_pIstr(0),
_pOstr(&ostr),
_state(ST_CR_LF)
{
}
MailStreamBuf::~MailStreamBuf()
{
}
void MailStreamBuf::close()
{
if (_pOstr && _state != ST_CR_LF_DOT_CR_LF)
{
if (!_buffer.empty())
_pOstr->write(_buffer.data(), (std::streamsize) _buffer.length());
if (_state != ST_CR_LF)
_pOstr->write("\r\n", 2);
_pOstr->write(".\r\n", 3);
_state = ST_CR_LF_DOT_CR_LF;
}
}
int MailStreamBuf::readFromDevice()
{
int c = std::char_traits<char>::eof();
if (!_buffer.empty())
{
c = _buffer[0];
_buffer.erase(0, 1);
}
else
{
c = readOne();
while (c != std::char_traits<char>::eof() && _state != ST_DATA && _state != ST_CR_LF_DOT_CR_LF)
c = readOne();
if (!_buffer.empty())
{
c = _buffer[0];
_buffer.erase(0, 1);
}
}
return c;
}
int MailStreamBuf::readOne()
{
int c = std::char_traits<char>::eof();
if (_state != ST_CR_LF_DOT_CR_LF)
{
c = _pIstr->get();
switch (c)
{
case '\r':
if (_state == ST_CR_LF_DOT)
_state = ST_CR_LF_DOT_CR;
else
_state = ST_CR;
break;
case '\n':
if (_state == ST_CR)
_state = ST_CR_LF;
else if (_state == ST_CR_LF_DOT_CR)
_state = ST_CR_LF_DOT_CR_LF;
else
_state = ST_DATA;
break;
case '.':
if (_state == ST_CR_LF)
_state = ST_CR_LF_DOT;
else if (_state == ST_CR_LF_DOT)
_state = ST_CR_LF_DOT_DOT;
else
_state = ST_DATA;
break;
default:
_state = ST_DATA;
}
if (_state == ST_CR_LF_DOT_DOT)
_state = ST_DATA;
else if (_state == ST_CR_LF_DOT_CR_LF)
_buffer.resize(_buffer.size() - 2);
else if (c != std::char_traits<char>::eof())
_buffer += (char) c;
}
return c;
}
int MailStreamBuf::writeToDevice(char c)
{
switch (c)
{
case '\r':
_state = ST_CR;
break;
case '\n':
if (_state == ST_CR)
_state = ST_CR_LF;
else
_state = ST_DATA;
break;
case '.':
if (_state == ST_CR_LF)
_state = ST_CR_LF_DOT;
else
_state = ST_DATA;
break;
default:
_state = ST_DATA;
}
if (_state == ST_DATA)
{
if (!_buffer.empty())
{
_pOstr->write(_buffer.data(), (std::streamsize) _buffer.length());
_buffer.clear();
}
_pOstr->put(c);
}
else if (_state == ST_CR_LF_DOT)
{
_pOstr->write("\r\n..", 4);
_state = ST_DATA;
_buffer.clear();
}
else _buffer += c;
return charToInt(c);
}
MailIOS::MailIOS(std::istream& istr): _buf(istr)
{
poco_ios_init(&_buf);
}
MailIOS::MailIOS(std::ostream& ostr): _buf(ostr)
{
poco_ios_init(&_buf);
}
MailIOS::~MailIOS()
{
}
void MailIOS::close()
{
_buf.close();
}
MailStreamBuf* MailIOS::rdbuf()
{
return &_buf;
}
MailInputStream::MailInputStream(std::istream& istr):
MailIOS(istr),
std::istream(&_buf)
{
}
MailInputStream::~MailInputStream()
{
}
MailOutputStream::MailOutputStream(std::ostream& ostr):
MailIOS(ostr),
std::ostream(&_buf)
{
}
MailOutputStream::~MailOutputStream()
{
}
Net_END

190
Net/src/MediaType.cpp Normal file
View File

@@ -0,0 +1,190 @@
//
// MediaType.cpp
//
// $Id: //poco/1.1.0/Net/src/MediaType.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: MediaType
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/MediaType.h"
#include "Net/MessageHeader.h"
#include "Foundation/String.h"
#include <algorithm>
#include <ctype.h>
using Foundation::icompare;
Net_BEGIN
MediaType::MediaType(const std::string& mediaType)
{
parse(mediaType);
}
MediaType::MediaType(const std::string& type, const std::string& subType):
_type(type),
_subType(subType)
{
}
MediaType::MediaType(const MediaType& mediaType):
_type(mediaType._type),
_subType(mediaType._subType),
_parameters(mediaType._parameters)
{
}
MediaType::~MediaType()
{
}
MediaType& MediaType::operator = (const MediaType& mediaType)
{
if (&mediaType != this)
{
_type = mediaType._type;
_subType = mediaType._subType;
_parameters = mediaType._parameters;
}
return *this;
}
MediaType& MediaType::operator = (const std::string& mediaType)
{
parse(mediaType);
return *this;
}
void MediaType::swap(MediaType& mediaType)
{
std::swap(_type, mediaType._type);
std::swap(_subType, mediaType._subType);
_parameters.swap(mediaType._parameters);
}
void MediaType::setType(const std::string& type)
{
_type = type;
}
void MediaType::setSubType(const std::string& subType)
{
_subType = subType;
}
void MediaType::setParameter(const std::string& name, const std::string& value)
{
_parameters.set(name, value);
}
const std::string& MediaType::getParameter(const std::string& name) const
{
return _parameters.get(name);
}
bool MediaType::hasParameter(const std::string& name) const
{
return _parameters.has(name);
}
void MediaType::removeParameter(const std::string& name)
{
_parameters.erase(name);
}
std::string MediaType::toString() const
{
std::string result;
result.append(_type);
result.append("/");
result.append(_subType);
for (NameValueCollection::ConstIterator it = _parameters.begin(); it != _parameters.end(); ++it)
{
result.append("; ");
result.append(it->first);
result.append("=");
MessageHeader::quote(it->second, result);
}
return result;
}
bool MediaType::matches(const MediaType& mediaType) const
{
return matches(mediaType._type, mediaType._subType);
}
bool MediaType::matches(const std::string& type, const std::string& subType) const
{
return icompare(_type, type) == 0 && icompare(_subType, subType) == 0;
}
bool MediaType::matches(const std::string& type) const
{
return icompare(_type, type) == 0;
}
void MediaType::parse(const std::string& mediaType)
{
_type.clear();
_subType.clear();
_parameters.clear();
std::string::const_iterator it = mediaType.begin();
std::string::const_iterator end = mediaType.end();
while (it != end && isspace(*it)) ++it;
while (it != end && *it != '/') _type += *it++;
if (it != end) ++it;
while (it != end && *it != ';' && !isspace(*it)) _subType += *it++;
while (it != end && *it != ';') ++it;
MessageHeader::splitParameters(it, end, _parameters);
}
Net_END

229
Net/src/MessageHeader.cpp Normal file
View File

@@ -0,0 +1,229 @@
//
// MessageHeader.cpp
//
// $Id: //poco/1.1.0/Net/src/MessageHeader.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: MessageHeader
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/MessageHeader.h"
#include "Net/NetException.h"
#include "Foundation/String.h"
#include <ctype.h>
Net_BEGIN
MessageHeader::MessageHeader()
{
}
MessageHeader::MessageHeader(const MessageHeader& messageHeader):
NameValueCollection(messageHeader)
{
}
MessageHeader::~MessageHeader()
{
}
MessageHeader& MessageHeader::operator = (const MessageHeader& messageHeader)
{
NameValueCollection::operator = (messageHeader);
return *this;
}
void MessageHeader::write(std::ostream& ostr) const
{
NameValueCollection::ConstIterator it = begin();
while (it != end())
{
ostr << it->first << ": " << it->second << "\r\n";
++it;
}
}
void MessageHeader::read(std::istream& istr)
{
static const int eof = std::char_traits<char>::eof();
int ch = istr.get();
while (ch != eof && ch != '\r' && ch != '\n')
{
std::string name;
std::string value;
while (ch != eof && ch != ':' && name.length() < MAX_NAME_LENGTH) { name += ch; ch = istr.get(); }
if (ch != ':') throw MessageException("Field name too long/no colon found");
if (ch != eof) ch = istr.get(); // ':'
while (isspace(ch)) ch = istr.get();
while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += ch; ch = istr.get(); }
if (ch == '\r') ch = istr.get();
if (ch == '\n')
ch = istr.get();
else if (ch != eof)
throw MessageException("Field value too long/no CRLF found");
while (ch == ' ' || ch == '\t') // folding
{
while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += ch; ch = istr.get(); }
if (ch == '\r') ch = istr.get();
if (ch == '\n')
ch = istr.get();
else if (ch != eof)
throw MessageException("Folded field value too long/no CRLF found");
}
add(name, value);
}
istr.putback(ch);
}
void MessageHeader::splitElements(const std::string& s, std::vector<std::string>& elements, bool ignoreEmpty)
{
elements.clear();
std::string::const_iterator it = s.begin();
std::string::const_iterator end = s.end();
std::string elem;
while (it != end)
{
if (*it == '"')
{
elem += *it++;
while (it != end && *it != '"')
{
if (*it == '\\')
{
++it;
if (it != end) elem += *it++;
}
else elem += *it++;
}
if (it != end) elem += *it++;
}
else if (*it == '\\')
{
++it;
if (it != end) elem += *it++;
}
else if (*it == ',')
{
Foundation::trimInPlace(elem);
if (!ignoreEmpty || !elem.empty())
elements.push_back(elem);
elem.clear();
++it;
}
else elem += *it++;
}
if (!elem.empty())
{
Foundation::trimInPlace(elem);
if (!ignoreEmpty || !elem.empty())
elements.push_back(elem);
}
}
void MessageHeader::splitParameters(const std::string& s, std::string& value, NameValueCollection& parameters)
{
value.clear();
parameters.clear();
std::string::const_iterator it = s.begin();
std::string::const_iterator end = s.end();
while (it != end && isspace(*it)) ++it;
while (it != end && *it != ';') value += *it++;
Foundation::trimRightInPlace(value);
if (it != end) ++it;
splitParameters(it, end, parameters);
}
void MessageHeader::splitParameters(const std::string::const_iterator& begin, const std::string::const_iterator& end, NameValueCollection& parameters)
{
std::string::const_iterator it = begin;
while (it != end)
{
std::string pname;
std::string pvalue;
while (it != end && isspace(*it)) ++it;
while (it != end && *it != '=' && *it != ';') pname += *it++;
Foundation::trimRightInPlace(pname);
if (it != end && *it != ';') ++it;
while (it != end && isspace(*it)) ++it;
while (it != end && *it != ';')
{
if (*it == '"')
{
++it;
while (it != end && *it != '"')
{
if (*it == '\\')
{
++it;
if (it != end) pvalue += *it++;
}
else pvalue += *it++;
}
if (it != end) ++it;
}
else if (*it == '\\')
{
++it;
if (it != end) pvalue += *it++;
}
else pvalue += *it++;
}
Foundation::trimRightInPlace(pvalue);
if (!pname.empty()) parameters.add(pname, pvalue);
if (it != end) ++it;
}
}
void MessageHeader::quote(const std::string& value, std::string& result, bool allowSpace)
{
bool mustQuote = false;
for (std::string::const_iterator it = value.begin(); !mustQuote && it != value.end(); ++it)
{
if (!isalnum(*it) && *it != '.' && *it != '_' && *it != '-' && !(isspace(*it) && allowSpace))
mustQuote = true;
}
if (mustQuote) result += '"';
result.append(value);
if (mustQuote) result += '"';
}
Net_END

260
Net/src/MulticastSocket.cpp Normal file
View File

@@ -0,0 +1,260 @@
//
// MulticastSocket.cpp
//
// $Id: //poco/1.1.0/Net/src/MulticastSocket.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: MulticastSocket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/MulticastSocket.h"
#include "Net/NetException.h"
#include <string.h>
#if defined(hpux) && defined(_XOPEN_SOURCE_EXTENDED)
// netinet/in.h does not define struct ip_mreq if
// _XOPEN_SOURCE_EXTENDED is #define'd.
struct ip_mreq
{
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
};
#endif
// some Unix variants don't have IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP
#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP)
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
#endif
Net_BEGIN
MulticastSocket::MulticastSocket()
{
}
MulticastSocket::MulticastSocket(IPAddress::Family family): DatagramSocket(family)
{
}
MulticastSocket::MulticastSocket(const SocketAddress& address, bool reuseAddress): DatagramSocket(address, reuseAddress)
{
}
MulticastSocket::MulticastSocket(const Socket& socket): DatagramSocket(socket)
{
}
MulticastSocket::~MulticastSocket()
{
}
MulticastSocket& MulticastSocket::operator = (const Socket& socket)
{
DatagramSocket::operator = (socket);
return *this;
}
void MulticastSocket::setInterface(const NetworkInterface& interface)
{
if (!interface.supportsIPv6())
{
impl()->setOption(IPPROTO_IP, IP_MULTICAST_IF, interface.address());
}
else
{
#if defined(POCO_HAVE_IPv6)
impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, interface.index());
#endif
}
}
NetworkInterface MulticastSocket::getInterface() const
{
try
{
IPAddress addr;
impl()->getOption(IPPROTO_IP, IP_MULTICAST_IF, addr);
return NetworkInterface::forAddress(addr);
}
catch (Foundation::Exception&)
{
#if defined(POCO_HAVE_IPv6)
int ix;
impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, ix);
return NetworkInterface::forIndex(ix);
#else
throw;
#endif
}
}
void MulticastSocket::setLoopback(bool flag)
{
if (address().af() == AF_INET)
{
unsigned char uflag = flag ? 1 : 0;
impl()->setOption(IPPROTO_IP, IP_MULTICAST_LOOP, uflag);
}
else
{
#if defined(POCO_HAVE_IPv6)
unsigned uflag = flag ? 1 : 0;
impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_LOOP, uflag);
#endif
}
}
bool MulticastSocket::getLoopback() const
{
bool flag = false;
if (address().af() == AF_INET)
{
unsigned char uflag;
impl()->getOption(IPPROTO_IP, IP_MULTICAST_LOOP, uflag);
flag = uflag != 0;
}
else
{
#if defined(POCO_HAVE_IPv6)
unsigned uflag;
impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_LOOP, uflag);
flag = uflag != 0;
#endif
}
return flag;
}
void MulticastSocket::setTimeToLive(unsigned value)
{
if (address().af() == AF_INET)
{
unsigned char ttl = (unsigned char) value;
impl()->setOption(IPPROTO_IP, IP_MULTICAST_TTL, ttl);
}
else
{
#if defined(POCO_HAVE_IPv6)
impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_HOPS, value);
#endif
}
}
unsigned MulticastSocket::getTimeToLive() const
{
unsigned ttl;
if (address().af() == AF_INET)
{
unsigned char cttl;
impl()->getOption(IPPROTO_IP, IP_MULTICAST_TTL, cttl);
ttl = cttl;
}
else
{
#if defined(POCO_HAVE_IPv6)
impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ttl);
#endif
}
return ttl;
}
void MulticastSocket::joinGroup(const IPAddress& groupAddress)
{
NetworkInterface intf;
joinGroup(groupAddress, intf);
}
void MulticastSocket::joinGroup(const IPAddress& groupAddress, const NetworkInterface& interface)
{
if (groupAddress.af() == AF_INET)
{
struct ip_mreq mr;
memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length());
memcpy(&mr.imr_interface, interface.address().addr(), interface.address().length());
impl()->setRawOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr));
}
else
{
#if defined(POCO_HAVE_IPv6)
struct ipv6_mreq mr;
memcpy(&mr.ipv6mr_multiaddr, groupAddress.addr(), groupAddress.length());
mr.ipv6mr_interface = interface.index();
impl()->setRawOption(IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr, sizeof(mr));
#endif
}
}
void MulticastSocket::leaveGroup(const IPAddress& groupAddress)
{
NetworkInterface intf;
leaveGroup(groupAddress, intf);
}
void MulticastSocket::leaveGroup(const IPAddress& groupAddress, const NetworkInterface& interface)
{
if (groupAddress.af() == AF_INET)
{
struct ip_mreq mr;
memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length());
memcpy(&mr.imr_interface, interface.address().addr(), interface.address().length());
impl()->setRawOption(IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr));
}
else
{
#if defined(POCO_HAVE_IPv6)
struct ipv6_mreq mr;
memcpy(&mr.ipv6mr_multiaddr, groupAddress.addr(), groupAddress.length());
mr.ipv6mr_interface = interface.index();
impl()->setRawOption(IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mr, sizeof(mr));
#endif
}
}
Net_END

316
Net/src/MultipartReader.cpp Normal file
View File

@@ -0,0 +1,316 @@
//
// MultipartReader.cpp
//
// $Id: //poco/1.1.0/Net/src/MultipartReader.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: MultipartReader
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/MultipartReader.h"
#include "Net/MessageHeader.h"
#include "Net/NetException.h"
#include <ctype.h>
using Foundation::BufferedStreamBuf;
Net_BEGIN
//
// MultipartStreamBuf
//
MultipartStreamBuf::MultipartStreamBuf(std::istream& istr, const std::string& boundary):
BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in),
_istr(istr),
_boundary(boundary),
_lastPart(false)
{
poco_assert (!boundary.empty() && boundary.length() < STREAM_BUFFER_SIZE - 6);
}
MultipartStreamBuf::~MultipartStreamBuf()
{
}
int MultipartStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
poco_assert_dbg (length >= _boundary.length() + 6);
static const int eof = std::char_traits<char>::eof();
int n = 0;
int ch = _istr.get();
*buffer++ = (char) ch; ++n;
if (ch == '\n' || ch == '\r' && _istr.peek() == '\n')
{
if (ch == '\r')
{
ch = _istr.get(); // '\n'
*buffer++ = (char) ch; ++n;
}
ch = _istr.peek();
if (ch == '\r' || ch == '\n') return n;
*buffer++ = (char) _istr.get(); ++n;
if (ch == '-' && _istr.peek() == '-')
{
ch = _istr.get(); // '-'
*buffer++ = (char) ch; ++n;
std::string::const_iterator it = _boundary.begin();
std::string::const_iterator end = _boundary.end();
ch = _istr.get();
*buffer++ = (char) ch; ++n;
while (it != end && ch == *it)
{
++it;
ch = _istr.get();
*buffer++ = (char) ch; ++n;
}
if (it == end)
{
if (ch == '\n' || ch == '\r' && _istr.peek() == '\n')
{
if (ch == '\r')
{
ch = _istr.get(); // '\n'
return 0;
}
}
else if (ch == '-' && _istr.peek() == '-')
{
ch = _istr.get(); // '-'
_lastPart = true;
return 0;
}
}
}
}
ch = _istr.peek();
while (ch != eof && ch != '\r' && ch != '\n' && n < length)
{
*buffer++ = (char) _istr.get(); ++n;
ch = _istr.peek();
}
return n;
}
bool MultipartStreamBuf::lastPart() const
{
return _lastPart;
}
//
// MultipartIOS
//
MultipartIOS::MultipartIOS(std::istream& istr, const std::string& boundary):
_buf(istr, boundary)
{
poco_ios_init(&_buf);
}
MultipartIOS::~MultipartIOS()
{
_buf.sync();
}
MultipartStreamBuf* MultipartIOS::rdbuf()
{
return &_buf;
}
bool MultipartIOS::lastPart() const
{
return _buf.lastPart();
}
//
// MultipartInputStream
//
MultipartInputStream::MultipartInputStream(std::istream& istr, const std::string& boundary):
MultipartIOS(istr, boundary),
std::istream(&_buf)
{
}
MultipartInputStream::~MultipartInputStream()
{
}
//
// MultipartReader
//
MultipartReader::MultipartReader(std::istream& istr):
_istr(istr),
_pMPI(0)
{
}
MultipartReader::MultipartReader(std::istream& istr, const std::string& boundary):
_istr(istr),
_boundary(boundary),
_pMPI(0)
{
}
MultipartReader::~MultipartReader()
{
delete _pMPI;
}
void MultipartReader::nextPart(MessageHeader& messageHeader)
{
if (!_pMPI)
{
if (_boundary.empty())
guessBoundary();
else
findFirstBoundary();
}
else if (_pMPI->lastPart())
{
throw MultipartException("No more parts available");
}
parseHeader(messageHeader);
delete _pMPI;
_pMPI = new MultipartInputStream(_istr, _boundary);
}
bool MultipartReader::hasNextPart()
{
return (!_pMPI || !_pMPI->lastPart()) && _istr.good();
}
std::istream& MultipartReader::stream() const
{
poco_check_ptr (_pMPI);
return *_pMPI;
}
const std::string& MultipartReader::boundary() const
{
return _boundary;
}
void MultipartReader::findFirstBoundary()
{
std::string expect("--");
expect.append(_boundary);
std::string line;
line.reserve(expect.length());
bool ok = true;
do
{
ok = readLine(line, expect.length());
}
while (ok && line != expect);
if (!ok) throw MultipartException("No boundary line found");
}
void MultipartReader::guessBoundary()
{
static const int eof = std::char_traits<char>::eof();
int ch = _istr.get();
while (isspace(ch))
ch = _istr.get();
if (ch == '-' && _istr.peek() == '-')
{
_istr.get();
ch = _istr.peek();
while (ch != eof && ch != '\r' && ch != '\n')
{
_boundary += (char) _istr.get();
ch = _istr.peek();
}
if (ch == '\r' || ch == '\n')
ch = _istr.get();
if (_istr.peek() == '\n')
_istr.get();
}
else throw MultipartException("No boundary line found");
}
void MultipartReader::parseHeader(MessageHeader& messageHeader)
{
messageHeader.clear();
messageHeader.read(_istr);
int ch = _istr.get();
if (ch == '\r' && _istr.peek() == '\n') ch = _istr.get();
}
bool MultipartReader::readLine(std::string& line, std::string::size_type n)
{
static const int eof = std::char_traits<char>::eof();
line.clear();
int ch = _istr.peek();
while (ch != eof && ch != '\r' && ch != '\n')
{
ch = (char) _istr.get();
if (line.length() < n) line += ch;
ch = _istr.peek();
}
if (ch != eof) _istr.get();
if (ch == '\r' && _istr.peek() == '\n') _istr.get();
return ch != eof;
}
Net_END

101
Net/src/MultipartWriter.cpp Normal file
View File

@@ -0,0 +1,101 @@
//
// MultipartWriter.cpp
//
// $Id: //poco/1.1.0/Net/src/MultipartWriter.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: MultipartWriter
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/MultipartWriter.h"
#include "Net/MessageHeader.h"
#include "Foundation/Random.h"
#include "Foundation/NumberFormatter.h"
using Foundation::Random;
using Foundation::NumberFormatter;
Net_BEGIN
MultipartWriter::MultipartWriter(std::ostream& ostr):
_ostr(ostr),
_boundary(createBoundary())
{
}
MultipartWriter::MultipartWriter(std::ostream& ostr, const std::string& boundary):
_ostr(ostr),
_boundary(boundary)
{
if (_boundary.empty())
_boundary = createBoundary();
}
MultipartWriter::~MultipartWriter()
{
}
void MultipartWriter::nextPart(const MessageHeader& header)
{
_ostr << "\r\n--" << _boundary << "\r\n";
header.write(_ostr);
_ostr << "\r\n";
}
void MultipartWriter::close()
{
_ostr << "\r\n--" << _boundary << "--\r\n";
}
const std::string& MultipartWriter::boundary() const
{
return _boundary;
}
std::string MultipartWriter::createBoundary()
{
std::string boundary("MIME_boundary_");
Random rnd;
boundary.append(NumberFormatter::formatHex(rnd.next(), 8));
boundary.append(NumberFormatter::formatHex(rnd.next(), 8));
return boundary;
}
Net_END

View File

@@ -0,0 +1,163 @@
//
// NameValueCollection.cpp
//
// $Id: //poco/1.1.0/Net/src/NameValueCollection.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: NameValueCollection
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/NameValueCollection.h"
#include "Foundation/Exception.h"
#include <algorithm>
using Foundation::NotFoundException;
Net_BEGIN
NameValueCollection::NameValueCollection()
{
}
NameValueCollection::NameValueCollection(const NameValueCollection& nvc):
_map(nvc._map)
{
}
NameValueCollection::~NameValueCollection()
{
}
NameValueCollection& NameValueCollection::operator = (const NameValueCollection& nvc)
{
if (&nvc != this)
{
_map = nvc._map;
}
return *this;
}
void NameValueCollection::swap(NameValueCollection& nvc)
{
std::swap(_map, nvc._map);
}
const std::string& NameValueCollection::operator [] (const std::string& name) const
{
ConstIterator it = _map.find(name);
if (it != _map.end())
return it->second;
else
throw NotFoundException(name);
}
void NameValueCollection::set(const std::string& name, const std::string& value)
{
Iterator it = _map.find(name);
if (it != _map.end())
_map.erase(it);
_map.insert(HeaderMap::value_type(name, value));
}
void NameValueCollection::add(const std::string& name, const std::string& value)
{
_map.insert(HeaderMap::value_type(name, value));
}
const std::string& NameValueCollection::get(const std::string& name) const
{
ConstIterator it = _map.find(name);
if (it != _map.end())
return it->second;
else
throw NotFoundException(name);
}
bool NameValueCollection::has(const std::string& name) const
{
return _map.find(name) != _map.end();
}
NameValueCollection::ConstIterator NameValueCollection::find(const std::string& name) const
{
return _map.find(name);
}
NameValueCollection::ConstIterator NameValueCollection::begin() const
{
return _map.begin();
}
NameValueCollection::ConstIterator NameValueCollection::end() const
{
return _map.end();
}
bool NameValueCollection::empty() const
{
return _map.empty();
}
int NameValueCollection::size() const
{
return (int) _map.size();
}
void NameValueCollection::erase(const std::string& name)
{
_map.erase(name);
}
void NameValueCollection::clear()
{
_map.clear();
}
Net_END

66
Net/src/NetException.cpp Normal file
View File

@@ -0,0 +1,66 @@
//
// NetException.cpp
//
// $Id: //poco/1.1.0/Net/src/NetException.cpp#2 $
//
// Library: Net
// Package: NetCore
// Module: NetException
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/NetException.h"
#include <typeinfo>
using Foundation::IOException;
Net_BEGIN
POCO_IMPLEMENT_EXCEPTION(NetException, IOException, "Net Exception")
POCO_IMPLEMENT_EXCEPTION(InvalidAddressException, NetException, "Invalid address")
POCO_IMPLEMENT_EXCEPTION(ServiceNotFoundException, NetException, "Service not found")
POCO_IMPLEMENT_EXCEPTION(ConnectionAbortedException, NetException, "Software caused connection abort")
POCO_IMPLEMENT_EXCEPTION(ConnectionResetException, NetException, "Connection reset by peer")
POCO_IMPLEMENT_EXCEPTION(ConnectionRefusedException, NetException, "Connection refused")
POCO_IMPLEMENT_EXCEPTION(DNSException, NetException, "DNS error")
POCO_IMPLEMENT_EXCEPTION(HostNotFoundException, DNSException, "Host not found")
POCO_IMPLEMENT_EXCEPTION(NoAddressFoundException, DNSException, "No address found")
POCO_IMPLEMENT_EXCEPTION(InterfaceNotFoundException, NetException, "Interface not found")
POCO_IMPLEMENT_EXCEPTION(MessageException, NetException, "Malformed message")
POCO_IMPLEMENT_EXCEPTION(MultipartException, MessageException, "Malformed multipart message")
POCO_IMPLEMENT_EXCEPTION(HTTPException, NetException, "HTTP Exception")
POCO_IMPLEMENT_EXCEPTION(NotAuthenticatedException, HTTPException, "No authentication information found")
POCO_IMPLEMENT_EXCEPTION(FTPException, NetException, "FTP Exception")
POCO_IMPLEMENT_EXCEPTION(SMTPException, NetException, "SMTP Exception")
POCO_IMPLEMENT_EXCEPTION(POP3Exception, NetException, "POP3 Exception")
Net_END

View File

@@ -0,0 +1,497 @@
//
// NetworkInterface.cpp
//
// $Id: //poco/1.1.0/Net/src/NetworkInterface.cpp#3 $
//
// Library: Net
// Package: Sockets
// Module: NetworkInterface
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/NetworkInterface.h"
#include "Net/DatagramSocket.h"
#include "Net/NetException.h"
#include "Foundation/NumberFormatter.h"
#include <string.h>
using Foundation::NumberFormatter;
using Foundation::FastMutex;
Net_BEGIN
FastMutex NetworkInterface::_mutex;
NetworkInterface::NetworkInterface():
_index(0)
{
}
NetworkInterface::NetworkInterface(const std::string& name, const IPAddress& address, int index):
_name(name),
_address(address),
_index(index)
{
}
NetworkInterface::NetworkInterface(const NetworkInterface& interface):
_index(interface._index),
_name(interface._name),
_address(interface._address)
{
}
NetworkInterface::~NetworkInterface()
{
}
NetworkInterface& NetworkInterface::operator = (const NetworkInterface& interface)
{
if (&interface != this)
{
_index = interface._index;
_name = interface._name;
_address = interface._address;
}
return *this;
}
NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6)
{
#if defined(_WIN32)
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->name() == name && it->supportsIPv6() == requireIPv6)
return *it;
}
throw InterfaceNotFoundException(name);
#else
FastMutex::ScopedLock lock(_mutex);
struct ifreq ifr;
strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ);
DatagramSocket ds(requireIPv6 ? IPAddress::IPv6 : IPAddress::IPv4);
ds.impl()->ioctl(SIOCGIFADDR, &ifr);
IPAddress addr;
#if defined(POCO_HAVE_IPv6)
if (ifr.ifr_addr.sa_family == AF_INET)
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr.ifr_addr)->sin_addr, sizeof(struct in_addr));
else if (ifr.ifr_addr.sa_family == AF_INET6)
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr.ifr_addr)->sin6_addr, sizeof(struct in6_addr));
else throw InterfaceNotFoundException(addr.toString(), "interface has no IP address");
int index = if_nametoindex(name.c_str());
#else
if (ifr.ifr_addr.sa_family == AF_INET)
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr.ifr_addr)->sin_addr, sizeof(struct in_addr));
else throw InterfaceNotFoundException(addr.toString(), "interface has no IP address");
int index = 0;
#endif
return NetworkInterface(name, addr, index);
#endif
}
NetworkInterface NetworkInterface::forAddress(const IPAddress& addr)
{
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->address() == addr)
return *it;
}
throw InterfaceNotFoundException(addr.toString());
}
NetworkInterface NetworkInterface::forIndex(int i)
{
if (i != 0)
{
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->index() == i)
return *it;
}
throw InterfaceNotFoundException("#" + NumberFormatter::format(i));
}
else return NetworkInterface();
}
Foundation_END
//
// platform-specific code below
//
#if defined(POCO_OS_FAMILY_WINDOWS)
//
// Windows
//
#include <iphlpapi.h>
Net_BEGIN
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
#if defined(POCO_HAVE_IPv6)
// On Windows XP/Server 2003 and later we use GetAdaptersAddresses.
PIP_ADAPTER_ADDRESSES pAdapterAddresses;
PIP_ADAPTER_ADDRESSES pAdapter = 0;
ULONG len = sizeof(IP_ADAPTER_ADDRESSES);
pAdapterAddresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(new char[len]);
// Make an initial call to GetAdaptersAddresses to get
// the necessary size into len
DWORD rc = GetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &len);
if (rc == ERROR_BUFFER_OVERFLOW)
{
delete [] reinterpret_cast<char*>(pAdapterAddresses);
pAdapterAddresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(new char[len]);
}
else if (rc != ERROR_SUCCESS)
{
throw NetException("cannot get network adapter list");
}
try
{
if (GetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &len) == NO_ERROR)
{
pAdapter = pAdapterAddresses;
while (pAdapter)
{
if (pAdapter->FirstUnicastAddress)
{
IPAddress addr(pAdapter->FirstUnicastAddress->Address.lpSockaddr, pAdapter->FirstUnicastAddress->Address.iSockaddrLength);
result.push_back(NetworkInterface(std::string(pAdapter->AdapterName), addr, pAdapter->Ipv6IfIndex));
pAdapter = pAdapter->Next;
}
}
}
else throw NetException("cannot get network adapter list");
}
catch (Foundation::Exception&)
{
delete [] reinterpret_cast<char*>(pAdapterAddresses);
throw;
}
delete [] reinterpret_cast<char*>(pAdapterAddresses);
#else
// On Windows 2000 we use GetAdaptersInfo.
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = 0;
ULONG len = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(new char[len]);
// Make an initial call to GetAdaptersInfo to get
// the necessary size into len
DWORD rc = GetAdaptersInfo(pAdapterInfo, &len);
if (rc == ERROR_BUFFER_OVERFLOW)
{
delete [] reinterpret_cast<char*>(pAdapterInfo);
pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(new char[len]);
}
else if (rc != ERROR_SUCCESS)
{
throw NetException("cannot get network adapter list");
}
try
{
if (GetAdaptersInfo(pAdapterInfo, &len) == NO_ERROR)
{
pAdapter = pAdapterInfo;
while (pAdapter)
{
IPAddress addr(std::string(pAdapter->IpAddressList.IpAddress.String));
result.push_back(NetworkInterface(std::string(pAdapter->AdapterName), addr));
pAdapter = pAdapter->Next;
}
}
else throw NetException("cannot get network adapter list");
}
catch (Foundation::Exception&)
{
delete [] reinterpret_cast<char*>(pAdapterInfo);
throw;
}
delete [] reinterpret_cast<char*>(pAdapterInfo);
#endif
return result;
}
Net_END
#elif defined(POCO_OS_FAMILY_BSD) || POCO_OS == POCO_OS_QNX
//
// BSD variants
//
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if_dl.h>
Net_BEGIN
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
struct ifaddrs* ifaphead;
int rc = getifaddrs(&ifaphead);
if (rc) throw NetException("cannot get network adapter list");
for (struct ifaddrs* ifap = ifaphead; ifap; ifap = ifap->ifa_next)
{
if (ifap->ifa_addr)
{
if (ifap->ifa_addr->sa_family == AF_INET)
{
IPAddress addr(&reinterpret_cast<struct sockaddr_in*>(ifap->ifa_addr)->sin_addr, sizeof(struct in_addr));
result.push_back(NetworkInterface(std::string(ifap->ifa_name), addr));
}
#if defined(POCO_HAVE_IPv6)
else if (ifap->ifa_addr->sa_family == AF_INET6)
{
IPAddress addr(&reinterpret_cast<struct sockaddr_in6*>(ifap->ifa_addr)->sin6_addr, sizeof(struct in6_addr));
result.push_back(NetworkInterface(std::string(ifap->ifa_name), addr, if_nametoindex(ifap->ifa_name)));
}
#endif
}
}
freeifaddrs(ifaphead);
return result;
}
Net_END
#elif POCO_OS == POCO_OS_LINUX
//
// Linux
//
Net_BEGIN
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
DatagramSocket socket;
// the following code is loosely based
// on W. Richard Stevens, UNIX Network Programming, pp 434ff.
int lastlen = 0;
int len = 100*sizeof(struct ifreq);
char* buf = 0;
try
{
struct ifconf ifc;
for (;;)
{
buf = new char[len];
ifc.ifc_len = len;
ifc.ifc_buf = buf;
if (::ioctl(socket.impl()->sockfd(), SIOCGIFCONF, &ifc) < 0)
{
if (errno != EINVAL || lastlen != 0)
throw NetException("cannot get network adapter list");
}
else
{
if (ifc.ifc_len == lastlen)
break;
lastlen = ifc.ifc_len;
}
len += 10*sizeof(struct ifreq);
delete [] buf;
}
for (const char* ptr = buf; ptr < buf + ifc.ifc_len;)
{
const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr);
IPAddress addr;
bool haveAddr = false;
switch (ifr->ifr_addr.sa_family)
{
#if defined(POCO_HAVE_IPv6)
case AF_INET6:
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr));
haveAddr = true;
break;
#endif
case AF_INET:
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr));
haveAddr = true;
break;
default:
break;
}
if (haveAddr)
{
#if defined(POCO_HAVE_IPv6)
int index = if_nametoindex(ifr->ifr_name);
#else
int index = -1;
#endif
result.push_back(NetworkInterface(std::string(ifr->ifr_name), addr, index));
}
ptr += sizeof(struct ifreq);
}
}
catch (...)
{
delete [] buf;
throw;
}
delete [] buf;
return result;
}
Net_END
#else
//
// Non-BSD Unix variants
//
Net_BEGIN
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
DatagramSocket socket;
// the following code is loosely based
// on W. Richard Stevens, UNIX Network Programming, pp 434ff.
int lastlen = 0;
int len = 100*sizeof(struct ifreq);
char* buf = 0;
try
{
struct ifconf ifc;
for (;;)
{
buf = new char[len];
ifc.ifc_len = len;
ifc.ifc_buf = buf;
if (::ioctl(socket.impl()->sockfd(), SIOCGIFCONF, &ifc) < 0)
{
if (errno != EINVAL || lastlen != 0)
throw NetException("cannot get network adapter list");
}
else
{
if (ifc.ifc_len == lastlen)
break;
lastlen = ifc.ifc_len;
}
len += 10*sizeof(struct ifreq);
delete [] buf;
}
for (const char* ptr = buf; ptr < buf + ifc.ifc_len;)
{
const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr);
#if defined(POCO_HAVE_SALEN)
len = ifr->ifr_addr.sa_len;
if (sizeof(struct sockaddr) > len) len = sizeof(struct sockaddr);
#else
len = sizeof(struct sockaddr);
#endif
IPAddress addr;
bool haveAddr = false;
switch (ifr->ifr_addr.sa_family)
{
#if defined(POCO_HAVE_IPv6)
case AF_INET6:
if (len < sizeof(struct sockaddr_in6)) len = sizeof(struct sockaddr_in6);
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr));
haveAddr = true;
break;
#endif
case AF_INET:
if (len < sizeof(struct sockaddr_in)) len = sizeof(struct sockaddr_in);
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr));
haveAddr = true;
break;
default:
break;
}
if (haveAddr)
{
#if defined(POCO_HAVE_IPv6)
int index = if_nametoindex(ifr->ifr_name);
#else
int index = -1;
#endif
result.push_back(NetworkInterface(std::string(ifr->ifr_name), addr, index));
}
len += sizeof(ifr->ifr_name);
ptr += len;
}
}
catch (...)
{
delete [] buf;
throw;
}
delete [] buf;
return result;
}
Net_END
#endif

View File

@@ -0,0 +1,67 @@
//
// NullPartHandler.cpp
//
// $Id: //poco/1.1.0/Net/src/NullPartHandler.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: NullPartHandler
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/NullPartHandler.h"
#include "Net/MessageHeader.h"
#include "Foundation/NullStream.h"
#include "Foundation/StreamCopier.h"
using Foundation::NullOutputStream;
using Foundation::StreamCopier;
Net_BEGIN
NullPartHandler::NullPartHandler()
{
}
NullPartHandler::~NullPartHandler()
{
}
void NullPartHandler::handlePart(const MessageHeader& header, std::istream& stream)
{
NullOutputStream ostr;
StreamCopier::copyStream(stream, ostr);
}
Net_END

View File

@@ -0,0 +1,299 @@
//
// POP3ClientSession.cpp
//
// $Id: //poco/1.1.0/Net/src/POP3ClientSession.cpp#2 $
//
// Library: Net
// Package: Mail
// Module: POP3ClientSession
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/POP3ClientSession.h"
#include "Net/MailMessage.h"
#include "Net/MailStream.h"
#include "Net/SocketAddress.h"
#include "Net/NetException.h"
#include "Foundation/StreamCopier.h"
#include "Foundation/NumberFormatter.h"
#include "Foundation/UnbufferedStreamBuf.h"
#include <istream>
#include <ctype.h>
using Foundation::NumberFormatter;
using Foundation::StreamCopier;
Net_BEGIN
class DialogStreamBuf: public Foundation::UnbufferedStreamBuf
{
public:
DialogStreamBuf(DialogSocket& socket):
_socket(socket)
{
}
~DialogStreamBuf()
{
}
private:
int readFromDevice()
{
return _socket.get();
}
DialogSocket& _socket;
};
class DialogIOS: public virtual std::ios
{
public:
DialogIOS(DialogSocket& socket):
_buf(socket)
{
poco_ios_init(&_buf);
}
~DialogIOS()
{
}
DialogStreamBuf* rdbuf()
{
return &_buf;
}
protected:
DialogStreamBuf _buf;
};
class DialogInputStream: public DialogIOS, public std::istream
{
public:
DialogInputStream(DialogSocket& socket):
DialogIOS(socket),
std::istream(&_buf)
{
}
~DialogInputStream()
{
}
};
POP3ClientSession::POP3ClientSession(const StreamSocket& socket):
_socket(socket),
_isOpen(true)
{
}
POP3ClientSession::POP3ClientSession(const std::string& host, Foundation::UInt16 port):
_socket(SocketAddress(host, port)),
_isOpen(true)
{
}
POP3ClientSession::~POP3ClientSession()
{
try
{
close();
}
catch (...)
{
}
}
void POP3ClientSession::setTimeout(const Foundation::Timespan& timeout)
{
_socket.setReceiveTimeout(timeout);
}
Foundation::Timespan POP3ClientSession::getTimeout() const
{
return _socket.getReceiveTimeout();
}
void POP3ClientSession::login(const std::string& username, const std::string& password)
{
std::string response;
_socket.receiveMessage(response);
if (!isPositive(response)) throw SMTPException("The POP3 service is unavailable", response);
sendCommand("USER", username, response);
if (!isPositive(response)) throw POP3Exception("Login rejected for user", response);
sendCommand("PASS", password, response);
if (!isPositive(response)) throw POP3Exception("Password rejected for user", response);
}
void POP3ClientSession::close()
{
if (_isOpen)
{
std::string response;
sendCommand("QUIT", response);
_socket.close();
_isOpen = false;
}
}
int POP3ClientSession::messageCount()
{
std::string response;
sendCommand("STAT", response);
if (!isPositive(response)) throw POP3Exception("Cannot determine message count", response);
std::string::const_iterator it = response.begin();
std::string::const_iterator end = response.end();
int count = 0;
while (it != end && !isspace(*it)) ++it;
while (it != end && isspace(*it)) ++it;
while (it != end && isdigit(*it)) count = count*10 + *it++ - '0';
return count;
}
void POP3ClientSession::listMessages(MessageInfoVec& messages)
{
messages.clear();
std::string response;
sendCommand("LIST", response);
if (!isPositive(response)) throw POP3Exception("Cannot get message list", response);
_socket.receiveMessage(response);
while (response != ".")
{
MessageInfo info = {0, 0};
std::string::const_iterator it = response.begin();
std::string::const_iterator end = response.end();
while (it != end && isdigit(*it)) info.id = info.id*10 + *it++ - '0';
while (it != end && isspace(*it)) ++it;
while (it != end && isdigit(*it)) info.size = info.size*10 + *it++ - '0';
messages.push_back(info);
_socket.receiveMessage(response);
}
}
void POP3ClientSession::retrieveMessage(int id, MailMessage& message)
{
std::string response;
sendCommand("RETR", NumberFormatter::format(id), response);
if (!isPositive(response)) throw POP3Exception("Cannot get message list", response);
DialogInputStream sis(_socket);
MailInputStream mis(sis);
message.read(mis);
}
void POP3ClientSession::retrieveMessage(int id, MailMessage& message, PartHandler& handler)
{
std::string response;
sendCommand("RETR", NumberFormatter::format(id), response);
if (!isPositive(response)) throw POP3Exception("Cannot get message list", response);
DialogInputStream sis(_socket);
MailInputStream mis(sis);
message.read(mis, handler);
}
void POP3ClientSession::retrieveMessage(int id, std::ostream& ostr)
{
std::string response;
sendCommand("RETR", NumberFormatter::format(id), response);
if (!isPositive(response)) throw POP3Exception("Cannot get message list", response);
DialogInputStream sis(_socket);
MailInputStream mis(sis);
StreamCopier::copyStream(mis, ostr);
}
void POP3ClientSession::retrieveHeader(int id, MessageHeader& header)
{
std::string response;
sendCommand("TOP", NumberFormatter::format(id), "0", response);
if (!isPositive(response)) throw POP3Exception("Cannot get message list", response);
DialogInputStream sis(_socket);
MailInputStream mis(sis);
header.read(mis);
// skip stuff following header
mis.get(); // \r
mis.get(); // \n
}
void POP3ClientSession::deleteMessage(int id)
{
std::string response;
sendCommand("DELE", NumberFormatter::format(id), response);
if (!isPositive(response)) throw POP3Exception("Cannot mark message for deletion", response);
}
bool POP3ClientSession::sendCommand(const std::string& command, std::string& response)
{
_socket.sendMessage(command);
_socket.receiveMessage(response);
return isPositive(response);
}
bool POP3ClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response)
{
_socket.sendMessage(command, arg);
_socket.receiveMessage(response);
return isPositive(response);
}
bool POP3ClientSession::sendCommand(const std::string& command, const std::string& arg1, const std::string& arg2, std::string& response)
{
_socket.sendMessage(command, arg1, arg2);
_socket.receiveMessage(response);
return isPositive(response);
}
bool POP3ClientSession::isPositive(const std::string& response)
{
return response.length() > 0 && response[0] == '+';
}
Net_END

53
Net/src/PartHandler.cpp Normal file
View File

@@ -0,0 +1,53 @@
//
// PartHandler.cpp
//
// $Id: //poco/1.1.0/Net/src/PartHandler.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: PartHandler
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/PartHandler.h"
Net_BEGIN
PartHandler::PartHandler()
{
}
PartHandler::~PartHandler()
{
}
Net_END

67
Net/src/PartSource.cpp Normal file
View File

@@ -0,0 +1,67 @@
//
// PartSource.cpp
//
// $Id: //poco/1.1.0/Net/src/PartSource.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: PartSource
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/PartSource.h"
Net_BEGIN
PartSource::PartSource():
_mediaType("application/octet-stream")
{
}
PartSource::PartSource(const std::string& mediaType):
_mediaType(mediaType)
{
}
PartSource::~PartSource()
{
}
const std::string& PartSource::filename()
{
static const std::string empty;
return empty;
}
Net_END

View File

@@ -0,0 +1,125 @@
//
// QuotedPrintableDecoder.cpp
//
// $Id: //poco/1.1.0/Net/src/QuotedPrintableDecoder.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: QuotedPrintableDecoder
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/QuotedPrintableDecoder.h"
#include "Foundation/NumberParser.h"
#include "Foundation/Exception.h"
#include <ctype.h>
using Foundation::UnbufferedStreamBuf;
using Foundation::NumberParser;
using Foundation::DataFormatException;
Net_BEGIN
QuotedPrintableDecoderBuf::QuotedPrintableDecoderBuf(std::istream& istr):
_istr(istr)
{
}
QuotedPrintableDecoderBuf::~QuotedPrintableDecoderBuf()
{
}
int QuotedPrintableDecoderBuf::readFromDevice()
{
static const int eof = std::char_traits<char>::eof();
int ch = _istr.get();
while (ch == '=')
{
ch = _istr.get();
if (ch == '\r')
{
ch = _istr.get(); // read \n
}
else if (isxdigit(ch))
{
std::string hex;
hex += (char) ch;
ch = _istr.get();
if (isxdigit(ch))
{
hex += (char) ch;
return NumberParser::parseHex(hex);
}
throw DataFormatException("Incomplete hex number in quoted-printable encoded stream");
}
else if (ch != '\n')
{
throw DataFormatException("Invalid occurrence of '=' in quoted-printable encoded stream");
}
ch = _istr.get();
}
return ch;
}
QuotedPrintableDecoderIOS::QuotedPrintableDecoderIOS(std::istream& istr): _buf(istr)
{
poco_ios_init(&_buf);
}
QuotedPrintableDecoderIOS::~QuotedPrintableDecoderIOS()
{
}
QuotedPrintableDecoderBuf* QuotedPrintableDecoderIOS::rdbuf()
{
return &_buf;
}
QuotedPrintableDecoder::QuotedPrintableDecoder(std::istream& istr):
QuotedPrintableDecoderIOS(istr),
std::istream(&_buf)
{
}
QuotedPrintableDecoder::~QuotedPrintableDecoder()
{
}
Net_END

View File

@@ -0,0 +1,171 @@
//
// QuotedPrintableEncoder.cpp
//
// $Id: //poco/1.1.0/Net/src/QuotedPrintableEncoder.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: QuotedPrintableEncoder
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/QuotedPrintableEncoder.h"
#include "Foundation/NumberFormatter.h"
using Foundation::UnbufferedStreamBuf;
using Foundation::NumberFormatter;
Net_BEGIN
QuotedPrintableEncoderBuf::QuotedPrintableEncoderBuf(std::ostream& ostr):
_pending(-1),
_lineLength(0),
_ostr(ostr)
{
}
QuotedPrintableEncoderBuf::~QuotedPrintableEncoderBuf()
{
try
{
close();
}
catch (...)
{
}
}
int QuotedPrintableEncoderBuf::writeToDevice(char c)
{
if (_pending != -1)
{
if (_pending == '\r' && c == '\n')
writeRaw((char) _pending);
else if (c == '\r' || c == '\n')
writeEncoded((char) _pending);
else
writeRaw((char) _pending);
_pending = -1;
}
if (c == '\t' || c == ' ')
{
_pending = charToInt(c);
return _pending;
}
else if (c == '\r' || c == '\n' || c > 32 && c < 127 && c != '=')
{
writeRaw(c);
}
else
{
writeEncoded(c);
}
return charToInt(c);
}
void QuotedPrintableEncoderBuf::writeEncoded(char c)
{
if (_lineLength >= 73)
{
_ostr << "=\r\n";
_lineLength = 3;
}
else _lineLength += 3;
_ostr << '=' << NumberFormatter::formatHex((unsigned) charToInt(c), 2);
}
void QuotedPrintableEncoderBuf::writeRaw(char c)
{
if (c == '\r' || c == '\n')
{
_ostr.put(c);
_lineLength = 0;
}
else if (_lineLength < 75)
{
_ostr.put(c);
++_lineLength;
}
else
{
_ostr << "=\r\n" << c;
_lineLength = 1;
}
}
int QuotedPrintableEncoderBuf::close()
{
sync();
return _ostr ? 0 : -1;
}
QuotedPrintableEncoderIOS::QuotedPrintableEncoderIOS(std::ostream& ostr): _buf(ostr)
{
poco_ios_init(&_buf);
}
QuotedPrintableEncoderIOS::~QuotedPrintableEncoderIOS()
{
}
int QuotedPrintableEncoderIOS::close()
{
return _buf.close();
}
QuotedPrintableEncoderBuf* QuotedPrintableEncoderIOS::rdbuf()
{
return &_buf;
}
QuotedPrintableEncoder::QuotedPrintableEncoder(std::ostream& ostr):
QuotedPrintableEncoderIOS(ostr),
std::ostream(&_buf)
{
}
QuotedPrintableEncoder::~QuotedPrintableEncoder()
{
}
Net_END

View File

@@ -0,0 +1,163 @@
//
// SMTPClientSession.cpp
//
// $Id: //poco/1.1.0/Net/src/SMTPClientSession.cpp#2 $
//
// Library: Net
// Package: Mail
// Module: SMTPClientSession
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/SMTPClientSession.h"
#include "Net/MailMessage.h"
#include "Net/MailRecipient.h"
#include "Net/MailStream.h"
#include "Net/SocketAddress.h"
#include "Net/SocketStream.h"
#include "Net/NetException.h"
#include "Foundation/Environment.h"
using Foundation::Environment;
Net_BEGIN
SMTPClientSession::SMTPClientSession(const StreamSocket& socket):
_socket(socket),
_isOpen(true)
{
}
SMTPClientSession::SMTPClientSession(const std::string& host, Foundation::UInt16 port):
_socket(SocketAddress(host, port)),
_isOpen(true)
{
}
SMTPClientSession::~SMTPClientSession()
{
try
{
close();
}
catch (...)
{
}
}
void SMTPClientSession::setTimeout(const Foundation::Timespan& timeout)
{
_socket.setReceiveTimeout(timeout);
}
Foundation::Timespan SMTPClientSession::getTimeout() const
{
return _socket.getReceiveTimeout();
}
void SMTPClientSession::login(const std::string& hostname)
{
std::string response;
int status = _socket.receiveStatusMessage(response);
if (!isPositiveCompletion(status)) throw SMTPException("The mail service is unavailable", response);
status = sendCommand("EHLO", hostname, response);
if (isPermanentNegative(status))
status = sendCommand("HELO", hostname, response);
if (!isPositiveCompletion(status)) throw SMTPException("Login failed", response);
}
void SMTPClientSession::login()
{
login(Environment::nodeName());
}
void SMTPClientSession::close()
{
if (_isOpen)
{
std::string response;
sendCommand("QUIT", response);
_socket.close();
_isOpen = false;
}
}
void SMTPClientSession::sendMessage(const MailMessage& message)
{
std::string response;
std::string sender("<");
sender.append(message.getSender());
sender.append(">");
int status = sendCommand("MAIL FROM:", sender, response);
if (!isPositiveCompletion(status)) throw SMTPException("Cannot send message", response);
for (MailMessage::Recipients::const_iterator it = message.recipients().begin(); it != message.recipients().end(); ++it)
{
std::string recipient("<");
recipient.append(it->getAddress());
recipient.append(">");
int status = sendCommand("RCPT TO:", recipient, response);
if (!isPositiveCompletion(status)) throw SMTPException(std::string("Recipient rejected: ") + recipient, response);
}
status = sendCommand("DATA", response);
if (!isPositiveIntermediate(status)) throw SMTPException("Cannot send message data", response);
SocketOutputStream socketStream(_socket);
MailOutputStream mailStream(socketStream);
message.write(mailStream);
mailStream.close();
socketStream.flush();
status = _socket.receiveStatusMessage(response);
if (!isPositiveCompletion(status)) throw SMTPException("The server rejected the message", response);
}
int SMTPClientSession::sendCommand(const std::string& command, std::string& response)
{
_socket.sendMessage(command);
return _socket.receiveStatusMessage(response);
}
int SMTPClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response)
{
_socket.sendMessage(command, arg);
return _socket.receiveStatusMessage(response);
}
Net_END

129
Net/src/ServerSocket.cpp Normal file
View File

@@ -0,0 +1,129 @@
//
// ServerSocket.cpp
//
// $Id: //poco/1.1.0/Net/src/ServerSocket.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: ServerSocket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/ServerSocket.h"
#include "Net/ServerSocketImpl.h"
#include "Foundation/Exception.h"
using Foundation::InvalidArgumentException;
Net_BEGIN
ServerSocket::ServerSocket(): Socket(new ServerSocketImpl)
{
}
ServerSocket::ServerSocket(const Socket& socket): Socket(socket)
{
if (!dynamic_cast<ServerSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
ServerSocket::ServerSocket(const SocketAddress& address, int backlog): Socket(new ServerSocketImpl)
{
impl()->bind(address, true);
impl()->listen(backlog);
}
ServerSocket::ServerSocket(Foundation::UInt16 port, int backlog): Socket(new ServerSocketImpl)
{
IPAddress wildcardAddr;
SocketAddress address(wildcardAddr, port);
impl()->bind(address, true);
impl()->listen(backlog);
}
ServerSocket::ServerSocket(SocketImpl* pImpl, bool ignore): Socket(pImpl)
{
}
ServerSocket::~ServerSocket()
{
}
ServerSocket& ServerSocket::operator = (const Socket& socket)
{
if (dynamic_cast<ServerSocketImpl*>(socket.impl()))
Socket::operator = (socket);
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
void ServerSocket::bind(const SocketAddress& address, bool reuseAddress)
{
impl()->bind(address, reuseAddress);
}
void ServerSocket::bind(Foundation::UInt16 port, bool reuseAddress)
{
IPAddress wildcardAddr;
SocketAddress address(wildcardAddr, port);
impl()->bind(address, reuseAddress);
}
void ServerSocket::listen(int backlog)
{
impl()->listen(backlog);
}
StreamSocket ServerSocket::acceptConnection(SocketAddress& clientAddr)
{
return StreamSocket(impl()->acceptConnection(clientAddr));
}
StreamSocket ServerSocket::acceptConnection()
{
SocketAddress clientAddr;
return StreamSocket(impl()->acceptConnection(clientAddr));
}
Net_END

View File

@@ -0,0 +1,53 @@
//
// ServerSocketImpl.cpp
//
// $Id: //poco/1.1.0/Net/src/ServerSocketImpl.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: ServerSocketImpl
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/ServerSocketImpl.h"
Net_BEGIN
ServerSocketImpl::ServerSocketImpl()
{
}
ServerSocketImpl::~ServerSocketImpl()
{
}
Net_END

144
Net/src/Socket.cpp Normal file
View File

@@ -0,0 +1,144 @@
//
// Socket.cpp
//
// $Id: //poco/1.1.0/Net/src/Socket.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: Socket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/Socket.h"
#include "Net/StreamSocketImpl.h"
#include <algorithm>
#include <string.h>
Net_BEGIN
Socket::Socket():
_pImpl(new StreamSocketImpl)
{
}
Socket::Socket(SocketImpl* pImpl):
_pImpl(pImpl)
{
poco_check_ptr (_pImpl);
}
Socket::Socket(const Socket& socket):
_pImpl(socket._pImpl)
{
poco_check_ptr (_pImpl);
_pImpl->duplicate();
}
Socket& Socket::operator = (const Socket& socket)
{
if (&socket != this)
{
if (_pImpl) _pImpl->release();
_pImpl = socket._pImpl;
if (_pImpl) _pImpl->duplicate();
}
return *this;
}
Socket::~Socket()
{
_pImpl->release();
}
int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Foundation::Timespan& timeout)
{
fd_set fdRead;
fd_set fdWrite;
fd_set fdExcept;
int nfd = 0;
FD_ZERO(&fdRead);
for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it)
{
if (int(it->sockfd()) > nfd)
nfd = int(it->sockfd());
FD_SET(it->sockfd(), &fdRead);
}
FD_ZERO(&fdWrite);
for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it)
{
if (int(it->sockfd()) > nfd)
nfd = int(it->sockfd());
FD_SET(it->sockfd(), &fdWrite);
}
FD_ZERO(&fdExcept);
for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it)
{
if (int(it->sockfd()) > nfd)
nfd = int(it->sockfd());
FD_SET(it->sockfd(), &fdExcept);
}
struct timeval tv;
tv.tv_sec = (long) timeout.totalSeconds();
tv.tv_usec = (long) timeout.useconds();
int rc = ::select(nfd + 1, &fdRead, &fdWrite, &fdExcept, &tv);
if (rc < 0) SocketImpl::error();
SocketList readyReadList;
for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it)
{
if (FD_ISSET(it->sockfd(), &fdRead))
readyReadList.push_back(*it);
}
std::swap(readList, readyReadList);
SocketList readyWriteList;
for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it)
{
if (FD_ISSET(it->sockfd(), &fdWrite))
readyWriteList.push_back(*it);
}
std::swap(writeList, readyWriteList);
SocketList readyExceptList;
for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it)
{
if (FD_ISSET(it->sockfd(), &fdExcept))
readyExceptList.push_back(*it);
}
std::swap(exceptList, readyExceptList);
return rc;
}
Net_END

350
Net/src/SocketAddress.cpp Normal file
View File

@@ -0,0 +1,350 @@
//
// SocketAddress.cpp
//
// $Id: //poco/1.1.0/Net/src/SocketAddress.cpp#2 $
//
// Library: Net
// Package: NetCore
// Module: SocketAddress
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/SocketAddress.h"
#include "Net/IPAddress.h"
#include "Net/NetException.h"
#include "Net/DNS.h"
#include "Foundation/RefCountedObject.h"
#include "Foundation/NumberParser.h"
#include "Foundation/NumberFormatter.h"
#include <algorithm>
#include <string.h>
using Foundation::RefCountedObject;
using Foundation::NumberParser;
using Foundation::NumberFormatter;
using Foundation::UInt16;
Net_BEGIN
//
// SocketAddressImpl
//
class SocketAddressImpl: public RefCountedObject
{
public:
virtual IPAddress host() const = 0;
virtual UInt16 port() const = 0;
virtual poco_socklen_t length() const = 0;
virtual const struct sockaddr* addr() const = 0;
virtual int af() const = 0;
protected:
SocketAddressImpl()
{
}
virtual ~SocketAddressImpl()
{
}
private:
SocketAddressImpl(const SocketAddressImpl&);
SocketAddressImpl& operator = (const SocketAddressImpl&);
};
class IPv4SocketAddressImpl: public SocketAddressImpl
{
public:
IPv4SocketAddressImpl()
{
memset(&_addr, 0, sizeof(_addr));
_addr.sin_family = AF_INET;
poco_set_sin_len(&_addr);
}
IPv4SocketAddressImpl(const struct sockaddr_in* addr)
{
memcpy(&_addr, addr, sizeof(_addr));
}
IPv4SocketAddressImpl(const void* addr, UInt16 port)
{
memset(&_addr, 0, sizeof(_addr));
_addr.sin_family = AF_INET;
memcpy(&_addr.sin_addr, addr, sizeof(_addr.sin_addr));
_addr.sin_port = port;
}
IPAddress host() const
{
return IPAddress(&_addr.sin_addr, sizeof(_addr.sin_addr));
}
UInt16 port() const
{
return _addr.sin_port;
}
poco_socklen_t length() const
{
return sizeof(_addr);
}
const struct sockaddr* addr() const
{
return reinterpret_cast<const struct sockaddr*>(&_addr);
}
int af() const
{
return _addr.sin_family;
}
private:
struct sockaddr_in _addr;
};
#if defined(POCO_HAVE_IPv6)
class IPv6SocketAddressImpl: public SocketAddressImpl
{
public:
IPv6SocketAddressImpl(const struct sockaddr_in6* addr)
{
memcpy(&_addr, addr, sizeof(_addr));
}
IPv6SocketAddressImpl(const void* addr, UInt16 port)
{
memset(&_addr, 0, sizeof(_addr));
_addr.sin6_family = AF_INET6;
poco_set_sin6_len(&_addr);
memcpy(&_addr.sin6_addr, addr, sizeof(_addr.sin6_addr));
_addr.sin6_port = port;
}
IPAddress host() const
{
return IPAddress(&_addr.sin6_addr, sizeof(_addr.sin6_addr));
}
UInt16 port() const
{
return _addr.sin6_port;
}
poco_socklen_t length() const
{
return sizeof(_addr);
}
const struct sockaddr* addr() const
{
return reinterpret_cast<const struct sockaddr*>(&_addr);
}
int af() const
{
return _addr.sin6_family;
}
private:
struct sockaddr_in6 _addr;
};
#endif // POCO_HAVE_IPv6
//
// SocketAddress
//
SocketAddress::SocketAddress()
{
_pImpl = new IPv4SocketAddressImpl;
}
SocketAddress::SocketAddress(const IPAddress& addr, Foundation::UInt16 port)
{
init(addr, port);
}
SocketAddress::SocketAddress(const std::string& addr, Foundation::UInt16 port)
{
init(addr, port);
}
SocketAddress::SocketAddress(const std::string& addr, const std::string& port)
{
init(addr, resolveService(port));
}
SocketAddress::SocketAddress(const SocketAddress& addr)
{
_pImpl = addr._pImpl;
_pImpl->duplicate();
}
SocketAddress::SocketAddress(const struct sockaddr* addr, poco_socklen_t length)
{
if (length == sizeof(struct sockaddr_in))
_pImpl = new IPv4SocketAddressImpl(reinterpret_cast<const struct sockaddr_in*>(addr));
#if defined(POCO_HAVE_IPv6)
else if (length == sizeof(struct sockaddr_in6))
_pImpl = new IPv6SocketAddressImpl(reinterpret_cast<const struct sockaddr_in6*>(addr));
#endif
else throw Foundation::InvalidArgumentException("Invalid address length passed to SocketAddress()");
}
SocketAddress::~SocketAddress()
{
_pImpl->release();
}
SocketAddress& SocketAddress::operator = (const SocketAddress& addr)
{
if (&addr != this)
{
_pImpl->release();
_pImpl = addr._pImpl;
_pImpl->duplicate();
}
return *this;
}
void SocketAddress::swap(SocketAddress& addr)
{
std::swap(_pImpl, addr._pImpl);
}
IPAddress SocketAddress::host() const
{
return _pImpl->host();
}
Foundation::UInt16 SocketAddress::port() const
{
return ntohs(_pImpl->port());
}
poco_socklen_t SocketAddress::length() const
{
return _pImpl->length();
}
const struct sockaddr* SocketAddress::addr() const
{
return _pImpl->addr();
}
int SocketAddress::af() const
{
return _pImpl->af();
}
std::string SocketAddress::toString() const
{
std::string result = host().toString();
result.append(":");
result.append(NumberFormatter::format(port()));
return result;
}
void SocketAddress::init(const IPAddress& host, Foundation::UInt16 port)
{
if (host.family() == IPAddress::IPv4)
_pImpl = new IPv4SocketAddressImpl(host.addr(), htons(port));
#if defined(POCO_HAVE_IPv6)
else if (host.family() == IPAddress::IPv6)
_pImpl = new IPv6SocketAddressImpl(host.addr(), htons(port));
#endif
else throw Foundation::NotImplementedException("unsupported IP address family");
}
void SocketAddress::init(const std::string& host, Foundation::UInt16 port)
{
IPAddress ip;
if (IPAddress::tryParse(host, ip))
{
init(ip, port);
}
else
{
HostEntry he = DNS::hostByName(host);
if (he.addresses().size() > 0)
init(he.addresses()[0], port);
else throw HostNotFoundException("No address found for host", host);
}
}
Foundation::UInt16 SocketAddress::resolveService(const std::string& service)
{
unsigned port;
if (NumberParser::tryParseUnsigned(service, port) && port <= 0xFFFF)
{
return (UInt16) port;
}
else
{
struct servent* se = getservbyname(service.c_str(), NULL);
if (se)
return ntohs(se->s_port);
else
throw ServiceNotFoundException(service);
}
}
Net_END

845
Net/src/SocketImpl.cpp Normal file
View File

@@ -0,0 +1,845 @@
//
// SocketImpl.cpp
//
// $Id: //poco/1.1.0/Net/src/SocketImpl.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: SocketImpl
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/SocketImpl.h"
#include "Net/NetException.h"
#include "Net/StreamSocketImpl.h"
#include "Foundation/NumberFormatter.h"
#include <string.h>
using Foundation::IOException;
using Foundation::TimeoutException;
using Foundation::InvalidArgumentException;
using Foundation::NumberFormatter;
using Foundation::Timespan;
Net_BEGIN
SocketImpl::SocketImpl():
_sockfd(POCO_INVALID_SOCKET)
{
}
SocketImpl::SocketImpl(poco_socket_t sockfd):
_sockfd(sockfd)
{
}
SocketImpl::~SocketImpl()
{
close();
}
SocketImpl* SocketImpl::acceptConnection(SocketAddress& clientAddr)
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
char buffer[SocketAddress::MAX_ADDRESS_LENGTH];
struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(buffer);
poco_socklen_t saLen = sizeof(buffer);
poco_socket_t sd;
do
{
sd = ::accept(_sockfd, pSA, &saLen);
}
while (sd == POCO_INVALID_SOCKET && lastError() == POCO_EINTR);
if (sd != POCO_INVALID_SOCKET)
{
clientAddr = SocketAddress(pSA, saLen);
return new StreamSocketImpl(sd);
}
error(); // will throw
return 0;
}
void SocketImpl::connect(const SocketAddress& address)
{
if (_sockfd == POCO_INVALID_SOCKET)
{
init(address.af());
}
int rc;
do
{
rc = ::connect(_sockfd, address.addr(), address.length());
}
while (rc != 0 && lastError() == POCO_EINTR);
if (rc != 0) error(address.toString());
}
void SocketImpl::connect(const SocketAddress& address, const Foundation::Timespan& timeout)
{
poco_assert (_sockfd == POCO_INVALID_SOCKET);
init(address.af());
setBlocking(false);
try
{
int rc = ::connect(_sockfd, address.addr(), address.length());
if (rc != 0)
{
if (lastError() != POCO_EINPROGRESS && lastError() != POCO_EWOULDBLOCK)
error(address.toString());
if (!poll(timeout, SELECT_READ | SELECT_WRITE))
throw Foundation::TimeoutException("connect timed out", address.toString());
int err = socketError();
if (err != 0) error(err);
}
}
catch (Foundation::Exception&)
{
setBlocking(true);
throw;
}
setBlocking(true);
}
void SocketImpl::connectNB(const SocketAddress& address)
{
if (_sockfd == POCO_INVALID_SOCKET)
{
init(address.af());
}
setBlocking(false);
int rc = ::connect(_sockfd, address.addr(), address.length());
if (rc != 0)
{
if (lastError() != POCO_EINPROGRESS && lastError() != POCO_EWOULDBLOCK)
error(address.toString());
}
}
void SocketImpl::bind(const SocketAddress& address, bool reuseAddress)
{
if (_sockfd == POCO_INVALID_SOCKET)
{
init(address.af());
}
if (reuseAddress)
{
setReuseAddress(true);
setReusePort(true);
}
int rc = ::bind(_sockfd, address.addr(), address.length());
if (rc != 0) error(address.toString());
}
void SocketImpl::listen(int backlog)
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
int rc = ::listen(_sockfd, backlog);
if (rc != 0) error();
}
void SocketImpl::close()
{
if (_sockfd != POCO_INVALID_SOCKET)
{
poco_closesocket(_sockfd);
_sockfd = POCO_INVALID_SOCKET;
}
}
void SocketImpl::shutdownReceive()
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
int rc = ::shutdown(_sockfd, 0);
if (rc != 0) error();
}
void SocketImpl::shutdownSend()
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
int rc = ::shutdown(_sockfd, 1);
if (rc != 0) error();
}
void SocketImpl::shutdown()
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
int rc = ::shutdown(_sockfd, 2);
if (rc != 0) error();
}
int SocketImpl::sendBytes(const void* buffer, int length, int flags)
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
int rc;
do
{
rc = ::send(_sockfd, reinterpret_cast<const char*>(buffer), length, flags);
}
while (rc < 0 && lastError() == POCO_EINTR);
if (rc < 0) error();
return rc;
}
int SocketImpl::receiveBytes(void* buffer, int length, int flags)
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
#if defined(POCO_BROKEN_TIMEOUTS)
if (_recvTimeout.totalMicroseconds() != 0)
{
if (!poll(_recvTimeout, SELECT_READ))
throw TimeoutException();
}
#endif
int rc;
do
{
rc = ::recv(_sockfd, reinterpret_cast<char*>(buffer), length, flags);
}
while (rc < 0 && lastError() == POCO_EINTR);
if (rc < 0)
{
if (lastError() == POCO_EAGAIN || lastError() == POCO_ETIMEDOUT)
throw TimeoutException();
else
error();
}
return rc;
}
int SocketImpl::sendTo(const void* buffer, int length, const SocketAddress& address, int flags)
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
int rc;
do
{
rc = ::sendto(_sockfd, reinterpret_cast<const char*>(buffer), length, flags, address.addr(), address.length());
}
while (rc < 0 && lastError() == POCO_EINTR);
if (rc < 0) error();
return rc;
}
int SocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags)
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
#if defined(POCO_BROKEN_TIMEOUTS)
if (_recvTimeout.totalMicroseconds() != 0)
{
if (!poll(_recvTimeout, SELECT_READ))
throw TimeoutException();
}
#endif
char abuffer[SocketAddress::MAX_ADDRESS_LENGTH];
struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(abuffer);
poco_socklen_t saLen = sizeof(abuffer);
int rc;
do
{
rc = ::recvfrom(_sockfd, reinterpret_cast<char*>(buffer), length, flags, pSA, &saLen);
}
while (rc < 0 && lastError() == POCO_EINTR);
if (rc >= 0)
{
address = SocketAddress(pSA, saLen);
}
else
{
if (lastError() == POCO_EAGAIN || lastError() == POCO_ETIMEDOUT)
throw TimeoutException();
else
error();
}
return rc;
}
void SocketImpl::sendUrgent(unsigned char data)
{
int rc = ::send(_sockfd, reinterpret_cast<const char*>(&data), sizeof(data), MSG_OOB);
if (rc < 0) error();
}
int SocketImpl::available()
{
int result;
ioctl(FIONREAD, result);
return result;
}
bool SocketImpl::poll(const Foundation::Timespan& timeout, int mode)
{
fd_set fdRead;
fd_set fdWrite;
fd_set fdExcept;
FD_ZERO(&fdRead);
FD_ZERO(&fdWrite);
FD_ZERO(&fdExcept);
if (mode & SELECT_READ)
{
FD_SET(_sockfd, &fdRead);
}
if (mode & SELECT_WRITE)
{
FD_SET(_sockfd, &fdWrite);
}
if (mode & SELECT_ERROR)
{
FD_SET(_sockfd, &fdExcept);
}
struct timeval tv;
tv.tv_sec = (long) timeout.totalSeconds();
tv.tv_usec = (long) timeout.useconds();
int rc = ::select(int(_sockfd) + 1, &fdRead, &fdWrite, &fdExcept, &tv);
if (rc < 0) error();
return rc > 0;
}
void SocketImpl::setSendBufferSize(int size)
{
setOption(SOL_SOCKET, SO_SNDBUF, size);
}
int SocketImpl::getSendBufferSize()
{
int result;
getOption(SOL_SOCKET, SO_SNDBUF, result);
return result;
}
void SocketImpl::setReceiveBufferSize(int size)
{
setOption(SOL_SOCKET, SO_RCVBUF, size);
}
int SocketImpl::getReceiveBufferSize()
{
int result;
getOption(SOL_SOCKET, SO_RCVBUF, result);
return result;
}
void SocketImpl::setSendTimeout(const Foundation::Timespan& timeout)
{
#if defined(_WIN32)
int value = (int) timeout.totalMilliseconds();
setOption(SOL_SOCKET, SO_SNDTIMEO, value);
#else
setOption(SOL_SOCKET, SO_SNDTIMEO, timeout);
#endif
}
Foundation::Timespan SocketImpl::getSendTimeout()
{
Timespan result;
#if defined(_WIN32)
int value;
getOption(SOL_SOCKET, SO_SNDTIMEO, value);
result = Timespan::TimeDiff(value)*1000;
#else
getOption(SOL_SOCKET, SO_SNDTIMEO, result);
#endif
return result;
}
void SocketImpl::setReceiveTimeout(const Foundation::Timespan& timeout)
{
#if defined(_WIN32)
int value = (int) timeout.totalMilliseconds();
setOption(SOL_SOCKET, SO_RCVTIMEO, value);
#else
setOption(SOL_SOCKET, SO_RCVTIMEO, timeout);
#endif
#if defined(POCO_BROKEN_TIMEOUTS)
_recvTimeout = timeout;
#endif
}
Foundation::Timespan SocketImpl::getReceiveTimeout()
{
Timespan result;
#if defined(_WIN32)
int value;
getOption(SOL_SOCKET, SO_RCVTIMEO, value);
result = Timespan::TimeDiff(value)*1000;
#elif defined(POCO_BROKEN_TIMEOUTS)
result = _recvTimeout;
#else
getOption(SOL_SOCKET, SO_RCVTIMEO, result);
#endif
return result;
}
SocketAddress SocketImpl::address()
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
char buffer[SocketAddress::MAX_ADDRESS_LENGTH];
struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(buffer);
poco_socklen_t saLen = sizeof(buffer);
int rc = ::getsockname(_sockfd, pSA, &saLen);
if (rc == 0)
return SocketAddress(pSA, saLen);
else
error();
return SocketAddress();
}
SocketAddress SocketImpl::peerAddress()
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
char buffer[SocketAddress::MAX_ADDRESS_LENGTH];
struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(buffer);
poco_socklen_t saLen = sizeof(buffer);
int rc = ::getpeername(_sockfd, pSA, &saLen);
if (rc == 0)
return SocketAddress(pSA, saLen);
else
error();
return SocketAddress();
}
void SocketImpl::setOption(int level, int option, int value)
{
setRawOption(level, option, &value, sizeof(value));
}
void SocketImpl::setOption(int level, int option, unsigned value)
{
setRawOption(level, option, &value, sizeof(value));
}
void SocketImpl::setOption(int level, int option, unsigned char value)
{
setRawOption(level, option, &value, sizeof(value));
}
void SocketImpl::setOption(int level, int option, const IPAddress& value)
{
setRawOption(level, option, value.addr(), value.length());
}
void SocketImpl::setOption(int level, int option, const Foundation::Timespan& value)
{
struct timeval tv;
tv.tv_sec = (long) value.totalSeconds();
tv.tv_usec = (long) value.useconds();
setRawOption(level, option, &tv, sizeof(tv));
}
void SocketImpl::setRawOption(int level, int option, const void* value, poco_socklen_t length)
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
int rc = ::setsockopt(_sockfd, level, option, reinterpret_cast<const char*>(value), length);
if (rc == -1) error();
}
void SocketImpl::getOption(int level, int option, int& value)
{
poco_socklen_t len = sizeof(value);
getRawOption(level, option, &value, len);
}
void SocketImpl::getOption(int level, int option, unsigned& value)
{
poco_socklen_t len = sizeof(value);
getRawOption(level, option, &value, len);
}
void SocketImpl::getOption(int level, int option, unsigned char& value)
{
poco_socklen_t len = sizeof(value);
getRawOption(level, option, &value, len);
}
void SocketImpl::getOption(int level, int option, Foundation::Timespan& value)
{
struct timeval tv;
poco_socklen_t len = sizeof(tv);
getRawOption(level, option, &tv, len);
value.assign(tv.tv_sec, tv.tv_usec);
}
void SocketImpl::getOption(int level, int option, IPAddress& value)
{
char buffer[IPAddress::MAX_ADDRESS_LENGTH];
poco_socklen_t len = sizeof(buffer);
getRawOption(level, option, buffer, len);
value = IPAddress(buffer, len);
}
void SocketImpl::getRawOption(int level, int option, void* value, poco_socklen_t& length)
{
poco_assert (_sockfd != POCO_INVALID_SOCKET);
int rc = ::getsockopt(_sockfd, level, option, reinterpret_cast<char*>(value), &length);
if (rc == -1) error();
}
void SocketImpl::setLinger(bool on, int seconds)
{
struct linger l;
l.l_onoff = on ? 1 : 0;
l.l_linger = seconds;
setRawOption(SOL_SOCKET, SO_LINGER, &l, sizeof(l));
}
void SocketImpl::getLinger(bool& on, int& seconds)
{
struct linger l;
poco_socklen_t len = sizeof(l);
getRawOption(SOL_SOCKET, SO_LINGER, &l, len);
on = l.l_onoff != 0;
seconds = l.l_linger;
}
void SocketImpl::setNoDelay(bool flag)
{
int value = flag ? 1 : 0;
setOption(IPPROTO_TCP, TCP_NODELAY, value);
}
bool SocketImpl::getNoDelay()
{
int value;
getOption(IPPROTO_TCP, TCP_NODELAY, value);
return value != 0;
}
void SocketImpl::setKeepAlive(bool flag)
{
int value = flag ? 1 : 0;
setOption(SOL_SOCKET, SO_KEEPALIVE, value);
}
bool SocketImpl::getKeepAlive()
{
int value;
getOption(SOL_SOCKET, SO_KEEPALIVE, value);
return value != 0;
}
void SocketImpl::setReuseAddress(bool flag)
{
int value = flag ? 1 : 0;
setOption(SOL_SOCKET, SO_REUSEADDR, value);
}
bool SocketImpl::getReuseAddress()
{
int value;
getOption(SOL_SOCKET, SO_REUSEADDR, value);
return value != 0;
}
void SocketImpl::setReusePort(bool flag)
{
#ifdef SO_REUSEPORT
try
{
int value = flag ? 1 : 0;
setOption(SOL_SOCKET, SO_REUSEPORT, value);
}
catch (IOException&)
{
// ignore error, since not all implementations
// support SO_REUSEPORT, even if the macro
// is defined.
}
#endif
}
bool SocketImpl::getReusePort()
{
#ifdef SO_REUSEPORT
int value;
getOption(SOL_SOCKET, SO_REUSEPORT, value);
return value != 0;
#else
return false;
#endif
}
void SocketImpl::setOOBInline(bool flag)
{
int value = flag ? 1 : 0;
setOption(SOL_SOCKET, SO_OOBINLINE, value);
}
bool SocketImpl::getOOBInline()
{
int value;
getOption(SOL_SOCKET, SO_OOBINLINE, value);
return value != 0;
}
void SocketImpl::setBroadcast(bool flag)
{
int value = flag ? 1 : 0;
setOption(SOL_SOCKET, SO_BROADCAST, value);
}
bool SocketImpl::getBroadcast()
{
int value;
getOption(SOL_SOCKET, SO_BROADCAST, value);
return value != 0;
}
void SocketImpl::setBlocking(bool flag)
{
int arg = flag ? 0 : 1;
ioctl(FIONBIO, arg);
}
int SocketImpl::socketError()
{
int result;
getOption(SOL_SOCKET, SO_ERROR, result);
return result;
}
void SocketImpl::init(int af)
{
initSocket(af, SOCK_STREAM);
}
void SocketImpl::initSocket(int af, int type, int proto)
{
poco_assert (_sockfd == POCO_INVALID_SOCKET);
_sockfd = ::socket(af, type, proto);
if (_sockfd == POCO_INVALID_SOCKET)
error();
}
void SocketImpl::ioctl(int request, int& arg)
{
#if defined(_WIN32)
int rc = ioctlsocket(_sockfd, request, reinterpret_cast<u_long*>(&arg));
#else
int rc = ::ioctl(_sockfd, request, &arg);
#endif
if (rc != 0) error();
}
void SocketImpl::ioctl(int request, void* arg)
{
#if defined(_WIN32)
int rc = ioctlsocket(_sockfd, request, reinterpret_cast<u_long*>(arg));
#else
int rc = ::ioctl(_sockfd, request, arg);
#endif
if (rc != 0) error();
}
void SocketImpl::setSockfd(poco_socket_t aSocket)
{
poco_assert(sockfd() == POCO_INVALID_SOCKET);
_sockfd = aSocket;
}
void SocketImpl::error()
{
std::string empty;
error(lastError(), empty);
}
void SocketImpl::error(const std::string& arg)
{
error(lastError(), arg);
}
void SocketImpl::error(int code)
{
std::string arg;
error(code, arg);
}
void SocketImpl::error(int code, const std::string& arg)
{
switch (code)
{
case POCO_ESYSNOTREADY:
throw NetException("Net subsystem not ready");
case POCO_ENOTINIT:
throw NetException("Net subsystem not initialized");
case POCO_EINTR:
throw IOException("Interrupted");
case POCO_EACCES:
throw IOException("Permission denied");
case POCO_EFAULT:
throw IOException("Bad address");
case POCO_EINVAL:
throw InvalidArgumentException();
case POCO_EMFILE:
throw IOException("Too many open files");
case POCO_EWOULDBLOCK:
throw IOException("Operation would block");
case POCO_EINPROGRESS:
throw IOException("Operation now in progress");
case POCO_EALREADY:
throw IOException("Operation already in progress");
case POCO_ENOTSOCK:
throw IOException("Socket operation attempted on non-socket");
case POCO_EDESTADDRREQ:
throw NetException("Destination address required");
case POCO_EMSGSIZE:
throw NetException("Message too long");
case POCO_EPROTOTYPE:
throw NetException("Wrong protocol type");
case POCO_ENOPROTOOPT:
throw NetException("Protocol not available");
case POCO_EPROTONOSUPPORT:
throw NetException("Protocol not supported");
case POCO_ESOCKTNOSUPPORT:
throw NetException("Socket type not supported");
case POCO_ENOTSUP:
throw NetException("Operation not supported");
case POCO_EPFNOSUPPORT:
throw NetException("Protocol family not supported");
case POCO_EAFNOSUPPORT:
throw NetException("Address family not supported");
case POCO_EADDRINUSE:
throw NetException("Address already in use", arg);
case POCO_EADDRNOTAVAIL:
throw NetException("Cannot assign requested address", arg);
case POCO_ENETDOWN:
throw NetException("Network is down");
case POCO_ENETUNREACH:
throw NetException("Network is unreachable");
case POCO_ENETRESET:
throw NetException("Network dropped connection on reset");
case POCO_ECONNABORTED:
throw ConnectionAbortedException();
case POCO_ECONNRESET:
throw ConnectionResetException();
case POCO_ENOBUFS:
throw IOException("No buffer space available");
case POCO_EISCONN:
throw NetException("Socket is already connected");
case POCO_ENOTCONN:
throw NetException("Socket is not connected");
case POCO_ESHUTDOWN:
throw NetException("Cannot send after socket shutdown");
case POCO_ETIMEDOUT:
throw TimeoutException();
case POCO_ECONNREFUSED:
throw ConnectionRefusedException(arg);
case POCO_EHOSTDOWN:
throw NetException("Host is down");
case POCO_EHOSTUNREACH:
throw NetException("No route to host");
default:
throw IOException(NumberFormatter::format(code) + arg);
}
}
Net_END

View File

@@ -0,0 +1,115 @@
//
// SocketNotification.cpp
//
// $Id: //poco/1.1.0/Net/src/SocketNotification.cpp#2 $
//
// Library: Net
// Package: Reactor
// Module: SocketNotification
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/SocketNotification.h"
Net_BEGIN
SocketNotification::SocketNotification(SocketReactor* pReactor):
_pReactor(pReactor)
{
}
SocketNotification::~SocketNotification()
{
}
void SocketNotification::setSocket(const Socket& socket)
{
_socket = socket;
}
ReadableNotification::ReadableNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
ReadableNotification::~ReadableNotification()
{
}
WritableNotification::WritableNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
WritableNotification::~WritableNotification()
{
}
ErrorNotification::ErrorNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
ErrorNotification::~ErrorNotification()
{
}
TimeoutNotification::TimeoutNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
TimeoutNotification::~TimeoutNotification()
{
}
ShutdownNotification::ShutdownNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
ShutdownNotification::~ShutdownNotification()
{
}
Net_END

View File

@@ -0,0 +1,95 @@
//
// SocketNotifier.cpp
//
// $Id: //poco/1.1.0/Net/src/SocketNotifier.cpp#2 $
//
// Library: Net
// Package: Reactor
// Module: SocketNotifier
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/SocketNotifier.h"
#include "Net/SocketReactor.h"
#include "Net/SocketNotification.h"
Net_BEGIN
SocketNotifier::SocketNotifier(const Socket& socket):
_socket(socket)
{
}
SocketNotifier::~SocketNotifier()
{
}
void SocketNotifier::addObserver(SocketReactor* pReactor, const Foundation::AbstractObserver& observer)
{
_nc.addObserver(observer);
if (observer.accepts(pReactor->_pReadableNotification))
_events.insert(pReactor->_pReadableNotification.get());
else if (observer.accepts(pReactor->_pWritableNotification))
_events.insert(pReactor->_pWritableNotification.get());
else if (observer.accepts(pReactor->_pErrorNotification))
_events.insert(pReactor->_pErrorNotification.get());
else if (observer.accepts(pReactor->_pTimeoutNotification))
_events.insert(pReactor->_pErrorNotification.get());
}
void SocketNotifier::removeObserver(SocketReactor* pReactor, const Foundation::AbstractObserver& observer)
{
_nc.removeObserver(observer);
EventSet::iterator it = _events.end();
if (observer.accepts(pReactor->_pReadableNotification))
it = _events.find(pReactor->_pReadableNotification.get());
else if (observer.accepts(pReactor->_pWritableNotification))
it = _events.find(pReactor->_pWritableNotification.get());
else if (observer.accepts(pReactor->_pErrorNotification))
it = _events.find(pReactor->_pErrorNotification.get());
else if (observer.accepts(pReactor->_pTimeoutNotification))
it = _events.find(pReactor->_pTimeoutNotification.get());
if (it != _events.end())
_events.erase(it);
}
void SocketNotifier::dispatch(SocketNotification* pNotification)
{
pNotification->setSocket(_socket);
pNotification->duplicate();
_nc.postNotification(pNotification);
}
Net_END

232
Net/src/SocketReactor.cpp Normal file
View File

@@ -0,0 +1,232 @@
//
// SocketReactor.cpp
//
// $Id: //poco/1.1.0/Net/src/SocketReactor.cpp#2 $
//
// Library: Net
// Package: Reactor
// Module: SocketReactor
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/SocketReactor.h"
#include "Net/SocketNotification.h"
#include "Net/SocketNotifier.h"
#include "Foundation/ErrorHandler.h"
#include "Foundation/Exception.h"
using Foundation::FastMutex;
using Foundation::Exception;
using Foundation::ErrorHandler;
Net_BEGIN
SocketReactor::SocketReactor():
_stop(false),
_timeout(DEFAULT_TIMEOUT),
_pReadableNotification(new ReadableNotification(this)),
_pWritableNotification(new WritableNotification(this)),
_pErrorNotification(new ErrorNotification(this)),
_pTimeoutNotification(new TimeoutNotification(this)),
_pShutdownNotification(new ShutdownNotification(this))
{
}
SocketReactor::SocketReactor(const Foundation::Timespan& timeout):
_stop(false),
_timeout(timeout),
_pReadableNotification(new ReadableNotification(this)),
_pWritableNotification(new WritableNotification(this)),
_pErrorNotification(new ErrorNotification(this)),
_pTimeoutNotification(new TimeoutNotification(this)),
_pShutdownNotification(new ShutdownNotification(this))
{
}
SocketReactor::~SocketReactor()
{
}
void SocketReactor::run()
{
Socket::SocketList readable;
Socket::SocketList writable;
Socket::SocketList except;
while (!_stop)
{
readable.clear();
writable.clear();
except.clear();
{
FastMutex::ScopedLock lock(_mutex);
for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it)
{
if (it->second->accepts(_pReadableNotification))
readable.push_back(it->first);
if (it->second->accepts(_pWritableNotification))
writable.push_back(it->first);
if (it->second->accepts(_pErrorNotification))
except.push_back(it->first);
}
}
if (Socket::select(readable, writable, except, _timeout))
{
for (Socket::SocketList::iterator it = readable.begin(); it != readable.end(); ++it)
dispatch(*it, _pReadableNotification);
for (Socket::SocketList::iterator it = writable.begin(); it != writable.end(); ++it)
dispatch(*it, _pWritableNotification);
for (Socket::SocketList::iterator it = except.begin(); it != except.end(); ++it)
dispatch(*it, _pErrorNotification);
}
else onTimeout();
}
onShutdown();
}
void SocketReactor::stop()
{
_stop = true;
}
void SocketReactor::setTimeout(const Foundation::Timespan& timeout)
{
_timeout = timeout;
}
const Foundation::Timespan& SocketReactor::getTimeout() const
{
return _timeout;
}
void SocketReactor::addEventHandler(const Socket& socket, const Foundation::AbstractObserver& observer)
{
FastMutex::ScopedLock lock(_mutex);
NotifierPtr pNotifier;
EventHandlerMap::iterator it = _handlers.find(socket);
if (it == _handlers.end())
{
pNotifier = new SocketNotifier(socket);
_handlers[socket] = pNotifier;
}
else pNotifier = it->second;
pNotifier->addObserver(this, observer);
}
void SocketReactor::removeEventHandler(const Socket& socket, const Foundation::AbstractObserver& observer)
{
FastMutex::ScopedLock lock(_mutex);
EventHandlerMap::iterator it = _handlers.find(socket);
if (it != _handlers.end())
{
NotifierPtr pNotifier = it->second;
pNotifier->removeObserver(this, observer);
if (!pNotifier->hasObservers())
_handlers.erase(it);
}
}
void SocketReactor::onTimeout()
{
dispatch(_pTimeoutNotification);
}
void SocketReactor::onShutdown()
{
dispatch(_pShutdownNotification);
}
void SocketReactor::dispatch(const Socket& socket, SocketNotification* pNotification)
{
NotifierPtr pNotifier;
{
FastMutex::ScopedLock lock(_mutex);
EventHandlerMap::iterator it = _handlers.find(socket);
if (it != _handlers.end())
pNotifier = it->second;
else
return;
}
dispatch(pNotifier, pNotification);
}
void SocketReactor::dispatch(SocketNotification* pNotification)
{
std::vector<NotifierPtr> delegates;
delegates.reserve(_handlers.size());
{
FastMutex::ScopedLock lock(_mutex);
for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it)
delegates.push_back(it->second);
}
for (std::vector<NotifierPtr>::iterator it = delegates.begin(); it != delegates.end(); ++it)
{
dispatch(*it, pNotification);
}
}
void SocketReactor::dispatch(NotifierPtr& pNotifier, SocketNotification* pNotification)
{
try
{
pNotifier->dispatch(pNotification);
}
catch (Exception& exc)
{
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
ErrorHandler::handle(exc);
}
catch (...)
{
ErrorHandler::handle();
}
}
Net_END

177
Net/src/SocketStream.cpp Normal file
View File

@@ -0,0 +1,177 @@
//
// SocketStream.cpp
//
// $Id: //poco/1.1.0/Net/src/SocketStream.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: SocketStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/SocketStream.h"
#include "Net/StreamSocketImpl.h"
#include "Foundation/Exception.h"
using Foundation::BufferedBidirectionalStreamBuf;
using Foundation::InvalidArgumentException;
Net_BEGIN
//
// SocketStreamBuf
//
SocketStreamBuf::SocketStreamBuf(const Socket& socket):
BufferedBidirectionalStreamBuf(STREAM_BUFFER_SIZE, std::ios::in | std::ios::out),
_pImpl(dynamic_cast<StreamSocketImpl*>(socket.impl()))
{
if (_pImpl)
_pImpl->duplicate();
else
throw InvalidArgumentException("Invalid or null SocketImpl passed to SocketStreamBuf");
}
SocketStreamBuf::~SocketStreamBuf()
{
_pImpl->release();
}
int SocketStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
return _pImpl->receiveBytes(buffer, (int) length);
}
int SocketStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
return _pImpl->sendBytes(buffer, (int) length);
}
//
// SocketIOS
//
SocketIOS::SocketIOS(const Socket& socket):
_buf(socket)
{
poco_ios_init(&_buf);
}
SocketIOS::~SocketIOS()
{
try
{
_buf.sync();
}
catch (...)
{
}
}
SocketStreamBuf* SocketIOS::rdbuf()
{
return &_buf;
}
void SocketIOS::close()
{
_buf.sync();
_buf.socketImpl()->close();
}
StreamSocket SocketIOS::socket() const
{
return StreamSocket(_buf.socketImpl());
}
//
// SocketOutputStream
//
SocketOutputStream::SocketOutputStream(const Socket& socket):
SocketIOS(socket),
std::ostream(&_buf)
{
}
SocketOutputStream::~SocketOutputStream()
{
}
//
// SocketInputStream
//
SocketInputStream::SocketInputStream(const Socket& socket):
SocketIOS(socket),
std::istream(&_buf)
{
}
SocketInputStream::~SocketInputStream()
{
}
//
// SocketStream
//
SocketStream::SocketStream(const Socket& socket):
SocketIOS(socket),
std::iostream(&_buf)
{
}
SocketStream::~SocketStream()
{
}
Net_END

142
Net/src/StreamSocket.cpp Normal file
View File

@@ -0,0 +1,142 @@
//
// StreamSocket.cpp
//
// $Id: //poco/1.1.0/Net/src/StreamSocket.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: StreamSocket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/StreamSocket.h"
#include "Net/StreamSocketImpl.h"
#include "Foundation/Exception.h"
using Foundation::InvalidArgumentException;
Net_BEGIN
StreamSocket::StreamSocket(): Socket(new StreamSocketImpl)
{
}
StreamSocket::StreamSocket(const SocketAddress& address): Socket(new StreamSocketImpl)
{
connect(address);
}
StreamSocket::StreamSocket(const Socket& socket): Socket(socket)
{
if (!dynamic_cast<StreamSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
StreamSocket::StreamSocket(SocketImpl* pImpl): Socket(pImpl)
{
if (!dynamic_cast<StreamSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
StreamSocket::~StreamSocket()
{
}
StreamSocket& StreamSocket::operator = (const Socket& socket)
{
if (dynamic_cast<StreamSocketImpl*>(socket.impl()))
Socket::operator = (socket);
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
void StreamSocket::connect(const SocketAddress& address)
{
impl()->connect(address);
}
void StreamSocket::connect(const SocketAddress& address, const Foundation::Timespan& timeout)
{
impl()->connect(address, timeout);
}
void StreamSocket::connectNB(const SocketAddress& address)
{
impl()->connectNB(address);
}
void StreamSocket::shutdownReceive()
{
impl()->shutdownReceive();
}
void StreamSocket::shutdownSend()
{
impl()->shutdownSend();
}
void StreamSocket::shutdown()
{
impl()->shutdown();
}
int StreamSocket::sendBytes(const void* buffer, int length, int flags)
{
return impl()->sendBytes(buffer, length, flags);
}
int StreamSocket::receiveBytes(void* buffer, int length, int flags)
{
return impl()->receiveBytes(buffer, length, flags);
}
void StreamSocket::sendUrgent(unsigned char data)
{
impl()->sendUrgent(data);
}
Net_END

View File

@@ -0,0 +1,72 @@
//
// StreamSocketImpl.cpp
//
// $Id: //poco/1.1.0/Net/src/StreamSocketImpl.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: StreamSocketImpl
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/StreamSocketImpl.h"
Net_BEGIN
StreamSocketImpl::StreamSocketImpl()
{
}
StreamSocketImpl::StreamSocketImpl(poco_socket_t sockfd): SocketImpl(sockfd)
{
}
StreamSocketImpl::~StreamSocketImpl()
{
}
int StreamSocketImpl::sendBytes(const void* buffer, int length, int flags)
{
const char* p = reinterpret_cast<const char*>(buffer);
int remaining = length;
while (remaining > 0)
{
int n = SocketImpl::sendBytes(p, length, flags);
p += n;
remaining -= n;
}
return length;
}
Net_END

View File

@@ -0,0 +1,82 @@
//
// StringPartSource.cpp
//
// $Id: //poco/1.1.0/Net/src/StringPartSource.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: StringPartSource
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/StringPartSource.h"
Net_BEGIN
StringPartSource::StringPartSource(const std::string& str):
PartSource("text/plain"),
_istr(str)
{
}
StringPartSource::StringPartSource(const std::string& str, const std::string& mediaType):
PartSource(mediaType),
_istr(str)
{
}
StringPartSource::StringPartSource(const std::string& str, const std::string& mediaType, const std::string& filename):
PartSource(mediaType),
_istr(str),
_filename(filename)
{
}
StringPartSource::~StringPartSource()
{
}
std::istream& StringPartSource::stream()
{
return _istr;
}
const std::string& StringPartSource::filename()
{
return _filename;
}
Net_END

175
Net/src/TCPServer.cpp Normal file
View File

@@ -0,0 +1,175 @@
//
// TCPServer.cpp
//
// $Id: //poco/1.1.0/Net/src/TCPServer.cpp#3 $
//
// Library: Net
// Package: TCPServer
// Module: TCPServer
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/TCPServer.h"
#include "Net/TCPServerDispatcher.h"
#include "Net/TCPServerConnection.h"
#include "Net/TCPServerConnectionFactory.h"
#include "Foundation/Timespan.h"
#include "Foundation/Exception.h"
#include "Foundation/ErrorHandler.h"
using Foundation::ErrorHandler;
Net_BEGIN
TCPServer::TCPServer(TCPServerConnectionFactory* pFactory, const ServerSocket& socket, TCPServerParams* pParams):
_pDispatcher(new TCPServerDispatcher(pFactory, Foundation::ThreadPool::defaultPool(), pParams)),
_socket(socket),
_thread(threadName(socket)),
_stopped(false)
{
}
TCPServer::TCPServer(TCPServerConnectionFactory* pFactory, Foundation::ThreadPool& threadPool, const ServerSocket& socket, TCPServerParams* pParams):
_pDispatcher(new TCPServerDispatcher(pFactory, threadPool, pParams)),
_socket(socket),
_thread(threadName(socket)),
_stopped(false)
{
}
TCPServer::~TCPServer()
{
stop();
_pDispatcher->release();
}
const TCPServerParams& TCPServer::params() const
{
return _pDispatcher->params();
}
void TCPServer::start()
{
poco_assert (!_stopped);
_thread.start(*this);
}
void TCPServer::stop()
{
if (!_stopped)
{
_stopped = true;
_thread.join();
_pDispatcher->stop();
}
}
void TCPServer::run()
{
while (!_stopped)
{
Foundation::Timespan timeout(250000);
if (_socket.poll(timeout, Socket::SELECT_READ))
{
try
{
StreamSocket ss = _socket.acceptConnection();
_pDispatcher->enqueue(ss);
}
catch (Foundation::Exception& exc)
{
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
ErrorHandler::handle(exc);
}
catch (...)
{
ErrorHandler::handle();
}
}
}
}
int TCPServer::currentThreads() const
{
return _pDispatcher->currentThreads();
}
int TCPServer::totalConnections() const
{
return _pDispatcher->totalConnections();
}
int TCPServer::currentConnections() const
{
return _pDispatcher->currentConnections();
}
int TCPServer::maxConcurrentConnections() const
{
return _pDispatcher->maxConcurrentConnections();
}
int TCPServer::queuedConnections() const
{
return _pDispatcher->queuedConnections();
}
int TCPServer::refusedConnections() const
{
return _pDispatcher->refusedConnections();
}
std::string TCPServer::threadName(const ServerSocket& socket)
{
std::string name("TCPServer: ");
name.append(socket.address().toString());
return name;
}
Net_END

View File

@@ -0,0 +1,81 @@
//
// TCPServerConnection.cpp
//
// $Id: //poco/1.1.0/Net/src/TCPServerConnection.cpp#2 $
//
// Library: Net
// Package: TCPServer
// Module: TCPServerConnection
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/TCPServerConnection.h"
#include "Foundation/Exception.h"
#include "Foundation/ErrorHandler.h"
using Foundation::Exception;
using Foundation::ErrorHandler;
Net_BEGIN
TCPServerConnection::TCPServerConnection(const StreamSocket& socket):
_socket(socket)
{
}
TCPServerConnection::~TCPServerConnection()
{
}
void TCPServerConnection::start()
{
try
{
run();
}
catch (Exception& exc)
{
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
ErrorHandler::handle(exc);
}
catch (...)
{
ErrorHandler::handle();
}
}
Net_END

View File

@@ -0,0 +1,53 @@
//
// TCPServerConnectionFactory.cpp
//
// $Id: //poco/1.1.0/Net/src/TCPServerConnectionFactory.cpp#2 $
//
// Library: Net
// Package: TCPServer
// Module: TCPServerConnectionFactory
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/TCPServerConnectionFactory.h"
Net_BEGIN
TCPServerConnectionFactory::TCPServerConnectionFactory()
{
}
TCPServerConnectionFactory::~TCPServerConnectionFactory()
{
}
Net_END

View File

@@ -0,0 +1,255 @@
//
// TCPServerDispatcher.cpp
//
// $Id: //poco/1.1.0/Net/src/TCPServerDispatcher.cpp#2 $
//
// Library: Net
// Package: TCPServer
// Module: TCPServerDispatcher
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/TCPServerDispatcher.h"
#include "Net/TCPServerConnectionFactory.h"
#include "Net/TCPServerParams.h"
#include "Foundation/Notification.h"
#include "Foundation/AutoPtr.h"
#include <memory>
using Foundation::Notification;
using Foundation::FastMutex;
using Foundation::AutoPtr;
Net_BEGIN
class TCPConnectionNotification: public Notification
{
public:
TCPConnectionNotification(const StreamSocket& socket):
_socket(socket)
{
}
~TCPConnectionNotification()
{
}
const StreamSocket& socket() const
{
return _socket;
}
private:
StreamSocket _socket;
};
TCPServerDispatcher::TCPServerDispatcher(TCPServerConnectionFactory* pFactory, Foundation::ThreadPool& threadPool, TCPServerParams* pParams):
_rc(1),
_pParams(pParams),
_currentThreads(0),
_totalConnections(0),
_currentConnections(0),
_maxConcurrentConnections(0),
_refusedConnections(0),
_stopped(false),
_pConnectionFactory(pFactory),
_threadPool(threadPool)
{
poco_check_ptr (pFactory);
if (!_pParams)
_pParams = new TCPServerParams;
if (_pParams->getMaxThreads() == 0)
_pParams->setMaxThreads(threadPool.capacity());
}
TCPServerDispatcher::~TCPServerDispatcher()
{
_pParams->release();
delete _pConnectionFactory;
}
void TCPServerDispatcher::duplicate()
{
_mutex.lock();
++_rc;
_mutex.unlock();
}
void TCPServerDispatcher::release()
{
_mutex.lock();
int rc = --_rc;
_mutex.unlock();
if (rc == 0) delete this;
}
void TCPServerDispatcher::run()
{
AutoPtr<TCPServerDispatcher> guard(this, true); // ensure object stays alive
int idleTime = (int) _pParams->getThreadIdleTime().totalMilliseconds();
for (;;)
{
AutoPtr<Notification> pNf = _queue.waitDequeueNotification(idleTime);
if (pNf)
{
TCPConnectionNotification* pCNf = dynamic_cast<TCPConnectionNotification*>(pNf.get());
if (pCNf)
{
std::auto_ptr<TCPServerConnection> pConnection(_pConnectionFactory->createConnection(pCNf->socket()));
poco_check_ptr(pConnection.get());
beginConnection();
pConnection->start();
endConnection();
}
}
FastMutex::ScopedLock lock(_mutex);
if (_stopped || _currentThreads > 1 && _queue.empty())
{
--_currentThreads;
break;
}
}
}
void TCPServerDispatcher::enqueue(const StreamSocket& socket)
{
FastMutex::ScopedLock lock(_mutex);
if (_queue.size() < _pParams->getMaxQueued())
{
_queue.enqueueNotification(new TCPConnectionNotification(socket));
if (!_queue.hasIdleThreads() && _currentThreads < _pParams->getMaxThreads())
{
try
{
static const std::string threadName("TCPServerConnection");
_threadPool.start(*this, threadName);
++_currentThreads;
}
catch (Foundation::Exception&)
{
// no problem here, connection is already queued
// and a new thread might be available later.
}
}
}
else
{
++_refusedConnections;
}
}
void TCPServerDispatcher::stop()
{
_stopped = true;
_queue.clear();
_queue.wakeUpAll();
}
int TCPServerDispatcher::currentThreads() const
{
FastMutex::ScopedLock lock(_mutex);
return _currentThreads;
}
int TCPServerDispatcher::totalConnections() const
{
FastMutex::ScopedLock lock(_mutex);
return _totalConnections;
}
int TCPServerDispatcher::currentConnections() const
{
FastMutex::ScopedLock lock(_mutex);
return _currentConnections;
}
int TCPServerDispatcher::maxConcurrentConnections() const
{
FastMutex::ScopedLock lock(_mutex);
return _maxConcurrentConnections;
}
int TCPServerDispatcher::queuedConnections() const
{
return _queue.size();
}
int TCPServerDispatcher::refusedConnections() const
{
FastMutex::ScopedLock lock(_mutex);
return _refusedConnections;
}
void TCPServerDispatcher::beginConnection()
{
FastMutex::ScopedLock lock(_mutex);
++_totalConnections;
++_currentConnections;
if (_currentConnections > _maxConcurrentConnections)
_maxConcurrentConnections = _currentConnections;
}
void TCPServerDispatcher::endConnection()
{
FastMutex::ScopedLock lock(_mutex);
--_currentConnections;
}
Net_END

View File

@@ -0,0 +1,80 @@
//
// TCPServerParams.cpp
//
// $Id: //poco/1.1.0/Net/src/TCPServerParams.cpp#2 $
//
// Library: Net
// Package: TCPServer
// Module: TCPServerParams
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Net/TCPServerParams.h"
Net_BEGIN
TCPServerParams::TCPServerParams():
_threadIdleTime(10000000),
_maxThreads(0),
_maxQueued(64)
{
}
TCPServerParams::~TCPServerParams()
{
}
void TCPServerParams::setThreadIdleTime(const Foundation::Timespan& milliseconds)
{
_threadIdleTime = milliseconds;
}
void TCPServerParams::setMaxThreads(int count)
{
poco_assert (count > 0);
_maxThreads = count;
}
void TCPServerParams::setMaxQueued(int count)
{
poco_assert (count > 0);
_maxQueued = count;
}
Net_END